ATA, (PATAPI dead), AHCI New Begginings
This commit is contained in:
parent
fd0de9f1d2
commit
0855abfd41
56
src/driver/storage/AHCI/AHCI.pas
Normal file
56
src/driver/storage/AHCI/AHCI.pas
Normal 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.
|
172
src/driver/storage/AHCI/AHCITypes.pas
Normal file
172
src/driver/storage/AHCI/AHCITypes.pas
Normal 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.
|
||||||
|
|
||||||
|
|
@ -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]);
|
||||||
|
@ -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 it’s about to send in LBA1:LBA2
|
// 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);
|
// 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.
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user