]> Zhao Yanbai Git Server - kernel.git/commitdiff
PCI IDE DMA 修改
authoracevest <zhaoyanbai@126.com>
Thu, 18 May 2023 15:52:54 +0000 (23:52 +0800)
committeracevest <zhaoyanbai@126.com>
Thu, 18 May 2023 15:53:00 +0000 (23:53 +0800)
drivers/ata.c
drivers/ide.c
drivers/pci.c
include/pci.h

index a981df9e262a2e0eefb12b782ead08dce2974f38..bef4eef185ae1b083192b67f9bd8819b7fad3961 100644 (file)
@@ -87,7 +87,7 @@ void ide_ata_init() {
         // 第49个word的第8个bit位表示是否支持DMA
         // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
         // 第100~103个word的八个字节表示user的LBA最大值
-        printk("%04x %04x %d %d\n", identify[49], 1 << 8, identify[49] & (1 << 8), (identify[49] & (1 << 8)) != 0);
+        // printk("%04x %04x %d %d\n", identify[49], 1 << 8, identify[49] & (1 << 8), (identify[49] & (1 << 8)) != 0);
         if ((identify[49] & (1 << 8)) != 0) {
             ide_drives[i].dma = 1;
         }
@@ -135,13 +135,12 @@ void ata_init() {
     r.count = 1;
     r.buf = mbr_buf;
     send_disk_request(&r);
-
     uint16_t *p = (uint16_t *)mbr_buf;
     for (int i = 0; i < 256; i++) {
         if (i % 12 == 0) {
             printk("\n[%03d] ", i * 2);
         }
-        printk("%04x ", p[i]);
+        printk("%04x.", p[i]);
     }
 }
 
@@ -200,8 +199,26 @@ void ata_read_identify_old(int dev) {  // 这里所用的dev是逻辑编号 ATA0
 
 // ATA_CMD_READ_DMA_EXT
 void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest) {
-    // 停止DMA
-    outb(PCI_IDE_CMD_STOP, ide_pci_controller.bus_cmd);
+    // Intel®
+    //  82801CA (ICH3), 82801BA
+    // (ICH2), 82801AA (ICH), and 82801AB
+    // (ICH0) IDE Controller
+    // Programmer’s Reference Manua
+    // Page 25. Table 23. BMIC1 and BMIC2
+
+    // • The Bus Master Read/Write Control bit【第3位】 shall set the transfer direction for DMA transfers. This
+    // bit must NOT be changed when the bus master function is active. While an Ultra DMA transfer
+    // is in progress, this bit will be READ ONLY. The bit will return to read/write once the
+    // synchronous DMA transfer has been completed or halted.
+
+    // • The Start/Stop Bus Master bit【第0位】 shall be the control method to start or stop the DMA transfer
+    // engine. When this bit is set to 1, bus master operation starts. The controller transfers data
+    // between the IDE device and memory only while this bit is set. Master operation can be stopped
+    // by writing a 0 to this bit. This results in all state information being lost (i.e., master mode
+    // operation cannot be stopped and then resumed).
+
+    // 停止DMA,并设置为读(这里的WRITE是对DMA控制器来说)
+    outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_STOP, ide_pci_controller.bus_cmd);
 
     // 配置描述符表
     unsigned long dest_paddr = va2pa(dest);
@@ -262,7 +279,24 @@ void ata_dma_read_ext(int dev, uint64_t pos, uint16_t count, void *dest) {
 
     // 指定DMA操作为读取硬盘操作,内核用DMA读取,对硬盘而言是写出
     // 并设置DMA的开始位,开始DMA
-    outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, ide_pci_controller.bus_cmd);
+    outb(PCI_IDE_CMD_START, ide_pci_controller.bus_cmd);
+}
+
+// TODO
+int ata_dma_stop() {
+    uint8_t x = inb(ide_pci_controller.bus_cmd);
+    x &= ~PCI_IDE_CMD_START;
+    outb(x, ide_pci_controller.bus_cmd);
+
+    uint8_t status = inb(ide_pci_controller.bus_status);
+    outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, ide_pci_controller.bus_status);
+
+    // TODO
+    if (status & PCI_IDE_STATUS_ERR) {
+        return -1;
+    }
+
+    return 0;
 }
 
 // ATA_CMD_READ_PIO_EXT
index cc9f0f4e02a0d8c7f876937162c55295b2893ccc..f66e0559213a45d78486a75e75e012211ba949b9 100644 (file)
@@ -193,12 +193,14 @@ void ide_pci_init(pci_device_t *pci) {
 
 //     kfree(buf);
 // }
-
+const char *pci_get_info(unsigned int classcode, unsigned int progif);
 void init_pci_controller(unsigned int classcode) {
     pci_device_t *pci = pci_find_device_by_classcode(classcode);
     if (pci != 0 && pci->intr_line < 16) {
-        printk("found pci vendor %04x device %04x class %04x intr %d progif: %x\n", pci->vendor, pci->device,
-               pci->classcode, pci->intr_line, pci->progif);
+        printk("found pci %03d:%02d.%d #%02d %04X:%04X ProgIF %02x %s\n", pci->bus, pci->dev, pci->devfn,
+               pci->intr_line, pci->vendor, pci->device, pci->progif, pci_get_info(pci->classcode, pci->progif));
+        // printk("found pci vendor %04x device %04x class %04x intr %d progif: %x\n", pci->vendor, pci->device,
+        //        pci->classcode, pci->intr_line, pci->progif);
         // printl(17, "found pci vendor %04x device %04x class %04x intr %d", pci->vendor, pci->device,
         // pci->classcode,
         // pci->intr_line);
index a027ba10a755c2491600a9b249f9b87eb07d4e49..4c35d0a101ce47d409182e40829d34a08c42d43a 100644 (file)
@@ -149,9 +149,11 @@ void dump_pci_dev() {
 
     list_for_each(p, &pci_devs) {
         pci_device_t *pci = list_entry(p, pci_device_t, list);
-        printk("vendor %04x device %04x class %04x:%02x bus %d intr %3d ", pci->vendor, pci->device, pci->classcode,
-               pci->progif, pci->bus, pci->intr_line);
-        printk("%s\n", pci_get_info(pci->classcode, pci->progif));
+        // printk("vendor %04x device %04x class %04x:%02x bus %d intr %3d ", pci->vendor, pci->device, pci->classcode,
+        //        pci->progif, pci->bus, pci->intr_line);
+        // printk("%s\n", pci_get_info(pci->classcode, pci->progif));
+        printk("PCI %03d:%02d.%d #%02d %04X:%04X %s\n", pci->bus, pci->dev, pci->devfn, pci->intr_line, pci->vendor,
+               pci->device, pci_get_info(pci->classcode, pci->progif));
 #if 0
         switch (pci->hdr_type) {
         case PCI_HDRTYPE_NORMAL:
index d0ca66f7dc482e3d0f5472d1d804cc94ad70e9e9..6deeeee4bf666c318f43bb6e237baeb956b34bb1 100644 (file)
 
 // PCI Command
 // 这个PCI_CMD是写入PCI_ADDR的,通过bus,dev,fn,reg可以定位到某个PCI总线(可以有多条PCI总线)上的某个设备的某个功能的某个寄存器
+// 0 ~ 7: 寄存器偏移
+// 8 ~ 10: 功能号
+// 11 ~ 15: 设备号
+// 16 ~ 23: 总线号
+// 24 ~ 30: 保留
+// 31: 有效位
 #define PCI_CMD(bus, dev, fn, reg) (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | reg)
 #define PCI_CONFIG_CMD(cmd) (cmd & ~3)
 #define PCI_GET_CMD_REG(cmd) (cmd & 0xFF)