Re: [PATCH 2.6] DIO driver model

From: Jochen Friedrich
Date: Thu Sep 30 2004 - 17:31:29 EST


Hi Roman,

here is the updated patch for the driver model of the hp300 DIO bus.

Thanks for your comments!
Jochen

drivers/dio/Makefile | 2
drivers/dio/dio-driver.c | 163 +++++++++++++++++++++++++++
drivers/dio/dio-sysfs.c | 77 +++++++++++++
drivers/dio/dio.c | 209 +++++++++++------------------------
drivers/net/Space.c | 3
drivers/net/hplance.c | 126 +++++++++------------
drivers/serial/8250_hp300.c | 259 +++++++++++++++++++++-----------------------
drivers/video/hpfb.c | 122 +++++++++++---------
include/linux/dio.h | 155 +++++++++++++++++++++++---
9 files changed, 697 insertions(+), 419 deletions(-)

On Wed, 29 Sep 2004, Roman Zippel wrote:

> Hi,
>
> Jochen Friedrich wrote:
>
> >>There seem to be some whitespace problems. Also, please set your indent
> >>size to 8 (following the Linux kernel coding style described in
> >>Documentation/CodingStyle).
> >
> > OK, done. I have it attached this time. Hopefully the whitespace problems
> > are gone now.
>
> One more code style nitpick: Please change the if blocks to:
>
> if (...) {
> ...
> } else {
> ...
> }
>
> Otherwise it looks ok, although it might be better to post it once to
> the kernel mailing list, as there there are the people who know better
> the driver model.Signed-off-by: Jochen Friedrich <jochen@xxxxxxxx>

diff -uprN -X dontdiff linux-2.6.orig/drivers/dio/Makefile linux-2.6/drivers/dio/Makefile
--- linux-2.6.orig/drivers/dio/Makefile 2004-09-26 21:11:22.000000000 +0200
+++ linux-2.6/drivers/dio/Makefile 2004-09-22 18:18:04.000000000 +0200
@@ -2,4 +2,4 @@
# Makefile for the linux kernel.
#

-obj-y := dio.o
+obj-y := dio.o dio-driver.o dio-sysfs.o
diff -uprN -X dontdiff linux-2.6.orig/drivers/dio/dio-driver.c linux-2.6/drivers/dio/dio-driver.c
--- linux-2.6.orig/drivers/dio/dio-driver.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6/drivers/dio/dio-driver.c 2004-09-29 08:42:51.000000000 +0200
@@ -0,0 +1,163 @@
+/*
+ * DIO Driver Services
+ *
+ * Copyright (C) 2004 Jochen Friedrich
+ *
+ * Loosely based on drivers/pci/pci-driver.c and drivers/zorro/zorro-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/dio.h>
+
+
+ /**
+ * dio_match_device - Tell if a DIO device structure has a matching
+ * DIO device id structure
+ * @ids: array of DIO device id structures to search in
+ * @dev: the DIO device structure to match against
+ *
+ * Used by a driver to check whether a DIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * dio_device_id structure or %NULL if there is no match.
+ */
+
+const struct dio_device_id *
+dio_match_device(const struct dio_device_id *ids,
+ const struct dio_dev *d)
+{
+ while (ids->id) {
+ if (ids->id == DIO_WILDCARD)
+ return ids;
+ if (DIO_NEEDSSECID(ids->id & 0xff)) {
+ if (ids->id == d->id)
+ return ids;
+ } else {
+ if ((ids->id & 0xff) == (d->id & 0xff))
+ return ids;
+ }
+ ids++;
+ }
+ return NULL;
+}
+
+static int dio_device_probe(struct device *dev)
+{
+ int error = 0;
+ struct dio_driver *drv = to_dio_driver(dev->driver);
+ struct dio_dev *d = to_dio_dev(dev);
+
+ if (!d->driver && drv->probe) {
+ const struct dio_device_id *id;
+
+ id = dio_match_device(drv->id_table, d);
+ if (id)
+ error = drv->probe(d, id);
+ if (error >= 0) {
+ d->driver = drv;
+ error = 0;
+ }
+ }
+ return error;
+}
+
+
+ /**
+ * dio_register_driver - register a new DIO driver
+ * @drv: the driver structure to register
+ *
+ * Adds the driver structure to the list of registered drivers
+ * Returns the number of DIO devices which were claimed by the driver
+ * during registration. The driver remains registered even if the
+ * return value is zero.
+ */
+
+int dio_register_driver(struct dio_driver *drv)
+{
+ int count = 0;
+
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &dio_bus_type;
+ drv->driver.probe = dio_device_probe;
+
+ /* register with core */
+ count = driver_register(&drv->driver);
+ return count ? count : 1;
+}
+
+
+ /**
+ * dio_unregister_driver - unregister a DIO driver
+ * @drv: the driver structure to unregister
+ *
+ * Deletes the driver structure from the list of registered DIO 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 dio_unregister_driver(struct dio_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+
+
+ /**
+ * dio_bus_match - Tell if a DIO device structure has a matching DIO
+ * device id structure
+ * @ids: array of DIO device id structures to search in
+ * @dev: the DIO device structure to match against
+ *
+ * Used by a driver to check whether a DIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * dio_device_id structure or %NULL if there is no match.
+ */
+
+static int dio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct dio_dev *d = to_dio_dev(dev);
+ struct dio_driver *dio_drv = to_dio_driver(drv);
+ const struct dio_device_id *ids = dio_drv->id_table;
+
+ if (!ids)
+ return 0;
+
+ while (ids->id) {
+ if (ids->id == DIO_WILDCARD)
+ return 1;
+ if (DIO_NEEDSSECID(ids->id & 0xff)) {
+ if (ids->id == d->id)
+ return 1;
+ } else {
+ if ((ids->id & 0xff) == (d->id & 0xff))
+ return 1;
+ }
+ ids++;
+ }
+ return 0;
+}
+
+
+struct bus_type dio_bus_type = {
+ .name = "dio",
+ .match = dio_bus_match
+};
+
+
+static int __init dio_driver_init(void)
+{
+ return bus_register(&dio_bus_type);
+}
+
+postcore_initcall(dio_driver_init);
+
+EXPORT_SYMBOL(dio_match_device);
+EXPORT_SYMBOL(dio_register_driver);
+EXPORT_SYMBOL(dio_unregister_driver);
+EXPORT_SYMBOL(dio_dev_driver);
+EXPORT_SYMBOL(dio_bus_type);
diff -uprN -X dontdiff linux-2.6.orig/drivers/dio/dio-sysfs.c linux-2.6/drivers/dio/dio-sysfs.c
--- linux-2.6.orig/drivers/dio/dio-sysfs.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6/drivers/dio/dio-sysfs.c 2004-09-27 19:50:56.000000000 +0200
@@ -0,0 +1,77 @@
+/*
+ * File Attributes for DIO Devices
+ *
+ * Copyright (C) 2004 Jochen Friedrich
+ *
+ * Loosely based on drivers/pci/pci-sysfs.c and drivers/zorro/zorro-sysfs.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/kernel.h>
+#include <linux/dio.h>
+#include <linux/stat.h>
+
+/* show configuration fields */
+
+static ssize_t dio_show_id(struct device *dev, char *buf)
+{
+ struct dio_dev *d;
+
+ d = to_dio_dev(dev);
+ return sprintf(buf, "0x%02x\n", (d->id & 0xff));
+}
+static DEVICE_ATTR(id, S_IRUGO, dio_show_id, NULL);
+
+static ssize_t dio_show_ipl(struct device *dev, char *buf)
+{
+ struct dio_dev *d;
+
+ d = to_dio_dev(dev);
+ return sprintf(buf, "0x%02x\n", d->ipl);
+}
+static DEVICE_ATTR(ipl, S_IRUGO, dio_show_ipl, NULL);
+
+static ssize_t dio_show_secid(struct device *dev, char *buf)
+{
+ struct dio_dev *d;
+
+ d = to_dio_dev(dev);
+ return sprintf(buf, "0x%02x\n", ((d->id >> 8)& 0xff));
+}
+static DEVICE_ATTR(secid, S_IRUGO, dio_show_secid, NULL);
+
+static ssize_t dio_show_name(struct device *dev, char *buf)
+{
+ struct dio_dev *d;
+
+ d = to_dio_dev(dev);
+ return sprintf(buf, "%s\n", d->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, dio_show_name, NULL);
+
+static ssize_t dio_show_resource(struct device *dev, char *buf)
+{
+ struct dio_dev *d = to_dio_dev(dev);
+
+ return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
+ dio_resource_start(d), dio_resource_end(d),
+ dio_resource_flags(d));
+}
+static DEVICE_ATTR(resource, S_IRUGO, dio_show_resource, NULL);
+
+void dio_create_sysfs_dev_files(struct dio_dev *d)
+{
+ struct device *dev = &d->dev;
+
+ /* current configuration's attributes */
+ device_create_file(dev, &dev_attr_id);
+ device_create_file(dev, &dev_attr_ipl);
+ device_create_file(dev, &dev_attr_secid);
+ device_create_file(dev, &dev_attr_name);
+ device_create_file(dev, &dev_attr_resource);
+}
+
diff -uprN -X dontdiff linux-2.6.orig/drivers/dio/dio.c linux-2.6/drivers/dio/dio.c
--- linux-2.6.orig/drivers/dio/dio.c 2004-09-26 21:11:22.000000000 +0200
+++ linux-2.6/drivers/dio/dio.c 2004-09-29 08:44:06.000000000 +0200
@@ -1,5 +1,6 @@
/* Code to support devices on the DIO and DIO-II bus
* Copyright (C) 05/1998 Peter Maydell <pmaydell@xxxxxxxxxxxxxxxxxxxxxx>
+ * Copyright (C) 1994 Jochen Friedrich <jochen@xxxxxxxx>
*
* This code has basically these routines at the moment:
* int dio_find(u_int deviceid)
@@ -23,15 +24,26 @@
* This file is based on the way the Amiga port handles Zorro II cards,
* although we aren't so complicated...
*/
-#include <linux/config.h>
-#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
#include <linux/dio.h>
#include <linux/slab.h> /* kmalloc() */
-#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/io.h> /* readb() */

+struct dio_bus dio_bus = {
+ .resources = {
+ /* DIO range */
+ { .name = "DIO mem", .start = 0x00600000, .end = 0x007fffff },
+ /* DIO-II range */
+ { .name = "DIO-II mem", .start = 0x01000000, .end = 0x1fffffff }
+ },
+ .name = "DIO bus"
+};
+
/* not a real config option yet! */
#define CONFIG_DIO_CONSTANTS

@@ -99,30 +111,16 @@ static char dio_no_name[] = { 0 };

#endif /* CONFIG_DIO_CONSTANTS */

-/* We represent all the DIO boards in the system with a linked list of these structs. */
-struct dioboard
+int __init dio_find(int deviceid)
{
- struct dioboard *next; /* link to next struct in list */
- int ipl; /* IPL of this board */
- int configured; /* has this board been configured? */
- int scode; /* select code of this board */
- int id; /* encoded ID */
- const char *name;
-};
-
-static struct dioboard *blist = NULL;
-
-static int __init dio_find_slow(int deviceid)
-{
- /* Called to find a DIO device before the full bus scan has run. Basically
- * only used by the console driver.
+ /* Called to find a DIO device before the full bus scan has run.
+ * Only used by the console driver.
*/
int scode, id;
u_char prid, secid, i;
mm_segment_t fs;

- for (scode = 0; scode < DIO_SCMAX; scode++)
- {
+ for (scode = 0; scode < DIO_SCMAX; scode++) {
void *va;
unsigned long pa;

@@ -142,8 +140,7 @@ static int __init dio_find_slow(int devi
fs = get_fs();
set_fs(KERNEL_DS);

- if (get_user(i, (unsigned char *)va + DIO_IDOFF))
- {
+ if (get_user(i, (unsigned char *)va + DIO_IDOFF)) {
set_fs(fs);
if (scode >= DIOII_SCBASE)
iounmap(va);
@@ -153,16 +150,13 @@ static int __init dio_find_slow(int devi
set_fs(fs);
prid = DIO_ID(va);

- if (DIO_NEEDSSECID(prid))
- {
+ if (DIO_NEEDSSECID(prid)) {
secid = DIO_SECID(va);
id = DIO_ENCODE_ID(prid, secid);
- }
- else
+ } else
id = prid;

- if (id == deviceid)
- {
+ if (id == deviceid) {
if (scode >= DIOII_SCBASE)
iounmap(va);
return scode;
@@ -172,35 +166,32 @@ static int __init dio_find_slow(int devi
return -1;
}

-int dio_find(int deviceid)
-{
- if (blist)
- {
- /* fast way */
- struct dioboard *b;
- for (b = blist; b; b = b->next)
- if (b->id == deviceid && b->configured == 0)
- return b->scode;
- return -1;
- }
- else
- {
- return dio_find_slow(deviceid);
- }
-}
-
/* This is the function that scans the DIO space and works out what
* hardware is actually present.
*/
static int __init dio_init(void)
{
int scode;
- struct dioboard *b, *bprev = NULL;
mm_segment_t fs;
- char i;
-
+ int i;
+ struct dio_dev *dev;
+
+ if (!MACH_IS_HP300)
+ return 0;
+
printk(KERN_INFO "Scanning for DIO devices...\n");
-
+
+ /* Initialize the DIO bus */
+ INIT_LIST_HEAD(&dio_bus.devices);
+ strcpy(dio_bus.dev.bus_id, "dio");
+ device_register(&dio_bus.dev);
+
+ /* Request all resources */
+ dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
+ for (i = 0; i < dio_bus.num_resources; i++)
+ request_resource(&iomem_resource, &dio_bus.resources[i]);
+
+ /* Register all devices */
for (scode = 0; scode < DIO_SCMAX; ++scode)
{
u_char prid, secid = 0; /* primary, secondary ID bytes */
@@ -223,8 +214,7 @@ static int __init dio_init(void)
fs = get_fs();
set_fs(KERNEL_DS);

- if (get_user(i, (unsigned char *)va + DIO_IDOFF))
- {
+ if (get_user(i, (unsigned char *)va + DIO_IDOFF)) {
set_fs(fs);
if (scode >= DIOII_SCBASE)
iounmap(va);
@@ -234,40 +224,40 @@ static int __init dio_init(void)
set_fs(fs);

/* Found a board, allocate it an entry in the list */
- b = kmalloc(sizeof(struct dioboard), GFP_KERNEL);
+ dev = kmalloc(sizeof(struct dio_dev), GFP_KERNEL);
+ if (!dev)
+ return 0;
+
+ memset(dev, 0, sizeof(struct dio_dev));
+ dev->bus = &dio_bus;
+ dev->dev.parent = &dio_bus.dev;
+ dev->dev.bus = &dio_bus_type;
+ dev->scode = scode;
+ dev->resource.start = pa;
+ dev->resource.end = pa + DIO_SIZE(scode, va);
+ sprintf(dev->dev.bus_id,"%02x", scode);

/* read the ID byte(s) and encode if necessary. */
prid = DIO_ID(va);

- if (DIO_NEEDSSECID(prid))
- {
+ if (DIO_NEEDSSECID(prid)) {
secid = DIO_SECID(va);
- b->id = DIO_ENCODE_ID(prid, secid);
- }
- else
- b->id = prid;
-
- b->configured = 0;
- b->scode = scode;
- b->ipl = DIO_IPL(va);
- b->name = dio_getname(b->id);
- printk(KERN_INFO "select code %3d: ipl %d: ID %02X", b->scode, b->ipl, prid);
+ dev->id = DIO_ENCODE_ID(prid, secid);
+ } else
+ dev->id = prid;
+
+ dev->ipl = DIO_IPL(va);
+ strcpy(dev->name,dio_getname(dev->id));
+ printk(KERN_INFO "select code %3d: ipl %d: ID %02X", dev->scode, dev->ipl, prid);
if (DIO_NEEDSSECID(prid))
printk(":%02X", secid);
- printk(": %s\n", b->name);
+ printk(": %s\n", dev->name);

if (scode >= DIOII_SCBASE)
iounmap(va);
-
- b->next = NULL;
-
- if (bprev)
- bprev->next = b;
- else
- blist = b;
- bprev = b;
+ device_register(&dev->dev);
+ dio_create_sysfs_dev_files(dev);
}
-
return 0;
}

@@ -278,77 +268,12 @@ subsys_initcall(dio_init);
*/
unsigned long dio_scodetophysaddr(int scode)
{
- if (scode >= DIOII_SCBASE)
- {
+ if (scode >= DIOII_SCBASE) {
return (DIOII_BASE + (scode - 132) * DIOII_DEVSIZE);
- }
- else if (scode > DIO_SCMAX || scode < 0)
+ } else if (scode > DIO_SCMAX || scode < 0)
return 0;
else if (DIO_SCINHOLE(scode))
return 0;

return (DIO_BASE + scode * DIO_DEVSIZE);
}
-
-int dio_scodetoipl(int scode)
-{
- struct dioboard *b;
- for (b = blist; b; b = b->next)
- if (b->scode == scode)
- break;
-
- if (!b)
- {
- printk(KERN_ERR "dio_scodetoipl: bad select code %d\n", scode);
- return 0;
- }
- else
- return b->ipl;
-}
-
-const char *dio_scodetoname(int scode)
-{
- struct dioboard *b;
- for (b = blist; b; b = b->next)
- if (b->scode == scode)
- break;
-
- if (!b)
- {
- printk(KERN_ERR "dio_scodetoname: bad select code %d\n", scode);
- return NULL;
- }
- else
- return b->name;
-}
-
-void dio_config_board(int scode)
-{
- struct dioboard *b;
- for (b = blist; b; b = b->next)
- if (b->scode == scode)
- break;
-
- if (!b)
- printk(KERN_ERR "dio_config_board: bad select code %d\n", scode);
- else if (b->configured)
- printk(KERN_WARNING "dio_config_board: board at select code %d already configured\n", scode);
- else
- b->configured = 1;
-}
-
-void dio_unconfig_board(int scode)
-{
- struct dioboard *b;
- for (b = blist; b; b = b->next)
- if (b->scode == scode)
- break;
-
- if (!b)
- printk(KERN_ERR "dio_unconfig_board: bad select code %d\n", scode);
- else if (!b->configured)
- printk(KERN_WARNING "dio_unconfig_board: board at select code %d not configured\n",
- scode);
- else
- b->configured = 0;
-}
diff -uprN -X dontdiff linux-2.6.orig/drivers/net/Space.c linux-2.6/drivers/net/Space.c
--- linux-2.6.orig/drivers/net/Space.c 2004-09-26 21:11:24.000000000 +0200
+++ linux-2.6/drivers/net/Space.c 2004-09-24 23:01:26.000000000 +0200
@@ -284,9 +284,6 @@ static struct devprobe2 m68k_probes[] __
#ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */
{pamsnet_probe, 0},
#endif
-#ifdef CONFIG_HPLANCE /* HP300 internal Ethernet */
- {hplance_probe, 0},
-#endif
#ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */
{mvme147lance_probe, 0},
#endif
diff -uprN -X dontdiff linux-2.6.orig/drivers/net/hplance.c linux-2.6/drivers/net/hplance.c
--- linux-2.6.orig/drivers/net/hplance.c 2004-09-26 21:11:24.000000000 +0200
+++ linux-2.6/drivers/net/hplance.c 2004-09-29 08:39:39.000000000 +0200
@@ -40,8 +40,7 @@

/* Our private data structure */
struct hplance_private {
- struct lance_private lance;
- unsigned int scode;
+ struct lance_private lance;
};

/* function prototypes... This is easy because all the grot is in the
@@ -49,76 +48,71 @@ struct hplance_private {
* plus board-specific init, open and close actions.
* Oh, and we need to tell the generic code how to read and write LANCE registers...
*/
-static void hplance_init(struct net_device *dev, int scode);
-static int hplance_open(struct net_device *dev);
-static int hplance_close(struct net_device *dev);
+static int __devinit hplance_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent);
+static void __devinit hplance_init(struct net_device *dev,
+ struct dio_dev *d);
+static void __devexit hplance_remove_one(struct dio_dev *d);
static void hplance_writerap(void *priv, unsigned short value);
static void hplance_writerdp(void *priv, unsigned short value);
static unsigned short hplance_readrdp(void *priv);
+static int hplance_open(struct net_device *dev);
+static int hplance_close(struct net_device *dev);

-#ifdef MODULE
-static struct hplance_private *root_hplance_dev;
-#endif
+static struct dio_device_id hplance_dio_tbl[] = {
+ { DIO_ID_LAN },
+ { 0 }
+};

-static void cleanup_card(struct net_device *dev)
-{
- struct hplance_private *lp = netdev_priv(dev);
- dio_unconfig_board(lp->scode);
-}
+static struct dio_driver hplance_driver = {
+ .name = "hplance",
+ .id_table = hplance_dio_tbl,
+ .probe = hplance_init_one,
+ .remove = __devexit_p(hplance_remove_one),
+};

/* Find all the HP Lance boards and initialise them... */
-struct net_device * __init hplance_probe(int unit)
+static int __devinit hplance_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent)
{
struct net_device *dev;
-
- if (!MACH_IS_HP300)
- return ERR_PTR(-ENODEV);
+ int err;

dev = alloc_etherdev(sizeof(struct hplance_private));
if (!dev)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;

- if (unit >= 0) {
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- }
+ if (!request_mem_region(d->resource.start, d->resource.end-d->resource.start, d->name))
+ return -EBUSY;

SET_MODULE_OWNER(dev);

- /* Isn't DIO nice? */
- for(;;)
- {
- int scode = dio_find(DIO_ID_LAN);
-
- if (scode < 0)
- break;
-
- dio_config_board(scode);
- hplance_init(dev, scode);
- if (!register_netdev(dev)) {
-#ifdef MODULE
- struct hplance_private *lp = netdev_priv(dev);
- lp->next_module = root_hplance_dev;
- root_hplance_dev = lp;
-#endif
- return dev;
- }
- cleanup_card(dev);
- }
+ hplance_init(dev, d);
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return err;
+ }
+ dio_set_drvdata(d, dev);
+ return 0;
+}
+
+static void __devexit hplance_remove_one(struct dio_dev *d)
+{
+ struct net_device *dev = dio_get_drvdata(d);
+
+ unregister_netdev(dev);
free_netdev(dev);
- return ERR_PTR(-ENODEV);
}

-/* Initialise a single lance board at the given select code */
-static void __init hplance_init(struct net_device *dev, int scode)
+/* Initialise a single lance board at the given DIO device */
+static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
{
- const char *name = dio_scodetoname(scode);
- unsigned long pa = dio_scodetophysaddr(scode);
- unsigned long va = (pa + DIO_VIRADDRBASE);
+ unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
struct hplance_private *lp;
int i;

- printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, name, scode);
+ printk(KERN_INFO "%s: %s; select code %d, addr", dev->name, d->name, d->scode);

/* reset the board */
out_8(va+DIO_IDOFF, 0xff);
@@ -136,8 +130,7 @@ static void __init hplance_init(struct n
dev->set_multicast_list = &lance_set_multicast;
dev->dma = 0;

- for (i=0; i<6; i++)
- {
+ for (i=0; i<6; i++) {
/* The NVRAM holds our ethernet address, one nibble per byte,
* at bytes NVRAMOFF+1,3,5,7,9...
*/
@@ -147,12 +140,12 @@ static void __init hplance_init(struct n
}

lp = netdev_priv(dev);
- lp->lance.name = (char*)name; /* discards const, shut up gcc */
+ lp->lance.name = (char*)d->name; /* discards const, shut up gcc */
lp->lance.base = va;
lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */
lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */
- lp->lance.irq = dio_scodetoipl(scode);
+ lp->lance.irq = d->ipl;
lp->lance.writerap = hplance_writerap;
lp->lance.writerdp = hplance_writerdp;
lp->lance.readrdp = hplance_readrdp;
@@ -160,7 +153,6 @@ static void __init hplance_init(struct n
lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
- lp->scode = scode;
printk(", irq %d\n", lp->lance.irq);
}

@@ -216,27 +208,17 @@ static int hplance_close(struct net_devi
return 0;
}

-#ifdef MODULE
-MODULE_LICENSE("GPL");
-int init_module(void)
+int __init hplance_init_module(void)
{
- int found = 0;
- while (!IS_ERR(hplance_probe(-1)))
- found++;
- return found ? 0 : -ENODEV;
+ return dio_module_init(&hplance_driver);
}

-void cleanup_module(void)
+void __exit hplance_cleanup_module(void)
{
- /* Walk the chain of devices, unregistering them */
- struct hplance_private *lp;
- while (root_hplance_dev) {
- lp = root_hplance_dev->next_module;
- unregister_netdev(root_lance_dev->dev);
- cleanup_card(root_lance_dev->dev);
- free_netdev(root_lance_dev->dev);
- root_lance_dev = lp;
- }
+ dio_unregister_driver(&hplance_driver);
}

-#endif /* MODULE */
+module_init(hplance_init_module);
+module_exit(hplance_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff -uprN -X dontdiff linux-2.6.orig/drivers/serial/8250_hp300.c linux-2.6/drivers/serial/8250_hp300.c
--- linux-2.6.orig/drivers/serial/8250_hp300.c 2004-09-26 21:11:26.000000000 +0200
+++ linux-2.6/drivers/serial/8250_hp300.c 2004-09-29 08:40:27.000000000 +0200
@@ -22,17 +22,40 @@
#warning CONFIG_8250 defined but neither CONFIG_HPDCA nor CONFIG_HPAPCI defined, are you sure?
#endif

+#ifdef CONFIG_HPAPCI
struct hp300_port
{
struct hp300_port *next; /* next port */
- unsigned long dio_base; /* start of DIO registers */
- int scode; /* select code of this board */
int line; /* line (tty) number */
};

-extern int hp300_uart_scode;
-
static struct hp300_port *hp300_ports;
+#endif
+
+#ifdef CONFIG_HPDCA
+
+static int __devinit hpdca_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent);
+static void __devexit hpdca_remove_one(struct dio_dev *d);
+
+static struct dio_device_id hpdca_dio_tbl[] = {
+ { DIO_ID_DCA0 },
+ { DIO_ID_DCA0REM },
+ { DIO_ID_DCA1 },
+ { DIO_ID_DCA1REM },
+ { 0 }
+};
+
+static struct dio_driver hpdca_driver = {
+ .name = "hpdca",
+ .id_table = hpdca_dio_tbl,
+ .probe = hpdca_init_one,
+ .remove = __devexit_p(hpdca_remove_one),
+};
+
+#endif
+
+extern int hp300_uart_scode;

/* Offset to UART registers from base of DCA */
#define UART_OFFSET 17
@@ -73,7 +96,10 @@ int __init hp300_setup_serial_console(vo

memset(&port, 0, sizeof(port));

- if (hp300_uart_scode < 0 || hp300_uart_scode > 256)
+ if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
+ return 0;
+
+ if (DIO_SCINHOLE(hp300_uart_scode))
return 0;

scode = hp300_uart_scode;
@@ -84,8 +110,7 @@ int __init hp300_setup_serial_console(vo
port.type = PORT_UNKNOWN;

/* Check for APCI console */
- if (scode == 256)
- {
+ if (scode == 256) {
#ifdef CONFIG_HPAPCI
printk(KERN_INFO "Serial console is HP APCI 1\n");

@@ -99,8 +124,7 @@ int __init hp300_setup_serial_console(vo
return 0;
#endif
}
- else
- {
+ else {
#ifdef CONFIG_HPDCA
unsigned long pa = dio_scodetophysaddr(scode);
if (!pa) {
@@ -135,47 +159,89 @@ int __init hp300_setup_serial_console(vo
}
#endif /* CONFIG_SERIAL_8250_CONSOLE */

+#ifdef CONFIG_HPDCA
+static int __devinit hpdca_init_one(struct dio_dev *d,
+ const struct dio_device_id *ent)
+{
+ struct serial_struct serial_req;
+ int line;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ if (hp300_uart_scode == d->scode) {
+ /* Already got it. */
+ return 0;
+ }
+#endif
+ memset(&serial_req, 0, sizeof(struct serial_struct));
+
+ /* Memory mapped I/O */
+ serial_req.io_type = SERIAL_IO_MEM;
+ serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+ serial_req.irq = d->ipl;
+ serial_req.baud_base = HPDCA_BAUD_BASE;
+ serial_req.iomap_base = (d->resource.start + UART_OFFSET);
+ serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
+ serial_req.iomem_reg_shift = 1;
+ line = register_serial(&serial_req);
+
+ if (line < 0) {
+ printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
+ " irq %d failed\n", d->scode, serial_req.irq);
+ return -ENOMEM;
+ }
+
+ /* Enable board-interrupts */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
+ dio_set_drvdata(d, (void *)line);
+
+ /* Reset the DCA */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_ID, 0xff);
+ udelay(100);
+
+ return 0;
+}
+#endif
+
static int __init hp300_8250_init(void)
{
static int called = 0;
-#ifdef CONFIG_HPDCA
- int scode;
-#endif
- int line, num_ports;
+ int num_ports;
+#ifdef CONFIG_HPAPCI
+ int line;
unsigned long base;
struct serial_struct serial_req;
struct hp300_port *port;
-
+ int i;
+#endif
if (called)
return -ENODEV;
called = 1;
- num_ports = 0;

- if (!MACH_IS_HP300) {
+ if (!MACH_IS_HP300)
return -ENODEV;
- }

-#ifdef CONFIG_HPDCA
- while (1) {
- /* We detect boards by looking for DIO boards which match a
- * given subset of IDs. dio_find() returns the board's scancode.
- * The scancode to physaddr mapping is a property of the hardware,
- * as is the scancode to IPL (interrupt priority) mapping.
- */
- scode = dio_find(DIO_ID_DCA0);
- if (scode < 0)
- scode = dio_find(DIO_ID_DCA0REM);
- if (scode < 0)
- scode = dio_find(DIO_ID_DCA1);
- if (scode < 0)
- scode = dio_find(DIO_ID_DCA1REM);
- if (scode < 0)
- break; /* no, none at all */
+ num_ports = 0;

+#ifdef CONFIG_HPDCA
+ if (dio_module_init(&hpdca_driver) == 0)
+ num_ports++;
+#endif
+#ifdef CONFIG_HPAPCI
+ if (hp300_model < HP_400) {
+ if (!num_ports)
+ return -ENODEV;
+ return 0;
+ }
+ /* These models have the Frodo chip.
+ * Port 0 is reserved for the Apollo Domain keyboard.
+ * Port 1 is either the console or the DCA.
+ */
+ for (i = 1; i < 4; i++) {
+ /* Port 1 is the console on a 425e, on other machines it's mapped to
+ * DCA.
+ */
#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (hp300_uart_scode == scode) {
- /* Already got it */
- dio_config_board(scode);
+ if (i == 1) {
continue;
}
#endif
@@ -186,109 +252,33 @@ static int __init hp300_8250_init(void)
return -ENOMEM;

memset(&serial_req, 0, sizeof(struct serial_struct));
-
- base = dio_scodetophysaddr(scode);

- /* If we want to tell the DIO code that this board is configured,
- * we should do that here.
- */
- dio_config_board(scode);
+ base = (FRODO_BASE + FRODO_APCI_OFFSET(i));

/* Memory mapped I/O */
serial_req.io_type = SERIAL_IO_MEM;
serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- serial_req.irq = dio_scodetoipl(scode);
- serial_req.baud_base = HPDCA_BAUD_BASE;
- serial_req.iomap_base = (base + UART_OFFSET);
+ /* XXX - no interrupt support yet */
+ serial_req.irq = 0;
+ serial_req.baud_base = HPAPCI_BAUD_BASE;
+ serial_req.iomap_base = base;
serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
- serial_req.iomem_reg_shift = 1;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (hp300_uart_scode != scode) {
-#endif
- /* Reset the DCA */
- out_8(base + DIO_VIRADDRBASE + DCA_ID, 0xff);
- udelay(100);
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- }
-#endif
+ serial_req.iomem_reg_shift = 2;

line = register_serial(&serial_req);

if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
- " irq %d failed\n", scode, serial_req.irq);
+ printk(KERN_NOTICE "8250_hp300: register_serial() APCI %d"
+ " irq %d failed\n", i, serial_req.irq);
kfree(port);
continue;
}

- /* Enable board-interrupts */
- out_8(base + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);
-
- port->dio_base = base + DIO_VIRADDRBASE;
- port->scode = scode;
port->line = line;
port->next = hp300_ports;
hp300_ports = port;

num_ports++;
- }
-#endif
-
-#ifdef CONFIG_HPAPCI
- if (hp300_model >= HP_400)
- {
- int i;
-
- /* These models have the Frodo chip.
- * Port 0 is reserved for the Apollo Domain keyboard.
- * Port 1 is either the console or the DCA.
- */
- for (i = 1; i < 4; i++) {
- /* Port 1 is the console on a 425e, on other machines it's mapped to
- * DCA.
- */
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (i == 1) {
- continue;
- }
-#endif
-
- /* Create new serial device */
- port = kmalloc(sizeof(struct hp300_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- memset(&serial_req, 0, sizeof(struct serial_struct));
-
- base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
-
- /* Memory mapped I/O */
- serial_req.io_type = SERIAL_IO_MEM;
- serial_req.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
- /* XXX - no interrupt support yet */
- serial_req.irq = 0;
- serial_req.baud_base = HPAPCI_BAUD_BASE;
- serial_req.iomap_base = base;
- serial_req.iomem_base = (char *)(serial_req.iomap_base + DIO_VIRADDRBASE);
- serial_req.iomem_reg_shift = 2;
-
- line = register_serial(&serial_req);
-
- if (line < 0) {
- printk(KERN_NOTICE "8250_hp300: register_serial() APCI %d"
- " irq %d failed\n", i, serial_req.irq);
- kfree(port);
- continue;
- }
-
- port->dio_base = 0;
- port->line = line;
- port->next = hp300_ports;
- hp300_ports = port;
-
- num_ports++;
- }
}
#endif

@@ -299,28 +289,37 @@ static int __init hp300_8250_init(void)
return 0;
}

+#ifdef CONFIG_HPDCA
+static void __devexit hpdca_remove_one(struct dio_dev *d)
+{
+ int line;
+
+ line = (int) dio_get_drvdata(d);
+ if (d->resource.start) {
+ /* Disable board-interrupts */
+ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, 0);
+ }
+ unregister_serial(line);
+}
+#endif
+
static void __exit hp300_8250_exit(void)
{
+#ifdef CONFIG_HPAPCI
struct hp300_port *port, *to_free;

for (port = hp300_ports; port; ) {
unregister_serial(port->line);
-
-#ifdef CONFIG_HPDCA
- if (port->dio_base) {
- /* Disable board-interrupts */
- out_8(port->dio_base + DCA_IC, 0);
-
- dio_unconfig_board(port->scode);
- }
-#endif
-
to_free = port;
port = port->next;
kfree(to_free);
}

hp300_ports = NULL;
+#endif
+#ifdef CONFIG_HPDCA
+ dio_unregister_driver(&hpdca_driver);
+#endif
}

module_init(hp300_8250_init);
diff -uprN -X dontdiff linux-2.6.orig/drivers/video/hpfb.c linux-2.6/drivers/video/hpfb.c
--- linux-2.6.orig/drivers/video/hpfb.c 2004-09-26 21:11:27.000000000 +0200
+++ linux-2.6/drivers/video/hpfb.c 2004-09-29 08:41:54.000000000 +0200
@@ -127,14 +127,12 @@ static int hpfb_blank(int blank, struct

static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h, int rr)
{
- if (rr >= 0)
- {
+ if (rr >= 0) {
while (in_8(fb_regs + BUSY) & fb_bitmask)
;
}
out_8(fb_regs + TC_FBEN, fb_bitmask);
- if (rr >= 0)
- {
+ if (rr >= 0) {
out_8(fb_regs + TC_WEN, fb_bitmask);
out_8(fb_regs + WMRR, rr);
}
@@ -221,13 +219,11 @@ static int __init hpfb_init_one(unsigned

fb_info.fix.smem_start = (in_8(fb_regs + fboff) << 16);

- if (phys_base >= DIOII_BASE)
- {
+ if (phys_base >= DIOII_BASE) {
fb_info.fix.smem_start += phys_base;
}

- if (DIO_SECID(fb_regs) != DIO_ID2_TOPCAT)
- {
+ if (DIO_SECID(fb_regs) != DIO_ID2_TOPCAT) {
/* This is the magic incantation the HP X server uses to make Catseye boards work. */
while (in_be16(fb_regs+0x4800) & 1)
;
@@ -299,8 +295,7 @@ static int __init hpfb_init_one(unsigned

fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);

- if (register_framebuffer(&fb_info) < 0)
- {
+ if (register_framebuffer(&fb_info) < 0) {
fb_dealloc_cmap(&fb_info.cmap);
return 1;
}
@@ -322,6 +317,51 @@ static int __init hpfb_init_one(unsigned
/*
* Initialise the framebuffer
*/
+static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_id * ent)
+{
+ unsigned long paddr, vaddr;
+
+ paddr = d->resource.start;
+ if (!request_mem_region(d->resource.start, d->resource.end - d->resource.start, d->name))
+ return -EBUSY;
+
+ if (d->scode >= DIOII_SCBASE) {
+ vaddr = (unsigned long)ioremap(paddr, d->resource.end - d->resource.start);
+ } else {
+ vaddr = paddr + DIO_VIRADDRBASE;
+ }
+ printk(KERN_INFO "Topcat found at DIO select code %d "
+ "(secondary id %02x)\n", d->scode, (d->id >> 8) & 0xff);
+ if (hpfb_init_one(paddr, vaddr)) {
+ if (d->scode >= DIOII_SCBASE)
+ iounmap((void *)vaddr);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void __devexit hpfb_remove_one(struct dio_dev *d)
+{
+ unregister_framebuffer(&fb_info);
+ if (d->scode >= DIOII_SCBASE)
+ iounmap((void *)fb_regs);
+ release_mem_region(d->resource.start, d->resource.end - d->resource.start);
+}
+
+static struct dio_device_id hpfb_dio_tbl[] = {
+ { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_LRCATSEYE) },
+ { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRCCATSEYE) },
+ { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRMCATSEYE) },
+ { DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_TOPCAT) },
+ { 0 }
+};
+
+static struct dio_driver hpfb_driver = {
+ .name = "hpfb",
+ .id_table = hpfb_dio_tbl,
+ .probe = hpfb_dio_probe,
+ .remove = __devexit_p(hpfb_remove_one),
+};

int __init hpfb_init(void)
{
@@ -344,62 +384,32 @@ int __init hpfb_init(void)
if (!MACH_IS_HP300)
return -ENXIO;

+ dio_module_init(&hpfb_driver);
+
fs = get_fs();
set_fs(KERNEL_DS);
err = get_user(i, (unsigned char *)INTFBVADDR + DIO_IDOFF);
set_fs(fs);

- if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR)))
- {
+ if (!err && (i == DIO_ID_FBUFFER) && topcat_sid_ok(sid = DIO_SECID(INTFBVADDR))) {
+ if (!request_mem_region(INTFBPADDR, DIO_DEVSIZE, "Internal Topcat"))
+ return -EBUSY;
printk(KERN_INFO "Internal Topcat found (secondary id %02x)\n", sid);
- if (hpfb_init_one(INTFBPADDR, INTFBVADDR))
- {
+ if (hpfb_init_one(INTFBPADDR, INTFBVADDR)) {
return -ENOMEM;
}
}
- else
- {
- int sc, size;
- unsigned long paddr, vaddr;
-
- if ((sc = dio_find(DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_LRCATSEYE))) < 0 &&
- (sc = dio_find(DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRCCATSEYE))) < 0 &&
- (sc = dio_find(DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_HRMCATSEYE))) < 0 &&
- (sc = dio_find(DIO_ENCODE_ID(DIO_ID_FBUFFER, DIO_ID2_TOPCAT))) < 0)
- {
- return -ENXIO;
- }
-
- dio_config_board(sc);
- paddr = dio_scodetophysaddr(sc);
-
- if (sc >= DIOII_SCBASE)
- {
- /* To find out the real size of the device we first need to map it. */
- vaddr = (unsigned long)ioremap(paddr, PAGE_SIZE);
- size = DIO_SIZE(sc, vaddr);
- iounmap((void *)vaddr);
- vaddr = (unsigned long)ioremap(paddr, size);
- }
- else
- {
- vaddr = paddr + DIO_VIRADDRBASE;
- size = DIO_SIZE(sc, vaddr);
- }
- sid = DIO_SECID(vaddr);
-
- printk(KERN_INFO "Topcat found at DIO select code %d "
- "(secondary id %02x)\n", sc, sid);
- if (hpfb_init_one(paddr, vaddr))
- {
- if (sc >= DIOII_SCBASE)
- iounmap((void *)vaddr);
- dio_unconfig_board(sc);
- return -ENOMEM;
- }
- }
-
return 0;
}

+void __exit hpfb_cleanup_module(void)
+{
+ dio_unregister_driver(&hpfb_driver);
+}
+
+#ifdef MODULE
+module_init(hpfb_init);
+#endif
+module_exit(hpfb_cleanup_module);
+
MODULE_LICENSE("GPL");
diff -uprN -X dontdiff linux-2.6.orig/include/linux/dio.h linux-2.6/include/linux/dio.h
--- linux-2.6.orig/include/linux/dio.h 2004-09-26 21:11:35.000000000 +0200
+++ linux-2.6/include/linux/dio.h 2004-09-27 19:48:52.000000000 +0200
@@ -3,11 +3,12 @@
* The general structure of this is vaguely based on how
* the Amiga port handles Zorro boards.
* Copyright (C) Peter Maydell 05/1998 <pmaydell@xxxxxxxxxxxxxxxxxxxxxx>
+ * Converted to driver model Jochen Friedrich <jochen@xxxxxxxx>
*
* The board IDs are from the NetBSD kernel, which for once provided
* helpful comments...
*
- * This goes with arch/m68k/hp300/dio.c
+ * This goes with drivers/dio/dio.c
*/

#ifndef _LINUX_DIO_H
@@ -27,18 +28,80 @@
* so currently we just don't handle DIO-II boards. It wouldn't be hard to
* do with ioremap() though.
*/
+
+#include <linux/device.h>
+
#ifdef __KERNEL__

#include <asm/hp300hw.h>

+typedef __u16 dio_id;
+
+ /*
+ * DIO devices
+ */
+
+struct dio_dev {
+ struct dio_bus *bus;
+ dio_id id;
+ int scode;
+ struct dio_driver *driver; /* which driver has allocated this device */
+ struct device dev; /* Generic device interface */
+ u8 ipl;
+ char name[64];
+ struct resource resource;
+};
+
+#define to_dio_dev(n) container_of(n, struct dio_dev, dev)
+
+ /*
+ * DIO bus
+ */
+
+struct dio_bus {
+ struct list_head devices; /* list of devices on this bus */
+ unsigned int num_resources; /* number of resources */
+ struct resource resources[2]; /* address space routed to this bus */
+ struct device dev;
+ char name[10];
+};
+
+extern struct dio_bus dio_bus; /* Single DIO bus */
+extern struct bus_type dio_bus_type;
+
+ /*
+ * DIO device IDs
+ */
+
+struct dio_device_id {
+ dio_id id; /* Device ID or DIO_WILDCARD */
+ unsigned long driver_data; /* Data private to the driver */
+};
+
+ /*
+ * DIO device drivers
+ */
+
+struct dio_driver {
+ struct list_head node;
+ char *name;
+ const struct dio_device_id *id_table; /* NULL if wants all devices */
+ int (*probe)(struct dio_dev *z, const struct dio_device_id *id);
+/* New device inserted */
+ void (*remove)(struct dio_dev *z); /* Device removed (NULL if not a hot-plug capable driver) */
+ struct device_driver driver;
+};
+
+#define to_dio_driver(drv) container_of(drv, struct dio_driver, driver)
+
/* DIO/DIO-II boards all have the following 8bit registers.
* These are offsets from the base of the device.
*/
-#define DIO_IDOFF 0x01 /* primary device ID */
-#define DIO_IPLOFF 0x03 /* interrupt priority level */
-#define DIO_SECIDOFF 0x15 /* secondary device ID */
-#define DIOII_SIZEOFF 0x101 /* device size, DIO-II only */
-#define DIO_VIRADDRBASE 0xf0000000UL /* vir addr where IOspace is mapped */
+#define DIO_IDOFF 0x01 /* primary device ID */
+#define DIO_IPLOFF 0x03 /* interrupt priority level */
+#define DIO_SECIDOFF 0x15 /* secondary device ID */
+#define DIOII_SIZEOFF 0x101 /* device size, DIO-II only */
+#define DIO_VIRADDRBASE 0xf0000000UL /* vir addr where IOspace is mapped */

#define DIO_BASE 0x600000 /* start of DIO space */
#define DIO_END 0x1000000 /* end of DIO space */
@@ -79,6 +142,7 @@
#define DIO_ENCODE_ID(pr,sec) ((((int)sec & 0xff) << 8) | ((int)pr & 0xff))
/* macro to determine whether a given primary ID requires a secondary ID byte */
#define DIO_NEEDSSECID(id) ((id) == DIO_ID_FBUFFER)
+#define DIO_WILDCARD 0xff

/* Now a whole slew of macros giving device IDs and descriptive strings: */
#define DIO_ID_DCA0 0x02 /* 98644A serial */
@@ -99,14 +163,14 @@
#define DIO_DESC_FHPIB "98625A/98625B fast HPIB"
#define DIO_ID_NHPIB 0x01 /* 98624A HP-IB (normal ie slow) */
#define DIO_DESC_NHPIB "98624A HPIB"
-#define DIO_ID_SCSI0 0x07 /* 98625A SCSI */
-#define DIO_DESC_SCSI0 "98625A SCSI0"
+#define DIO_ID_SCSI0 0x07 /* 98265A SCSI */
+#define DIO_DESC_SCSI0 "98265A SCSI0"
#define DIO_ID_SCSI1 0x27 /* ditto */
-#define DIO_DESC_SCSI1 "98625A SCSI1"
+#define DIO_DESC_SCSI1 "98265A SCSI1"
#define DIO_ID_SCSI2 0x47 /* ditto */
-#define DIO_DESC_SCSI2 "98625A SCSI2"
+#define DIO_DESC_SCSI2 "98265A SCSI2"
#define DIO_ID_SCSI3 0x67 /* ditto */
-#define DIO_DESC_SCSI3 "98625A SCSI3"
+#define DIO_DESC_SCSI3 "98265A SCSI3"
#define DIO_ID_FBUFFER 0x39 /* framebuffer: flavour is distinguished by secondary ID */
#define DIO_DESC_FBUFFER "bitmapped display"
/* the NetBSD kernel source is a bit unsure as to what these next IDs actually do :-> */
@@ -177,11 +241,72 @@

extern int dio_find(int deviceid);
extern unsigned long dio_scodetophysaddr(int scode);
-extern int dio_scodetoipl(int scode);
-extern const char *dio_scodetoname(int scode);
-extern void dio_config_board(int scode);
-extern void dio_unconfig_board(int scode);
+extern void dio_create_sysfs_dev_files(struct dio_dev *);
+
+/* New-style probing */
+extern int dio_register_driver(struct dio_driver *);
+extern void dio_unregister_driver(struct dio_driver *);
+extern const struct dio_device_id *dio_match_device(const struct dio_device_id *ids, const struct dio_dev *z);
+static inline struct dio_driver *dio_dev_driver(const struct dio_dev *d)
+{
+ return d->driver;
+}
+
+#define dio_resource_start(d) ((d)->resource.start)
+#define dio_resource_end(d) ((d)->resource.end)
+#define dio_resource_len(d) ((d)->resource.end-(z)->resource.start+1)
+#define dio_resource_flags(d) ((d)->resource.flags)
+
+#define dio_request_device(d, name) \
+ request_mem_region(dio_resource_start(d), dio_resource_len(d), name)
+#define dio_release_device(d) \
+ release_mem_region(dio_resource_start(d), dio_resource_len(d))
+
+/* Similar to the helpers above, these manipulate per-dio_dev
+ * driver-specific data. They are really just a wrapper around
+ * the generic device structure functions of these calls.
+ */
+static inline void *dio_get_drvdata (struct dio_dev *d)
+{
+ return dev_get_drvdata(&d->dev);
+}
+
+static inline void dio_set_drvdata (struct dio_dev *d, void *data)
+{
+ dev_set_drvdata(&d->dev, data);
+}
+
+/*
+ * A helper function which helps ensure correct dio_driver
+ * setup and cleanup for commonly-encountered hotplug/modular cases
+ *
+ * This MUST stay in a header, as it checks for -DMODULE
+ */
+static inline int dio_module_init(struct dio_driver *drv)
+{
+ int rc = dio_register_driver(drv);
+
+ if (rc > 0)
+ return 0;
+
+ /* iff CONFIG_HOTPLUG and built into kernel, we should
+ * leave the driver around for future hotplug events.
+ * For the module case, a hotplug daemon of some sort
+ * should load a module in response to an insert event. */
+#if defined(CONFIG_HOTPLUG) && !defined(MODULE)
+ if (rc == 0)
+ return 0;
+#else
+ if (rc == 0)
+ rc = -ENODEV;
+#endif
+
+ /* if we get here, we need to clean up DIO driver instance
+ * and return some sort of error */
+ dio_unregister_driver(drv);

+ return rc;
+}

#endif /* __KERNEL__ */
#endif /* ndef _LINUX_DIO_H */