M storage/IDE.pas

M    storage/fat32.pas
M    storage/storagemanagement.pas


git-svn-id: https://spexeah.com:8443/svn/Asuro@970 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c
This commit is contained in:
aaron 2020-07-11 00:32:59 +00:00
parent 6c931149f3
commit 86013b1125
3 changed files with 226 additions and 316 deletions

View File

@ -20,11 +20,13 @@ uses
vmemorymanager, vmemorymanager,
lmemorymanager, lmemorymanager,
storagemanagement, storagemanagement,
strings,
tracer; tracer;
type type
TIdentResponse = array[0..255] of uint16; TPortMode = (P_READ, P_WRITE);
TIdentResponse = array[0..255] of uint16;
TIDE_Channel_Registers = record TIDE_Channel_Registers = record
base : uint16; base : uint16;
@ -105,7 +107,7 @@ const
ATA_REG_DATA = $00; ATA_REG_DATA = $00;
ATA_REG_ERROR = $01; ATA_REG_ERROR = $01;
ATA_REG_FEATURES = $01; ATA_REG_FEATURES = $01;
ATA_REG_SECCOUNT0 = $02; ATA_REG_SECCOUNT = $02;
ATA_REG_LBA0 = $03; ATA_REG_LBA0 = $03;
ATA_REG_LBA1 = $04; ATA_REG_LBA1 = $04;
ATA_REG_LBA2 = $05; ATA_REG_LBA2 = $05;
@ -120,6 +122,11 @@ const
ATA_REG_ALTSTATUS = $0C; ATA_REG_ALTSTATUS = $0C;
ATA_REG_DEVADDRESS = $0D; ATA_REG_DEVADDRESS = $0D;
ATA_DEVICE_MASTER = $A0;
ATA_DEVICE_SLAVE = $B0;
ATA_PRIMARY_BASE = $1F0;
var var
controller : PPCI_Device; controller : PPCI_Device;
@ -133,70 +140,106 @@ var
procedure init(); procedure init();
function load(ptr : void) : boolean; function load(ptr : void) : boolean;
function identify_device(bus : uint8; drive : uint8) : TIdentResponse; function identify_device(bus : uint8; device : uint8) : TIdentResponse;
procedure readPIO28(drive : uint8; LBA : uint32; sectorCount : uint8; buffer : puint32);
procedure writePIO28(drive : uint8; LBA : uint32; sectorCount : uint8; buffer : Puint32); // procedure flush();
procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
//read/write must be capable of reading/writting any amknt of data upto disk size //read/write must be capable of reading/writting any amknt of data upto disk size
procedure read(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); procedure read(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
procedure write(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); procedure write(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32);
implementation implementation
procedure test_command(params : PParamList); function port_read(register : uint8) : uint8;
var
secotrs : uint32;
cpacityMB : uint32;
buffer : puint32;
i : uint32;
d : uint8;
begin begin
port_read:= inb(ATA_PRIMARY_BASE + register);
end;
for d:= 0 to 1 do begin procedure port_write(register : uint8; data : uint8);
secotrs := IDEDevices[d].info[60]; var
secotrs := secotrs or (IDEDevices[d].info[61] shl 16); i : uint8;
begin
cpacityMB := (secotrs * 512) DIV 1000 DIV 1000; outb(ATA_PRIMARY_BASE + register, data);
util.psleep(1);
if d = 0 then console.writestring('HHD_Primary_MASTER -'); if register = ATA_REG_COMMAND then begin
if d = 1 then console.writestring('HHD_Primary_SLAVE -'); for i:= 0 to 5 do begin
port_read(ATA_REG_STATUS);
console.writestring(' Capacity: ');
console.writeint(cpacityMB);
console.writestringln('MB');
buffer := puint32(kalloc(1024 * 2000));
//buffer^:= secotrs;
for i:=0 to 20 do begin
puint32(buffer + (i div 2))^:= $10010110;
end;
writePIO28(d, 2, 2, buffer);
//buffer^:= $FFFF;
for i:=0 to 20 do begin
puint32(buffer + (i div 2))^:= $FFFFFFFF;
end;
readPIO28(d, 2, 2, buffer);
for i:=0 to 20 do begin
if puint32(buffer + (i div 2))^ <> $10010110 then begin
console.writestringln('Tests failed!');
exit;
end; end;
end; end;
end;
// if uint32(buffer^) = secotrs then begin procedure no_interrupt(device : uint8);
console.writestringln('Tests successful!'); begin
// end outb($3F6, inb($3f6) or (1 shl 1));
// else begin end;
// console.writestringln('Tests failed!');
// console.writehexln($01101001); procedure device_select(device : uint8);
// console.writehexln(uint32(buffer^)); begin
// end; outb($1F6, device); //TODO clean
kfree(buffer); end;
function is_ready() : boolean;
var
status : uint8;
i : uint32;
begin
//wait for drive to be ready
while true do begin
status := port_read(ATA_REG_COMMAND);
if(status and ATA_SR_ERR) = ATA_SR_ERR then begin
console.writestringln('[IDE] (IDENTIFY_DEVICE) DRIVE ERROR!');
console.redrawWindows();
is_ready := false;
break;
end; end;
if (status and ATA_SR_BUSY) <> ATA_SR_BUSY then begin
is_ready := true;
break;
end;
end;
end;
function validate_28bit_address(addr : uint32) : boolean;
begin
validate_28bit_address := (addr and $F0000000) = 0;
end;
function identify_device(bus : uint8; device : uint8) : TIdentResponse;
var
status : uint8;
identResponse : TIdentResponse;
i : uint8;
begin
device_select(device);
no_interrupt(device);
port_write(ATA_REG_CONTROL, 0);
//check if bus is floating
status := port_read(ATA_REG_COMMAND);
if status = $FF then exit;
port_write(ATA_REG_SECCOUNT, 0);
port_write(ATA_REG_LBA0, 0);
port_write(ATA_REG_LBA1, 0);
port_write(ATA_REG_LBA2, 0);
port_write(ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
//check if drive is present
status := port_read(ATA_REG_COMMAND);
if status = $00 then exit;
if not is_ready() then exit;
for i:=0 to 255 do begin
identResponse[i] := inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
end;
identify_device := identResponse;
end; end;
procedure init(); procedure init();
@ -221,306 +264,183 @@ end;
function load(ptr : void) : boolean; function load(ptr : void) : boolean;
var var
storageDevice : TStorage_Device; controller : PPCI_Device;
storageDevice1 : TStorage_Device; masterDevice : TStorage_Device;
slaveDevice : TStorage_Device;
buffer : puint8;
i : uint8;
begin begin
push_trace('ide.load'); push_trace('ide.load');
console.writestringln('[IDE] (LOAD) BEGIN'); console.writestringln('[IDE] (LOAD) BEGIN');
//controller := PPCI_Device(ptr); //controller := PPCI_Device(ptr);
controller := PPCI_Device(ptr);
console.writestringln('[IDE] (INIT) CHECK FLOATING BUS'); console.writestringln('[IDE] (INIT) CHECK FLOATING BUS');
//check if bus is floating and identify device //check if bus is floating and identify device
if inb($1F7) <> $FF then begin if inb($1F7) <> $FF then begin
//outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts //outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts
IDEDevices[0].isMaster:= true; IDEDevices[0].isMaster:= true;
IDEDevices[0].info := identify_device(0, $A0); IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER);
storageDevice.controller := ControllerIDE; masterDevice.controller := ControllerIDE;
storageDevice.controllerId0:= 0; masterDevice.controllerId0:= 0;
storageDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA
storageDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); if IDEDevices[0].info[1] = 0 then begin
console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!');
exit;
end;
storageDevice.sectorSize:= 512; masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]);
if storageDevice.maxSectorCount <> 0 then begin
masterDevice.sectorSize:= 512;
if masterDevice.maxSectorCount <> 0 then begin
IDEDevices[0].exists:= true; IDEDevices[0].exists:= true;
storageDevice.readCallback:= @read; masterDevice.readCallback:= @read;
storageDevice.writeCallback:= @write; masterDevice.writeCallback:= @write;
storagemanagement.register_device(@storageDevice); storagemanagement.register_device(@masterDevice);
end;
end; end;
if inb($1F7) <> $FF then begin
IDEDevices[1].isMaster:= false;
IDEDevices[1].info := identify_device(0, $B0);
storageDevice1.controller := ControllerIDE;
storageDevice1.controllerId0:= 1;
storageDevice1.maxSectorCount:= (IDEDevices[1].info[60] or (IDEDevices[1].info[61] shl 16) ); //LBA28 SATA
storageDevice1.sectorSize:= 512;
if storageDevice1.maxSectorCount <> 0 then begin
IDEDevices[1].exists:= true;
storageDevice1.readCallback:= @read;
storageDevice1.writeCallback:= @write;
//storagemanagement.register_device(@storageDevice1);
end;
end; end;
console.writestringln('[IDE] (LOAD) END'); console.writestringln('[IDE] (LOAD) END');
pop_trace(); pop_trace();
end; end;
procedure noInt(drive : uint8); // procedure flush();
begin // begin
if drive = 0 then begin // port_write(ATA_CMD_CACHE_FLUSH);
outb($1F6, $A0); //drive select // if not is_ready() then exit;
outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts // end;
//outb($1F6, $B0); //drive select
//outb($3F6, inb($3f6) and (0 shl 1)); // disable interrupts
end else begin
outb($1F6, $B0); //drive select
outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts
//outb($1F6, $A0); //drive select
//outb($3F6, inb($3f6) and (0 shl 1)); // disable interrupts
end;
end;
function identify_device(bus : uint8; drive : uint8) : TIdentResponse; procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8);
var var
i : uint8; status : uint8;
identResponse : TIdentResponse; i: uint16;
t : uint32 = 0; device: uint8;
data: uint16;
begin begin
push_trace('ide.identify_device'); if not validate_28bit_address(LBA) then begin
console.writestringln('[IDE] (IDENTIFY_DEVICE) BEGIN'); console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
if bus = 0 then begin
if drive = $A0 then noInt(0);
if drive = $B0 then noInt(1);
outb($1F6, drive); //drive select
outb($1F2, 0); //clear sector count and lba
outb($1F3, 0);
outb($1F4, 0);
outb($1F5, 0);
outb($1F7, ATA_CMD_IDENTIFY); //send identify command//
while true do begin
if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
end; end;
while true do begin //Add last 4 bits of LBA to device port
if (inb($1f7) and (1 shl 3)) <> 0 then break;
if (inb($1F7) and 1) <> 0 then exit; //drive error
if t > 100000 then exit; //todo return false
t +=1;
end;
for i:=0 to 255 do begin
identResponse[i] := inb($1F0); //read all bits
end;
identify_device:= identResponse;
exit;
end;
console.writestringln('[IDE] (IDENTIFY_DEVICE) END');
pop_trace();
end;
procedure writePIO28(drive : uint8; LBA : uint32; sectorCount : uint8; buffer : Puint32);
var
i : uint8;
ii : uint8;
iii : uint32;
begin
push_trace('ide.writePIO28');
console.writestringln('[IDE] (WRITEPIO28) BEGIN');
console.redrawWindows;
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
console.writestringln('[IDE] (WRITEPIO28) 1');
console.redrawWindows;
noInt(drive);
if IDEDevices[drive].isMaster then begin if IDEDevices[drive].isMaster then begin
outb($1F6, $A0); //drive select device:= ATA_DEVICE_MASTER;
outb($1F7, $E0 or ((LBA shr 24) and $0F)); //LBA command primary master device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
end end
else begin else begin
outb($1F6, $B0); //drive select device:= ATA_DEVICE_SLAVE;
outb($1F7, $F0 or ((LBA shr 24) and $0F)); //LBA command primary slave device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
end; end;
console.writestringln('[IDE] (WRITEPIO28) 2'); no_interrupt(device);
console.redrawWindows; port_write(ATA_REG_ERROR, 0);
outb($1F2, sectorCount); //Write sector count and LBA
outb($1F3, LBA); port_write(ATA_REG_SECCOUNT, 1);
outb($1F4, LBA shr 8); port_write(ATA_REG_LBA0, (LBA and $000000FF));
outb($1F5, LBA shr 16); port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
outb($1F7, $30); //write command port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
console.writestringln('[IDE] (WRITEPIO28) 3'); //send read command
console.redrawWindows; port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO);
if not is_ready() then exit;
for i:=0 to sectorCount-1 do begin i:=0;
while i < 512 do begin
// if not is_ready() then exit;
//poll status data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA);
while true do if (inb($1f7) and ATA_SR_BUSY) = 0 then break; //Wait until drive not busy
console.writestringln('[IDE] (WRITEPIO28) 4'); buffer[i+1] := uint8($00ff and (data shr 8));
console.redrawWindows; buffer[i] := uint8($00ff and data);
while true do begin i:= i + 2;
console.writestring('[IDE] (WRITEPIO28) inb($1f7): ');
writehexpair(inb($1f7));
if inb($1f7) = $40 then begin
while true do begin console.redrawWindows; end;
end; end;
writestringln(' ');
console.redrawWindows;
if (inb($1f7) and (1 shl 3)) <> 0 then break;
if (inb($1F7) and 1) <> 0 then begin
console.writestringln('write error');
console.redrawWindows;
exit;
end; //drive error
end;
console.writestringln('[IDE] (WRITEPIO28) 5');
console.redrawWindows;
for ii:=0 to 127 do begin //write data
outb($1F0, Puint32(buffer + ((i * 512) + (ii * 32) DIV 32) )^);
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
outb($1F7, $E7);
if ii <> 127 then begin
outb($1F0, Puint32(buffer + ((i * 512) + (ii * 32) DIV 32) )^ shr 16);
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
outb($1F7, $E7);
end;
end;
console.writestringln('[IDE] (WRITEPIO28) 6');
console.redrawWindows;
end;
console.writestringln('[IDE] (WRITEPIO28) END');
console.redrawWindows;
pop_trace();
end; end;
procedure readPIO28(drive : uint8; LBA : uint32; sectorCount : uint8; buffer : puint32); procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8);
var var
i : uint8; status : uint8;
ii : uint8; i: uint16;
iii : uint32; device: uint8;
begin begin
push_trace('ide.readPIO28'); if not validate_28bit_address(LBA) then begin
console.writestringln('[IDE] (READPIO28) BEGIN'); console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!');
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy end;
noInt(drive);
//Add last 4 bits of LBA to device port
if IDEDevices[drive].isMaster then begin if IDEDevices[drive].isMaster then begin
//outb($1F6, $A0); //drive select device:= ATA_DEVICE_MASTER;
outb($1F7, $E0 or ((LBA shr 24) and $0F)); //read command primary master device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master
end end
else begin else begin
//outb($1F6, $B0); //drive select device:= ATA_DEVICE_SLAVE;
outb($1F7, $F0 or ((LBA shr 24) and $0F)); //read command primary slave device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave
end; end;
outb($1F2, sectorCount); no_interrupt(device);
outb($1F3, LBA); port_write(ATA_REG_ERROR, 0);
outb($1F4, LBA shr 8); port_write(ATA_REG_CONTROL, 0);
outb($1F5, LBA shr 16);
outb($1F7, $20); //read command
//check if bus is floating
status := port_read(ATA_REG_COMMAND);
if status = $FF then exit;
for i:=0 to sectorCount-1 do begin //Write sector count and LBA
port_write(ATA_REG_SECCOUNT, 1);
port_write(ATA_REG_LBA0, (LBA and $000000FF));
port_write(ATA_REG_LBA1, (LBA and $0000FF00) shr 8);
port_write(ATA_REG_LBA2, (LBA and $00FF0000) shr 16);
//poll status //send write command
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
while true do begin
if (inb($1f7) and (1 shl 3)) <> 0 then break; console.writestringln('ide write sttart');
if (inb($1f7) and (1 shl 5)) <> 0 then begin console.redrawWindows();
console.writestringln('IDE DRIVE FAULT');
redrawWindows(); //write data
exit; i:=0;
end; while i < 512 do begin
if (inb($1f7) and (1 shl 6)) <> 0 then begin outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8)));
console.writestringln('IDE Spun Down'); i:= i + 2;
redrawWindows();
exit;
end;
if (inb($1F7) and 1) <> 0 then begin
console.writestringln('IDE read ERROR');
redrawWindows();
exit;
end; //drive error
end; end;
for ii:=0 to 127 do begin //read data console.writestringln('ise write stop');
Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^ := uint32(inb($1F0)); console.redrawWindows();
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
if ii <> 127 then begin //flush drive cache
Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^ := ((uint32(inb($1F0)) shl 16) or Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^); //wrong psleep(1);
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH);
end; psleep(1);
end; if not is_ready() then exit;
end;
console.writestringln('[IDE] (READPIO28) END'); console.writestringln('ide write end');
pop_trace(); console.redrawWindows();
end; end;
procedure readPIOPI(drive : uint8; LBA : uint32; buffer : Puint32); procedure read(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
var var
i : uint16; i : uint16;
begin begin
console.writestringln('[IDE] (READPIOPI) BEGIN'); // for i:=0 to sectorCount-1 do begin
if IDEDevices[drive].isMaster then begin // readPIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
outb($1F7, $E0 or ((LBA shr 24) and $0F)); // command primary master
end
else begin
outb($1F7, $F0 or ((LBA shr 24) and $0F)); // command primary slave
end;
outb($1F2, 1);
outb($1F3, LBA);
outb($1F4, LBA shr 8);
outb($1F5, LBA shr 16);
outb($1F7, ATAPI_CMD_READ); //read command
//poll status
while true do if (inb($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy
while true do begin
if (inb($1f7) and (1 shl 3)) <> 0 then break;
if (inb($1F7) and 1) <> 0 then begin
console.writestringln('IDE read ERROR');
exit;
end; //drive error
end;
// for i:=0 to 1023 do begin
// Puint32(buffer + (i * 1))^ := inb($1F0);
// end; // end;
console.writestringln('[IDE] (READPIOPI) END');
end;
readPIO28(device^.controllerId0, LBA, puint8(buffer));
procedure read(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
begin
readPIO28(device^.controllerId0, LBA, sectorCount, buffer); //need to figure out max read/write amount per operation
end; end;
procedure write(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); procedure write(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32);
var
i : uint16;
begin begin
writePIO28(device^.controllerId0, LBA, sectorCount, buffer); // for i:=0 to sectorCount-1 do begin
// writePIO28(device^.controllerId0, LBA, puint8(@buffer[512*i]));
// end;
writePIO28(device^.controllerId0, LBA, puint8(buffer));
end; end;
end. end.

View File

@ -834,21 +834,11 @@ begin //maybe increase buffer size by one?
zeroBuffer:= puint32(kalloc( disk^.sectorSize )); zeroBuffer:= puint32(kalloc( disk^.sectorSize ));
memset(uint32(zeroBuffer), 0, disk^.sectorSize ); memset(uint32(zeroBuffer), 0, disk^.sectorSize );
{while true do begin // while true do begin
if i > FATSize then break; // if i > FATSize then break;
writestring('LOOP BEGIN: '); // disk^.writecallback(disk, fatStart + i, 1, zeroBuffer);
writeintln(i); // i+=1;
writeintln(bootRecord^.rsvSectors); // end;
writeintln(start);
writeintln(fatStart);
writeintln(FATSize);
console.redrawWindows;
disk^.writecallback(disk, fatStart + i, 1, zeroBuffer);
writestring('LOOP END: ');
writeintln(i);
console.redrawWindows;
i+=1;
end;}
kfree(buffer); kfree(buffer);
kfree(zeroBuffer); kfree(zeroBuffer);

View File

@ -25,7 +25,7 @@ uses
type type
TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, ControllerNET); TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3);
TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry); TDirectory_Entry_Type = (directoryEntry, fileEntry, mountEntry);
PStorage_volume = ^TStorage_Volume; PStorage_volume = ^TStorage_Volume;
PStorage_device = ^TStorage_Device; PStorage_device = ^TStorage_Device;