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