📄 sis5513.c
字号:
if ((reg4bh & rw_prefetch) != rw_prefetch) pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);#ifdef DEBUG sis5513_load_verify_registers(dev, "config_drive_art_rwp end");#endif}/* Set per-drive active and recovery time */static void config_art_rwp_pio (ide_drive_t *drive, byte pio){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte timing, drive_pci, test1, test2; unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes;#ifdef DEBUG sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start");#endif config_drive_art_rwp(drive); pio = ide_get_best_pio_mode(drive, 255, pio, NULL); if (xfer_pio> 4) xfer_pio = 0; if (drive->id->eide_pio_iordy > 0) { for (xfer_pio = 5; (xfer_pio > 0) && (drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]); xfer_pio--); } else { xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : (drive->id->eide_pio_modes & 2) ? 0x04 : (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio; } timing = (xfer_pio >= pio) ? xfer_pio : pio;#ifdef DEBUG printk("SIS5513: config_drive_art_rwp_pio, drive %d, pio %d, timing %d\n", drive->dn, pio, timing);#endif switch(drive->dn) { case 0: drive_pci = 0x40; break; case 1: drive_pci = 0x42; break; case 2: drive_pci = 0x44; break; case 3: drive_pci = 0x46; break; default: return; } /* register layout changed with newer ATA100 chips */ if (chipset_family < ATA_100) { pci_read_config_byte(dev, drive_pci, &test1); pci_read_config_byte(dev, drive_pci+1, &test2); /* Clear active and recovery timings */ test1 &= ~0x0F; test2 &= ~0x07; switch(timing) { case 4: test1 |= 0x01; test2 |= 0x03; break; case 3: test1 |= 0x03; test2 |= 0x03; break; case 2: test1 |= 0x04; test2 |= 0x04; break; case 1: test1 |= 0x07; test2 |= 0x06; break; default: break; } pci_write_config_byte(dev, drive_pci, test1); pci_write_config_byte(dev, drive_pci+1, test2); } else { switch(timing) { /* active recovery v v */ case 4: test1 = 0x30|0x01; break; case 3: test1 = 0x30|0x03; break; case 2: test1 = 0x40|0x04; break; case 1: test1 = 0x60|0x07; break; default: break; } pci_write_config_byte(dev, drive_pci, test1); }#ifdef DEBUG sis5513_load_verify_registers(dev, "config_drive_art_rwp_pio start");#endif}static int config_chipset_for_pio (ide_drive_t *drive, byte pio){ byte speed; switch(pio) { case 4: speed = XFER_PIO_4; break; case 3: speed = XFER_PIO_3; break; case 2: speed = XFER_PIO_2; break; case 1: speed = XFER_PIO_1; break; default: speed = XFER_PIO_0; break; } config_art_rwp_pio(drive, pio); drive->current_speed = speed; return ide_config_drive_speed(drive, speed);}static int sis5513_tune_chipset (ide_drive_t *drive, byte speed){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte drive_pci, reg;#ifdef DEBUG sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); printk("SIS5513: sis5513_tune_chipset, drive %d, speed %d\n", drive->dn, speed);#endif switch(drive->dn) { case 0: drive_pci = 0x40; break; case 1: drive_pci = 0x42; break; case 2: drive_pci = 0x44; break; case 3: drive_pci = 0x46; break; default: return ide_dma_off; }#ifdef BROKEN_LEVEL#ifdef DEBUG printk("SIS5513: BROKEN_LEVEL activated, speed=%d -> speed=%d\n", speed, BROKEN_LEVEL);#endif if (speed > BROKEN_LEVEL) speed = BROKEN_LEVEL;#endif pci_read_config_byte(dev, drive_pci+1, ®); /* Disable UDMA bit for non UDMA modes on UDMA chips */ if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { reg &= 0x7F; pci_write_config_byte(dev, drive_pci+1, reg); } /* Config chip for mode */ switch(speed) {#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5: case XFER_UDMA_4: case XFER_UDMA_3: case XFER_UDMA_2: case XFER_UDMA_1: case XFER_UDMA_0: /* 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;#endif /* CONFIG_BLK_DEV_IDEDMA */ 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)); } drive->current_speed = speed;#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, byte pio){ (void) config_chipset_for_pio(drive, pio);}#ifdef CONFIG_BLK_DEV_IDEDMA/* * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */static int config_chipset_for_dma (ide_drive_t *drive, byte ultra){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); byte speed = 0; byte unit = (drive->select.b.unit & 0x01); byte udma_66 = eighty_ninty_three(drive);#ifdef DEBUG printk("SIS5513: config_chipset_for_dma, drive %d, ultra %d\n", drive->dn, ultra);#endif if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a)) speed = XFER_UDMA_5; else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66)) speed = XFER_UDMA_4; else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66)) speed = XFER_UDMA_3; else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_2; else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_1; else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33)) speed = XFER_UDMA_0; else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2; else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1; else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0; else return ((int) ide_dma_off_quietly); outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); sis5513_tune_chipset(drive, speed); return ((int) ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly);}static int config_drive_xfer_rate (ide_drive_t *drive){ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_off_quietly; (void) config_chipset_for_pio(drive, 5); if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* 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) { if (id->dma_ultra & 0x003F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive, 1); 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, 0); if (dma_func != ide_dma_on) goto no_dma_set; } } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && (id->eide_dma_time > 150)) { /* Consult the list of known "good" drives */ dma_func = config_chipset_for_dma(drive, 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: (void) config_chipset_for_pio(drive, 5); } return HWIF(drive)->dmaproc(dma_func, drive);}/* initiates/aborts (U)DMA read/write operations on a drive. */int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive){ switch (func) { case ide_dma_check: config_drive_art_rwp(drive); config_art_rwp_pio(drive, 5); return config_drive_xfer_rate(drive); default: break; } return ide_dmaproc(func, drive); /* use standard DMA stuff */}#endif /* CONFIG_BLK_DEV_IDEDMA *//* Chip detection and general config */unsigned int __init pci_init_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; printk(SiSHostChipInfo[i].name); printk("\n");#ifdef DEBUG sis5513_print_registers(dev, "pci_init_sis5513 start");#endif if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { byte 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 Compabitility mode only 2/ tell old chips to allow per drive IDE timings */ if (host_dev) { byte reg; switch(chipset_family) { case ATA_133: 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; sis_display_info = &sis_get_info; }#endif }#ifdef DEBUG sis5513_load_verify_registers(dev, "pci_init_sis5513 end");#endif return 0;}unsigned int __init ata66_sis5513 (ide_hwif_t *hwif){ byte reg48h = 0, ata66 = 0; byte mask = hwif->channel ? 0x20 : 0x10; pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); if (chipset_family >= ATA_66) { ata66 = (reg48h & mask) ? 0 : 1; } return ata66;}void __init ide_init_sis5513 (ide_hwif_t *hwif){ hwif->irq = hwif->channel ? 15 : 14; hwif->tuneproc = &sis5513_tune_drive; hwif->speedproc = &sis5513_tune_chipset; if (!(hwif->dma_base)) return; if (host_dev) {#ifdef CONFIG_BLK_DEV_IDEDMA if (chipset_family > ATA_16) { hwif->autodma = noautodma ? 0 : 1; hwif->dmaproc = &sis5513_dmaproc; } else {#endif hwif->autodma = 0;#ifdef CONFIG_BLK_DEV_IDEDMA }#endif } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -