feature (AHCI): implemented ahci controllers and ahci controller device enumeration
This commit is contained in:
parent
62bbc52205
commit
091220ac71
|
@ -4,6 +4,31 @@
|
|||
#define NOXOS_AHCI_H
|
||||
|
||||
#include "utils/stdtypes.h"
|
||||
#include "drivers/pci.h"
|
||||
|
||||
#define SATA_SIG_ATA 0x00000101
|
||||
#define SATA_SIG_ATAPI 0xEB140101
|
||||
#define SATA_SIG_SEMB 0xC33C0101
|
||||
#define SATA_SIG_PORT_MULTIPLIER 0x96690101
|
||||
|
||||
#define ATA_DEVICE_BUSY 0x80
|
||||
#define ATA_DEVICE_DRQ 0x08
|
||||
#define ATA_CMD_READ_DMA_EX 0x25
|
||||
#define ATA_CMD_WRITE_DMA_EX 0x35
|
||||
|
||||
#define HBA_PX_IS_TFES (1 << 30)
|
||||
#define HBA_PORT_DEVICE_PRESENT 0x03
|
||||
#define HBA_PORT_IPM_ACTIVE 0x01
|
||||
|
||||
typedef enum {
|
||||
AHCI_DEVICE_NONE,
|
||||
AHCI_DEVICE_SATA,
|
||||
AHCI_DEVICE_SEMB,
|
||||
AHCI_DEVICE_PORT_MULTIPLIER,
|
||||
AHCI_DEVICE_SATAPI,
|
||||
|
||||
AHCI_DEVICE_TYPE_END_OF_ENUM
|
||||
} ahci_device_type_E;
|
||||
|
||||
typedef enum {
|
||||
AHCI_FIS_REGISTER_HOST_TO_DEVICE = 0x27, // host --> device
|
||||
|
@ -105,6 +130,64 @@ typedef struct {
|
|||
uint32_t reserved_3;
|
||||
} ahci_fis_dma_setup_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t command_list_base;
|
||||
uint32_t command_list_base_upper;
|
||||
uint32_t fis_base_address;
|
||||
uint32_t fis_base_address_upper;
|
||||
uint32_t interrupt_status;
|
||||
uint32_t interrupt_enable;
|
||||
uint32_t command_status;
|
||||
uint32_t reserved_0;
|
||||
uint32_t task_file_data;
|
||||
uint32_t signature;
|
||||
uint32_t sata_status;
|
||||
uint32_t sata_control;
|
||||
uint32_t sata_error;
|
||||
uint32_t sata_active;
|
||||
uint32_t command_issue;
|
||||
uint32_t sata_notification;
|
||||
uint32_t fis_switch_control;
|
||||
uint32_t reserved_1 [11];
|
||||
uint32_t vendor [4];
|
||||
} ahci_hba_port_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t host_capability;
|
||||
uint32_t global_host_control;
|
||||
uint32_t interrupt_status;
|
||||
uint32_t ports_implemented;
|
||||
uint32_t version;
|
||||
uint32_t ccc_control;
|
||||
uint32_t ccc_ports;
|
||||
uint32_t enclosure_management_location;
|
||||
uint32_t enclosure_management_control;
|
||||
uint32_t host_capabilities_extended;
|
||||
uint32_t bios_handoff_control_status;
|
||||
uint8_t reserved_0 [0x74];
|
||||
uint8_t vendor [0x60];
|
||||
ahci_hba_port_T ports [1];
|
||||
} ahci_hba_memory_T;
|
||||
|
||||
typedef struct {
|
||||
ahci_hba_port_T* hba_port;
|
||||
ahci_device_type_E type;
|
||||
uint8_t* buffer;
|
||||
uint8_t id;
|
||||
} ahci_port_T;
|
||||
|
||||
typedef struct {
|
||||
ahci_port_T ports [32];
|
||||
int num_ports;
|
||||
pci_device_T* pci_device;
|
||||
ahci_hba_memory_T* abar;
|
||||
} ahci_controller_T;
|
||||
|
||||
ahci_controller_T* ahci_controller_alloc (pci_device_T* pci_device);
|
||||
void ahci_controller_destruct (ahci_controller_T* controller);
|
||||
void ahci_port_configure (ahci_port_T* port);
|
||||
ahci_device_type_E ahci_port_get_type (ahci_hba_port_T* port);
|
||||
|
||||
extern string_t g_ahci_device_type_strings[AHCI_DEVICE_TYPE_END_OF_ENUM];
|
||||
|
||||
#endif //NOXOS_AHCI_H
|
||||
|
|
|
@ -233,6 +233,7 @@ typedef struct {
|
|||
typedef struct pci_device_T pci_device_T;
|
||||
struct pci_device_T {
|
||||
pci_device_header_T* header;
|
||||
void* specific;
|
||||
pci_device_T* prev;
|
||||
pci_device_T* next;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,74 @@
|
|||
// This file is part of noxos and licensed under the MIT open source license
|
||||
|
||||
#include "drivers/ahci.h"
|
||||
#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;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "drivers/pci.h"
|
||||
#include "drivers/acpi/acpi.h"
|
||||
#include "drivers/acpi/mcfg.h"
|
||||
#include "drivers/ahci.h"
|
||||
#include "mm/page_map.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/memory.h"
|
||||
|
@ -310,6 +311,20 @@ void pci_manager_add_device(pci_device_header_T* header) {
|
|||
if (device->next != NULL) {
|
||||
device->next->prev = device;
|
||||
}
|
||||
|
||||
// init controller
|
||||
switch (header->main_class) {
|
||||
case PCI_CLASS_MASS_STORAGE_CONTROLLER: {
|
||||
switch (header->subclass) {
|
||||
case PCI_SUBCLASS_SERIAL_ATA_CONTROLLER: {
|
||||
if (header->progif != 0x01) break;
|
||||
device->specific = ahci_controller_alloc(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pci_manager_remove_device(pci_device_T* device) {
|
||||
|
@ -320,6 +335,20 @@ void pci_manager_remove_device(pci_device_T* device) {
|
|||
device->next->prev = device->prev;
|
||||
}
|
||||
|
||||
// destruct controller
|
||||
switch (device->header->main_class) {
|
||||
case PCI_CLASS_MASS_STORAGE_CONTROLLER: {
|
||||
switch (device->header->subclass) {
|
||||
case PCI_SUBCLASS_SERIAL_ATA_CONTROLLER: {
|
||||
if (device->header->progif != 0x01) break;
|
||||
ahci_controller_destruct(device->specific);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memory_free(device);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue