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

📄 siimage.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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)) {		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;		}	}}/** *	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");		return 0;	}			ioaddr = ioremap(bar5, barsize);	if (ioaddr == NULL)	{		release_mem_region(bar5, barsize);		return 0;	}	pci_set_master(dev);	pci_set_drvdata(dev, ioaddr);	addr = (unsigned long) ioaddr;	if (pdev_is_sata(dev)) {		writel(0, addr + 0x148);		writel(0, addr + 0x1C8);	}	writeb(0, addr + 0xB4);	writeb(0, addr + 0xF4);	tmpbyte = readb(addr + 0x4A);	switch(tmpbyte & 0x30) {		case 0x00:			/* In 100 MHz clocking, try and switch to 133 */			writeb(tmpbyte|0x10, addr + 0x4A);			break;		case 0x10:			/* On 133Mhz clocking */			break;		case 0x20:			/* On PCIx2 clocking */			break;		case 0x30:			/* Clocking is disabled */			/* 133 clock attempt to force it on */			writeb(tmpbyte & ~0x20, addr + 0x4A);			break;	}		writeb(      0x72, addr + 0xA1);	writew(    0x328A, addr + 0xA2);	writel(0x62DD62DD, addr + 0xA4);	writel(0x43924392, addr + 0xA8);	writel(0x40094009, addr + 0xAC);	writeb(      0x72, addr + 0xE1);	writew(    0x328A, addr + 0xE2);	writel(0x62DD62DD, addr + 0xE4);	writel(0x43924392, addr + 0xE8);	writel(0x40094009, addr + 0xEC);	if (pdev_is_sata(dev)) {		writel(0xFFFF0000, addr + 0x108);		writel(0xFFFF0000, addr + 0x188);		writel(0x00680000, addr + 0x148);		writel(0x00680000, addr + 0x1C8);	}	tmpbyte = readb(addr + 0x4A);	proc_reports_siimage(dev, (tmpbyte>>4), name);	return 1;}/** *	init_chipset_siimage	-	set up an SI device *	@dev: PCI device *	@name: device name * *	Perform the initial PCI set up for this device. Attempt to switch *	to 133MHz clocking if the system isn't already set up to do it. */static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name){	u32 class_rev	= 0;	u8 tmpbyte	= 0;	u8 BA5_EN	= 0;        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);        class_rev &= 0xff;	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255);		pci_read_config_byte(dev, 0x8A, &BA5_EN);	if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) {		if (setup_mmio_siimage(dev, name)) {			return 0;		}	}	pci_write_config_byte(dev, 0x80, 0x00);	pci_write_config_byte(dev, 0x84, 0x00);	pci_read_config_byte(dev, 0x8A, &tmpbyte);	switch(tmpbyte & 0x30) {		case 0x00:			/* 133 clock attempt to force it on */			pci_write_config_byte(dev, 0x8A, tmpbyte|0x10);		case 0x30:			/* if clocking is disabled */			/* 133 clock attempt to force it on */			pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20);		case 0x10:			/* 133 already */			break;		case 0x20:			/* BIOS set PCI x2 clocking */			break;	}	pci_read_config_byte(dev,   0x8A, &tmpbyte);	pci_write_config_byte(dev,  0xA1, 0x72);	pci_write_config_word(dev,  0xA2, 0x328A);	pci_write_config_dword(dev, 0xA4, 0x62DD62DD);	pci_write_config_dword(dev, 0xA8, 0x43924392);	pci_write_config_dword(dev, 0xAC, 0x40094009);	pci_write_config_byte(dev,  0xB1, 0x72);	pci_write_config_word(dev,  0xB2, 0x328A);	pci_write_config_dword(dev, 0xB4, 0x62DD62DD);	pci_write_config_dword(dev, 0xB8, 0x43924392);	pci_write_config_dword(dev, 0xBC, 0x40094009);	proc_reports_siimage(dev, (tmpbyte>>4), name);	return 0;}/** *	init_mmio_iops_siimage	-	set up the iops for MMIO *	@hwif: interface to set up * *	The basic setup here is fairly simple, we can use standard MMIO *	operations. However we do have to set the taskfile register offsets *	by hand as there isnt a standard defined layout for them this *	time. * *	The hardware supports buffered taskfiles and also some rather nice *	extended PRD tables. Unfortunately right now we don't. */static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif){	struct pci_dev *dev	= hwif->pci_dev;	void *addr		= pci_get_drvdata(dev);	u8 ch			= hwif->channel;	hw_regs_t		hw;	unsigned long		base;	/*	 *	Fill in the basic HWIF bits	 */	default_hwif_mmiops(hwif);	hwif->hwif_data			= addr;	/*	 *	Now set up the hw. We have to do this ourselves as	 *	the MMIO layout isnt the same as the the standard port	 *	based I/O	 */	 	memset(&hw, 0, sizeof(hw_regs_t));	hw.priv				= addr;	base				= (unsigned long)addr;	if(ch)		base += 0xC0;	else		base += 0x80;	/*	 *	The buffered task file doesn't have status/control	 *	so we can't currently use it sanely since we want to	 *	use LBA48 mode.	 */	//	base += 0x10;//	hwif->no_lba48 = 1;	hw.io_ports[IDE_DATA_OFFSET]	= base;	hw.io_ports[IDE_ERROR_OFFSET]	= base + 1;	hw.io_ports[IDE_NSECTOR_OFFSET]	= base + 2;	hw.io_ports[IDE_SECTOR_OFFSET]	= base + 3;	hw.io_ports[IDE_LCYL_OFFSET]	= base + 4;	hw.io_ports[IDE_HCYL_OFFSET]	= base + 5;	hw.io_ports[IDE_SELECT_OFFSET]	= base + 6;	hw.io_ports[IDE_STATUS_OFFSET]	= base + 7;	hw.io_ports[IDE_CONTROL_OFFSET]	= base + 10;	hw.io_ports[IDE_IRQ_OFFSET]	= 0;        if (pdev_is_sata(dev)) {        	base = (unsigned long) addr;        	if(ch)        		base += 0x80;		hw.sata_scr[SATA_STATUS_OFFSET]	= base + 0x104;		hw.sata_scr[SATA_ERROR_OFFSET]	= base + 0x108;		hw.sata_scr[SATA_CONTROL_OFFSET]= base + 0x100;		hw.sata_misc[SATA_MISC_OFFSET]	= base + 0x140;		hw.sata_misc[SATA_PHY_OFFSET]	= base + 0x144;		hw.sata_misc[SATA_IEN_OFFSET]	= base + 0x148;	}	hw.irq				= hwif->pci_dev->irq;	memcpy(&hwif->hw, &hw, sizeof(hw));	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));	if (is_sata(hwif)) {		memcpy(hwif->sata_scr, hwif->hw.sata_scr, sizeof(hwif->hw.sata_scr));		memcpy(hwif->sata_misc, hwif->hw.sata_misc, sizeof(hwif->hw.sata_misc));	}	hwif->irq			= hw.irq;       	base = (unsigned long) addr;#ifdef SIIMAGE_LARGE_DMA/* Watch the brackets - even Ken and Dennis get some language design wrong */	hwif->dma_base			= base + (ch ? 0x18 : 0x10);	hwif->dma_base2			= base + (ch ? 0x08 : 0x00);	hwif->dma_prdtable		= hwif->dma_base2 + 4;#else /* ! SIIMAGE_LARGE_DMA */	hwif->dma_base			= base + (ch ? 0x08 : 0x00);	hwif->dma_base2			= base + (ch ? 0x18 : 0x10);#endif /* SIIMAGE_LARGE_DMA */	hwif->mmio			= 2;}static int is_dev_seagate_sata(ide_drive_t *drive){	const char *s = &drive->id->model[0];	unsigned len;	if (!drive->present)		return 0;	len = strnlen(s, sizeof(drive->id->model));	if ((len > 4) && (!memcmp(s, "ST", 2))) {		if ((!memcmp(s + len - 2, "AS", 2)) ||		    (!memcmp(s + len - 3, "ASL", 3))) {			printk(KERN_INFO "%s: applying pessimistic Seagate "					 "errata fix\n", drive->name);			return 1;		}	}	return 0;}/** *	init_iops_siimage	-	set up iops *	@hwif: interface to set up * *	Do the basic setup for the SIIMAGE hardware interface *	and then do the MMIO setup if we can. This is the first *	look in we get for setting up the hwif so that we *	can get the iops right before using them. */static void __devinit init_iops_siimage(ide_hwif_t *hwif){	struct pci_dev *dev	= hwif->pci_dev;	u32 class_rev		= 0;	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);	class_rev &= 0xff;		hwif->hwif_data = NULL;	hwif->rqsize = 128;	if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0]))		hwif->rqsize = 15;	if (pci_get_drvdata(dev) == NULL)		return;	init_mmio_iops_siimage(hwif);}/** *	ata66_siimage	-	check for 80 pin cable *	@hwif: interface to check * *	Check for the presence of an ATA66 capable cable on the *	interface. */static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif){	unsigned long addr = siimage_selreg(hwif, 0);	if (pci_get_drvdata(hwif->pci_dev) == NULL) {		u8 ata66 = 0;		pci_read_config_byte(hwif->pci_dev, addr, &ata66);		return (ata66 & 0x01) ? 1 : 0;	}	return (hwif->INB(addr) & 0x01) ? 1 : 0;}/** *	init_hwif_siimage	-	set up hwif structs *	@hwif: interface to set up * *	We do the basic set up of the interface structure. The SIIMAGE *	requires several custom handlers so we override the default *	ide DMA handlers appropriately */static void __devinit init_hwif_siimage(ide_hwif_t *hwif){	hwif->autodma = 0;		hwif->resetproc = &siimage_reset;	hwif->speedproc = &siimage_tune_chipset;	hwif->tuneproc	= &siimage_tuneproc;	hwif->reset_poll = &siimage_reset_poll;	hwif->pre_reset = &siimage_pre_reset;	if(is_sata(hwif))		hwif->busproc   = &siimage_busproc;	if (!hwif->dma_base) {		hwif->drives[0].autotune = 1;		hwif->drives[1].autotune = 1;		return;	}	hwif->ultra_mask = 0x7f;	hwif->mwdma_mask = 0x07;	hwif->swdma_mask = 0x07;	if (!is_sata(hwif))		hwif->atapi_dma = 1;	hwif->ide_dma_check = &siimage_config_drive_for_dma;	if (!(hwif->udma_four))		hwif->udma_four = ata66_siimage(hwif);	if (hwif->mmio) {		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;		hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose;	} else {		hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;	}		/*	 *	The BIOS often doesn't set up DMA on this controller	 *	so we always do it.	 */	hwif->autodma = 1;	hwif->drives[0].autodma = hwif->autodma;	hwif->drives[1].autodma = hwif->autodma;}#define DECLARE_SII_DEV(name_str)			\	{						\		.name		= name_str,		\		.init_chipset	= init_chipset_siimage,	\		.init_iops	= init_iops_siimage,	\		.init_hwif	= init_hwif_siimage,	\		.channels	= 2,			\		.autodma	= AUTODMA,		\		.bootable	= ON_BOARD,		\	}static ide_pci_device_t siimage_chipsets[] __devinitdata = {	/* 0 */ DECLARE_SII_DEV("SiI680"),	/* 1 */ DECLARE_SII_DEV("SiI3112 Serial ATA"),	/* 2 */ DECLARE_SII_DEV("Adaptec AAR-1210SA")};/** *	siimage_init_one	-	pci layer discovery entry *	@dev: PCI device *	@id: ident table entry * *	Called by the PCI code when it finds an SI680 or SI3112 controller. *	We then use the IDE PCI generic helper to do most of the work. */ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id){	ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);	return 0;}static struct pci_device_id siimage_pci_tbl[] = {	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},#ifdef CONFIG_BLK_DEV_IDE_SATA	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},#endif	{ 0, },};MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);static struct pci_driver driver = {	.name		= "SiI IDE",	.id_table	= siimage_pci_tbl,	.probe		= siimage_init_one,};static int siimage_ide_init(void){	return ide_pci_register_driver(&driver);}module_init(siimage_ide_init);MODULE_AUTHOR("Andre Hedrick, Alan Cox");MODULE_DESCRIPTION("PCI driver module for SiI IDE");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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