?? sis5513.c
字號:
case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: if (chipset_family >= ATA_133) { regdw |= 0x04; regdw &= 0xfffff00f; /* check if ATA133 enable */ if (regdw & 0x08) { regdw |= (unsigned long)cycle_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 4; regdw |= (unsigned long)cvs_time_value[ATA_133-ATA_00][speed-XFER_UDMA_0] << 8; } else { /* if ATA133 disable, we should not set speed above UDMA5 */ if (speed > XFER_UDMA_5) speed = XFER_UDMA_5; regdw |= (unsigned long)cycle_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 4; regdw |= (unsigned long)cvs_time_value[ATA_100-ATA_00][speed-XFER_UDMA_0] << 8; } pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); } else { /* Force the UDMA bit on if we want to use UDMA */ reg |= 0x80; /* clean reg cycle time bits */ reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family])) << cycle_time_offset[chipset_family]); /* set reg cycle time bits */ reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0] << cycle_time_offset[chipset_family]; pci_write_config_byte(dev, drive_pci+1, reg); } break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: case XFER_SW_DMA_2: case XFER_SW_DMA_1: case XFER_SW_DMA_0: break; case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); case XFER_PIO_0: default: return((int) config_chipset_for_pio(drive, 0)); }#ifdef DEBUG sis5513_load_verify_registers(dev, "sis5513_tune_chipset end");#endif return ((int) ide_config_drive_speed(drive, speed));}static void sis5513_tune_drive (ide_drive_t *drive, u8 pio){ (void) config_chipset_for_pio(drive, pio);}/* * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */static int config_chipset_for_dma (ide_drive_t *drive){ u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive));#ifdef DEBUG printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", drive->dn, drive->id->dma_ultra);#endif if (!(speed)) return 0; sis5513_tune_chipset(drive, speed); return ide_dma_enable(drive);}static int sis5513_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; if (id->field_valid & 4) { 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: sis5513_tune_drive(drive, 5); return hwif->ide_dma_off_quietly(drive); } return hwif->ide_dma_on(drive);}/* initiates/aborts (U)DMA read/write operations on a drive. */static int sis5513_config_xfer_rate (ide_drive_t *drive){ config_drive_art_rwp(drive); config_art_rwp_pio(drive, 5); return sis5513_config_drive_xfer_rate(drive);}/* Chip detection and general config */static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name){ struct pci_dev *host; int i = 0; /* Find the chip */ for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) { host = pci_find_device (PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); if (!host) continue; host_dev = host; chipset_family = SiSHostChipInfo[i].chipset_family; /* check 100/133 chipset family */ if (chipset_family == ATA_133) { u32 reg54h; u16 reg02h; pci_read_config_dword(dev, 0x54, ®54h); pci_write_config_dword(dev, 0x54, (reg54h & 0x7fffffff)); pci_read_config_word(dev, 0x02, ®02h); pci_write_config_dword(dev, 0x54, reg54h); /* devid 5518 here means SiS962 or later which supports ATA133 */ if (reg02h != 0x5518) { u8 reg49h; unsigned long sbrev; /* SiS961 family */ /* * FIXME !!! GAK!!!!!!!!!! PCI DIRECT POKING */ outl(0x80001008, 0x0cf8); sbrev = inl(0x0cfc); pci_read_config_byte(dev, 0x49, ®49h); if (((sbrev & 0xff) == 0x10) && (reg49h & 0x80)) chipset_family = ATA_133a; else chipset_family = ATA_100; } } printk(SiSHostChipInfo[i].name); printk(" %s controller", chipset_capability[chipset_family]); printk("\n");#ifdef DEBUG sis5513_print_registers(dev, "pci_init_sis5513 start");#endif if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); } } /* Make general config ops here 1/ tell IDE channels to operate in Compatibility mode only 2/ tell old chips to allow per drive IDE timings */ if (host_dev) { u8 reg; u16 regw; switch(chipset_family) { case ATA_133: /* SiS962 operation mode */ pci_read_config_word(dev, 0x50, ®w); if (regw & 0x08) pci_write_config_word(dev, 0x50, regw&0xfff7); pci_read_config_word(dev, 0x52, ®w); if (regw & 0x08) pci_write_config_word(dev, 0x52, regw&0xfff7); break; case ATA_133a: case ATA_100: /* Set compatibility bit */ pci_read_config_byte(dev, 0x49, ®); if (!(reg & 0x01)) { pci_write_config_byte(dev, 0x49, reg|0x01); } break; case ATA_100a: case ATA_66: /* On ATA_66 chips the bit was elsewhere */ pci_read_config_byte(dev, 0x52, ®); if (!(reg & 0x04)) { pci_write_config_byte(dev, 0x52, reg|0x04); } break; case ATA_33: /* On ATA_33 we didn't have a single bit to set */ pci_read_config_byte(dev, 0x09, ®); if ((reg & 0x0f) != 0x00) { pci_write_config_byte(dev, 0x09, reg&0xf0); } case ATA_16: /* force per drive recovery and active timings needed on ATA_33 and below chips */ pci_read_config_byte(dev, 0x52, ®); if (!(reg & 0x08)) { pci_write_config_byte(dev, 0x52, reg|0x08); } break; case ATA_00: default: break; }#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) if (!sis_proc) { sis_proc = 1; bmide_dev = dev; ide_pci_register_host_proc(&sis_procs[0]); }#endif }#ifdef DEBUG sis5513_load_verify_registers(dev, "pci_init_sis5513 end");#endif return 0;}static unsigned int __init ata66_sis5513 (ide_hwif_t *hwif){ u8 ata66 = 0; if (chipset_family >= ATA_133) { u16 regw = 0; u16 reg_addr = hwif->channel ? 0x52: 0x50; pci_read_config_word(hwif->pci_dev, reg_addr, ®w); ata66 = (regw & 0x8000) ? 0 : 1; } else if (chipset_family >= ATA_66) { u8 reg48h = 0; u8 mask = hwif->channel ? 0x20 : 0x10; pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); ata66 = (reg48h & mask) ? 0 : 1; } return ata66;}static void __init init_hwif_sis5513 (ide_hwif_t *hwif){ hwif->autodma = 0; if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; hwif->tuneproc = &sis5513_tune_drive; hwif->speedproc = &sis5513_tune_chipset; if (!(hwif->dma_base)) { hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; return; } hwif->atapi_dma = 1; hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; if (!host_dev) return; if (!(hwif->udma_four)) hwif->udma_four = ata66_sis5513(hwif); if (chipset_family > ATA_16) { hwif->ide_dma_check = &sis5513_config_xfer_rate; if (!noautodma) hwif->autodma = 1; } hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; return;}static void __init init_dma_sis5513 (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 sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id){ ide_pci_device_t *d = &sis5513_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 sis5513_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 0, },};static struct pci_driver driver = { .name = "SIS IDE", .id_table = sis5513_pci_tbl, .probe = sis5513_init_one,};static int sis5513_ide_init(void){ return ide_pci_register_driver(&driver);}static void sis5513_ide_exit(void){ ide_pci_unregister_driver(&driver);}module_init(sis5513_ide_init);module_exit(sis5513_ide_exit);MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for SIS IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;/* * TODO: * - Get ridden of SisHostChipInfo[] completness dependancy. * - Study drivers/ide/ide-timing.h. * - Are there pre-ATA_16 SiS5513 chips ? -> tune init code for them * or remove ATA_00 define * - More checks in the config registers (force values instead of * relying on the BIOS setting them correctly). * - Further optimisations ? * . for example ATA66+ regs 0x48 & 0x4A */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -