starting to work
This commit is contained in:
parent
f04f8aa411
commit
05eab23956
@ -461,9 +461,11 @@ begin
|
|||||||
cmd := inl(PCI_CONFIG_DATA_PORT);
|
cmd := inl(PCI_CONFIG_DATA_PORT);
|
||||||
cmd := cmd or PCI_COMMAND_MEM_SPACE;
|
cmd := cmd or PCI_COMMAND_MEM_SPACE;
|
||||||
cmd := cmd or PCI_COMMAND_BUS_MASTER;
|
cmd := cmd or PCI_COMMAND_BUS_MASTER;
|
||||||
|
cmd := cmd or (3 shl 1);
|
||||||
|
|
||||||
//enable interrupts, remove disable interrupt bit
|
//enable interrupts, remove disable interrupt bit
|
||||||
cmd := cmd and not PCI_COMMAND_INT_DISABLE;
|
cmd := cmd and not PCI_COMMAND_INT_DISABLE;
|
||||||
|
cmd := cmd and not (1 shl 9);
|
||||||
|
|
||||||
outl(PCI_CONFIG_ADDRESS_PORT, addr);
|
outl(PCI_CONFIG_ADDRESS_PORT, addr);
|
||||||
outl(PCI_CONFIG_DATA_PORT, cmd);
|
outl(PCI_CONFIG_DATA_PORT, cmd);
|
||||||
|
@ -42,7 +42,7 @@ var
|
|||||||
procedure init();
|
procedure init();
|
||||||
function load(ptr : void) : boolean;
|
function load(ptr : void) : boolean;
|
||||||
procedure check_ports(controller : PAHCI_Controller);
|
procedure check_ports(controller : PAHCI_Controller);
|
||||||
procedure identify_device(controller : PAHCI_Controller; port : uint32);
|
procedure identify_device(controller : PAHCI_Controller; portIndex : uint32);
|
||||||
procedure ahci_isr();
|
procedure ahci_isr();
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -65,18 +65,49 @@ end;
|
|||||||
|
|
||||||
procedure stop_port(port : PHBA_Port);
|
procedure stop_port(port : PHBA_Port);
|
||||||
begin
|
begin
|
||||||
port^.cmd := port^.cmd and not $1; ///maybe also bit 4
|
port^.cmd := port^.cmd and not $1;
|
||||||
while (port^.cmd and $1) = 1 do begin
|
port^.cmd := port^.cmd and not $100;
|
||||||
|
while ((port^.cmd and $4000) or (port^.cmd and $8000)) <> 0 do begin
|
||||||
//wait for the port to stop
|
//wait for the port to stop
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure start_port(port : PHBA_Port);
|
procedure start_port(port : PHBA_Port);
|
||||||
begin
|
begin
|
||||||
port^.cmd := port^.cmd or $1; ///maybe also bit 4
|
|
||||||
while (port^.cmd and $1) = 0 do begin
|
while (port^.cmd and $8000) <> 0 do begin
|
||||||
//wait for the port to start
|
//wait for port to not be busy
|
||||||
end;
|
end;
|
||||||
|
port^.cmd := port^.cmd or $100;
|
||||||
|
port^.cmd := port^.cmd or $1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure reset_port(port : PHBA_Port);
|
||||||
|
var
|
||||||
|
ssts, serr, timeout : uint32;
|
||||||
|
begin
|
||||||
|
console.writestringln('AHCI: Performing a full port reset.');
|
||||||
|
|
||||||
|
port^.cmd := port^.cmd and not $1;
|
||||||
|
|
||||||
|
// Wait until CR (bit 15) is cleared.
|
||||||
|
timeout := 0;
|
||||||
|
while (port^.cmd and $8000) <> 0 do begin
|
||||||
|
timeout := timeout + 1;
|
||||||
|
if timeout > 1000000 then begin
|
||||||
|
console.writestringln('AHCI: Port reset timeout.');
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
port^.sata_ctrl := port^.sata_ctrl or $FFFF0000;
|
||||||
|
|
||||||
|
while (port^.sata_status and $F) <> 3 do begin
|
||||||
|
//wait for the port to be ready
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Clear the SERR register by writing 1s to it.
|
||||||
|
port^.sata_error := $FFFFFFFF;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -98,13 +129,22 @@ begin
|
|||||||
console.writehexln(controller^.mio^.ports_implimented);
|
console.writehexln(controller^.mio^.ports_implimented);
|
||||||
|
|
||||||
for i:=0 to 31 do begin
|
for i:=0 to 31 do begin
|
||||||
if (controller^.mio^.ports_implimented shr i) = 1 then begin
|
port := @controller^.mio^.ports[i];
|
||||||
|
console.writehex(port^.signature);
|
||||||
|
console.writestring(' ');
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to 31 do begin
|
||||||
|
if ((controller^.mio^.ports_implimented shr i) and 1) = 1 then begin
|
||||||
port := @controller^.mio^.ports[i];
|
port := @controller^.mio^.ports[i];
|
||||||
console.writestring('AHCI: Port ');
|
console.writestring('AHCI: Port ');
|
||||||
console.writeint(i);
|
console.writeint(i);
|
||||||
console.writestring(' implemented on controller ');
|
console.writestring(' implemented on controller ');
|
||||||
console.writehexln(uint32(controller^.pci_device^.address5));
|
console.writehexln(uint32(controller^.pci_device^.address5));
|
||||||
|
|
||||||
|
device := PAHCI_Device(DL_Add(controller^.devices));
|
||||||
|
device^.port := port;
|
||||||
|
|
||||||
//check if the port is active TODO
|
//check if the port is active TODO
|
||||||
// if ((port^.sata_status shr 8) <> 1) and ((port^.sata_status and $0F) <> 3) then begin
|
// if ((port^.sata_status shr 8) <> 1) and ((port^.sata_status and $0F) <> 3) then begin
|
||||||
// continue; wrong
|
// continue; wrong
|
||||||
@ -135,26 +175,28 @@ begin
|
|||||||
|
|
||||||
//NEEED TO STOP the port before doing anything
|
//NEEED TO STOP the port before doing anything
|
||||||
stop_port(port);
|
stop_port(port);
|
||||||
|
console.writestringln('AHCI: Port stopped');
|
||||||
device := PAHCI_Device(DL_Add(controller^.devices));
|
|
||||||
device^.port := port;
|
|
||||||
|
|
||||||
//allocate memory for the command list and ensure it is aligned to 1024 bytes
|
//allocate memory for the command list and ensure it is aligned to 1024 bytes
|
||||||
cmd_list_base := kalloc(sizeof(THBA_CMD_HEADER) * 64);
|
cmd_list_base := kalloc(sizeof(THBA_CMD_HEADER) * 64);
|
||||||
cmd_list_base := puint32((uint32(cmd_list_base) + 1023) and $FFFFFC00);
|
cmd_list_base := puint32((uint32(cmd_list_base) + 1023) and $FFFFFC00);
|
||||||
|
memset(uint32(cmd_list_base), 0, sizeof(THBA_CMD_HEADER) * 32);
|
||||||
//allocate memory for the FIS and ensure it is aligned to 256 bytes
|
|
||||||
fis_base := kalloc(sizeof(THBA_FIS) * 8);
|
|
||||||
fis_base := puint32((uint32(fis_base) + 255) and $FFFFFF00);
|
|
||||||
|
|
||||||
//set the command list base address
|
//set the command list base address
|
||||||
port^.cmdl_basel := vtop(uint32(cmd_list_base)); //todo set virtual address in device
|
port^.cmdl_basel := vtop(uint32(cmd_list_base)); //todo set virtual address in device
|
||||||
port^.cmdl_baseu := 0;
|
port^.cmdl_baseu := 0;
|
||||||
|
|
||||||
memset(uint32(cmd_list_base), 0, sizeof(THBA_CMD_HEADER));
|
|
||||||
|
|
||||||
device^.command_list := PHBA_CMD_HEADER(cmd_list_base);
|
device^.command_list := PHBA_CMD_HEADER(cmd_list_base);
|
||||||
|
|
||||||
|
|
||||||
|
//print the command list base address
|
||||||
|
console.writestring('AHCI: Command list base address: ');
|
||||||
|
console.writehexln(uint32(cmd_list_base));
|
||||||
|
|
||||||
|
//allocate memory for the FIS and ensure it is aligned to 256 bytes
|
||||||
|
fis_base := kalloc(sizeof(THBA_FIS) * 8);
|
||||||
|
fis_base := puint32((uint32(fis_base) + 255) and $FFFFFF00);
|
||||||
|
|
||||||
//set the FIS base address
|
//set the FIS base address
|
||||||
port^.fis_basel := vtop(uint32(fis_base));
|
port^.fis_basel := vtop(uint32(fis_base));
|
||||||
port^.fis_baseu := 0;
|
port^.fis_baseu := 0;
|
||||||
@ -164,9 +206,10 @@ begin
|
|||||||
device^.fis := PHBA_FIS(fis_base);
|
device^.fis := PHBA_FIS(fis_base);
|
||||||
//todo check how many simultaneous commands are supported
|
//todo check how many simultaneous commands are supported
|
||||||
|
|
||||||
//allocate memory for the command table and ensure it is aligned to 1024 bytes
|
//allocate memory for the command table and ensure it is aligned to 128 bytes
|
||||||
cmd_table_base := kalloc(sizeof(THBA_CMD_TABLE) * 64);
|
cmd_table_base := kalloc(sizeof(THBA_CMD_TABLE) * 64);
|
||||||
cmd_table_base := puint32((uint32(cmd_table_base) + 1023) and $FFFFFC00);
|
cmd_table_base := puint32((uint32(cmd_table_base) + 127) and $FFFFFF80);
|
||||||
|
memset(uint32(cmd_table_base), 0, sizeof(THBA_CMD_TABLE) * 32);
|
||||||
|
|
||||||
device^.command_table := PHBA_CMD_TABLE(cmd_table_base);
|
device^.command_table := PHBA_CMD_TABLE(cmd_table_base);
|
||||||
|
|
||||||
@ -174,93 +217,148 @@ begin
|
|||||||
for ii:=0 to 31 do begin
|
for ii:=0 to 31 do begin
|
||||||
//set command header locations
|
//set command header locations
|
||||||
command_header := PHBA_CMD_HEADER(uint32(cmd_list_base) + (ii * sizeof(THBA_CMD_HEADER)));
|
command_header := PHBA_CMD_HEADER(uint32(cmd_list_base) + (ii * sizeof(THBA_CMD_HEADER)));
|
||||||
|
|
||||||
command_header^.prdtl := 32;
|
command_header^.prdtl := 32;
|
||||||
//TODO do i need to set prdbc byte count here?
|
|
||||||
command_header^.cmd_table_base := vtop(uint32(cmd_table_base)) + (ii * sizeof(THBA_CMD_TABLE));
|
command_header^.cmd_table_base := vtop(uint32(cmd_table_base)) + (ii * sizeof(THBA_CMD_TABLE));
|
||||||
command_header^.cmd_table_baseu := 0;
|
command_header^.cmd_table_baseu := 0;
|
||||||
memset(uint32(cmd_table_base) + (ii * sizeof(THBA_CMD_TABLE)), 0, sizeof(THBA_CMD_TABLE));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
//reset the port
|
||||||
|
reset_port(port);
|
||||||
start_port(port);
|
start_port(port);
|
||||||
|
|
||||||
|
//print sata status
|
||||||
|
console.writestring('AHCI: sata status: ');
|
||||||
|
console.writehexln(port^.sata_status);
|
||||||
|
|
||||||
//pass devices count as second param
|
//pass devices count as second param
|
||||||
|
if (device^.device_type = SATA) then begin
|
||||||
identify_device(controller, DL_Size(controller^.devices) - 1);
|
identify_device(controller, DL_Size(controller^.devices) - 1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
controller^.mio^.int_status := $FFFFFFFF;
|
||||||
|
|
||||||
|
// identify_device(controller, DL_Size(controller^.devices) - 1);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure identify_device(controller : PAHCI_Controller; port : uint32);
|
procedure identify_device(controller : PAHCI_Controller; portIndex : uint32);
|
||||||
var
|
var
|
||||||
fis : PHBA_FIS_REG_H2D;
|
fis : PHBA_FIS_REG_H2D;
|
||||||
cmd_header : PHBA_CMD_HEADER;
|
cmd_header : PHBA_CMD_HEADER;
|
||||||
cmd_table : PHBA_CMD_TABLE;
|
cmd_table : PHBA_CMD_TABLE;
|
||||||
cmd : uint32;
|
cmd : uint32;
|
||||||
i : uint32;
|
i, timeout : uint32;
|
||||||
buffer :puint32;
|
buffer : puint32;
|
||||||
device : PAHCI_Device;
|
device : PAHCI_Device;
|
||||||
|
tfd : uint32;
|
||||||
|
sec_count : uint32;
|
||||||
|
b8 : puint16;
|
||||||
begin
|
begin
|
||||||
|
console.writestringln('AHCI: Identifying device');
|
||||||
|
device := PAHCI_Device(DL_Get(controller^.devices, portIndex));
|
||||||
|
|
||||||
device := PAHCI_Device(DL_Get(controller^.devices, port));
|
// (Optional) Print the device type if you store it:
|
||||||
|
console.writestring('AHCI: Device type: ');
|
||||||
|
// For example: if device^.device_type = SATA then ...
|
||||||
|
console.writestring('AHCI: sata status: ');
|
||||||
|
console.writehexln(device^.port^.sata_status);
|
||||||
|
|
||||||
|
//clear any pending interrupts
|
||||||
|
device^.port^.int_status := $FFFFFFFF;
|
||||||
|
device^.port^.int_enable := 0;
|
||||||
|
|
||||||
|
// Allocate a 512-byte DMA buffer for the IDENTIFY data
|
||||||
buffer := kalloc(512);
|
buffer := kalloc(512);
|
||||||
memset(uint32(buffer), 0, 512);
|
memset(uint32(buffer), 0, 512);
|
||||||
|
|
||||||
cmd_header := device^.command_list;
|
// Use command slot 0 for the IDENTIFY command.
|
||||||
|
cmd_header := device^.command_list; // Assuming slot 0 is at the beginning.
|
||||||
cmd_header^.cmd_fis_length := sizeof(THBA_FIS_REG_H2D) div sizeof(uint32);
|
cmd_header^.cmd_fis_length := sizeof(THBA_FIS_REG_H2D) div sizeof(uint32);
|
||||||
|
// cmd_header^.command := ATA_CMD_IDENTIFY;
|
||||||
cmd_header^.wrt := 0;
|
cmd_header^.wrt := 0;
|
||||||
cmd_header^.prdtl := 1;
|
cmd_header^.prdtl := 1;
|
||||||
|
cmd_header^.clear_busy := 1;
|
||||||
|
|
||||||
//just use first command table for identify as no other commands are running
|
|
||||||
|
// Setup the command table (using slot 0)
|
||||||
cmd_table := device^.command_table;
|
cmd_table := device^.command_table;
|
||||||
cmd_table^.prdt[0].dba := vtop(uint32(buffer));
|
cmd_table^.prdt[0].dba := vtop(uint32(buffer));
|
||||||
cmd_table^.prdt[0].dbc := 511;
|
cmd_table^.prdt[0].dbc := 511; // 512 bytes (0-based count)
|
||||||
cmd_table^.prdt[0].int := 1;
|
cmd_table^.prdt[0].int := 1; // Interrupt on completion
|
||||||
|
|
||||||
|
// Construct the Command FIS in the command table's CFIS area
|
||||||
fis := PHBA_FIS_REG_H2D(@device^.command_table^.cmd_fis);
|
fis := PHBA_FIS_REG_H2D(@device^.command_table^.cmd_fis);
|
||||||
|
memset(uint32(fis), 0, sizeof(THBA_FIS_REG_H2D));
|
||||||
fis^.fis_type := uint8(FIS_TYPE_REG_H2D);
|
fis^.fis_type := uint8(FIS_TYPE_REG_H2D);
|
||||||
fis^.pmport := 0;
|
fis^.c := $1;
|
||||||
fis^.command := ATA_CMD_IDENTIFY;
|
fis^.command := ATA_CMD_IDENTIFY;
|
||||||
fis^.device := 0;
|
fis^.device := $A0; // LBA mode 40?
|
||||||
fis^.lba0 := 0;
|
|
||||||
fis^.lba1 := 0;
|
|
||||||
fis^.lba2 := 0;
|
|
||||||
fis^.lba3 := 0;
|
|
||||||
fis^.lba4 := 0;
|
|
||||||
fis^.lba5 := 0;
|
|
||||||
fis^.countl := 1;
|
|
||||||
fis^.counth := 0;
|
|
||||||
fis^.featurel := 0;
|
|
||||||
fis^.featureh := 0;
|
|
||||||
|
|
||||||
//send the command
|
//waut for the port to be ready, bit 7 in the TFD register and bit 3 tfd
|
||||||
cmd := device^.port^.cmd;
|
while (device^.port^.tfd and $88) <> 0 do begin
|
||||||
|
console.writestring('AHCI: tfd: ');
|
||||||
|
console.writehexln(device^.port^.tfd);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Issue the command by setting bit 0 in the port's Command Issue register.
|
||||||
|
cmd := device^.port^.cmd_issue;
|
||||||
cmd := cmd or $1;
|
cmd := cmd or $1;
|
||||||
device^.port^.cmd := cmd;
|
device^.port^.cmd_issue := cmd;
|
||||||
|
|
||||||
//wait for the command to complete
|
console.writestringln('AHCI: Sent identify command');
|
||||||
while (cmd and $1) = 1 do begin
|
|
||||||
cmd := device^.port^.cmd;
|
|
||||||
|
// Wait for command completion with a timeout.
|
||||||
|
timeout := 0;
|
||||||
|
repeat
|
||||||
|
cmd := device^.port^.cmd_issue; // Command Issue register
|
||||||
|
tfd := device^.port^.tfd; // Task File Data often contains error/status info.
|
||||||
|
timeout := timeout + 10;
|
||||||
|
if timeout > 100000 then begin
|
||||||
|
console.writestringln('AHCI: IDENTIFY command timeout');
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
// check for bit 30 in the tfd register
|
||||||
|
if (tfd and $40000000) <> 0 then begin
|
||||||
|
console.writestringln('AHCI: error');
|
||||||
|
break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//check the status of the command
|
until ((device^.port^.cmd_issue and $1) = 0); // Wait until slot 0 is cleared
|
||||||
if (cmd and $2) = 1 then begin
|
|
||||||
|
console.writestringln('AHCI: Command complete');
|
||||||
|
|
||||||
|
// Check for an error flag in the command register (bit 1)
|
||||||
|
if (cmd and $2) <> 0 then begin
|
||||||
console.writestringln('AHCI: Error sending identify command');
|
console.writestringln('AHCI: Error sending identify command');
|
||||||
|
|
||||||
|
// Check the error register for more information
|
||||||
|
console.writestring('AHCI: Error register: ');
|
||||||
|
console.writehexln(device^.port^.sata_error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//parse the identify data
|
// Dump the 512-byte IDENTIFY data for debugging (display 64 DWORDs)
|
||||||
for i:=0 to 63 do begin
|
for i := 0 to 63 do begin
|
||||||
console.writehex(uint32(buffer[i]));
|
console.writehex(uint32(buffer[i]));
|
||||||
console.writestring(' ');
|
console.writestring(' ');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
console.writestringln('');
|
console.writestringln('');
|
||||||
|
|
||||||
|
b8 := puint16(buffer);
|
||||||
|
sec_count := (b8[61] shl 16) or b8[60];
|
||||||
|
console.writestring('AHCI: Sector count: ');
|
||||||
|
console.writeintln(sec_count);
|
||||||
|
console.writestring('AHCI: Device size: ');
|
||||||
|
console.writeint(sec_count * 512 div 1024 div 1024);
|
||||||
|
console.writestringln(' MB');
|
||||||
|
|
||||||
|
|
||||||
|
console.writestringln('');
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function load(ptr : void) : boolean;
|
function load(ptr : void) : boolean;
|
||||||
var
|
var
|
||||||
device : PPCI_Device;
|
device : PPCI_Device;
|
||||||
@ -271,6 +369,8 @@ var
|
|||||||
fis_base : puint32;
|
fis_base : puint32;
|
||||||
cmd_table_base : puint32;
|
cmd_table_base : puint32;
|
||||||
int_no : uInt8;
|
int_no : uInt8;
|
||||||
|
timeout : uint32;
|
||||||
|
bohc : uint32;
|
||||||
begin
|
begin
|
||||||
console.writestringln('AHCI: initilizing a new controller');
|
console.writestringln('AHCI: initilizing a new controller');
|
||||||
|
|
||||||
@ -284,7 +384,10 @@ begin
|
|||||||
pci.enableDevice(device^.bus, device^.slot, device^.func);
|
pci.enableDevice(device^.bus, device^.slot, device^.func);
|
||||||
int_no := device^.interrupt_line;
|
int_no := device^.interrupt_line;
|
||||||
|
|
||||||
registerISR(int_no, @ahci_isr);
|
|
||||||
|
//print interrupt number
|
||||||
|
console.writestring('AHCI: Interrupt number: ');
|
||||||
|
console.writehexln(int_no);
|
||||||
|
|
||||||
controller := PAHCI_Controller(DL_Add(ahciControllers));
|
controller := PAHCI_Controller(DL_Add(ahciControllers));
|
||||||
controller^.devices := DL_New(SizeOf(TAHCI_Device));
|
controller^.devices := DL_New(SizeOf(TAHCI_Device));
|
||||||
@ -299,19 +402,53 @@ begin
|
|||||||
base := PHBA_Memory(device^.address5);
|
base := PHBA_Memory(device^.address5);
|
||||||
controller^.mio := base;
|
controller^.mio := base;
|
||||||
|
|
||||||
|
if (controller^.mio^.capabilites2 and $28) <> 0 then begin
|
||||||
|
console.writestringln('AHCI: Controller needs to be handed off to the OS');
|
||||||
|
end;
|
||||||
|
|
||||||
console.writestring('AHCI: Controller at: ');
|
console.writestring('AHCI: Controller at: ');
|
||||||
console.writehexln(device^.address5);
|
console.writehexln(device^.address5);
|
||||||
console.writehexln(uint32(page_base));
|
console.writehexln(uint32(page_base));
|
||||||
|
|
||||||
|
bohc := controller^.mio^.bohc;
|
||||||
|
|
||||||
|
if (bohc and $1) <> 0 or (bohc and not (1 shl 1)) then begin
|
||||||
|
console.writestringln('AHCI: BIOS Owned Semaphore is set, initiating handoff.');
|
||||||
|
|
||||||
|
// Set the OS Owned Semaphore (typically bit 1).
|
||||||
|
bohc := bohc or (1 shl 1);
|
||||||
|
controller^.mio^.bohc := bohc;
|
||||||
|
|
||||||
|
// Wait until the BIOS Owned Semaphore (bit 0) is cleared.
|
||||||
|
timeout := 0;
|
||||||
|
while ((controller^.mio^.bohc and $1) <> 0) and (timeout < 1000000) do begin
|
||||||
|
timeout := timeout + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if timeout = 1000000 then begin
|
||||||
|
console.writestringln('AHCI: BIOS/OS handoff timed out.');
|
||||||
|
end else begin
|
||||||
|
console.writestringln('AHCI: BIOS/OS handoff successful.');
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
console.writestringln('AHCI: BIOS not holding controller or handoff already complete.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
base^.global_ctrl := base^.global_ctrl or 1;
|
||||||
|
|
||||||
|
while (base^.global_ctrl and 1) <> 0 do begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
registerISR(int_no, @ahci_isr);
|
||||||
|
|
||||||
//enable AHCI mode, TODO check if is not already in AHCI mode and enable it, also perhaps remove if loaded as IDE
|
//enable AHCI mode, TODO check if is not already in AHCI mode and enable it, also perhaps remove if loaded as IDE
|
||||||
base^.global_ctrl := base^.global_ctrl or AHCI_CONTROLLER_MODE;
|
base^.global_ctrl := base^.global_ctrl or AHCI_CONTROLLER_MODE;
|
||||||
|
base^.global_ctrl := base^.global_ctrl or $2; //enable interrupts
|
||||||
|
|
||||||
|
|
||||||
//clear any pending interrupts
|
//clear any pending interrupts
|
||||||
base^.int_status := $FFFFFFFF;
|
base^.int_status := $FFFFFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
check_ports(controller);
|
check_ports(controller);
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ type
|
|||||||
sata_noti: uint32; // SATA Notification
|
sata_noti: uint32; // SATA Notification
|
||||||
fis_switch_ctrl: uint32;// FIS-based Switch Control
|
fis_switch_ctrl: uint32;// FIS-based Switch Control
|
||||||
rsv1: array[0..10] of uint32;
|
rsv1: array[0..10] of uint32;
|
||||||
|
vendor: array[0..3] of uint32;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PHBA_Port = ^THBA_Port;
|
PHBA_Port = ^THBA_Port;
|
||||||
@ -102,8 +103,16 @@ type
|
|||||||
em_control: uint32; // Enclosure Management Control
|
em_control: uint32; // Enclosure Management Control
|
||||||
capabilites2: uint32; // Host Capabilities Extended
|
capabilites2: uint32; // Host Capabilities Extended
|
||||||
bohc: uint32; // BIOS/OS Handoff Control and Status
|
bohc: uint32; // BIOS/OS Handoff Control and Status
|
||||||
rsv0: array[0..$210] of boolean;
|
|
||||||
|
//0x2c to 0x9f reserved
|
||||||
|
rsv0: array[0..115] of uint8;
|
||||||
|
|
||||||
|
//vendor specific
|
||||||
|
vendor: array[0..95] of uint8;
|
||||||
|
|
||||||
|
//port registers
|
||||||
ports: array[0..31] of THBA_Port;
|
ports: array[0..31] of THBA_Port;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PHBA_Memory = ^THBA_Memory;
|
PHBA_Memory = ^THBA_Memory;
|
||||||
@ -145,7 +154,10 @@ type
|
|||||||
}
|
}
|
||||||
THBA_FIS_REG_H2D = bitpacked record
|
THBA_FIS_REG_H2D = bitpacked record
|
||||||
fis_type: uint8; // FIS Type
|
fis_type: uint8; // FIS Type
|
||||||
pmport: uint8; // Port Multiplier Port
|
// pmport: uint8; // Port Multiplier Port is pmport:4 and rsv0:3 and i:1
|
||||||
|
pmport: ubit4; // Port Multiplier Port
|
||||||
|
rsv: ubit3; // Reserved
|
||||||
|
c: ubit1; // command or control
|
||||||
command: uint8; // Command
|
command: uint8; // Command
|
||||||
featurel: uint8; // Feature Lower 8-bits
|
featurel: uint8; // Feature Lower 8-bits
|
||||||
lba0: uint8; // LBA0
|
lba0: uint8; // LBA0
|
||||||
@ -160,7 +172,7 @@ type
|
|||||||
counth: uint8; // Count Upper 8-bits
|
counth: uint8; // Count Upper 8-bits
|
||||||
icc: uint8; // Isochronous Command Completion
|
icc: uint8; // Isochronous Command Completion
|
||||||
control: uint8; // Control
|
control: uint8; // Control
|
||||||
rsv0: array[0..2] of uint8;
|
rsv0: array[0..3] of uint8;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PHBA_FIS_REG_H2D = ^THBA_FIS_REG_H2D;
|
PHBA_FIS_REG_H2D = ^THBA_FIS_REG_H2D;
|
||||||
@ -171,19 +183,22 @@ type
|
|||||||
AHCI Host Bus Adapter (HBA) Command Header Interface
|
AHCI Host Bus Adapter (HBA) Command Header Interface
|
||||||
}
|
}
|
||||||
THBA_CMD_HEADER = bitpacked record
|
THBA_CMD_HEADER = bitpacked record
|
||||||
cmd_fis_length: uint8; // Command FIS Length
|
cmd_fis_length: UBit5; // Command FIS Length
|
||||||
atapi: uint8; // ATAPI
|
atapi: UBit1; // ATAPI
|
||||||
wrt: uint8; // Write
|
wrt: UBit1; // Write
|
||||||
prefetchable: uint8; // Prefetchable
|
prefetchable: UBit1; // Prefetchable
|
||||||
reset: uint8; // Reset
|
|
||||||
bist: uint8; // BIST
|
reset: UBit1; // Reset
|
||||||
clear_busy: uint8; // Clear Busy
|
bist: UBit1; // BIST
|
||||||
reserved0: uint8; // Reserved
|
clear_busy: UBit1; // Clear Busy
|
||||||
|
reserved0: UBit1; // Reserved
|
||||||
|
port_multiplier: UBit4; // Port Multiplier Port
|
||||||
|
|
||||||
prdtl: uint16; // Physical Region Descriptor Table Length
|
prdtl: uint16; // Physical Region Descriptor Table Length
|
||||||
prdbc: uint32; // Physical Region Descriptor Byte Count
|
prdbc: uint32; // Physical Region Descriptor Byte Count
|
||||||
cmd_table_base: uint32; // Command Table Base Address
|
cmd_table_base: uint32; // Command Table Base Address
|
||||||
cmd_table_baseu: uint32; // Command Table Base Address Upper 32-bits
|
cmd_table_baseu: uint32; // Command Table Base Address Upper 32-bits
|
||||||
rsv0: array[0..4] of uint32;
|
rsv0: array[0..3] of uint32;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PHBA_CMD_HEADER = ^THBA_CMD_HEADER;
|
PHBA_CMD_HEADER = ^THBA_CMD_HEADER;
|
||||||
@ -195,8 +210,8 @@ type
|
|||||||
dba: uint32; // Data Base Address
|
dba: uint32; // Data Base Address
|
||||||
dbau: uint32; // Data Base Address Upper 32-bits
|
dbau: uint32; // Data Base Address Upper 32-bits
|
||||||
rsv0: uint32; // Reserved
|
rsv0: uint32; // Reserved
|
||||||
reserved: ubit9; // Reserved
|
|
||||||
dbc: ubit22; // Data Byte Count
|
dbc: ubit22; // Data Byte Count
|
||||||
|
reserved: ubit9; // Reserved
|
||||||
int: ubit1; // Interrupt
|
int: ubit1; // Interrupt
|
||||||
// dbc: uint32; // Data Byte Count, bit 1 is Interrupt, then 22 bits of Byte Count, then 9 bits of Reserved
|
// dbc: uint32; // Data Byte Count, bit 1 is Interrupt, then 22 bits of Byte Count, then 9 bits of Reserved
|
||||||
end;
|
end;
|
||||||
@ -211,7 +226,7 @@ type
|
|||||||
cmd_fis: array[0..63] of uint8; // Command FIS
|
cmd_fis: array[0..63] of uint8; // Command FIS
|
||||||
acmd: array[0..15] of uint8; // ATAPI Command
|
acmd: array[0..15] of uint8; // ATAPI Command
|
||||||
rsv0: array[0..47] of uint8;
|
rsv0: array[0..47] of uint8;
|
||||||
prdt: TPRDT; // Physical Region Descriptor Table
|
prdt: array[0..31] of THBA_PRD; // Physical Region Descriptor Table
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PHBA_CMD_TABLE = ^THBA_CMD_TABLE;
|
PHBA_CMD_TABLE = ^THBA_CMD_TABLE;
|
||||||
@ -227,8 +242,8 @@ type
|
|||||||
Device type enum
|
Device type enum
|
||||||
}
|
}
|
||||||
TDeviceType = (
|
TDeviceType = (
|
||||||
SATA,
|
SATA = 1,
|
||||||
ATAPI,
|
ATAPI = 2,
|
||||||
SEMB,
|
SEMB,
|
||||||
PM
|
PM
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user