From: acevest Date: Thu, 18 May 2023 15:52:54 +0000 (+0800) Subject: PCI IDE DMA 修改 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=923a6120b7a2eff2628170a84c9c66d6a4c21503;p=kernel.git PCI IDE DMA 修改 --- diff --git a/drivers/ata.c b/drivers/ata.c index a981df9..bef4eef 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -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 diff --git a/drivers/ide.c b/drivers/ide.c index cc9f0f4..f66e055 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -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); diff --git a/drivers/pci.c b/drivers/pci.c index a027ba1..4c35d0a 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -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: diff --git a/include/pci.h b/include/pci.h index d0ca66f..6deeeee 100644 --- a/include/pci.h +++ b/include/pci.h @@ -24,6 +24,12 @@ // 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)