?? cmd64x.c
字號:
(void) pci_write_config_byte(dev, pciU, regU); (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); } switch(speed) { case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; case XFER_UDMA_2: regU |= (unit ? 0x42 : 0x11); break; case XFER_UDMA_1: regU |= (unit ? 0x82 : 0x21); break; case XFER_UDMA_0: regU |= (unit ? 0xC2 : 0x31); break; case XFER_MW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_MW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_MW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; 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; } if (speed > XFER_PIO_4) { (void) pci_write_config_byte(dev, pciU, regU); regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); } return (ide_config_drive_speed(drive, speed));}static int config_chipset_for_dma (ide_drive_t *drive){ u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); config_chipset_for_pio(drive, !speed); if (!speed) return 0; if(ide_set_xfer_rate(drive, speed)) return 0; if (!drive->init_speed) drive->init_speed = speed; return ide_dma_enable(drive);}static int cmd64x_config_drive_for_dma (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; if ((id->capability & 1) != 0 && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) goto fast_ata_pio; if ((id->field_valid & 4) && cmd64x_ratemask(drive)) { if (id->dma_ultra & hwif->ultra_mask) { /* Force if Capable UltraDMA */ int dma = config_chipset_for_dma(drive); if ((id->field_valid & 2) && !dma) goto try_dma_modes; } } else if (id->field_valid & 2) {try_dma_modes: if ((id->dma_mword & hwif->mwdma_mask) || (id->dma_1word & hwif->swdma_mask)) { /* Force if Capable regular DMA modes */ if (!config_chipset_for_dma(drive)) goto no_dma_set; } } else if (hwif->ide_dma_good_drive(drive) && (id->eide_dma_time < 150)) { /* Consult the list of known "good" drives */ if (!config_chipset_for_dma(drive)) goto no_dma_set; } else { goto fast_ata_pio; } } else if ((id->capability & 8) || (id->field_valid & 2)) {fast_ata_pio:no_dma_set: config_chipset_for_pio(drive, 1); return hwif->ide_dma_off_quietly(drive); } return hwif->ide_dma_on(drive);}static int cmd64x_alt_dma_status (struct pci_dev *dev){ switch(dev->device) { case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_649: return 1; default: break; } return 0;}static int cmd64x_ide_dma_end (ide_drive_t *drive){ u8 dma_stat = 0, dma_cmd = 0; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; drive->waiting_for_dma = 0; /* read DMA command state */ dma_cmd = hwif->INB(hwif->dma_command); /* stop DMA */ hwif->OUTB((dma_cmd & ~1), hwif->dma_command); /* get DMA status */ dma_stat = hwif->INB(hwif->dma_status); /* clear the INTR & ERROR bits */ hwif->OUTB(dma_stat|6, hwif->dma_status); if (cmd64x_alt_dma_status(dev)) { u8 dma_intr = 0; u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; u8 dma_reg = (hwif->channel) ? ARTTIM2 : CFR; (void) pci_read_config_byte(dev, dma_reg, &dma_intr); /* clear the INTR bit */ (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); } /* purge DMA mappings */ ide_destroy_dmatable(drive); /* verify good DMA status */ return (dma_stat & 7) != 4;}static int cmd64x_ide_dma_test_irq (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 dma_alt_stat = 0, mask = (hwif->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; u8 dma_stat = hwif->INB(hwif->dma_status); (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 1 if INTR asserted */ if ((dma_stat & 4) == 4) return 1; return 0;}/* * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old * event order for DMA transfers. */static int cmd646_1_ide_dma_end (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = 0, dma_cmd = 0; drive->waiting_for_dma = 0; /* get DMA status */ dma_stat = hwif->INB(hwif->dma_status); /* read DMA command state */ dma_cmd = hwif->INB(hwif->dma_command); /* stop DMA */ hwif->OUTB((dma_cmd & ~1), hwif->dma_command); /* clear the INTR & ERROR bits */ hwif->OUTB(dma_stat|6, hwif->dma_status); /* and free any DMA resources */ ide_destroy_dmatable(drive); /* verify good DMA status */ return (dma_stat & 7) != 4;}static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name){ u32 class_rev = 0; u8 mrdmode = 0; 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(KERN_INFO "%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(KERN_INFO "%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) cmd_devs[n_cmd_devs++] = dev; if (!cmd64x_proc) { cmd64x_proc = 1; ide_pci_register_host_proc(&cmd64x_procs[0]); }#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0;}static unsigned int __init ata66_cmd64x (ide_hwif_t *hwif){ u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01; switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_CMD_643: case PCI_DEVICE_ID_CMD_646: return ata66; default: break; } pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66); return (ata66 & mask) ? 1 : 0;}static void __init init_hwif_cmd64x (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; unsigned int class_rev; hwif->autodma = 0; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; if (!hwif->dma_base) { hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; return; } hwif->atapi_dma = 1; hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; if (dev->device == PCI_DEVICE_ID_CMD_643) hwif->ultra_mask = 0x80; if (dev->device == PCI_DEVICE_ID_CMD_646) hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80; if (dev->device == PCI_DEVICE_ID_CMD_648) hwif->ultra_mask = 0x1f; hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_cmd64x(hwif); if (dev->device == PCI_DEVICE_ID_CMD_646) { hwif->chipset = ide_cmd646; if (class_rev == 0x01) { hwif->ide_dma_end = &cmd646_1_ide_dma_end; } else { hwif->ide_dma_end = &cmd64x_ide_dma_end; hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; } } else { hwif->ide_dma_end = &cmd64x_ide_dma_end; hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; } if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma;}static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase){ ide_setup_dma(hwif, dmabase, 8);}extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id){ ide_pci_device_t *d = &cmd64x_chipsets[id->driver_data]; if (dev->device != d->device) BUG(); ide_setup_pci_device(dev, d); MOD_INC_USE_COUNT; return 0;}static struct pci_device_id cmd64x_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, { 0, },};static struct pci_driver driver = { .name = "CMD64x IDE", .id_table = cmd64x_pci_tbl, .probe = cmd64x_init_one,};static int cmd64x_ide_init(void){ return ide_pci_register_driver(&driver);}static void cmd64x_ide_exit(void){ ide_pci_unregister_driver(&driver);}module_init(cmd64x_ide_init);module_exit(cmd64x_ide_exit);MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -