ahci progress

This commit is contained in:
Aaron Hance 2025-03-15 20:13:33 +00:00
parent b2ecbe58da
commit 6a3ebf1387
7 changed files with 503 additions and 354 deletions

View File

@ -4,4 +4,4 @@ echo "======================="
echo " " echo " "
echo "Compiling FPC Sources..." echo "Compiling FPC Sources..."
echo " " echo " "
fpc -Aelf -gw -n -va -O3 -Op3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/* -Fusrc/driver/net/* src/kernel.pas fpc -Aelf -gw -n -O3 -Op3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/driver/storage/* -Fusrc/driver/storage/AHCI/* -Fusrc/driver/* -Fusrc/driver/net/* src/kernel.pas

View File

@ -1,296 +0,0 @@
// Copyright 2021 Aaron Hance
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{
Drivers->Storage->AHCI - AHCI SATA Driver.
@author(Aaron Hance <ah@aaronhance.me>)
}
unit AHCI;
interface
uses
util,
PCI,
drivertypes,
drivermanagement,
lmemorymanager,
console,
vmemorymanager;
type
//Struct hell
TFIS_Type = (
REG_H2D = $27,
REG_D2H = $34,
DMA_ACT = $39,
DMA_SETUP = $41,
DATA = $46,
BIST = $58,
PIO_SETUP = $5F,
DEV_BITS = $A0
);
PFIS_REG_H2D = ^TFIS_REG_H2D;
TFIS_REG_H2D = bitpacked record
fis_type : uint8;
port_mult : UBit4;
rsv0 : UBit3;
coc : boolean;
command : uint8;
feature_low : uint8;
lba0 : uint8;
lba1 : uint8;
lba2 : uint8;
device : uint8;
lba3 : uint8;
lba4 : uint8;
lba5 : uint8;
feature_high : uint8;
count_low : uint8;
count_high : uint8;
icc : uint8;
control : uint8;
rsvl : uint32;
end;
TFIS_REG_D2H = bitpacked record
fis_type : uint8;
port_mult : UBit4;
rsv0 : UBit2;
i : boolean;
rsvl : boolean;
status : uint8;
error : uint8;
lba0 : uint8;
lba1 : uint8;
lba2 : uint8;
device : uint8;
lba3 : uint8;
lba4 : uint8;
lba5 : uint8;
rsv2 : uint8;
count_low : uint8;
count_high : uint8;
rsv3 : uint16;
rsv4 : uint32;
end;
TFIS_Data = bitpacked record
fis_type : uint8;
port_mult : UBit4;
rsv0 : UBit4;
rsv1 : uint16;
data : ^uint32;
end;
TFIS_PIO_Setup = bitpacked record
fis_type : uint8;
pmport : UBit4;
rsv0 : boolean;
d : boolean;
i : boolean;
rsv1 : boolean;
status : uint8;
error : uint8;
lba0 : uint8;
lba1 : uint8;
lba2 : uint8;
device : uint8;
lba3 : uint8;
lba4 : uint8;
lba5 : uint8;
rsv2 : uint8;
countl : uint8;
counth : uint8;
rsv3 : uint8;
e_status : uint8;
tc : uint16;
rsv4 : uint16;
end;
// TFIS_DMA_Setup = bitpacked record
// end;
// THBA_Memory = bitpacked record
// end;
// THBA_Port = bitpacked record
// end;
// THBA_FIS = bitpacked record
// end;
PHBA_PORT = ^THBA_PORT;
THBA_PORT = bitpacked record
clb : uint32;
clbu : uint32;
fb : uint32;
fbu : uint32;
istat : uint32;
ie : uint32;
cmd : uint32;
rsv0 : uint32;
tfd : uint32;
sig : uint32;
ssts : uint32;
sctl : uint32;
serr : uint32;
sact : uint32;
ci : uint32;
sntf : uint32;
fbs : uint32;
rsv1 : array[0..11] of uint32;
vendor : array[0..4] of uint32;
end;
THBA_MEM = bitpacked record
cap : uint32; //0
global_host_control : uint32; //4
interrupt_status : uint32; //8
port_implemented : uint32; //c
version : uint32; //10
ccc_control : uint32; //14
ccc_ports : uint32; //18
em_location : uint32; //1c
em_Control : uint32; //20
hcap2 : uint32; //24
bohc : uint32; //28
rsv0 : array[0..210] of boolean;
ports : array[0..31] of THBA_Port;
end;
PHBA = ^THBA_MEM;
PCMDHeader = ^ TCommand_Header;
TCommand_Header = bitpacked record
cfl : ubit5;
a : boolean;
w : boolean;
p : boolean;
r : boolean;
b : boolean;
c : boolean;
rsv0 : boolean;
pmp : ubit4;
PRDTL : uint16;
PRDTBC : uint32;
CTBA : uint32;
CTBAU : uint32;
rsv1 : array[0..3] of uint32;
end;
TPRD_Entry = bitpacked record
data_base_address : uint32;
data_bade_address_U : uint32;
rsv0 : uint32;
data_byte_count : ubit22;
rsv1 : ubit9;
interrupt_oc : boolean;
end;
PCommand_Table = ^TCommand_Table;
TCommand_Table = bitpacked record
cfis : array[0..64] of uint8;
acmd : array[0..16] of uint8;
rsv : array[0..48] of uint8;
prdt : array[0..7] of TPRD_Entry;
end;
TSataDevice = record
controller : uint8;
port : uint8;
end;
var
//constants
//SATA_SIG_ATA := $101;
//SATA_SIG_ATAPI := $EB140101;
//STA_SIG_SEMB := $C33C0101;
//STAT_SIG_PM := $96690101;
AHCI_BASE: uint32 = $400000; //irrelivent
//other
ahciControllers : array[0.16] of PuInt32;
ahciControllerCount : uint8 = 0;
hba : array[0..16] of PHBA;
sataDevices : array[0..127] of TSataDevice;
sataDeviceCount : uint8;
procedure init();
procedure check_ports(controller : uint8);
procedure enable_cmd(port : uint8);
procedure disable_cmd(port : uint8);
procedure port_rebase(port : uint8);
function load(ptr:void): boolean;
function read(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
function write(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
function find_cmd_slot(port : uint8) : uint32;
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('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;
procedure check_ports(controller : uint8);
var
d : uint32 = 1;
i : uint32;
begin
for i:=0 to 31 do begin
if (d > 0) and (hba[controller]^.port_implemented shr i) = 1 then begin
if (hba[controller]^.ports[i].ssts shr 8) <> 1 and (hba[controller]^.ports[i].ssts and $0F) <> 3 then begin
if hba[controller]^.ports[i].sig = 1 then begin
//device is sata
sataDevices[sataDeviceCount].controller := controller;
sataDevices[sataDeviceCount].port := i;
sataDeviceCount += 1;
end;
//TODO implement ATAPI
end;
end;
end;
end;

View File

@ -34,10 +34,11 @@ uses
lists; lists;
var var
ahciControllers : PDLList; ahciControllers : PDList;
page_base : puint32;
procedure init(); procedure init();
procedure load(); function load(ptr : void) : boolean;
implementation implementation
@ -57,19 +58,117 @@ begin
//TODO check IDE devices in ide for sata devices //TODO check IDE devices in ide for sata devices
end; end;
procedure stop_port(port : PHBA_Port);
begin
port^.cmd_sts := port^.cmd_sts and not $1; ///maybe also bit 4
while (port^.cmd_sts and $1) = 1 do begin
//wait for the port to stop
end;
end;
procedure start_port(port : PHBA_Port);
begin
port^.cmd_sts := port^.cmd_sts or $1; ///maybe also bit 4
while (port^.cmd_sts and $1) = 0 do begin
//wait for the port to start
end;
end;
{
Check the ports on the controller and setup the command list, FIS, and command table
}
procedure check_ports(controller : PAHCI_Controller); procedure check_ports(controller : PAHCI_Controller);
var var
i : uint32; i : uint32;
port : PHBA_Port; port : PHBA_Port;
device : PAHCI_Device;
cmd_list_base : puint32;
fis_base : puint32;
cmd_table_base : puint32;
cmd_header : PHBA_CMD_HEADER;
begin begin
for i:=0 to 31 do begin
if (controller^.mio^.port_implemented shr i) = 1 then begin
port := @controller^.mio^.ports[i];
console.writestring('AHCI: Port ');
console.writeint(i);
console.writestring(' implemented on controller ');
console.writehexln(uint32(controller^.pci_device^.address5));
//NEEED TO STOP the port before doing anything
device := PAHCI_Device(DL_Add(controller^.devices));
device^.port := port;
//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 := puint32((uint32(cmd_list_base) + 1023) and $FFFFFC00);
//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
port^.cmd_list_base := uint32(vtop(cmd_list_base)); //todo set virtual address in device
port^.cmd_list_base_upper := 0;
memset(uint32(cmd_list_base), 0, sizeof(THBA_CMD_HEADER));
device^.command_list := PHBA_CMD_HEADER(cmd_list_base);
//set the FIS base address
port^.fis_base := uint32(vtop(fis_base));
port^.fis_base_upper := 0;
memset(uint32(fis_base), 0, sizeof(THBA_FIS));
device^.fis := PHBA_FIS(fis_base);
//todo check how many simultaneous commands are supported
//allocate memory for the command table and ensure it is aligned to 1024 bytes
cmd_table_base := kalloc(sizeof(THBA_CMD_TABLE) * 64);
cmd_table_base := puint32((uint32(cmd_table_base) + 1023) and $FFFFFC00);
device^.command_table := PHBA_CMD_TABLE(cmd_table_base);
//set the command table base address and setup command table
for i:=0 to 31 do begin
//set command header locations
command_header := PHBA_CMD_HEADER(uint32(cmd_list_base) + (i * sizeof(THBA_CMD_HEADER)));
command_header^.prdtl := 32;
//TODO do i need to set prdbc byte count here?
command_header^.cmd_table_base := uint32(vtop(cmd_table_base) + (i * sizeof(THBA_CMD_TABLE));
command_header^.cmd_table_base_upper := 0;
memset(uint32(cmd_table_base) + (i * sizeof(THBA_CMD_TABLE)), 0, sizeof(THBA_CMD_TABLE));
end;
start_port(port);
end;
end;
end; end;
procedure load(ptr : void); // procedure identify_device(controller : PAHCI_Controller; port : uint32);
// var
// fis : PFIS_REG_H2D;
// cmd : uint32;
// i : uint32;
// begin
// end;
function load(ptr : void) : boolean;
var var
device : PPCI_Device; device : PPCI_Device;
controller : PAHCI_Controller; controller : PAHCI_Controller;
i : uint32; i : uint32;
base : PHBA_Memory; base : PHBA_Memory;
cmd_list_base : puint32;
fis_base : puint32;
cmd_table_base : puint32;
begin begin
console.writestringln('AHCI: initilizing a new controller'); console.writestringln('AHCI: initilizing a new controller');
@ -80,14 +179,23 @@ begin
device := PPCI_Device(ptr); device := PPCI_Device(ptr);
controller := DL_Add(ahciControllers); controller := PAHCI_Controller(DL_Add(ahciControllers));
controller^.device := device; controller^.devices := DL_New(SizeOf(TAHCI_Device));
base: PHBA_Memory(kpalloc(device^.address5)); // get the base address of the controller controller^.pci_device := PPCI_Device(device);
//get the base address of the controller
page_base := kpalloc(device^.address5); // TODO MEM memory manager need to be improved
base := PHBA_Memory(device^.address5);
controller^.mio := base; controller^.mio := base;
console.writestring('AHCI: Controller at: ');
console.writehexln(device^.address5);
console.writehexln(uint32(page_base));
//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^.ghc := base^.ghc or AHCI_CONTROLLER_MODE; base^.global_ctrl := base^.global_ctrl or AHCI_CONTROLLER_MODE;
//clear any pending interrupts //clear any pending interrupts
base^.int_status := $FFFFFFFF; base^.int_status := $FFFFFFFF;
@ -95,6 +203,10 @@ begin
check_ports(controller);
// console.writestringln('AHCI: initilizing a new controller'); // console.writestringln('AHCI: initilizing a new controller');
// ahciControllers[ahciControllerCount] := ptr; // ahciControllers[ahciControllerCount] := ptr;
@ -109,4 +221,5 @@ begin
end; end;
end. end.

View File

@ -26,11 +26,18 @@ uses
drivermanagement, drivermanagement,
lmemorymanager, lmemorymanager,
console, console,
vmemorymanager; vmemorymanager,
idetypes,
lists;
const const
AHCI_CONTROLLER_MODE = $80000000; AHCI_CONTROLLER_MODE = $80000000;
CMD_LIST_ALIGN = 1024;
CMD_TBL_ALIGN = 128;
NUM_CMD_ENTRIES = 32;
//device type signatures //device type signatures
SATA_SIG_ATA = $00000101; SATA_SIG_ATA = $00000101;
SATA_SIG_ATAPI = $EB140101; SATA_SIG_ATAPI = $EB140101;
@ -75,17 +82,19 @@ type
rsv1: array[0..10] of uint32; rsv1: array[0..10] of uint32;
end; end;
PHBA_Port = ^THBA_Port;
{ {
AHCI Host Bus Adapter (HBA) Memory-Mapped Register Interface AHCI Host Bus Adapter (HBA) Memory-Mapped Register Interface
This structure is used to access the AHCI HBA's memory-mapped registers. This structure is used to access the AHCI's memory-mapped registers.
The AHCI HBA's memory-mapped registers are used to configure the HBA and The AHCI's memory-mapped registers are used to configure the HBA and to
to issue commands to the SATA devices connected to the HBA. issue commands to the SATA devices connected to the HBA.
} }
THBA_Memory = bitpacked record THBA_Memory = bitpacked record
capabilites: uint32; // Host Capabilities capabilites: uint32; // Host Capabilities
global_ctrl: uint32; // Global Host Control global_ctrl: uint32; // Global Host Control
int_status: uint32; // Interrupt Status int_status: uint32; // Interrupt Status
ports_implemented: uint32; // Ports Implemented ports_implimented: uint32;// Ports Implemented
version: uint32; // Version version: uint32; // Version
ccc_control: uint32; // Command Completion Coalescing Control ccc_control: uint32; // Command Completion Coalescing Control
ccc_ports: uint32; // Command Completion Coalescing Ports ccc_ports: uint32; // Command Completion Coalescing Ports
@ -93,7 +102,7 @@ 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..0x210] of boolean; rsv0: array[0..$210] of boolean;
ports: array[0..31] of THBA_Port; ports: array[0..31] of THBA_Port;
end; end;
@ -102,26 +111,26 @@ type
{ {
AHCI Host Bus Adapter (HBA) FIS (Frame Information Structure) Interface AHCI Host Bus Adapter (HBA) FIS (Frame Information Structure) Interface
This structure is used to access the AHCI HBA's FIS (Frame Information Structure) 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 memory-mapped registers.
configure the HBA and to issue commands to the SATA devices connected to the HBA.
} }
THBA_FIS = bitpacked record THBA_FIS = bitpacked record
dsfis: array[0..0x1F] of uint32; // DMA Setup FIS dsfis: array[0..$1F] of uint32; // DMA Setup FIS
rsv0: array[0..0x1F] of uint32; rsv0: array[0..$1F] of uint32;
psfis: array[0..0x1F] of uint32; // PIO Setup FIS psfis: array[0..$1F] of uint32; // PIO Setup FIS
rsv1: array[0..0x1F] of uint32; rsv1: array[0..$1F] of uint32;
rfis: array[0..0x1F] of uint32; // D2H Register FIS rfis: array[0..$1F] of uint32; // D2H Register FIS
rsv2: array[0..0x1F] of uint32; rsv2: array[0..$1F] of uint32;
sdbfis: array[0..0xF] of uint32; // Set Device Bits FIS sdbfis: array[0..$F] of uint32; // Set Device Bits FIS
ufis: array[0..0x1F] of uint32; // Unknown FIS ufis: array[0..$1F] of uint32; // Unknown FIS
rsv3: array[0..0x67] of uint32; rsv3: array[0..$67] of uint32;
end; end;
PHBA_FIS = ^THBA_FIS;
{ {
AHCI Host Bus Adapter (HBA) Command Header Interface AHCI Host Bus Adapter (HBA) Command Header Interface
This structure is used to access the AHCI HBA's Command Header memory-mapped 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 registers.
configure the HBA and to issue commands to the SATA devices connected to the HBA.
} }
THBA_CMD_HEADER = bitpacked record THBA_CMD_HEADER = bitpacked record
cmd_fis_length: uint8; // Command FIS Length cmd_fis_length: uint8; // Command FIS Length
@ -139,6 +148,8 @@ type
rsv0: array[0..4] of uint32; rsv0: array[0..4] of uint32;
end; end;
PHBA_CMD_HEADER = ^THBA_CMD_HEADER;
{ {
AHCI Host Bus Adapter (HBA) Command Table Interface AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped This structure is used to access the AHCI HBA's Command Table memory-mapped
@ -147,15 +158,19 @@ type
} }
THBA_CMD_TABLE = bitpacked record THBA_CMD_TABLE = bitpacked record
cmd_fis: THBA_FIS; // Command FIS cmd_fis: THBA_FIS; // Command FIS
acmd: array[0..0x1F] of uint8; // ATAPI Command acmd: array[0..$1F] of uint8; // ATAPI Command
rsv0: array[0..0x30] of uint8; rsv0: array[0..$30] of uint8;
end; end;
PHBA_CMD_TABLE = ^THBA_CMD_TABLE;
TCMD_LIST = array[0..255] of THBA_CMD_HEADER;
PCMD_LIST = ^TCMD_LIST;
{ {
AHCI Host Bus Adapter (HBA) Command Table Interface AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped 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 registers.
configure the HBA and to issue commands to the SATA devices connected to the HBA.
} }
THBA_PRD = bitpacked record THBA_PRD = bitpacked record
dba: uint32; // Data Base Address dba: uint32; // Data Base Address
@ -168,24 +183,22 @@ type
{ {
AHCI Host Bus Adapter (HBA) Command Table Interface AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped 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 registers.
configure the HBA and to issue commands to the SATA devices connected to the HBA.
} }
THBA_CMD = bitpacked record THBA_CMD = bitpacked record
header: THBA_CMD_HEADER; // Command Header header: THBA_CMD_HEADER; // Command Header
table: THBA_CMD_TABLE; // Command Table table: THBA_CMD_TABLE; // Command Table
prd: array[0..0x7] of THBA_PRD; // Physical Region Descriptor Table prd: array[0..31] of THBA_PRD; // Physical Region Descriptor Table
end; end;
{ {
AHCI Host Bus Adapter (HBA) Command Table Interface AHCI Host Bus Adapter (HBA) Command Table Interface
This structure is used to access the AHCI HBA's Command Table memory-mapped 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 registers.
configure the HBA and to issue commands to the SATA devices connected to the HBA.
} }
THBA = bitpacked record THBA = bitpacked record
memory: THBA_Memory; // HBA Memory memory: THBA_Memory; // HBA Memory
cmd: array[0..0x7FF] of THBA_CMD; // Command List cmd: array[0..$7FF] of THBA_CMD; // Command List
end; end;
PHBA = ^THBA; PHBA = ^THBA;
@ -204,20 +217,35 @@ type
PM PM
); );
{
AHCI device reference
}
TAHCI_Device = bitpacked record
port : PHBA_Port;
device_type : TDeviceType;
ata_info : TIdentResponse;
command_list : PHBA_CMD_HEADER;
fis : PHBA_FIS;
command_table : PHBA_CMD_TABLE;
end;
PAHCI_Device = ^TAHCI_Device;
{ {
controller reference controller reference
} }
TAHCI_Controller = bitpacked record TAHCI_Controller = bitpacked record
pci_device : PPCI_Device; pci_device : PPCI_Device;
mio: PHBA_Memory; mio: PHBA_Memory;
devices : array[0..31] of uint8; //TODO type for devices ata_info : TIdentResponse;
devices : PDList;
end; end;
PAHCI_Controller = ^TAHCI_Controller; PAHCI_Controller = ^TAHCI_Controller;
function get_device_type(sig : uint32) : TDeviceType; function get_device_type(sig : uint32) : TDeviceType;
function get_device_type_string(deive_type : TDeviceType) : string; // function get_device_type_string(deive_type : TDeviceType) : string;
implementation implementation
@ -239,23 +267,23 @@ begin
end; end;
end; end;
function get_device_type_string(deive_type : TDeviceType) : string; // function get_device_type_string(deive_type : TDeviceType) : string;
begin // begin
case deive_type of // case deive_type of
SATA: begin // SATA: begin
get_device_type_string := 'SATA'; // get_device_type_string := 'SATA';
end; // end;
ATAPI: begin // ATAPI: begin
get_device_type_string := 'ATAPI'; // get_device_type_string := 'ATAPI';
end; // end;
SEMB: begin // SEMB: begin
get_device_type_string := 'SEMB'; // get_device_type_string := 'SEMB';
end; // end;
PM: begin // PM: begin
get_device_type_string := 'PM'; // get_device_type_string := 'PM';
end; // end;
end; // end;
end; // end;
end. end.

View File

@ -0,0 +1,296 @@
// // Copyright 2021 Aaron Hance
// //
// // Licensed under the Apache License, Version 2.0 (the "License");
// // you may not use this file except in compliance with the License.
// // You may obtain a copy of the License at
// //
// // http://www.apache.org/licenses/LICENSE-2.0
// //
// // Unless required by applicable law or agreed to in writing, software
// // distributed under the License is distributed on an "AS IS" BASIS,
// // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// // See the License for the specific language governing permissions and
// // limitations under the License.
// {
// Drivers->Storage->AHCI - AHCI SATA Driver.
// @author(Aaron Hance <ah@aaronhance.me>)
// }
// unit AHCI;
// interface
// uses
// util,
// PCI,
// drivertypes,
// drivermanagement,
// lmemorymanager,
// console,
// vmemorymanager;
// type
// //Struct hell
// TFIS_Type = (
// REG_H2D = $27,
// REG_D2H = $34,
// DMA_ACT = $39,
// DMA_SETUP = $41,
// DATA = $46,
// BIST = $58,
// PIO_SETUP = $5F,
// DEV_BITS = $A0
// );
// PFIS_REG_H2D = ^TFIS_REG_H2D;
// TFIS_REG_H2D = bitpacked record
// fis_type : uint8;
// port_mult : UBit4;
// rsv0 : UBit3;
// coc : boolean;
// command : uint8;
// feature_low : uint8;
// lba0 : uint8;
// lba1 : uint8;
// lba2 : uint8;
// device : uint8;
// lba3 : uint8;
// lba4 : uint8;
// lba5 : uint8;
// feature_high : uint8;
// count_low : uint8;
// count_high : uint8;
// icc : uint8;
// control : uint8;
// rsvl : uint32;
// end;
// TFIS_REG_D2H = bitpacked record
// fis_type : uint8;
// port_mult : UBit4;
// rsv0 : UBit2;
// i : boolean;
// rsvl : boolean;
// status : uint8;
// error : uint8;
// lba0 : uint8;
// lba1 : uint8;
// lba2 : uint8;
// device : uint8;
// lba3 : uint8;
// lba4 : uint8;
// lba5 : uint8;
// rsv2 : uint8;
// count_low : uint8;
// count_high : uint8;
// rsv3 : uint16;
// rsv4 : uint32;
// end;
// TFIS_Data = bitpacked record
// fis_type : uint8;
// port_mult : UBit4;
// rsv0 : UBit4;
// rsv1 : uint16;
// data : ^uint32;
// end;
// TFIS_PIO_Setup = bitpacked record
// fis_type : uint8;
// pmport : UBit4;
// rsv0 : boolean;
// d : boolean;
// i : boolean;
// rsv1 : boolean;
// status : uint8;
// error : uint8;
// lba0 : uint8;
// lba1 : uint8;
// lba2 : uint8;
// device : uint8;
// lba3 : uint8;
// lba4 : uint8;
// lba5 : uint8;
// rsv2 : uint8;
// countl : uint8;
// counth : uint8;
// rsv3 : uint8;
// e_status : uint8;
// tc : uint16;
// rsv4 : uint16;
// end;
// // TFIS_DMA_Setup = bitpacked record
// // end;
// // THBA_Memory = bitpacked record
// // end;
// // THBA_Port = bitpacked record
// // end;
// // THBA_FIS = bitpacked record
// // end;
// PHBA_PORT = ^THBA_PORT;
// THBA_PORT = bitpacked record
// clb : uint32;
// clbu : uint32;
// fb : uint32;
// fbu : uint32;
// istat : uint32;
// ie : uint32;
// cmd : uint32;
// rsv0 : uint32;
// tfd : uint32;
// sig : uint32;
// ssts : uint32;
// sctl : uint32;
// serr : uint32;
// sact : uint32;
// ci : uint32;
// sntf : uint32;
// fbs : uint32;
// rsv1 : array[0..11] of uint32;
// vendor : array[0..4] of uint32;
// end;
// THBA_MEM = bitpacked record
// cap : uint32; //0
// global_host_control : uint32; //4
// interrupt_status : uint32; //8
// port_implemented : uint32; //c
// version : uint32; //10
// ccc_control : uint32; //14
// ccc_ports : uint32; //18
// em_location : uint32; //1c
// em_Control : uint32; //20
// hcap2 : uint32; //24
// bohc : uint32; //28
// rsv0 : array[0..210] of boolean;
// ports : array[0..31] of THBA_Port;
// end;
// PHBA = ^THBA_MEM;
// PCMDHeader = ^ TCommand_Header;
// TCommand_Header = bitpacked record
// cfl : ubit5;
// a : boolean;
// w : boolean;
// p : boolean;
// r : boolean;
// b : boolean;
// c : boolean;
// rsv0 : boolean;
// pmp : ubit4;
// PRDTL : uint16;
// PRDTBC : uint32;
// CTBA : uint32;
// CTBAU : uint32;
// rsv1 : array[0..3] of uint32;
// end;
// TPRD_Entry = bitpacked record
// data_base_address : uint32;
// data_bade_address_U : uint32;
// rsv0 : uint32;
// data_byte_count : ubit22;
// rsv1 : ubit9;
// interrupt_oc : boolean;
// end;
// PCommand_Table = ^TCommand_Table;
// TCommand_Table = bitpacked record
// cfis : array[0..64] of uint8;
// acmd : array[0..16] of uint8;
// rsv : array[0..48] of uint8;
// prdt : array[0..7] of TPRD_Entry;
// end;
// TSataDevice = record
// controller : uint8;
// port : uint8;
// end;
// var
// //constants
// //SATA_SIG_ATA := $101;
// //SATA_SIG_ATAPI := $EB140101;
// //STA_SIG_SEMB := $C33C0101;
// //STAT_SIG_PM := $96690101;
// AHCI_BASE: uint32 = $400000; //irrelivent
// //other
// ahciControllers : array[0.16] of PuInt32;
// ahciControllerCount : uint8 = 0;
// hba : array[0..16] of PHBA;
// sataDevices : array[0..127] of TSataDevice;
// sataDeviceCount : uint8;
// procedure init();
// procedure check_ports(controller : uint8);
// procedure enable_cmd(port : uint8);
// procedure disable_cmd(port : uint8);
// procedure port_rebase(port : uint8);
// function load(ptr:void): boolean;
// function read(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
// function write(port : uint8; startl : uint32; starth : uint32; count : uint32; buf : PuInt32) : boolean;
// function find_cmd_slot(port : uint8) : uint32;
// 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('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;
// procedure check_ports(controller : uint8);
// var
// d : uint32 = 1;
// i : uint32;
// begin
// for i:=0 to 31 do begin
// if (d > 0) and (hba[controller]^.port_implemented shr i) = 1 then begin
// if (hba[controller]^.ports[i].ssts shr 8) <> 1 and (hba[controller]^.ports[i].ssts and $0F) <> 3 then begin
// if hba[controller]^.ports[i].sig = 1 then begin
// //device is sata
// sataDevices[sataDeviceCount].controller := controller;
// sataDevices[sataDeviceCount].port := i;
// sataDeviceCount += 1;
// end;
// //TODO implement ATAPI
// end;
// end;
// end;
// end;

View File

@ -57,7 +57,8 @@ uses
base64, base64,
rand, rand,
terminal, terminal,
hashmap, vfs; hashmap, vfs,
AHCI;
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall; procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
@ -228,7 +229,8 @@ begin
mouse.init(); mouse.init();
testdriver.init(); testdriver.init();
E1000.init(); E1000.init();
IDE.init(); // IDE.init();
AHCI.init();
console.outputln('KERNEL', 'DEVICE DRIVERS: INIT END.'); console.outputln('KERNEL', 'DEVICE DRIVERS: INIT END.');
{ Bus Drivers } { Bus Drivers }

View File

@ -57,6 +57,7 @@ var
procedure init; procedure init;
function kalloc(size : uint32) : void; function kalloc(size : uint32) : void;
function kalloc(size : uint32; isPersistent : boolean) : void;
function klalloc(size : uint32) : void; function klalloc(size : uint32) : void;
procedure klfree(size : uint32); //Todo ??? Profit? procedure klfree(size : uint32); //Todo ??? Profit?
function kpalloc(address : uint32) : void; function kpalloc(address : uint32) : void;
@ -217,6 +218,11 @@ begin
//pop_trace; //pop_trace;
end; end;
function kalloc(size : uint32; isPersistent : boolean) : void;
begin
kalloc:= kalloc(size);
end;
procedure kfree(area : void); procedure kfree(area : void);
var var
hp : PHeapPage; hp : PHeapPage;