18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Zorro Driver Services 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2003 Geert Uytterhoeven 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Loosely based on drivers/pci/pci-driver.c 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 98c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 108c2ecf20Sopenharmony_ci * for more details. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/zorro.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "zorro.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci /** 218c2ecf20Sopenharmony_ci * zorro_match_device - Tell if a Zorro device structure has a matching 228c2ecf20Sopenharmony_ci * Zorro device id structure 238c2ecf20Sopenharmony_ci * @ids: array of Zorro device id structures to search in 248c2ecf20Sopenharmony_ci * @dev: the Zorro device structure to match against 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Used by a driver to check whether a Zorro device present in the 278c2ecf20Sopenharmony_ci * system is in its list of supported devices. Returns the matching 288c2ecf20Sopenharmony_ci * zorro_device_id structure or %NULL if there is no match. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const struct zorro_device_id * 328c2ecf20Sopenharmony_cizorro_match_device(const struct zorro_device_id *ids, 338c2ecf20Sopenharmony_ci const struct zorro_dev *z) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci while (ids->id) { 368c2ecf20Sopenharmony_ci if (ids->id == ZORRO_WILDCARD || ids->id == z->id) 378c2ecf20Sopenharmony_ci return ids; 388c2ecf20Sopenharmony_ci ids++; 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci return NULL; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic int zorro_device_probe(struct device *dev) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci int error = 0; 478c2ecf20Sopenharmony_ci struct zorro_driver *drv = to_zorro_driver(dev->driver); 488c2ecf20Sopenharmony_ci struct zorro_dev *z = to_zorro_dev(dev); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (!z->driver && drv->probe) { 518c2ecf20Sopenharmony_ci const struct zorro_device_id *id; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci id = zorro_match_device(drv->id_table, z); 548c2ecf20Sopenharmony_ci if (id) 558c2ecf20Sopenharmony_ci error = drv->probe(z, id); 568c2ecf20Sopenharmony_ci if (error >= 0) { 578c2ecf20Sopenharmony_ci z->driver = drv; 588c2ecf20Sopenharmony_ci error = 0; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci return error; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int zorro_device_remove(struct device *dev) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct zorro_dev *z = to_zorro_dev(dev); 688c2ecf20Sopenharmony_ci struct zorro_driver *drv = to_zorro_driver(dev->driver); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci if (drv) { 718c2ecf20Sopenharmony_ci if (drv->remove) 728c2ecf20Sopenharmony_ci drv->remove(z); 738c2ecf20Sopenharmony_ci z->driver = NULL; 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci return 0; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /** 808c2ecf20Sopenharmony_ci * zorro_register_driver - register a new Zorro driver 818c2ecf20Sopenharmony_ci * @drv: the driver structure to register 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * Adds the driver structure to the list of registered drivers 848c2ecf20Sopenharmony_ci * Returns zero or a negative error value. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciint zorro_register_driver(struct zorro_driver *drv) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci /* initialize common driver fields */ 908c2ecf20Sopenharmony_ci drv->driver.name = drv->name; 918c2ecf20Sopenharmony_ci drv->driver.bus = &zorro_bus_type; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* register with core */ 948c2ecf20Sopenharmony_ci return driver_register(&drv->driver); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zorro_register_driver); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /** 1008c2ecf20Sopenharmony_ci * zorro_unregister_driver - unregister a zorro driver 1018c2ecf20Sopenharmony_ci * @drv: the driver structure to unregister 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * Deletes the driver structure from the list of registered Zorro drivers, 1048c2ecf20Sopenharmony_ci * gives it a chance to clean up by calling its remove() function for 1058c2ecf20Sopenharmony_ci * each device it was responsible for, and marks those devices as 1068c2ecf20Sopenharmony_ci * driverless. 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_civoid zorro_unregister_driver(struct zorro_driver *drv) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci driver_unregister(&drv->driver); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zorro_unregister_driver); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /** 1178c2ecf20Sopenharmony_ci * zorro_bus_match - Tell if a Zorro device structure has a matching Zorro 1188c2ecf20Sopenharmony_ci * device id structure 1198c2ecf20Sopenharmony_ci * @ids: array of Zorro device id structures to search in 1208c2ecf20Sopenharmony_ci * @dev: the Zorro device structure to match against 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * Used by the driver core to check whether a Zorro device present in the 1238c2ecf20Sopenharmony_ci * system is in a driver's list of supported devices. Returns 1 if 1248c2ecf20Sopenharmony_ci * supported, and 0 if there is no match. 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int zorro_bus_match(struct device *dev, struct device_driver *drv) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci struct zorro_dev *z = to_zorro_dev(dev); 1308c2ecf20Sopenharmony_ci struct zorro_driver *zorro_drv = to_zorro_driver(drv); 1318c2ecf20Sopenharmony_ci const struct zorro_device_id *ids = zorro_drv->id_table; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (!ids) 1348c2ecf20Sopenharmony_ci return 0; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci return !!zorro_match_device(ids, z); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct zorro_dev *z; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (!dev) 1448c2ecf20Sopenharmony_ci return -ENODEV; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci z = to_zorro_dev(dev); 1478c2ecf20Sopenharmony_ci if (!z) 1488c2ecf20Sopenharmony_ci return -ENODEV; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || 1518c2ecf20Sopenharmony_ci add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || 1528c2ecf20Sopenharmony_ci add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || 1538c2ecf20Sopenharmony_ci add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) 1548c2ecf20Sopenharmony_ci return -ENOMEM; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistruct bus_type zorro_bus_type = { 1608c2ecf20Sopenharmony_ci .name = "zorro", 1618c2ecf20Sopenharmony_ci .dev_name = "zorro", 1628c2ecf20Sopenharmony_ci .dev_groups = zorro_device_attribute_groups, 1638c2ecf20Sopenharmony_ci .match = zorro_bus_match, 1648c2ecf20Sopenharmony_ci .uevent = zorro_uevent, 1658c2ecf20Sopenharmony_ci .probe = zorro_device_probe, 1668c2ecf20Sopenharmony_ci .remove = zorro_device_remove, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zorro_bus_type); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int __init zorro_driver_init(void) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci return bus_register(&zorro_bus_type); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cipostcore_initcall(zorro_driver_init); 1778c2ecf20Sopenharmony_ci 178