ahci progress
This commit is contained in:
parent
b2ecbe58da
commit
6a3ebf1387
@ -4,4 +4,4 @@ echo "======================="
|
||||
echo " "
|
||||
echo "Compiling FPC Sources..."
|
||||
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
|
@ -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;
|
@ -34,10 +34,11 @@ uses
|
||||
lists;
|
||||
|
||||
var
|
||||
ahciControllers : PDLList;
|
||||
ahciControllers : PDList;
|
||||
page_base : puint32;
|
||||
|
||||
procedure init();
|
||||
procedure load();
|
||||
function load(ptr : void) : boolean;
|
||||
|
||||
implementation
|
||||
|
||||
@ -57,19 +58,117 @@ begin
|
||||
//TODO check IDE devices in ide for sata devices
|
||||
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);
|
||||
var
|
||||
i : uint32;
|
||||
port : PHBA_Port;
|
||||
device : PAHCI_Device;
|
||||
cmd_list_base : puint32;
|
||||
fis_base : puint32;
|
||||
cmd_table_base : puint32;
|
||||
cmd_header : PHBA_CMD_HEADER;
|
||||
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;
|
||||
|
||||
procedure load(ptr : void);
|
||||
start_port(port);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
// 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
|
||||
device : PPCI_Device;
|
||||
controller : PAHCI_Controller;
|
||||
i : uint32;
|
||||
base : PHBA_Memory;
|
||||
cmd_list_base : puint32;
|
||||
fis_base : puint32;
|
||||
cmd_table_base : puint32;
|
||||
begin
|
||||
console.writestringln('AHCI: initilizing a new controller');
|
||||
|
||||
@ -80,14 +179,23 @@ begin
|
||||
|
||||
device := PPCI_Device(ptr);
|
||||
|
||||
controller := DL_Add(ahciControllers);
|
||||
controller^.device := device;
|
||||
controller := PAHCI_Controller(DL_Add(ahciControllers));
|
||||
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;
|
||||
|
||||
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
|
||||
base^.ghc := base^.ghc or AHCI_CONTROLLER_MODE;
|
||||
base^.global_ctrl := base^.global_ctrl or AHCI_CONTROLLER_MODE;
|
||||
|
||||
//clear any pending interrupts
|
||||
base^.int_status := $FFFFFFFF;
|
||||
@ -95,6 +203,10 @@ begin
|
||||
|
||||
|
||||
|
||||
check_ports(controller);
|
||||
|
||||
|
||||
|
||||
|
||||
// console.writestringln('AHCI: initilizing a new controller');
|
||||
// ahciControllers[ahciControllerCount] := ptr;
|
||||
@ -109,4 +221,5 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
@ -26,11 +26,18 @@ uses
|
||||
drivermanagement,
|
||||
lmemorymanager,
|
||||
console,
|
||||
vmemorymanager;
|
||||
vmemorymanager,
|
||||
idetypes,
|
||||
lists;
|
||||
|
||||
const
|
||||
AHCI_CONTROLLER_MODE = $80000000;
|
||||
|
||||
CMD_LIST_ALIGN = 1024;
|
||||
CMD_TBL_ALIGN = 128;
|
||||
|
||||
NUM_CMD_ENTRIES = 32;
|
||||
|
||||
//device type signatures
|
||||
SATA_SIG_ATA = $00000101;
|
||||
SATA_SIG_ATAPI = $EB140101;
|
||||
@ -75,17 +82,19 @@ type
|
||||
rsv1: array[0..10] of uint32;
|
||||
end;
|
||||
|
||||
PHBA_Port = ^THBA_Port;
|
||||
|
||||
{
|
||||
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.
|
||||
This structure is used to access the AHCI's memory-mapped registers.
|
||||
The AHCI'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
|
||||
ports_implimented: uint32;// Ports Implemented
|
||||
version: uint32; // Version
|
||||
ccc_control: uint32; // Command Completion Coalescing Control
|
||||
ccc_ports: uint32; // Command Completion Coalescing Ports
|
||||
@ -93,7 +102,7 @@ type
|
||||
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;
|
||||
rsv0: array[0..$210] of boolean;
|
||||
ports: array[0..31] of THBA_Port;
|
||||
end;
|
||||
|
||||
@ -102,26 +111,26 @@ type
|
||||
{
|
||||
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.
|
||||
memory-mapped registers.
|
||||
}
|
||||
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;
|
||||
dsfis: array[0..$1F] of uint32; // DMA Setup FIS
|
||||
rsv0: array[0..$1F] of uint32;
|
||||
psfis: array[0..$1F] of uint32; // PIO Setup FIS
|
||||
rsv1: array[0..$1F] of uint32;
|
||||
rfis: array[0..$1F] of uint32; // D2H Register FIS
|
||||
rsv2: array[0..$1F] of uint32;
|
||||
sdbfis: array[0..$F] of uint32; // Set Device Bits FIS
|
||||
ufis: array[0..$1F] of uint32; // Unknown FIS
|
||||
rsv3: array[0..$67] of uint32;
|
||||
end;
|
||||
|
||||
PHBA_FIS = ^THBA_FIS;
|
||||
|
||||
{
|
||||
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.
|
||||
registers.
|
||||
}
|
||||
THBA_CMD_HEADER = bitpacked record
|
||||
cmd_fis_length: uint8; // Command FIS Length
|
||||
@ -139,6 +148,8 @@ type
|
||||
rsv0: array[0..4] of uint32;
|
||||
end;
|
||||
|
||||
PHBA_CMD_HEADER = ^THBA_CMD_HEADER;
|
||||
|
||||
{
|
||||
AHCI Host Bus Adapter (HBA) Command Table Interface
|
||||
This structure is used to access the AHCI HBA's Command Table memory-mapped
|
||||
@ -147,15 +158,19 @@ type
|
||||
}
|
||||
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;
|
||||
acmd: array[0..$1F] of uint8; // ATAPI Command
|
||||
rsv0: array[0..$30] of uint8;
|
||||
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
|
||||
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.
|
||||
registers.
|
||||
}
|
||||
THBA_PRD = bitpacked record
|
||||
dba: uint32; // Data Base Address
|
||||
@ -168,24 +183,22 @@ type
|
||||
{
|
||||
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.
|
||||
registers.
|
||||
}
|
||||
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
|
||||
prd: array[0..31] 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.
|
||||
registers.
|
||||
}
|
||||
THBA = bitpacked record
|
||||
memory: THBA_Memory; // HBA Memory
|
||||
cmd: array[0..0x7FF] of THBA_CMD; // Command List
|
||||
cmd: array[0..$7FF] of THBA_CMD; // Command List
|
||||
end;
|
||||
|
||||
PHBA = ^THBA;
|
||||
@ -204,20 +217,35 @@ type
|
||||
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
|
||||
}
|
||||
TAHCI_Controller = bitpacked record
|
||||
pci_device : PPCI_Device;
|
||||
mio: PHBA_Memory;
|
||||
devices : array[0..31] of uint8; //TODO type for devices
|
||||
ata_info : TIdentResponse;
|
||||
devices : PDList;
|
||||
end;
|
||||
|
||||
PAHCI_Controller = ^TAHCI_Controller;
|
||||
|
||||
|
||||
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
|
||||
|
||||
@ -239,23 +267,23 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_device_type_string(deive_type : TDeviceType) : string;
|
||||
begin
|
||||
case deive_type of
|
||||
SATA: begin
|
||||
get_device_type_string := 'SATA';
|
||||
end;
|
||||
ATAPI: begin
|
||||
get_device_type_string := 'ATAPI';
|
||||
end;
|
||||
SEMB: begin
|
||||
get_device_type_string := 'SEMB';
|
||||
end;
|
||||
PM: begin
|
||||
get_device_type_string := 'PM';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// function get_device_type_string(deive_type : TDeviceType) : string;
|
||||
// begin
|
||||
// case deive_type of
|
||||
// SATA: begin
|
||||
// get_device_type_string := 'SATA';
|
||||
// end;
|
||||
// ATAPI: begin
|
||||
// get_device_type_string := 'ATAPI';
|
||||
// end;
|
||||
// SEMB: begin
|
||||
// get_device_type_string := 'SEMB';
|
||||
// end;
|
||||
// PM: begin
|
||||
// get_device_type_string := 'PM';
|
||||
// end;
|
||||
// end;
|
||||
// end;
|
||||
|
||||
end.
|
||||
|
||||
|
296
src/driver/storage/AHCIold.pas
Normal file
296
src/driver/storage/AHCIold.pas
Normal 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;
|
@ -57,7 +57,8 @@ uses
|
||||
base64,
|
||||
rand,
|
||||
terminal,
|
||||
hashmap, vfs;
|
||||
hashmap, vfs,
|
||||
AHCI;
|
||||
|
||||
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
|
||||
|
||||
@ -228,7 +229,8 @@ begin
|
||||
mouse.init();
|
||||
testdriver.init();
|
||||
E1000.init();
|
||||
IDE.init();
|
||||
// IDE.init();
|
||||
AHCI.init();
|
||||
console.outputln('KERNEL', 'DEVICE DRIVERS: INIT END.');
|
||||
|
||||
{ Bus Drivers }
|
||||
|
@ -57,6 +57,7 @@ var
|
||||
|
||||
procedure init;
|
||||
function kalloc(size : uint32) : void;
|
||||
function kalloc(size : uint32; isPersistent : boolean) : void;
|
||||
function klalloc(size : uint32) : void;
|
||||
procedure klfree(size : uint32); //Todo ??? Profit?
|
||||
function kpalloc(address : uint32) : void;
|
||||
@ -217,6 +218,11 @@ begin
|
||||
//pop_trace;
|
||||
end;
|
||||
|
||||
function kalloc(size : uint32; isPersistent : boolean) : void;
|
||||
begin
|
||||
kalloc:= kalloc(size);
|
||||
end;
|
||||
|
||||
procedure kfree(area : void);
|
||||
var
|
||||
hp : PHeapPage;
|
||||
|
Loading…
x
Reference in New Issue
Block a user