📄 ide-dma.c
字号:
// printk ("***************\n"); do { unsigned char *virt_addr = bh->b_data; unsigned int size = bh->b_size; if (nents >= PRD_ENTRIES) return 0; while ((bh = bh->b_reqnext) != NULL) { if ((virt_addr + size) != (unsigned char *) bh->b_data) break; size += bh->b_size; } memset(&sg[nents], 0, sizeof(*sg)); sg[nents].address = virt_addr; sg[nents].length = size; nents++; } while (bh != NULL);// return pci_map_sg(PCIDEV(hwif), sg, nents, hwif->sg_dma_direction); { int i; for (i = 0; i < nents; i++, sg++) {// consistent_sync(sg->address, sg->length, direction); sg->dma_address = virt_to_bus(sg->address); } } return nents;}/* * ide_build_dmatable() prepares a dma request. * Returns 0 if all went okay, returns 1 otherwise. * May also be invoked from trm290.c */int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func){ unsigned int *table = HWIF(drive)->dmatable_cpu;#ifdef CONFIG_BLK_DEV_TRM290 unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);#else const int is_trm290_chipset = 0;#endif unsigned int count = 0; int i; struct scatterlist *sg; HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); if (!i) return 0; sg = HWIF(drive)->sg_table; while (i && sg_dma_len(sg)) { u32 cur_addr; u32 cur_len; cur_addr = sg_dma_address(sg); cur_len = sg_dma_len(sg); /* * Fill in the dma table, without crossing any 64kB boundaries. * Most hardware requires 16-bit alignment of all blocks, * but the trm290 requires 32-bit alignment. */ while (cur_len) { if (count++ >= PRD_ENTRIES) { printk("%s: DMA table too small\n", drive->name); goto use_pio_instead; } else { u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); if (bcount > cur_len) bcount = cur_len; *table++ = cpu_to_le32(cur_addr); xcount = bcount & 0xffff; if (is_trm290_chipset) xcount = ((xcount >> 2) - 1) << 16; if (xcount == 0x0000) { /* * Most chipsets correctly interpret a length of 0x0000 as 64KB, * but at least one (e.g. CS5530) misinterprets it as zero (!). * So here we break the 64KB entry into two 32KB entries instead. */ if (count++ >= PRD_ENTRIES) { printk("%s: DMA table too small\n", drive->name); goto use_pio_instead; } *table++ = cpu_to_le32(0x8000); *table++ = cpu_to_le32(cur_addr + 0x8000); xcount = 0x8000; } *table++ = cpu_to_le32(xcount); cur_addr += bcount; cur_len -= bcount; } } sg++; i--; } if (count) { if (!is_trm290_chipset) *--table |= cpu_to_le32(0x80000000); return count; } printk("%s: empty DMA table?\n", drive->name);use_pio_instead: pci_unmap_sg(PCIDEV(HWIF(drive)), HWIF(drive)->sg_table, HWIF(drive)->sg_nents, HWIF(drive)->sg_dma_direction); HWIF(drive)->sg_dma_active = 0; return 0; /* revert to PIO for this request */}/* Teardown mappings after DMA has completed. */void ide_destroy_dmatable (ide_drive_t *drive){ struct pci_dev *dev = PCIDEV(HWIF(drive)); struct scatterlist *sg = HWIF(drive)->sg_table; int nents = HWIF(drive)->sg_nents; pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction); HWIF(drive)->sg_dma_active = 0;}/* * For both Blacklisted and Whitelisted drives. * This is setup to be called as an extern for future support * to other special driver code. */int check_drive_lists (ide_drive_t *drive, int good_bad){ struct hd_driveid *id = drive->id;#ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS if (good_bad) { return in_drive_list(id, drive_whitelist); } else { int blacklist = in_drive_list(id, drive_blacklist); if (blacklist) printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); return(blacklist); }#else /* !CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ const char **list; if (good_bad) { /* Consult the list of known "good" drives */ list = good_dma_drives; while (*list) { if (!strcmp(*list++,id->model)) return 1; } } else { /* Consult the list of known "bad" drives */ list = bad_dma_drives; while (*list) { if (!strcmp(*list++,id->model)) { printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); return 1; } } }#endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ return 0;}int report_drive_dmaing (ide_drive_t *drive){ struct hd_driveid *id = drive->id; if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { if ((id->dma_ultra >> 13) & 1) { printk(", UDMA(100)"); /* UDMA BIOS-enabled! */ } else if ((id->dma_ultra >> 12) & 1) { printk(", UDMA(66)"); /* UDMA BIOS-enabled! */ } else { printk(", UDMA(44)"); /* UDMA BIOS-enabled! */ } } else if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { if ((id->dma_ultra >> 10) & 1) { printk(", UDMA(33)"); /* UDMA BIOS-enabled! */ } else if ((id->dma_ultra >> 9) & 1) { printk(", UDMA(25)"); /* UDMA BIOS-enabled! */ } else { printk(", UDMA(16)"); /* UDMA BIOS-enabled! */ } } else if (id->field_valid & 4) { printk(", (U)DMA"); /* Can be BIOS-enabled! */ } else { printk(", DMA"); } return 1;}static int config_drive_for_dma (ide_drive_t *drive){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); int autodma = hwif->autodma;#ifndef CONFIG_ARCH_JASPER // we dont have no BIOS if (hwif->chipset != ide_trm290 && hwif->chipset != ide_acorn) { /* take note of what the bios did when setting up * the interface. If the BIOS didn't configure * the drive for DMA mode, then we should not use * it unless we are prepared to configure the * drive as well. -- rmk */ byte dma_stat = inb(hwif->dma_base+BMIS_OFFSET); if (drive->select.b.unit) { if (!(dma_stat & 0x40)) autodma = 0; } else { if (!(dma_stat & 0x20)) autodma = 0; } }#endif printk ("config_drive_for_dma:\n"); printk (" capability = 0x%04x\n", id->capability); printk (" field_valid = 0x%04x\n", id->field_valid); printk (" dma_ultra = 0x%04x\n", id->dma_ultra); printk (" dma_lword (s) = 0x%04x\n", id->dma_1word); printk (" dma_mword (m) = 0x%04x\n", id->dma_mword); printk (" autodma = 0x%04x\n", autodma); if (id && (id->capability & 1) && autodma) { /* Consult the list of known "bad" drives */// if (ide_dmaproc(ide_dma_bad_drive, drive))// return hwif->dmaproc(ide_dma_off, drive); /* Enable DMA on any drive that has UltraDMA (mode 3/4/5) enabled */// if ((id->field_valid & 4) && (eighty_ninty_three(drive)))// if ((id->dma_ultra & (id->dma_ultra >> 11) & 7))// {// printk("UltraDMA mode 3/4/5\n");// return hwif->dmaproc(ide_dma_on, drive);// } /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */// if (id->field_valid & 4) /* UltraDMA */// if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))// {// printk("UltraDMA mode 0/1/2\n");// return hwif->dmaproc(ide_dma_on, drive);// } /* Enable DMA on any drive that has UltraDMA (mode 2) supported, but not enabled */ if (id->dma_ultra & (1 << 2)) { printk("Jasper IDE controller activated - UDMA mode 2\n"); outl (0x3, JASPER_IDE_BASE + 0x54); // enable UDMA outl (0x22,JASPER_IDE_BASE + 0x58); // UDMA2 - Cycle time = 4 clocks, Ready to Pause = 8 clocks ide_config_drive_speed (drive, XFER_UDMA_2); ide_config_drive_speed (drive, XFER_UDMA_2); return hwif->dmaproc(ide_dma_on, drive); } /* Enable DMA on any drive that has UltraDMA (mode 1) supported, but not enabled */ if (id->dma_ultra & (1 << 1)) { printk("Jasper IDE controller activated - UDMA mode 1\n"); outl (0x3, JASPER_IDE_BASE + 0x54); // enable UDMA outl (0x11,JASPER_IDE_BASE + 0x58); // UDMA1 - Cycle time = 6 clocks, Ready to Pause = 10 clocks ide_config_drive_speed (drive, XFER_UDMA_1); ide_config_drive_speed (drive, XFER_UDMA_1); return hwif->dmaproc(ide_dma_on, drive); } /* Enable DMA on any drive that has UltraDMA (mode 0) supported, but not enabled */ if (id->dma_ultra & (1 << 1)) { printk("Jasper IDE controller activated - UDMA mode 0\n"); outl (0x3, JASPER_IDE_BASE + 0x54); // enable UDMA outl (0x00,JASPER_IDE_BASE + 0x58); // UDMA0 - Cycle time = 6 clocks, Ready to Pause = 10 clocks ide_config_drive_speed (drive, XFER_UDMA_0); ide_config_drive_speed (drive, XFER_UDMA_0); return hwif->dmaproc(ide_dma_on, drive); } /* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */ if (id->field_valid & 2) /* regular DMA */ { // XXX vincent if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404) return hwif->dmaproc(ide_dma_on, drive); // allow any mode if (id->dma_mword & 0xff00) // single word dma return hwif->dmaproc(ide_dma_on, drive); if (id->dma_1word & 0xff00) // multiword dma return hwif->dmaproc(ide_dma_on, drive); } /* Consult the list of known "good" drives */ if (ide_dmaproc(ide_dma_good_drive, drive)) return hwif->dmaproc(ide_dma_on, drive); } printk ("DMA disabled quitely\n"); return hwif->dmaproc(ide_dma_off_quietly, drive);}#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT/* * 1 dmaing, 2 error, 4 intr */static int dma_timer_expiry (ide_drive_t *drive){ byte dma_stat = inb(HWIF(drive)->dma_base+BMIS_OFFSET);#ifdef DEBUG printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);#endif /* DEBUG */#if 1 HWGROUP(drive)->expiry = NULL; /* one free ride for now */#endif if (dma_stat & 2) { /* ERROR */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -