Gather HBA port-specific context in a struct
This commit is contained in:
parent
f33421857a
commit
df7898d216
1 changed files with 101 additions and 345 deletions
|
|
@ -6,282 +6,24 @@
|
||||||
|
|
||||||
#include <x86_64/sata.h>
|
#include <x86_64/sata.h>
|
||||||
|
|
||||||
#if 0
|
struct port_context {
|
||||||
AHCI_CONTROLLER Sata_devices[10];
|
volatile HBA_PORT *port_mem;
|
||||||
|
struct pa alloc_pa;
|
||||||
int check_PCI_devices(AHCI_CONTROLLER *list_of_devices, int range)
|
struct pa cmd_list_pa;
|
||||||
{
|
struct pa cmd_table_pa;
|
||||||
int array_index = 0;
|
struct pa recv_fis_pa;
|
||||||
for (int bus = 0; bus < 256; bus++) {
|
struct pa buffer_pa;
|
||||||
for (int device = 0; device < 32; device++) { // Up to 32 devices per bus.
|
volatile uint8_t *alloc_ptr;
|
||||||
for (int function = 0; function < 8; function++) { // Up to 8 functions per device.
|
volatile HBA_CMD_HEADER *cmd_list_ptr;
|
||||||
// --- Read the common PCI header fields ---
|
volatile HBA_CMD_TBL *cmd_table_ptr;
|
||||||
uint16_t bdf_device = pci_bdf_make(bus, device, function);
|
volatile uint8_t *recv_fis_ptr;
|
||||||
// Offset 0x00: Vendor and Device IDs.
|
volatile uint8_t *buffer_ptr;
|
||||||
uint32_t id_val = pci_config_read_u32(bdf_device, 0x00);
|
Timer timer;
|
||||||
uint16_t vendor_id = id_val & 0xFFFF;
|
};
|
||||||
if (vendor_id == 0xFFFF) { // Device not present.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uint16_t device_id = (id_val >> 16) & 0xFFFF;
|
|
||||||
|
|
||||||
// Offset 0x04: Command (lower 16 bits) and Status (upper 16
|
|
||||||
// bits).
|
|
||||||
uint32_t cmd_status = pci_config_read_u32(bdf_device, 0x04);
|
|
||||||
uint16_t command = cmd_status & 0xFFFF;
|
|
||||||
uint16_t status = (cmd_status >> 16) & 0xFFFF;
|
|
||||||
|
|
||||||
// Offset 0x08: Revision ID and Class Codes.
|
|
||||||
// The 32-bit value at 0x08 has:
|
|
||||||
// Bits 0-7: Revision ID,
|
|
||||||
// Bits 8-15: Programming Interface,
|
|
||||||
// Bits 16-23: Subclass,
|
|
||||||
// Bits 24-31: Base Class.
|
|
||||||
uint32_t rev_class = pci_config_read_u32(bdf_device, 0x08);
|
|
||||||
uint8_t revision_id = rev_class & 0xFF;
|
|
||||||
uint8_t prog_if = (rev_class >> 8) & 0xFF;
|
|
||||||
uint8_t subclass = (rev_class >> 16) & 0xFF;
|
|
||||||
uint8_t base_class = (rev_class >> 24) & 0xFF;
|
|
||||||
|
|
||||||
// Check for AHCI SATA Controller:
|
|
||||||
// Base Class 0x01 (Mass Storage),// Macros for the Global
|
|
||||||
// Host Control (GHC) register bits. Subclass 0x06 (SATA),
|
|
||||||
// Programming Interface 0x01 (AHCI).
|
|
||||||
if (!(base_class == 0x01 && subclass == 0x06 && prog_if == 0x01)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset 0x0C: Contains four 8-bit fields.
|
|
||||||
// Byte 0: Cache Line Size
|
|
||||||
// Byte 1: Master Latency Timer
|
|
||||||
// Byte 2: Header Type
|
|
||||||
// Byte 3: BIST
|
|
||||||
uint32_t misc = pci_config_read_u32(bdf_device, 0x0C);
|
|
||||||
uint8_t cache_line_size = misc & 0xFF;
|
|
||||||
uint8_t master_latency_timer = (misc >> 8) & 0xFF;
|
|
||||||
uint8_t header_type = (misc >> 16) & 0xFF;
|
|
||||||
uint8_t bist = (misc >> 24) & 0xFF;
|
|
||||||
|
|
||||||
// Offsets 0x10 - 0x23: BAR0 - BAR4.
|
|
||||||
uint32_t bars[5];
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
bars[i] = pci_config_read_u32(bdf_device, 0x10 + (i * 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset 0x24: AHCI BAR (BAR5); mask lower nibble.
|
|
||||||
uint32_t abar = pci_config_read_u32(bdf_device,
|
|
||||||
0x24); // Macros for the Global Host
|
|
||||||
// Control (GHC) register bits.
|
|
||||||
|
|
||||||
// Offset 0x28: Reserved.
|
|
||||||
uint32_t reserved0 = pci_config_read_u32(bdf_device, 0x28);
|
|
||||||
|
|
||||||
// Offsets 0x2C - 0x2F: Subsystem Identifiers.
|
|
||||||
uint32_t subsys = pci_config_read_u32(bdf_device, 0x2C);
|
|
||||||
uint16_t subsystem_vendor_id = subsys & 0xFFFF;
|
|
||||||
uint16_t subsystem_id = (subsys >> 16) & 0xFFFF;
|
|
||||||
|
|
||||||
// Offset 0x30: Expansion ROM Base Address.
|
|
||||||
uint32_t expansion_rom_base = pci_config_read_u32(bdf_device, 0x30);
|
|
||||||
|
|
||||||
// Offset 0x34: Capabilities Pointer (a single byte).
|
|
||||||
uint32_t cap_val = pci_config_read_u32(bdf_device, 0x34);
|
|
||||||
uint8_t cap_ptr = cap_val & 0xFF;
|
|
||||||
|
|
||||||
// Offsets 0x35 - 0x3B: Reserved bytes.
|
|
||||||
// For simplicity, we initialize these to zero.
|
|
||||||
uint8_t reserved1[7] = {0, 0, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
// Offset 0x3C - 0x3F: Interrupt Information.
|
|
||||||
// Byte 0: Interrupt Line
|
|
||||||
// Byte 1: Interrupt Pin
|
|
||||||
// Byte 2: Min Grant
|
|
||||||
// Byte 3: Max Latency
|
|
||||||
uint32_t intr = pci_config_read_u32(bdf_device, 0x3C);
|
|
||||||
uint8_t interrupt_line = intr & 0xFF;
|
|
||||||
uint8_t interrupt_pin = (intr >> 8) & 0xFF;
|
|
||||||
uint8_t min_grant = (intr >> 16) & 0xFF;
|
|
||||||
uint8_t max_latency = (intr >> 24) & 0xFF;
|
|
||||||
|
|
||||||
// --- Populate the SATA_DEVICE structure --- Add only if Sata
|
|
||||||
// device
|
|
||||||
if (array_index < range && subclass == 0x06) {
|
|
||||||
AHCI_CONTROLLER dev;
|
|
||||||
dev.vendor_id = vendor_id;
|
|
||||||
dev.device_id = device_id;
|
|
||||||
dev.command = command;
|
|
||||||
dev.status = status;
|
|
||||||
dev.revision_id = revision_id;
|
|
||||||
dev.class_code[0] = prog_if; // Programming Interface.
|
|
||||||
dev.class_code[1] = subclass; // Subclass. if Subclass =
|
|
||||||
// 06h then Sata device
|
|
||||||
dev.class_code[2] = base_class; // Base Class.
|
|
||||||
dev.cache_line_size = cache_line_size;
|
|
||||||
dev.master_latency_timer = master_latency_timer;
|
|
||||||
dev.header_type = header_type;
|
|
||||||
dev.bist = bist;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
dev.bars[i] = bars[i];
|
|
||||||
}
|
|
||||||
dev.abar = abar;
|
|
||||||
dev.reserved0 = reserved0;
|
|
||||||
dev.subsystem_vendor_id = subsystem_vendor_id;
|
|
||||||
dev.subsystem_id = subsystem_id;
|
|
||||||
dev.expansion_rom_base = expansion_rom_base;
|
|
||||||
dev.cap_ptr = cap_ptr;
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
dev.reserved1[i] = reserved1[i];
|
|
||||||
}
|
|
||||||
dev.interrupt_line = interrupt_line;
|
|
||||||
dev.interrupt_pin = interrupt_pin;
|
|
||||||
dev.min_grant = min_grant;
|
|
||||||
dev.max_latency = max_latency;
|
|
||||||
dev.bdf = bdf_device;
|
|
||||||
list_of_devices[array_index++] = dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void map_HBA_memory(AHCI_CONTROLLER controller)
|
|
||||||
{
|
|
||||||
// Setup Stuff
|
|
||||||
controller.virtual_HBA_address = HBA_pointer(controller);
|
|
||||||
update_PCI_BUS(controller);
|
|
||||||
reset_controller(controller);
|
|
||||||
activate_SATA_mode(controller);
|
|
||||||
scan_ahci_ports(controller.virtual_HBA_address);
|
|
||||||
update_PCI_BUS(controller);
|
|
||||||
|
|
||||||
// Allocate Memory for Command List
|
|
||||||
struct ppn page_number_command_list;
|
|
||||||
struct ram_buffer_requirements buffer_requirements = {0};
|
|
||||||
buffer_requirements.size = 0b1000000;
|
|
||||||
bool allocation_success = ram_alloc_buffer(&page_number_command_list, buffer_requirements);
|
|
||||||
struct pa phys_page = pa_from_ppn(page_number_command_list);
|
|
||||||
uint64_t value = pa_to_value(phys_page);
|
|
||||||
HBA_CMD_HEADER *cmd_list = pa_to_pointer(phys_page);
|
|
||||||
|
|
||||||
// Allocate Memeory for a single Command Table
|
|
||||||
struct ppn page_number_command_table;
|
|
||||||
bool allocation_success_command_table = ram_alloc_buffer(&page_number_command_table, buffer_requirements);
|
|
||||||
struct pa phys_page_command_table = pa_from_ppn(page_number_command_table);
|
|
||||||
uint64_t value_command_tbl = pa_to_value(phys_page_command_table);
|
|
||||||
HBA_CMD_TBL *cmd_tbl = pa_to_pointer(phys_page_command_table);
|
|
||||||
|
|
||||||
// Allocate Memory for recived FIS Strcture
|
|
||||||
struct ppn page_number_fb;
|
|
||||||
struct ram_buffer_requirements buffer_requirements_fis_receive = {0};
|
|
||||||
buffer_requirements_fis_receive.size = 0x1; // TODO
|
|
||||||
bool allocation_success_fb = ram_alloc_buffer(&page_number_fb, buffer_requirements_fis_receive);
|
|
||||||
struct pa phys_page_fb = pa_from_ppn(page_number_fb);
|
|
||||||
uint64_t value_fb = pa_to_value(phys_page_fb);
|
|
||||||
HBA_FIS *fb = pa_to_pointer(phys_page_fb);
|
|
||||||
|
|
||||||
// Set bits for command List
|
|
||||||
cmd_list[0] = (HBA_CMD_HEADER){0};
|
|
||||||
cmd_list[0].w = 0;
|
|
||||||
cmd_list[0].a = 0;
|
|
||||||
cmd_list[0].c = 1;
|
|
||||||
cmd_list[0].cfl = 4;
|
|
||||||
cmd_list[0].p = 0;
|
|
||||||
cmd_list[0].prdbc = 0;
|
|
||||||
cmd_list[0].prdtl = 0;
|
|
||||||
cmd_list[0].ctba = (uint32_t)(value_command_tbl & 0xFFFFFFFF);
|
|
||||||
cmd_list[0].ctbau = (uint32_t)(value_command_tbl >> 32);
|
|
||||||
|
|
||||||
// Set FIS for sending
|
|
||||||
FIS_REG_H2D fis_identify = { 0 };
|
|
||||||
fis_identify.fis_type = FIS_TYPE_REG_H2D;
|
|
||||||
fis_identify.command = 0xEC;
|
|
||||||
fis_identify.device = 0;
|
|
||||||
fis_identify.c = 1;
|
|
||||||
|
|
||||||
// Setting up Receive FIS
|
|
||||||
controller.virtual_HBA_address->ports[0].fb = (uint32_t)(value_fb & 0xFFFFFFFF);
|
|
||||||
controller.virtual_HBA_address->ports[0].fbu = (uint32_t)(value_fb >> 32);
|
|
||||||
|
|
||||||
*((FIS_REG_H2D *)cmd_tbl->cfis) = fis_identify;
|
|
||||||
|
|
||||||
// stolen from OSDEV wiki idfk
|
|
||||||
# define HBA_PxCMD_ST 0x0001
|
|
||||||
# define HBA_PxCMD_FRE 0x0010
|
|
||||||
# define HBA_PxCMD_FR 0x4000
|
|
||||||
# define HBA_PxCMD_CR 0x8000
|
|
||||||
|
|
||||||
// Start Command
|
|
||||||
controller.virtual_HBA_address->ports[0].cmd |= HBA_PxCMD_FRE;
|
|
||||||
controller.virtual_HBA_address->ports[0].cmd |= HBA_PxCMD_ST;
|
|
||||||
|
|
||||||
// FIS RECIVE ENABLE SETZEN
|
|
||||||
// TODO:
|
|
||||||
// Currently Ci register changes
|
|
||||||
volatile HBA_PORT *port = &controller.virtual_HBA_address->ports[0];
|
|
||||||
port->clb = value;
|
|
||||||
port->cmd &= ~1;
|
|
||||||
port->ci |= 0x01 << 0;
|
|
||||||
port->cmd |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
HBA_MEM *HBA_pointer(AHCI_CONTROLLER controller)
|
|
||||||
{
|
|
||||||
struct pa pa = pa_from_value(controller.abar);
|
|
||||||
return pa_to_pointer(pa);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scan_ahci_ports(volatile HBA_MEM *hba)
|
|
||||||
{
|
|
||||||
uint32_t pi = hba->pi;
|
|
||||||
|
|
||||||
volatile HBA_PORT *port = &hba->ports[0];
|
|
||||||
uint32_t ssts = port->ssts;
|
|
||||||
uint32_t det = ssts & 0x0F; // [3:0]
|
|
||||||
uint32_t ipm = (ssts >> 8) & 0x0F; // [11:8]
|
|
||||||
printf("Port %d: (DET=0x%x, IPM=0x%x)\n", 0, det, ipm);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_PCI_BUS(AHCI_CONTROLLER controller)
|
|
||||||
{
|
|
||||||
uint32_t command = pci_config_read_u32(controller.bdf, 0x04);
|
|
||||||
printf("Current Command Register %x\n", command);
|
|
||||||
command |= 0x06;
|
|
||||||
pci_config_write_u32(controller.bdf, 0x04, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define HBA_GHC_HR (1 << 0) // Host reset
|
|
||||||
void reset_controller(AHCI_CONTROLLER controller)
|
|
||||||
{
|
|
||||||
controller.virtual_HBA_address->ghc |= HBA_GHC_HR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define HBA_GHC_AE (1 << 2)
|
|
||||||
void activate_SATA_mode(AHCI_CONTROLLER controller)
|
|
||||||
{
|
|
||||||
controller.virtual_HBA_address->ghc |= HBA_GHC_AE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int allocate_data_entry()
|
|
||||||
{
|
|
||||||
struct ppn page_number;
|
|
||||||
struct ram_buffer_requirements buffer_requirements = {0};
|
|
||||||
buffer_requirements.size = 0x1000;
|
|
||||||
bool allocation_success = ram_alloc_buffer(&page_number, buffer_requirements);
|
|
||||||
return allocation_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int allocate_list(AHCI_CONTROLLER controller) {}
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static uint16_t hba_bdf;
|
static uint16_t hba_bdf;
|
||||||
static volatile HBA_MEM *hba_mem;
|
static volatile HBA_MEM *hba_mem;
|
||||||
static volatile HBA_PORT *hba_ports[32];
|
static struct port_context ports[32];
|
||||||
static Timer hba_port_timers[32];
|
|
||||||
static volatile uint8_t *hba_port_recv_fis[32];
|
|
||||||
static volatile uint8_t *hba_port_buffers[32];
|
|
||||||
|
|
||||||
void find_ahci_controllers(void)
|
void find_ahci_controllers(void)
|
||||||
{
|
{
|
||||||
|
|
@ -294,12 +36,15 @@ void find_ahci_controllers(void)
|
||||||
|
|
||||||
void sata_revisit_port(Timer *timer)
|
void sata_revisit_port(Timer *timer)
|
||||||
{
|
{
|
||||||
int port_num = timer - hba_port_timers;
|
struct port_context *port = container_of(timer, struct port_context, timer);
|
||||||
printf("Port %d command bits: %x\n", port_num, hba_ports[port_num]->ci);
|
int port_num = port - ports;
|
||||||
|
printf("Port %d command bits: %x\n", port_num, port->port_mem->ci);
|
||||||
for (int r = 0; r < 1024 / 16; r++) {
|
for (int r = 0; r < 1024 / 16; r++) {
|
||||||
for (int c = 0; c < 16; c++) {
|
for (int c = 0; c < 16; c++) {
|
||||||
int i = r * 16 + c;
|
int i = r * 16 + c;
|
||||||
printf("%x%x ", hba_port_buffers[port_num][i] >> 4, hba_port_buffers[port_num][i] & 0xF);
|
printf("%x%x ",
|
||||||
|
port->buffer_ptr[i] >> 4,
|
||||||
|
port->buffer_ptr[i] & 0xF);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
@ -307,86 +52,91 @@ void sata_revisit_port(Timer *timer)
|
||||||
|
|
||||||
void sata_init_port(int port_num)
|
void sata_init_port(int port_num)
|
||||||
{
|
{
|
||||||
printf("Found SATA Port %d\n", port_num);
|
struct port_context *port = &ports[port_num];
|
||||||
|
|
||||||
// Allocate a buffer of physical memory
|
printf("Found SATA Port %d\n", port_num);
|
||||||
struct ram_buffer_requirements alloc_reqs = { 0 };
|
|
||||||
alloc_reqs.size = 1024 + 1024 + 256 + 256;
|
|
||||||
struct ppn alloc_ppn;
|
|
||||||
bool alloc_ok = ram_alloc_buffer(&alloc_ppn, alloc_reqs);
|
|
||||||
ASSERT(alloc_ok);
|
|
||||||
struct pa alloc_pa = pa_from_ppn(alloc_ppn);
|
|
||||||
|
|
||||||
// Cut up buffer into separate structures
|
// Allocate a buffer of physical memory
|
||||||
struct pa cmd_list_pa = alloc_pa;
|
struct ram_buffer_requirements alloc_reqs = { 0 };
|
||||||
alloc_pa = pa_from_value(pa_to_value(alloc_pa) + 1024);
|
alloc_reqs.size = 1024 + 1024 + 256 + 256;
|
||||||
struct pa buffer_pa = alloc_pa;
|
struct ppn alloc_ppn;
|
||||||
alloc_pa = pa_from_value(pa_to_value(alloc_pa) + 1024);
|
bool alloc_ok = ram_alloc_buffer(&alloc_ppn, alloc_reqs);
|
||||||
struct pa cmd_table_pa = alloc_pa;
|
ASSERT(alloc_ok);
|
||||||
alloc_pa = pa_from_value(pa_to_value(alloc_pa) + 256);
|
port->alloc_pa = pa_from_ppn(alloc_ppn);
|
||||||
struct pa recv_fis_pa = alloc_pa;
|
|
||||||
alloc_pa = pa_from_value(pa_to_value(alloc_pa) + 256);
|
|
||||||
|
|
||||||
hba_port_buffers[port_num] = pa_to_pointer(buffer_pa);
|
// Cut up buffer into separate structures
|
||||||
memset((void *)hba_port_buffers[port_num], 0, 1024);
|
port->cmd_list_pa = port->alloc_pa;
|
||||||
|
port->alloc_pa = pa_from_value(pa_to_value(port->alloc_pa) + 1024);
|
||||||
|
port->buffer_pa = port->alloc_pa;
|
||||||
|
port->alloc_pa = pa_from_value(pa_to_value(port->alloc_pa) + 1024);
|
||||||
|
port->cmd_table_pa = port->alloc_pa;
|
||||||
|
port->alloc_pa = pa_from_value(pa_to_value(port->alloc_pa) + 256);
|
||||||
|
port->recv_fis_pa = port->alloc_pa;
|
||||||
|
port->alloc_pa = pa_from_value(pa_to_value(port->alloc_pa) + 256);
|
||||||
|
|
||||||
// TODO make sure port is in idle state
|
// Get pointers to the contents of the structures
|
||||||
|
port->cmd_list_ptr = pa_to_pointer(port->cmd_list_pa);
|
||||||
// TODO determine how many command slots the HBA supports (CAP.NCS)
|
port->cmd_table_ptr = pa_to_pointer(port->cmd_table_pa);
|
||||||
|
port->recv_fis_ptr = pa_to_pointer(port->recv_fis_pa);
|
||||||
|
port->buffer_ptr = pa_to_pointer(port->buffer_pa);
|
||||||
|
memset((void *)port->recv_fis_ptr, 0, 256);
|
||||||
|
memset((void *)port->buffer_ptr, 0, 1024);
|
||||||
|
|
||||||
// Register structures with the HBA port
|
// TODO make sure port is in idle state
|
||||||
hba_ports[port_num]->clb = pa_to_value(cmd_list_pa);
|
|
||||||
hba_ports[port_num]->fb = pa_to_value(recv_fis_pa);
|
// TODO determine how many command slots the HBA supports (CAP.NCS)
|
||||||
hba_ports[port_num]->cmd |= PORT_CMD_FIS_RECV_ENABLE;
|
|
||||||
|
|
||||||
// TODO clear the PxSERR register
|
// Register structures with the HBA port
|
||||||
hba_ports[port_num]->serr |= (1 << 9) | (1 << 10) | (1 << 11);
|
port->port_mem->clb = pa_to_value(port->cmd_list_pa);
|
||||||
|
port->port_mem->fb = pa_to_value(port->recv_fis_pa);
|
||||||
|
port->port_mem->cmd |= PORT_CMD_FIS_RECV_ENABLE;
|
||||||
|
|
||||||
// TODO Clear PxIS, then IS.IPS, then:
|
// TODO clear the PxSERR register
|
||||||
// TODO Set PxIE register with appropriate enables
|
port->port_mem->serr |= (1 << 9) | (1 << 10) | (1 << 11);
|
||||||
// TODO Also set GHC.IE to 1
|
|
||||||
|
|
||||||
// Get pointers to the contents of the structures
|
// TODO Clear PxIS, then IS.IPS, then:
|
||||||
volatile HBA_CMD_HEADER *cmd_list = pa_to_pointer(cmd_list_pa);
|
// TODO Set PxIE register with appropriate enables
|
||||||
volatile HBA_CMD_TBL *cmd_table = pa_to_pointer(cmd_table_pa);
|
// TODO Also set GHC.IE to 1
|
||||||
volatile void *recv_fis = pa_to_pointer(recv_fis_pa);
|
}
|
||||||
hba_port_recv_fis[port_num] = recv_fis;
|
|
||||||
memset((void *)recv_fis, 0, 256);
|
|
||||||
|
|
||||||
// Fill out the command table
|
void sata_submit_command(int port_num)
|
||||||
FIS_REG_H2D *fis_identify = (void *)cmd_table;
|
{
|
||||||
fis_identify->fis_type = FIS_TYPE_REG_H2D;
|
struct port_context *port = &ports[port_num];
|
||||||
//fis_identify->command = ATA_CMD_IDENTIFY;
|
|
||||||
fis_identify->command = ATA_CMD_READ_DMA_EXT;
|
|
||||||
fis_identify->device = (1 << 6);
|
|
||||||
fis_identify->lba0 = 0;
|
|
||||||
fis_identify->lba1 = 0;
|
|
||||||
fis_identify->lba2 = 0;
|
|
||||||
fis_identify->lba3 = 0;
|
|
||||||
fis_identify->lba4 = 0;
|
|
||||||
fis_identify->lba5 = 0;
|
|
||||||
fis_identify->countl = 1;
|
|
||||||
fis_identify->counth = 0;
|
|
||||||
fis_identify->c = 1;
|
|
||||||
cmd_table->prdt_entry[0].dba = pa_to_value(buffer_pa);
|
|
||||||
cmd_table->prdt_entry[0].dbc = 512 - 1;
|
|
||||||
|
|
||||||
// Fill out the command header
|
// Fill out the command table
|
||||||
memset((void *)&cmd_list[0], 0, sizeof cmd_list[0]);
|
volatile FIS_REG_H2D *fis_identify = (volatile void *)port->cmd_table_ptr;
|
||||||
cmd_list[0].clr_busy_on_ok = 1;
|
fis_identify->fis_type = FIS_TYPE_REG_H2D;
|
||||||
cmd_list[0].cmd_fis_length = 4 + 4;
|
//fis_identify->command = ATA_CMD_IDENTIFY;
|
||||||
cmd_list[0].ctba = pa_to_value(cmd_table_pa);
|
fis_identify->command = ATA_CMD_READ_DMA_EXT;
|
||||||
cmd_list[0].prdtl = 1;
|
fis_identify->device = (1 << 6);
|
||||||
|
fis_identify->lba0 = 0;
|
||||||
|
fis_identify->lba1 = 0;
|
||||||
|
fis_identify->lba2 = 0;
|
||||||
|
fis_identify->lba3 = 0;
|
||||||
|
fis_identify->lba4 = 0;
|
||||||
|
fis_identify->lba5 = 0;
|
||||||
|
fis_identify->countl = 1;
|
||||||
|
fis_identify->counth = 0;
|
||||||
|
fis_identify->c = 1;
|
||||||
|
port->cmd_table_ptr->prdt_entry[0].dba = pa_to_value(port->buffer_pa);
|
||||||
|
port->cmd_table_ptr->prdt_entry[0].dbc = 512 - 1;
|
||||||
|
|
||||||
// Start processing commands
|
// Fill out the command header
|
||||||
hba_ports[port_num]->cmd |= PORT_CMD_START;
|
memset((void *)&port->cmd_list_ptr[0], 0, sizeof port->cmd_list_ptr[0]);
|
||||||
|
port->cmd_list_ptr[0].clr_busy_on_ok = 1;
|
||||||
|
port->cmd_list_ptr[0].cmd_fis_length = 4 + 4;
|
||||||
|
port->cmd_list_ptr[0].ctba = pa_to_value(port->cmd_table_pa);
|
||||||
|
port->cmd_list_ptr[0].prdtl = 1;
|
||||||
|
|
||||||
// Only now can be submit the command
|
// Start processing commands
|
||||||
hba_ports[port_num]->ci |= (1 << 0);
|
port->port_mem->cmd |= PORT_CMD_START;
|
||||||
|
|
||||||
Time time = time_current();
|
// Only now can be submit the command
|
||||||
time.sec += 1;
|
port->port_mem->ci |= (1 << 0);
|
||||||
timer_set_absolute(&hba_port_timers[port_num], time, sata_revisit_port);
|
|
||||||
|
Time time = time_current();
|
||||||
|
time.sec += 1;
|
||||||
|
timer_set_absolute(&port->timer, time, sata_revisit_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sata_init()
|
void sata_init()
|
||||||
|
|
@ -407,8 +157,14 @@ void sata_init()
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
if (hba_mem->pi & (1 << i)) {
|
if (hba_mem->pi & (1 << i)) {
|
||||||
hba_ports[i] = (void *)((uintptr_t)hba_mem + 0x100 + i * 0x80);
|
ports[i].port_mem = (void *)((uintptr_t)hba_mem + 0x100 + i * 0x80);
|
||||||
sata_init_port(i);
|
sata_init_port(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (hba_mem->pi & (1 << i)) {
|
||||||
|
sata_submit_command(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue