xref: /linux/drivers/dio/dio-driver.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  DIO Driver Services
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 2004 Jochen Friedrich
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *  Loosely based on drivers/pci/pci-driver.c and drivers/zorro/zorro-driver.c
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  This file is subject to the terms and conditions of the GNU General Public
91da177e4SLinus Torvalds  *  License.  See the file COPYING in the main directory of this archive
101da177e4SLinus Torvalds  *  for more details.
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds #include <linux/init.h>
141da177e4SLinus Torvalds #include <linux/module.h>
151da177e4SLinus Torvalds #include <linux/dio.h>
161da177e4SLinus Torvalds 
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds /**
19771fcb58SRandy Dunlap  *  dio_match_device - Tell if a DIO device structure has a matching DIO device id structure
201da177e4SLinus Torvalds  *  @ids: array of DIO device id structures to search in
21771fcb58SRandy Dunlap  *  @d: the DIO device structure to match against
221da177e4SLinus Torvalds  *
231da177e4SLinus Torvalds  *  Used by a driver to check whether a DIO device present in the
241da177e4SLinus Torvalds  *  system is in its list of supported devices. Returns the matching
251da177e4SLinus Torvalds  *  dio_device_id structure or %NULL if there is no match.
261da177e4SLinus Torvalds  */
271da177e4SLinus Torvalds 
28b3875759SGeert Uytterhoeven static const struct dio_device_id *
dio_match_device(const struct dio_device_id * ids,const struct dio_dev * d)291da177e4SLinus Torvalds dio_match_device(const struct dio_device_id *ids,
301da177e4SLinus Torvalds 		   const struct dio_dev *d)
311da177e4SLinus Torvalds {
321da177e4SLinus Torvalds 	while (ids->id) {
331da177e4SLinus Torvalds 		if (ids->id == DIO_WILDCARD)
341da177e4SLinus Torvalds 			return ids;
351da177e4SLinus Torvalds 		if (DIO_NEEDSSECID(ids->id & 0xff)) {
361da177e4SLinus Torvalds 			if (ids->id == d->id)
371da177e4SLinus Torvalds 				return ids;
381da177e4SLinus Torvalds 		} else {
391da177e4SLinus Torvalds 			if ((ids->id & 0xff) == (d->id & 0xff))
401da177e4SLinus Torvalds 				return ids;
411da177e4SLinus Torvalds 		}
421da177e4SLinus Torvalds 		ids++;
431da177e4SLinus Torvalds 	}
441da177e4SLinus Torvalds 	return NULL;
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds 
dio_device_probe(struct device * dev)471da177e4SLinus Torvalds static int dio_device_probe(struct device *dev)
481da177e4SLinus Torvalds {
491da177e4SLinus Torvalds 	int error = 0;
501da177e4SLinus Torvalds 	struct dio_driver *drv = to_dio_driver(dev->driver);
511da177e4SLinus Torvalds 	struct dio_dev *d = to_dio_dev(dev);
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds 	if (!d->driver && drv->probe) {
541da177e4SLinus Torvalds 		const struct dio_device_id *id;
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds 		id = dio_match_device(drv->id_table, d);
571da177e4SLinus Torvalds 		if (id)
581da177e4SLinus Torvalds 			error = drv->probe(d, id);
591da177e4SLinus Torvalds 		if (error >= 0) {
601da177e4SLinus Torvalds 			d->driver = drv;
611da177e4SLinus Torvalds 			error = 0;
621da177e4SLinus Torvalds 		}
631da177e4SLinus Torvalds 	}
641da177e4SLinus Torvalds 	return error;
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds /**
691da177e4SLinus Torvalds  *  dio_register_driver - register a new DIO driver
701da177e4SLinus Torvalds  *  @drv: the driver structure to register
711da177e4SLinus Torvalds  *
721da177e4SLinus Torvalds  *  Adds the driver structure to the list of registered drivers
73e51c01b0SBjorn Helgaas  *  Returns zero or a negative error value.
741da177e4SLinus Torvalds  */
751da177e4SLinus Torvalds 
dio_register_driver(struct dio_driver * drv)761da177e4SLinus Torvalds int dio_register_driver(struct dio_driver *drv)
771da177e4SLinus Torvalds {
781da177e4SLinus Torvalds 	/* initialize common driver fields */
791da177e4SLinus Torvalds 	drv->driver.name = drv->name;
801da177e4SLinus Torvalds 	drv->driver.bus = &dio_bus_type;
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds 	/* register with core */
83e51c01b0SBjorn Helgaas 	return driver_register(&drv->driver);
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds /**
881da177e4SLinus Torvalds  *  dio_unregister_driver - unregister a DIO driver
891da177e4SLinus Torvalds  *  @drv: the driver structure to unregister
901da177e4SLinus Torvalds  *
911da177e4SLinus Torvalds  *  Deletes the driver structure from the list of registered DIO drivers,
921da177e4SLinus Torvalds  *  gives it a chance to clean up by calling its remove() function for
931da177e4SLinus Torvalds  *  each device it was responsible for, and marks those devices as
941da177e4SLinus Torvalds  *  driverless.
951da177e4SLinus Torvalds  */
961da177e4SLinus Torvalds 
dio_unregister_driver(struct dio_driver * drv)971da177e4SLinus Torvalds void dio_unregister_driver(struct dio_driver *drv)
981da177e4SLinus Torvalds {
991da177e4SLinus Torvalds 	driver_unregister(&drv->driver);
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds /**
104771fcb58SRandy Dunlap  *  dio_bus_match - Tell if a DIO device structure has a matching DIO device id structure
1051da177e4SLinus Torvalds  *  @dev: the DIO device structure to match against
106771fcb58SRandy Dunlap  *  @drv: the &device_driver that points to the array of DIO device id structures to search
1071da177e4SLinus Torvalds  *
108b87c9661SGeert Uytterhoeven  *  Used by the driver core to check whether a DIO device present in the
109b87c9661SGeert Uytterhoeven  *  system is in a driver's list of supported devices. Returns 1 if supported,
110b87c9661SGeert Uytterhoeven  *  and 0 if there is no match.
1111da177e4SLinus Torvalds  */
1121da177e4SLinus Torvalds 
dio_bus_match(struct device * dev,const struct device_driver * drv)113*af46fe8cSGeert Uytterhoeven static int dio_bus_match(struct device *dev, const struct device_driver *drv)
1141da177e4SLinus Torvalds {
1151da177e4SLinus Torvalds 	struct dio_dev *d = to_dio_dev(dev);
116*af46fe8cSGeert Uytterhoeven 	const struct dio_driver *dio_drv = to_dio_driver(drv);
1171da177e4SLinus Torvalds 	const struct dio_device_id *ids = dio_drv->id_table;
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	if (!ids)
1201da177e4SLinus Torvalds 		return 0;
1211da177e4SLinus Torvalds 
12218c99362SAkinobu Mita 	return dio_match_device(ids, d) ? 1 : 0;
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 
126cb1c1224SRicardo B. Marliere const struct bus_type dio_bus_type = {
1271da177e4SLinus Torvalds 	.name	= "dio",
1285b34bf88SRussell King 	.match	= dio_bus_match,
1295b34bf88SRussell King 	.probe	= dio_device_probe,
1301da177e4SLinus Torvalds };
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 
dio_driver_init(void)1331da177e4SLinus Torvalds static int __init dio_driver_init(void)
1341da177e4SLinus Torvalds {
1351da177e4SLinus Torvalds 	return bus_register(&dio_bus_type);
1361da177e4SLinus Torvalds }
1371da177e4SLinus Torvalds 
1381da177e4SLinus Torvalds postcore_initcall(dio_driver_init);
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds EXPORT_SYMBOL(dio_register_driver);
1411da177e4SLinus Torvalds EXPORT_SYMBOL(dio_unregister_driver);
1421da177e4SLinus Torvalds EXPORT_SYMBOL(dio_bus_type);
143