📄 piix.c
字号:
case XFER_PIO_2: case XFER_PIO_0: break; default: return -1; } if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) pci_write_config_byte(dev, 0x48, reg48 | u_flag); if (speed == XFER_UDMA_5) { pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); } else { pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } if ((reg4a & a_speed) != u_speed) pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); if (speed > XFER_UDMA_2) { if (!(reg54 & v_flag)) pci_write_config_byte(dev, 0x54, reg54 | v_flag); } else pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); } else { if (reg48 & u_flag) pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); if (reg54 & v_flag) pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); if (reg55 & w_flag) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); } piix_tune_drive(drive, piix_dma_2_pio(speed)); return (ide_config_drive_speed(drive, speed));}/** * piix_faulty_dma0 - check for DMA0 errata * @hwif: IDE interface to check * * If an ICH/ICH0/ICH2 interface is is operating in multi-word * DMA mode with 600nS cycle time the IDE PIO prefetch buffer will * inadvertently provide an extra piece of secondary data to the primary * device resulting in data corruption. * * With such a device this test function returns true. This allows * our tuning code to follow Intel recommendations and use PIO on * such devices. */ static int piix_faulty_dma0(ide_hwif_t *hwif){ switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_INTEL_82801AA_1: /* ICH */ case PCI_DEVICE_ID_INTEL_82801AB_1: /* ICH0 */ case PCI_DEVICE_ID_INTEL_82801BA_8: /* ICH2 */ case PCI_DEVICE_ID_INTEL_82801BA_9: /* ICH2 */ return 1; } return 0;}/** * piix_config_drive_for_dma - configure drive for DMA * @drive: IDE drive to configure * * Set up a PIIX interface channel for the best available speed. * We prefer UDMA if it is available and then MWDMA. If DMA is * not available we switch to PIO and return 0. */ static int piix_config_drive_for_dma (ide_drive_t *drive){ u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); /* Some ICH devices cannot support DMA mode 0 */ if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive))) speed = 0; /* If no DMA speed was available or the chipset has DMA bugs then disable DMA and use PIO */ if (!speed || no_piix_dma) { u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); } (void) piix_tune_chipset(drive, speed); return ide_dma_enable(drive);}/** * piix_config_drive_xfer_rate - set up an IDE device * @drive: IDE drive to configure * * Set up the PIIX interface for the best available speed on this * interface, preferring DMA to PIO. */ static int piix_config_drive_xfer_rate (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; drive->init_speed = 0; if ((id->capability & 1) && (drive->autodma)) { /* Consult the list of known "bad" drives. */ if (hwif->ide_dma_bad_drive(drive)) { goto fast_ata_pio; } /** * Try to turn DMA on if: * - UDMA or EIDE modes are supported or * - drive is a known "good" drive * * Checks for best mode supported are down later by * piix_config_drive_for_dma() -> ide_dma_speed() */ if ((id->field_valid & (4 | 2)) || (hwif->ide_dma_good_drive(drive) && (id->eide_dma_time < 150))) { if (piix_config_drive_for_dma(drive)) { return hwif->ide_dma_on(drive); } } /* For some reason DMA wasn't turned on, so try PIO. */ goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) { /* Find best PIO mode. */fast_ata_pio: hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ return 0;}/** * ich3_busproc - bus isolation ioctl * @drive: drive to isolate/restore * @state: bus state to set * * Used by the ICH3 to handle bus isolation. We have to do * a little bit of fixing to keep the hardware happy. */ static int ich3_busproc (ide_drive_t * drive, int state){ ide_hwif_t *hwif = HWIF(drive); u32 sig_mode; int shift; int bits; if(hwif->channel == 0) shift = 17; else shift = 19; switch (state) { case BUSSTATE_ON: bits = 0x00; hwif->drives[0].failures = 0; hwif->drives[1].failures = 0; break; case BUSSTATE_OFF: bits = 0x01; break; case BUSSTATE_TRISTATE: bits = 0x10; break; default: return -EINVAL; } if(bits) { int port = hwif->channel == 0 ? 0x40 : 0x42; u16 reg; hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; /* Turn off IORDY checking to avoid hangs */ pci_read_config_word(hwif->pci_dev, port, ®); reg&=~(1<<5)|(1<<1); pci_write_config_word(hwif->pci_dev, port, reg); } /* Todo: Check locking */ pci_read_config_dword(hwif->pci_dev, 0x54, &sig_mode); sig_mode&=~(3<<shift); sig_mode|=(bits<<shift); pci_write_config_dword(hwif->pci_dev, 0x54, sig_mode); hwif->bus_state = state; return 0;}/** * init_chipset_piix - set up the PIIX chipset * @dev: PCI device to set up * @name: Name of the device * * Initialize the PCI device as required. For the PIIX this turns * out to be nice and simple */ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name){ switch(dev->device) { case PCI_DEVICE_ID_INTEL_82801EB_1: case PCI_DEVICE_ID_INTEL_82801AA_1: case PCI_DEVICE_ID_INTEL_82801AB_1: case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_11: case PCI_DEVICE_ID_INTEL_82801DB_10: case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801EB_11: case PCI_DEVICE_ID_INTEL_82801E_11: case PCI_DEVICE_ID_INTEL_ESB_2: case PCI_DEVICE_ID_INTEL_ICH6_2: { unsigned int extra = 0; pci_read_config_dword(dev, 0x54, &extra); pci_write_config_dword(dev, 0x54, extra|0x400); } default: break; }#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) piix_devs[n_piix_devs++] = dev; if (!piix_proc) { piix_proc = 1; ide_pci_register_host_proc(&piix_procs[0]); }#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ return 0;}/** * init_hwif_piix - fill in the hwif for the PIIX * @hwif: IDE interface * * Set up the ide_hwif_t for the PIIX interface according to the * capabilities of the hardware. */ static void __init init_hwif_piix (ide_hwif_t *hwif){ u8 reg54h = 0, reg55h = 0, ata66 = 0; u8 mask = hwif->channel ? 0xc0 : 0x30;#ifndef CONFIG_IA64 if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14;#endif /* CONFIG_IA64 */ if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_82371MX) { /* This is a painful system best to let it self tune for now */ return; } hwif->autodma = 0; hwif->tuneproc = &piix_tune_drive; hwif->speedproc = &piix_tune_chipset; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; if (!hwif->dma_base) return; hwif->atapi_dma = 1; hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_INTEL_82371MX: hwif->mwdma_mask = 0x80; hwif->swdma_mask = 0x80; case PCI_DEVICE_ID_INTEL_82371FB_0: case PCI_DEVICE_ID_INTEL_82371FB_1: case PCI_DEVICE_ID_INTEL_82371SB_1: hwif->ultra_mask = 0x80; break; case PCI_DEVICE_ID_INTEL_82371AB: case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82451NX: case PCI_DEVICE_ID_INTEL_82801AB_1: hwif->ultra_mask = 0x07; break; case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_11: hwif->busproc = ich3_busproc; /* fall through */ default: pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); pci_read_config_byte(hwif->pci_dev, 0x55, ®55h); ata66 = (reg54h & mask) ? 1 : 0; break; } if (!(hwif->udma_four)) hwif->udma_four = ata66; hwif->ide_dma_check = &piix_config_drive_xfer_rate; if (!noautodma) hwif->autodma = 1; hwif->drives[1].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->autodma;}/** * init_dma_piix - set up the PIIX DMA * @hwif: IDE interface * @dmabase: DMA PCI base * * Set up the DMA on the PIIX controller, providing a DMA base is * available. The PIIX follows the normal specs so we do nothing * magical here. */static void __init init_dma_piix (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 *);/** * init_setup_piix - callback for IDE initialize * @dev: PIIX PCI device * @d: IDE pci info * * Enable the xp fixup for the PIIX controller and then perform * a standard ide PCI setup */ static void __init init_setup_piix (struct pci_dev *dev, ide_pci_device_t *d){ ide_setup_pci_device(dev, d);}/** * piix_init_one - called when a PIIX is found * @dev: the piix device * @id: the matching pci id * * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. */ static int __devinit piix_init_one(struct pci_dev *dev, const struct pci_device_id *id){ ide_pci_device_t *d = &piix_pci_info[id->driver_data]; if (dev->device != d->device) BUG(); d->init_setup(dev, d); MOD_INC_USE_COUNT; return 0;}/** * piix_check_450nx - Check for problem 450NX setup * * Check for the present of 450NX errata #19 and errata #25. If * they are found, disable use of DMA IDE */ static void __init piix_check_450nx(void){ struct pci_dev *pdev = NULL; u16 cfg; u8 rev; while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL) { /* Look for 450NX PXB. Check for problem configurations A PCI quirk checks bit 6 already */ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); pci_read_config_word(pdev, 0x41, &cfg); /* Only on the original revision: IDE DMA can hang */ if(rev == 0x00) no_piix_dma = 1; /* On all revisions PXB bus lock must be disabled for IDE */ else if(cfg & (1<<14)) no_piix_dma = 2; } if(no_piix_dma) printk(KERN_WARNING "piix: 450NX errata present, disabling IDE DMA.\n"); if(no_piix_dma == 2) printk(KERN_WARNING "piix: A BIOS update may resolve this.\n");} static struct pci_device_id piix_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},#ifdef CONFIG_BLK_DEV_IDE_SATA { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},#endif { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, { 0, },};static struct pci_driver driver = { .name = "PIIX IDE", .id_table = piix_pci_tbl, .probe = piix_init_one,};static int piix_ide_init(void){ piix_check_450nx(); return ide_pci_register_driver(&driver);}static void piix_ide_exit(void){ ide_pci_unregister_driver(&driver);}module_init(piix_ide_init);module_exit(piix_ide_exit);MODULE_AUTHOR("Andre Hedrick, Andrzej Krzysztofowicz");MODULE_DESCRIPTION("PCI driver module for Intel PIIX IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -