Messages in this thread Patch in this message | | | Subject | [PATCH] pci bridge class code | From | Mark Haverkamp <> | Date | 29 May 2003 13:17:42 -0700 |
| |
This adds pci-pci bridge driver model class code. Entries appear in /sys/class/pci_bridge.
Makefile | 2 pci-bridge.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 1 deletion(-)
===== drivers/pci/Makefile 1.28 vs edited ===== --- 1.28/drivers/pci/Makefile Mon May 5 10:58:50 2003 +++ edited/drivers/pci/Makefile Thu May 29 10:32:28 2003 @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o hotplug.o \ - pci-sysfs.o + pci-sysfs.o pci-bridge.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o ===== drivers/pci/pci-bridge.c 1.1 vs edited ===== --- 1.1/drivers/pci/pci-bridge.c Thu May 29 11:00:38 2003 +++ edited/drivers/pci/pci-bridge.c Thu May 29 12:57:13 2003 @@ -0,0 +1,205 @@ +/* + * drivers/pci/pci-bridge.c + * + * Copyright (c) 2003 Mark Haverkamp <markh@osdl.org> + * + * pci bridge driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/pci.h> + +static int __devinit pci_bridge_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id); +static void __devexit pci_bridge_remove(struct pci_dev *pci); + +static void pci_bridge_create_sysfs_files(struct device *device); + +static struct class pci_bridge_class = { + .name = "pci_bridge", +}; + +static struct class_device class_dev_data; + + +static struct pci_device_id pci_bridge_id[] __devinitdata = { + { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = PCI_CLASS_BRIDGE_PCI << 8, + .class_mask = 0xffff00, + .driver_data = 0, + }, + {0}, +}; + +static struct pci_driver driver = { + .name = "pci_bridge", + .id_table = pci_bridge_id, + .probe = pci_bridge_probe, + .remove = __devexit_p(pci_bridge_remove), +}; + +struct pci_bridge_dev_data { + u32 br_num; + u8 primary_bus; + u8 secondary_bus; + u8 subordinate_bus; +}; + +static u32 pci_bridge_num = 0; +static spinlock_t br_config_lock = SPIN_LOCK_UNLOCKED; + +/* + * pci_bridge_probe - Initialze driver for pci-pci bridge. + * + * @pci: Pointer to pci bridge device data. + * @pci_id: Pointer to pci_bridge_id data. + */ +static int __devinit pci_bridge_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + int err = 0; + u32 buses; + struct pci_bridge_dev_data *dev; + + + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (dev == NULL) { + err = -ENOMEM; + goto out; + } + + spin_lock(&br_config_lock); + dev->br_num = pci_bridge_num++; + spin_unlock(&br_config_lock); + + pci_read_config_dword(pci, PCI_PRIMARY_BUS, &buses); + dev->primary_bus = buses & 0xff; + dev->secondary_bus = (buses >> 8) & 0xff; + dev->subordinate_bus = (buses >> 16) & 0xff; + + pci_set_drvdata(pci, dev); + + memset(&class_dev_data, 0, sizeof(class_dev_data)); + class_dev_data.dev = &pci->dev; + class_dev_data.class = &pci_bridge_class; + sprintf(class_dev_data.class_id, "pci_bridge%d", dev->br_num); + + pci_bridge_create_sysfs_files(&pci->dev); + + err = class_device_register(&class_dev_data); + +out: + return err; + +} + +/* + * pci_bridge_remove - Clean up on device removal + * + * @pci: Pointer to pci bridge device data. + */ +static void __devexit pci_bridge_remove(struct pci_dev *pci) +{ + class_device_unregister(&class_dev_data); +} + +/* + * pci_bridge_init - initialize module. + */ +static int __init pci_bridge_init(void) +{ + + int err; + + err = class_register(&pci_bridge_class); + if (err < 0 ) { + return err; + } + + err = pci_module_init(&driver); + if (err < 0) { + class_unregister(&pci_bridge_class); + } + + return err; + +} + +/* + * pci_bridge_exit - Cleanup on module removal + */ +static void __exit pci_bridge_exit(void) +{ + pci_unregister_driver(&driver); + class_unregister(&pci_bridge_class); +} + +/* + * Display pci-pci bridge attributes. + */ + +static ssize_t pci_bridge_show_primary(struct device *device, char *buf) +{ + struct pci_bridge_dev_data *dev = dev_get_drvdata(device); + + if (dev == NULL) { + return 0; + } + + return sprintf(buf, "%u\n", dev->primary_bus); +} +static DEVICE_ATTR(primary_bus, S_IRUGO, pci_bridge_show_primary, NULL); + +static ssize_t pci_bridge_show_secondary(struct device *device, char *buf) +{ + struct pci_bridge_dev_data *dev = dev_get_drvdata(device); + + if (dev == NULL) { + return 0; + } + + return sprintf(buf, "%u\n", dev->secondary_bus); +} +static DEVICE_ATTR(secondary_bus, S_IRUGO, pci_bridge_show_secondary, NULL); + +static ssize_t pci_bridge_show_subordinate(struct device *device, char *buf) +{ + struct pci_bridge_dev_data *dev = dev_get_drvdata(device); + + if (dev == NULL) { + return 0; + } + + return sprintf(buf, "%u\n", dev->subordinate_bus); +} +static DEVICE_ATTR(subordinate_bus, S_IRUGO, pci_bridge_show_subordinate, NULL); + + +/* + * pci_bridge_create_sysfs_files - create sysfs files for pci-pci bridge. + * + * @device: Pointer to device data for the pci-pci bridge. + */ +static void pci_bridge_create_sysfs_files(struct device *device) +{ + device_create_file(device, &dev_attr_primary_bus); + device_create_file(device, &dev_attr_secondary_bus); + device_create_file(device, &dev_attr_subordinate_bus); +} + +MODULE_DEVICE_TABLE(pci, pci_bridge_id); +module_init(pci_bridge_init); +module_exit(pci_bridge_exit); +MODULE_AUTHOR("Mark Haverkamp"); +MODULE_DESCRIPTION("PCI bridge driver"); +MODULE_LICENSE("GPL");
-- Mark Haverkamp <markh@osdl.org>
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |