123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/module.h>
- #include "pci.h"
- int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
- {
- struct pci_dev *pdev;
- char *scratch;
- int i = 0;
- int length = 0;
- if (!dev)
- return -ENODEV;
- pdev = to_pci_dev(dev);
- if (!pdev)
- return -ENODEV;
- scratch = buffer;
- /* stuff we want to pass to /sbin/hotplug */
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
- pdev->class);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
- pdev->vendor, pdev->device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length,
- "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device);
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
- ++length;
- scratch += length;
- envp[i++] = scratch;
- length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
- pci_name(pdev));
- if ((buffer_size - length <= 0) || (i >= num_envp))
- return -ENOMEM;
- envp[i] = NULL;
- return 0;
- }
- static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
- {
- struct list_head *ln;
- struct pci_dev *dev;
- struct pci_dev_wrapped wrapped_dev;
- int result = 0;
- pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(wrapped_bus->bus),
- wrapped_bus->bus->number);
- if (fn->pre_visit_pci_bus) {
- result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
- if (result)
- return result;
- }
- ln = wrapped_bus->bus->devices.next;
- while (ln != &wrapped_bus->bus->devices) {
- dev = pci_dev_b(ln);
- ln = ln->next;
- memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
- wrapped_dev.dev = dev;
- result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
- if (result)
- return result;
- }
- if (fn->post_visit_pci_bus)
- result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
- return result;
- }
- static int pci_visit_bridge (struct pci_visit * fn,
- struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
- {
- struct pci_bus *bus;
- struct pci_bus_wrapped wrapped_bus;
- int result = 0;
- pr_debug("PCI: Scanning bridge %s\n", pci_name(wrapped_dev->dev));
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
- bus = wrapped_dev->dev->subordinate;
- if (bus) {
- memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
- wrapped_bus.bus = bus;
- result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
- }
- return result;
- }
- /**
- * pci_visit_dev - scans the pci buses.
- * @fn: callback functions that are called while visiting
- * @wrapped_dev: the device to scan
- * @wrapped_parent: the bus where @wrapped_dev is connected to
- *
- * Every bus and every function is presented to a custom
- * function that can act upon it.
- */
- int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
- {
- struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
- int result = 0;
- if (!dev)
- return 0;
- if (fn->pre_visit_pci_dev) {
- result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
- switch (dev->class >> 8) {
- case PCI_CLASS_BRIDGE_PCI:
- result = pci_visit_bridge(fn, wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- break;
- default:
- pr_debug("PCI: Scanning device %s\n", pci_name(dev));
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev (wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- }
- }
- if (fn->post_visit_pci_dev)
- result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
- return result;
- }
- EXPORT_SYMBOL(pci_visit_dev);
|