📄 cmd64x.c
字号:
case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; default: return 1; }#ifdef CONFIG_BLK_DEV_IDEDMA (void) pci_write_config_byte(dev, pciU, regU);#endif /* CONFIG_BLK_DEV_IDEDMA */ err = ide_config_drive_speed(drive, speed); drive->current_speed = speed;#ifdef CONFIG_BLK_DEV_IDEDMA regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD);#endif /* CONFIG_BLK_DEV_IDEDMA */ return err;}#ifdef CONFIG_BLK_DEV_IDEDMAstatic int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte speed = 0x00; byte set_pio = 0x00; byte udma_33 = ((rev >= 0x05) || (ultra_66)) ? 1 : 0; byte udma_66 = eighty_ninty_three(drive); byte udma_100 = 0; int rval; switch(dev->device) { case PCI_DEVICE_ID_CMD_649: udma_100 = 1; break; case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_646: case PCI_DEVICE_ID_CMD_643: default: break; } if (drive->media != ide_disk) { cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n"); return ((int) ide_dma_off); } /* UltraDMA only supported on PCI646U and PCI646U2, * which correspond to revisions 0x03, 0x05 and 0x07 respectively. * Actually, although the CMD tech support people won't * tell me the details, the 0x03 revision cannot support * UDMA correctly without hardware modifications, and even * then it only works with Quantum disks due to some * hold time assumptions in the 646U part which are fixed * in the 646U2. * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. */ if ((id->dma_ultra & 0x0020) && (udma_100) && (udma_66) && (udma_33)) { speed = XFER_UDMA_5; } else if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { speed = XFER_UDMA_3; } else if ((id->dma_ultra & 0x0004) && (udma_33)) { speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (udma_33)) { speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (udma_33)) { speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { speed = XFER_SW_DMA_0; } else { set_pio = 1; } if (!drive->init_speed) drive->init_speed = speed; config_chipset_for_pio(drive, set_pio); if (set_pio) return ((int) ide_dma_off_quietly); if (cmd64x_tune_chipset(drive, speed)) return ((int) ide_dma_off); rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); return rval;}static int cmd64x_config_drive_for_dma (ide_drive_t *drive){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; unsigned int class_rev = 0; byte can_ultra_33 = 0; byte can_ultra_66 = 0; byte can_ultra_100 = 0; ide_dma_action_t dma_func = ide_dma_on; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; switch(dev->device) { case PCI_DEVICE_ID_CMD_649: can_ultra_100 = 1; case PCI_DEVICE_ID_CMD_648: can_ultra_66 = 1; case PCI_DEVICE_ID_CMD_643: can_ultra_33 = 1; break; case PCI_DEVICE_ID_CMD_646: can_ultra_33 = (class_rev >= 0x05) ? 1 : 0; can_ultra_66 = 0; can_ultra_100 = 0; break; default: return hwif->dmaproc(ide_dma_off, drive); } if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma && (drive->media == ide_disk)) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { dma_func = ide_dma_off; goto fast_ata_pio; } dma_func = ide_dma_off_quietly; if ((id->field_valid & 4) && (can_ultra_33)) { if (id->dma_ultra & 0x002F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; } } else if (id->field_valid & 2) {try_dma_modes: if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive, class_rev, 0); if (dma_func != ide_dma_on) goto no_dma_set; } } else if (ide_dmaproc(ide_dma_good_drive, drive)) { if (id->eide_dma_time > 150) { goto no_dma_set; } /* Consult the list of known "good" drives */ dma_func = config_chipset_for_dma(drive, class_rev, 0); if (dma_func != ide_dma_on) goto no_dma_set; } else { goto fast_ata_pio; } } else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio: dma_func = ide_dma_off_quietly;no_dma_set: config_chipset_for_pio(drive, 1); } return HWIF(drive)->dmaproc(dma_func, drive);}static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive){ byte dma_stat = 0; byte dma_alt_stat = 0; byte mask = (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; unsigned long dma_base = HWIF(drive)->dma_base; struct pci_dev *dev = HWIF(drive)->pci_dev; byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; switch (func) { case ide_dma_check: return cmd64x_config_drive_for_dma(drive); case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; outb(inb(dma_base)&~1, dma_base); /* stop DMA */ dma_stat = inb(dma_base+2); /* get DMA status */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ if (jack_slap) { byte dma_intr = 0; byte dma_mask = (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; byte dma_reg = (HWIF(drive)->channel) ? ARTTIM2 : CFR; (void) pci_read_config_byte(dev, dma_reg, &dma_intr); /* * DAMN BMIDE is not connected to PCI space! * Have to manually jack-slap that bitch! * To allow the PCI side to read incoming interrupts. */ (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */ } ide_destroy_dmatable(drive); /* purge DMA mappings */ return (dma_stat & 7) != 4; /* verify good DMA status */ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ dma_stat = inb(dma_base+2); (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat);#ifdef DEBUG printk("%s: dma_stat: 0x%02x dma_alt_stat: 0x%02x mask: 0x%02x\n", drive->name, dma_stat, dma_alt_stat, mask);#endif if (!(dma_alt_stat & mask)) { return 0; } return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ default: break; } /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive);}/* * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old * event order for DMA transfers. */static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; byte dma_stat; switch (func) { case ide_dma_check: return cmd64x_config_drive_for_dma(drive); case ide_dma_end: drive->waiting_for_dma = 0; dma_stat = inb(dma_base+2); /* get DMA status */ outb(inb(dma_base)&~1, dma_base); /* stop DMA */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ ide_destroy_dmatable(drive); /* and free any DMA resources */ return (dma_stat & 7) != 4; /* verify good DMA status */ default: break; } /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive);}#endif /* CONFIG_BLK_DEV_IDEDMA */unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name){ unsigned char mrdmode; unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff;#ifdef __i386__ if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); }#endif switch(dev->device) { case PCI_DEVICE_ID_CMD_643: break; case PCI_DEVICE_ID_CMD_646: printk("%s: chipset revision 0x%02X, ", name, class_rev); switch(class_rev) { case 0x07: case 0x05: printk("UltraDMA Capable"); break; case 0x03: printk("MultiWord DMA Force Limited"); break; case 0x01: default: printk("MultiWord DMA Limited, IRQ workaround enabled"); break; } printk("\n"); break; case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_649: break; default: break; } /* Set a good latency timer and cache line size value. */ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);#ifdef __sparc_v9__ (void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);#endif /* Setup interrupts. */ (void) pci_read_config_byte(dev, MRDMODE, &mrdmode); mrdmode &= ~(0x30); (void) pci_write_config_byte(dev, MRDMODE, mrdmode); /* Use MEMORY READ LINE for reads. * NOTE: Although not mentioned in the PCI0646U specs, * these bits are write only and won't be read * back as set or not. The PCI0646U2 specs clarify * this point. */ (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02); /* Set reasonable active/recovery/address-setup values. */ (void) pci_write_config_byte(dev, ARTTIM0, 0x40); (void) pci_write_config_byte(dev, DRWTIM0, 0x3f); (void) pci_write_config_byte(dev, ARTTIM1, 0x40); (void) pci_write_config_byte(dev, DRWTIM1, 0x3f);#ifdef __i386__ (void) pci_write_config_byte(dev, ARTTIM23, 0x1c);#else (void) pci_write_config_byte(dev, ARTTIM23, 0x5c);#endif (void) pci_write_config_byte(dev, DRWTIM23, 0x3f); (void) pci_write_config_byte(dev, DRWTIM3, 0x3f);#ifdef CONFIG_PPC (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);#endif /* CONFIG_PPC */#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; bmide_dev = dev; cmd64x_display_info = &cmd64x_get_info; }#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0;}unsigned int __init ata66_cmd64x (ide_hwif_t *hwif){ byte ata66 = 0; byte mask = (hwif->channel) ? 0x02 : 0x01; pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); return (ata66 & mask) ? 1 : 0;}void __init ide_init_cmd64x (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; if (!hwif->dma_base) return;#ifdef CONFIG_BLK_DEV_IDEDMA switch(dev->device) { case PCI_DEVICE_ID_CMD_649: case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_643: hwif->dmaproc = &cmd64x_dmaproc; break; case PCI_DEVICE_ID_CMD_646: hwif->chipset = ide_cmd646; if (class_rev == 0x01) { hwif->dmaproc = &cmd646_1_dmaproc; } else { hwif->dmaproc = &cmd64x_dmaproc; } break; default: break; }#endif /* CONFIG_BLK_DEV_IDEDMA */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -