diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index 4eb3054d..12c22c2d 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -44,7 +44,7 @@ var function load(ptr: void) : boolean; procedure init(); function get_status(var device : TIDE_Device) : TIDE_Status; - function wait_for_device(device : TIDE_Device) : boolean; + function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean; procedure no_interrupt(isPrimary : boolean); procedure select_device(device : TIDE_Device); @@ -69,7 +69,7 @@ end; @param(device The device to wait for) @returns(@True if the device is ready, @False otherwise) } -function wait_for_device(device : TIDE_Device) : boolean; +function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean; var status : TIDE_Status; i : uint32; @@ -78,10 +78,10 @@ begin i := 0; - while (i < 10000) do begin + while (i < 50000) do begin status := get_status(device); - if (status.BUSY = false) then begin //todo test + if (status.BUSY = false) and (status.DRQ or (not ioop)) then begin //todo test wait_for_device := true; pop_trace(); exit; @@ -127,17 +127,31 @@ end; function get_status(var device : TIDE_Device) : TIDE_Status; var status : TIDE_Status; + errorReg : uint8; begin push_trace('ide.get_status()'); - select_device(device); + // select_device(device); status := TIDE_Status(inb(device.base + ATA_REG_STATUS)); device.status := status; - pop_trace(); - get_status := status; + if status.ERROR then begin + errorReg := inb(device.base + ATA_REG_ERROR); + + console.writestringln('[IDE] ERROR detected!'); + console.writestring('[IDE] ERROR REGISTER: '); + console.writebin8ln(errorReg); + + if (errorReg and $04) <> 0 then console.writestringln('[IDE] ERROR: Aborted Command'); + if (errorReg and $10) <> 0 then console.writestringln('[IDE] ERROR: ID Not Found'); + if (errorReg and $40) <> 0 then console.writestringln('[IDE] ERROR: Uncorrectable Data'); + if (errorReg and $80) <> 0 then console.writestringln('[IDE] ERROR: Bad Block'); + + console.redrawWindows(); + end; + end; { @@ -175,6 +189,19 @@ begin select_device(device); //TODO make sure dvice signture is set at this time, else reset it + //reset any device signature +{ +Write 0x04 to the Control Register (0x3F6 for primary bus, 0x376 for secondary). +Wait ~5 microseconds. +Write 0x00 back to Control Register to complete reset. +// } + outb(ATA_PRIMARY_BASE1, $04); + outb(ATA_SECONDARY_BASE1, $04); + sleep(1); + // outb(ATA_PRIMARY_BASE1, $00); + // outb(ATA_SECONDARY_BASE1, $00); + + sleep(1); //read all bytes of LBA address sec := inb(device.base + ATA_REG_SECCOUNT); @@ -182,14 +209,26 @@ begin lba1 := inb(device.base + ATA_REG_LBA1); lba2 := inb(device.base + ATA_REG_LBA2); - //check if the device is an ATAPI device (01, 01, 14, EB) - if (lba1 = $14) and (lba2 = $EB) then begin + console.writestring('[IDE] (check_device_type) SEC: '); + console.writehexln(sec); + console.writestring('[IDE] (check_device_type) LBA0: '); + console.writehexln(lba0); + console.writestring('[IDE] (check_device_type) LBA1: '); + console.writehexln(lba1); + console.writestring('[IDE] (check_device_type) LBA2: '); + console.writehexln(lba2); + + + //check if the device is an ATAPI device + if ((sec = 3) or (lba2 = $EB)) then begin check_device_type := true; + device.isATAPI := true; + end else if sec = 1 then begin + check_device_type := true; + device.isATAPI := false; end else begin check_device_type := false; end; - - device.isATAPI := check_device_type; end; { @@ -207,11 +246,12 @@ var begin push_trace('ide.load_device()'); + success := check_device_type(device); - if (is_device_present(device)) then begin + if (is_device_present(device) and success) then begin console.writestringln('[IDE] (load_device) Device is present'); - if (check_device_type(device)) then begin + if (device.isATAPI) then begin console.writestringln('[IDE] (load_device) Device is ATAPI'); //todo load device info end else begin @@ -253,25 +293,27 @@ begin end; //wrtie test, 1F2F1F2F repeated - buffer := puint8(kalloc(512)); - memset(uint32(buffer), 0, 512); - for i:=0 to 200 do begin - if (i mod 4 = 0) then begin - buffer[i] := $1F; - end else begin - buffer[i] := $2F; - end; - end; + buffer := puint8(kalloc(1024)); + memset(uint32(buffer), $02, 1024); + uint8(buffer[0]) := $1F; + uint8(buffer[1]) := $2F; + uint8(buffer[2]) := $3F; + uint8(buffer[3]) := $4F; + uint8(buffer[4]) := $5F; + uint8(buffer[5]) := $6F; + uint8(buffer[6]) := $7F; + uint8(buffer[7]) := $8F; + //write to the first sector - ata.write_pio28(device, 0, 1, puint16(buffer)); + ata.write_pio28(device, 10, 2, puint16(buffer)); //read the first sector memset(uint32(buffer), 0, 512); - ata.read_pio28(device, 0, 1, puint16(buffer)); + ata.read_pio28(device, 10, 1, puint16(buffer)); //check if the data is the same - for i:=0 to 200 do begin + for i:=0 to 10 do begin console.writehexln(buffer[i]); end; end; diff --git a/src/driver/storage/ata.pas b/src/driver/storage/ata.pas index 207e6051..a817ca2d 100644 --- a/src/driver/storage/ata.pas +++ b/src/driver/storage/ata.pas @@ -30,6 +30,14 @@ implementation uses ide; + + procedure outb(port : uint16; value : uint8); + begin + util.outb(port, value); + psleep(1); + // get_status(primaryDevices[0]); + end; + { ensure the address is a valid 28 bit address @@ -72,7 +80,7 @@ begin console.writestringln('Error identifying device, maybe'); //todo end; - ready := wait_for_device(device); + ready := wait_for_device(device, false); if not ready then begin console.writestringln('Device not ready in time!'); @@ -123,18 +131,26 @@ begin end; select_device(device); + psleep(50); no_interrupt(device.isPrimary); - + psleep(50); set_lba_mode(device, lba); + psleep(50); outb(device.base + ATA_REG_SECCOUNT, count); + psleep(50); + outb(device.base + ATA_REG_LBA0, (lba and $000000FF)); + psleep(50); outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8); + psleep(50); outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16); + psleep(50); outb(device.base + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + psleep(50); - ready := wait_for_device(device); + ready := wait_for_device(device, false); if not ready then begin console.writestringln('Device not ready in time!'); @@ -142,15 +158,11 @@ begin end; for i:=0 to count-1 do begin - for ii:=0 to 511 do begin //TODO needs to read sector size - buffer[i] := inw(device.base + ATA_REG_DATA); - - ready := wait_for_device(device); - - if not ready then begin - console.writestringln('Device not ready in time!'); - BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR READ'); - end; + ii:=0; + while ii < 256 do begin + buffer[ii+(i*256)] := inw(device.base + ATA_REG_DATA); + ii := ii + 1; + psleep(50); end; end; @@ -175,17 +187,16 @@ begin select_device(device); no_interrupt(device.isPrimary); //maybe not? - set_lba_mode(device, lba); + outb(device.base + ATA_REG_SECCOUNT, count); outb(device.base + ATA_REG_LBA0, (lba and $000000FF)); outb(device.base + ATA_REG_LBA1, (lba and $0000FF00) shr 8); outb(device.base + ATA_REG_LBA2, (lba and $00FF0000) shr 16); - outb(device.base + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - ready := wait_for_device(device); + ready := wait_for_device(device, false); if not ready then begin console.writestringln('Device not ready in time!'); @@ -193,21 +204,23 @@ begin end; for i:=0 to count-1 do begin - for ii:=0 to 511 do begin //TODO needs to read sector size - outw(device.base + ATA_REG_DATA, uint16(buffer[i])); - - ready := wait_for_device(device); - - if not ready then begin - console.writestringln('Device not ready in time!'); - BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE'); - end; + ii:=0; + while ii < 256 do begin + outw(ATA_PRIMARY_BASE + ATA_REG_DATA, buffer[ii+(i*256)]); + ii := ii + 1; + psleep(50); end; + + psleep(50); //todo check + outb(device.base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); + ready := wait_for_device(device, false); + + if not ready then begin + console.writestringln('Device not ready in time!'); + BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR WRITE'); + end; end; - psleep(50); //todo check - outb(device.base + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); - ready := wait_for_device(device); // if not ready then begin // console.writestringln('Device not ready in time!'); diff --git a/src/driver/storage/atapi.pas b/src/driver/storage/atapi.pas index e69de29b..34225b7d 100644 --- a/src/driver/storage/atapi.pas +++ b/src/driver/storage/atapi.pas @@ -0,0 +1,104 @@ +unit atapi; + +interface + +uses + util, + drivertypes, + console, + terminal, + drivermanagement, + vmemorymanager, + lmemorymanager, + storagemanagement, + strings, + tracer, + drivemanager, + storagetypes, + idetypes; + +var + + test : uint32; + + function identify_device(var device : TIDE_Device) : Boolean; + function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; + function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; + + +implementation +uses + ide; + +{ + Identify the device on the IDE bus + + @param(device The device to identify) + @returns(@True if the device is identified, @False otherwise) +} +function identify_device(var device : TIDE_Device) : Boolean; +var + i : uint8; + status : TIDE_Status; + buffer : TIdentResponse; + ready : boolean; +begin + select_device(device); + no_interrupt(device.isPrimary); + + status := get_status(device); + + outb(device.base + ATA_REG_SECCOUNT, 0); + outb(device.base + ATA_REG_LBA0, 0); + outb(device.base + ATA_REG_LBA1, 0); + outb(device.base + ATA_REG_LBA2, 0); + + psleep(1); + + outb(device.base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + + status := get_status(device); + + if status.ERROR then begin + console.writestringln('Error identifying device, maybe'); //todo + end; + + ready := wait_for_device(device, false); + + if not ready then begin + console.writestringln('Device not ready in time!'); + //teapot time + // BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR IDENT'); + exit(false); + end; + + for i:=0 to 255 do begin + buffer[i] := inw(device.base + ATA_REG_DATA); + end; + + device.info := @buffer; + + identify_device := true; +end; + +function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; +var + i : uint16; + ii : uint16; + status : TIDE_Status; + ready : boolean; +begin + +end; + +function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; +var + i : uint16; + ii : uint16; + status : TIDE_Status; + ready : boolean; +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/storage/idetypes.pas b/src/driver/storage/idetypes.pas index b6214234..4a800907 100644 --- a/src/driver/storage/idetypes.pas +++ b/src/driver/storage/idetypes.pas @@ -84,7 +84,7 @@ const ATA_REG_LBA3 = $09; ATA_REG_LBA4 = $0A; ATA_REG_LBA5 = $0B; - ATA_REG_CONTROL = $0C; + ATA_REG_CONTROL = $0C; //1FC on some systems, 3F6 on all ATA_REG_ALTSTATUS = $0C; ATA_REG_DEVADDRESS = $0D; @@ -134,6 +134,13 @@ type info : PIdentResponse; end; + TIDE_PACKET = record + command : uint8; + lba : uint32; + count : uint8; + buffer : puint16; + end; + implementation diff --git a/src/include/util.pas b/src/include/util.pas index 9db9096e..bdff7c13 100644 --- a/src/include/util.pas +++ b/src/include/util.pas @@ -335,6 +335,7 @@ begin //serial.sendString('[outb]'); //serial.sendHex(port); //serial.sendHex(val); + psleep(1); asm PUSH EAX PUSH EDX