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

📄 pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct pci_dev *dev = bus->self;	struct pci_controller *hose = dev->sysdata;	if (!hose) {		printk("update_bridge_base: no hose?\n");		return;	}	pci_read_config_word(dev, PCI_COMMAND, &cmd);	pci_write_config_word(dev, PCI_COMMAND,			      cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));	if (res->flags & IORESOURCE_IO) {		off = (unsigned long) hose->io_base_virt - isa_io_base;		start = res->start - off;		end = res->end - off;		io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;		io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;		if (end > 0xffff) {			pci_write_config_word(dev, PCI_IO_BASE_UPPER16,					      start >> 16);			pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,					      end >> 16);			io_base_lo |= PCI_IO_RANGE_TYPE_32;		} else			io_base_lo |= PCI_IO_RANGE_TYPE_16;		pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);		pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);	} else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))		   == IORESOURCE_MEM) {		off = hose->pci_mem_offset;		mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;		mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;		pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);		pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);	} else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))		   == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {		off = hose->pci_mem_offset;		mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;		mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;		pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);		pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);	} else {		DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",		    pci_name(dev), i, res->flags);	}	pci_write_config_word(dev, PCI_COMMAND, cmd);}static inline void alloc_resource(struct pci_dev *dev, int idx){	struct resource *pr, *r = &dev->resource[idx];	DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",	    pci_name(dev), idx, r->start, r->end, r->flags);	pr = pci_find_parent_resource(dev, r);	if (!pr || request_resource(pr, r) < 0) {		printk(KERN_ERR "PCI: Cannot allocate resource region %d"		       " of device %s\n", idx, pci_name(dev));		if (pr)			DBG("PCI:  parent is %p: %08lx-%08lx (f=%lx)\n",			    pr, pr->start, pr->end, pr->flags);		/* We'll assign a new address later */		r->flags |= IORESOURCE_UNSET;		r->end -= r->start;		r->start = 0;	}}static void __initpcibios_allocate_resources(int pass){	struct pci_dev *dev = NULL;	int idx, disabled;	u16 command;	struct resource *r;	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {		pci_read_config_word(dev, PCI_COMMAND, &command);		for (idx = 0; idx < 6; idx++) {			r = &dev->resource[idx];			if (r->parent)		/* Already allocated */				continue;			if (!r->flags || (r->flags & IORESOURCE_UNSET))				continue;	/* Not assigned at all */			if (r->flags & IORESOURCE_IO)				disabled = !(command & PCI_COMMAND_IO);			else				disabled = !(command & PCI_COMMAND_MEMORY);			if (pass == disabled)				alloc_resource(dev, idx);		}		if (pass)			continue;		r = &dev->resource[PCI_ROM_RESOURCE];		if (r->flags & PCI_ROM_ADDRESS_ENABLE) {			/* Turn the ROM off, leave the resource region, but keep it unregistered. */			u32 reg;			DBG("PCI: Switching off ROM of %s\n", pci_name(dev));			r->flags &= ~PCI_ROM_ADDRESS_ENABLE;			pci_read_config_dword(dev, dev->rom_base_reg, &reg);			pci_write_config_dword(dev, dev->rom_base_reg,					       reg & ~PCI_ROM_ADDRESS_ENABLE);		}	}}static void __initpcibios_assign_resources(void){	struct pci_dev *dev = NULL;	int idx;	struct resource *r;	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {		int class = dev->class >> 8;		/* Don't touch classless devices and host bridges */		if (!class || class == PCI_CLASS_BRIDGE_HOST)			continue;		for (idx = 0; idx < 6; idx++) {			r = &dev->resource[idx];			/*			 * We shall assign a new address to this resource,			 * either because the BIOS (sic) forgot to do so			 * or because we have decided the old address was			 * unusable for some reason.			 */			if ((r->flags & IORESOURCE_UNSET) && r->end &&			    (!ppc_md.pcibios_enable_device_hook ||			     !ppc_md.pcibios_enable_device_hook(dev, 1))) {				r->flags &= ~IORESOURCE_UNSET;				pci_assign_resource(dev, idx);			}		}#if 0 /* don't assign ROMs */		r = &dev->resource[PCI_ROM_RESOURCE];		r->end -= r->start;		r->start = 0;		if (r->end)			pci_assign_resource(dev, PCI_ROM_RESOURCE);#endif	}}intpcibios_enable_resources(struct pci_dev *dev, int mask){	u16 cmd, old_cmd;	int idx;	struct resource *r;	pci_read_config_word(dev, PCI_COMMAND, &cmd);	old_cmd = cmd;	for (idx=0; idx<6; idx++) {		/* Only set up the requested stuff */		if (!(mask & (1<<idx)))			continue;			r = &dev->resource[idx];		if (r->flags & IORESOURCE_UNSET) {			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));			return -EINVAL;		}		if (r->flags & IORESOURCE_IO)			cmd |= PCI_COMMAND_IO;		if (r->flags & IORESOURCE_MEM)			cmd |= PCI_COMMAND_MEMORY;	}	if (dev->resource[PCI_ROM_RESOURCE].start)		cmd |= PCI_COMMAND_MEMORY;	if (cmd != old_cmd) {		printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);		pci_write_config_word(dev, PCI_COMMAND, cmd);	}	return 0;}static int next_controller_index;struct pci_controller * __initpcibios_alloc_controller(void){	struct pci_controller *hose;	hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));	memset(hose, 0, sizeof(struct pci_controller));	*hose_tail = hose;	hose_tail = &hose->next;	hose->index = next_controller_index++;	return hose;}#ifdef CONFIG_PPC_OF/* * Functions below are used on OpenFirmware machines. */static void __openfirmwaremake_one_node_map(struct device_node* node, u8 pci_bus){	int *bus_range;	int len;	if (pci_bus >= pci_bus_count)		return;	bus_range = (int *) get_property(node, "bus-range", &len);	if (bus_range == NULL || len < 2 * sizeof(int)) {		printk(KERN_WARNING "Can't get bus-range for %s, "		       "assuming it starts at 0\n", node->full_name);		pci_to_OF_bus_map[pci_bus] = 0;	} else		pci_to_OF_bus_map[pci_bus] = bus_range[0];	for (node=node->child; node != 0;node = node->sibling) {		struct pci_dev* dev;		unsigned int *class_code, *reg;			class_code = (unsigned int *) get_property(node, "class-code", NULL);		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))			continue;		reg = (unsigned int *)get_property(node, "reg", NULL);		if (!reg)			continue;		dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));		if (!dev || !dev->subordinate)			continue;		make_one_node_map(node, dev->subordinate->number);	}}	void __openfirmwarepcibios_make_OF_bus_map(void){	int i;	struct pci_controller* hose;	u8* of_prop_map;	pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);	if (!pci_to_OF_bus_map) {		printk(KERN_ERR "Can't allocate OF bus map !\n");		return;	}	/* We fill the bus map with invalid values, that helps	 * debugging.	 */	for (i=0; i<pci_bus_count; i++)		pci_to_OF_bus_map[i] = 0xff;	/* For each hose, we begin searching bridges */	for(hose=hose_head; hose; hose=hose->next) {		struct device_node* node;			node = (struct device_node *)hose->arch_data;		if (!node)			continue;		make_one_node_map(node, hose->first_busno);	}	of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);	if (of_prop_map)		memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);#ifdef DEBUG	printk("PCI->OF bus map:\n");	for (i=0; i<pci_bus_count; i++) {		if (pci_to_OF_bus_map[i] == 0xff)			continue;		printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);	}#endif}typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);static struct device_node* __openfirmwarescan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data){	struct device_node* sub_node;	for (; node != 0;node = node->sibling) {		unsigned int *class_code;			if (filter(node, data))			return node;		/* For PCI<->PCI bridges or CardBus bridges, we go down		 * Note: some OFs create a parent node "multifunc-device" as		 * a fake root for all functions of a multi-function device,		 * we go down them as well.		 */		class_code = (unsigned int *) get_property(node, "class-code", NULL);		if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&			strcmp(node->name, "multifunc-device"))			continue;		sub_node = scan_OF_pci_childs(node->child, filter, data);		if (sub_node)			return sub_node;	}	return NULL;}static intscan_OF_pci_childs_iterator(struct device_node* node, void* data){	unsigned int *reg;	u8* fdata = (u8*)data;		reg = (unsigned int *) get_property(node, "reg", NULL);	if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]		&& ((reg[0] >> 16) & 0xff) == fdata[0])		return 1;	return 0;}static struct device_node* __openfirmwarescan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn){	u8 filter_data[2] = {bus, dev_fn};	return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);}/* * Scans the OF tree for a device node matching a PCI device */struct device_node *pci_busdev_to_OF_node(struct pci_bus *bus, int devfn){	struct pci_controller *hose;	struct device_node *node;	int busnr;	if (!have_of)		return NULL;		/* Lookup the hose */	busnr = bus->number;	hose = pci_bus_to_hose(busnr);	if (!hose)		return NULL;	/* Check it has an OF node associated */	node = (struct device_node *) hose->arch_data;	if (!node)		return NULL;	/* Fixup bus number according to what OF think it is. */#ifdef CONFIG_PPC_PMAC	/* The G5 need a special case here. Basically, we don't remap all	 * busses on it so we don't create the pci-OF-map. However, we do	 * remap the AGP bus and so have to deal with it. A future better	 * fix has to be done by making the remapping per-host and always	 * filling the pci_to_OF map. --BenH	 */	if (_machine == _MACH_Pmac && busnr >= 0xf0)		busnr -= 0xf0;	else#endif	if (pci_to_OF_bus_map)		busnr = pci_to_OF_bus_map[busnr];	if (busnr == 0xff)		return NULL;		/* Now, lookup childs of the hose */	return scan_OF_childs_for_device(node->child, busnr, devfn);}struct device_node*pci_device_to_OF_node(struct pci_dev *dev){	return pci_busdev_to_OF_node(dev->bus, dev->devfn);}/* This routine is meant to be used early during boot, when the * PCI bus numbers have not yet been assigned, and you need to * issue PCI config cycles to an OF device. * It could also be used to "fix" RTAS config cycles if you want * to set pci_assign_all_busses to 1 and still use RTAS for PCI * config cycles. */struct pci_controller*pci_find_hose_for_OF_device(struct device_node* node){	if (!have_of)		return NULL;	while(node) {		struct pci_controller* hose;		for (hose=hose_head;hose;hose=hose->next)			if (hose->arch_data == node)				return hose;		node=node->parent;	}	return NULL;}static int __openfirmwarefind_OF_pci_device_filter(struct device_node* node, void* data){	return ((void *)node == data);}/* * Returns the PCI device matching a given OF node */intpci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn){	unsigned int *reg;	struct pci_controller* hose;	struct pci_dev* dev = NULL;		if (!have_of)		return -ENODEV;	/* Make sure it's really a PCI device */	hose = pci_find_hose_for_OF_device(node);	if (!hose || !hose->arch_data)		return -ENODEV;	if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,			find_OF_pci_device_filter, (void *)node))		return -ENODEV;	reg = (unsigned int *) get_property(node, "reg", NULL);	if (!reg)		return -ENODEV;	*bus = (reg[0] >> 16) & 0xff;	*devfn = ((reg[0] >> 8) & 0xff);	/* Ok, here we need some tweak. If we have already renumbered	 * all busses, we can't rely on the OF bus number any more.	 * the pci_to_OF_bus_map is not enough as several PCI busses	 * may match the same OF bus number.	 */	if (!pci_to_OF_bus_map)		return 0;	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {		if (pci_to_OF_bus_map[dev->bus->number] != *bus)			continue;		if (dev->devfn != *devfn)			continue;		*bus = dev->bus->number;		return 0;

⌨️ 快捷键说明

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