rework external irq system, introduce hierarchical irq
[lunaix-os.git] / lunaix-os / hal / ahci / io_event.c
1 #include <hal/ahci/ahci.h>
2 #include <hal/ahci/sata.h>
3 #include <asm-generic/isrm.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/syslog.h>
6
7 LOG_MODULE("io_evt")
8
9 void
10 ahci_hba_isr(irq_t irq, const struct hart_state* hstate)
11 {
12     struct ahci_hba* hba;
13     struct ahci_driver *pos, *n;
14     struct llist_header* ahcis;
15
16     ahcis = irq_payload(irq, struct llist_header);
17     llist_for_each(pos, n, ahcis, ahci_drvs)
18     {
19         if (pos->id == hart_vector_stamp(hstate)) {
20             hba = &pos->hba;
21             goto proceed;
22         }
23     }
24
25     return;
26
27 proceed:
28     // ignore spurious interrupt
29     if (!hba->base[HBA_RIS])
30         return;
31
32     u32_t port_num = msbiti - clz(hba->base[HBA_RIS]);
33     struct hba_port* port = hba->ports[port_num];
34     struct hba_cmd_context* cmdctx = &port->cmdctx;
35     u32_t processed = port->regs[HBA_RPxCI] ^ cmdctx->tracked_ci;
36
37     sata_read_error(port);
38
39     // FIXME When error occurs, CI will not change. Need error recovery!
40     if (!processed) {
41         if (port->regs[HBA_RPxIS] & HBA_FATAL) {
42             // TODO perform error recovery
43             // This should include:
44             //      1. Discard all issued (but pending) requests (signaled as
45             //      error)
46             //      2. Restart port
47             // Complete steps refer to AHCI spec 6.2.2.1
48         }
49         goto done;
50     }
51
52     u32_t slot = msbiti - clz(processed);
53     struct hba_cmd_state* cmdstate = cmdctx->issued[slot];
54
55     if (!cmdstate) {
56         goto done;
57     }
58
59     struct blkio_req* ioreq = (struct blkio_req*)cmdstate->state_ctx;
60
61     if ((port->device->last_result.status & HBA_PxTFD_ERR)) {
62         ioreq->errcode = port->regs[HBA_RPxTFD] & 0xffff;
63         ioreq->flags |= BLKIO_ERROR;
64         hba_clear_reg(port->regs[HBA_RPxSERR]);
65     }
66
67     blkio_schedule(ioreq->io_ctx);
68     blkio_complete(ioreq);
69     vfree_dma(cmdstate->cmd_table);
70
71 done:
72     hba_clear_reg(port->regs[HBA_RPxIS]);
73     hba->base[HBA_RIS] &= ~(1 << (31 - port_num));
74 }
75
76 void
77 __ahci_blkio_handler(struct blkio_req* req)
78 {
79     struct hba_device* hbadev = (struct hba_device*)req->io_ctx->driver;
80
81     hbadev->ops.submit(hbadev, req);
82 }