📄 cmd64x.c
字号:
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 & 0x007F) { /* 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 cmd680_dmaproc (ide_dma_action_t func, ide_drive_t *drive){ switch (func) { case ide_dma_check: return cmd64x_config_drive_for_dma(drive); default: break; } /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(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 */static int cmd680_busproc (ide_drive_t * drive, int state){#if 0 ide_hwif_t *hwif = HWIF(drive); u8 addr_mask = (hwif->channel) ? 0xB0 : 0xA0; u32 stat_config = 0; pci_read_config_dword(hwif->pci_dev, addr_mask, &stat_config); if (!hwif) return -EINVAL; switch (state) { case BUSSTATE_ON: hwif->drives[0].failures = 0; hwif->drives[1].failures = 0; break; case BUSSTATE_OFF: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; case BUSSTATE_TRISTATE: hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; break; default: return 0; } hwif->bus_state = state;#endif return 0;}void cmd680_reset (ide_drive_t *drive){#if 0 ide_hwif_t *hwif = HWIF(drive); u8 addr_mask = (hwif->channel) ? 0xB0 : 0xA0; byte reset = 0; pci_read_config_byte(hwif->pci_dev, addr_mask, &reset); pci_write_config_byte(hwif->pci_dev, addr_mask, reset|0x03);#endif}unsigned int cmd680_pci_init (struct pci_dev *dev, const char *name){ u8 tmpbyte = 0; pci_write_config_byte(dev, 0x80, 0x00); pci_write_config_byte(dev, 0x84, 0x00); pci_read_config_byte(dev, 0x8A, &tmpbyte); pci_write_config_byte(dev, 0x8A, tmpbyte|0x01); pci_write_config_word(dev, 0xA2, 0x328A); pci_write_config_dword(dev, 0xA4, 0x328A); pci_write_config_dword(dev, 0xA8, 0x4392); pci_write_config_dword(dev, 0xAC, 0x4009); pci_write_config_word(dev, 0xB2, 0x328A); pci_write_config_dword(dev, 0xB4, 0x328A); pci_write_config_dword(dev, 0xB8, 0x4392); pci_write_config_dword(dev, 0xBC, 0x4009);#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; bmide_dev = dev; cmd64x_display_info = &cmd680_get_info; }#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0;}unsigned int cmd64x_pci_init (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 pci_init_cmd64x (struct pci_dev *dev, const char *name){ if (dev->device == PCI_DEVICE_ID_CMD_680) return cmd680_pci_init (dev, name); return cmd64x_pci_init (dev, name);}unsigned int cmd680_ata66 (ide_hwif_t *hwif){ byte ata66 = 0; byte addr_mask = (hwif->channel) ? 0xB0 : 0xA0; pci_read_config_byte(hwif->pci_dev, addr_mask, &ata66); return (ata66 & 0x01) ? 1 : 0;}unsigned int cmd64x_ata66 (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;}unsigned int __init ata66_cmd64x (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; if (dev->device == PCI_DEVICE_ID_CMD_680) return cmd680_ata66(hwif); return cmd64x_ata66(hwif);}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->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_680: hwif->busproc = &cmd680_busproc; hwif->dmaproc = &cmd680_dmaproc; hwif->resetproc = &cmd680_reset; hwif->speedproc = &cmd680_tune_chipset; hwif->tuneproc = &cmd680_tuneproc; break; case PCI_DEVICE_ID_CMD_649: case PCI_DEVICE_ID_CMD_648: case PCI_DEVICE_ID_CMD_643: hwif->dmaproc = &cmd64x_dmaproc; hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; 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; } hwif->tuneproc = &cmd64x_tuneproc; hwif->speedproc = &cmd64x_tune_chipset; break; default: break; }#endif /* CONFIG_BLK_DEV_IDEDMA */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -