feat: Ability to send command to ATA device.
authorMinep <zelong56@gmail.com>
Mon, 4 Jul 2022 12:05:04 +0000 (13:05 +0100)
committerMinep <zelong56@gmail.com>
Mon, 4 Jul 2022 12:15:27 +0000 (13:15 +0100)
feat: Implementation of IDENTIFY (PACKET) DEVICE command issuing.

15 files changed:
lunaix-os/.gitignore
lunaix-os/config/make-debug-tool
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/utils.c [new file with mode: 0644]
lunaix-os/includes/arch/x86/interrupts.h
lunaix-os/includes/arch/x86/vectors.h
lunaix-os/includes/hal/ahci.h [deleted file]
lunaix-os/includes/hal/ahci/ahci.h [new file with mode: 0644]
lunaix-os/includes/hal/ahci/utils.h [new file with mode: 0644]
lunaix-os/includes/lunaix/mm/vmm.h
lunaix-os/includes/lunaix/spike.h
lunaix-os/kernel/asm/x86/idt.c
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/mm/vmm.c
lunaix-os/kernel/proc0.c

index 0b666f608891ffc23607978a06b54a54543986bb..31aeefdf100bce92bbf5c014e55115ced31a205c 100644 (file)
@@ -4,4 +4,5 @@ playground/
 .vscode/*.log
 .VSCodeCounter/
 .idea
-bx_enh_dbg.ini
\ No newline at end of file
+bx_enh_dbg.ini
+machine/
\ No newline at end of file
index 647a45676e03e3628e92d3ac9146910f0d14ae3d..8d4e13dc8f20251c6338ffbac4c683448e6b9bca 100644 (file)
@@ -4,7 +4,10 @@ QEMU_MON_PORT := 45454
 QEMU_OPTIONS := -s -S -m 1G \
                                -rtc base=utc \
                                -no-reboot \
+                               -machine q35 \
                                -no-shutdown \
                                -d cpu_reset \
+                               -drive id=disk,file="machine/disk0.vdi",if=none \
                                -device ahci,id=ahci \
+                               -device ide-hd,drive=disk,bus=ahci.0 \
                                -monitor telnet::$(QEMU_MON_PORT),server,nowait &
\ No newline at end of file
index c5989fb58f8036af6e732e1cd5b9fc085cf03c49..57bedb6b1f93616589841684a3957e76f04a031c 100644 (file)
@@ -8,12 +8,14 @@
  * @copyright Copyright (c) 2022
  *
  */
-#include <hal/ahci.h>
+#include <hal/ahci/ahci.h>
+#include <hal/ahci/utils.h>
 #include <hal/pci.h>
 #include <klibc/string.h>
-#include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/mmio.h>
 #include <lunaix/mm/pmm.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/mm/vmm.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 
@@ -24,6 +26,9 @@ LOG_MODULE("AHCI")
 
 static struct ahci_hba hba;
 
+void
+__ahci_hba_isr(isr_param param);
+
 void
 ahci_init()
 {
@@ -41,6 +46,11 @@ ahci_init()
 
     pci_write_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD, cmd);
 
+    pci_setup_msi(ahci_dev, AHCI_HBA_IV);
+    intr_subscribe(AHCI_HBA_IV, __ahci_hba_isr);
+
+    memset(&hba, 0, sizeof(hba));
+
     hba.base = (hba_reg_t*)ioremap(PCI_BAR_ADDR_MM(bar6), size);
 
     // 重置HBA
@@ -48,7 +58,8 @@ ahci_init()
     wait_until(!(hba.base[HBA_RGHC] & HBA_RGHC_RESET));
 
     // 启用AHCI工作模式,启用中断
-    hba.base[HBA_RGHC] |= (HBA_RGHC_ACHI_ENABLE | HBA_RGHC_INTR_ENABLE);
+    hba.base[HBA_RGHC] |= HBA_RGHC_ACHI_ENABLE;
+    hba.base[HBA_RGHC] |= HBA_RGHC_INTR_ENABLE;
 
     // As per section 3.1.1, this is 0 based value.
     hba_reg_t cap = hba.base[HBA_RCAP];
@@ -66,7 +77,7 @@ ahci_init()
         }
 
         struct ahci_port* port =
