1/* 2 * ISA bus. 3 */ 4 5#include <linux/device.h> 6#include <linux/kernel.h> 7#include <linux/slab.h> 8#include <linux/module.h> 9#include <linux/init.h> 10#include <linux/isa.h> 11 12static struct device isa_bus = { 13 .bus_id = "isa" 14}; 15 16struct isa_dev { 17 struct device dev; 18 struct device *next; 19 unsigned int id; 20}; 21 22#define to_isa_dev(x) container_of((x), struct isa_dev, dev) 23 24static int isa_bus_match(struct device *dev, struct device_driver *driver) 25{ 26 struct isa_driver *isa_driver = to_isa_driver(driver); 27 28 if (dev->platform_data == isa_driver) { 29 if (!isa_driver->match || 30 isa_driver->match(dev, to_isa_dev(dev)->id)) 31 return 1; 32 dev->platform_data = NULL; 33 } 34 return 0; 35} 36 37static int isa_bus_probe(struct device *dev) 38{ 39 struct isa_driver *isa_driver = dev->platform_data; 40 41 if (isa_driver->probe) 42 return isa_driver->probe(dev, to_isa_dev(dev)->id); 43 44 return 0; 45} 46 47static int isa_bus_remove(struct device *dev) 48{ 49 struct isa_driver *isa_driver = dev->platform_data; 50 51 if (isa_driver->remove) 52 return isa_driver->remove(dev, to_isa_dev(dev)->id); 53 54 return 0; 55} 56 57static void isa_bus_shutdown(struct device *dev) 58{ 59 struct isa_driver *isa_driver = dev->platform_data; 60 61 if (isa_driver->shutdown) 62 isa_driver->shutdown(dev, to_isa_dev(dev)->id); 63} 64 65static int isa_bus_suspend(struct device *dev, pm_message_t state) 66{ 67 struct isa_driver *isa_driver = dev->platform_data; 68 69 if (isa_driver->suspend) 70 return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); 71 72 return 0; 73} 74 75static int isa_bus_resume(struct device *dev) 76{ 77 struct isa_driver *isa_driver = dev->platform_data; 78 79 if (isa_driver->resume) 80 return isa_driver->resume(dev, to_isa_dev(dev)->id); 81 82 return 0; 83} 84 85static struct bus_type isa_bus_type = { 86 .name = "isa", 87 .match = isa_bus_match, 88 .probe = isa_bus_probe, 89 .remove = isa_bus_remove, 90 .shutdown = isa_bus_shutdown, 91 .suspend = isa_bus_suspend, 92 .resume = isa_bus_resume 93}; 94 95static void isa_dev_release(struct device *dev) 96{ 97 kfree(to_isa_dev(dev)); 98} 99 100void isa_unregister_driver(struct isa_driver *isa_driver) 101{ 102 struct device *dev = isa_driver->devices; 103 104 while (dev) { 105 struct device *tmp = to_isa_dev(dev)->next; 106 device_unregister(dev); 107 dev = tmp; 108 } 109 driver_unregister(&isa_driver->driver); 110} 111EXPORT_SYMBOL_GPL(isa_unregister_driver); 112 113int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) 114{ 115 int error; 116 unsigned int id; 117 118 isa_driver->driver.bus = &isa_bus_type; 119 isa_driver->devices = NULL; 120 121 error = driver_register(&isa_driver->driver); 122 if (error) 123 return error; 124 125 for (id = 0; id < ndev; id++) { 126 struct isa_dev *isa_dev; 127 128 isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); 129 if (!isa_dev) { 130 error = -ENOMEM; 131 break; 132 } 133 134 isa_dev->dev.parent = &isa_bus; 135 isa_dev->dev.bus = &isa_bus_type; 136 137 snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u", 138 isa_driver->driver.name, id); 139 140 isa_dev->dev.platform_data = isa_driver; 141 isa_dev->dev.release = isa_dev_release; 142 isa_dev->id = id; 143 144 error = device_register(&isa_dev->dev); 145 if (error) { 146 put_device(&isa_dev->dev); 147 break; 148 } 149 150 if (isa_dev->dev.platform_data) { 151 isa_dev->next = isa_driver->devices; 152 isa_driver->devices = &isa_dev->dev; 153 } else 154 device_unregister(&isa_dev->dev); 155 } 156 157 if (!error && !isa_driver->devices) 158 error = -ENODEV; 159 160 if (error) 161 isa_unregister_driver(isa_driver); 162 163 return error; 164} 165EXPORT_SYMBOL_GPL(isa_register_driver); 166 167static int __init isa_bus_init(void) 168{ 169 int error; 170 171 error = bus_register(&isa_bus_type); 172 if (!error) { 173 error = device_register(&isa_bus); 174 if (error) 175 bus_unregister(&isa_bus_type); 176 } 177 return error; 178} 179 180device_initcall(isa_bus_init); 181