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
|
#define NOXOS_AHCI_H
|
||||||
|
|
||||||
#include "utils/stdtypes.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 {
|
typedef enum {
|
||||||
AHCI_FIS_REGISTER_HOST_TO_DEVICE = 0x27, // host --> device
|
AHCI_FIS_REGISTER_HOST_TO_DEVICE = 0x27, // host --> device
|
||||||
|
@ -105,6 +130,64 @@ typedef struct {
|
||||||
uint32_t reserved_3;
|
uint32_t reserved_3;
|
||||||
} ahci_fis_dma_setup_T;
|
} 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
|
#endif //NOXOS_AHCI_H
|
||||||
|
|
|
@ -233,6 +233,7 @@ typedef struct {
|
||||||
typedef struct pci_device_T pci_device_T;
|
typedef struct pci_device_T pci_device_T;
|
||||||
struct pci_device_T {
|
struct pci_device_T {
|
||||||
pci_device_header_T* header;
|
pci_device_header_T* header;
|
||||||
|
void* specific;
|
||||||
pci_device_T* prev;
|
pci_device_T* prev;
|
||||||
pci_device_T* next;
|
pci_device_T* next;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,74 @@
|
||||||
// This file is part of noxos and licensed under the MIT open source license
|
// This file is part of noxos and licensed under the MIT open source license
|
||||||
|
|
||||||
#include "drivers/ahci.h"
|
#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/pci.h"
|
||||||
#include "drivers/acpi/acpi.h"
|
#include "drivers/acpi/acpi.h"
|
||||||
#include "drivers/acpi/mcfg.h"
|
#include "drivers/acpi/mcfg.h"
|
||||||
|
#include "drivers/ahci.h"
|
||||||
#include "mm/page_map.h"
|
#include "mm/page_map.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
|
@ -310,6 +311,20 @@ void pci_manager_add_device(pci_device_header_T* header) {
|
||||||
if (device->next != NULL) {
|
if (device->next != NULL) {
|
||||||
device->next->prev = device;
|
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) {
|
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;
|
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);
|
memory_free(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue