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

📄 pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	return -ENODEV;}void __initpci_process_bridge_OF_ranges(struct pci_controller *hose,			   struct device_node *dev, int primary){	static unsigned int static_lc_ranges[256] __initdata;	unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;	unsigned int size;	int rlen = 0, orig_rlen;	int memno = 0;	struct resource *res;	int np, na = prom_n_addr_cells(dev);	np = na + 5;	/* First we try to merge ranges to fix a problem with some pmacs	 * that can have more than 3 ranges, fortunately using contiguous	 * addresses -- BenH	 */	dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);	if (!dt_ranges)		return;	/* Sanity check, though hopefully that never happens */	if (rlen > sizeof(static_lc_ranges)) {		printk(KERN_WARNING "OF ranges property too large !\n");		rlen = sizeof(static_lc_ranges);	}	lc_ranges = static_lc_ranges;	memcpy(lc_ranges, dt_ranges, rlen);	orig_rlen = rlen;	/* Let's work on a copy of the "ranges" property instead of damaging	 * the device-tree image in memory	 */	ranges = lc_ranges;	prev = NULL;	while ((rlen -= np * sizeof(unsigned int)) >= 0) {		if (prev) {			if (prev[0] == ranges[0] && prev[1] == ranges[1] &&				(prev[2] + prev[na+4]) == ranges[2] &&				(prev[na+2] + prev[na+4]) == ranges[na+2]) {				prev[na+4] += ranges[na+4];				ranges[0] = 0;				ranges += np;				continue;			}		}		prev = ranges;		ranges += np;	}	/*	 * The ranges property is laid out as an array of elements,	 * each of which comprises:	 *   cells 0 - 2:	a PCI address	 *   cells 3 or 3+4:	a CPU physical address	 *			(size depending on dev->n_addr_cells)	 *   cells 4+5 or 5+6:	the size of the range	 */	ranges = lc_ranges;	rlen = orig_rlen;	while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {		res = NULL;		size = ranges[na+4];		switch (ranges[0] >> 24) {		case 1:		/* I/O space */			if (ranges[2] != 0)				break;			hose->io_base_phys = ranges[na+2];			/* limit I/O space to 16MB */			if (size > 0x01000000)				size = 0x01000000;			hose->io_base_virt = ioremap(ranges[na+2], size);			if (primary)				isa_io_base = (unsigned long) hose->io_base_virt;			res = &hose->io_resource;			res->flags = IORESOURCE_IO;			res->start = ranges[2];			break;		case 2:		/* memory space */			memno = 0;			if (ranges[1] == 0 && ranges[2] == 0			    && ranges[na+4] <= (16 << 20)) {				/* 1st 16MB, i.e. ISA memory area */				if (primary)					isa_mem_base = ranges[na+2];				memno = 1;			}			while (memno < 3 && hose->mem_resources[memno].flags)				++memno;			if (memno == 0)				hose->pci_mem_offset = ranges[na+2] - ranges[2];			if (memno < 3) {				res = &hose->mem_resources[memno];				res->flags = IORESOURCE_MEM;				res->start = ranges[na+2];			}			break;		}		if (res != NULL) {			res->name = dev->full_name;			res->end = res->start + size - 1;			res->parent = NULL;			res->sibling = NULL;			res->child = NULL;		}		ranges += np;	}}/* We create the "pci-OF-bus-map" property now so it appears in the * /proc device tree */void __initpci_create_OF_bus_map(void){	struct property* of_prop;		of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);	if (of_prop && find_path_device("/")) {		memset(of_prop, -1, sizeof(struct property) + 256);		of_prop->name = "pci-OF-bus-map";		of_prop->length = 256;		of_prop->value = (unsigned char *)&of_prop[1];		prom_add_property(find_path_device("/"), of_prop);	}}static ssize_t pci_show_devspec(struct device *dev, char *buf){	struct pci_dev *pdev;	struct device_node *np;	pdev = to_pci_dev (dev);	np = pci_device_to_OF_node(pdev);	if (np == NULL || np->full_name == NULL)		return 0;	return sprintf(buf, "%s", np->full_name);}static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);#endif /* CONFIG_PPC_OF *//* Add sysfs properties */void pcibios_add_platform_entries(struct pci_dev *pdev){#ifdef CONFIG_PPC_OF	device_create_file(&pdev->dev, &dev_attr_devspec);#endif /* CONFIG_PPC_OF */}#ifdef CONFIG_PPC_PMAC/* * This set of routines checks for PCI<->PCI bridges that have closed * IO resources and have child devices. It tries to re-open an IO * window on them. * * This is a _temporary_ fix to workaround a problem with Apple's OF * closing IO windows on P2P bridges when the OF drivers of cards * below this bridge don't claim any IO range (typically ATI or * Adaptec). * * A more complete fix would be to use drivers/pci/setup-bus.c, which * involves a working pcibios_fixup_pbus_ranges(), some more care about * ordering when creating the host bus resources, and maybe a few more * minor tweaks *//* Initialize bridges with base/limit values we have collected */static void __initdo_update_p2p_io_resource(struct pci_bus *bus, int enable_vga){	struct pci_dev *bridge = bus->self;	struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;	u32 l;	u16 w;	struct resource res;	if (bus->resource[0] == NULL)		return; 	res = *(bus->resource[0]);	DBG("Remapping Bus %d, bridge: %s\n", bus->number, bridge->slot_name);	res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);	res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);	DBG("  IO window: %08lx-%08lx\n", res.start, res.end);	/* Set up the top and bottom of the PCI I/O segment for this bus. */	pci_read_config_dword(bridge, PCI_IO_BASE, &l);	l &= 0xffff000f;	l |= (res.start >> 8) & 0x00f0;	l |= res.end & 0xf000;	pci_write_config_dword(bridge, PCI_IO_BASE, l);	if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {		l = (res.start >> 16) | (res.end & 0xffff0000);		pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);	}	pci_read_config_word(bridge, PCI_COMMAND, &w);	w |= PCI_COMMAND_IO;	pci_write_config_word(bridge, PCI_COMMAND, w);#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */	if (enable_vga) {		pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);		w |= PCI_BRIDGE_CTL_VGA;		pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);	}#endif}/* This function is pretty basic and actually quite broken for the * general case, it's enough for us right now though. It's supposed * to tell us if we need to open an IO range at all or not and what * size. */static int __initcheck_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga){	struct list_head *ln;	int	i;	int	rc = 0;#define push_end(res, size) do { unsigned long __sz = (size) ; \	res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \    } while (0)	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {		struct pci_dev *dev = pci_dev_b(ln);		u16 class = dev->class >> 8;		if (class == PCI_CLASS_DISPLAY_VGA ||		    class == PCI_CLASS_NOT_DEFINED_VGA)			*found_vga = 1;		if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)			rc |= check_for_io_childs(dev->subordinate, res, found_vga);		if (class == PCI_CLASS_BRIDGE_CARDBUS)			push_end(res, 0xfff);		for (i=0; i<PCI_NUM_RESOURCES; i++) {			struct resource *r;			unsigned long r_size;			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_size < 0xfff)				r_size = 0xfff;			if (r->flags & IORESOURCE_IO && (r_size) != 0) {				rc = 1;				push_end(res, r_size);			}		}	}	return rc;}/* Here we scan all P2P bridges of a given level that have a closed * IO window. Note that the test for the presence of a VGA card should * be improved to take into account already configured P2P bridges, * currently, we don't see them and might end up configuring 2 bridges * with VGA pass through enabled */static void __initdo_fixup_p2p_level(struct pci_bus *bus){	struct list_head *ln;	int i, parent_io;	int has_vga = 0;	for (parent_io=0; parent_io<4; parent_io++)		if (bus->resource[parent_io]		    && bus->resource[parent_io]->flags & IORESOURCE_IO)			break;	if (parent_io >= 4)		return;	for (ln=bus->children.next; ln != &bus->children; ln=ln->next) {		struct pci_bus *b = pci_bus_b(ln);		struct pci_dev *d = b->self;		struct pci_controller* hose = (struct pci_controller *)d->sysdata;		struct resource *res = b->resource[0];		struct resource tmp_res;		unsigned long max;		int found_vga = 0;		memset(&tmp_res, 0, sizeof(tmp_res));		tmp_res.start = bus->resource[parent_io]->start;		/* We don't let low addresses go through that closed P2P bridge, well,		 * that may not be necessary but I feel safer that way		 */		if (tmp_res.start == 0)			tmp_res.start = 0x1000;			if (!list_empty(&b->devices) && res && res->flags == 0 &&		    res != bus->resource[parent_io] &&		    (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&		    check_for_io_childs(b, &tmp_res, &found_vga)) {			u8 io_base_lo;			printk(KERN_INFO "Fixing up IO bus %s\n", b->name);			if (found_vga) {				if (has_vga) {					printk(KERN_WARNING "Skipping VGA, already active"					    " on bus segment\n");					found_vga = 0;				} else					has_vga = 1;			}			pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);			if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)				max = ((unsigned long) hose->io_base_virt					- isa_io_base) + 0xffffffff;			else				max = ((unsigned long) hose->io_base_virt					- isa_io_base) + 0xffff;			*res = tmp_res;			res->flags = IORESOURCE_IO;			res->name = b->name;					/* Find a resource in the parent where we can allocate */			for (i = 0 ; i < 4; i++) {				struct resource *r = bus->resource[i];				if (!r)					continue;				if ((r->flags & IORESOURCE_IO) == 0)					continue;				DBG("Trying to allocate from %08lx, size %08lx from parent"				    " res %d: %08lx -> %08lx\n",					res->start, res->end, i, r->start, r->end);							if (allocate_resource(r, res, res->end + 1, res->start, max,				    res->end + 1, NULL, NULL) < 0) {					DBG("Failed !\n");					continue;				}				do_update_p2p_io_resource(b, found_vga);				break;			}		}		do_fixup_p2p_level(b);	}}static voidpcibios_fixup_p2p_bridges(void){	struct list_head *ln;	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {		struct pci_bus *b = pci_bus_b(ln);		do_fixup_p2p_level(b);	}}#endif /* CONFIG_PPC_PMAC */static int __initpcibios_init(void){	struct pci_controller *hose;	struct pci_bus *bus;	int next_busno;	printk(KERN_INFO "PCI: Probing PCI hardware\n");	/* Scan all of the recorded PCI controllers.  */	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {		if (pci_assign_all_busses)			hose->first_busno = next_busno;		hose->last_busno = 0xff;		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);		hose->last_busno = bus->subordinate;		if (pci_assign_all_busses || next_busno <= hose->last_busno)			next_busno = hose->last_busno+1;	}	pci_bus_count = next_busno;	/* OpenFirmware based machines need a map of OF bus	 * numbers vs. kernel bus numbers since we may have to	 * remap them.	 */	if (pci_assign_all_busses && have_of)		pcibios_make_OF_bus_map();	/* Do machine dependent PCI interrupt routing */	if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)		pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);	/* Call machine dependent fixup */	if (ppc_md.pcibios_fixup)		ppc_md.pcibios_fixup();	/* Allocate and assign resources */	pcibios_allocate_bus_resources(&pci_root_buses);	pcibios_allocate_resources(0);	pcibios_allocate_resources(1);#ifdef CONFIG_PPC_PMAC	pcibios_fixup_p2p_bridges();#endif /* CONFIG_PPC_PMAC */	pcibios_assign_resources();	/* Call machine dependent post-init code */	if (ppc_md.pcibios_after_init)		ppc_md.pcibios_after_init();	return 0;}subsys_initcall(pcibios_init);unsigned char __initcommon_swizzle(struct pci_dev *dev, unsigned char *pinp){	struct pci_controller *hose = dev->sysdata;	if (dev->bus->number != hose->first_busno) {		u8 pin = *pinp;		do {			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));			/* Move up the chain of bridges. */			dev = dev->bus->self;		} while (dev->bus->self);		*pinp = pin;		/* The slot is the idsel of the last bridge. */	}	return PCI_SLOT(dev->devfn);}unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,			     unsigned long start, unsigned long size){	return start;}void __init pcibios_fixup_bus(struct pci_bus *bus)

⌨️ 快捷键说明

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