int __ide_dma_on (ide_drive_t *drive)
{
- /* consult the list of known "bad" drives */
- if (__ide_dma_bad_drive(drive))
- return 1;
-
drive->using_dma = 1;
ide_toggle_bounce(drive, 1);
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat = hwif->INB(hwif->dma_status);
-#if 0 /* do not set unless you know what you are doing */
- if (dma_stat & 4) {
- u8 stat = hwif->INB(IDE_STATUS_REG);
- hwif->OUTB(hwif->dma_status, dma_stat & 0xE4);
- }
-#endif
/* return 1 if INTR asserted */
if ((dma_stat & 4) == 4)
return 1;
mode = XFER_MW_DMA_1;
}
- printk(KERN_DEBUG "%s: %s mode selected\n", drive->name,
+ mode = min(mode, req_mode);
+
+ printk(KERN_INFO "%s: %s mode selected\n", drive->name,
mode ? ide_xfer_verbose(mode) : "no DMA");
- return min(mode, req_mode);
+ return mode;
}
EXPORT_SYMBOL_GPL(ide_find_dma_mode);
if (__ide_dma_bad_drive(drive))
return 0;
+ if (ide_id_dma_bug(drive))
+ return 0;
+
if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
return config_drive_for_dma(drive);
return vdma ? 0 : -1;
}
-void ide_dma_verbose(ide_drive_t *drive)
+int ide_id_dma_bug(ide_drive_t *drive)
{
- struct hd_driveid *id = drive->id;
- ide_hwif_t *hwif = HWIF(drive);
+ struct hd_driveid *id = drive->id;
if (id->field_valid & 4) {
if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
- goto bug_dma_off;
- if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {
- if (((id->dma_ultra >> 11) & 0x1F) &&
- eighty_ninty_three(drive)) {
- if ((id->dma_ultra >> 15) & 1) {
- printk(", UDMA(mode 7)");
- } else if ((id->dma_ultra >> 14) & 1) {
- printk(", UDMA(133)");
- } else if ((id->dma_ultra >> 13) & 1) {
- printk(", UDMA(100)");
- } else if ((id->dma_ultra >> 12) & 1) {
- printk(", UDMA(66)");
- } else if ((id->dma_ultra >> 11) & 1) {
- printk(", UDMA(44)");
- } else
- goto mode_two;
- } else {
- mode_two:
- if ((id->dma_ultra >> 10) & 1) {
- printk(", UDMA(33)");
- } else if ((id->dma_ultra >> 9) & 1) {
- printk(", UDMA(25)");
- } else if ((id->dma_ultra >> 8) & 1) {
- printk(", UDMA(16)");
- }
- }
- } else {
- printk(", (U)DMA"); /* Can be BIOS-enabled! */
- }
+ goto err_out;
} else if (id->field_valid & 2) {
if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
- goto bug_dma_off;
- printk(", DMA");
- } else if (id->field_valid & 1) {
- goto bug_dma_off;
+ goto err_out;
}
- return;
-bug_dma_off:
- printk(", BUG DMA OFF");
- hwif->dma_off_quietly(drive);
- return;
+ return 0;
+err_out:
+ printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
+ return 1;
}
-EXPORT_SYMBOL(ide_dma_verbose);
-
int ide_set_dma(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
int rc;
- rc = ide_dma_check(drive);
+ /*
+ * Force DMAing for the beginning of the check.
+ * Some chipsets appear to do interesting
+ * things, if not checked and cleared.
+ * PARANOIA!!!
+ */
+ hwif->dma_off_quietly(drive);
- switch(rc) {
- case -1: /* DMA needs to be disabled */
- hwif->dma_off_quietly(drive);
- return -1;
- case 0: /* DMA needs to be enabled */
- return hwif->ide_dma_on(drive);
- case 1: /* DMA setting cannot be changed */
- break;
- default:
- BUG();
- break;
- }
+ rc = ide_dma_check(drive);
+ if (rc)
+ return rc;
- return rc;
+ return hwif->ide_dma_on(drive);
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
hwif->dma_base = base;
- if (hwif->mate)
- hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
- else
- hwif->dma_master = base;
-
if (!(hwif->dma_command))
hwif->dma_command = hwif->dma_base;
if (!(hwif->dma_vendor1))
hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
}
printk("\n");
-
- BUG_ON(!hwif->dma_master);
}
EXPORT_SYMBOL_GPL(ide_setup_dma);