]> Zhao Yanbai Git Server - kernel.git/commitdiff
读IDE设备时区分是ATA还是ATAPI
authoracevest <zhaoyanbai@126.com>
Sun, 22 Sep 2024 02:54:13 +0000 (10:54 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 22 Sep 2024 02:54:13 +0000 (10:54 +0800)
drivers/ata.c
drivers/ide.h
drivers/pci.c
include/pci.h

index a751cd9fd63d1f1ddc6de52487cb37440eb21a56..66158977ae2a327f8a5f0512146bfbcd2b07d8d9 100644 (file)
@@ -49,15 +49,89 @@ void ata_pio_read_data(int drv, int sect_cnt, void *dst) {
     insl(REG_DATA(drv), dst, (512 * sect_cnt) / sizeof(uint32_t));
 }
 
+void ata_io_wait() {
+    for (int i = 0; i < 65536; i++) {
+        asm("nop;");
+    }
+}
+
 // 这里所用的drv是逻辑编号 ATA0、ATA1下的Master、Salve的drv分别为0,1,2,3
-void ata_read_identify(int drv, int disable_intr) {
+bool ata_read_identify(int drv, int disable_intr, uint8_t *status, u16 *identify) {
+    memset(identify, 0, SECT_SIZE);
+
     uint8_t ctlv = 0x00;
     if (disable_intr != 0) {
         ctlv |= ATA_CTL_NIEN;
     }
+
     outb(ctlv, REG_CTL(drv));
+
     outb(0x00 | ((drv & 0x01) << 4), REG_DEVICE(drv));  // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
+
     outb(ATA_CMD_IDENTIFY, REG_CMD(drv));
+
+    ata_io_wait();
+
+    *status = inb(REG_STATUS(drv));
+
+    if ((*status) == 0 || (*status) == 0xFF) {
+        return false;
+    }
+
+    if (((*status) & ATA_STATUS_BSY) != 0) {
+        *status = inb(REG_STATUS(drv));
+    }
+
+    if (((*status) & ATA_STATUS_ERR) != 0) {
+        return false;
+    }
+
+    while (((*status) & ATA_STATUS_DRQ) == 0) {
+        *status = inb(REG_STATUS(drv));
+    }
+
+    insl(REG_DATA(drv), identify, SECT_SIZE / sizeof(uint32_t));
+
+    return true;
+}
+
+bool ata_read_identify_packet(int drv, int disable_intr, uint8_t *status, u16 *identify) {
+    memset(identify, 0, SECT_SIZE);
+
+    uint8_t ctlv = 0x00;
+    if (disable_intr != 0) {
+        ctlv |= ATA_CTL_NIEN;
+    }
+
+    outb(ctlv, REG_CTL(drv));
+
+    outb(0x00 | ((drv & 0x01) << 4), REG_DEVICE(drv));
+
+    outb(ATA_CMD_IDENTIFY_PACKET, REG_CMD(drv));
+
+    ata_io_wait();
+
+    *status = inb(REG_STATUS(drv));
+
+    if ((*status) == 0 || (*status) == 0xFF) {
+        return false;
+    }
+
+    if (((*status) & ATA_STATUS_BSY) != 0) {
+        *status = inb(REG_STATUS(drv));
+    }
+
+    if (((*status) & ATA_STATUS_ERR) != 0) {
+        return false;
+    }
+
+    while (((*status) & ATA_STATUS_DRQ) == 0) {
+        *status = inb(REG_STATUS(drv));
+    }
+
+    insl(REG_DATA(drv), identify, SECT_SIZE / sizeof(uint32_t));
+
+    return true;
 }
 
 void ata_read_identity_string(const uint16_t *identify, int bgn, int end, char *buf) {
@@ -71,8 +145,15 @@ void ata_read_identity_string(const uint16_t *identify, int bgn, int end, char *
     buf[i] = 0;
 }
 
+extern unsigned int IDE_CHL0_CMD_BASE;
+extern unsigned int IDE_CHL1_CMD_BASE;
+
+extern unsigned int IDE_CHL0_CTL_BASE;
+extern unsigned int IDE_CHL1_CTL_BASE;
+
 // 《AT Attachment 8 - ATA/ATAPI Command Set》
 void ide_ata_init() {
+    printk("IDE %04X %04X %04X %04X\n", IDE_CHL0_CMD_BASE, IDE_CHL1_CMD_BASE, IDE_CHL0_CTL_BASE, IDE_CHL1_CTL_BASE);
     for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) {
         int drv_no = i;
         int channel = drv_no >> 1;
@@ -113,19 +194,50 @@ void ide_ata_init() {
         //  1. 若为0,就认为没有IDE
         //  2. 等到status的BSY位清除
         //  3. 等到status的DRQ位或ERR位设置
+        uint8_t status = 0;
+        const char *ide_drive_type = "NONE";
+        if (ata_read_identify(drv_no, 1, &status, identify)) {
+            drv->present = 1;
+            drv->type = IDE_DRIVE_TYPE_ATA;
+            ide_drive_type = "ATA";
+        } else {
+            if (ata_read_identify_packet(drv_no, 1, &status, identify)) {
+                printk("ATAPI DEVICE\n");
+                drv->present = 1;
+                drv->type = IDE_DRIVE_TYPE_ATAPI;
+                ide_drive_type = "ATAPI";
+            } else {
+                drv->present = 0;
+                drv->type = IDE_DRIVE_TYPE_NONE;
+                ide_drive_type = "NONE";
+            }
+        }
 
-        ata_read_identify(drv_no, 1);
+        printk("ata[%d] status %x %s exists %s\n", i, status, drv->present == 1 ? "" : "not", ide_drive_type);
 
-        uint8_t status = inb(REG_STATUS(drv_no));
-        if (status == 0 || (status & ATA_STATUS_ERR) || (status & ATA_STATUS_RDY == 0)) {
+        // 所有ATAPI设备当成不存在
+        if (drv->type == IDE_DRIVE_TYPE_ATAPI) {
+            assert(drv->present == 1);
             drv->present = 0;
+        }
+
+        if (drv->present == 0) {
             continue;
-        } else {
-            drv->present = 1;
         }
 
-        printk("ata[%d] status %x %s exists\n", i, status, drv->present == 1 ? "" : "not");
-        insl(REG_DATA(drv_no), identify, SECT_SIZE / sizeof(uint32_t));
+        // insl(REG_DATA(drv_no), identify, SECT_SIZE / sizeof(uint32_t));
+
+        // Bit 15: 0 表示 ATA 设备,1 表示 ATAPI 设备。
+        // Bit 14-8: 保留。
+        // Bit 7: 1 表示设备支持可拆卸介质。
+        // Bit 6: 1 表示设备支持硬盘缓存。
+        // Bit 5-3: 保留。
+        // Bit 2: 1 表示设备支持应急电源降级。
+        // Bit 1: 1 表示设备支持硬件重置。
+        // Bit 0: 1 表示设备支持软重置。
+        uint16_t devtype = identify[ATA_IDENT_DEVTYPE];
+
+        printk("device type %04X\n", devtype);
 
         // 第49个word的第8个bit位表示是否支持DMA
         // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
@@ -141,25 +253,26 @@ void ide_ata_init() {
             drv->lba48 = 1;
             drv->max_lba = max_lba;
         }
-#if 0
-        uint16_t i80 = identify[80];
-        if (i80 & (1 << 8)) {
+#if 1
+        uint16_t ata_major = identify[80];
+        uint16_t ata_minor = identify[81];
+        if (ata_major & (1 << 8)) {
             printk("ATA8-ACS ");
         }
-        if (i80 & (1 << 7)) {
+        if (ata_major & (1 << 7)) {
             printk("ATA/ATAPI-7 ");
         }
-        if (i80 & (1 << 6)) {
+        if (ata_major & (1 << 6)) {
             printk("ATA/ATAPI-6 ");
         }
-        if (i80 & (1 << 5)) {
+        if (ata_major & (1 << 5)) {
             printk("ATA/ATAPI-5 ");
         }
-        if (i80 & (1 << 4)) {
+        if (ata_major & (1 << 4)) {
             printk("ATA/ATAPI-4 ");
         }
 
-        printk(" %02x\n", identify[81]);
+        printk("%04X %02X\n", ata_major, ata_minor);
 #endif
         printk("Ultra DMA modes: %04x\n", identify[88]);
 
index ea90706e8823b54458753b92a3f60624a30c102c..2c599ebbd69eba102097c66de6e6a7f497398bd1 100644 (file)
@@ -195,7 +195,12 @@ typedef struct _ide_pci_controller {
 #define NR_IDE_CONTROLLER 2
 extern ide_pci_controller_t ide_pci_controller[NR_IDE_CONTROLLER];
 
+#define IDE_DRIVE_TYPE_NONE 0x00
+#define IDE_DRIVE_TYPE_ATA 0x01
+#define IDE_DRIVE_TYPE_ATAPI 0x02
+
 typedef struct _ide_drive {
+    int type;
     int present;
     int drv_no;
     int dma;
index 214172000d4ef6495bf5ae334ce383e8641b93a7..e18cd32826f9ad64a1ff06865a88e8cc87984542 100644 (file)
@@ -123,7 +123,9 @@ pci_device_t *pci_find_device(unsigned int vendor, unsigned int device) {
     list_for_each(p, &pci_devs) {
         pci = list_entry(p, pci_device_t, list);
 
-        if (pci->vendor == vendor && pci->device == device) return pci;
+        if (pci->vendor == vendor && pci->device == device) {
+            return pci;
+        }
     }
 
     return 0;
index 26d72421c6e54cf66a206dbdd584aa55c423eaac..184da524704769b7eb4825c304c15aac989240ba 100644 (file)
@@ -120,6 +120,16 @@ typedef struct pci_device {
     unsigned int classcode;
     unsigned int hdr_type;
     // unsigned int bar0, bar1, bar2, bar3, bar4, bar5;
+    // 关于BAR寄存器
+    // 位0: 表示地址类型
+    //      0: 内存地址
+    //      1: I/O地址
+    // 若为内存地址,位1~2: 表示地址类型
+    //      00: 32位地址
+    //      01: 低位为32位,高位可扩展到64位地址
+    //      10: 保留,不使用
+    //      11: 32位地址,保留不使用
+    // 若为IO地址,位1~31:表示基地址
     unsigned int bars[BARS_CNT];
     unsigned int sub_system_id;
     unsigned int system_id;