/*
 *  Zorro Driver Services
 *
 *  Copyright (C) 2003 Geert Uytterhoeven
 *
 *  Loosely based on drivers/pci/pci-driver.c
 *
 *  This file is subject to the terms and conditions of the GNU General Public
 *  License.  See the file COPYING in the main directory of this archive
 *  for more details.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/zorro.h>

#include "zorro.h"


    /**
     *  zorro_match_device - Tell if a Zorro device structure has a matching
     *                       Zorro device id structure
     *  @ids: array of Zorro device id structures to search in
     *  @dev: the Zorro device structure to match against
     *
     *  Used by a driver to check whether a Zorro device present in the
     *  system is in its list of supported devices. Returns the matching
     *  zorro_device_id structure or %NULL if there is no match.
     */

const struct zorro_device_id *
zorro_match_device(const struct zorro_device_id *ids,
		   const struct zorro_dev *z)
{
	while (ids->id) {
		if (ids->id == ZORRO_WILDCARD || ids->id == z->id)
			return ids;
		ids++;
	}
	return NULL;
}
EXPORT_SYMBOL(zorro_match_device);


static int zorro_device_probe(struct device *dev)
{
	int error = 0;
	struct zorro_driver *drv = to_zorro_driver(dev->driver);
	struct zorro_dev *z = to_zorro_dev(dev);

	if (!z->driver && drv->probe) {
		const struct zorro_device_id *id;

		id = zorro_match_device(drv->id_table, z);
		if (id)
			error = drv->probe(z, id);
		if (error >= 0) {
			z->driver = drv;
			error = 0;
		}
	}
	return error;
}


static int zorro_device_remove(struct device *dev)
{
	struct zorro_dev *z = to_zorro_dev(dev);
	struct zorro_driver *drv = to_zorro_driver(dev->driver);

	if (drv) {
		if (drv->remove)
			drv->remove(z);
		z->driver = NULL;
	}
	return 0;
}


    /**
     *  zorro_register_driver - register a new Zorro driver
     *  @drv: the driver structure to register
     *
     *  Adds the driver structure to the list of registered drivers
     *  Returns zero or a negative error value.
     */

int zorro_register_driver(struct zorro_driver *drv)
{
	/* initialize common driver fields */
	drv->driver.name = drv->name;
	drv->driver.bus = &zorro_bus_type;

	/* register with core */
	return driver_register(&drv->driver);
}
EXPORT_SYMBOL(zorro_register_driver);


    /**
     *  zorro_unregister_driver - unregister a zorro driver
     *  @drv: the driver structure to unregister
     *
     *  Deletes the driver structure from the list of registered Zorro drivers,
     *  gives it a chance to clean up by calling its remove() function for
     *  each device it was responsible for, and marks those devices as
     *  driverless.
     */

void zorro_unregister_driver(struct zorro_driver *drv)
{
	driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(zorro_unregister_driver);


    /**
     *  zorro_bus_match - Tell if a Zorro device structure has a matching Zorro
     *                    device id structure
     *  @ids: array of Zorro device id structures to search in
     *  @dev: the Zorro device structure to match against
     *
     *  Used by a driver to check whether a Zorro device present in the
     *  system is in its list of supported devices.Returns the matching
     *  zorro_device_id structure or %NULL if there is no match.
     */

static int zorro_bus_match(struct device *dev, struct device_driver *drv)
{
	struct zorro_dev *z = to_zorro_dev(dev);
	struct zorro_driver *zorro_drv = to_zorro_driver(drv);
	const struct zorro_device_id *ids = zorro_drv->id_table;

	if (!ids)
		return 0;

	while (ids->id) {
		if (ids->id == ZORRO_WILDCARD || ids->id == z->id)
			return 1;
		ids++;
	}
	return 0;
}

static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct zorro_dev *z;

	if (!dev)
		return -ENODEV;

	z = to_zorro_dev(dev);
	if (!z)
		return -ENODEV;

	if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) ||
	    add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) ||
	    add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) ||
	    add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id))
		return -ENOMEM;

	return 0;
}

struct bus_type zorro_bus_type = {
	.name		= "zorro",
	.dev_name	= "zorro",
	.dev_groups	= zorro_device_attribute_groups,
	.match		= zorro_bus_match,
	.uevent		= zorro_uevent,
	.probe		= zorro_device_probe,
	.remove		= zorro_device_remove,
};
EXPORT_SYMBOL(zorro_bus_type);


static int __init zorro_driver_init(void)
{
	return bus_register(&zorro_bus_type);
}

postcore_initcall(zorro_driver_init);

