|
@@ -7,6 +7,7 @@ struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
|
|
|
uint32_t count_ahci_devices = 0;
|
|
|
|
|
|
uint64_t ahci_port_base_vaddr; // 端口映射base addr
|
|
|
+uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ahci控制器的参数的地址都是物理地址)
|
|
|
|
|
|
static void start_cmd(HBA_PORT *port);
|
|
|
static void stop_cmd(HBA_PORT *port);
|
|
@@ -24,21 +25,24 @@ static int ahci_find_cmdslot(HBA_PORT *port);
|
|
|
*/
|
|
|
void ahci_init()
|
|
|
{
|
|
|
+ kinfo("Initializing AHCI...");
|
|
|
pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices);
|
|
|
|
|
|
// 映射ABAR
|
|
|
mm_map_phys_addr(AHCI_MAPPING_BASE, ((ul)(((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
|
|
|
- //kdebug("ABAR mapped!");
|
|
|
+ // kdebug("ABAR mapped!");
|
|
|
|
|
|
for (int i = 0; i < count_ahci_devices; ++i)
|
|
|
{
|
|
|
- //kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, ABAR=%#010lx", i, ahci_devs[i]->Class_code, ahci_devs[i]->SubClass, ahci_devs[i]->ProgIF, ((struct pci_device_structure_general_device_t *)(ahci_devs[i]))->BAR5);
|
|
|
- // 赋值HBA_MEM结构体
|
|
|
+ // kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, ABAR=%#010lx", i, ahci_devs[i]->Class_code, ahci_devs[i]->SubClass, ahci_devs[i]->ProgIF, ((struct pci_device_structure_general_device_t *)(ahci_devs[i]))->BAR5);
|
|
|
+ // 赋值HBA_MEM结构体
|
|
|
ahci_devices[i].dev_struct = ahci_devs[i];
|
|
|
ahci_devices[i].hba_mem = (HBA_MEM *)(cal_HBA_MEM_VIRT_ADDR(i));
|
|
|
+ kdebug("ahci_devices[i].hba_mem = %#018lx", (ul)ahci_devices[i].hba_mem);
|
|
|
}
|
|
|
// todo: 支持多个ahci控制器。
|
|
|
ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0);
|
|
|
+ kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr);
|
|
|
ahci_probe_port(0);
|
|
|
port_rebase(&ahci_devices[0].hba_mem->ports[0], 0);
|
|
|
|
|
@@ -118,7 +122,7 @@ static void ahci_probe_port(const uint32_t device_num)
|
|
|
static void start_cmd(HBA_PORT *port)
|
|
|
{
|
|
|
// Wait until CR (bit15) is cleared
|
|
|
- while (port->cmd & HBA_PxCMD_CR)
|
|
|
+ while ((port->cmd) & HBA_PxCMD_CR)
|
|
|
;
|
|
|
|
|
|
// Set FRE (bit4) and ST (bit0)
|
|
@@ -160,29 +164,29 @@ static void port_rebase(HBA_PORT *port, int portno)
|
|
|
// Command list entry maxim count = 32
|
|
|
// Command list maxim size = 32*32 = 1K per port
|
|
|
|
|
|
- port->clb = ahci_port_base_vaddr + (portno << 10);
|
|
|
+ port->clb = virt_2_phys(ahci_port_base_vaddr + (portno << 10));
|
|
|
|
|
|
- memset((void *)(port->clb), 0, 1024);
|
|
|
+ memset((void *)(phys_2_virt(port->clb)), 0, 1024);
|
|
|
|
|
|
// FIS offset: 32K+256*portno
|
|
|
// FIS entry size = 256 bytes per port
|
|
|
- port->fb = ahci_port_base_vaddr + (32 << 10) + (portno << 8);
|
|
|
+ port->fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (portno << 8));
|
|
|
|
|
|
- memset((void *)(port->fb), 0, 256);
|
|
|
+ memset((void *)(phys_2_virt(port->fb)), 0, 256);
|
|
|
|
|
|
// Command table offset: 40K + 8K*portno
|
|
|
// Command table size = 256*32 = 8K per port
|
|
|
- HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(port->clb);
|
|
|
+ HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(phys_2_virt(port->clb));
|
|
|
for (int i = 0; i < 32; ++i)
|
|
|
{
|
|
|
cmdheader[i].prdtl = 8; // 8 prdt entries per command table
|
|
|
// 256 bytes per command table, 64+16+48+16*8
|
|
|
// Command table offset: 40K + 8K*portno + cmdheader_index*256
|
|
|
- cmdheader[i].ctba = ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8);
|
|
|
+ cmdheader[i].ctba = virt_2_phys((ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8)));
|
|
|
|
|
|
- memset((void *)cmdheader[i].ctba, 0, 256);
|
|
|
+ memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
start_cmd(port); // Start command engine
|
|
|
}
|
|
|
|
|
@@ -206,20 +210,20 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t
|
|
|
if (slot == -1)
|
|
|
return E_NOEMPTYSLOT;
|
|
|
|
|
|
- HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)port->clb;
|
|
|
+ HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
|
|
|
cmdheader += slot;
|
|
|
cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
|
|
|
cmdheader->w = 0; // Read from device
|
|
|
cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
|
|
|
|
|
|
- HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)(cmdheader->ctba);
|
|
|
+ HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
|
|
|
memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
|
|
|
|
|
|
// 8K bytes (16 sectors) per PRDT
|
|
|
int i;
|
|
|
for (i = 0; i < cmdheader->prdtl - 1; ++i)
|
|
|
{
|
|
|
- cmdtbl->prdt_entry[i].dba = buf;
|
|
|
+ cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
|
|
|
cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes (this value should always be set to 1 less than the actual value)
|
|
|
cmdtbl->prdt_entry[i].i = 1;
|
|
|
buf += 4 * 1024; // 4K uint16_ts
|
|
@@ -227,7 +231,7 @@ static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t
|
|
|
}
|
|
|
|
|
|
// Last entry
|
|
|
- cmdtbl->prdt_entry[i].dba = buf;
|
|
|
+ cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
|
|
|
cmdtbl->prdt_entry[i].dbc = (count << 9) - 1; // 512 bytes per sector
|
|
|
cmdtbl->prdt_entry[i].i = 1;
|
|
|
|
|
@@ -296,7 +300,7 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_
|
|
|
if (slot == -1)
|
|
|
return E_NOEMPTYSLOT;
|
|
|
|
|
|
- HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)port->clb;
|
|
|
+ HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
|
|
|
|
|
|
cmdheader += slot;
|
|
|
cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
|
|
@@ -305,7 +309,7 @@ static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_
|
|
|
cmdheader->p = 1;
|
|
|
cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
|
|
|
|
|
|
- HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)(cmdheader->ctba);
|
|
|
+ HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
|
|
|
memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
|
|
|
|
|
|
int i = 0;
|
|
@@ -438,7 +442,7 @@ static void ahci_end_request()
|
|
|
ahci_req_queue.in_service = NULL;
|
|
|
|
|
|
// 进行下一轮的磁盘请求 (由于未实现单独的io调度器,这里会造成长时间的io等待)
|
|
|
- if (ahci_req_queue.request_count>0)
|
|
|
+ if (ahci_req_queue.request_count > 0)
|
|
|
ahci_query_disk();
|
|
|
}
|
|
|
|