update readme for more up-to-date information
[lunaix-os.git] / lunaix-os / hal / ahci / io_event.c
index 632197cc82813fb5dd918bf51172700caa50e633..bb3142b37aefedc6749835460d61b6bba80a4afa 100644 (file)
@@ -1,27 +1,54 @@
-#include <hal/ahci/hba.h>
+#include <hal/ahci/ahci.h>
 #include <hal/ahci/sata.h>
 #include <lunaix/isrm.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/syslog.h>
 
-extern struct ahci_hba hba;
+LOG_MODULE("io_evt")
+
+extern struct llist_header ahcis;
 
 void
 __ahci_hba_isr(const isr_param* param)
 {
+    struct ahci_hba* hba;
+    struct ahci_driver *pos, *n;
+    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 - __builtin_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 - __builtin_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);
 
 done:
     hba_clear_reg(port->regs[HBA_RPxIS]);
+    hba->base[HBA_RIS] &= ~(1 << (31 - port_num));
 }
 
 void