ATA, (PATAPI dead), AHCI New Begginings

This commit is contained in:
Aaron Hance 2025-03-14 19:49:56 +00:00
parent fd0de9f1d2
commit 0855abfd41
6 changed files with 475 additions and 40 deletions

View File

@ -0,0 +1,56 @@
unit AHCI;
interface
uses
util,
PCI,
drivertypes,
drivermanagement,
lmemorymanager,
console,
vmemorymanager,
AHCITypes;
var
ahciControllers : array[0..255] of pointer;
ahciControllerCount : uint32;
hba : array[0..255] of THBA_Memory;
procedure init();
procedure load();
implementation
procedure init();
var
devID : TDeviceIdentifier;
begin
console.writestringln('AHCI: Registering driver');
devID.bus:= biPCI;
devID.id0:= idANY;
devID.id1:= $00000001;
devID.id2:= $00000006;
devID.id3:= $00000001;
devID.id4:= idANY;
devID.ex:= nil;
drivermanagement.register_driver('ATA/PI AHCI Driver', @devID, @load);
end;
procedure load(ptr : void);
begin
// console.writestringln('AHCI: initilizing a new controller');
// ahciControllers[ahciControllerCount] := ptr;
// hba[ahciControllerCount] := PPCI_Device(ptr)^.address5;
// new_page_at_address(hba[ahciControllerCount]);
// //here would be any controller setup needed
// check_ports(ahciControllerCount);
// ahciControllerCount += 1;
// exit(true);
end;
end.

View File

