2023-04-25 22:06:36 +00:00
|
|
|
// This file is part of noxos and licensed under the MIT open source license
|
|
|
|
|
2023-04-28 17:00:43 +00:00
|
|
|
#include "drivers/ahci.h"
|
2023-05-04 11:28:55 +00:00
|
|
|
#include "utils/memory.h"
|
|
|
|
#include "utils/logger.h"
|
|
|
|
#include "mm/page_map.h"
|
|
|
|
|
|
|
|
string_t g_ahci_device_type_strings[AHCI_DEVICE_TYPE_END_OF_ENUM] = {
|
|
|
|
"None",
|
|
|
|
"SATA",
|
|
|
|
"SEMB",
|
|
|
|
"Port Multiplier",
|
|
|
|
"SATAPI"
|
|
|
|
};
|
|
|
|
|
|
|
|
ahci_controller_T* ahci_controller_alloc(pci_device_T* pci_device) {
|
|
|
|
ahci_controller_T* controller = memory_allocate(sizeof(ahci_controller_T));
|
|
|
|
|
|
|
|
controller->pci_device = pci_device;
|
|
|
|
controller->abar = (ahci_hba_memory_T*)((pci_header_0_T*)pci_device->header)->bar5;
|
|
|
|
controller->num_ports = 0;
|
|
|
|
|
|
|
|
page_map_map_memory(g_kernel_page_map, controller->abar, controller->abar, PM_FLAG_READ_WRITE);
|
|
|
|
|
|
|
|
// probe ports
|
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if ((controller->abar->ports_implemented & (1 << i)) == 0) continue;
|
|
|
|
|
|
|
|
ahci_device_type_E type = ahci_port_get_type(&controller->abar->ports[i]);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case AHCI_DEVICE_SATAPI:
|
|
|
|
case AHCI_DEVICE_SATA: {
|
|
|
|
ahci_port_T* port = &controller->ports[controller->num_ports];
|
|
|
|
port->type = type;
|
|
|
|
port->hba_port = &controller->abar->ports[i];
|
|
|
|
port->id = controller->num_ports;
|
|
|
|
|
|
|
|
controller->num_ports += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// configure ports
|
|
|
|
log(LOG_INFO, "AHCI devices:");
|
|
|
|
for (int i = 0; i < controller->num_ports; i++) {
|
|
|
|
log(LOG_INFO, " %s", g_ahci_device_type_strings[controller->ports[i].type]);
|
|
|
|
ahci_port_configure(&controller->ports[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ahci_controller_destruct(ahci_controller_T* controller) {
|
|
|
|
memory_free(controller);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ahci_port_configure(ahci_port_T* port) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ahci_device_type_E ahci_port_get_type(ahci_hba_port_T* port) {
|
|
|
|
if ((port->sata_status & 0b111) != HBA_PORT_DEVICE_PRESENT) return AHCI_DEVICE_NONE;
|
|
|
|
if (((port->sata_status >> 8) & 0b111) != HBA_PORT_IPM_ACTIVE) return AHCI_DEVICE_NONE;
|
|
|
|
|
|
|
|
switch (port->signature) {
|
|
|
|
case SATA_SIG_ATA: return AHCI_DEVICE_SATA;
|
|
|
|
case SATA_SIG_ATAPI: return AHCI_DEVICE_SATAPI;
|
|
|
|
case SATA_SIG_SEMB: return AHCI_DEVICE_SEMB;
|
|
|
|
case SATA_SIG_PORT_MULTIPLIER: return AHCI_DEVICE_PORT_MULTIPLIER;
|
|
|
|
default: return AHCI_DEVICE_NONE;
|
|
|
|
}
|
|
|
|
}
|