-          (struct ahci_port*)lxmalloc(sizeof(struct ahci_port));
+          (struct ahci_port*)valloc(sizeof(struct ahci_port));
         hba_reg_t* port_regs =
           (hba_reg_t*)(&hba.base[HBA_RPBASE + i * HBA_RPSIZE]);
 
@@ -87,18 +98,30 @@ ahci_init()
         port_regs[HBA_RPxCLB] = clb_pa + clbp * HBA_CLB_SIZE;
         port_regs[HBA_RPxFB] = fis_pa + fisp * HBA_FIS_SIZE;
 
-        *port =
-          (struct ahci_port){ .regs = port_regs,
-                              .ssts = port_regs[HBA_RPxSSTS],
-                              .cmdlstv = clb_pg_addr + clbp * HBA_CLB_SIZE,
-                              .fisv = fis_pg_addr + fisp * HBA_FIS_SIZE };
+        *port = (struct ahci_port){ .regs = port_regs,
+                                    .ssts = port_regs[HBA_RPxSSTS],
+                                    .cmdlst = clb_pg_addr + clbp * HBA_CLB_SIZE,
+                                    .fis = fis_pg_addr + fisp * HBA_FIS_SIZE };
 
         /* 初始化端口,并置于就绪状态 */
         port_regs[HBA_RPxCI] = 0;
-        port_regs[HBA_RPxIE] |= (HBA_PxINTR_DMA | HBA_PxINTR_D2HR);
-        port_regs[HBA_RPxCMD] |= (HBA_PxCMD_FRE | HBA_PxCMD_ST);
+
+        // 需要通过全部置位去清空这些寄存器(相当的奇怪……)
+        port_regs[HBA_RPxSERR] = -1;
+
+        port_regs[HBA_RPxIE] |= (HBA_PxINTR_DMA);
+        port_regs[HBA_RPxIE] |= (HBA_PxINTR_D2HR);
 
         hba.ports[i] = port;
+
+        if (HBA_RPxSSTS_IF(port->ssts)) {
+            wait_until(!(port_regs[HBA_RPxCMD] & HBA_PxCMD_CR));
+            port_regs[HBA_RPxCMD] |= HBA_PxCMD_FRE;
+            port_regs[HBA_RPxCMD] |= HBA_PxCMD_ST;
+            if (!ahci_identify_device(port)) {
+                kprintf(KERROR "fail to probe device info");
+            }
+        }
     }
 }
 
@@ -107,14 +130,155 @@ char sata_ifs[][20] = { "Not detected",
                         "SATA II (3.0Gbps)",
                         "SATA III (6.0Gbps)" };
 
