linux/drivers/pci/pci-stub.c
<<
>>
Prefs
   1/* pci-stub - simple stub driver to reserve a pci device
   2 *
   3 * Copyright (C) 2008 Red Hat, Inc.
   4 * Author:
   5 *      Chris Wright
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2.
   8 *
   9 * Usage is simple, allocate a new id to the stub driver and bind the
  10 * device to it.  For example:
  11 *
  12 * # echo "8086 10f5" > /sys/bus/pci/drivers/pci-stub/new_id
  13 * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind
  14 * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/pci-stub/bind
  15 * # ls -l /sys/bus/pci/devices/0000:00:19.0/driver
  16 * .../0000:00:19.0/driver -> ../../../bus/pci/drivers/pci-stub
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/pci.h>
  21
  22static char ids[1024] __initdata;
  23
  24module_param_string(ids, ids, sizeof(ids), 0);
  25MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
  26                 "\"vendor:device[:subvendor[:subdevice[:class[:class_mask]]]]\""
  27                 " and multiple comma separated entries can be specified");
  28
  29static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
  30{
  31        dev_info(&dev->dev, "claimed by stub\n");
  32        return 0;
  33}
  34
  35static struct pci_driver stub_driver = {
  36        .name           = "pci-stub",
  37        .id_table       = NULL, /* only dynamic id's */
  38        .probe          = pci_stub_probe,
  39};
  40
  41static int __init pci_stub_init(void)
  42{
  43        char *p, *id;
  44        int rc;
  45
  46        rc = pci_register_driver(&stub_driver);
  47        if (rc)
  48                return rc;
  49
  50        /* no ids passed actually */
  51        if (ids[0] == '\0')
  52                return 0;
  53
  54        /* add ids specified in the module parameter */
  55        p = ids;
  56        while ((id = strsep(&p, ","))) {
  57                unsigned int vendor, device, subvendor = PCI_ANY_ID,
  58                        subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
  59                int fields;
  60
  61                if (!strlen(id))
  62                        continue;
  63
  64                fields = sscanf(id, "%x:%x:%x:%x:%x:%x",
  65                                &vendor, &device, &subvendor, &subdevice,
  66                                &class, &class_mask);
  67
  68                if (fields < 2) {
  69                        printk(KERN_WARNING
  70                               "pci-stub: invalid id string \"%s\"\n", id);
  71                        continue;
  72                }
  73
  74                printk(KERN_INFO
  75                       "pci-stub: add %04X:%04X sub=%04X:%04X cls=%08X/%08X\n",
  76                       vendor, device, subvendor, subdevice, class, class_mask);
  77
  78                rc = pci_add_dynid(&stub_driver, vendor, device,
  79                                   subvendor, subdevice, class, class_mask, 0);
  80                if (rc)
  81                        printk(KERN_WARNING
  82                               "pci-stub: failed to add dynamic id (%d)\n", rc);
  83        }
  84
  85        return 0;
  86}
  87
  88static void __exit pci_stub_exit(void)
  89{
  90        pci_unregister_driver(&stub_driver);
  91}
  92
  93module_init(pci_stub_init);
  94module_exit(pci_stub_exit);
  95
  96MODULE_LICENSE("GPL");
  97MODULE_AUTHOR("Chris Wright <chrisw@sous-sol.org>");
  98