From fd0de9f1d23b24567a0e1655ada50cfe263523e7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 10 Mar 2025 22:38:50 +0000 Subject: [PATCH] atapi progress --- src/driver/storage/IDE.pas | 92 +++++++++++++---- src/driver/storage/atapi.pas | 189 ++++++++++++++++++++++++++++++++++- 2 files changed, 256 insertions(+), 25 deletions(-) diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index 12c22c2d..7f3ba440 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -4,6 +4,7 @@ interface uses ata, + atapi, util, drivertypes, console, @@ -243,10 +244,12 @@ var buffer : puint8; storageDevice : PStorage_device; success : boolean; + size : uint32; begin push_trace('ide.load_device()'); success := check_device_type(device); + select_device(device); if (is_device_present(device) and success) then begin console.writestringln('[IDE] (load_device) Device is present'); @@ -254,9 +257,28 @@ begin if (device.isATAPI) then begin console.writestringln('[IDE] (load_device) Device is ATAPI'); //todo load device info + success := atapi.identify_device(device); + + device.exists := true; + device.isATAPI := true; + end else begin console.writestringln('[IDE] (load_device) Device is ATA'); success:= ata.identify_device(device); + + //check if atapi device using info from identify_device + console.writestringln('[IDE] (load_device) Device info: '); + console.writecharln(char(puint8(device.info)[252])); + console.writecharln(char(puint8(device.info)[253])); + + if (puint8(device.info)[253] = $FF) then begin + console.writestringln('[IDE] (load_device) Device is ATAPI'); + device.isATAPI := true; + device.exists := true; + + success := atapi.identify_device(device); + end; + end; if not success then begin @@ -273,6 +295,36 @@ begin if (device.isATAPI) then begin storageDevice^.controller := TControllerType.ControllerATAPI; storageDevice^.writable := false; //TODO atapi + size := atapi.get_device_size(device); + storageDevice^.maxSectorCount := size; + storageDevice^.sectorSize := 2048; //todo + + if (device.isMaster) then begin + storageDevice^.controllerId0 := 0; + end else begin + storageDevice^.controllerId0 := 1; + end; + + //read and print first sector + buffer := puint8(kalloc(2048)); + memset(uint32(buffer), 11, 2048); + atapi.read_pio28(device, 11, 1, puint16(buffer)); + + console.writestringln('[IDE] (load_device) First sector of ATAPI device: '); + for i:=0 to 16 do begin + console.writehexln(buffer[i]); + end; + + memset(uint32(buffer), 0, 2048); + + atapi.read_pio28(device, 5200, 1, puint16(buffer)); + + console.writestringln('[IDE] (load_device) First sector of ATAPI device: '); + for i:=0 to 16 do begin + console.writehexln(buffer[i]); + end; + + end else begin storageDevice^.controller := TControllerType.ControllerATA; storageDevice^.writable := true; @@ -292,30 +344,30 @@ begin exit; end; - //wrtie test, 1F2F1F2F repeated - buffer := puint8(kalloc(1024)); - memset(uint32(buffer), $02, 1024); + // //wrtie test, 1F2F1F2F repeated + // 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; + // 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, 10, 2, puint16(buffer)); + // //write to the first sector + // ata.write_pio28(device, 10, 2, puint16(buffer)); - //read the first sector - memset(uint32(buffer), 0, 512); - ata.read_pio28(device, 10, 1, puint16(buffer)); + // //read the first sector + // memset(uint32(buffer), 0, 512); + // ata.read_pio28(device, 10, 1, puint16(buffer)); - //check if the data is the same - for i:=0 to 10 do begin - console.writehexln(buffer[i]); - end; + // //check if the data is the same + // for i:=0 to 10 do begin + // console.writehexln(buffer[i]); + // end; end; //register the device diff --git a/src/driver/storage/atapi.pas b/src/driver/storage/atapi.pas index 34225b7d..cf45e278 100644 --- a/src/driver/storage/atapi.pas +++ b/src/driver/storage/atapi.pas @@ -24,11 +24,20 @@ var 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; + function get_device_size(device : TIDE_Device) : uint32; implementation uses - ide; + ide, ata; + +procedure outb(port : uint16; value : uint8); +begin + util.outb(port, value); + psleep(1); + // get_status(primaryDevices[0]); +end; + { Identify the device on the IDE bus @@ -46,6 +55,10 @@ begin select_device(device); no_interrupt(device.isPrimary); + outb(ATA_PRIMARY_BASE1, $04); + outb(ATA_SECONDARY_BASE1, $04); + sleep(1); + status := get_status(device); outb(device.base + ATA_REG_SECCOUNT, 0); @@ -81,16 +94,77 @@ begin identify_device := true; end; -function read_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; +function read_PIO28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; var - i : uint16; - ii : uint16; + i, j : uint16; status : TIDE_Status; ready : boolean; + packet : array[0..11] of uint8; begin + push_trace('read_PIO28()'); + if not device.isATAPI then begin + console.writestringln('[ATAPI] Device is not an ATAPI device!'); + read_PIO28 := false; + exit; + end; + + select_device(device); + no_interrupt(device.isPrimary); + + // Step 1: Send PACKET command + outb(device.base + ATA_REG_FEATURES, 0); // No special features + outb(device.base + ATA_REG_SECCOUNT, 0); // ATAPI requires this to be 0 + outb(device.base + ATA_REG_LBA0, (2048 shr 0) and $FF); // Byte size of transfer (2048 for CDs) + outb(device.base + ATA_REG_LBA1, (2048 shr 8) and $FF); + outb(device.base + ATA_REG_LBA2, 0); // Reserved + outb(device.base + ATA_REG_COMMAND, ATA_CMD_PACKET); + + // Step 2: Wait for DRQ=1 (drive wants a command packet) + ready := wait_for_device(device, true); + if not ready then begin + console.writestringln('[ATAPI] Timeout waiting for PACKET DRQ!'); + read_PIO28 := false; + exit; + end; + + // Step 3: Prepare 12-byte SCSI CDB (Read Sectors Command 0xA8) + packet[0] := $A8; // ATAPI READ (10) command + packet[1] := 0; // Reserved + packet[2] := (lba shr 24) and $FF; // LBA high byte + packet[3] := (lba shr 16) and $FF; + packet[4] := (lba shr 8) and $FF; + packet[5] := (lba shr 0) and $FF; + packet[6] := 0; // Reserved + packet[7] := count; // Number of sectors to read + packet[8] := 0; // Reserved + packet[9] := 0; // Control + + // Step 4: Send the command packet + for i := 0 to 5 do + outw(device.base + ATA_REG_DATA, (packet[i*2] or (packet[i*2+1] shl 8))); + + // Step 5: Wait for DRQ=1 (data ready) + ready := wait_for_device(device, true); + if not ready then begin + console.writestringln('[ATAPI] Timeout waiting for data DRQ!'); + read_PIO28 := false; + exit; + end; + + // Step 6: Read the data (count * 2048 bytes) + for i := 0 to (count * 1024) - 1 do begin + for j := 0 to 255 do begin + buffer[i * 256 + j] := inw(device.base + ATA_REG_DATA); + end; + end; + + // Success + read_PIO28 := true; + pop_trace(); end; + function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean; var i : uint16; @@ -98,7 +172,112 @@ var status : TIDE_Status; ready : boolean; begin - + write_pio28 := false; end; +function get_device_size(device: TIDE_Device): uint32; +var + i: uint8; + ready: boolean; + packet: puint16; // Will hold our 10-byte CDB (as 5 words) + response: puint16; // Will hold the 8-byte capacity response + xferCount: uint16; +begin + get_device_size := 0; + + // 1) Select the device (Master/Slave) - presumably your function + select_device(device); + + // 2) We set "no special features" for ATAPI + outb(device.base + ATA_REG_FEATURES, 0); + + // 3) Indicate how many bytes we expect from the drive. + // Usually we place "MaxByteCount" in LBA1:LBA2. + // We need at least 8 bytes for READ CAPACITY(10). + // We'll do 8 => low byte in LBA1, high byte in LBA2. + outb(device.base + ATA_REG_LBA1, $08); + outb(device.base + ATA_REG_LBA2, $00); + + // 4) Send the "PACKET" command (0xA0) to start an ATAPI packet transfer + outb(device.base + ATA_REG_COMMAND, ATA_CMD_PACKET); + + // 5) Build our 10-byte SCSI "READ CAPACITY(10)" command descriptor block (CDB) + // We'll store it in 5 words = 10 bytes + packet := puint16(kalloc(10)); // 5 * 2 = 10 bytes + memset(uint32(packet), 0, 10); + + // READ CAPACITY(10) = opcode 0x25 + // The rest can be 0 for a basic capacity read + // We'll store it as little-endian 16-bit words: + // packet[0] = 0x0025 means low byte=0x25 (opcode), high byte=0x00 + packet[0] := $0025; // cdb[0..1] + packet[1] := 0; // cdb[2..3] + packet[2] := 0; // cdb[4..5] + packet[3] := 0; // cdb[6..7] + packet[4] := 0; // cdb[8..9] + + // 6) Wait for drive to be ready to receive the CDB + ready := wait_for_device(device, false); + if not ready then + begin + console.writestringln('Device not ready to receive READ CAPACITY(10) CDB.'); + exit; + end; + + // 7) Write our 5 words (10 bytes) of CDB to the drive + for i := 0 to 4 do + begin + outw(device.base + ATA_REG_DATA, packet[i]); + psleep(1); // short delay + end; + // Free the CDB memory +// kfree(uint32(packet)); + + // 8) Wait for next phase (the data phase). The device should assert DRQ + // if it has data to send. We'll poll again. + ready := wait_for_device(device, false); + if not ready then + begin + console.writestringln('Drive not ready after sending the CDB.'); + exit; + end; + + // 9) The drive indicates how many bytes it’s about to send in LBA1:LBA2 + xferCount := (inb(device.base + ATA_REG_LBA2) shl 8) or inb(device.base + ATA_REG_LBA1); + if xferCount < 8 then + begin + console.writestringln('Drive is returning less than 8 bytes for capacity!'); + exit; + end; + + // 10) Allocate space for the 8-byte result + response := puint16(kalloc(8)); + memset(uint32(response), 0, 8); + + // We'll read 4 words = 8 bytes from the data register + for i := 0 to 3 do + begin + response[i] := inw(device.base + ATA_REG_DATA); + psleep(1); + ready := wait_for_device(device, false); + if not ready then + begin + console.writestringln('Device got stuck while reading capacity data!'); + exit; + end; + end; + + // 11) Now parse the returned 8 bytes: + // - first 4 bytes = last LBA + // - next 4 bytes = block size + console.writestring('Device sector count: '); + console.writeintln(puint32(response)[0]); // last LBA + console.writestring('Device sector size: '); + console.writeintln(puint32(response)[1]); // block size + + // Return the LBA as "size" (some drivers do lastLBA+1). + get_device_size := puint32(response)[1]; +end; + + end. \ No newline at end of file