X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/97901724584e74554916b89dfb8e95dc6497e687..b60166b327a9108b07e3069fa6568a451529ffd9:/lunaix-os/hal/ahci/io_event.c diff --git a/lunaix-os/hal/ahci/io_event.c b/lunaix-os/hal/ahci/io_event.c index 632197c..aec209e 100644 --- a/lunaix-os/hal/ahci/io_event.c +++ b/lunaix-os/hal/ahci/io_event.c @@ -1,27 +1,54 @@ -#include +#include #include #include #include +#include -extern struct ahci_hba hba; +LOG_MODULE("io_evt") void -__ahci_hba_isr(const isr_param* param) +ahci_hba_isr(const isr_param* param) { + struct ahci_hba* hba; + struct ahci_driver *pos, *n; + struct llist_header* ahcis = (struct llist_header*)isrm_get_payload(param); + + llist_for_each(pos, n, ahcis, ahci_drvs) + { + if (pos->id == (int)param->execp->vector) { + hba = &pos->hba; + goto proceed; + } + } + + return; + +proceed: // ignore spurious interrupt - if (!hba.base[HBA_RIS]) + if (!hba->base[HBA_RIS]) return; - u32_t port_num = 31 - __builtin_clz(hba.base[HBA_RIS]); - struct hba_port* port = hba.ports[port_num]; + u32_t port_num = 31 - clz(hba->base[HBA_RIS]); + struct hba_port* port = hba->ports[port_num]; struct hba_cmd_context* cmdctx = &port->cmdctx; - u32_t ci_filtered = port->regs[HBA_RPxCI] ^ cmdctx->tracked_ci; + u32_t processed = port->regs[HBA_RPxCI] ^ cmdctx->tracked_ci; - if (!ci_filtered) { + sata_read_error(port); + + // FIXME When error occurs, CI will not change. Need error recovery! + if (!processed) { + if (port->regs[HBA_RPxIS] & HBA_FATAL) { + // TODO perform error recovery + // This should include: + // 1. Discard all issued (but pending) requests (signaled as + // error) + // 2. Restart port + // Complete steps refer to AHCI spec 6.2.2.1 + } goto done; } - u32_t slot = 31 - __builtin_clz(ci_filtered); + u32_t slot = 31 - clz(processed); struct hba_cmd_state* cmdstate = cmdctx->issued[slot]; if (!cmdstate) { @@ -29,17 +56,20 @@ __ahci_hba_isr(const isr_param* param) } struct blkio_req* ioreq = (struct blkio_req*)cmdstate->state_ctx; - sata_read_error(port); + if ((port->device->last_result.status & HBA_PxTFD_ERR)) { ioreq->errcode = port->regs[HBA_RPxTFD] & 0xffff; ioreq->flags |= BLKIO_ERROR; + hba_clear_reg(port->regs[HBA_RPxSERR]); } + blkio_schedule(ioreq->io_ctx); blkio_complete(ioreq); - vfree(cmdstate->cmd_table); + vfree_dma(cmdstate->cmd_table); done: hba_clear_reg(port->regs[HBA_RPxIS]); + hba->base[HBA_RIS] &= ~(1 << (31 - port_num)); } void