probe.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 815 行 · 第 1/2 页

C
815
字号
		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);		if (!is_cardbus) {			child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;			/* Now we can scan all subordinate buses... */			max = pci_scan_child_bus(child);		} else {			/*			 * For CardBus bridges, we leave 4 bus numbers			 * as cards with a PCI-to-PCI bridge can be			 * inserted later.			 */			max += CARDBUS_RESERVE_BUSNR;		}		/*		 * Set the subordinate bus number to its real value.		 */		child->subordinate = max;		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);	}	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);	sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);	return max;}/* * Read interrupt line and base address registers. * The architecture-dependent code can tweak these, of course. */static void pci_read_irq(struct pci_dev *dev){	unsigned char irq;	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);	if (irq)		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);	dev->irq = irq;}/** * pci_setup_device - fill in class and map information of a device * @dev: the device structure to fill * * Initialize the device structure with information about the device's  * vendor,class,memory and IO-space addresses,IRQ lines etc. * Called at initialisation of the PCI subsystem and by CardBus services. * Returns 0 on success and -1 if unknown type of device (not normal, bridge * or CardBus). */static int pci_setup_device(struct pci_dev * dev){	u32 class;	dev->slot_name = dev->dev.bus_id;	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);	class >>= 8;				    /* upper 3 bytes */	dev->class = class;	class >>= 8;	DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number,	    dev->devfn, dev->vendor, dev->device, class, dev->hdr_type);	/* "Unknown power state" */	dev->current_state = 4;	switch (dev->hdr_type) {		    /* header type */	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */		if (class == PCI_CLASS_BRIDGE_PCI)			goto bad;		pci_read_irq(dev);		pci_read_bases(dev, 6, PCI_ROM_ADDRESS);		pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);		pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);		break;	case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */		if (class != PCI_CLASS_BRIDGE_PCI)			goto bad;		/* The PCI-to-PCI bridge spec requires that subtractive		   decoding (i.e. transparent) bridge must have programming		   interface code of 0x01. */ 		dev->transparent = ((dev->class & 0xff) == 1);		pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);		break;	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */		if (class != PCI_CLASS_BRIDGE_CARDBUS)			goto bad;		pci_read_irq(dev);		pci_read_bases(dev, 1, 0);		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);		break;	default:				    /* unknown header */		printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n",			pci_name(dev), dev->hdr_type);		return -1;	bad:		printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n",		       pci_name(dev), class, dev->hdr_type);		dev->class = PCI_CLASS_NOT_DEFINED;	}	/* We found a fine healthy device, go go go... */	return 0;}/** * pci_release_dev - free a pci device structure when all users of it are finished. * @dev: device that's been disconnected * * Will be called only by the device core when all users of this pci device are * done. */static void pci_release_dev(struct device *dev){	struct pci_dev *pci_dev;	pci_dev = to_pci_dev(dev);	kfree(pci_dev);}/** * pci_cfg_space_size - get the configuration space size of the PCI device. * * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices * have 4096 bytes.  Even if the device is capable, that doesn't mean we can * access it.  Maybe we don't have a way to generate extended config space * accesses, or the device is behind a reverse Express bridge.  So we try * reading the dword at 0x100 which must either be 0 or a valid extended * capability header. */static int pci_cfg_space_size(struct pci_dev *dev){	int pos;	u32 status;	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);	if (!pos) {		pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);		if (!pos)			goto fail;		pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);		if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))			goto fail;	}	if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)		goto fail;	if (status == 0xffffffff)		goto fail;	return PCI_CFG_SPACE_EXP_SIZE; fail:	return PCI_CFG_SPACE_SIZE;}static void pci_release_bus_bridge_dev(struct device *dev){	kfree(dev);}/* * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... */static struct pci_dev * __devinitpci_scan_device(struct pci_bus *bus, int devfn){	struct pci_dev *dev;	u32 l;	u8 hdr_type;	if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))		return NULL;	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))		return NULL;	/* some broken boards return 0 or ~0 if a slot is empty: */	if (l == 0xffffffff || l == 0x00000000 ||	    l == 0x0000ffff || l == 0xffff0000)		return NULL;	dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(struct pci_dev));	dev->bus = bus;	dev->sysdata = bus->sysdata;	dev->dev.parent = bus->bridge;	dev->dev.bus = &pci_bus_type;	dev->devfn = devfn;	dev->hdr_type = hdr_type & 0x7f;	dev->multifunction = !!(hdr_type & 0x80);	dev->vendor = l & 0xffff;	dev->device = (l >> 16) & 0xffff;	dev->cfg_size = pci_cfg_space_size(dev);	/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)	   set this higher, assuming the system even supports it.  */	dev->dma_mask = 0xffffffff;	if (pci_setup_device(dev) < 0) {		kfree(dev);		return NULL;	}	device_initialize(&dev->dev);	dev->dev.release = pci_release_dev;	pci_dev_get(dev);	pci_name_device(dev);	dev->dev.dma_mask = &dev->dma_mask;	dev->dev.coherent_dma_mask = 0xffffffffull;	return dev;}struct pci_dev * __devinitpci_scan_single_device(struct pci_bus *bus, int devfn){	struct pci_dev *dev;	dev = pci_scan_device(bus, devfn);	pci_scan_msi_device(dev);	if (!dev)		return NULL;		/* Fix up broken headers */	pci_fixup_device(pci_fixup_header, dev);	/*	 * Add the device to our list of discovered devices	 * and the bus list for fixup functions, etc.	 */	INIT_LIST_HEAD(&dev->global_list);	list_add_tail(&dev->bus_list, &bus->devices);	return dev;}/** * pci_scan_slot - scan a PCI slot on a bus for devices. * @bus: PCI bus to scan * @devfn: slot number to scan (must have zero function.) * * Scan a PCI slot on the specified PCI bus for devices, adding * discovered devices to the @bus->devices list.  New devices * will have an empty dev->global_list head. */int __devinit pci_scan_slot(struct pci_bus *bus, int devfn){	int func, nr = 0;	int scan_all_fns;	scan_all_fns = pcibios_scan_all_fns(bus, devfn);	for (func = 0; func < 8; func++, devfn++) {		struct pci_dev *dev;		dev = pci_scan_single_device(bus, devfn);		if (dev) {			nr++;			/*		 	 * If this is a single function device,		 	 * don't scan past the first function.		 	 */			if (!dev->multifunction) {				if (func > 0) {					dev->multifunction = 1;				} else { 					break;				}			}		} else {			if (func == 0 && !scan_all_fns)				break;		}	}	return nr;}unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus){	unsigned int devfn, pass, max = bus->secondary;	struct pci_dev *dev;	DBG("Scanning bus %02x\n", bus->number);	/* Go find them, Rover! */	for (devfn = 0; devfn < 0x100; devfn += 8)		pci_scan_slot(bus, devfn);	/*	 * After performing arch-dependent fixup of the bus, look behind	 * all PCI-to-PCI bridges on this bus.	 */	DBG("Fixups for bus %02x\n", bus->number);	pcibios_fixup_bus(bus);	for (pass=0; pass < 2; pass++)		list_for_each_entry(dev, &bus->devices, bus_list) {			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)				max = pci_scan_bridge(bus, dev, max, pass);		}	/*	 * We've scanned the bus and so we know all about what's on	 * the other side of any bridges that may be on this bus plus	 * any devices.	 *	 * Return how far we've got finding sub-buses.	 */	DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max);	return max;}unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus){	unsigned int max;	max = pci_scan_child_bus(bus);	/*	 * Make the discovered devices available.	 */	pci_bus_add_devices(bus);	return max;}struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata){	struct pci_bus *b;	struct device *dev;	b = pci_alloc_bus();	if (!b)		return NULL;	dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev){		kfree(b);		return NULL;	}	b->sysdata = sysdata;	b->ops = ops;	if (pci_find_bus(pci_domain_nr(b), bus)) {		/* If we already got to this bus through a different bridge, ignore it */		DBG("PCI: Bus %02x already known\n", bus);		kfree(dev);		kfree(b);		return NULL;	}	list_add_tail(&b->node, &pci_root_buses);	memset(dev, 0, sizeof(*dev));	dev->parent = parent;	dev->release = pci_release_bus_bridge_dev;	sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);	device_register(dev);	b->bridge = get_device(dev);	b->class_dev.class = &pcibus_class;	sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);	class_device_register(&b->class_dev);	class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);	sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");	b->number = b->secondary = bus;	b->resource[0] = &ioport_resource;	b->resource[1] = &iomem_resource;	b->subordinate = pci_scan_child_bus(b);	pci_bus_add_devices(b);	return b;}EXPORT_SYMBOL(pci_scan_bus_parented);#ifdef CONFIG_HOTPLUGEXPORT_SYMBOL(pci_add_new_bus);EXPORT_SYMBOL(pci_do_scan_bus);EXPORT_SYMBOL(pci_scan_slot);EXPORT_SYMBOL(pci_scan_bridge);EXPORT_SYMBOL(pci_scan_single_device);EXPORT_SYMBOL_GPL(pci_scan_child_bus);#endif

⌨️ 快捷键说明

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