44 port->
cmd &= ~(1UL << 0);
48 while (timeout-- > 0) {
50 if (!(port->
cmd & (1UL << 15)))
54 log(
mod,
"Warning: CR not cleared");
57 port->
cmd &= ~(1UL << 4);
61 while (timeout-- > 0) {
63 if (!(port->
cmd & (1UL << 14)))
67 log(
mod,
"Warning: FR not cleared");
73 while (timeout-- > 0) {
74 if (!(port->
cmd & (1UL << 15)))
80 port->
cmd |= (1UL << 4);
82 port->
cmd |= (1UL << 0);
88 for (
int i = 0; i < 32; i++) {
93 log(
"AHCI",
"Cannot find free command list entry\n");
104 if (spin >= timeout_ms) {
105 log(
"AHCI",
"Port is hung (pre-issue timeout)");
113 while (spin < timeout_ms) {
114 if ((p->
ci & (1UL <<
slot)) == 0)
116 if (p->
is & (1UL << 30)) {
118 "Task file error: TFD=0x%x SERR=0x%x IS=0x%x",
125 for (
int i = 0; i < 1000; i++)
126 __asm__
volatile(
"pause");
133 if (spin >= timeout_ms) {
135 "Command timeout after %dms (CI=0x%x IS=0x%x TFD=0x%x)",
136 timeout_ms, p->
ci, p->
is, p->
tfd);
144 if (p->
is & (1UL << 30)) {
145 log(
"AHCI",
"Read disk error after completion");
152#define ATA_CMD_IDENTIFY_PACKET 0xA1
153#define ATA_CMD_IDENTIFY 0xEC
154#define ATA_CMD_WRITE_DMA_EXT 0x35
155#define ATA_CMD_READ_DMA_EXT 0x25
156#define ATA_CMD_PACKET 0xA0
157#define ATA_CMD_FLUSH_CACHE_EXT 0xEA
170 size_t bytes = (
size > 0x400000) ? 0x400000 :
size;
175 cmdtbl->prdt[
idx].i = 1;
202 ahci_cmd_tbl_t* cmdtbl = (ahci_cmd_tbl_t*) (vaddr->
cmd[freeslot]);
204 sizeof(ahci_cmd_tbl_t) + (8 - 1) *
sizeof(ahci_prdt_t));
253 cmd->w = is_write ? 1 : 0;
257 ahci_cmd_tbl_t* cmdtbl = (ahci_cmd_tbl_t*) (vaddr->
cmd[freeslot]);
259 sizeof(ahci_cmd_tbl_t) + (8 - 1) *
sizeof(ahci_prdt_t));
285 (
uint8_t) ((byte_count >> 8) & 0xFF);
311 ahci_cmd_tbl_t* cmdtbl = (ahci_cmd_tbl_t*) (vaddr->
cmd[freeslot]);
313 sizeof(ahci_cmd_tbl_t) + (8 - 1) *
sizeof(ahci_prdt_t));
361 ahci_cmd_tbl_t* cmdtbl = (ahci_cmd_tbl_t*) (vaddr->
cmd[freeslot]);
363 sizeof(ahci_cmd_tbl_t) + (
cmd->prdtl - 1) *
sizeof(ahci_prdt_t));
393 log(
mod,
"request packet found type");
415 return instance->submit_impl(dev, req);
426 auto aligned_clb_paddr = (clb_phys_addr + 1024 - 1) & (
uintptr_t)~(1024 - 1);
428 port->
clbu = (aligned_clb_paddr >> 32) & 0xFFFFFFFF;
429 port->
clb = aligned_clb_paddr & 0xFFFFFFFF;
435 auto aligned_fb_paddr = (fb_paddr + 256 - 1) & (
uintptr_t)~(256 - 1);
437 port->
fb = aligned_fb_paddr & 0xFFFFFFFF;
438 port->
fbu = (aligned_fb_paddr >> 32) & 0xFFFFFFFF;
443 for (
int j = 0; j < 32; j++) {
449 vaddr->
cmd[j] = ctba;
450 auto aligned_ctba_paddr = (ctba_paddr + 128 - 1) & (
uintptr_t)~(128 - 1);
451 cmd[j].ctba = aligned_ctba_paddr & 0xFFFFFFFF;
452 cmd[j].ctbau = (aligned_ctba_paddr >> 32) & 0xFFFFFFFF;
463 for (
uint8_t i = 0; i < 32; i++) {
464 if (ports_implemented & (1UL << i)) {
465 log(
mod,
"Port %d implemented", i);
477 while (spin++ < 50 && !present) {
485 log(
mod,
"No device on port %d", i);
496 log(
mod,
"SATA device found on port %d", i);
499 log(
mod,
"SATAPI device found on port %d", i);
503 log(
mod,
"SEMB device found on port %d", i);
506 log(
mod,
"PM device found on port %d", i);
569 if (!
dev_ || !
dev_->bar[5].address) {
570 log(
mod,
"Device BAR not found");
574 op = (ahci_op_t*)
dev_->bar[5].address;
577 op->ghc |= (1UL << 31);
580 op->ghc |= (1UL << 0);
584 while ((
op->ghc & (1UL << 0)) && timeout-- > 0) {
588 log(
mod,
"HBA reset timeout");
593 op->ghc |= (1UL << 31) | (1UL << 1);
595 log(
mod,
"AHCI reset ghc done");
597 if (
op->cap & (1UL << 31)) {
598 log(
mod,
"Support 64bit");
static AHCIModule instance
static bool is_device_present(ahci_port_t *port)
#define ATA_CMD_WRITE_DMA_EXT
#define ATA_CMD_READ_DMA_EXT
static ahci_device_type_t get_device_type(ahci_port_t *port)
static int find_cmdslot(ahci_port_t *port)
#define ATA_CMD_IDENTIFY_PACKET
int submit(struct ioforge_block_device *dev, struct ioforge_block_request *req)
static struct ahci_internal_vaddr port_vaddr[32]
int submit(struct ioforge_block_device *dev, struct ioforge_block_request *req)
#define HBA_PxSSTS_DET_MASK
#define HBA_PxSSTS_DET_ESTABLISHED
struct ioforge_pci_device * dev_
int ata_flush(ahci_port_t *p, struct ahci_internal_vaddr *vaddr, struct ioforge_block_request *req)
void port_power_on(ahci_port_t *port)
void port_power_off(ahci_port_t *port)
void port_configure(ahci_port_t *port, struct ahci_internal_vaddr *vaddr)
int submit_impl(struct ioforge_block_device *dev, struct ioforge_block_request *req)
void build_prdt(ahci_cmd_t *cmd, ahci_cmd_tbl_t *cmdtbl, void *buffer, size_t size)
int atapi_packet(ahci_port_t *p, struct ahci_internal_vaddr *vaddr, struct ioforge_block_request *req)
int ata_identify(ahci_port_t *p, struct ahci_internal_vaddr *vaddr, struct ioforge_block_request *req, bool is_atapi)
static AHCIModule * getInstance()
bool ata_rw(ahci_port_t *p, struct ahci_internal_vaddr *vaddr, struct ioforge_block_request *req)
boolean_t issue_and_wait(ahci_port_t *p, int slot, uint32_t timeout)
static void * DMAAlloc(size_t size, uintptr_t *paddr)
static void sleep(uint32_t us)
static void memset(void *ptr, uint8_t value, size_t num)
volatile uint32_t buffer[5]
void ioforge_attach(struct ioforge_device *parent, struct ioforge_device *child)
void ioforge_sleep(uint32_t time)
struct ioforge_device * ioforge_get_block_devices_root()
#define log(mod, fmt,...)
@ IOFORGE_BLOCK_TYPE_SATA
@ IOFORGE_BLOCK_TYPE_SATAPI
@ IOFORGE_BLOCK_OP_PACKET
@ IOFORGE_BLOCK_OP_IDENTIFY
void * kalloc(size_t size)
void strcpy(char *dest, const char *src)
void memset(void *ptr, int value, size_t num)
void memcopy(void *dest, void *src, size_t size)
struct ioforge_device base
struct ioforge_block_op ops
int(* submit)(struct ioforge_block_device *dev, struct ioforge_block_request *req)
struct xhci_slot_ctx slot