atapi progress
This commit is contained in:
parent
920aca5bbf
commit
fd0de9f1d2
@ -4,6 +4,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
ata,
|
ata,
|
||||||
|
atapi,
|
||||||
util,
|
util,
|
||||||
drivertypes,
|
drivertypes,
|
||||||
console,
|
console,
|
||||||
@ -243,10 +244,12 @@ var
|
|||||||
buffer : puint8;
|
buffer : puint8;
|
||||||
storageDevice : PStorage_device;
|
storageDevice : PStorage_device;
|
||||||
success : boolean;
|
success : boolean;
|
||||||
|
size : uint32;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
push_trace('ide.load_device()');
|
push_trace('ide.load_device()');
|
||||||
success := check_device_type(device);
|
success := check_device_type(device);
|
||||||
|
select_device(device);
|
||||||
|
|
||||||
if (is_device_present(device) and success) then begin
|
if (is_device_present(device) and success) then begin
|
||||||
console.writestringln('[IDE] (load_device) Device is present');
|
console.writestringln('[IDE] (load_device) Device is present');
|
||||||
@ -254,9 +257,28 @@ begin
|
|||||||
if (device.isATAPI) then begin
|
if (device.isATAPI) then begin
|
||||||
console.writestringln('[IDE] (load_device) Device is ATAPI');
|
console.writestringln('[IDE] (load_device) Device is ATAPI');
|
||||||
//todo load device info
|
//todo load device info
|
||||||
|
success := atapi.identify_device(device);
|
||||||
|
|
||||||
|
device.exists := true;
|
||||||
|
device.isATAPI := true;
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
console.writestringln('[IDE] (load_device) Device is ATA');
|
console.writestringln('[IDE] (load_device) Device is ATA');
|
||||||
success:= ata.identify_device(device);
|
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;
|
end;
|
||||||
|
|
||||||
if not success then begin
|
if not success then begin
|
||||||
@ -273,6 +295,36 @@ begin
|
|||||||
if (device.isATAPI) then begin
|
if (device.isATAPI) then begin
|
||||||
storageDevice^.controller := TControllerType.ControllerATAPI;
|
storageDevice^.controller := TControllerType.ControllerATAPI;
|
||||||
storageDevice^.writable := false; //TODO atapi
|
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
|
end else begin
|
||||||
storageDevice^.controller := TControllerType.ControllerATA;
|
storageDevice^.controller := TControllerType.ControllerATA;
|
||||||
storageDevice^.writable := true;
|
storageDevice^.writable := true;
|
||||||
@ -292,30 +344,30 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//wrtie test, 1F2F1F2F repeated
|
// //wrtie test, 1F2F1F2F repeated
|
||||||
buffer := puint8(kalloc(1024));
|
// buffer := puint8(kalloc(1024));
|
||||||
memset(uint32(buffer), $02, 1024);
|
// memset(uint32(buffer), $02, 1024);
|
||||||
|
|
||||||
uint8(buffer[0]) := $1F;
|
// uint8(buffer[0]) := $1F;
|
||||||
uint8(buffer[1]) := $2F;
|
// uint8(buffer[1]) := $2F;
|
||||||
uint8(buffer[2]) := $3F;
|
// uint8(buffer[2]) := $3F;
|
||||||
uint8(buffer[3]) := $4F;
|
// uint8(buffer[3]) := $4F;
|
||||||
uint8(buffer[4]) := $5F;
|
// uint8(buffer[4]) := $5F;
|
||||||
uint8(buffer[5]) := $6F;
|
// uint8(buffer[5]) := $6F;
|
||||||
uint8(buffer[6]) := $7F;
|
// uint8(buffer[6]) := $7F;
|
||||||
uint8(buffer[7]) := $8F;
|
// uint8(buffer[7]) := $8F;
|
||||||
|
|
||||||
//write to the first sector
|
// //write to the first sector
|
||||||
ata.write_pio28(device, 10, 2, puint16(buffer));
|
// ata.write_pio28(device, 10, 2, puint16(buffer));
|
||||||
|
|
||||||
//read the first sector
|
// //read the first sector
|
||||||
memset(uint32(buffer), 0, 512);
|
// memset(uint32(buffer), 0, 512);
|
||||||
ata.read_pio28(device, 10, 1, puint16(buffer));
|
// ata.read_pio28(device, 10, 1, puint16(buffer));
|
||||||
|
|
||||||
//check if the data is the same
|
// //check if the data is the same
|
||||||
for i:=0 to 10 do begin
|
// for i:=0 to 10 do begin
|
||||||
console.writehexln(buffer[i]);
|
// console.writehexln(buffer[i]);
|
||||||
end;
|
// end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//register the device
|
//register the device
|
||||||
|
@ -24,11 +24,20 @@ var
|
|||||||
function identify_device(var device : TIDE_Device) : Boolean;
|
function identify_device(var device : TIDE_Device) : Boolean;
|
||||||
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;
|
||||||
function write_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
|
implementation
|
||||||
uses
|
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
|
Identify the device on the IDE bus
|
||||||
@ -46,6 +55,10 @@ begin
|
|||||||
select_device(device);
|
select_device(device);
|
||||||
no_interrupt(device.isPrimary);
|
no_interrupt(device.isPrimary);
|
||||||
|
|
||||||
|
outb(ATA_PRIMARY_BASE1, $04);
|
||||||
|
outb(ATA_SECONDARY_BASE1, $04);
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
status := get_status(device);
|
status := get_status(device);
|
||||||
|
|
||||||
outb(device.base + ATA_REG_SECCOUNT, 0);
|
outb(device.base + ATA_REG_SECCOUNT, 0);
|
||||||
@ -81,16 +94,77 @@ begin
|
|||||||
identify_device := true;
|
identify_device := true;
|
||||||
end;
|
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
|
var
|
||||||
i : uint16;
|
i, j : uint16;
|
||||||
ii : uint16;
|
|
||||||
status : TIDE_Status;
|
status : TIDE_Status;
|
||||||
ready : boolean;
|
ready : boolean;
|
||||||
|
packet : array[0..11] of uint8;
|
||||||
begin
|
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;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
function write_pio28(device : TIDE_Device; lba : uint32; count : uint8; buffer : puint16) : boolean;
|
||||||
var
|
var
|
||||||
i : uint16;
|
i : uint16;
|
||||||
@ -98,7 +172,112 @@ var
|
|||||||
status : TIDE_Status;
|
status : TIDE_Status;
|
||||||
ready : boolean;
|
ready : boolean;
|
||||||
begin
|
begin
|
||||||
|
write_pio28 := false;
|
||||||
end;
|
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.
|
end.
|
Loading…
x
Reference in New Issue
Block a user