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