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

📄 setup-res.c

📁 IXP425 平台下嵌入式LINUX的PCI总线的驱动程序
💻 C
字号:
/* *	drivers/pci/setup-res.c * * Extruded from code written by *      Dave Rusling (david.rusling@reo.mts.dec.com) *      David Mosberger (davidm@cs.arizona.edu) *	David Miller (davem@redhat.com) * * Support routines for initializing a PCI subsystem. *//* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> *//* * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru> *	     Resource sorting */#include <linux/init.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/cache.h>#include <linux/slab.h>#define DEBUG_CONFIG 0#if DEBUG_CONFIG# define DBGC(args)     printk args#else# define DBGC(args)#endifint __initpci_claim_resource(struct pci_dev *dev, int resource){        struct resource *res = &dev->resource[resource];	struct resource *root = pci_find_parent_resource(dev, res);	int err;	err = -EINVAL;	if (root != NULL) {		err = request_resource(root, res);		if (err) {			printk(KERN_ERR "PCI: Address space collision on "			       "region %d of device %s [%lx:%lx]\n",			       resource, dev->name, res->start, res->end);		}	} else {		printk(KERN_ERR "PCI: No parent found for region %d "		       "of device %s\n", resource, dev->name);	}	return err;}/* * Given the PCI bus a device resides on, try to * find an acceptable resource allocation for a * specific device resource.. */static int pci_assign_bus_resource(const struct pci_bus *bus,	struct pci_dev *dev,	struct resource *res,	unsigned long size,	unsigned long min,	unsigned int type_mask,	int resno){	int i;	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;	for (i = 0 ; i < 4; i++) {		struct resource *r = bus->resource[i];		if (!r)			continue;		/* type_mask must match */		if ((res->flags ^ r->flags) & type_mask)			continue;		/* We cannot allocate a non-prefetching resource from a pre-fetching area */		if ((r->flags & IORESOURCE_PREFETCH) && !(res->flags & IORESOURCE_PREFETCH))			continue;		/* Ok, try it out.. */		if (allocate_resource(r, res, size, min, -1, size, pcibios_align_resource, dev) < 0)			continue;		/* Update PCI config space.  */		pcibios_update_resource(dev, r, res, resno);		return 0;	}	return -EBUSY;}int pci_assign_resource(struct pci_dev *dev, int i){	const struct pci_bus *bus = dev->bus;	struct resource *res = dev->resource + i;	unsigned long size, min;	size = res->end - res->start + 1;	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;	/* First, try exact prefetching match.. */	if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {		/*		 * That failed.		 *		 * But a prefetching area can handle a non-prefetching		 * window (it will just not perform as well).		 */		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {			printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",			       i, res->start, res->end, dev->slot_name);			return -EBUSY;		}	}	DBGC((KERN_ERR "  got res[%lx:%lx] for resource %d of %s\n", res->start,						res->end, i, dev->name));	return 0;}/* Sort resources of a given type by alignment */void __initpdev_sort_resources(struct pci_dev *dev,		    struct resource_list *head, u32 type_mask){	int i;	for (i = 0; i < PCI_NUM_RESOURCES; i++) {		struct resource *r;		struct resource_list *list, *tmp;		unsigned long r_size;		/* PCI-PCI bridges may have I/O ports or		   memory on the primary bus */		if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI &&						i >= PCI_BRIDGE_RESOURCES)			continue;		r = &dev->resource[i];		r_size = r->end - r->start;				if (!(r->flags & type_mask) || r->parent)			continue;		if (!r_size) {			printk(KERN_WARNING "PCI: Ignore bogus resource %d "					 "[%lx:%lx] of %s\n",					  i, r->start, r->end, dev->name);			continue;		}		for (list = head; ; list = list->next) {			unsigned long size = 0;			struct resource_list *ln = list->next;			if (ln)				size = ln->res->end - ln->res->start;			if (r_size > size) {				tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);				if (!tmp) {					printk(KERN_ERR "pdev_sort_resources(): kmalloc() failed!\n");					continue;				}				tmp->next = ln;				tmp->res = r;				tmp->dev = dev;				list->next = tmp;				break;			}		}	}}void __initpdev_enable_device(struct pci_dev *dev){	u32 reg;	u16 cmd;	int i;	DBGC((KERN_ERR "PCI enable device: (%s)\n", dev->name));	pci_read_config_word(dev, PCI_COMMAND, &cmd);	for (i = 0; i < PCI_NUM_RESOURCES; i++) {		struct resource *res = &dev->resource[i];		if (res->flags & IORESOURCE_IO)			cmd |= PCI_COMMAND_IO;		else if (res->flags & IORESOURCE_MEM)			cmd |= PCI_COMMAND_MEMORY;	}	/* Special case, disable the ROM.  Several devices act funny	   (ie. do not respond to memory space writes) when it is left	   enabled.  A good example are QlogicISP adapters.  */	if (dev->rom_base_reg) {		pci_read_config_dword(dev, dev->rom_base_reg, &reg);		reg &= ~PCI_ROM_ADDRESS_ENABLE;		pci_write_config_dword(dev, dev->rom_base_reg, reg);		dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;	}	/* All of these (may) have I/O scattered all around and may not	   use I/O base address registers at all.  So we just have to	   always enable IO to these devices.  */	if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED	    || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA	    || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE	    || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {		cmd |= PCI_COMMAND_IO;	}	/* ??? Always turn on bus mastering.  If the device doesn't support	   it, the bit will go into the bucket. */	cmd |= PCI_COMMAND_MASTER;	/* Set the cache line and default latency (32).  */	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,			(32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));	/* Enable the appropriate bits in the PCI command register.  */	pci_write_config_word(dev, PCI_COMMAND, cmd);	DBGC((KERN_ERR "  cmd reg 0x%x\n", cmd));}

⌨️ 快捷键说明

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