📄 serverworks.c
字号:
if (!drive->init_speed) drive->init_speed = speed; pci_write_config_byte(dev, drive_pci, pio_timing); if (csb5) pci_write_config_word(dev, 0x4A, csb5_pio);#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci2, dma_timing); pci_write_config_byte(dev, drive_pci3, ultra_timing); pci_write_config_byte(dev, 0x54, ultra_enable); if (speed > XFER_PIO_4) outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); else outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);#endif /* CONFIG_BLK_DEV_IDEDMA */ err = ide_config_drive_speed(drive, speed); drive->current_speed = speed; return err;}static void config_chipset_for_pio (ide_drive_t *drive){ unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes; byte timing, speed, pio; pio = ide_get_best_pio_mode(drive, 255, 5, 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 : (drive->id->tPIO & 2) ? 0x02 : (drive->id->tPIO & 1) ? 0x01 : xfer_pio; timing = (xfer_pio >= pio) ? xfer_pio : pio; switch(timing) { 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 = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; } (void) svwks_tune_chipset(drive, speed); drive->current_speed = speed;}static void svwks_tune_drive (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; } (void) svwks_tune_chipset(drive, speed);}#ifdef CONFIG_BLK_DEV_IDEDMAstatic int config_chipset_for_dma (ide_drive_t *drive){ struct hd_driveid *id = drive->id; struct pci_dev *dev = HWIF(drive)->pci_dev; byte udma_66 = eighty_ninty_three(drive); int ultra66 = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0; int ultra100 = (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0; byte speed; if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { speed = XFER_UDMA_5; } else if (id->dma_ultra & 0x0010) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; } else if (id->dma_ultra & 0x0008) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; } else if (id->dma_ultra & 0x0004) { speed = XFER_UDMA_2; } else if (id->dma_ultra & 0x0002) { speed = XFER_UDMA_1; } else if (id->dma_ultra & 0x0001) { 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_1word & 0x0004) { speed = XFER_SW_DMA_2; } else { speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); } (void) svwks_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_on; 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); 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 & 0x007)) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive); 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); 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); } return HWIF(drive)->dmaproc(dma_func, drive);}static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive){ switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_end: { ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; if(inb(dma_base+0x02)&1) {#if 0 int i; printk(KERN_ERR "Curious - OSB4 thinks the DMA is still running.\n"); for(i=0;i<10;i++) { if(!(inb(dma_base+0x02)&1)) { printk(KERN_ERR "OSB4 now finished.\n"); break; } udelay(5); }#endif printk(KERN_CRIT "Serverworks OSB4 in impossible state.\n"); printk(KERN_CRIT "Disable UDMA or if you are using Seagate then try switching disk types\n"); printk(KERN_CRIT "on this controller. Please report this event to osb4-bug@ide.cabal.tm\n");#if 0 /* Panic might sys_sync -> death by corrupt disk */ panic("OSB4: continuing might cause disk corruption.\n");#else printk(KERN_CRIT "OSB4: continuing might cause disk corruption.\n"); while(1) cpu_relax();#endif } /* and drop through */ } default: break; } /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive);}#endif /* CONFIG_BLK_DEV_IDEDMA */unsigned int __init pci_init_svwks (struct pci_dev *dev, const char *name){ unsigned int reg; byte btr; /* save revision id to determine DMA capability */ pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); /* force Master Latency Timer value to 64 PCICLKs */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); /* OSB4 : South Bridge and IDE */ if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); if (isa_dev) { pci_read_config_dword(isa_dev, 0x64, ®); reg &= ~0x00002000; /* disable 600ns interrupt mask */ reg |= 0x00004000; /* enable UDMA/33 support */ pci_write_config_dword(isa_dev, 0x64, reg); } } /* setup CSB5 : South Bridge and IDE */ else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) { /* setup the UDMA Control register * * 1. clear bit 6 to enable DMA * 2. enable DMA modes with bits 0-1 * 00 : legacy * 01 : udma2 * 10 : udma2/udma4 * 11 : udma2/udma4/udma5 */ pci_read_config_byte(dev, 0x5A, &btr); btr &= ~0x40; btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; pci_write_config_byte(dev, 0x5A, btr); }#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) if (!svwks_proc) { svwks_proc = 1; bmide_dev = dev; svwks_display_info = &svwks_get_info; }#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ return 0;}/* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem * device ID indicate presence of an 80-pin cable. * Bit 15 clear = secondary IDE channel does not have 80-pin cable. * Bit 15 set = secondary IDE channel has 80-pin cable. * Bit 14 clear = primary IDE channel does not have 80-pin cable. * Bit 14 set = primary IDE channel has 80-pin cable. */static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) return ((1 << (hwif->channel + 14)) & dev->subsystem_device) ? 1 : 0; return 0;}/* Sun Cobalt Alpine hardware avoids the 80-pin cable * detect issue by attaching the drives directly to the board. * This check follows the Dell precedent (how scary is that?!) * * WARNING: this only works on Alpine hardware! */static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && dev->vendor == PCI_VENDOR_ID_SERVERWORKS && dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) return ((1 << (hwif->channel + 14)) & dev->subsystem_device) ? 1 : 0; return 0;}unsigned int __init ata66_svwks (ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; /* Dell PowerEdge */ if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) return ata66_svwks_dell (hwif); /* Cobalt Alpine */ if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN) return ata66_svwks_cobalt (hwif); return 0;}void __init ide_init_svwks (ide_hwif_t *hwif){ if (!hwif->irq) hwif->irq = hwif->channel ? 15 : 14; hwif->tuneproc = &svwks_tune_drive; hwif->speedproc = &svwks_tune_chipset;#ifndef CONFIG_BLK_DEV_IDEDMA hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0;#else /* CONFIG_BLK_DEV_IDEDMA */ if (hwif->dma_base) {#ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1;#endif hwif->dmaproc = &svwks_dmaproc; } else { hwif->autodma = 0; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; }#endif /* !CONFIG_BLK_DEV_IDEDMA */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -