11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Zorro Driver Services
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2003 Geert Uytterhoeven
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Loosely based on drivers/pci/pci-driver.c
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This file is subject to the terms and conditions of the GNU General Public
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  License.  See the file COPYING in the main directory of this archive
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  for more details.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/zorro.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /**
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_match_device - Tell if a Zorro device structure has a matching
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *                       Zorro device id structure
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @ids: array of Zorro device id structures to search in
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @dev: the Zorro device structure to match against
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  Used by a driver to check whether a Zorro device present in the
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  system is in its list of supported devices. Returns the matching
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_device_id structure or %NULL if there is no match.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst struct zorro_device_id *
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldszorro_match_device(const struct zorro_device_id *ids,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   const struct zorro_dev *z)
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ids->id) {
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ids->id == ZORRO_WILDCARD || ids->id == z->id)
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ids;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ids++;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return NULL;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40d996e9dc453a5f327961f19d274c6481b3bf4f34Jim RotmalmEXPORT_SYMBOL(zorro_match_device);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zorro_device_probe(struct device *dev)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zorro_driver *drv = to_zorro_driver(dev->driver);
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zorro_dev *z = to_zorro_dev(dev);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!z->driver && drv->probe) {
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		const struct zorro_device_id *id;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		id = zorro_match_device(drv->id_table, z);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (id)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			error = drv->probe(z, id);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (error >= 0) {
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			z->driver = drv;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			error = 0;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return error;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
642f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoevenstatic int zorro_device_remove(struct device *dev)
652f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven{
662f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	struct zorro_dev *z = to_zorro_dev(dev);
672f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	struct zorro_driver *drv = to_zorro_driver(dev->driver);
682f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven
692f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	if (drv) {
702f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven		if (drv->remove)
712f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven			drv->remove(z);
722f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven		z->driver = NULL;
732f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	}
742f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	return 0;
752f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven}
762f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven
772f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /**
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_register_driver - register a new Zorro driver
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @drv: the driver structure to register
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  Adds the driver structure to the list of registered drivers
8333d8675ea66e79d21da3ed64ce88dfb2a18bc6a7Bjorn Helgaas     *  Returns zero or a negative error value.
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint zorro_register_driver(struct zorro_driver *drv)
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* initialize common driver fields */
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.name = drv->name;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drv->driver.bus = &zorro_bus_type;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* register with core */
9333d8675ea66e79d21da3ed64ce88dfb2a18bc6a7Bjorn Helgaas	return driver_register(&drv->driver);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
95d996e9dc453a5f327961f19d274c6481b3bf4f34Jim RotmalmEXPORT_SYMBOL(zorro_register_driver);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /**
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_unregister_driver - unregister a zorro driver
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @drv: the driver structure to unregister
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  Deletes the driver structure from the list of registered Zorro drivers,
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  gives it a chance to clean up by calling its remove() function for
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  each device it was responsible for, and marks those devices as
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  driverless.
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid zorro_unregister_driver(struct zorro_driver *drv)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	driver_unregister(&drv->driver);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
112d996e9dc453a5f327961f19d274c6481b3bf4f34Jim RotmalmEXPORT_SYMBOL(zorro_unregister_driver);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /**
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_bus_match - Tell if a Zorro device structure has a matching Zorro
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *                    device id structure
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @ids: array of Zorro device id structures to search in
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  @dev: the Zorro device structure to match against
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  Used by a driver to check whether a Zorro device present in the
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  system is in its list of supported devices.Returns the matching
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     *  zorro_device_id structure or %NULL if there is no match.
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int zorro_bus_match(struct device *dev, struct device_driver *drv)
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zorro_dev *z = to_zorro_dev(dev);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct zorro_driver *zorro_drv = to_zorro_driver(drv);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct zorro_device_id *ids = zorro_drv->id_table;
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!ids)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ids->id) {
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ids->id == ZORRO_WILDCARD || ids->id == z->id)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ids++;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoevenstatic int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
144bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven{
145bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven#ifdef CONFIG_HOTPLUG
146bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	struct zorro_dev *z;
147bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven
148bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	if (!dev)
149bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven		return -ENODEV;
150bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven
151bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	z = to_zorro_dev(dev);
152bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	if (!z)
153bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven		return -ENODEV;
154bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven
155bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) ||
156bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	    add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) ||
157bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	    add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) ||
158bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	    add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id))
159bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven		return -ENOMEM;
160bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven
161bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	return 0;
162bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven#else /* !CONFIG_HOTPLUG */
163bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	return -ENODEV;
164bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven#endif /* !CONFIG_HOTPLUG */
165bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type zorro_bus_type = {
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name	= "zorro",
169b6a01e9bda69aaf22f3a23bafc91c0fb51420a7aRussell King	.match	= zorro_bus_match,
170bf54a2b3c0dbf76136f00ff785bf6d8f6291311dGeert Uytterhoeven	.uevent	= zorro_uevent,
171b6a01e9bda69aaf22f3a23bafc91c0fb51420a7aRussell King	.probe	= zorro_device_probe,
1722f9b0b5e46f0381fd41af8cb9ed4daffee59d4f3Geert Uytterhoeven	.remove	= zorro_device_remove,
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
174d996e9dc453a5f327961f19d274c6481b3bf4f34Jim RotmalmEXPORT_SYMBOL(zorro_bus_type);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init zorro_driver_init(void)
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bus_register(&zorro_bus_type);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspostcore_initcall(zorro_driver_init);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
184