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