162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci *  Zorro Driver Services
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *  Copyright (C) 2003 Geert Uytterhoeven
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Loosely based on drivers/pci/pci-driver.c
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  This file is subject to the terms and conditions of the GNU General Public
962306a36Sopenharmony_ci *  License.  See the file COPYING in the main directory of this archive
1062306a36Sopenharmony_ci *  for more details.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/zorro.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "zorro.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci    /**
2162306a36Sopenharmony_ci     *  zorro_match_device - Tell if a Zorro device structure has a matching
2262306a36Sopenharmony_ci     *                       Zorro device id structure
2362306a36Sopenharmony_ci     *  @ids: array of Zorro device id structures to search in
2462306a36Sopenharmony_ci     *  @dev: the Zorro device structure to match against
2562306a36Sopenharmony_ci     *
2662306a36Sopenharmony_ci     *  Used by a driver to check whether a Zorro device present in the
2762306a36Sopenharmony_ci     *  system is in its list of supported devices. Returns the matching
2862306a36Sopenharmony_ci     *  zorro_device_id structure or %NULL if there is no match.
2962306a36Sopenharmony_ci     */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic const struct zorro_device_id *
3262306a36Sopenharmony_cizorro_match_device(const struct zorro_device_id *ids,
3362306a36Sopenharmony_ci		   const struct zorro_dev *z)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	while (ids->id) {
3662306a36Sopenharmony_ci		if (ids->id == ZORRO_WILDCARD || ids->id == z->id)
3762306a36Sopenharmony_ci			return ids;
3862306a36Sopenharmony_ci		ids++;
3962306a36Sopenharmony_ci	}
4062306a36Sopenharmony_ci	return NULL;
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic int zorro_device_probe(struct device *dev)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	int error = 0;
4762306a36Sopenharmony_ci	struct zorro_driver *drv = to_zorro_driver(dev->driver);
4862306a36Sopenharmony_ci	struct zorro_dev *z = to_zorro_dev(dev);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (drv->probe) {
5162306a36Sopenharmony_ci		const struct zorro_device_id *id;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		id = zorro_match_device(drv->id_table, z);
5462306a36Sopenharmony_ci		if (id)
5562306a36Sopenharmony_ci			error = drv->probe(z, id);
5662306a36Sopenharmony_ci		if (error >= 0)
5762306a36Sopenharmony_ci			error = 0;
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci	return error;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void zorro_device_remove(struct device *dev)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct zorro_dev *z = to_zorro_dev(dev);
6662306a36Sopenharmony_ci	struct zorro_driver *drv = to_zorro_driver(dev->driver);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (drv->remove)
6962306a36Sopenharmony_ci		drv->remove(z);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci    /**
7462306a36Sopenharmony_ci     *  zorro_register_driver - register a new Zorro driver
7562306a36Sopenharmony_ci     *  @drv: the driver structure to register
7662306a36Sopenharmony_ci     *
7762306a36Sopenharmony_ci     *  Adds the driver structure to the list of registered drivers
7862306a36Sopenharmony_ci     *  Returns zero or a negative error value.
7962306a36Sopenharmony_ci     */
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciint zorro_register_driver(struct zorro_driver *drv)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	/* initialize common driver fields */
8462306a36Sopenharmony_ci	drv->driver.name = drv->name;
8562306a36Sopenharmony_ci	drv->driver.bus = &zorro_bus_type;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* register with core */
8862306a36Sopenharmony_ci	return driver_register(&drv->driver);
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ciEXPORT_SYMBOL(zorro_register_driver);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci    /**
9462306a36Sopenharmony_ci     *  zorro_unregister_driver - unregister a zorro driver
9562306a36Sopenharmony_ci     *  @drv: the driver structure to unregister
9662306a36Sopenharmony_ci     *
9762306a36Sopenharmony_ci     *  Deletes the driver structure from the list of registered Zorro drivers,
9862306a36Sopenharmony_ci     *  gives it a chance to clean up by calling its remove() function for
9962306a36Sopenharmony_ci     *  each device it was responsible for, and marks those devices as
10062306a36Sopenharmony_ci     *  driverless.
10162306a36Sopenharmony_ci     */
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_civoid zorro_unregister_driver(struct zorro_driver *drv)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	driver_unregister(&drv->driver);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ciEXPORT_SYMBOL(zorro_unregister_driver);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci    /**
11162306a36Sopenharmony_ci     *  zorro_bus_match - Tell if a Zorro device structure has a matching Zorro
11262306a36Sopenharmony_ci     *                    device id structure
11362306a36Sopenharmony_ci     *  @ids: array of Zorro device id structures to search in
11462306a36Sopenharmony_ci     *  @dev: the Zorro device structure to match against
11562306a36Sopenharmony_ci     *
11662306a36Sopenharmony_ci     *  Used by the driver core to check whether a Zorro device present in the
11762306a36Sopenharmony_ci     *  system is in a driver's list of supported devices.  Returns 1 if
11862306a36Sopenharmony_ci     *  supported, and 0 if there is no match.
11962306a36Sopenharmony_ci     */
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic int zorro_bus_match(struct device *dev, struct device_driver *drv)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	struct zorro_dev *z = to_zorro_dev(dev);
12462306a36Sopenharmony_ci	struct zorro_driver *zorro_drv = to_zorro_driver(drv);
12562306a36Sopenharmony_ci	const struct zorro_device_id *ids = zorro_drv->id_table;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (!ids)
12862306a36Sopenharmony_ci		return 0;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	return !!zorro_match_device(ids, z);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic int zorro_uevent(const struct device *dev, struct kobj_uevent_env *env)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	const struct zorro_dev *z;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (!dev)
13862306a36Sopenharmony_ci		return -ENODEV;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	z = to_zorro_dev(dev);
14162306a36Sopenharmony_ci	if (!z)
14262306a36Sopenharmony_ci		return -ENODEV;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) ||
14562306a36Sopenharmony_ci	    add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) ||
14662306a36Sopenharmony_ci	    add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) ||
14762306a36Sopenharmony_ci	    add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id))
14862306a36Sopenharmony_ci		return -ENOMEM;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	return 0;
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistruct bus_type zorro_bus_type = {
15462306a36Sopenharmony_ci	.name		= "zorro",
15562306a36Sopenharmony_ci	.dev_name	= "zorro",
15662306a36Sopenharmony_ci	.dev_groups	= zorro_device_attribute_groups,
15762306a36Sopenharmony_ci	.match		= zorro_bus_match,
15862306a36Sopenharmony_ci	.uevent		= zorro_uevent,
15962306a36Sopenharmony_ci	.probe		= zorro_device_probe,
16062306a36Sopenharmony_ci	.remove		= zorro_device_remove,
16162306a36Sopenharmony_ci};
16262306a36Sopenharmony_ciEXPORT_SYMBOL(zorro_bus_type);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int __init zorro_driver_init(void)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	return bus_register(&zorro_bus_type);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cipostcore_initcall(zorro_driver_init);
17162306a36Sopenharmony_ci
172