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

📄 setup-pci.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/ide/setup-pci.c		Version 1.10	2002/08/19 * *  Copyright (c) 1998-2000  Andre Hedrick <andre@linux-ide.org> * *  Copyright (c) 1995-1998  Mark Lord *  May be copied or modified under the terms of the GNU General Public License * *  Recent Changes *	Split the set up function into multiple functions *	Use pci_set_master *	Fix misreporting of I/O v MMIO problems *	Initial fixups for simplex devices *//* *  This module provides support for automatic detection and *  configuration of all PCI IDE interfaces present in a system.   */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/ide.h>#include <asm/io.h>#include <asm/irq.h>/** *	ide_match_hwif	-	match a PCI IDE against an ide_hwif *	@io_base: I/O base of device *	@bootable: set if its bootable *	@name: name of device * *	Match a PCI IDE port against an entry in ide_hwifs[], *	based on io_base port if possible. Return the matching hwif, *	or a new hwif. If we find an error (clashing, out of devices, etc) *	return NULL * *	FIXME: we need to handle mmio matches here too */static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name){	int h;	ide_hwif_t *hwif;	/*	 * Look for a hwif with matching io_base specified using	 * parameters to ide_setup().	 */	for (h = 0; h < MAX_HWIFS; ++h) {		hwif = &ide_hwifs[h];		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {			if (hwif->chipset == ide_generic)				return hwif; /* a perfect match */		}	}	/*	 * Look for a hwif with matching io_base default value.	 * If chipset is "ide_unknown", then claim that hwif slot.	 * Otherwise, some other chipset has already claimed it..  :(	 */	for (h = 0; h < MAX_HWIFS; ++h) {		hwif = &ide_hwifs[h];		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {			if (hwif->chipset == ide_unknown)				return hwif; /* match */			printk(KERN_ERR "%s: port 0x%04lx already claimed by %s\n",				name, io_base, hwif->name);			return NULL;	/* already claimed */		}	}	/*	 * Okay, there is no hwif matching our io_base,	 * so we'll just claim an unassigned slot.	 * Give preference to claiming other slots before claiming ide0/ide1,	 * just in case there's another interface yet-to-be-scanned	 * which uses ports 1f0/170 (the ide0/ide1 defaults).	 *	 * Unless there is a bootable card that does not use the standard	 * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.	 */	if (bootable) {		for (h = 0; h < MAX_HWIFS; ++h) {			hwif = &ide_hwifs[h];			if (hwif->chipset == ide_unknown)				return hwif;	/* pick an unused entry */		}	} else {		for (h = 2; h < MAX_HWIFS; ++h) {			hwif = ide_hwifs + h;			if (hwif->chipset == ide_unknown)				return hwif;	/* pick an unused entry */		}	}	for (h = 0; h < 2; ++h) {		hwif = ide_hwifs + h;		if (hwif->chipset == ide_unknown)			return hwif;	/* pick an unused entry */	}	printk(KERN_ERR "%s: too many IDE interfaces, no room in table\n", name);	return NULL;}/** *	ide_setup_pci_baseregs	-	place a PCI IDE controller native *	@dev: PCI device of interface to switch native *	@name: Name of interface * *	We attempt to place the PCI interface into PCI native mode. If *	we succeed the BARs are ok and the controller is in PCI mode. *	Returns 0 on success or an errno code.  * *	FIXME: if we program the interface and then fail to set the BARS *	we don't switch it back to legacy mode. Do we actually care ?? */ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name){	u8 progif = 0;	/*	 * Place both IDE interfaces into PCI "native" mode:	 */	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||			 (progif & 5) != 5) {		if ((progif & 0xa) != 0xa) {			printk(KERN_INFO "%s: device not capable of full "				"native PCI mode\n", name);			return -EOPNOTSUPP;		}		printk("%s: placing both ports into native PCI mode\n", name);		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||		    (progif & 5) != 5) {			printk(KERN_ERR "%s: rewrite of PROGIF failed, wanted "				"0x%04x, got 0x%04x\n",				name, progif|5, progif);			return -EOPNOTSUPP;		}	}	return 0;}#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED/* * Long lost data from 2.0.34 that is now in 2.0.39 * * This was used in ./drivers/block/triton.c to do DMA Base address setup * when PnP failed.  Oh the things we forget.  I believe this was part * of SFF-8038i that has been withdrawn from public access... :-(( */#define DEFAULT_BMIBA	0xe800	/* in case BIOS did not init it */#define DEFAULT_BMCRBA	0xcc00	/* VIA's default value */#define DEFAULT_BMALIBA	0xd400	/* ALI's default value */#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED *//** *	ide_get_or_set_dma_base		-	setup BMIBA *	@hwif: Interface * *	Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: *	If need be we set up the DMA base. Where a device has a partner that *	is already in DMA mode we check and enforce IDE simplex rules. */static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif){	unsigned long	dma_base = 0;	struct pci_dev	*dev = hwif->pci_dev;#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED	int second_chance = 0;second_chance_to_dma:#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */	if ((hwif->mmio) && (hwif->dma_base))		return hwif->dma_base;	if (hwif->mate && hwif->mate->dma_base) {		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);	} else {		dma_base = (hwif->mmio) ?			((unsigned long) hwif->hwif_data) :			(pci_resource_start(dev, 4));		if (!dma_base) {			printk(KERN_ERR "%s: dma_base is invalid (0x%04lx)\n",				hwif->cds->name, dma_base);			dma_base = 0;		}	}#ifdef CONFIG_BLK_DEV_IDEDMA_FORCED	/* FIXME - should use pci_assign_resource surely */	if ((!dma_base) && (!second_chance)) {		unsigned long set_bmiba = 0;		second_chance++;		switch(dev->vendor) {			case PCI_VENDOR_ID_AL:				set_bmiba = DEFAULT_BMALIBA; break;			case PCI_VENDOR_ID_VIA:				set_bmiba = DEFAULT_BMCRBA; break;			case PCI_VENDOR_ID_INTEL:				set_bmiba = DEFAULT_BMIBA; break;			default:				return dma_base;		}		pci_write_config_dword(dev, 0x20, set_bmiba|1);		goto second_chance_to_dma;	}#endif /* CONFIG_BLK_DEV_IDEDMA_FORCED */	if (dma_base) {		u8 simplex_stat = 0;		dma_base += hwif->channel ? 8 : 0;		switch(dev->device) {			case PCI_DEVICE_ID_AL_M5219:			case PCI_DEVICE_ID_AL_M5229:			case PCI_DEVICE_ID_AMD_VIPER_7409:			case PCI_DEVICE_ID_CMD_643:			case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:				simplex_stat = hwif->INB(dma_base + 2);				hwif->OUTB((simplex_stat&0x60),(dma_base + 2));				simplex_stat = hwif->INB(dma_base + 2);				if (simplex_stat & 0x80) {					printk(KERN_INFO "%s: simplex device: "						"DMA forced\n",						hwif->cds->name);				}				break;			default:				/*				 * If the device claims "simplex" DMA,				 * this means only one of the two interfaces				 * can be trusted with DMA at any point in time.				 * So we should enable DMA only on one of the				 * two interfaces.				 */				simplex_stat = hwif->INB(dma_base + 2);				if (simplex_stat & 0x80) {					/* simplex device? */#if 0					/* *	At this point we haven't probed the drives so we can't make the *	appropriate decision. Really we should defer this problem *	until we tune the drive then try to grab DMA ownership if we want *	to be the DMA end. This has to be become dynamic to handle hot *	plug. */					/* Don't enable DMA on a simplex channel with no drives */					if (!hwif->drives[0].present && !hwif->drives[1].present)					{						printk(KERN_INFO "%s: simplex device with no drives: DMA disabled\n",								hwif->cds->name);						dma_base = 0;					}					/* If our other channel has DMA then we cannot */					else #endif										if(hwif->mate && hwif->mate->dma_base) 					{						printk(KERN_INFO "%s: simplex device: "							"DMA disabled\n",							hwif->cds->name);						dma_base = 0;					}				}		}	}	return dma_base;}static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d){	if ((d->vendor != dev->vendor) && (d->device != dev->device)) {		printk(KERN_INFO "%s: unknown IDE controller at PCI slot "			"%s, VID=%04x, DID=%04x\n",			d->name, dev->slot_name, dev->vendor, dev->device);        } else {		printk(KERN_INFO "%s: IDE controller at PCI slot %s\n",			d->name, dev->slot_name);	}}/** *	ide_pci_enable	-	do PCI enables *	@dev: PCI device *	@d: IDE pci device data * *	Enable the IDE PCI device. We attempt to enable the device in full *	but if that fails then we only need BAR4 so we will enable that. *	 *	Returns zero on success or an error code */ static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d){		if (pci_enable_device(dev)) {		if (pci_enable_device_bars(dev, 1 << 4)) {			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "				"Could not enable device.\n", d->name);			return -EBUSY;		} else			printk(KERN_WARNING "%s: Not fully BIOS configured!\n", d->name);	}	/*	 * assume all devices can do 32-bit dma for now. we can add a	 * dma mask field to the ide_pci_device_t if we need it (or let	 * lower level driver set the dma mask)	 */	if (pci_set_dma_mask(dev, 0xffffffff)) {		printk(KERN_ERR "%s: can't set dma mask\n", d->name);		return -EBUSY;	}	 	/* FIXME: Temporary - until we put in the hotplug interface logic	   Check that the bits we want are not in use by someone else */	if (pci_request_region(dev, 4, "ide_tmp"))		return -EBUSY;	pci_release_region(dev, 4);		return 0;	}/** *	ide_pci_configure	-	configure an unconfigured device *	@dev: PCI device *	@d: IDE pci device data * *	Enable and configure the PCI device we have been passed. *	Returns zero on success or an error code. */ static int ide_pci_configure(struct pci_dev *dev, ide_pci_device_t *d){	u16 pcicmd = 0;	/*	 * PnP BIOS was *supposed* to have setup this device, but we	 * can do it ourselves, so long as the BIOS has assigned an IRQ	 * (or possibly the device is using a "legacy header" for IRQs).	 * Maybe the user deliberately *disabled* the device,	 * but we'll eventually ignore it again if no drives respond.	 */	if (ide_setup_pci_baseregs(dev, d->name) || pci_write_config_word(dev, PCI_COMMAND, pcicmd|PCI_COMMAND_IO)) 	{		printk(KERN_INFO "%s: device disabled (BIOS)\n", d->name);		return -ENODEV;	}	if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {		printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);		return -EIO;	}	if (!(pcicmd & PCI_COMMAND_IO)) {		printk(KERN_ERR "%s: unable to enable IDE controller\n", d->name);		return -ENXIO;	}	return 0;}/** *	ide_pci_check_iomem	-	check a register is I/O *	@dev: pci device *	@d: ide_pci_device *	@bar: bar number * *	Checks if a BAR is configured and points to MMIO space. If so *	print an error and return an error code. Otherwise return 0 */ static int ide_pci_check_iomem(struct pci_dev *dev, ide_pci_device_t *d, int bar){	ulong flags = pci_resource_flags(dev, bar);		/* Unconfigured ? */	if (!flags || pci_resource_len(dev, bar) == 0)		return 0;	/* I/O space */			if(flags & PCI_BASE_ADDRESS_IO_MASK)		return 0;			/* Bad */	printk(KERN_ERR "%s: IO baseregs (BIOS) are reported "			"as MEM, report to "			"<andre@linux-ide.org>.\n", d->name);	return -EINVAL;}			/** *	ide_hwif_configure	-	configure an IDE interface *	@dev: PCI device holding interface *	@d: IDE pci data *	@mate: Paired interface if any * *	Perform the initial set up for the hardware interface structure. This *	is done per interface port rather than per PCI device. There may be *	more than one port per device. * *	Returns the new hardware interface structure, or NULL on a failure */ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, ide_pci_device_t *d, ide_hwif_t *mate, int port, int irq){	unsigned long ctl = 0, base = 0;

⌨️ 快捷键说明

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