fa87fd3c9a46f9acb59dbbc9bf9a5d95dedf4dbf
[lunaix-os.git] / lunaix-os / hal / ahci.c
1 /**
2  * @file ahci.c
3  * @author Lunaixsky (zelong56@gmail.com)
4  * @brief A software implementation of Serial ATA AHCI 1.3.1 Specification
5  * @version 0.1
6  * @date 2022-06-28
7  *
8  * @copyright Copyright (c) 2022
9  *
10  */
11 #include <hal/ahci.h>
12 #include <hal/pci.h>
13 #include <lunaix/mm/mmio.h>
14 #include <lunaix/spike.h>
15 #include <lunaix/syslog.h>
16
17 LOG_MODULE("AHCI")
18
19 static struct ahci_hba hba;
20
21 void
22 ahci_init()
23 {
24     struct pci_device* ahci_dev = pci_get_device_by_class(0x10601);
25     assert_msg(ahci_dev, "AHCI: Not found.");
26
27     uintptr_t bar6, size;
28     size = pci_bar_sizing(ahci_dev, &bar6, 6);
29     assert_msg(bar6 && PCI_BAR_MMIO(bar6), "AHCI: BAR#6 is not MMIO.");
30
31     hba.base = (hba_reg_t*)ioremap(PCI_BAR_ADDR_MM(bar6), size);
32
33     // Enable AHCI, Enable interrupt generation.
34     hba.base[HBA_RGHC] |= 0x80000002;
35
36     // As per section 3.1.1, this is 0 based value.
37     hba.ports_num = (hba.base[HBA_RCAP] & 0x1f) + 1;
38     hba.version = hba.base[HBA_RVER];
39
40     kprintf(KINFO "Version: %x; Ports: %d\n", hba.version, hba.ports_num);
41
42     hba_reg_t pmap = hba.base[HBA_RPI];
43     for (size_t i = 0; i < 32; i++, pmap = pmap >> 1) {
44         if (!(pmap & 0x1)) {
45             continue;
46         }
47         hba.ports[i] = (hba_reg_t*)(&hba.base[HBA_RPBASE] + i);
48         kprintf("\t Port#%d, clb: %p, fis: %p\n",
49                 i + 1,
50                 hba.ports[i][HBA_RPxCLB],
51                 hba.ports[i][HBA_RPxFB]);
52
53         // TODO: (?) Rebasing each port's command list and FIS
54     }
55 }