Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / drivers / dio / dio-driver.c
1 /*
2  *  DIO Driver Services
3  *
4  *  Copyright (C) 2004 Jochen Friedrich
5  *
6  *  Loosely based on drivers/pci/pci-driver.c and drivers/zorro/zorro-driver.c
7  *
8  *  This file is subject to the terms and conditions of the GNU General Public
9  *  License.  See the file COPYING in the main directory of this archive
10  *  for more details.
11  */
12
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/dio.h>
16
17
18 /**
19  *  dio_match_device - Tell if a DIO device structure has a matching DIO device id structure
20  *  @ids: array of DIO device id structures to search in
21  *  @d: the DIO device structure to match against
22  *
23  *  Used by a driver to check whether a DIO device present in the
24  *  system is in its list of supported devices. Returns the matching
25  *  dio_device_id structure or %NULL if there is no match.
26  */
27
28 const struct dio_device_id *
29 dio_match_device(const struct dio_device_id *ids,
30                    const struct dio_dev *d)
31 {
32         while (ids->id) {
33                 if (ids->id == DIO_WILDCARD)
34                         return ids;
35                 if (DIO_NEEDSSECID(ids->id & 0xff)) {
36                         if (ids->id == d->id)
37                                 return ids;
38                 } else {
39                         if ((ids->id & 0xff) == (d->id & 0xff))
40                                 return ids;
41                 }
42                 ids++;
43         }
44         return NULL;
45 }
46
47 static int dio_device_probe(struct device *dev)
48 {
49         int error = 0;
50         struct dio_driver *drv = to_dio_driver(dev->driver);
51         struct dio_dev *d = to_dio_dev(dev);
52
53         if (!d->driver && drv->probe) {
54                 const struct dio_device_id *id;
55
56                 id = dio_match_device(drv->id_table, d);
57                 if (id)
58                         error = drv->probe(d, id);
59                 if (error >= 0) {
60                         d->driver = drv;
61                         error = 0;
62                 }
63         }
64         return error;
65 }
66
67
68 /**
69  *  dio_register_driver - register a new DIO driver
70  *  @drv: the driver structure to register
71  *
72  *  Adds the driver structure to the list of registered drivers
73  *  Returns zero or a negative error value.
74  */
75
76 int dio_register_driver(struct dio_driver *drv)
77 {
78         /* initialize common driver fields */
79         drv->driver.name = drv->name;
80         drv->driver.bus = &dio_bus_type;
81
82         /* register with core */
83         return driver_register(&drv->driver);
84 }
85
86
87 /**
88  *  dio_unregister_driver - unregister a DIO driver
89  *  @drv: the driver structure to unregister
90  *
91  *  Deletes the driver structure from the list of registered DIO drivers,
92  *  gives it a chance to clean up by calling its remove() function for
93  *  each device it was responsible for, and marks those devices as
94  *  driverless.
95  */
96
97 void dio_unregister_driver(struct dio_driver *drv)
98 {
99         driver_unregister(&drv->driver);
100 }
101
102
103 /**
104  *  dio_bus_match - Tell if a DIO device structure has a matching DIO device id structure
105  *  @dev: the DIO device structure to match against
106  *  @drv: the &device_driver that points to the array of DIO device id structures to search
107  *
108  *  Used by a driver to check whether a DIO device present in the
109  *  system is in its list of supported devices. Returns the matching
110  *  dio_device_id structure or %NULL if there is no match.
111  */
112
113 static int dio_bus_match(struct device *dev, struct device_driver *drv)
114 {
115         struct dio_dev *d = to_dio_dev(dev);
116         struct dio_driver *dio_drv = to_dio_driver(drv);
117         const struct dio_device_id *ids = dio_drv->id_table;
118
119         if (!ids)
120                 return 0;
121
122         while (ids->id) {
123                 if (ids->id == DIO_WILDCARD)
124                         return 1;
125                 if (DIO_NEEDSSECID(ids->id & 0xff)) {
126                         if (ids->id == d->id)
127                                 return 1;
128                 } else {
129                         if ((ids->id & 0xff) == (d->id & 0xff))
130                                 return 1;
131                 }
132                 ids++;
133         }
134         return 0;
135 }
136
137
138 struct bus_type dio_bus_type = {
139         .name   = "dio",
140         .match  = dio_bus_match,
141         .probe  = dio_device_probe,
142 };
143
144
145 static int __init dio_driver_init(void)
146 {
147         return bus_register(&dio_bus_type);
148 }
149
150 postcore_initcall(dio_driver_init);
151
152 EXPORT_SYMBOL(dio_match_device);
153 EXPORT_SYMBOL(dio_register_driver);
154 EXPORT_SYMBOL(dio_unregister_driver);
155 EXPORT_SYMBOL(dio_dev_driver);
156 EXPORT_SYMBOL(dio_bus_type);