@ -0,0 +1,172 @@
unit AHCITypes;
interface
uses
util,
PCI,
drivertypes,
drivermanagement,
lmemorymanager,
console,
vmemorymanager;
const
type
{
AHCI Host Bus Adapter (HBA) Memory-Mapped Register Interface
This structure is used to access the AHCI HBA's memory-mapped registers.
The AHCI HBA's memory-mapped registers are used to configure the HBA and
to issue commands to the SATA devices connected to the HBA.
The AHCI HBA's memory-mapped registers are accessed by reading and writing
to the HBA's memory-mapped I/O space. The HBA's memory-mapped I/O space is
typically mapped to a region of physical memory by the system's BIOS or
UEFI firmware. The HBA's memory-mapped I/O space is typically mapped to a
region of physical memory that is accessible to the system's CPU(s) and
other devices.
}
THBA_Port = bitpacked record
cmdl_basel: uint32; // Command List Base Address Lower 32-bits
cmdl_baseu: uint32; // Command List Base Address Upper 32-bits
fis_basel: uint32; // FIS Base Address Lower 32-bits
fis_baseu: uint32; // FIS Base Address Upper 32-bits
int_status: uint32; // Interrupt Status
int_enable: uint32; // Interrupt Enable
cmd: uint32; // Command and Status
rsv0: uint32; // Reserved
tfd: uint32; // Task File Data
signature: uint32; // Signature
sata_stat: uint32; // SATA Status (SCR0:SStatus)
sata_ctrl: uint32; // SATA Control (SCR2:SControl)
sata_error: uint32; // SATA Error (SCR1:SError)
sata_active: uint32; // SATA Active
cmd_issue: uint32; // Command Issue
sata_noti: uint32; // SATA Notification
fis_switch_ctrl: uint32;// FIS-based Switch Control
rsv1: array[0..10] of uint32;
end;
{
AHCI Host Bus Adapter (HBA) Memory-Mapped Register Interface
This structure is used to access the AHCI HBA's memory-mapped registers.
The AHCI HBA's memory-mapped registers are used to configure the HBA and
to issue commands to the SATA devices connected to the HBA.
}
THBA_Memory = bitpacked record
capabilites: uint32; // Host Capabilities
global_ctrl: uint32; // Global Host Control
int_status: uint32; // Interrupt Status
ports_implemented: uint32; // Ports Implemented
version: uint32; // Version
ccc_control: uint32; // Command Completion Coalescing Control
ccc_ports: uint32; // Command Completion Coalescing Ports
em_location: uint32; // Enclosure Management Location
em_control: uint32; // Enclosure Management Control
capabilites2: uint32; // Host Capabilities Extended
bohc: uint32; // BIOS/OS Handoff Control and Status
rsv0: array[0..0x210] of boolean;
ports: array[0..31] of THBA_Port;
end;
{
AHCI Host Bus Adapter (HBA) FIS (Frame Information Structure) Interface
This structure is used to access the AHCI HBA's FIS (Frame Information Structure)
memory-mapped registers. The AHCI HBA's FIS memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA_FIS = bitpacked record
dsfis: array[0..0x1F] of uint32; // DMA Setup FIS
rsv0: array[0..0x1F] of uint32;
psfis: array[0..0x1F] of uint32; // PIO Setup FIS
rsv1: array[0..0x1F] of uint32;
rfis: array[0..0x1F] of uint32; // D2H Register FIS
rsv2: array[0..0x1F] of uint32;
sdbfis: array[0..0xF] of uint32; // Set Device Bits FIS
ufis: array[0..0x1F] of uint32; // Unknown FIS
rsv3: array[0..0x67] of uint32;
end;
{
AHCI Host Bus Adapter (HBA) Command Header Interface
This structure is used to access the AHCI HBA's Command Header memory-mapped
registers. The AHCI HBA's Command Header memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA_CMD_HEADER = bitpacked record
cmd_fis_length: uint8; // Command FIS Length
atapi: uint8; // ATAPI
write: uint8; // Write
prefetchable: uint8; // Prefetchable
reset: uint8; // Reset
bist: uint8; // BIST
clear_busy: uint8; // Clear Busy
reserved0: uint8; // Reserved
prdtl: uint16; // Physical Region Descriptor Table Length
prdbc: uint32; // Physical Region Descriptor Byte Count
cmd_table_base: uint32; // Command Table Base Address
cmd_table_baseu: uint32; // Command Table Base Address Upper 32-bits
rsv0: array[0..4] of uint32;
end;
{
AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped
registers. The AHCI HBA's Command Table memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA_CMD_TABLE = bitpacked record
cmd_fis: THBA_FIS; // Command FIS
acmd: array[0..0x1F] of uint8; // ATAPI Command
rsv0: array[0..0x30] of uint8;
end;
{
AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped
registers. The AHCI HBA's Command Table memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA_PRD = bitpacked record
dba: uint32; // Data Base Address
dbau: uint32; // Data Base Address Upper 32-bits
rsv0: uint32; // Reserved
dbc: uint32; // Data Byte Count
rsv1: uint32; // Reserved
end;
{
AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped
registers. The AHCI HBA's Command Table memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA_CMD = bitpacked record
header: THBA_CMD_HEADER; // Command Header
table: THBA_CMD_TABLE; // Command Table
prd: array[0..0x7] of THBA_PRD; // Physical Region Descriptor Table
end;
{
AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped
registers. The AHCI HBA's Command Table memory-mapped registers are used to
configure the HBA and to issue commands to the SATA devices connected to the HBA.
}
THBA = bitpacked record
memory: THBA_Memory; // HBA Memory
cmd: array[0..0x7FF] of THBA_CMD; // Command List
end;
PHBA = ^THBA;
implementation
end.

View File

@ -17,28 +17,29 @@ uses
tracer, tracer,
drivemanager, drivemanager,
storagetypes, storagetypes,
idetypes; idetypes,
isrmanager;
var var
primaryDevices: array[0..1] of TIDE_Device = ( primaryDevices: array[0..1] of TIDE_Device = (
(exists: false; isPrimary: true; isMaster: true; isATAPI: false; (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); status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
base: ATA_PRIMARY_BASE; info: nil), base: ATA_PRIMARY_BASE; blockSize: 0; info: nil),
(exists: false; isPrimary: true; isMaster: false; isATAPI: false; (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); status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
base: ATA_PRIMARY_BASE; info: nil) base: ATA_PRIMARY_BASE; blockSize: 0; info: nil)
); );
secondaryDevices: array[0..1] of TIDE_Device = ( secondaryDevices: array[0..1] of TIDE_Device = (
(exists: false; isPrimary: false; isMaster: true; isATAPI: false; (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); status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
base: ATA_SECONDARY_BASE; info: nil), base: ATA_SECONDARY_BASE; blockSize: 0; info: nil),
(exists: false; isPrimary: false; isMaster: false; isATAPI: false; (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); status: (Busy: false; Ready: false; Fault: false; Seek: false; DRQ: false; CORR: false; IDDEX: false; ERROR: false);
base: ATA_SECONDARY_BASE; info: nil) base: ATA_SECONDARY_BASE; blockSize: 0; info: nil)
); );
@ -47,6 +48,8 @@ var
function get_status(var device : TIDE_Device) : TIDE_Status; function get_status(var device : TIDE_Device) : TIDE_Status;
function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean; function wait_for_device(device : TIDE_Device; ioop : boolean) : boolean;
procedure no_interrupt(isPrimary : boolean); procedure no_interrupt(isPrimary : boolean);
procedure enable_interrupt(isPrimary : boolean);
procedure reset_device(device : TIDE_Device);
procedure select_device(device : TIDE_Device); procedure select_device(device : TIDE_Device);
implementation implementation
@ -64,6 +67,51 @@ begin
end; end;
end; end;
procedure enable_interrupt(isPrimary : boolean);
var
reg : uint8;
begin
if isPrimary then begin
reg := inb(ATA_INTERRUPT_PRIMARY);
reg := reg and not (1 shl 1);
outb(ATA_INTERRUPT_PRIMARY, reg);
end else begin
reg := inb(ATA_INTERRUPT_SECONDARY);
reg := reg and not (1 shl 1);
outb(ATA_INTERRUPT_SECONDARY, reg);
end;
end;
//soft reset
procedure reset_device(device : TIDE_Device);
var
reg : uint8;
begin
if device.isPrimary then begin
reg := inb(ATA_INTERRUPT_PRIMARY);
reg := reg and (1 shl 2);
outb(ATA_INTERRUPT_PRIMARY, reg);
end else begin
reg := inb(ATA_INTERRUPT_SECONDARY);
reg := reg and (1 shl 2);
outb(ATA_INTERRUPT_SECONDARY, reg);
end;
sleep(20);
if device.isPrimary then begin
reg := inb(ATA_INTERRUPT_PRIMARY);
reg := reg and not (1 shl 2);
outb(ATA_INTERRUPT_PRIMARY, reg);
end else begin
reg := inb(ATA_INTERRUPT_SECONDARY);
reg := reg and not (1 shl 2);
outb(ATA_INTERRUPT_SECONDARY, reg);
end;
end;
{ {
Wait for the device to be ready on the IDE bus Wait for the device to be ready on the IDE bus
@ -105,6 +153,7 @@ end;
procedure select_device(device : TIDE_Device); procedure select_device(device : TIDE_Device);
var var
dev : uint8; dev : uint8;
reg : uint8;
begin begin
push_trace('ide.select_device()'); push_trace('ide.select_device()');
@ -114,7 +163,10 @@ begin
dev := ATA_DEVICE_MASTER; dev := ATA_DEVICE_MASTER;
end; end;
outb(device.base + ATA_REG_HDDEVSEL, dev); reg := inb(device.base + ATA_REG_HDDEVSEL);
reg := (reg and $F0) or dev;
outb(device.base + ATA_REG_HDDEVSEL, reg);
pop_trace(); pop_trace();
end; end;
@ -201,6 +253,7 @@ Write 0x00 back to Control Register to complete reset.
sleep(1); sleep(1);
// outb(ATA_PRIMARY_BASE1, $00); // outb(ATA_PRIMARY_BASE1, $00);
// outb(ATA_SECONDARY_BASE1, $00); // outb(ATA_SECONDARY_BASE1, $00);
select_device(device);
sleep(1); sleep(1);
@ -246,10 +299,8 @@ var
success : boolean; success : boolean;
size : uint32; 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');
@ -297,7 +348,7 @@ begin
storageDevice^.writable := false; //TODO atapi storageDevice^.writable := false; //TODO atapi
size := atapi.get_device_size(device); size := atapi.get_device_size(device);
storageDevice^.maxSectorCount := size; storageDevice^.maxSectorCount := size;
storageDevice^.sectorSize := 2048; //todo storageDevice^.sectorSize := device.blockSize;
if (device.isMaster) then begin if (device.isMaster) then begin
storageDevice^.controllerId0 := 0; storageDevice^.controllerId0 := 0;
@ -390,7 +441,11 @@ var
begin begin
push_trace('ide.load()'); push_trace('ide.load()');
console.writestringln('[IDE] (load) Loading IDE Devices'); console.writestringln('[IDE] (load) Loading IDE Devices');
console.redrawWindows();
registerISR(14, @atapi.ide_irq);
registerISR(15, @atapi.ide_irq);
console.writestringln('[IDE] (load) Loading IDE Devices 2');
console.redrawWindows();
pciDevice := PPCI_Device(ptr); pciDevice := PPCI_Device(ptr);
load_device(primaryDevices[0]); load_device(primaryDevices[0]);

View File

@ -24,13 +24,48 @@ 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; function get_device_size(var device : TIDE_Device) : uint32;
procedure ide_irq();
implementation implementation
uses uses
ide, ata; ide, ata;
procedure ide_irq();
begin
console.writestringln('IDE IRQ Handler');
console.redrawWindows();
end;
//print status of the device, alt status register
procedure print_status(device : TIDE_Device);
begin
get_status(device);
console.writestring('Status: ');
// console.writeintln(uint32(device.status));
console.writestring('Busy: ');
console.writeintln(uint32(device.status.Busy));
console.writestring('Ready: ');
console.writeintln(uint32(device.status.Ready));
console.writestring('Fault: ');
console.writeintln(uint32(device.status.Fault));
console.writestring('Seek: ');
console.writeintln(uint32(device.status.Seek));
console.writestring('DRQ: ');
console.writeintln(uint32(device.status.DRQ));
console.writestring('CORR: ');
console.writeintln(uint32(device.status.CORR));
console.writestring('IDDEX: ');
console.writeintln(uint32(device.status.IDDEX));
console.writestring('ERROR: ');
console.writeintln(uint32(device.status.ERROR));
end;
procedure outb(port : uint16; value : uint8); procedure outb(port : uint16; value : uint8);
begin begin
util.outb(port, value); util.outb(port, value);
@ -38,7 +73,6 @@ begin
// get_status(primaryDevices[0]); // get_status(primaryDevices[0]);
end; end;
{ {
Identify the device on the IDE bus Identify the device on the IDE bus
@ -55,9 +89,9 @@ begin
select_device(device); select_device(device);
no_interrupt(device.isPrimary); no_interrupt(device.isPrimary);
outb(ATA_PRIMARY_BASE1, $04); // outb(ATA_PRIMARY_BASE1, $04);
outb(ATA_SECONDARY_BASE1, $04); // outb(ATA_SECONDARY_BASE1, $04);
sleep(1); // sleep(1);
status := get_status(device); status := get_status(device);
@ -85,9 +119,79 @@ begin
exit(false); exit(false);
end; end;
console.writestringln('ATAPI Device identified: ');
for i:=0 to 255 do begin for i:=0 to 255 do begin
buffer[i] := inw(device.base + ATA_REG_DATA); buffer[i] := inw(device.base + ATA_REG_DATA);
console.writestring('[');
console.writehexpair(buffer[i]);
console.writestring('] ');
if (i mod 4) = 0 then begin
console.writestringln('');
end; end;
end;
//bits 14 and 15 of word 0
{
00h
01h
Direct-access device
Sequential-access device
02h
03h
Printer device
Processor device
04h
05h
Write-once device
CD-ROM device
06h
07h
Scanner device
Optical memory device
08h
09h
Medium changer device
Communications device
0A-0Bh
0Ch
Reserved for ACS IT8 (Graphic arts pre-press devices)
Array controller device
0Dh
0Eh
Enclosure services device
Reduced block command devices
0Fh
10-1Eh
Optical card reader/writer device
Reserved
1Fh
Unknown or no device type}
//print device type
console.writestring('Device Type: ');
case (buffer[0] shr 8) and $3 of
0: console.writestringln('Direct-access device');
1: console.writestringln('Sequential-access device');
2: console.writestringln('Printer device');
3: console.writestringln('Processor device');
4: console.writestringln('Write-once device');
5: console.writestringln('CD-ROM device');
6: console.writestringln('Scanner device');
7: console.writestringln('Optical memory device');
8: console.writestringln('Medium changer device');
9: console.writestringln('Communications device');
10: console.writestringln('Reserved for ACS IT8 (Graphic arts pre-press devices)');
11: console.writestringln('Array controller device');
12: console.writestringln('Reserved');
13: console.writestringln('Enclosure services device');
14: console.writestringln('Reduced block command devices');
15: console.writestringln('Unknown or no device type');
end;
outb(ATA_PRIMARY_BASE1, $04);
outb(ATA_SECONDARY_BASE1, $04);
sleep(10);
device.info := @buffer; device.info := @buffer;
@ -121,7 +225,7 @@ begin
outb(device.base + ATA_REG_COMMAND, ATA_CMD_PACKET); outb(device.base + ATA_REG_COMMAND, ATA_CMD_PACKET);
// Step 2: Wait for DRQ=1 (drive wants a command packet) // Step 2: Wait for DRQ=1 (drive wants a command packet)
ready := wait_for_device(device, true); ready := wait_for_device(device, false);
if not ready then begin if not ready then begin
console.writestringln('[ATAPI] Timeout waiting for PACKET DRQ!'); console.writestringln('[ATAPI] Timeout waiting for PACKET DRQ!');
read_PIO28 := false; read_PIO28 := false;
@ -139,22 +243,24 @@ begin
packet[7] := count; // Number of sectors to read packet[7] := count; // Number of sectors to read
packet[8] := 0; // Reserved packet[8] := 0; // Reserved
packet[9] := 0; // Control packet[9] := 0; // Control
packet[10] := 0; // Reserved
packet[11] := 0; // Reserved
// Step 4: Send the command packet // Step 4: Send the command packet
for i := 0 to 5 do for i := 0 to 5 do
outw(device.base + ATA_REG_DATA, (packet[i*2] or (packet[i*2+1] shl 8))); outw(device.base + ATA_REG_DATA, (packet[i*2] or (packet[i*2+1] shl 8)));
// Step 5: Wait for DRQ=1 (data ready) // Step 6: Read the data (count * 2048 bytes)
ready := wait_for_device(device, true); for i := 0 to (count) - 1 do begin
for j := 0 to 1023 do begin
ready := wait_for_device(device, false);
if not ready then begin if not ready then begin
console.writestringln('[ATAPI] Timeout waiting for data DRQ!'); console.writestringln('[ATAPI] Timeout waiting for data DRQ!');
read_PIO28 := false; read_PIO28 := false;
exit; exit;
end; 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); buffer[i * 256 + j] := inw(device.base + ATA_REG_DATA);
end; end;
end; end;
@ -175,18 +281,21 @@ begin
write_pio28 := false; write_pio28 := false;
end; end;
function get_device_size(device: TIDE_Device): uint32; function get_device_size(var device: TIDE_Device): uint32;
var var
i: uint8; i: uint8;
ready: boolean; ready: boolean;
packet: puint16; // Will hold our 10-byte CDB (as 5 words) packet: puint16; // Will hold our 10-byte CDB (as 5 words)
response: puint16; // Will hold the 8-byte capacity response response: puint16; // Will hold the 8-byte capacity response
xferCount: uint16; xferCount: uint16;
temp: uInt32;
data: uint16;
begin begin
get_device_size := 0; get_device_size := 0;
// 1) Select the device (Master/Slave) - presumably your function // 1) Select the device (Master/Slave) - presumably your function
select_device(device); select_device(device);
enable_interrupt(device.isPrimary);
// 2) We set "no special features" for ATAPI // 2) We set "no special features" for ATAPI
outb(device.base + ATA_REG_FEATURES, 0); outb(device.base + ATA_REG_FEATURES, 0);
@ -203,8 +312,8 @@ begin
// 5) Build our 10-byte SCSI "READ CAPACITY(10)" command descriptor block (CDB) // 5) Build our 10-byte SCSI "READ CAPACITY(10)" command descriptor block (CDB)
// We'll store it in 5 words = 10 bytes // We'll store it in 5 words = 10 bytes
packet := puint16(kalloc(10)); // 5 * 2 = 10 bytes packet := puint16(kalloc(12)); // 5 * 2 = 10 bytes
memset(uint32(packet), 0, 10); memset(uint32(packet), 0, 12);
// READ CAPACITY(10) = opcode 0x25 // READ CAPACITY(10) = opcode 0x25
// The rest can be 0 for a basic capacity read // The rest can be 0 for a basic capacity read
@ -215,6 +324,7 @@ begin
packet[2] := 0; // cdb[4..5] packet[2] := 0; // cdb[4..5]
packet[3] := 0; // cdb[6..7] packet[3] := 0; // cdb[6..7]
packet[4] := 0; // cdb[8..9] packet[4] := 0; // cdb[8..9]
packet[5] := 0; // cdb[10..11]
// 6) Wait for drive to be ready to receive the CDB // 6) Wait for drive to be ready to receive the CDB
ready := wait_for_device(device, false); ready := wait_for_device(device, false);
@ -225,7 +335,7 @@ begin
end; end;
// 7) Write our 5 words (10 bytes) of CDB to the drive // 7) Write our 5 words (10 bytes) of CDB to the drive
for i := 0 to 4 do for i := 0 to 5 do
begin begin
outw(device.base + ATA_REG_DATA, packet[i]); outw(device.base + ATA_REG_DATA, packet[i]);
psleep(1); // short delay psleep(1); // short delay
@ -236,6 +346,7 @@ begin
// 8) Wait for next phase (the data phase). The device should assert DRQ // 8) Wait for next phase (the data phase). The device should assert DRQ
// if it has data to send. We'll poll again. // if it has data to send. We'll poll again.
ready := wait_for_device(device, false); ready := wait_for_device(device, false);
psleep(1);
if not ready then if not ready then
begin begin
console.writestringln('Drive not ready after sending the CDB.'); console.writestringln('Drive not ready after sending the CDB.');
@ -243,12 +354,12 @@ begin
end; end;
// 9) The drive indicates how many bytes its about to send in LBA1:LBA2 // 9) The drive indicates how many bytes its about to send in LBA1:LBA2
xferCount := (inb(device.base + ATA_REG_LBA2) shl 8) or inb(device.base + ATA_REG_LBA1); // xferCount := (inb(device.base + ATA_REG_LBA2) shl 8) or inb(device.base + ATA_REG_LBA1);
if xferCount < 8 then // if xferCount < 8 then
begin // begin
console.writestringln('Drive is returning less than 8 bytes for capacity!'); // console.writestringln('Drive is returning less than 8 bytes for capacity!');
exit; // exit;
end; // end;
// 10) Allocate space for the 8-byte result // 10) Allocate space for the 8-byte result
response := puint16(kalloc(8)); response := puint16(kalloc(8));
@ -257,14 +368,35 @@ begin
// We'll read 4 words = 8 bytes from the data register // We'll read 4 words = 8 bytes from the data register
for i := 0 to 3 do for i := 0 to 3 do
begin begin
response[i] := inw(device.base + ATA_REG_DATA);
psleep(1);
ready := wait_for_device(device, false); ready := wait_for_device(device, false);
if not ready then if not ready then
begin begin
console.writestringln('Device got stuck while reading capacity data!'); console.writestringln('Device got stuck while reading capacity data!');
exit; exit;
end; end;
psleep(3);
data := inw(device.base + ATA_REG_DATA);
response[i] := data;
psleep(1);
end;
// //fix the order of the bytes of each number
// endiness of device sector count
temp := puint32(response)[0];
puint32(response)[0] := 0;
for i := 0 to 31 do begin
puint32(response)[0] := puint32(response)[0] or ((temp shr i) and 1) shl (31 - i);
end;
//endiness of device sector size
temp := puint32(response)[1];
puint32(response)[1] := 0;
for i := 0 to 31 do begin
puint32(response)[1] := puint32(response)[1] or ((temp shr i) and 1) shl (31 - i);
end; end;
// 11) Now parse the returned 8 bytes: // 11) Now parse the returned 8 bytes:
@ -272,12 +404,22 @@ begin
// - next 4 bytes = block size // - next 4 bytes = block size
console.writestring('Device sector count: '); console.writestring('Device sector count: ');
console.writeintln(puint32(response)[0]); // last LBA console.writeintln(puint32(response)[0]); // last LBA
console.writebin32ln(puint32(response)[0]);
console.writestring('Device sector size: '); console.writestring('Device sector size: ');
console.writeintln(puint32(response)[1]); // block size console.writeintln(puint32(response)[1] ); // block size
console.writebin32ln(puint32(response)[1]);
device.blockSize := puint32(response)[1];
console.writestringln('Device size: ');
console.writeintln(puint32(response)[0] * (puint32(response)[1]) );
// Return the LBA as "size" (some drivers do lastLBA+1). // Return the LBA as "size" (some drivers do lastLBA+1).
get_device_size := puint32(response)[1]; get_device_size := puint32(response)[0];
end; end;
end. end.

View File

@ -131,6 +131,7 @@ type
isATAPI : boolean; isATAPI : boolean;
status : TIDE_Status; status : TIDE_Status;
base : uint16; base : uint16;
blockSize : uint32;
info : PIdentResponse; info : PIdentResponse;
end; end;

View File

@ -33,6 +33,8 @@ procedure init;
procedure registerISR(INT_N : uint8; callback : TISRHook); procedure registerISR(INT_N : uint8; callback : TISRHook);
implementation implementation
uses
console;
var var
Hooks : TISRHookArray; Hooks : TISRHookArray;
@ -56,6 +58,13 @@ var
i : uint8; i : uint8;
begin begin
// if int_n <> $20 then begin
// console.writestring('ISR: ');
// console.writehexpair(Int_N);
// console.writestringln(' called');
// end;
for i:=0 to MAX_HOOKS do begin for i:=0 to MAX_HOOKS do begin
if Hooks[INT_N][i] <> nil then Hooks[INT_N][i](); if Hooks[INT_N][i] <> nil then Hooks[INT_N][i]();
end; end;