siimage.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 1,228 行 · 第 1/3 页

C
1,228
字号
			mode |= ((unit) ? 0x10 : 0x01);			break;		case XFER_MW_DMA_2:		case XFER_MW_DMA_1:		case XFER_MW_DMA_0:			multi = dma[speed - XFER_MW_DMA_0];			mode |= ((unit) ? 0x20 : 0x02);			config_siimage_chipset_for_pio(drive, 0);			break;		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:			multi = dma[2];			ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :					   (ultra5[speed - XFER_UDMA_0]));			mode |= ((unit) ? 0x30 : 0x03);			config_siimage_chipset_for_pio(drive, 0);			break;		default:			return 1;	}	if (hwif->mmio) {		hwif->OUTB(mode, base + addr_mask);		hwif->OUTW(multi, ma);		hwif->OUTW(ultra, ua);	} else {		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);		pci_write_config_word(hwif->pci_dev, ma, multi);		pci_write_config_word(hwif->pci_dev, ua, ultra);	}	return (ide_config_drive_speed(drive, speed));}/** *	config_chipset_for_dma	-	configure for DMA *	@drive: drive to configure * *	Called by the IDE layer when it wants the timings set up. *	For the CMD680 we also need to set up the PIO timings and *	enable DMA. */ static int config_chipset_for_dma (ide_drive_t *drive){	u8 speed	= ide_dma_speed(drive, siimage_ratemask(drive));	config_chipset_for_pio(drive, !speed);	if (!speed)		return 0;	if (ide_set_xfer_rate(drive, speed))		return 0;	if (!drive->init_speed)		drive->init_speed = speed;	return ide_dma_enable(drive);}/** *	siimage_configure_drive_for_dma	-	set up for DMA transfers *	@drive: drive we are going to set up * *	Set up the drive for DMA, tune the controller and drive as  *	required. If the drive isn't suitable for DMA or we hit *	other problems then we will drop down to PIO and set up *	PIO appropriately */ static int siimage_config_drive_for_dma (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	struct hd_driveid *id	= drive->id;	if ((id->capability & 1) != 0 && 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) && siimage_ratemask(drive)) {			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:		config_chipset_for_pio(drive, 1);		return hwif->ide_dma_off_quietly(drive);	}	/* IORDY not supported */	return 0;}/* returns 1 if dma irq issued, 0 otherwise */static int siimage_io_ide_dma_test_irq (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 dma_altstat		= 0;	unsigned long addr	= siimage_selreg(hwif, 1);	/* return 1 if INTR asserted */	if ((hwif->INB(hwif->dma_status) & 4) == 4)		return 1;	/* return 1 if Device INTR asserted */	pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat);	if (dma_altstat & 8)		return 0;	//return 1;	return 0;}/** *	siimage_mmio_ide_dma_count	-	DMA bytes done *	@drive * *	If we are doing VDMA the CMD680 requires a little bit *	of more careful handling and we have to read the counts *	off ourselves. For non VDMA life is normal. */ static int siimage_mmio_ide_dma_count (ide_drive_t *drive){#ifdef SIIMAGE_VIRTUAL_DMAPIO	struct request *rq	= HWGROUP(drive)->rq;	ide_hwif_t *hwif	= HWIF(drive);	u32 count		= (rq->nr_sectors * SECTOR_SIZE);	u32 rcount		= 0;	unsigned long addr	= siimage_selreg(hwif, 0x1C);	hwif->OUTL(count, addr);	rcount = hwif->INL(addr);	printk("\n%s: count = %d, rcount = %d, nr_sectors = %lu\n",		drive->name, count, rcount, rq->nr_sectors);#endif /* SIIMAGE_VIRTUAL_DMAPIO */	return __ide_dma_count(drive);}/** *	siimage_mmio_ide_dma_test_irq	-	check we caused an IRQ *	@drive: drive we are testing * *	Check if we caused an IDE DMA interrupt. We may also have caused *	SATA status interrupts, if so we clean them up and continue. */ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	unsigned long base	= (unsigned long)hwif->hwif_data;	unsigned long addr	= siimage_selreg(hwif, 0x1);	if (SATA_ERROR_REG) {		u32 ext_stat = hwif->INL(base + 0x10);		u8 watchdog = 0;		if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {			u32 sata_error = hwif->INL(SATA_ERROR_REG);			hwif->OUTL(sata_error, SATA_ERROR_REG);			watchdog = (sata_error & 0x00680000) ? 1 : 0;#if 1			printk(KERN_WARNING "%s: sata_error = 0x%08x, "				"watchdog = %d, %s\n",				drive->name, sata_error, watchdog,				__FUNCTION__);#endif		} else {			watchdog = (ext_stat & 0x8000) ? 1 : 0;		}		ext_stat >>= 16;		if (!(ext_stat & 0x0404) && !watchdog)			return 0;	}	/* return 1 if INTR asserted */	if ((hwif->INB(hwif->dma_status) & 0x04) == 0x04)		return 1;	/* return 1 if Device INTR asserted */	if ((hwif->INB(addr) & 8) == 8)		return 0;	//return 1;	return 0;}static int siimage_mmio_ide_dma_verbose (ide_drive_t *drive){	int temp = __ide_dma_verbose(drive);	return temp;}/** *	siimage_busproc		-	bus isolation ioctl *	@drive: drive to isolate/restore *	@state: bus state to set * *	Used by the SII3112 to handle bus isolation. As this is a  *	SATA controller the work required is quite limited, we  *	just have to clean up the statistics */ static int siimage_busproc (ide_drive_t * drive, int state){	ide_hwif_t *hwif	= HWIF(drive);	u32 stat_config		= 0;	unsigned long addr	= siimage_selreg(hwif, 0);	if (hwif->mmio) {		stat_config = hwif->INL(addr);	} else		pci_read_config_dword(hwif->pci_dev, addr, &stat_config);	switch (state) {		case BUSSTATE_ON:			hwif->drives[0].failures = 0;			hwif->drives[1].failures = 0;			break;		case BUSSTATE_OFF:			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;			break;		case BUSSTATE_TRISTATE:			hwif->drives[0].failures = hwif->drives[0].max_failures + 1;			hwif->drives[1].failures = hwif->drives[1].max_failures + 1;			break;		default:			return -EINVAL;	}	hwif->bus_state = state;	return 0;}/** *	siimage_reset_poll	-	wait for sata reset *	@drive: drive we are resetting * *	Poll the SATA phy and see whether it has come back from the dead *	yet. */ static int siimage_reset_poll (ide_drive_t *drive){	if (SATA_STATUS_REG) {		ide_hwif_t *hwif	= HWIF(drive);		if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) {			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",				hwif->name, hwif->INL(SATA_STATUS_REG));			HWGROUP(drive)->poll_timeout = 0;			return ide_started;		}		return 0;	} else {		return 0;	}}/** *	siimage_pre_reset	-	reset hook *	@drive: IDE device being reset * *	For the SATA devices we need to handle recalibration/geometry *	differently */ static void siimage_pre_reset (ide_drive_t *drive){	if (drive->media != ide_disk)		return;	if (is_sata(HWIF(drive)))	{		drive->special.b.set_geometry = 0;		drive->special.b.recalibrate = 0;	}}/** *	siimage_reset	-	reset a device on an siimage controller *	@drive: drive to reset * *	Perform a controller level reset fo the device. For *	SATA we must also check the PHY. */ static void siimage_reset (ide_drive_t *drive){	ide_hwif_t *hwif	= HWIF(drive);	u8 reset		= 0;	unsigned long addr	= siimage_selreg(hwif, 0);	if (hwif->mmio) {		reset = hwif->INB(addr);		hwif->OUTB((reset|0x03), addr);		/* FIXME:posting */		udelay(25);		hwif->OUTB(reset, addr);		(void) hwif->INB(addr);	} else {		pci_read_config_byte(hwif->pci_dev, addr, &reset);		pci_write_config_byte(hwif->pci_dev, addr, reset|0x03);		udelay(25);		pci_write_config_byte(hwif->pci_dev, addr, reset);		pci_read_config_byte(hwif->pci_dev, addr, &reset);	}	if (SATA_STATUS_REG) {		u32 sata_stat = hwif->INL(SATA_STATUS_REG);		printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n",			hwif->name, sata_stat, __FUNCTION__);		if (!(sata_stat)) {			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",				hwif->name, sata_stat);			drive->failures++;		}	}}/** *	proc_reports_siimage		-	add siimage controller to proc *	@dev: PCI device *	@clocking: SCSC value *	@name: controller name * *	Report the clocking mode of the controller and add it to *	the /proc interface layer */ static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name){	if(pdev_is_sata(dev))		goto sata_skip;	printk(KERN_INFO "%s: BASE CLOCK ", name);	clocking &= 0x03;	switch(clocking) {		case 0x03: printk("DISABLED !\n"); break;		case 0x02: printk("== 2X PCI \n"); break;		case 0x01: printk("== 133 \n"); break;		case 0x00: printk("== 100 \n"); break;	}sata_skip:#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS)	siimage_devs[n_siimage_devs++] = dev;	if (!siimage_proc) {		siimage_proc = 1;		ide_pci_register_host_proc(&siimage_procs[0]);	}#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */}/** *	setup_mmio_siimage	-	switch an SI controller into MMIO *	@dev: PCI device we are configuring *	@name: device name * *	Attempt to put the device into mmio mode. There are some slight *	complications here with certain systems where the mmio bar isnt *	mapped so we have to be sure we can fall back to I/O. */ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name){	unsigned long bar5	= pci_resource_start(dev, 5);	unsigned long barsize	= pci_resource_len(dev, 5);	u8 tmpbyte	= 0;	unsigned long addr;	void *ioaddr;	/*	 *	Drop back to PIO if we can't map the mmio. Some	 *	systems seem to get terminally confused in the PCI	 *	spaces.	 */	 	if(!request_mem_region(bar5, barsize, name))	{		printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?