📄 cmd64x.c
字号:
case XFER_MW_DMA_1: program_cycle_times(drive, 150, 80); break; case XFER_MW_DMA_0: program_cycle_times(drive, 480, 215); break; default: return; } if (speed >= XFER_SW_DMA_0) (void) pci_write_config_byte(dev, pciU, regU);}static int cmd648_ide_dma_end (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); int err = __ide_dma_end(drive); u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; u8 mrdmode = inb(hwif->dma_master + 0x01); /* clear the interrupt bit */ outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask, hwif->dma_master + 0x01); return err;}static int cmd64x_ide_dma_end (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; int irq_reg = hwif->channel ? ARTTIM23 : CFR; u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; u8 irq_stat = 0; int err = __ide_dma_end(drive); (void) pci_read_config_byte(dev, irq_reg, &irq_stat); /* clear the interrupt bit */ (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask); return err;}static int cmd648_ide_dma_test_irq (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; u8 dma_stat = inb(hwif->dma_status); u8 mrdmode = inb(hwif->dma_master + 0x01);#ifdef DEBUG printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n", drive->name, dma_stat, mrdmode, irq_mask);#endif if (!(mrdmode & irq_mask)) return 0; /* return 1 if INTR asserted */ if (dma_stat & 4) return 1; return 0;}static int cmd64x_ide_dma_test_irq (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; int irq_reg = hwif->channel ? ARTTIM23 : CFR; u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; u8 dma_stat = inb(hwif->dma_status); u8 irq_stat = 0; (void) pci_read_config_byte(dev, irq_reg, &irq_stat);#ifdef DEBUG printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n", drive->name, dma_stat, irq_stat, irq_mask);#endif if (!(irq_stat & irq_mask)) return 0; /* return 1 if INTR asserted */ if (dma_stat & 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 = inb(hwif->dma_status); /* read DMA command state */ dma_cmd = inb(hwif->dma_command); /* stop DMA */ outb(dma_cmd & ~1, hwif->dma_command); /* clear the INTR & ERROR bits */ 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 __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name){ u8 mrdmode = 0; if (dev->device == PCI_DEVICE_ID_CMD_646) { switch (dev->revision) { case 0x07: case 0x05: printk("%s: UltraDMA capable\n", name); break; case 0x03: default: printk("%s: MultiWord DMA force limited\n", name); break; case 0x01: printk("%s: MultiWord DMA limited, " "IRQ workaround enabled\n", name); break; } } /* Set a good latency timer and cache line size value. */ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); /* FIXME: pci_set_master() to ensure a good latency timer value */ /* * Enable interrupts, select MEMORY READ LINE for reads. * * NOTE: although not mentioned in the PCI0646U specs, * bits 0-1 are write only and won't be read back as * set or not -- PCI0646U2 specs clarify this point. */ (void) pci_read_config_byte (dev, MRDMODE, &mrdmode); mrdmode &= ~0x30; (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) cmd_devs[n_cmd_devs++] = dev; if (!cmd64x_proc) { cmd64x_proc = 1; ide_pci_create_host_proc("cmd64x", cmd64x_get_info); }#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */ return 0;}static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01; switch (dev->device) { case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_649: pci_read_config_byte(dev, BMIDECSR, &bmidecsr); return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; default: return ATA_CBL_PATA40; }}static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; hwif->set_pio_mode = &cmd64x_set_pio_mode; hwif->set_dma_mode = &cmd64x_set_dma_mode; if (!hwif->dma_base) return; /* * 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 (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5) hwif->ultra_mask = 0x00; if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = ata66_cmd64x(hwif); switch (dev->device) { case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_649: alt_irq_bits: hwif->ide_dma_end = &cmd648_ide_dma_end; hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq; break; case PCI_DEVICE_ID_CMD_646: if (dev->revision == 0x01) { hwif->ide_dma_end = &cmd646_1_ide_dma_end; break; } else if (dev->revision >= 0x03) goto alt_irq_bits; /* fall thru */ default: hwif->ide_dma_end = &cmd64x_ide_dma_end; hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; break; }}static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { { /* 0 */ .name = "CMD643", .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* no udma */ },{ /* 1 */ .name = "CMD646", .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .chipset = ide_cmd646, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, },{ /* 2 */ .name = "CMD648", .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, },{ /* 3 */ .name = "CMD649", .init_chipset = init_chipset_cmd64x, .init_hwif = init_hwif_cmd64x, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .host_flags = IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE, .pio_mask = ATA_PIO5, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, }};static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id){ struct ide_port_info d; u8 idx = id->driver_data; d = cmd64x_chipsets[idx]; /* * The original PCI0646 didn't have the primary channel enable bit, * it appeared starting with PCI0646U (i.e. revision ID 3). */ if (idx == 1 && dev->revision < 3) d.enablebits[0].reg = 0; return ide_setup_pci_device(dev, &d);}static const struct pci_device_id cmd64x_pci_tbl[] = { { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 }, { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_646), 1 }, { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_648), 2 }, { PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_649), 3 }, { 0, },};MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);static struct pci_driver driver = { .name = "CMD64x_IDE", .id_table = cmd64x_pci_tbl, .probe = cmd64x_init_one,};static int __init cmd64x_ide_init(void){ return ide_pci_register_driver(&driver);}module_init(cmd64x_ide_init);MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -