X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/489fcbc119f6ae46efc8f4077cbb5aa43683e404..bf870a1dde437a48ae40d092a14e164c861ea102:/lunaix-os/hal/ahci/ahci.c diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 1562676..21eaa1d 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,7 @@ LOG_MODULE("AHCI") static struct ahci_hba hba; void -__ahci_hba_isr(isr_param param); +__ahci_hba_isr(const isr_param* param); int ahci_init_device(struct hba_port* port); @@ -160,8 +161,6 @@ ahci_init() // 需要通过全部置位去清空这些寄存器(相当的奇怪……) port_regs[HBA_RPxSERR] = -1; - port_regs[HBA_RPxIE] |= (HBA_PxINTR_D2HR); - hba.ports[i] = port; if (!HBA_RPxSSTS_IF(port->ssts)) { @@ -173,8 +172,11 @@ ahci_init() port_regs[HBA_RPxCMD] |= HBA_PxCMD_ST; if (!ahci_init_device(port)) { - kprintf(KERROR "fail to init device"); + kprintf(KERROR "init fail: 0x%x@p%d\n", port->regs[HBA_RPxSIG], i); + continue; } + + block_mount_disk(port->device); } } @@ -184,9 +186,10 @@ char sata_ifs[][20] = { "Not detected", "SATA III (6.0Gbps)" }; void -__ahci_hba_isr(isr_param param) +__ahci_hba_isr(const isr_param* param) { - // TODO: hba interrupt + // TODO: clear the interrupt status + // TODO: I/O-operation scheduler should be here kprintf(KDEBUG "HBA INTR\n"); } @@ -277,7 +280,7 @@ hba_prepare_cmd(struct hba_port* port, // 构建命令头(Command Header)和命令表(Command Table) struct hba_cmdh* cmd_header = &port->cmdlst[slot]; - struct hba_cmdt* cmd_table = vcalloc_dma(sizeof(struct hba_cmdt)); + struct hba_cmdt* cmd_table = vzalloc_dma(sizeof(struct hba_cmdt)); memset(cmd_header, 0, sizeof(*cmd_header)); @@ -306,6 +309,9 @@ ahci_init_device(struct hba_port* port) struct hba_cmdt* cmd_table; struct hba_cmdh* cmd_header; + // mask DHR interrupt + port->regs[HBA_RPxIE] &= ~HBA_PxINTR_DHR; + // 确保端口是空闲的 wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY))); @@ -378,12 +384,20 @@ ahci_init_device(struct hba_port* port) * SATA AHCI HBA Spec, Section 5.3.7 * SCSI Command Reference Manual, Section 3.26 */ - struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd; sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0); - scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 512); - cdb16->misc1 = 0x10; // service action + // for dev use 12 bytes cdb, READ_CAPACITY must use the 10 bytes variation. + if (port->device->cbd_size == 12) { + struct scsi_cdb12* cdb12 = (struct scsi_cdb12*)cmd_table->atapi_cmd; + // ugly tricks to construct 10 byte cdb from 12 byte cdb + scsi_create_packet12(cdb12, SCSI_READ_CAPACITY_10, 0, 512 << 8); + } else { + struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd; + scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 512); + cdb16->misc1 = 0x10; // service action + } + cmd_header->transferred_size = 0; cmd_header->options |= HBA_CMDH_ATAPI; @@ -399,6 +413,9 @@ ahci_init_device(struct hba_port* port) scsi_parse_capacity(port->device, (uint32_t*)data_in); done: + // reset interrupt status and unmask D2HR interrupt + port->regs[HBA_RPxIS] = -1; + port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR; achi_register_ops(port); vfree_dma(data_in); @@ -407,6 +424,8 @@ done: return 1; fail: + port->regs[HBA_RPxIS] = -1; + port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR; vfree_dma(data_in); vfree_dma(cmd_table); @@ -414,11 +433,11 @@ fail: } int -ahci_identify_device(struct hba_port* port) +ahci_identify_device(struct hba_device* device) { // 用于重新识别设备(比如在热插拔的情况下) - vfree(port->device); - return ahci_init_device(port); + vfree(device); + return ahci_init_device(device->port); } void