⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sis5513.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 if (chipset_family < ATA_133) {		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);	} else { /* ATA_133 */		u32 test3;		pci_read_config_dword(dev, drive_pci, &test3);		test3 &= 0xc0c00fff;		if (test3 & 0x08) {			test3 |= (unsigned long)ini_time_value[ATA_133][timing] << 12;			test3 |= (unsigned long)act_time_value[ATA_133][timing] << 16;			test3 |= (unsigned long)rco_time_value[ATA_133][timing] << 24;		} else {			test3 |= (unsigned long)ini_time_value[ATA_100][timing] << 12;			test3 |= (unsigned long)act_time_value[ATA_100][timing] << 16;			test3 |= (unsigned long)rco_time_value[ATA_100][timing] << 24;		}		pci_write_config_dword(dev, drive_pci, test3);	}}static int config_chipset_for_pio (ide_drive_t *drive, u8 pio){	if (pio == 255)		pio = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;	config_art_rwp_pio(drive, pio);	return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4));}static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed){	ide_hwif_t *hwif	= HWIF(drive);	struct pci_dev *dev	= hwif->pci_dev;	u8 drive_pci, reg, speed;	u32 regdw;	speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed);	/* See config_art_rwp_pio for drive pci config registers */	drive_pci = 0x40;	if (chipset_family >= ATA_133) {		u32 reg54h;		pci_read_config_dword(dev, 0x54, &reg54h);		if (reg54h & 0x40000000) drive_pci = 0x70;		drive_pci += ((drive->dn)*0x4);		pci_read_config_dword(dev, (unsigned long)drive_pci, &regdw);		/* Disable UDMA bit for non UDMA modes on UDMA chips */		if (speed < XFER_UDMA_0) {			regdw &= 0xfffffffb;			pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);		}		} else {		drive_pci += ((drive->dn)*0x2);		pci_read_config_byte(dev, drive_pci+1, &reg);		/* 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) {		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][speed-XFER_UDMA_0] << 4;					regdw |= (unsigned long)cvs_time_value[ATA_133][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][speed-XFER_UDMA_0] << 4;					regdw |= (unsigned long)cvs_time_value[ATA_100][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][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));		}	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;		}		return hwif->ide_dma_on(drive);	} 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);	}	/* IORDY not supported */	return 0;}/* 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);}/*  Future simpler config_xfer_rate :   When ide_find_best_mode is made bad-drive aware   - remove config_drive_xfer_rate and config_chipset_for_dma,   - replace config_xfer_rate with the followingstatic int sis5513_config_xfer_rate (ide_drive_t *drive){	u16 w80 = HWIF(drive)->udma_four;	u16 speed;	config_drive_art_rwp(drive);	config_art_rwp_pio(drive, 5);	speed = ide_find_best_mode(drive,		XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |		(chipset_family >= ATA_33 ? XFER_UDMA : 0) |		(w80 && chipset_family >= ATA_66 ? XFER_UDMA_66 : 0) |		(w80 && chipset_family >= ATA_100a ? XFER_UDMA_100 : 0) |		(w80 && chipset_family >= ATA_133a ? XFER_UDMA_133 : 0));	sis5513_tune_chipset(drive, speed);	if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)		return HWIF(drive)->ide_dma_on(drive);	return HWIF(drive)->ide_dma_off_quietly(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;	chipset_family = 0;	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) {		host = pci_find_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL);		if (!host)			continue;		chipset_family = SiSHostChipInfo[i].chipset_family;		/* Special case for SiS630 : 630S/ET is ATA_100a */		if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {			u8 hostrev;			pci_read_config_byte(host, PCI_REVISION_ID, &hostrev);			if (hostrev >= 0x30)				chipset_family = ATA_100a;		}			printk(KERN_INFO "SIS5513: %s %s controller\n",			 SiSHostChipInfo[i].name, chipset_capability[chipset_family]);	}	if (!chipset_family) { /* Belongs to pci-quirks */			u32 idemisc;			u16 trueid;			/* Disable ID masking and register remapping */			pci_read_config_dword(dev, 0x54, &idemisc);			pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff));			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);			pci_write_config_dword(dev, 0x54, idemisc);			if (trueid == 0x5518) {				printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");				chipset_family = ATA_133;			}	}	if (!chipset_family) { /* Belongs to pci-quirks */			struct pci_dev *lpc_bridge;			u16 trueid;			u8 prefctl;			u8 idecfg;			u8 sbrev;			pci_read_config_byte(dev, 0x4a, &idecfg);			pci_write_config_byte(dev, 0x4a, idecfg | 0x10);			pci_read_config_word(dev, PCI_DEVICE_ID, &trueid);			pci_write_config_byte(dev, 0x4a, idecfg);			if (trueid == 0x5517) { /* SiS 961/961B */				lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */				pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);				pci_read_config_byte(dev, 0x49, &prefctl);				if (sbrev == 0x10 && (prefctl & 0x80)) {					printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");					chipset_family = ATA_133a;				} else {					printk(KERN_INFO "SIS5513: SiS 961 MuTIOL IDE UDMA100 controller\n");					chipset_family = ATA_100;				}			}	}	if (!chipset_family)		return -1;	/* 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 */	{		u8 reg;		u16 regw;		switch(chipset_family) {			case ATA_133:				/* SiS962 operation mode */				pci_read_config_word(dev, 0x50, &regw);				if (regw & 0x08)					pci_write_config_word(dev, 0x50, regw&0xfff7);				pci_read_config_word(dev, 0x52, &regw);				if (regw & 0x08)					pci_write_config_word(dev, 0x52, regw&0xfff7);				break;			case ATA_133a:			case ATA_100:				/* Fixup latency */				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);				/* Set compatibility bit */				pci_read_config_byte(dev, 0x49, &reg);				if (!(reg & 0x01)) {					pci_write_config_byte(dev, 0x49, reg|0x01);				}				break;			case ATA_100a:			case ATA_66:				/* Fixup latency */				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);				/* On ATA_66 chips the bit was elsewhere */				pci_read_config_byte(dev, 0x52, &reg);				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, &reg);				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, &reg);				if (!(reg & 0x08)) {					pci_write_config_byte(dev, 0x52, reg|0x08);				}				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	}	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, &regw);		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, &reg48h);		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 (!chipset_family)		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, Vojtech Pavlik");MODULE_DESCRIPTION("PCI driver module for SIS IDE");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;/* * TODO: *	- CLEANUP *	- Use drivers/ide/ide-timing.h ! *	- 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 + -