atapi progress
This commit is contained in:
parent
920aca5bbf
commit
fd0de9f1d2
@ -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
|
||||
|
@ -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.
|
Loading…
x
Reference in New Issue
Block a user