X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/43c43c058ededea929645fef68d15820eed1f5e9..f044ca812256b421e793c4335ce1ffed74710a70:/lunaix-os/hal/ahci/ahci.c diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index b9bca95..c20e21d 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -12,8 +12,11 @@ #include #include #include - #include + +#include +#include + #include #include #include @@ -27,13 +30,13 @@ #define HBA_FIS_SIZE 256 #define HBA_CLB_SIZE 1024 -#define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFEE | HBA_PxINTR_OFE) +#define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFE | HBA_PxINTR_OF) // #define DO_HBA_FULL_RESET LOG_MODULE("AHCI") -struct llist_header ahcis; +DEFINE_LLIST(ahcis); static char sata_ifs[][20] = { "Not detected", "SATA I (1.5Gbps)", @@ -58,9 +61,6 @@ achi_register_ops(struct hba_port* port); void ahci_register_device(struct hba_device* hbadev); -void* -ahci_driver_init(struct pci_device* ahci_dev); - void __hba_reset_port(hba_reg_t* port_reg) { @@ -73,20 +73,15 @@ __hba_reset_port(hba_reg_t* port_reg) } // 如果port未响应,则继续执行重置 port_reg[HBA_RPxSCTL] = (port_reg[HBA_RPxSCTL] & ~0xf) | 1; - io_delay(100000); //等待至少一毫秒,差不多就行了 + port_delay(100000); // 等待至少一毫秒,差不多就行了 port_reg[HBA_RPxSCTL] &= ~0xf; } -void -ahci_init() +int +ahci_driver_init(struct device_def* def, struct device* dev) { - llist_init_head(&ahcis); - pci_add_driver("Serial ATA AHCI", AHCI_HBA_CLASS, 0, 0, ahci_driver_init); -} + struct pci_device* ahci_dev = container_of(dev, struct pci_device, dev); -void* -ahci_driver_init(struct pci_device* ahci_dev) -{ struct pci_base_addr* bar6 = &ahci_dev->bar[5]; assert_msg(bar6->type & BAR_TYPE_MMIO, "AHCI: BAR#6 is not MMIO."); @@ -99,6 +94,7 @@ ahci_driver_init(struct pci_device* ahci_dev) int iv = isrm_ivexalloc(__ahci_hba_isr); pci_setup_msi(ahci_dev, iv); + isrm_set_payload(iv, (ptr_t)&ahcis); struct ahci_driver* ahci_drv = vzalloc(sizeof(*ahci_drv)); struct ahci_hba* hba = &ahci_drv->hba; @@ -128,7 +124,9 @@ ahci_driver_init(struct pci_device* ahci_dev) hba->ports_bmp = pmap; /* ------ HBA端口配置 ------ */ - uintptr_t clb_pg_addr, fis_pg_addr, clb_pa, fis_pa; + ptr_t clb_pg_addr = 0, fis_pg_addr = 0; + ptr_t clb_pa = 0, fis_pa = 0; + for (size_t i = 0, fisp = 0, clbp = 0; i < 32; i++, pmap >>= 1, fisp = (fisp + 1) % 16, clbp = (clbp + 1) % 4) { if (!(pmap & 0x1)) { @@ -147,25 +145,27 @@ ahci_driver_init(struct pci_device* ahci_dev) if (!clbp) { // 每页最多4个命令队列 clb_pa = pmm_alloc_page(KERNEL_PID, PP_FGLOCKED); - clb_pg_addr = ioremap(clb_pa, 0x1000); - memset(clb_pg_addr, 0, 0x1000); + clb_pg_addr = (ptr_t)ioremap(clb_pa, 0x1000); + memset((void*)clb_pg_addr, 0, 0x1000); } if (!fisp) { // 每页最多16个FIS fis_pa = pmm_alloc_page(KERNEL_PID, PP_FGLOCKED); - fis_pg_addr = ioremap(fis_pa, 0x1000); - memset(fis_pg_addr, 0, 0x1000); + fis_pg_addr = (ptr_t)ioremap(fis_pa, 0x1000); + memset((void*)fis_pg_addr, 0, 0x1000); } /* 重定向CLB与FIS */ port_regs[HBA_RPxCLB] = clb_pa + clbp * HBA_CLB_SIZE; port_regs[HBA_RPxFB] = fis_pa + fisp * HBA_FIS_SIZE; - *port = (struct hba_port){ .regs = port_regs, - .ssts = port_regs[HBA_RPxSSTS], - .cmdlst = clb_pg_addr + clbp * HBA_CLB_SIZE, - .fis = fis_pg_addr + fisp * HBA_FIS_SIZE, - .hba = hba }; + *port = (struct hba_port){ + .regs = port_regs, + .ssts = port_regs[HBA_RPxSSTS], + .cmdlst = (struct hba_cmdh*)(clb_pg_addr + clbp * HBA_CLB_SIZE), + .fis = (void*)(fis_pg_addr + fisp * HBA_FIS_SIZE), + .hba = hba + }; /* 初始化端口,并置于就绪状态 */ port_regs[HBA_RPxCI] = 0; @@ -192,12 +192,13 @@ ahci_driver_init(struct pci_device* ahci_dev) i, hbadev->model, hbadev->block_size, - (uint32_t)hbadev->max_lba); + (u32_t)hbadev->max_lba); ahci_register_device(hbadev); } - return ahci_drv; + dev->underlay = ahci_drv; + return 0; } void @@ -218,7 +219,7 @@ __get_free_slot(struct hba_port* port) hba_reg_t pxsact = port->regs[HBA_RPxSACT]; hba_reg_t pxci = port->regs[HBA_RPxCI]; hba_reg_t free_bmp = pxsact | pxci; - uint32_t i = 0; + u32_t i = 0; for (; i <= port->hba->cmd_slots && (free_bmp & 0x1); i++, free_bmp >>= 1) ; return i | -(i > port->hba->cmd_slots); @@ -226,9 +227,9 @@ __get_free_slot(struct hba_port* port) void sata_create_fis(struct sata_reg_fis* cmd_fis, - uint8_t command, - uint64_t lba, - uint16_t sector_count) + u8_t command, + lba_t lba, + u16_t sector_count) { cmd_fis->head.type = SATA_REG_FIS_H2D; cmd_fis->head.options = SATA_REG_FIS_COMMAND; @@ -249,10 +250,13 @@ sata_create_fis(struct sata_reg_fis* cmd_fis, int hba_bind_sbuf(struct hba_cmdh* cmdh, struct hba_cmdt* cmdt, struct membuf mbuf) { - assert_msg(mbuf.size <= 0x400000, "HBA: Buffer too big"); + assert_msg(mbuf.size <= 0x400000U, "HBA: Buffer too big"); cmdh->prdt_len = 1; - cmdt->entries[0] = (struct hba_prdte){ .data_base = vmm_v2p(mbuf.buffer), - .byte_count = mbuf.size - 1 }; + cmdt->entries[0] = + (struct hba_prdte){ .data_base = vmm_v2p((ptr_t)mbuf.buffer), + .byte_count = mbuf.size - 1 }; + + return 0; } int @@ -263,15 +267,17 @@ hba_bind_vbuf(struct hba_cmdh* cmdh, struct hba_cmdt* cmdt, struct vecbuf* vbuf) do { assert_msg(i < HBA_MAX_PRDTE, "HBA: Too many PRDTEs"); - assert_msg(pos->buf.size <= 0x400000, "HBA: Buffer too big"); + assert_msg(pos->buf.size <= 0x400000U, "HBA: Buffer too big"); cmdt->entries[i++] = - (struct hba_prdte){ .data_base = vmm_v2p(pos->buf.buffer), + (struct hba_prdte){ .data_base = vmm_v2p((ptr_t)pos->buf.buffer), .byte_count = pos->buf.size - 1 }; pos = list_entry(pos->components.next, struct vecbuf, components); } while (pos != vbuf); cmdh->prdt_len = i + 1; + + return 0; } int @@ -289,7 +295,7 @@ hba_prepare_cmd(struct hba_port* port, memset(cmd_header, 0, sizeof(*cmd_header)); // 将命令表挂到命令头上 - cmd_header->cmd_table_base = vmm_v2p(cmd_table); + cmd_header->cmd_table_base = vmm_v2p((ptr_t)cmd_table); cmd_header->options = HBA_CMDH_FIS_LEN(sizeof(struct sata_reg_fis)) | HBA_CMDH_CLR_BUSY; @@ -310,7 +316,7 @@ ahci_init_device(struct hba_port* port) port->regs[HBA_RPxIE] &= ~HBA_MY_IE; // 预备DMA接收缓存,用于存放HBA传回的数据 - uint16_t* data_in = (uint16_t*)valloc_dma(512); + u16_t* data_in = (u16_t*)valloc_dma(512); int slot = hba_prepare_cmd(port, &cmd_table, &cmd_header); hba_bind_sbuf( @@ -393,7 +399,7 @@ ahci_init_device(struct hba_port* port) goto fail; } - scsi_parse_capacity(port->device, (uint32_t*)data_in); + scsi_parse_capacity(port->device, (u32_t*)data_in); done: // reset interrupt status and unmask D2HR interrupt @@ -430,4 +436,14 @@ achi_register_ops(struct hba_port* port) } else { port->device->ops.submit = scsi_submit; } -} \ No newline at end of file +} + +static struct pci_device_def ahcidef = { + .dev_class = AHCI_HBA_CLASS, + .dev_vendor = PCI_ID_ANY, + .dev_id = PCI_ID_ANY, + .devdef = { .class = DEVCLASS(DEVIF_PCI, DEVFN_STORAGE, DEV_SATA, 0), + .name = "SATA AHCI", + .init_for = ahci_driver_init } +}; +EXPORT_DEVICE(ahci, &ahcidef.devdef, load_on_demand); \ No newline at end of file