+void
+__ahci_hba_isr(isr_param param)
+{
+    // TODO: hba interrupt
+    kprintf(KDEBUG "HBA INTR\n");
+}
+
 void
 ahci_list_device()
 {
-    kprintf(KINFO "Version: %x; Ports: %d\n", hba.version, hba.ports_num);
+    kprintf(KINFO "Version: %x; Ports: %d; Slot: %d\n",
+            hba.version,
+            hba.ports_num,
+            hba.cmd_slots);
+    struct ahci_port* port;
     for (size_t i = 0; i < 32; i++) {
-        struct ahci_port* port = hba.ports[i];
-        if (!port)
+        port = hba.ports[i];
+
+        // 愚蠢的gcc似乎认为 struct ahci_port* 不可能为空
+        //  所以将这个非常关键的if给优化掉了。
+        //  这里将指针强制转换为整数,欺骗gcc :)
+        if ((uintptr_t)port == 0) {
             continue;
-        kprintf("\t Port %d: %s\n", i, &sata_ifs[HBA_RPxSSTS_IF(port->ssts)]);
+        }
+
+        int device_state = HBA_RPxSSTS_IF(port->ssts);
+
+        kprintf("\t Port %d: %s (%x)\n",
+                i,
+                &sata_ifs[device_state],
+                port->regs[HBA_RPxSIG]);
+
+        struct ahci_device_info* dev_info = port->device_info;
+        if (!device_state || !dev_info) {
+            continue;
+        }
+
+        kprintf("\t\t capacity: %d KiB\n",
+                (dev_info->max_lba * dev_info->sector_size) >> 10);
+        kprintf("\t\t sector size: %dB\n", dev_info->sector_size);
+        kprintf("\t\t model: %s\n", &dev_info->model);
+        kprintf("\t\t serial: %s\n", &dev_info->serial_num);
     }
-}
\ No newline at end of file
+}
+
+int
+achi_alloc_slot(struct ahci_port* port)
+{
+    hba_reg_t pxsact = port->regs[HBA_RPxSACT];
+    hba_reg_t pxci = port->regs[HBA_RPxCI];
+    hba_reg_t free_bmp = pxsact | pxci;
+    uint32_t i = 0;
+    for (; i <= hba.cmd_slots && (free_bmp & 0x1); i++, free_bmp >>= 1)
+        ;
+    return i | -(i > hba.cmd_slots);
+}
+
+void
+__ahci_create_fis(struct sata_reg_fis* cmd_fis,
+                  uint8_t command,
+                  uint32_t lba_lo,
+                  uint32_t lba_hi,
+                  uint16_t sector_count)
+{
+    cmd_fis->head.type = SATA_REG_FIS_H2D;
+    cmd_fis->head.options = SATA_REG_FIS_COMMAND;
+    cmd_fis->head.status_cmd = command;
+    cmd_fis->dev = 0;
+
+    cmd_fis->lba0 = SATA_LBA_COMPONENT(lba_lo, 0);
+    cmd_fis->lba8 = SATA_LBA_COMPONENT(lba_lo, 8);
+    cmd_fis->lba16 = SATA_LBA_COMPONENT(lba_lo, 16);
+    cmd_fis->lba24 = SATA_LBA_COMPONENT(lba_lo, 24);
+
+    cmd_fis->lba32 = SATA_LBA_COMPONENT(lba_hi, 0);
+    cmd_fis->lba40 = SATA_LBA_COMPONENT(lba_hi, 8);
+
+    cmd_fis->count = sector_count;
+}
+
+int
+ahci_identify_device(struct ahci_port* port)
+{
+    int slot = achi_alloc_slot(port);
+    assert_msg(slot >= 0, "No free slot");
+
+    // 清空任何待响应的中断
+    port->regs[HBA_RPxIS] = 0;
+
+    /* 发送ATA命令,参考:SATA AHCI Spec Rev.1.3.1, section 5.5 */
+
+    // 构建命令头(Command Header)和命令表(Command Table)
+    struct ahci_hba_cmdh* cmd_header = &port->cmdlst[slot];
+    struct ahci_hba_cmdt* cmd_table = valloc_dma(sizeof(struct ahci_hba_cmdt));
+
+    memset(cmd_header, 0, sizeof(*cmd_header));
+    memset(cmd_table, 0, sizeof(*cmd_table));
+
+    // 预备DMA接收缓存,用于存放HBA传回的数据
+    uint16_t* data_in = (uint16_t*)valloc_dma(512);
+
+    cmd_table->entries[0] =
+      (struct ahci_hba_prdte){ .data_base = vmm_v2p(data_in),
+                               .byte_count = 511 }; // byte_count是从0开始算的
+
+    // 在命令表中构建命令FIS
+    struct sata_reg_fis* cmd_fis = (struct sata_reg_fis*)cmd_table->command_fis;
+
+    // 根据设备类型使用合适的命令
+    if (port->regs[HBA_RPxSIG] == HBA_DEV_SIG_ATA) {
+        // ATA 一般为硬盘
+        __ahci_create_fis(cmd_fis, ATA_IDENTIFY_DEVICE, 0, 0, 0);
+    } else {
+        // ATAPI 一般为光驱,软驱,或者磁带机
+        __ahci_create_fis(cmd_fis, ATA_IDENTIFY_PAKCET_DEVICE, 0, 0, 0);
+    }
+
+    // 将命令表挂到命令头上
+    cmd_header->cmd_table_base = vmm_v2p(cmd_table);
+    cmd_header->prdt_len = 1;
+    cmd_header->options |=
+      HBA_CMDH_FIS_LEN(sizeof(*cmd_fis)) | HBA_CMDH_CLR_BUSY;
+
+    // PxCI寄存器置位,告诉HBA这儿有个数据需要发送到SATA端口
+    port->regs[HBA_RPxCI] = (1 << slot);
+
+    wait_until(!(port->regs[HBA_RPxCI] & (1 << slot)));
+
+    /*
+        等待数据到达内存
+        解析IDENTIFY DEVICE传回来的数据。
+          参考:
+            * ATA/ATAPI Command Set - 3 (ACS-3), Section 7.12.7
+
+        注意:ATAPI无法通过IDENTIFY PACKET DEVICE 获取容量信息。
+        这需要另外使用特殊的SCSI命令中的READ CAPACITY(16)
+        来获取,这种命令需要使用ATA的PACKET命令发出。
+          参考:
+            * ATA/ATAPI Command Set - 3 (ACS-3), Section 7.18
+            * SATA AHCI HBA Spec, Section 5.3.7
+            * SCSI Command Reference Manual, Section 3.26
+    */
+    port->device_info = valloc(sizeof(struct ahci_device_info));
+    ahci_parse_dev_info(port->device_info, data_in);
+
+    vfree_dma(data_in);
+    vfree_dma(cmd_table);
+
+    return 1;
+}
+
+// TODO: Support ATAPI Device.
\ No newline at end of file
diff --git a/lunaix-os/hal/ahci/utils.c b/lunaix-os/hal/ahci/utils.c
new file mode 100644 (file)
index 0000000..279cd50
--- /dev/null
@@ -0,0 +1,31 @@
+#include <hal/ahci/utils.h>
+#include <klibc/string.h>
+
+#define IDDEV_MAXLBA_OFFSET 60
+#define IDDEV_LSECSIZE_OFFSET 117
+#define IDDEV_WWN_OFFSET 108
+#define IDDEV_SERIALNUM_OFFSET 10
+#define IDDEV_MODELNUM_OFFSET 27
+
+void
+ahci_parse_dev_info(struct ahci_device_info* dev_info, uint16_t* data)
+{
+    dev_info->max_lba = *((uint32_t*)(data + IDDEV_MAXLBA_OFFSET));
+    dev_info->sector_size = *((uint32_t*)(data + IDDEV_LSECSIZE_OFFSET));
+    memcpy(&dev_info->wwn, (uint8_t*)(data + IDDEV_WWN_OFFSET), 8);
+    if (!dev_info->sector_size) {
+        dev_info->sector_size = 512;
+    }
+    ahci_parsestr(&dev_info->serial_num, data + IDDEV_SERIALNUM_OFFSET, 10);
+    ahci_parsestr(&dev_info->model, data + IDDEV_MODELNUM_OFFSET, 20);
+}
+
+void
+ahci_parsestr(char* str, uint16_t* reg_start, int size_word)
+{
+    for (int i = 0, j = 0; i < size_word; i++, j += 2) {
+        uint16_t reg = *(reg_start + i);
+        str[j] = (char)(reg >> 8);
+        str[j + 1] = (char)(reg & 0xff);
+    }
+}
\ No newline at end of file
index 88138b604cef639e898804919069017a281f8c9e..862ef05bc46bbb4d64f0b4b698e577a222e0b343 100644 (file)
@@ -65,6 +65,7 @@ ISR(32)
 ISR(33)
 
 ISR(201)
+ISR(202)
 
 ISR(210)
 
index 5fb424f9be39466569464acfd959facd7b999a18..e4a19688232967d480802c3cece4e1f1ff78861c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __LUNAIX_VECTORS_H
 #define __LUNAIX_VECTORS_H
 
+// clang-format off
+
 #define FAULT_DIVISION_ERROR            0
 #define FAULT_TRAP_DEBUG_EXCEPTION      1
 #define INT_NMI                         2
@@ -32,6 +34,7 @@
 
 // Keyboard
 #define PC_KBD_IV                       201
+#define AHCI_HBA_IV                     202
 
 #define RTC_TIMER_IV                    210
 
@@ -45,4 +48,6 @@
 #define PC_AT_IRQ_RTC                   8
 #define PC_AT_IRQ_KBD                   1
 
+// clang-format on
+
 #endif /* __LUNAIX_VECTORS_H */
diff --git a/lunaix-os/includes/hal/ahci.h b/lunaix-os/includes/hal/ahci.h
deleted file mode 100644 (file)
index dc30ca8..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef __LUNAIX_AHCI_H
-#define __LUNAIX_AHCI_H
-
-/*
- * Macro naming rule:
- *      HBA_R[xxx]
- *          HBA Register [xxx]
- *          e.g. HBA_RPxCLB is Register PxCLB
- *
- * All registers offset are 0 based index of a DWORD array
- */
-
-#define AHCI_HBA_CLASS 0x10601
-
-#define HBA_RCAP 0
-#define HBA_RGHC 1
-#define HBA_RIS 2
-#define HBA_RPI 3
-#define HBA_RVER 4
-
-#define HBA_RPBASE (0x40)
-#define HBA_RPSIZE (0x80 >> 2)
-#define HBA_RPxCLB 0
-#define HBA_RPxFB 2
-#define HBA_RPxIS 4
-#define HBA_RPxIE 5
-#define HBA_RPxCMD 6
-#define HBA_RPxTFD 8
-#define HBA_RPxSIG 9
-#define HBA_RPxSSTS 10
-#define HBA_RPxSCTL 11
-#define HBA_RPxSERR 12
-#define HBA_RPxSACT 13
-#define HBA_RPxCI 14
-#define HBA_RPxSNTF 15
-#define HBA_RPxFBS 16
-
-#define HBA_PxCMD_FRE (1 << 4)
-#define HBA_PxCMD_ST (1)
-#define HBA_PxINTR_DMA (1 << 2)
-#define HBA_PxINTR_D2HR (1)
-
-#define HBA_RGHC_ACHI_ENABLE (1 << 31)
-#define HBA_RGHC_INTR_ENABLE (1 << 1)
-#define HBA_RGHC_RESET 1
-
-#define HBA_RPxSSTS_PWR(x) (((x) >> 8) & 0xf)
-#define HBA_RPxSSTS_IF(x) (((x) >> 4) & 0xf)
-#define HBA_RPxSSTS_PHYSTATE(x) ((x)&0xf)
-
-typedef unsigned int hba_reg_t;
-
-struct ahci_port
-{
-    hba_reg_t* regs;
-    unsigned int ssts;
-    void* cmdlstv;
-    void* fisv;
-};
-
-struct ahci_hba
-{
-    volatile hba_reg_t* base;
-    unsigned int ports_num;
-    unsigned int cmd_slots;
-    unsigned int version;
-    struct ahci_port* ports[32];
-};
-
-/**
- * @brief 初始化AHCI与HBA
- *
- */
-void
-ahci_init();
-
-void
-ahci_list_device();
-
-#endif /* __LUNAIX_AHCI_H */
diff --git a/lunaix-os/includes/hal/ahci/ahci.h b/lunaix-os/includes/hal/ahci/ahci.h
new file mode 100644 (file)
index 0000000..c0c483a
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef __LUNAIX_AHCI_H
+#define __LUNAIX_AHCI_H
+
+#include <stdint.h>
+
+/*
+ * Macro naming rule:
+ *      HBA_R[xxx]
+ *          HBA Register [xxx]
+ *          e.g. HBA_RPxCLB is Register PxCLB
+ *
+ * All registers offset are 0 based index of a DWORD array
+ */
+
+#define AHCI_HBA_CLASS 0x10601
+
+#define HBA_RCAP 0
+#define HBA_RGHC 1
+#define HBA_RIS 2
+#define HBA_RPI 3
+#define HBA_RVER 4
+
+#define HBA_RPBASE (0x40)
+#define HBA_RPSIZE (0x80 >> 2)
+#define HBA_RPxCLB 0
+#define HBA_RPxFB 2
+#define HBA_RPxIS 4
+#define HBA_RPxIE 5
+#define HBA_RPxCMD 6
+#define HBA_RPxTFD 8
+#define HBA_RPxSIG 9
+#define HBA_RPxSSTS 10
+#define HBA_RPxSCTL 11
+#define HBA_RPxSERR 12
+#define HBA_RPxSACT 13
+#define HBA_RPxCI 14
+#define HBA_RPxSNTF 15
+#define HBA_RPxFBS 16
+
+#define HBA_PxCMD_FRE (1 << 4)
+#define HBA_PxCMD_CR (1 << 15)
+#define HBA_PxCMD_FR (1 << 14)
+#define HBA_PxCMD_ST (1)
+#define HBA_PxINTR_DMA (1 << 2)
+#define HBA_PxINTR_D2HR (1)
+
+#define HBA_RGHC_ACHI_ENABLE (1 << 31)
+#define HBA_RGHC_INTR_ENABLE (1 << 1)
+#define HBA_RGHC_RESET 1
+
+#define HBA_RPxSSTS_PWR(x) (((x) >> 8) & 0xf)
+#define HBA_RPxSSTS_IF(x) (((x) >> 4) & 0xf)
+#define HBA_RPxSSTS_PHYSTATE(x) ((x)&0xf)
+
+#define HBA_DEV_SIG_ATAPI 0xeb140101
+#define HBA_DEV_SIG_ATA 0x00000101
+
+#define __HBA_PACKED__ __attribute__((packed))
+
+typedef unsigned int hba_reg_t;
+
+#define HBA_CMDH_FIS_LEN(fis_bytes) (((fis_bytes) / 4) & 0x1f)
+#define HBA_CMDH_ATAPI (1 << 5)
+#define HBA_CMDH_WRITE (1 << 6)
+#define HBA_CMDH_PREFETCH (1 << 7)
+#define HBA_CMDH_R (1 << 8)
+#define HBA_CMDH_CLR_BUSY (1 << 10)
+#define HBA_CMDH_PRDT_LEN(entries) (((entries)&0xffff) << 16)
+
+struct ahci_hba_cmdh
+{
+    uint16_t options;
+    uint16_t prdt_len;
+    uint32_t transferred_size;
+    uint32_t cmd_table_base;
+    uint32_t reserved[5];
+} __HBA_PACKED__;
+
+#define HBA_PRDTE_BYTE_CNT(cnt) ((cnt & 0x3FFFFF) | 0x1)
+
+struct ahci_hba_prdte
+{
+    uint32_t data_base;
+    uint32_t reserved[2];
+    uint32_t byte_count;
+} __HBA_PACKED__;
+
+struct ahci_hba_cmdt
+{
+    uint8_t command_fis[64];
+    uint8_t atapi_cmd[16];
+    uint8_t reserved[0x30];
+    struct ahci_hba_prdte entries[3];
+} __HBA_PACKED__;
+
+#define SATA_REG_FIS_D2H 0x34
+#define SATA_REG_FIS_H2D 0x27
+#define SATA_REG_FIS_COMMAND 0x80
+#define SATA_LBA_COMPONENT(lba, offset) ((((lba_lo) >> (offset)) & 0xff))
+
+struct sata_fis_head
+{
+    uint8_t type;
+    uint8_t options;
+    uint8_t status_cmd;
+    uint8_t feat_err;
+} __HBA_PACKED__;
+
+struct sata_reg_fis
+{
+    struct sata_fis_head head;
+
+    uint8_t lba0, lba8, lba16;
+    uint8_t dev;
+    uint8_t lba24, lba32, lba40;
+    uint8_t reserved1;
+
+    uint16_t count;
+
+    uint8_t reserved[6];
+} __HBA_PACKED__;
+
+struct sata_data_fis
+{
+    struct sata_fis_head head;
+
+    uint8_t data[0];
+} __HBA_PACKED__;
+
+struct ahci_device_info
+{
+    char serial_num[20];
+    char model[40];
+    uint32_t max_lba;
+    uint32_t sector_size;
+    uint8_t wwn[8];
+};
+
+struct ahci_port
+{
+    volatile hba_reg_t* regs;
+    unsigned int ssts;
+    struct ahci_hba_cmdh* cmdlst;
+    struct sata_fis_head* fis;
+    struct ahci_device_info* device_info;
+};
+
+struct ahci_hba
+{
+    volatile hba_reg_t* base;
+    unsigned int ports_num;
+    unsigned int cmd_slots;
+    unsigned int version;
+    struct ahci_port* ports[32];
+};
+
+#define ATA_IDENTIFY_DEVICE 0xec
+#define ATA_IDENTIFY_PAKCET_DEVICE 0xa1
+
+/**
+ * @brief 初始化AHCI与HBA
+ *
+ */
+void
+ahci_init();
+
+void
+ahci_list_device();
+
+int
+ahci_identify_device(struct ahci_port* port);
+
+#endif /* __LUNAIX_AHCI_H */
diff --git a/lunaix-os/includes/hal/ahci/utils.h b/lunaix-os/includes/hal/ahci/utils.h
new file mode 100644 (file)
index 0000000..1ff5f32
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __LUNAIX_AHCI_UTILS_H
+#define __LUNAIX_AHCI_UTILS_H
+
+#include <hal/ahci/ahci.h>
+#include <stdint.h>
+
+void
+ahci_parse_dev_info(struct ahci_device_info* dev_info, uint16_t* data);
+
+void
+ahci_parsestr(char* str, uint16_t* reg_start, int size_word);
+
+#endif /* __LUNAIX_UTILS_H */
index 98f57634f1a42963abfc6bc2290d696f195509bd..182058bf9835b444d9d56e8a5dbdac25fe1b2528 100644 (file)
@@ -119,4 +119,7 @@ vmm_next_free(uintptr_t start, int options);
 void*
 vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr);
 
+void*
+vmm_v2p(void* va);
+
 #endif /* __LUNAIX_VMM_H */
index 48a19045dbb5b801d5e901856b9c391f8ed4ec81..cbdadfb80d8bd45c3d4d5ed284d05b1fa49a29a6 100644 (file)
@@ -52,4 +52,12 @@ panick(const char* msg);
     while (!(cond))                                                            \
         ;
 
+#define wait_until_expire(cond, max)                                           \
+    ({                                                                         \
+        unsigned int __wcounter__ = (max);                                     \
+        while (!(cond) && __wcounter__-- > 0)                                  \
+            ;                                                                  \
+        __wcounter__;                                                          \
+    })
+
 #endif /* __LUNAIX_SPIKE_H */
index 3e408fd80836a09049370464b2fa9660bb3be307..d2578f7dc7d890ff6c66e12a913233b7051dc473 100644 (file)
@@ -51,7 +51,9 @@ _init_idt()
     _set_idt_intr_entry(APIC_LINT0_IV, 0x08, _asm_isr251, 0);
     _set_idt_intr_entry(APIC_SPIV_IV, 0x08, _asm_isr252, 0);
     _set_idt_intr_entry(APIC_TIMER_IV, 0x08, _asm_isr253, 0);
+
     _set_idt_intr_entry(PC_KBD_IV, 0x08, _asm_isr201, 0);
