From 837d69a44bfa1310e713a5a96c3f8eaec97daff4 Mon Sep 17 00:00:00 2001 From: Aaron Date: Sun, 9 Mar 2025 13:50:11 +0000 Subject: [PATCH] ide rework again --- src/driver/storage/IDE.pas | 696 ++++++++++------------- src/driver/storage/ata.pas | 221 +++++++ src/driver/storage/atapi.pas | 0 src/driver/storage/drivemanager.pas | 5 +- src/driver/storage/idetypes.pas | 140 +++++ src/driver/storage/oldIDE.pas | 504 ++++++++++++++++ src/driver/storage/storagemanagement.pas | 3 +- src/driver/storage/storagetypes.pas | 2 +- 8 files changed, 1164 insertions(+), 407 deletions(-) create mode 100644 src/driver/storage/ata.pas create mode 100644 src/driver/storage/atapi.pas create mode 100644 src/driver/storage/idetypes.pas create mode 100644 src/driver/storage/oldIDE.pas diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index e05d058d..4eb3054d 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -1,17 +1,9 @@ -{ ************************************************ - * Asuro - * Unit: Drivers/storage/IDE - * Description: IDE ATA Driver - * - ************************************************ - * Author: Aaron Hance - * Contributors: - ************************************************ } -unit IDE; +unit ide; interface uses + ata, util, drivertypes, console, @@ -23,226 +15,324 @@ uses strings, tracer, drivemanager, - storagetypes; - -type - TPortMode = (P_READ, P_WRITE); - - TIdentResponse = array[0..255] of uint16; - - TIDE_Channel_Registers = record - base : uint16; - ctrl : uint16; - bmide : uint16; - noInter : uint8 - end; - - TIDE_Device = record - exists : boolean; - isPrimary : boolean; - isMaster : boolean; - isATAPI : boolean; - info : TIdentResponse; - end; - - TIDE_Status = bitpacked record - Busy : Boolean; - Ready : Boolean; - Fault : Boolean; - Seek : Boolean; - DRQ : Boolean; - CORR : Boolean; - IDDEX : Boolean; - ERROR : Boolean; - end; - PIDE_Status = ^TIDE_Status; - - -const - ATA_SR_BUSY = $80; //BUSY - ATA_SR_DRDY = $40; //DRIVE READY - ATA_SR_DF = $20; //DRIVE WRITE FAULT - ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE - ATA_SR_DRQ = $08; //DATA REQUEST READY - ATA_SR_CORR = $04; //CORRECTED DATA - ATA_SR_IDX = $02; //INLEX - ATA_SR_ERR = $01; //ERROR - - ATA_ER_BBK = $80; //BAD SECTOR - ATA_ER_UNC = $40; //UNCORRECTABLE DATA - ATA_ER_MC = $20; //NO MEDIA - ATA_ER_IDNF = $10; //ID MARK NOT FOUND - ATA_ER_MCR = $08; //NO MEDIA - ATA_ER_ABRT = $04; //COMMAND ABORTED - ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND - ATA_ER_AMNF = $01; //NO ADDRESS MARK - - ATA_CMD_READ_PIO = $20; - ATA_CMD_READ_PIO_EXT = $24; - ATA_CMD_READ_DMA = $C8; - ATA_CMD_READ_DMA_EXT = $25; - ATA_CMD_WRITE_PIO = $30; - ATA_CMD_WRITE_PIO_EXT = $34; - ATA_CMD_WRITE_DMA = $CA; - ATA_CMD_WRITE_DMA_EXT = $35; - ATA_CMD_CACHE_FLUSH = $E7; - ATA_CMD_CACHE_FLUSH_EXT = $EA; - ATA_CMD_PACKET = $A0; - ATA_CMD_IDENTIFY_PACKET = $A1; - ATA_CMD_IDENTIFY = $EC; - - ATAPI_CMD_READ = $A8; - ATAPI_CMD_EJECT = $1B; - - ATA_IDENT_DEVICETYPE = $0; - ATA_IDENT_CYLINDERS = $2; - ATA_IDENT_HEADS = $6; - ATA_IDENT_SECOTRS = $12; - ATA_IDENT_SERIAL = $20; - ATA_IDENT_MODEL = $54; - ATA_IDENT_CAPABILITIES = $98; - ATA_IDENT_FIELDVALID = $106; - ATA_IDENT_MAX_LBA = $120; - ATA_IDENT_COMMANDSETS = $164; - ATA_IDENT_MAX_LBA_EXT = $200; - - ATA_REG_DATA = $00; - ATA_REG_ERROR = $01; - ATA_REG_FEATURES = $01; - ATA_REG_SECCOUNT = $02; - ATA_REG_LBA0 = $03; - ATA_REG_LBA1 = $04; - ATA_REG_LBA2 = $05; - ATA_REG_HDDEVSEL = $06; - ATA_REG_COMMAND = $07; - ATA_REG_STATUS = $07; - ATA_REG_SECCOUNT1 = $08; - ATA_REG_LBA3 = $09; - ATA_REG_LBA4 = $0A; - ATA_REG_LBA5 = $0B; - ATA_REG_CONTROL = $0C; - ATA_REG_ALTSTATUS = $0C; - ATA_REG_DEVADDRESS = $0D; - - ATA_DEVICE_MASTER = $A0; - ATA_DEVICE_SLAVE = $B0; - - ATA_PRIMARY_BASE = $1F0; + storagetypes, + idetypes; + var - controller : PPCI_Device; + primaryDevices: array[0..1] of TIDE_Device = ( + (exists: false; isPrimary: true; isMaster: true; isATAPI: false; + status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false); + base: ATA_PRIMARY_BASE; info: nil), - bar0 : uint32; - bar1 : uint32; - bar4 : uint32; + (exists: false; isPrimary: true; isMaster: false; isATAPI: false; + status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false); + base: ATA_PRIMARY_BASE; info: nil) + ); - IDEDevices : array[0..3] of TIDE_Device; + secondaryDevices: array[0..1] of TIDE_Device = ( + (exists: false; isPrimary: false; isMaster: true; isATAPI: false; + status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false); + base: ATA_SECONDARY_BASE; info: nil), - buffer : Puint32; + (exists: false; isPrimary: false; isMaster: false; isATAPI: false; + status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false); + base: ATA_SECONDARY_BASE; info: nil) + ); -procedure init(); -function load(ptr : void) : boolean; -function identify_device(bus : uint8; device : uint8) : TIdentResponse; -// 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 + function load(ptr: void) : boolean; + procedure init(); + function get_status(var device : TIDE_Device) : TIDE_Status; + function wait_for_device(device : TIDE_Device) : boolean; + procedure no_interrupt(isPrimary : boolean); + procedure select_device(device : TIDE_Device); -procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32); -procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32); +implementation -implementation - -function port_read(register : uint8) : uint8; +{ + Disable interrupts on the IDE bus + @param(isPrimary The bus to disable interrupts on) +} +procedure no_interrupt(isPrimary : boolean); begin - port_read:= inb(ATA_PRIMARY_BASE + register); -end; - -procedure port_write(register : uint8; data : uint8); -var - i : uint8; -begin - outb(ATA_PRIMARY_BASE + register, data); - util.psleep(1); - if register = ATA_REG_COMMAND then begin - for i:= 0 to 5 do begin - port_read(ATA_REG_STATUS); - end; + if isPrimary then begin + outb(ATA_INTERRUPT_PRIMARY, inb(ATA_INTERRUPT_PRIMARY) or (1 shl 1)); + end else begin + outb(ATA_INTERRUPT_SECONDARY, inb(ATA_INTERRUPT_SECONDARY) or (1 shl 1)); end; end; -procedure no_interrupt(device : uint8); -begin - outb($3F6, inb($3f6) or (1 shl 1)); -end; +{ + Wait for the device to be ready on the IDE bus -procedure device_select(device : uint8); -begin - outb($1F6, device); //TODO clean -end; - -function is_ready() : boolean; -var - status : uint8; + @param(device The device to wait for) + @returns(@True if the device is ready, @False otherwise) +} +function wait_for_device(device : TIDE_Device) : boolean; +var + status : TIDE_Status; i : uint32; begin - //wait for drive to be ready - while true do begin - status := port_read(ATA_REG_COMMAND); + push_trace('ide.wait_for_device()'); - if(status and ATA_SR_ERR) = ATA_SR_ERR then begin - console.writestringln('[IDE] (IDENTIFY_DEVICE) DRIVE ERROR!'); - console.redrawWindows(); - is_ready := false; - break; + i := 0; + + while (i < 10000) do begin + status := get_status(device); + + if (status.BUSY = false) then begin //todo test + wait_for_device := true; + pop_trace(); + exit; end; - if (status and ATA_SR_BUSY) <> ATA_SR_BUSY then begin - is_ready := true; - break; - end; + i := i + 1; end; + + wait_for_device := false; + pop_trace(); end; -function validate_28bit_address(addr : uint32) : boolean; -begin - validate_28bit_address := (addr and $F0000000) = 0; -end; +{ + Select the active device on the IDE bus + @param(device The device to select) -function identify_device(bus : uint8; device : uint8) : TIdentResponse; + Function can set the device to either master or slave, + one device per bus/channel can be active at a time. +} +procedure select_device(device : TIDE_Device); var - status : uint8; - identResponse : TIdentResponse; - i : uint8; -begin - push_trace('IDE.Identify_Device'); - device_select(device); - no_interrupt(device); - port_write(ATA_REG_CONTROL, 0); + dev : uint8; +begin + push_trace('ide.select_device()'); - //check if bus is floating - status := port_read(ATA_REG_COMMAND); - if status = $FF then exit; + dev := ATA_DEVICE_SLAVE; - 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); + if device.isMaster then begin + dev := ATA_DEVICE_MASTER; end; - identify_device := identResponse; + outb(device.base + ATA_REG_HDDEVSEL, dev); + + pop_trace(); +end; + +{ + Get the status of the device on the IDE bus + + @param(device The device to get the status of) + @returns(@TIDE_Device The status of the device on the IDE bus) +} +function get_status(var device : TIDE_Device) : TIDE_Status; +var + status : TIDE_Status; +begin + push_trace('ide.get_status()'); + + select_device(device); + + status := TIDE_Status(inb(device.base + ATA_REG_STATUS)); + + device.status := status; + + pop_trace(); + get_status := status; +end; + +{ + Check if the device is present on the IDE bus + + @param(device The device to check) + @returns(@True if the device is present, @False otherwise) +} +function is_device_present(var device : TIDE_Device) : boolean; +begin + push_trace('ide.is_device_present()'); + + get_status(device); + + if (uInt8(device.status) = $FF) then begin //TODO make this more robust + is_device_present := false; + end else begin + is_device_present := true; + end; + +end; + +{ + Check if the device is an ATAPI device + + @param(device The device to check) + @returns(@True if the device is an ATAPI device, @False otherwise) +} +function check_device_type(var device : TIDE_Device) : boolean; +var + sec, lba0, lba1, lba2 : uint8; +begin + push_trace('ide.check_device_type()'); + + select_device(device); + + //TODO make sure dvice signture is set at this time, else reset it + + //read all bytes of LBA address + sec := inb(device.base + ATA_REG_SECCOUNT); + lba0 := inb(device.base + ATA_REG_LBA0); + 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 + check_device_type := true; + end else begin + check_device_type := false; + end; + + device.isATAPI := check_device_type; +end; + +{ + Load the device on the IDE bus + + @param(device The device to load) + @returns(@True if the device is loaded, @False otherwise) +} +procedure load_device(var device : TIDE_Device); +var + i : uint8; + buffer : puint8; + storageDevice : PStorage_device; + success : boolean; +begin + + push_trace('ide.load_device()'); + + if (is_device_present(device)) then begin + console.writestringln('[IDE] (load_device) Device is present'); + + if (check_device_type(device)) then begin + console.writestringln('[IDE] (load_device) Device is ATAPI'); + //todo load device info + end else begin + console.writestringln('[IDE] (load_device) Device is ATA'); + success:= ata.identify_device(device); + end; + + if not success then begin + console.writestringln('[IDE] (load_device) Error identifying device'); //todo + device.exists := false; + exit; + end; + + device.exists := true; + + storageDevice := PStorage_Device(kalloc(sizeof(TStorage_Device))); + memset(uint32(storageDevice), 0, sizeof(TStorage_Device)); + + if (device.isATAPI) then begin + storageDevice^.controller := TControllerType.ControllerATAPI; + storageDevice^.writable := false; //TODO atapi + end else begin + storageDevice^.controller := TControllerType.ControllerATA; + storageDevice^.writable := true; + + storageDevice^.maxSectorCount := (device.info^[61] shl 16) or device.info^[60]; + storageDevice^.sectorSize := 512; //todo + + if (device.isMaster) then begin + storageDevice^.controllerId0 := 0; + end else begin + storageDevice^.controllerId0 := 1; + end; + + //if secotorcount is 0, then the device is not present + if (storageDevice^.maxSectorCount = 0) then begin + device.exists := false; + exit; + 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; + + //write to the first sector + ata.write_pio28(device, 0, 1, puint16(buffer)); + + //read the first sector + memset(uint32(buffer), 0, 512); + ata.read_pio28(device, 0, 1, puint16(buffer)); + + //check if the data is the same + for i:=0 to 200 do begin + console.writehexln(buffer[i]); + end; + end; + + //register the device + drivemanager.register_device(storageDevice); + + end else begin + console.writestringln('[IDE] (load_device) Device is not present'); + device.exists := false; + end; + + pop_trace(); +end; + + +function load(ptr: void) : boolean; +var + pciDevice : PPCI_Device; + buffer : puint8; + i : uint8; +begin + push_trace('ide.load()'); + console.writestringln('[IDE] (load) Loading IDE Devices'); + + pciDevice := PPCI_Device(ptr); + + load_device(primaryDevices[0]); + load_device(primaryDevices[1]); + load_device(secondaryDevices[0]); + load_device(secondaryDevices[1]); + + pop_trace(); + load := true; + + console.writestringln('[IDE] (load) IDE Device Loading Finished'); + + i := 0; + + if (primaryDevices[0].exists) then begin + console.writestringln('[IDE] (load) FOUND Primary Master Device 0'); + i := i + 1; + end; + + if (primaryDevices[1].exists) then begin + console.writestringln('[IDE] (load) FOUND Primary Slave Device 1'); + i := i + 1; + end; + + if (secondaryDevices[0].exists) then begin + console.writestringln('[IDE] (load) FOUND Secondary Master Device 2'); + i := i + 1; + end; + + if (secondaryDevices[1].exists) then begin + console.writestringln('[IDE] (load) FOUND Secondary Slave Device 3'); + i := i + 1; + end; + + // console.writestringln('[IDE] (load) Found ' + i + ' IDE Devices'); + end; procedure init(); @@ -258,208 +348,8 @@ begin devID.id3:= idANY; devID.id4:= idANY; devID.ex:= nil; - drivermanagement.register_driver('IDE ATA Driver', @devID, @load); + drivermanagement.register_driver('IDE ATA/ATAPI Driver', @devID, @load); console.writestringln('[IDE] (INIT) END'); end; -function load(ptr : void) : boolean; -var - controller : PPCI_Device; - masterDevice : TStorage_Device; - slaveDevice : TStorage_Device; - buffer : puint8; - i : uint8; - test : PStorage_device; -begin - push_trace('ide.load'); - console.writestringln('[IDE] (LOAD) BEGIN'); - controller := PPCI_Device(ptr); - - console.writestringln('[IDE] (INIT) CHECK FLOATING BUS'); - //check if bus is floating and identify device - if inb($1F7) <> $FF then begin - //outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts - IDEDevices[0].isMaster:= true; - IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER); - - masterDevice.controller := ControllerIDE; - masterDevice.controllerId0:= 0; - masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA - - if IDEDevices[0].info[1] = 0 then begin - console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!'); - exit; - end; - - // masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); //TODO wtf is hpc - - masterDevice.sectorSize:= 512; - if masterDevice.maxSectorCount <> 0 then begin - IDEDevices[0].exists:= true; - masterDevice.readCallback:= @dread; - masterDevice.writeCallback:= @dwrite; - // storagemanagement.register_device(@masterDevice); - drivemanager.register_device(@masterDevice); - end; - - end; - - // buffer:= puint8(kalloc(512)); - // buffer[0] := 1; - // buffer[1] := 2; - // buffer[2] := 3; - // buffer[3] := 4; - // buffer[4] := 5; - // buffer[5] := 6; - // writePIO28(0, 3, buffer); - // writePIO28(0, 3, buffer); - // writePIO28(0, 3, buffer); - // writePIO28(0, 4, buffer); - // writePIO28(0, 5, buffer); - // writePIO28(0, 5, buffer); - // writePIO28(0, 5, buffer); - // psleep(1000); - // writePIO28(0, 5, buffer); - // writePIO28(0, 5, buffer); - // writePIO28(0, 5, buffer); - // kfree(puint32(buffer)); - - console.writestringln('[IDE] (LOAD) END'); -end; - -procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8); -var - status : uint8; - i: uint16; - device: uint8; - data: uint16; -begin - push_trace('IDE.readPIO28'); - - if not validate_28bit_address(LBA) then begin - console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!'); - end; - - // push_trace('IDE.readPIO28.2'); - - //Add last 4 bits of LBA to device port - if IDEDevices[drive].isMaster then begin - device:= ATA_DEVICE_MASTER; - device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master - end - else begin - device:= ATA_DEVICE_SLAVE; - device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave - end; - - // push_trace('IDE.readPIO28.3'); - - no_interrupt(device); - port_write(ATA_REG_ERROR, 0); - - //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); - - // push_trace('IDE.readPIO28.4'); - - //send read command - port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO); - if not is_ready() then exit; - - i:=0; - while i < 512 do begin - // if not is_ready() then exit; - - data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA); - - buffer[i+1] := uint8($00ff and (data shr 8)); - buffer[i] := uint8($00ff and data); - - i:= i + 2; - end; - - // push_trace('IDE.readPIO28.5'); -end; - -procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8); -var - status : uint8; - i: uint16; - device: uint8; -begin - push_trace('IDE.WritePIO28'); - if not validate_28bit_address(LBA) then begin - console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!'); - end; - - console.writeintln(uint32(drive)); - console.writeintln(LBA); - - //Add last 4 bits of LBA to device port - if IDEDevices[drive].isMaster then begin - device:= ATA_DEVICE_MASTER; - device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master - end - else begin - device:= ATA_DEVICE_SLAVE; - device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave - end; - - // no_interrupt(device); - - port_write(ATA_REG_ERROR, 0); - port_write(ATA_REG_CONTROL, 0); - - // check if bus is floating - status := port_read(ATA_REG_COMMAND); - if status = $FF then exit; - - //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); - - //send write command - port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - - //write data - i:=0; - while i < 512 do begin - outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8))); - i:= i + 2; - end; - - //flush drive cache - psleep(1); - port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); - psleep(1); - if not is_ready() then exit; -end; - -procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); -var - i : uint16; -begin - push_trace('IDE.dread'); - for i:=0 to sectorCount-1 do begin - readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); - psleep(100) - end; -end; - -procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); -var - i : uint16; -begin - for i:=0 to sectorCount-1 do begin - writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); - psleep(100) - end; - // writePIO28(device^.controllerId0, LBA, puint8(buffer)); -end; - end. \ No newline at end of file diff --git a/src/driver/storage/ata.pas b/src/driver/storage/ata.pas new file mode 100644 index 00000000..207e6051 --- /dev/null +++ b/src/driver/storage/ata.pas @@ -0,0 +1,221 @@ +unit ata; + +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; + +{ + ensure the address is a valid 28 bit address + + @param(addr The address to validate) + @returns(@True if the address is valid, @False otherwise) +} +function validate_28bit_address(addr : uint32) : boolean; +begin + validate_28bit_address := (addr and $F0000000) = 0; +end; + +{ + 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); + + outb(device.base + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + status := get_status(device); + + if status.ERROR then begin + console.writestringln('Error identifying device, maybe'); //todo + end; + + ready := wait_for_device(device); + + 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; + +procedure set_lba_mode(device : TIDE_Device; lba : uint32); +begin + // if device.isPrimary then begin + if device.isMaster then begin + outb(device.base + ATA_REG_HDDEVSEL, $E0 or ((lba and $0F000000) shr 24)); + end else begin + outb(device.base + ATA_REG_HDDEVSEL, $F0 or ((lba and $0F000000) shr 24)); + end; + // end else begin //TODO + // if device.isMaster then begin + // outb(device.base + ATA_REG_HDDEVSEL, $A0); + // end else begin + // outb(device.base + ATA_REG_HDDEVSEL, $B0); + // end; + // end; +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 + push_trace('ata.read_pio28()'); + + if not validate_28bit_address(lba) then begin + console.writestringln('Invalid address for 28 bit read'); + read_pio28 := false; + exit; + end; + + select_device(device); + no_interrupt(device.isPrimary); + + 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_READ_PIO); + + 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 COMMAND'); + 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; + end; + end; + + read_pio28 := true; + pop_trace(); +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 + push_trace('ata.write_pio28()'); + + if not validate_28bit_address(lba) then begin + console.writestringln('Invalid address for 28 bit write'); + write_pio28 := false; + exit; + end; + + 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); + + 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 COMMAND'); + 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; + 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!'); + // BSOD('Device not ready in time!', 'ATA DEVICE NOT READY IN TIME FOR CACHE FLUSH'); + // end; + + write_pio28 := true; + pop_trace(); +end; + +end. \ No newline at end of file diff --git a/src/driver/storage/atapi.pas b/src/driver/storage/atapi.pas new file mode 100644 index 00000000..e69de29b diff --git a/src/driver/storage/drivemanager.pas b/src/driver/storage/drivemanager.pas index 2286b881..be089a86 100644 --- a/src/driver/storage/drivemanager.pas +++ b/src/driver/storage/drivemanager.pas @@ -271,7 +271,7 @@ begin PStorage_device(elm)^.volumes := LL_New(sizeof(TStorage_Volume)); //TODO register with volume manager - volumemanager.check_for_volumes(PStorage_Device(elm)); + //volumemanager.check_for_volumes(PStorage_Device(elm)); end; { Get the drive list } @@ -290,7 +290,8 @@ begin //return string of controller type case controllerType of - ControllerIDE : controller_type_2_string:= 'IDE'; + ControllerATA : controller_type_2_string:= 'ATA'; + ControllerATAPI : controller_type_2_string:= 'ATAPI'; ControllerUSB : controller_type_2_string:= 'USB'; ControllerAHCI : controller_type_2_string:= 'ACHI (SATA)'; ControllerNET : controller_type_2_string:= 'Net'; diff --git a/src/driver/storage/idetypes.pas b/src/driver/storage/idetypes.pas new file mode 100644 index 00000000..b6214234 --- /dev/null +++ b/src/driver/storage/idetypes.pas @@ -0,0 +1,140 @@ +// Copyright 2021 Aaron Hance +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Storage->IDE->idetypes - IDE device types and constants. + + @author(Aaron Hance ) +} +unit idetypes; + +interface + +const + + ATA_SR_BUSY = $80; //BUSY + ATA_SR_DRDY = $40; //DRIVE READY + ATA_SR_DF = $20; //DRIVE WRITE FAULT + ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE + ATA_SR_DRQ = $08; //DATA REQUEST READY + ATA_SR_CORR = $04; //CORRECTED DATA + ATA_SR_IDX = $02; //INLEX + ATA_SR_ERR = $01; //ERROR + + ATA_ER_BBK = $80; //BAD SECTOR + ATA_ER_UNC = $40; //UNCORRECTABLE DATA + ATA_ER_MC = $20; //NO MEDIA + ATA_ER_IDNF = $10; //ID MARK NOT FOUND + ATA_ER_MCR = $08; //NO MEDIA + ATA_ER_ABRT = $04; //COMMAND ABORTED + ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND + ATA_ER_AMNF = $01; //NO ADDRESS MARK + + ATA_CMD_READ_PIO = $20; + ATA_CMD_READ_PIO_EXT = $24; + ATA_CMD_READ_DMA = $C8; + ATA_CMD_READ_DMA_EXT = $25; + ATA_CMD_WRITE_PIO = $30; + ATA_CMD_WRITE_PIO_EXT = $34; + ATA_CMD_WRITE_DMA = $CA; + ATA_CMD_WRITE_DMA_EXT = $35; + ATA_CMD_CACHE_FLUSH = $E7; + ATA_CMD_CACHE_FLUSH_EXT = $EA; + ATA_CMD_PACKET = $A0; + ATA_CMD_IDENTIFY_PACKET = $A1; + ATA_CMD_IDENTIFY = $EC; + + ATAPI_CMD_READ = $A8; + ATAPI_CMD_EJECT = $1B; + + ATA_IDENT_DEVICETYPE = $0; + ATA_IDENT_CYLINDERS = $2; + ATA_IDENT_HEADS = $6; + ATA_IDENT_SECOTRS = $12; + ATA_IDENT_SERIAL = $20; + ATA_IDENT_MODEL = $54; + ATA_IDENT_CAPABILITIES = $98; + ATA_IDENT_FIELDVALID = $106; + ATA_IDENT_MAX_LBA = $120; + ATA_IDENT_COMMANDSETS = $164; + ATA_IDENT_MAX_LBA_EXT = $200; + + ATA_REG_DATA = $00; + ATA_REG_ERROR = $01; + ATA_REG_FEATURES = $01; + ATA_REG_SECCOUNT = $02; + ATA_REG_LBA0 = $03; + ATA_REG_LBA1 = $04; + ATA_REG_LBA2 = $05; + ATA_REG_HDDEVSEL = $06; + ATA_REG_COMMAND = $07; + ATA_REG_STATUS = $07; + ATA_REG_SECCOUNT1 = $08; + ATA_REG_LBA3 = $09; + ATA_REG_LBA4 = $0A; + ATA_REG_LBA5 = $0B; + ATA_REG_CONTROL = $0C; + ATA_REG_ALTSTATUS = $0C; + ATA_REG_DEVADDRESS = $0D; + + ATA_DEVICE_MASTER = $A0; + ATA_DEVICE_SLAVE = $B0; + + ATA_PRIMARY_BASE = $1F0; + ATA_PRIMARY_BASE1 = $3F6; + ATA_SECONDARY_BASE = $170; //todo check this + ATA_SECONDARY_BASE1 = $376; //todo check this + + ATA_INTERRUPT_PRIMARY = $3F6; + ATA_INTERRUPT_SECONDARY = $376; + +type + TPortMode = (P_READ, P_WRITE); + + TIdentResponse = array[0..255] of uint16; + PIdentResponse = ^TIdentResponse; + + TIDE_Channel_Registers = record + base : uint16; + ctrl : uint16; + bmide : uint16; + noInter : uint8 + end; + + TIDE_Status = bitpacked record + Busy : Boolean; + Ready : Boolean; + Fault : Boolean; + Seek : Boolean; + DRQ : Boolean; + CORR : Boolean; + IDDEX : Boolean; + ERROR : Boolean; + end; + PIDE_Status = ^TIDE_Status; + + TIDE_Device = record + exists : boolean; + isPrimary : boolean; + isMaster : boolean; + isATAPI : boolean; + status : TIDE_Status; + base : uint16; + info : PIdentResponse; + end; + + +implementation + +end. \ No newline at end of file diff --git a/src/driver/storage/oldIDE.pas b/src/driver/storage/oldIDE.pas new file mode 100644 index 00000000..dcdc2261 --- /dev/null +++ b/src/driver/storage/oldIDE.pas @@ -0,0 +1,504 @@ +{ ************************************************ + * Asuro + * Unit: Drivers/storage/IDE + * Description: IDE ATA Driver + * + ************************************************ + * Author: Aaron Hance + * Contributors: + ************************************************ } +unit IDE; + +interface + +uses + util, + drivertypes, + console, + terminal, + drivermanagement, + vmemorymanager, + lmemorymanager, + storagemanagement, + strings, + tracer, + drivemanager, + storagetypes; + +type + TPortMode = (P_READ, P_WRITE); + + TIdentResponse = array[0..255] of uint16; + + TIDE_Channel_Registers = record + base : uint16; + ctrl : uint16; + bmide : uint16; + noInter : uint8 + end; + + TIDE_Device = record + exists : boolean; + isPrimary : boolean; + isMaster : boolean; + isATAPI : boolean; + info : TIdentResponse; + end; + + TIDE_Status = bitpacked record + Busy : Boolean; + Ready : Boolean; + Fault : Boolean; + Seek : Boolean; + DRQ : Boolean; + CORR : Boolean; + IDDEX : Boolean; + ERROR : Boolean; + end; + PIDE_Status = ^TIDE_Status; + + +const + ATA_SR_BUSY = $80; //BUSY + ATA_SR_DRDY = $40; //DRIVE READY + ATA_SR_DF = $20; //DRIVE WRITE FAULT + ATA_SR_DSC = $10; //DRIVE SEEK COMPLETE + ATA_SR_DRQ = $08; //DATA REQUEST READY + ATA_SR_CORR = $04; //CORRECTED DATA + ATA_SR_IDX = $02; //INLEX + ATA_SR_ERR = $01; //ERROR + + ATA_ER_BBK = $80; //BAD SECTOR + ATA_ER_UNC = $40; //UNCORRECTABLE DATA + ATA_ER_MC = $20; //NO MEDIA + ATA_ER_IDNF = $10; //ID MARK NOT FOUND + ATA_ER_MCR = $08; //NO MEDIA + ATA_ER_ABRT = $04; //COMMAND ABORTED + ATA_ER_TK0NF = $02; //TRACK 0 NOT FOUND + ATA_ER_AMNF = $01; //NO ADDRESS MARK + + ATA_CMD_READ_PIO = $20; + ATA_CMD_READ_PIO_EXT = $24; + ATA_CMD_READ_DMA = $C8; + ATA_CMD_READ_DMA_EXT = $25; + ATA_CMD_WRITE_PIO = $30; + ATA_CMD_WRITE_PIO_EXT = $34; + ATA_CMD_WRITE_DMA = $CA; + ATA_CMD_WRITE_DMA_EXT = $35; + ATA_CMD_CACHE_FLUSH = $E7; + ATA_CMD_CACHE_FLUSH_EXT = $EA; + ATA_CMD_PACKET = $A0; + ATA_CMD_IDENTIFY_PACKET = $A1; + ATA_CMD_IDENTIFY = $EC; + + ATAPI_CMD_READ = $A8; + ATAPI_CMD_EJECT = $1B; + + ATA_IDENT_DEVICETYPE = $0; + ATA_IDENT_CYLINDERS = $2; + ATA_IDENT_HEADS = $6; + ATA_IDENT_SECOTRS = $12; + ATA_IDENT_SERIAL = $20; + ATA_IDENT_MODEL = $54; + ATA_IDENT_CAPABILITIES = $98; + ATA_IDENT_FIELDVALID = $106; + ATA_IDENT_MAX_LBA = $120; + ATA_IDENT_COMMANDSETS = $164; + ATA_IDENT_MAX_LBA_EXT = $200; + + ATA_REG_DATA = $00; + ATA_REG_ERROR = $01; + ATA_REG_FEATURES = $01; + ATA_REG_SECCOUNT = $02; + ATA_REG_LBA0 = $03; + ATA_REG_LBA1 = $04; + ATA_REG_LBA2 = $05; + ATA_REG_HDDEVSEL = $06; + ATA_REG_COMMAND = $07; + ATA_REG_STATUS = $07; + ATA_REG_SECCOUNT1 = $08; + ATA_REG_LBA3 = $09; + ATA_REG_LBA4 = $0A; + ATA_REG_LBA5 = $0B; + ATA_REG_CONTROL = $0C; + ATA_REG_ALTSTATUS = $0C; + ATA_REG_DEVADDRESS = $0D; + + ATA_DEVICE_MASTER = $A0; + ATA_DEVICE_SLAVE = $B0; + + ATA_PRIMARY_BASE = $1F0; + +var + controller : PPCI_Device; + + bar0 : uint32; + bar1 : uint32; + bar4 : uint32; + + IDEDevices : array[0..3] of TIDE_Device; + + buffer : Puint32; + +procedure init(); +function load(ptr : void) : boolean; +function identify_device(bus : uint8; device : uint8) : TIdentResponse; + +// 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 + +procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32); +procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : puint32); + +implementation + +function port_read(register : uint8) : uint8; +begin + port_read:= inb(ATA_PRIMARY_BASE + register); +end; + +procedure port_write(register : uint8; data : uint8); +var + i : uint8; +begin + outb(ATA_PRIMARY_BASE + register, data); + util.psleep(1); + if register = ATA_REG_COMMAND then begin + for i:= 0 to 5 do begin + port_read(ATA_REG_STATUS); + end; + end; +end; + +procedure no_interrupt(device : uint8); +begin + outb($3F6, inb($3f6) or (1 shl 1)); +end; + +procedure device_select(device : uint8); +begin + outb($1F6, device); //TODO clean +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; + + 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 + push_trace('IDE.Identify_Device'); + device_select(device); + no_interrupt(device); + port_write(ATA_REG_CONTROL, 0); + + console.writestringln('[IDE] (IDENTIFY_DEVICE) CHECK FLOATING BUS'); + + //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); + + console.writestringln('[IDE] (IDENTIFY_DEVICE) SEND IDENTIFY COMMAND'); + + port_write(ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY'); + + //check if drive is present + status := port_read(ATA_REG_COMMAND); + if status = $00 then exit; + + console.writestringln('[IDE] (IDENTIFY_DEVICE) WAIT FOR DRIVE TO BE READY'); + + if not is_ready() then exit; + + console.writestringln('[IDE] (IDENTIFY_DEVICE) READ IDENTIFY RESPONSE'); + + for i:=0 to 255 do begin + console.writeint(i); + identResponse[i] := inw(ATA_PRIMARY_BASE + ATA_REG_DATA); + end; + + console.writestringln('[IDE] (IDENTIFY_DEVICE) IDENTIFY RESPONSE RECEIVED'); + + identify_device := identResponse; +end; + +procedure init(); +var + devID : TDeviceIdentifier; +begin + push_trace('ide.init'); + console.writestringln('[IDE] (INIT) BEGIN'); + devID.bus:= biPCI; + devID.id0:= idANY; + devID.id1:= $00000001; + devID.id2:= $00000001; + devID.id3:= idANY; + devID.id4:= idANY; + devID.ex:= nil; + drivermanagement.register_driver('IDE ATA Driver', @devID, @load); + console.writestringln('[IDE] (INIT) END'); +end; + +function load(ptr : void) : boolean; +var + controller : PPCI_Device; + masterDevice : TStorage_Device; + slaveDevice : TStorage_Device; + buffer : puint8; + i : uint8; + test : PStorage_device; + tbuf : puint8; +begin + push_trace('ide.load'); + console.writestringln('[IDE] (LOAD) BEGIN'); + controller := PPCI_Device(ptr); + + console.writestringln('[IDE] (INIT) CHECK FLOATING BUS'); + //check if bus is floating and identify device + if inb($1F7) <> $FF then begin + //outb($3F6, inb($3f6) or (1 shl 1)); // disable interrupts + IDEDevices[0].isMaster:= true; + IDEDevices[0].info := identify_device(0, ATA_DEVICE_MASTER); +e + mastrDevice.controller := ControllerIDE; + masterDevice.controllerId0:= 0; + masterDevice.maxSectorCount:= (IDEDevices[0].info[60] or (IDEDevices[0].info[61] shl 16) ); //LBA28 SATA + + if IDEDevices[0].info[1] = 0 then begin + console.writestringln('[IDE] (INIT) ERROR: DEVICE IDENT FAILED!'); + exit; + end; + + // masterDevice.hpc:= uint32(IDEDevices[0].info[3] DIV IDEDevices[0].info[1]); //TODO wtf is hpc + + masterDevice.sectorSize:= 512; + if masterDevice.maxSectorCount <> 0 then begin + IDEDevices[0].exists:= true; + masterDevice.readCallback:= @dread; + masterDevice.writeCallback:= @dwrite; + // storagemanagement.register_device(@masterDevice); + drivemanager.register_device(@masterDevice); + end; + + end; + + // buffer:= puint8(kalloc(512)); + // buffer[0] := 1; + // buffer[1] := 2; + // buffer[2] := 3; + // buffer[3] := 4; + // buffer[4] := 5; + // buffer[5] := 6; + // writePIO28(0, 3, buffer); + // writePIO28(0, 3, buffer); + // writePIO28(0, 3, buffer); + // writePIO28(0, 4, buffer); + // writePIO28(0, 5, buffer); + // writePIO28(0, 5, buffer); + // writePIO28(0, 5, buffer); + // psleep(1000); + // writePIO28(0, 5, buffer); + // writePIO28(0, 5, buffer); + // writePIO28(0, 5, buffer); + // kfree(puint32(buffer)); + + console.writestringln('[IDE] (LOAD) END'); + + //read first 16 bytes of disk + tbuf:= puint8(kalloc(512)); + + //set buffer to 1F1F repeating + for i:=0 to 200 do begin + tbuf[i] := 31; + end; + + //write buffer to disk + writePIO28(0, 0, tbuf); + + memset(uint32(tbuf), 0, 512); + readPIO28(0, 0, puint8(tbuf)); + console.writestringln('[IDE] (INIT) READ FIRST 4 BYTES OF DISK'); + console.writehexln(tbuf[0]); + console.writehexln(tbuf[1]); + console.writehexln(tbuf[2]); + console.writehexln(tbuf[3]); + kfree(puint32(tbuf)); + + + +end; + +procedure readPIO28(drive : uint8; LBA : uint32; buffer : puint8); +var + status : uint8; + i: uint16; + device: uint8; + data: uint16; +begin + push_trace('IDE.readPIO28'); + + if not validate_28bit_address(LBA) then begin + console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!'); + end; + + // push_trace('IDE.readPIO28.2'); + + //Add last 4 bits of LBA to device port + if IDEDevices[drive].isMaster then begin + device:= ATA_DEVICE_MASTER; + device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master + end + else begin + device:= ATA_DEVICE_SLAVE; + device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave + end; + + // push_trace('IDE.readPIO28.3'); + + no_interrupt(device); + port_write(ATA_REG_ERROR, 0); + + //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); + + // push_trace('IDE.readPIO28.4'); + + //send read command + port_write(ATA_REG_COMMAND, ATA_CMD_READ_PIO); + if not is_ready() then exit; + + i:=0; + while i < 512 do begin + // if not is_ready() then exit; + + data:= inw(ATA_PRIMARY_BASE + ATA_REG_DATA); + + buffer[i+1] := uint8($00ff and (data shr 8)); + buffer[i] := uint8($00ff and data); + + i:= i + 2; + + if not is_ready() then exit; + end; + + // push_trace('IDE.readPIO28.5'); +end; + +procedure writePIO28(drive : uint8; LBA : uint32; buffer : puint8); +var + status : uint8; + i: uint16; + device: uint8; +begin + push_trace('IDE.WritePIO28'); + if not validate_28bit_address(LBA) then begin + console.writestringln('IDE (writePIO28) ERROR: Invalid LBA!'); + end; + + console.writeintln(uint32(drive)); + console.writeintln(LBA); + + //Add last 4 bits of LBA to device port + if IDEDevices[drive].isMaster then begin + device:= ATA_DEVICE_MASTER; + device_select($E0 or ((LBA and $0F000000) shr 24)); //LBA primary master + end + else begin + device:= ATA_DEVICE_SLAVE; + device_select($F0 or ((LBA and $0F000000) shr 24)); //LBA primary slave + end; + + // no_interrupt(device); + + port_write(ATA_REG_ERROR, 0); + port_write(ATA_REG_CONTROL, 0); + + // check if bus is floating + status := port_read(ATA_REG_COMMAND); + if status = $FF then exit; + + //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); + + //send write command + port_write(ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + + //write data + i:=0; + while i < 512 do begin + outw(ATA_PRIMARY_BASE + ATA_REG_DATA, uint16(buffer[i] or (buffer[i+1] shl 8))); + i:= i + 2; + end; + + //flush drive cache + psleep(1); + port_write(ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH); + psleep(1); + if not is_ready() then exit; +end; + +procedure dread(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); +var + i : uint16; +begin + push_trace('IDE.dread'); + for i:=0 to sectorCount-1 do begin + readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); + psleep(100) + end; +end; + +procedure dwrite(device : PStorage_device; LBA : uint32; sectorCount : uint32; buffer : Puint32); +var + i : uint16; +begin + for i:=0 to sectorCount-1 do begin + writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); + psleep(100) + end; + // writePIO28(device^.controllerId0, LBA, puint8(buffer)); +end; + +end. \ No newline at end of file diff --git a/src/driver/storage/storagemanagement.pas b/src/driver/storage/storagemanagement.pas index 011a4152..b2f6ae40 100644 --- a/src/driver/storage/storagemanagement.pas +++ b/src/driver/storage/storagemanagement.pas @@ -82,7 +82,8 @@ implementation function controller_type_2_string(controllerType : TControllerType) : pchar; begin case controllerType of - ControllerIDE : controller_type_2_string:= 'IDE'; + ControllerATA : controller_type_2_string:= 'ATA'; + ControllerATAPI : controller_type_2_string:= 'ATAPI'; ControllerUSB : controller_type_2_string:= 'USB'; ControllerAHCI : controller_type_2_string:= 'ACHI (SATA)'; ControllerNET : controller_type_2_string:= 'Net'; diff --git a/src/driver/storage/storagetypes.pas b/src/driver/storage/storagetypes.pas index 66e763d9..0da6d1a7 100644 --- a/src/driver/storage/storagetypes.pas +++ b/src/driver/storage/storagetypes.pas @@ -26,7 +26,7 @@ uses type - TControllerType = (ControllerIDE, ControllerUSB, ControllerAHCI, + TControllerType = (ControllerATA, ControllerATAPI, ControllerUSB, ControllerAHCI, ControllerNET, ControllerRAM, rsvctr1, rsvctr2, rsvctr3); PStorage_device = ^TStorage_Device;