245 lines
8.0 KiB
C
245 lines
8.0 KiB
C
// This file is part of noxos and licensed under the MIT open source license
|
|
|
|
#ifndef NOXOS_AHCI_H
|
|
#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_PX_COMMAND_CMD_LIST_RUNNING 0x8000
|
|
#define HBA_PX_COMMAND_START 0x0001
|
|
#define HBA_PX_COMMAND_FIS_RECV_ENABLE 0x0010
|
|
#define HBA_PX_COMMAND_FIS_RECV_RUNNING 0x4000
|
|
|
|
#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
|
|
AHCI_FIS_REGISTER_DEVICE_TO_HOST = 0x34, // host <-- device
|
|
AHCI_FIS_DMA_ACTIVATE = 0x39, // host <-- device
|
|
AHCI_FIS_DMA_SETUP = 0x41, // host <--> device
|
|
AHCI_FIS_DATA = 0x46, // host <--> device
|
|
AHCI_FIS_BIST = 0x58, // host <--> device
|
|
AHCI_FIS_PIO_SETUP = 0x5F, // host <-- device
|
|
AHCI_FIS_DEVICE_BITS = 0xA1 // host <-- device
|
|
} ahci_fis_type_E;
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t port_multiplier:4;
|
|
uint8_t reserved_0:3;
|
|
uint8_t command_control_select:1;
|
|
uint8_t command;
|
|
uint8_t feature_0;
|
|
uint8_t lba_0;
|
|
uint8_t lba_1;
|
|
uint8_t lba_2;
|
|
uint8_t device;
|
|
uint8_t lba_3;
|
|
uint8_t lba_4;
|
|
uint8_t lba_5;
|
|
uint8_t feature_1;
|
|
uint8_t count_low;
|
|
uint8_t count_high;
|
|
uint8_t icc;
|
|
uint8_t control;
|
|
uint32_t reserved_1;
|
|
} ahci_fis_register_host_to_device_T;
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t port_multiplier:4;
|
|
uint8_t reserved_0:2;
|
|
uint8_t interrupt:1;
|
|
uint8_t reserved_1:1;
|
|
uint8_t status;
|
|
uint8_t error;
|
|
uint8_t lba_0;
|
|
uint8_t lba_1;
|
|
uint8_t lba_2;
|
|
uint8_t device;
|
|
uint8_t lba_3;
|
|
uint8_t lba_4;
|
|
uint8_t lba_5;
|
|
uint8_t reserved_2;
|
|
uint16_t count;
|
|
uint16_t reserved_3;
|
|
uint32_t reserved_4;
|
|
} ahci_fis_register_device_to_host_T;
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t port_multiplier:4;
|
|
uint8_t reserved_0:4;
|
|
uint16_t reserved_1;
|
|
uint32_t data; // this can be followed by more data
|
|
} ahci_fis_data_T;
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t port_multiplier:4;
|
|
uint8_t reserved_0:1;
|
|
uint8_t transfer_direction:1;
|
|
uint8_t interrupt:1;
|
|
uint8_t reserved_1:1;
|
|
uint8_t status;
|
|
uint8_t error;
|
|
uint8_t lba_0;
|
|
uint8_t lba_1;
|
|
uint8_t lba_2;
|
|
uint8_t device;
|
|
uint8_t lba_3;
|
|
uint8_t lba_4;
|
|
uint8_t lba_5;
|
|
uint8_t reserved_2;
|
|
uint16_t count;
|
|
uint8_t reserved_3;
|
|
uint8_t new_status;
|
|
uint16_t transfer_count;
|
|
uint16_t reserved_4;
|
|
} ahci_fis_pio_setup_T;
|
|
|
|
typedef struct {
|
|
uint8_t type;
|
|
uint8_t port_multiplier:4;
|
|
uint8_t reserved_0:1;
|
|
uint8_t transfer_direction:1;
|
|
uint8_t interrupt:1;
|
|
uint8_t auto_activate:1;
|
|
uint16_t reserved_1;
|
|
uint64_t dma_buffer_id;
|
|
uint32_t reserved_2;
|
|
uint32_t dma_buffer_offset;
|
|
uint32_t transfer_count;
|
|
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 {
|
|
uint8_t command_fis_length:5;
|
|
uint8_t atapi:1;
|
|
uint8_t write:1;
|
|
uint8_t prefetchable:1;
|
|
uint8_t reset:1;
|
|
uint8_t bist:1;
|
|
uint8_t clear_busy:1;
|
|
uint8_t reserved_0:1;
|
|
uint8_t port_multiplier:4;
|
|
uint16_t prdt_length;
|
|
uint32_t prdb_count;
|
|
uint32_t command_table_base_address;
|
|
uint32_t command_table_base_address_upper;
|
|
uint32_t reserved_1 [4];
|
|
} ahci_hba_command_T;
|
|
|
|
typedef struct {
|
|
uint32_t data_base_address;
|
|
uint32_t data_base_address_upper;
|
|
uint32_t reserved_0;
|
|
uint32_t byte_count:22;
|
|
uint32_t reserved_1:9;
|
|
uint32_t interrupt_on_completion:1;
|
|
} ahci_hba_prdt_entry_T;
|
|
|
|
typedef struct{
|
|
uint8_t command_fis [64];
|
|
uint8_t atapi_command [16];
|
|
uint8_t reserved [48];
|
|
ahci_hba_prdt_entry_T prdt_entry [];
|
|
} ahci_hba_command_table_T;
|
|
|
|
|
|
typedef struct {
|
|
ahci_hba_port_T* hba_port;
|
|
ahci_device_type_E type;
|
|
uint8_t* buffer;
|
|
uint8_t id;
|
|
|
|
void* cmd_list_base;
|
|
void* fis_base;
|
|
void* command_tables [32];
|
|
} 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_init (ahci_port_T* port);
|
|
void ahci_port_destruct (ahci_port_T* port);
|
|
ahci_device_type_E ahci_port_get_type (ahci_hba_port_T* port);
|
|
void ahci_port_command_stop (ahci_port_T* port);
|
|
void ahci_port_command_start (ahci_port_T* port);
|
|
bool ahci_port_read (ahci_port_T* port, uint64_t sector, uint32_t num_sectors, void* buffer_out);
|
|
bool ahci_port_write (ahci_port_T* port, uint64_t sector, uint32_t num_sectors, void* buffer_in);
|
|
|
|
|
|
extern string_t g_ahci_device_type_strings[AHCI_DEVICE_TYPE_END_OF_ENUM];
|
|
|
|
#endif //NOXOS_AHCI_H
|