+    _set_idt_intr_entry(AHCI_HBA_IV, 0x08, _asm_isr202, 0);
 
     _set_idt_intr_entry(RTC_TIMER_IV, 0x08, _asm_isr210, 0);
 
index dc5c4c395ee750abfb379707cd5c26db5b3193bf..738214242db8573957dae50312ec285a66c14e80 100644 (file)
@@ -42,7 +42,9 @@
     isr_template APIC_TIMER_IV
     isr_template APIC_SPIV_IV
     isr_template RTC_TIMER_IV
+    
     isr_template PC_KBD_IV
+    isr_template AHCI_HBA_IV
 
     interrupt_wrapper:
         /*
index fe3d65cc46b7ca40ec4eacb232772754dbceba8d..6e134fd0e2ec4da15a1590fe0ccb971cde1a3d8e 100644 (file)
@@ -128,6 +128,25 @@ vmm_lookup(uintptr_t va, v_mapping* mapping)
     return 0;
 }
 
+void*
+vmm_v2p(void* va)
+{
+    uint32_t l1_index = L1_INDEX(va);
+    uint32_t l2_index = L2_INDEX(va);
+
+    x86_page_table* l1pt = (x86_page_table*)L1_BASE_VADDR;
+    x86_pte_t l1pte = l1pt->entry[l1_index];
+
+    if (l1pte) {
+        x86_pte_t* l2pte =
+          &((x86_page_table*)L2_VADDR(l1_index))->entry[l2_index];
+        if (l2pte) {
+            return PG_ENTRY_ADDR(*l2pte) | ((uintptr_t)va & 0xfff);
+        }
+    }
+    return 0;
+}
+
 void*
 vmm_mount_pd(uintptr_t mnt, void* pde)
 {
index e94397492c06d7a272d4d63e6ba4b0fcb6003983..dcd6bf49fc231be321cf885adddb72fe39536578 100644 (file)
@@ -14,7 +14,7 @@
 #include <stddef.h>
 
 #include <hal/acpi/acpi.h>
-#include <hal/ahci.h>
+#include <hal/ahci/ahci.h>
 #include <hal/apic.h>
 #include <hal/ioapic.h>
 #include <hal/pci.h>