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

📄 sis5513.c

📁 at91rm9200处理器ide接口驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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, &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) {#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, &reg);				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, &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;			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, &reg48h);	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 + -