📄 siimage.c
字号:
static int siimage_reset_poll (ide_drive_t *drive){ if (SATA_STATUS_REG) { ide_hwif_t *hwif = HWIF(drive); if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", hwif->name, hwif->INL(SATA_STATUS_REG)); HWGROUP(drive)->poll_timeout = 0; return ide_started; } return 0; } else { return 0; }}/** * siimage_pre_reset - reset hook * @drive: IDE device being reset * * For the SATA devices we need to handle recalibration/geometry * differently */ static void siimage_pre_reset (ide_drive_t *drive){ if (drive->media != ide_disk) return; if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_SII_3112) { drive->special.b.set_geometry = 0; drive->special.b.recalibrate = 0; }}/** * siimage_reset - reset a device on an siimage controller * @drive: drive to reset * * Perform a controller level reset fo the device. For * SATA we must also check the PHY. */ static void siimage_reset (ide_drive_t *drive){ ide_hwif_t *hwif = HWIF(drive); u8 reset = 0; if (hwif->mmio) { reset = hwif->INB(SELADDR(0)); hwif->OUTB((reset|0x03), SELADDR(0)); udelay(25); hwif->OUTB(reset, SELADDR(0)); (void) hwif->INB(SELADDR(0)); } else { pci_read_config_byte(hwif->pci_dev, SELREG(0), &reset); pci_write_config_byte(hwif->pci_dev, SELREG(0), reset|0x03); udelay(25); pci_write_config_byte(hwif->pci_dev, SELREG(0), reset); pci_read_config_byte(hwif->pci_dev, SELREG(0), &reset); } if (SATA_STATUS_REG) { u32 sata_stat = hwif->INL(SATA_STATUS_REG); printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", hwif->name, sata_stat, __FUNCTION__); if (!(sata_stat)) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", hwif->name, sata_stat); drive->failures++; } }}/** * proc_reports_siimage - add siimage controller to proc * @dev: PCI device * @clocking: SCSC value * @name: controller name * * Report the clocking mode of the controller and add it to * the /proc interface layer */ static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name){ if (dev->device == PCI_DEVICE_ID_SII_3112) goto sata_skip; printk(KERN_INFO "%s: BASE CLOCK ", name); clocking &= ~0x03; switch(clocking) { case 0x03: printk("DISABLED !\n"); break; case 0x02: printk("== 2X PCI \n"); break; case 0x01: printk("== 133 \n"); break; case 0x00: printk("== 100 \n"); break; }sata_skip:#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) siimage_devs[n_siimage_devs++] = dev; if (!siimage_proc) { siimage_proc = 1; ide_pci_register_host_proc(&siimage_procs[0]); }#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */}static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name){ unsigned long bar5 = pci_resource_start(dev, 5); unsigned long len5 = pci_resource_len(dev, 5); u8 tmpbyte = 0; unsigned long addr; void *ioaddr; /* * Drop back to PIO if we can't map the mmio. Some * systems seem to get terminally confused in the PCI * spaces. */ if(check_mem_region(bar5, len5)!=0) { printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n"); return 0; } ioaddr = ioremap_nocache(bar5, len5); if (ioaddr == NULL) return 0; pci_set_master(dev); pci_set_drvdata(dev, ioaddr); addr = (unsigned long) ioaddr; if (dev->device == PCI_DEVICE_ID_SII_3112) { writel(0, DEVADDR(0x148)); writel(0, DEVADDR(0x1C8)); } writeb(0, DEVADDR(0xB4)); writeb(0, DEVADDR(0xF4)); tmpbyte = readb(DEVADDR(0x4A)); switch(tmpbyte & 0x30) { case 0x00: /* In 100 MHz clocking, try and switch to 133 */ writeb(tmpbyte|0x10, DEVADDR(0x4A)); break; case 0x10: /* On 133Mhz clocking */ break; case 0x20: /* On PCIx2 clocking */ break; case 0x30: /* Clocking is disabled */ /* 133 clock attempt to force it on */ writeb(tmpbyte & ~0x20, DEVADDR(0x4A)); break; } writeb(0x72, DEVADDR(0xA1)); writew(0x328A, DEVADDR(0xA2)); writel(0x62DD62DD, DEVADDR(0xA4)); writel(0x43924392, DEVADDR(0xA8)); writel(0x40094009, DEVADDR(0xAC)); writeb(0x72, DEVADDR(0xE1)); writew(0x328A, DEVADDR(0xE2)); writel(0x62DD62DD, DEVADDR(0xE4)); writel(0x43924392, DEVADDR(0xE8)); writel(0x40094009, DEVADDR(0xEC)); if (dev->device == PCI_DEVICE_ID_SII_3112) { writel(0xFFFF0000, DEVADDR(0x108)); writel(0xFFFF0000, DEVADDR(0x188)); writel(0x00680000, DEVADDR(0x148)); writel(0x00680000, DEVADDR(0x1C8)); } tmpbyte = readb(DEVADDR(0x4A)); proc_reports_siimage(dev, (tmpbyte>>=4), name); return 1;}static unsigned int __init init_chipset_siimage (struct pci_dev *dev, const char *name){ u32 class_rev = 0; u8 tmpbyte = 0; u8 BA5_EN = 0; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255); pci_read_config_byte(dev, 0x8A, &BA5_EN); if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) { if (setup_mmio_siimage(dev, name)) { return 0; } } pci_write_config_byte(dev, 0x80, 0x00); pci_write_config_byte(dev, 0x84, 0x00); pci_read_config_byte(dev, 0x8A, &tmpbyte); switch(tmpbyte & 0x30) { case 0x00: /* 133 clock attempt to force it on */ pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); case 0x30: /* if clocking is disabled */ /* 133 clock attempt to force it on */ pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20); case 0x10: /* 133 already */ break; case 0x20: /* BIOS set PCI x2 clocking */ break; } pci_read_config_byte(dev, 0x8A, &tmpbyte); pci_write_config_byte(dev, 0xA1, 0x72); pci_write_config_word(dev, 0xA2, 0x328A); pci_write_config_dword(dev, 0xA4, 0x62DD62DD); pci_write_config_dword(dev, 0xA8, 0x43924392); pci_write_config_dword(dev, 0xAC, 0x40094009); pci_write_config_byte(dev, 0xB1, 0x72); pci_write_config_word(dev, 0xB2, 0x328A); pci_write_config_dword(dev, 0xB4, 0x62DD62DD); pci_write_config_dword(dev, 0xB8, 0x43924392); pci_write_config_dword(dev, 0xBC, 0x40094009); pci_read_config_byte(dev, 0x8A, &tmpbyte); proc_reports_siimage(dev, (tmpbyte>>=4), name); return 0;}static void __init init_mmio_iops_siimage (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; unsigned long addr = (unsigned long) pci_get_drvdata(hwif->pci_dev); u8 ch = hwif->channel;// u16 i = 0; hw_regs_t hw; default_hwif_mmiops(hwif); memset(&hw, 0, sizeof(hw_regs_t));#if 1#ifdef SIIMAGE_BUFFERED_TASKFILE hw.io_ports[IDE_DATA_OFFSET] = DEVADDR((ch) ? 0xD0 : 0x90); hw.io_ports[IDE_ERROR_OFFSET] = DEVADDR((ch) ? 0xD1 : 0x91); hw.io_ports[IDE_NSECTOR_OFFSET] = DEVADDR((ch) ? 0xD2 : 0x92); hw.io_ports[IDE_SECTOR_OFFSET] = DEVADDR((ch) ? 0xD3 : 0x93); hw.io_ports[IDE_LCYL_OFFSET] = DEVADDR((ch) ? 0xD4 : 0x94); hw.io_ports[IDE_HCYL_OFFSET] = DEVADDR((ch) ? 0xD5 : 0x95); hw.io_ports[IDE_SELECT_OFFSET] = DEVADDR((ch) ? 0xD6 : 0x96); hw.io_ports[IDE_STATUS_OFFSET] = DEVADDR((ch) ? 0xD7 : 0x97); hw.io_ports[IDE_CONTROL_OFFSET] = DEVADDR((ch) ? 0xDA : 0x9A);#else /* ! SIIMAGE_BUFFERED_TASKFILE */ hw.io_ports[IDE_DATA_OFFSET] = DEVADDR((ch) ? 0xC0 : 0x80); hw.io_ports[IDE_ERROR_OFFSET] = DEVADDR((ch) ? 0xC1 : 0x81); hw.io_ports[IDE_NSECTOR_OFFSET] = DEVADDR((ch) ? 0xC2 : 0x82); hw.io_ports[IDE_SECTOR_OFFSET] = DEVADDR((ch) ? 0xC3 : 0x83); hw.io_ports[IDE_LCYL_OFFSET] = DEVADDR((ch) ? 0xC4 : 0x84); hw.io_ports[IDE_HCYL_OFFSET] = DEVADDR((ch) ? 0xC5 : 0x85); hw.io_ports[IDE_SELECT_OFFSET] = DEVADDR((ch) ? 0xC6 : 0x86); hw.io_ports[IDE_STATUS_OFFSET] = DEVADDR((ch) ? 0xC7 : 0x87); hw.io_ports[IDE_CONTROL_OFFSET] = DEVADDR((ch) ? 0xCA : 0x8A);#endif /* SIIMAGE_BUFFERED_TASKFILE */#else#ifdef SIIMAGE_BUFFERED_TASKFILE for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) hw.io_ports[i] = DEVADDR((ch) ? 0xD0 : 0x90)|(i); hw.io_ports[IDE_CONTROL_OFFSET] = DEVADDR((ch) ? 0xDA : 0x9A);#else /* ! SIIMAGE_BUFFERED_TASKFILE */ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) hw.io_ports[i] = DEVADDR((ch) ? 0xC0 : 0x80)|(i); hw.io_ports[IDE_CONTROL_OFFSET] = DEVADDR((ch) ? 0xCA : 0x8A);#endif /* SIIMAGE_BUFFERED_TASKFILE */#endif#if 0 printk(KERN_DEBUG "%s: ", hwif->name); for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) printk("0x%08x ", DEVADDR((ch) ? 0xC0 : 0x80)|(i)); printk("0x%08x ", DEVADDR((ch) ? 0xCA : 0x8A)|(i));#endif hw.io_ports[IDE_IRQ_OFFSET] = 0; if (dev->device == PCI_DEVICE_ID_SII_3112) { hw.sata_scr[SATA_STATUS_OFFSET] = DEVADDR((ch) ? 0x184 : 0x104); hw.sata_scr[SATA_ERROR_OFFSET] = DEVADDR((ch) ? 0x188 : 0x108); hw.sata_scr[SATA_CONTROL_OFFSET]= DEVADDR((ch) ? 0x180 : 0x100); hw.sata_misc[SATA_MISC_OFFSET] = DEVADDR((ch) ? 0x1C0 : 0x140); hw.sata_misc[SATA_PHY_OFFSET] = DEVADDR((ch) ? 0x1C4 : 0x144); hw.sata_misc[SATA_IEN_OFFSET] = DEVADDR((ch) ? 0x1C8 : 0x148); } hw.priv = (void *) addr;// hw.priv = pci_get_drvdata(hwif->pci_dev); hw.irq = hwif->pci_dev->irq; memcpy(&hwif->hw, &hw, sizeof(hw)); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports)); if (hwif->pci_dev->device == PCI_DEVICE_ID_SII_3112) { memcpy(hwif->sata_scr, hwif->hw.sata_scr, sizeof(hwif->hw.sata_scr)); memcpy(hwif->sata_misc, hwif->hw.sata_misc, sizeof(hwif->hw.sata_misc)); }#ifdef SIIMAGE_BUFFERED_TASKFILE hwif->addressing = 1;#endif /* SIIMAGE_BUFFERED_TASKFILE */ hwif->irq = hw.irq; hwif->hwif_data = pci_get_drvdata(hwif->pci_dev);#ifdef SIIMAGE_LARGE_DMA hwif->dma_base = DEVADDR((ch) ? 0x18 : 0x10); hwif->dma_base2 = DEVADDR((ch) ? 0x08 : 0x00); hwif->dma_prdtable = (hwif->dma_base2 + 4);#else /* ! SIIMAGE_LARGE_DMA */ hwif->dma_base = DEVADDR((ch) ? 0x08 : 0x00); hwif->dma_base2 = DEVADDR((ch) ? 0x18 : 0x10);#endif /* SIIMAGE_LARGE_DMA */ hwif->mmio = 2;}static void __init init_iops_siimage (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; u32 class_rev = 0; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; hwif->rqsize = 128; if ((dev->device == PCI_DEVICE_ID_SII_3112) && (!(class_rev))) hwif->rqsize = 16; if (pci_get_drvdata(dev) == NULL) return; init_mmio_iops_siimage(hwif);}static unsigned int __init ata66_siimage (ide_hwif_t *hwif){ if (pci_get_drvdata(hwif->pci_dev) == NULL) { u8 ata66 = 0; pci_read_config_byte(hwif->pci_dev, SELREG(0), &ata66); return (ata66 & 0x01) ? 1 : 0; } return (hwif->INB(SELADDR(0)) & 0x01) ? 1 : 0;}static void __init init_hwif_siimage (ide_hwif_t *hwif){ hwif->autodma = 0; hwif->resetproc = &siimage_reset; hwif->speedproc = &siimage_tune_chipset; hwif->tuneproc = &siimage_tuneproc; hwif->reset_poll = &siimage_reset_poll; hwif->pre_reset = &siimage_pre_reset; if(hwif->pci_dev->device == PCI_DEVICE_ID_SII_3112) hwif->busproc = &siimage_busproc; if (!hwif->dma_base) { hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; return; } hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; if (hwif->pci_dev->device != PCI_DEVICE_ID_SII_3112) hwif->atapi_dma = 1; hwif->ide_dma_check = &siimage_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_siimage(hwif); if (hwif->mmio) { hwif->ide_dma_count = &siimage_mmio_ide_dma_count; hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq; hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose; } else { hwif->ide_dma_test_irq = & siimage_io_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_siimage (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 siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id){ ide_pci_device_t *d = &siimage_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 siimage_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, },};static struct pci_driver driver = { .name = "SiI IDE", .id_table = siimage_pci_tbl, .probe = siimage_init_one,};static int siimage_ide_init(void){ return ide_pci_register_driver(&driver);}static void siimage_ide_exit(void){ ide_pci_unregister_driver(&driver);}module_init(siimage_ide_init);module_exit(siimage_ide_exit);MODULE_AUTHOR("Andre Hedrick, Alan Cox");MODULE_DESCRIPTION("PCI driver module for SiI IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -