[PATCH 13/15] irda/nsc-ircc: Add ISAPNP support

From: Ben Collins
Date: Wed Jan 04 2006 - 17:01:38 EST


Author: Jean Tourrilhes <jt@xxxxxxxxxx>
Signed-off-by: Ben Collins <bcollins@xxxxxxxxxx>

---

drivers/net/irda/nsc-ircc.c | 102 +++++++++++++++++++++++++++++++++++++++++--
1 files changed, 98 insertions(+), 4 deletions(-)

7fd4a2788d8e81700779727795757252e92ea394
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index ee717d0..fe07bf9 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -12,6 +12,7 @@
* Copyright (c) 1998-2000 Dag Brattli <dagb@xxxxxxxxx>
* Copyright (c) 1998 Lichen Wang, <lwang@xxxxxxxxxxx>
* Copyright (c) 1998 Actisys Corp., www.actisys.com
+ * Copyright (c) 2000-2004 Jean Tourrilhes <jt@xxxxxxxxxx>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or
@@ -53,6 +54,7 @@
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
+#include <linux/pnp.h>

#include <asm/io.h>
#include <asm/dma.h>
@@ -87,6 +89,8 @@ static int nsc_ircc_probe_39x(nsc_chip_t
static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
+static int __devinit nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id);
+static void __devexit nsc_ircc_pnp_remove(struct pnp_dev * dev);

/* These are the known NSC chips */
static nsc_chip_t chips[] = {
@@ -126,8 +130,24 @@ static char *dongle_types[] = {
"No dongle connected",
};

+/* PNP probing */
+static const struct pnp_device_id nsc_ircc_pnp_table[] = {
+ { .id = "NSC6001", .driver_data = 0 },
+ { .id = "IBM0071", .driver_data = 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table);
+
+static struct pnp_driver nsc_ircc_pnp_driver = {
+ .name = "nsc-ircc",
+ .id_table = nsc_ircc_pnp_table,
+ .probe = nsc_ircc_pnp_probe,
+ .remove = __devexit_p(nsc_ircc_pnp_remove),
+};
+
/* Some prototypes */
-static int nsc_ircc_open(int i, chipio_t *info);
+static int nsc_ircc_open(chipio_t *info);
static int nsc_ircc_close(struct nsc_ircc_cb *self);
static int nsc_ircc_setup(chipio_t *info);
static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
@@ -148,6 +168,9 @@ static int nsc_ircc_net_ioctl(struct ne
static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);

+/* Globals */
+static int pnp_registered_port;
+
/*
* Function nsc_ircc_init ()
*
@@ -163,6 +186,14 @@ static int __init nsc_ircc_init(void)
int cfg, id;
int reg;
int i = 0;
+ int r;
+
+ /* Register with PnP subsystem to detect disable ports */
+ r = pnp_register_driver(&nsc_ircc_pnp_driver);
+ if (r >= 0) {
+ pnp_registered_port = 1;
+ ret = 0;
+ }

/* Probe for all the NSC chipsets we know about */
for (chip=chips; chip->name ; chip++) {
@@ -204,7 +235,7 @@ static int __init nsc_ircc_init(void)
} else
chip->probe(chip, &info);

- if (nsc_ircc_open(i, &info) == 0)
+ if (nsc_ircc_open(&info) == 0)
ret = 0;
i++;
} else {
@@ -229,6 +260,9 @@ static void __exit nsc_ircc_cleanup(void

pm_unregister_all(nsc_ircc_pmproc);

+ if (pnp_registered_port)
+ pnp_unregister_driver(&nsc_ircc_pnp_driver);
+
for (i=0; i < 4; i++) {
if (dev_self[i])
nsc_ircc_close(dev_self[i]);
@@ -241,16 +275,26 @@ static void __exit nsc_ircc_cleanup(void
* Open driver instance
*
*/
-static int __init nsc_ircc_open(int i, chipio_t *info)
+static int __devinit nsc_ircc_open(chipio_t *info)
{
struct net_device *dev;
struct nsc_ircc_cb *self;
struct pm_dev *pmdev;
void *ret;
int err;
+ int i;

IRDA_DEBUG(2, "%s()\n", __FUNCTION__);

+ for (i=0; i < 4; i++) {
+ if (!dev_self[i])
+ break;
+ }
+ if (i == 4) {
+ IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
info->cfg_base);

@@ -389,7 +433,7 @@ static int __init nsc_ircc_open(int i, c
* Close driver instance
*
*/
-static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
+static int __devexit nsc_ircc_close(struct nsc_ircc_cb *self)
{
int iobase;

@@ -806,6 +850,56 @@ static int nsc_ircc_probe_39x(nsc_chip_t
return 0;
}

+/* PNP probing */
+static int __devinit
+nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id)
+{
+ chipio_t info;
+
+ memset(&info, 0, sizeof(chipio_t));
+ info.irq = -1;
+ info.dma = -1;
+
+ /* There don't seem to be any way to get the cfg_base.
+ * On my box, cfg_base is in the PnP descriptor of the
+ * motherboard. Oh well... Jean II */
+
+ if (pnp_port_valid(dev, 0) &&
+ !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED))
+ info.fir_base = pnp_port_start(dev, 0);
+
+ if (pnp_irq_valid(dev, 0) &&
+ !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED))
+ info.irq = pnp_irq(dev, 0);
+
+ if (pnp_dma_valid(dev, 0) &&
+ !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED))
+ info.dma = pnp_dma(dev, 0);
+
+ IRDA_DEBUG(0, "%s() : Found cfg_base 0x%03X ; firbase 0x%03X ; irq %d ; dma %d.\n", __FUNCTION__, info.cfg_base, info.fir_base, info.irq, info.dma);
+
+ if(/*(info.cfg_base == 0) ||*/ (info.fir_base == 0) ||
+ (info.irq == -1) || (info.dma == -1)) {
+ /* Returning an error will disable the device. Yuck ! */
+ //return -EINVAL;
+ return 0;
+ }
+
+ /* We should identify and initialise the device */
+ if (nsc_ircc_open(&info) == 0)
+ pnp_set_drvdata(dev, (void *)1);
+
+ return 0;
+}
+
+static void __devexit
+nsc_ircc_pnp_remove(struct pnp_dev * dev)
+{
+ int index = (int)pnp_get_drvdata(dev);
+ if (index && dev_self[index - 1])
+ nsc_ircc_close(dev_self[index - 1]);
+}
+
/*
* Function nsc_ircc_setup (info)
*
--
1.0.5
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/