aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn-Mark Gurney <jmg@FreeBSD.org>1997-09-19 15:25:49 +0000
committerJohn-Mark Gurney <jmg@FreeBSD.org>1997-09-19 15:25:49 +0000
commit6a796ce0a15c7fbf2b936b9859e4869cfd6c228c (patch)
treee1d8d866dedc47bfc4ca5c02fc6192a26bf120d9
parent77509afdf34774f22c3e0dca52fefa2c656237c7 (diff)
downloadsrc-6a796ce0a15c7fbf2b936b9859e4869cfd6c228c.tar.gz
src-6a796ce0a15c7fbf2b936b9859e4869cfd6c228c.zip
teach sio how to attach to isa PnP cards. This is mainly for use with
internal modems. Currently detects a USR modem, and a couple Supra modems... vendor id's for sio capabile cards welcomed... document new option EXTRA_SIO that will increase sio's internal data structures to support X more serial ports... these are used by the PnP part of sio for attaching... If you don't have it specified, it will default to 2... This is defaulted to 0 if you don't have PnP compiled into your kernel... also document that if you set the PnP flags (pnp x flags y) to 0x1 that the modem will be refused to be recognized by the sio driver... this is for people that want the traditional isa driver to probe and attach the modem... (for keeping legacy sio numbering)
Notes
Notes: svn path=/head/; revision=29614
-rw-r--r--sys/conf/NOTES7
-rw-r--r--sys/conf/options.i3863
-rw-r--r--sys/dev/sio/sio.c135
-rw-r--r--sys/i386/conf/LINT7
-rw-r--r--sys/i386/conf/NOTES7
-rw-r--r--sys/i386/conf/options.i3863
-rw-r--r--sys/i386/isa/sio.c135
-rw-r--r--sys/isa/sio.c135
8 files changed, 388 insertions, 44 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index a75c0a148ac7..4e09a864e913 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.365 1997/09/14 21:45:01 jmg Exp $
+# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -860,6 +860,10 @@ device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr
# higher priority console). This replaces the COMCONSOLE option.
# 0x40 reserve this unit for low level console operations. Do not
#
+# PnP `flags' (set via userconfig using pnp x flags y)
+# 0x1 disable probing of this device. Used to prevent your modem
+# from being attached as a PnP modem.
+#
# Options for serial drivers that support consoles (only for sio now):
options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to
@@ -870,6 +874,7 @@ options CONSPEED=9600 #default speed for serial console (default 9600)
options COM_ESP #code for Hayes ESP
options COM_MULTIPORT #code for some cards with shared IRQs
options DSI_SOFT_MODEM #code for DSI Softmodems
+options "EXTRA_SIO=2" #number of extra sio ports to allocate
# Other flags for sio that aren't documented in the man page.
# 0x20000 enable hardware RTS/CTS and larger FIFOs. Only works for
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index f696dfafb796..44e71d0670c3 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -1,4 +1,4 @@
-# $Id: options.i386,v 1.58 1997/09/04 23:03:11 yokota Exp $
+# $Id: options.i386,v 1.59 1997/09/16 07:45:33 joerg Exp $
BOUNCEPAGES opt_bounce.h
USER_LDT
@@ -23,6 +23,7 @@ CONUNIT opt_defunct.h
COM_ESP opt_sio.h
COM_MULTIPORT opt_sio.h
DSI_SOFT_MODEM opt_sio.h
+EXTRA_SIO opt_sio.h
I586_CTR_GUPROF opt_i586_guprof.h
I586_PMC_GUPROF opt_i586_guprof.h
FAT_CURSOR opt_pcvt.h
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index d7bebbbb59b9..37d8ecdaafae 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -31,13 +31,24 @@
* SUCH DAMAGE.
*
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
- * $Id: sio.c,v 1.180 1997/09/01 07:45:28 fsmp Exp $
+ * $Id: sio.c,v 1.181 1997/09/14 03:19:23 peter Exp $
*/
#include "opt_comconsole.h"
#include "opt_ddb.h"
#include "opt_sio.h"
#include "sio.h"
+#include "pnp.h"
+
+#ifndef EXTRA_SIO
+#if NPNP > 0
+#define EXTRA_SIO 2
+#else
+#define EXTRA_SIO 0
+#endif
+#endif
+
+#define NSIOTOT (NSIO + EXTRA_SIO)
/*
* Serial driver, based on 386BSD-0.1 com driver.
@@ -83,6 +94,10 @@
#include <pccard/slot.h>
#endif
+#if NPNP > 0
+#include <i386/isa/pnp.h>
+#endif
+
#ifdef SMP
#define disable_intr() COM_DISABLE_INTR()
#define enable_intr() COM_ENABLE_INTR()
@@ -329,7 +344,7 @@ static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr
static char driver_name[] = "sio";
/* table and macro for fast conversion from a unit number to its com struct */
-static struct com_s *p_com_addr[NSIO];
+static struct com_s *p_com_addr[NSIOTOT];
#define com_addr(unit) (p_com_addr[unit])
struct isa_driver siodriver = {
@@ -359,11 +374,11 @@ static Port_t siocniobase;
static int sio_timeout;
static int sio_timeouts_until_log;
#if 0 /* XXX */
-static struct tty *sio_tty[NSIO];
+static struct tty *sio_tty[NSIOTOT];
#else
-static struct tty sio_tty[NSIO];
+static struct tty sio_tty[NSIOTOT];
#endif
-static const int nsio_tty = NSIO;
+static const int nsio_tty = NSIOTOT;
static struct speedtab comspeedtab[] = {
{ 0, 0 },
@@ -498,7 +513,7 @@ sioinit(struct pccard_dev *dp, int first)
/* validate unit number. */
if (first) {
- if (dp->isahd.id_unit >= NSIO)
+ if (dp->isahd.id_unit >= (NSIOTOT))
return(ENODEV);
/* Make sure it isn't already probed. */
if (com_addr(dp->isahd.id_unit))
@@ -1075,7 +1090,7 @@ sioopen(dev, flag, mode, p)
mynor = minor(dev);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
+ if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL)
return (ENXIO);
if (com->gone)
return (ENXIO);
@@ -1441,7 +1456,7 @@ siointr(unit)
COM_LOCK();
do {
possibly_more_intrs = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
/*
* XXX COM_LOCK();
@@ -1817,7 +1832,7 @@ siopoll()
if (com_events == 0)
return;
repeat:
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
u_char *buf;
struct com_s *com;
u_char *ibuf;
@@ -2322,7 +2337,7 @@ siodevtotty(dev)
if (mynor & CONTROL_MASK)
return (NULL);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO)
+ if ((u_int) unit >= NSIOTOT)
return (NULL);
return (&sio_tty[unit]);
}
@@ -2398,7 +2413,7 @@ siosettimeout()
untimeout(comwakeup, (void *)NULL);
sio_timeout = hz;
someopen = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && com->tp != NULL
&& com->tp->t_state & TS_ISOPEN && !com->gone) {
@@ -2433,7 +2448,7 @@ comwakeup(chan)
* Recover from lost output interrupts.
* Poll any lines that don't use interrupts.
*/
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && !com->gone
&& (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
@@ -2449,7 +2464,7 @@ comwakeup(chan)
if (--sio_timeouts_until_log > 0)
return;
sio_timeouts_until_log = hz / sio_timeout;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
int errnum;
com = com_addr(unit);
@@ -2873,3 +2888,97 @@ error:
return EIO;
}
#endif /* DSI_SOFT_MODEM */
+
+/*
+ * support PnP cards if we are using 'em
+ */
+
+#if NPNP > 0
+
+static struct siopnp_ids {
+ u_long vend_id;
+ char *id_str;
+} siopnp_ids[] = {
+ { 0x8113b04e, "Supra1381"},
+ { 0x9012b04e, "Supra1290"},
+ { 0x11007256, "USR0011"},
+ { 0 }
+};
+
+static char *siopnp_probe(u_long csn, u_long vend_id);
+static void siopnp_attach(u_long csn, u_long vend_id, char *name,
+ struct isa_device *dev);
+static u_long nsiopnp = NSIO;
+
+static struct pnp_device siopnp = {
+ "siopnp",
+ siopnp_probe,
+ siopnp_attach,
+ &nsiopnp,
+ &tty_imask
+};
+DATA_SET (pnpdevice_set, siopnp);
+
+static char *
+siopnp_probe(u_long csn, u_long vend_id)
+{
+ struct siopnp_ids *ids;
+ char *s = NULL;
+
+ for(ids = siopnp_ids; ids->vend_id != 0; ids++) {
+ if (vend_id == ids->vend_id) {
+ s = ids->id_str;
+ break;
+ }
+ }
+
+ if (s) {
+ struct pnp_cinfo d;
+ read_pnp_parms(&d, 0);
+ if (d.enable == 0 || d.flags & 1) {
+ printf("CSN %d is disabled.\n", csn);
+ return (NULL);
+ }
+
+ }
+
+ return (s);
+}
+
+static void
+siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
+{
+ struct pnp_cinfo d;
+ struct isa_device *dvp;
+
+ if (dev->id_unit >= NSIOTOT)
+ return;
+
+ if (read_pnp_parms(&d, 0) == 0) {
+ printf("failed to read pnp parms\n");
+ return;
+ }
+
+ write_pnp_parms(&d, 0);
+
+ enable_pnp_card();
+
+ dev->id_iobase = d.port[0];
+ dev->id_irq = (1 << d.irq[0]);
+ dev->id_intr = siointr;
+ dev->id_ri_flags = RI_FAST;
+ dev->id_drq = -1;
+
+ if (dev->id_driver == NULL) {
+ dev->id_driver = &siodriver;
+ dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
+ if (dvp != NULL)
+ dev->id_id = dvp->id_id;
+ }
+
+ if ((dev->id_alive = sioprobe(dev)) != 0)
+ sioattach(dev);
+ else
+ printf("sio%d: probe failed\n", dev->id_unit);
+}
+#endif
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index a75c0a148ac7..4e09a864e913 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.365 1997/09/14 21:45:01 jmg Exp $
+# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -860,6 +860,10 @@ device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr
# higher priority console). This replaces the COMCONSOLE option.
# 0x40 reserve this unit for low level console operations. Do not
#
+# PnP `flags' (set via userconfig using pnp x flags y)
+# 0x1 disable probing of this device. Used to prevent your modem
+# from being attached as a PnP modem.
+#
# Options for serial drivers that support consoles (only for sio now):
options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to
@@ -870,6 +874,7 @@ options CONSPEED=9600 #default speed for serial console (default 9600)
options COM_ESP #code for Hayes ESP
options COM_MULTIPORT #code for some cards with shared IRQs
options DSI_SOFT_MODEM #code for DSI Softmodems
+options "EXTRA_SIO=2" #number of extra sio ports to allocate
# Other flags for sio that aren't documented in the man page.
# 0x20000 enable hardware RTS/CTS and larger FIFOs. Only works for
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index a75c0a148ac7..4e09a864e913 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.365 1997/09/14 21:45:01 jmg Exp $
+# $Id: LINT,v 1.366 1997/09/16 07:45:31 joerg Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -860,6 +860,10 @@ device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr
# higher priority console). This replaces the COMCONSOLE option.
# 0x40 reserve this unit for low level console operations. Do not
#
+# PnP `flags' (set via userconfig using pnp x flags y)
+# 0x1 disable probing of this device. Used to prevent your modem
+# from being attached as a PnP modem.
+#
# Options for serial drivers that support consoles (only for sio now):
options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to
@@ -870,6 +874,7 @@ options CONSPEED=9600 #default speed for serial console (default 9600)
options COM_ESP #code for Hayes ESP
options COM_MULTIPORT #code for some cards with shared IRQs
options DSI_SOFT_MODEM #code for DSI Softmodems
+options "EXTRA_SIO=2" #number of extra sio ports to allocate
# Other flags for sio that aren't documented in the man page.
# 0x20000 enable hardware RTS/CTS and larger FIFOs. Only works for
diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386
index f696dfafb796..44e71d0670c3 100644
--- a/sys/i386/conf/options.i386
+++ b/sys/i386/conf/options.i386
@@ -1,4 +1,4 @@
-# $Id: options.i386,v 1.58 1997/09/04 23:03:11 yokota Exp $
+# $Id: options.i386,v 1.59 1997/09/16 07:45:33 joerg Exp $
BOUNCEPAGES opt_bounce.h
USER_LDT
@@ -23,6 +23,7 @@ CONUNIT opt_defunct.h
COM_ESP opt_sio.h
COM_MULTIPORT opt_sio.h
DSI_SOFT_MODEM opt_sio.h
+EXTRA_SIO opt_sio.h
I586_CTR_GUPROF opt_i586_guprof.h
I586_PMC_GUPROF opt_i586_guprof.h
FAT_CURSOR opt_pcvt.h
diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c
index d7bebbbb59b9..37d8ecdaafae 100644
--- a/sys/i386/isa/sio.c
+++ b/sys/i386/isa/sio.c
@@ -31,13 +31,24 @@
* SUCH DAMAGE.
*
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
- * $Id: sio.c,v 1.180 1997/09/01 07:45:28 fsmp Exp $
+ * $Id: sio.c,v 1.181 1997/09/14 03:19:23 peter Exp $
*/
#include "opt_comconsole.h"
#include "opt_ddb.h"
#include "opt_sio.h"
#include "sio.h"
+#include "pnp.h"
+
+#ifndef EXTRA_SIO
+#if NPNP > 0
+#define EXTRA_SIO 2
+#else
+#define EXTRA_SIO 0
+#endif
+#endif
+
+#define NSIOTOT (NSIO + EXTRA_SIO)
/*
* Serial driver, based on 386BSD-0.1 com driver.
@@ -83,6 +94,10 @@
#include <pccard/slot.h>
#endif
+#if NPNP > 0
+#include <i386/isa/pnp.h>
+#endif
+
#ifdef SMP
#define disable_intr() COM_DISABLE_INTR()
#define enable_intr() COM_ENABLE_INTR()
@@ -329,7 +344,7 @@ static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr
static char driver_name[] = "sio";
/* table and macro for fast conversion from a unit number to its com struct */
-static struct com_s *p_com_addr[NSIO];
+static struct com_s *p_com_addr[NSIOTOT];
#define com_addr(unit) (p_com_addr[unit])
struct isa_driver siodriver = {
@@ -359,11 +374,11 @@ static Port_t siocniobase;
static int sio_timeout;
static int sio_timeouts_until_log;
#if 0 /* XXX */
-static struct tty *sio_tty[NSIO];
+static struct tty *sio_tty[NSIOTOT];
#else
-static struct tty sio_tty[NSIO];
+static struct tty sio_tty[NSIOTOT];
#endif
-static const int nsio_tty = NSIO;
+static const int nsio_tty = NSIOTOT;
static struct speedtab comspeedtab[] = {
{ 0, 0 },
@@ -498,7 +513,7 @@ sioinit(struct pccard_dev *dp, int first)
/* validate unit number. */
if (first) {
- if (dp->isahd.id_unit >= NSIO)
+ if (dp->isahd.id_unit >= (NSIOTOT))
return(ENODEV);
/* Make sure it isn't already probed. */
if (com_addr(dp->isahd.id_unit))
@@ -1075,7 +1090,7 @@ sioopen(dev, flag, mode, p)
mynor = minor(dev);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
+ if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL)
return (ENXIO);
if (com->gone)
return (ENXIO);
@@ -1441,7 +1456,7 @@ siointr(unit)
COM_LOCK();
do {
possibly_more_intrs = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
/*
* XXX COM_LOCK();
@@ -1817,7 +1832,7 @@ siopoll()
if (com_events == 0)
return;
repeat:
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
u_char *buf;
struct com_s *com;
u_char *ibuf;
@@ -2322,7 +2337,7 @@ siodevtotty(dev)
if (mynor & CONTROL_MASK)
return (NULL);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO)
+ if ((u_int) unit >= NSIOTOT)
return (NULL);
return (&sio_tty[unit]);
}
@@ -2398,7 +2413,7 @@ siosettimeout()
untimeout(comwakeup, (void *)NULL);
sio_timeout = hz;
someopen = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && com->tp != NULL
&& com->tp->t_state & TS_ISOPEN && !com->gone) {
@@ -2433,7 +2448,7 @@ comwakeup(chan)
* Recover from lost output interrupts.
* Poll any lines that don't use interrupts.
*/
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && !com->gone
&& (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
@@ -2449,7 +2464,7 @@ comwakeup(chan)
if (--sio_timeouts_until_log > 0)
return;
sio_timeouts_until_log = hz / sio_timeout;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
int errnum;
com = com_addr(unit);
@@ -2873,3 +2888,97 @@ error:
return EIO;
}
#endif /* DSI_SOFT_MODEM */
+
+/*
+ * support PnP cards if we are using 'em
+ */
+
+#if NPNP > 0
+
+static struct siopnp_ids {
+ u_long vend_id;
+ char *id_str;
+} siopnp_ids[] = {
+ { 0x8113b04e, "Supra1381"},
+ { 0x9012b04e, "Supra1290"},
+ { 0x11007256, "USR0011"},
+ { 0 }
+};
+
+static char *siopnp_probe(u_long csn, u_long vend_id);
+static void siopnp_attach(u_long csn, u_long vend_id, char *name,
+ struct isa_device *dev);
+static u_long nsiopnp = NSIO;
+
+static struct pnp_device siopnp = {
+ "siopnp",
+ siopnp_probe,
+ siopnp_attach,
+ &nsiopnp,
+ &tty_imask
+};
+DATA_SET (pnpdevice_set, siopnp);
+
+static char *
+siopnp_probe(u_long csn, u_long vend_id)
+{
+ struct siopnp_ids *ids;
+ char *s = NULL;
+
+ for(ids = siopnp_ids; ids->vend_id != 0; ids++) {
+ if (vend_id == ids->vend_id) {
+ s = ids->id_str;
+ break;
+ }
+ }
+
+ if (s) {
+ struct pnp_cinfo d;
+ read_pnp_parms(&d, 0);
+ if (d.enable == 0 || d.flags & 1) {
+ printf("CSN %d is disabled.\n", csn);
+ return (NULL);
+ }
+
+ }
+
+ return (s);
+}
+
+static void
+siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
+{
+ struct pnp_cinfo d;
+ struct isa_device *dvp;
+
+ if (dev->id_unit >= NSIOTOT)
+ return;
+
+ if (read_pnp_parms(&d, 0) == 0) {
+ printf("failed to read pnp parms\n");
+ return;
+ }
+
+ write_pnp_parms(&d, 0);
+
+ enable_pnp_card();
+
+ dev->id_iobase = d.port[0];
+ dev->id_irq = (1 << d.irq[0]);
+ dev->id_intr = siointr;
+ dev->id_ri_flags = RI_FAST;
+ dev->id_drq = -1;
+
+ if (dev->id_driver == NULL) {
+ dev->id_driver = &siodriver;
+ dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
+ if (dvp != NULL)
+ dev->id_id = dvp->id_id;
+ }
+
+ if ((dev->id_alive = sioprobe(dev)) != 0)
+ sioattach(dev);
+ else
+ printf("sio%d: probe failed\n", dev->id_unit);
+}
+#endif
diff --git a/sys/isa/sio.c b/sys/isa/sio.c
index d7bebbbb59b9..37d8ecdaafae 100644
--- a/sys/isa/sio.c
+++ b/sys/isa/sio.c
@@ -31,13 +31,24 @@
* SUCH DAMAGE.
*
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
- * $Id: sio.c,v 1.180 1997/09/01 07:45:28 fsmp Exp $
+ * $Id: sio.c,v 1.181 1997/09/14 03:19:23 peter Exp $
*/
#include "opt_comconsole.h"
#include "opt_ddb.h"
#include "opt_sio.h"
#include "sio.h"
+#include "pnp.h"
+
+#ifndef EXTRA_SIO
+#if NPNP > 0
+#define EXTRA_SIO 2
+#else
+#define EXTRA_SIO 0
+#endif
+#endif
+
+#define NSIOTOT (NSIO + EXTRA_SIO)
/*
* Serial driver, based on 386BSD-0.1 com driver.
@@ -83,6 +94,10 @@
#include <pccard/slot.h>
#endif
+#if NPNP > 0
+#include <i386/isa/pnp.h>
+#endif
+
#ifdef SMP
#define disable_intr() COM_DISABLE_INTR()
#define enable_intr() COM_ENABLE_INTR()
@@ -329,7 +344,7 @@ static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr
static char driver_name[] = "sio";
/* table and macro for fast conversion from a unit number to its com struct */
-static struct com_s *p_com_addr[NSIO];
+static struct com_s *p_com_addr[NSIOTOT];
#define com_addr(unit) (p_com_addr[unit])
struct isa_driver siodriver = {
@@ -359,11 +374,11 @@ static Port_t siocniobase;
static int sio_timeout;
static int sio_timeouts_until_log;
#if 0 /* XXX */
-static struct tty *sio_tty[NSIO];
+static struct tty *sio_tty[NSIOTOT];
#else
-static struct tty sio_tty[NSIO];
+static struct tty sio_tty[NSIOTOT];
#endif
-static const int nsio_tty = NSIO;
+static const int nsio_tty = NSIOTOT;
static struct speedtab comspeedtab[] = {
{ 0, 0 },
@@ -498,7 +513,7 @@ sioinit(struct pccard_dev *dp, int first)
/* validate unit number. */
if (first) {
- if (dp->isahd.id_unit >= NSIO)
+ if (dp->isahd.id_unit >= (NSIOTOT))
return(ENODEV);
/* Make sure it isn't already probed. */
if (com_addr(dp->isahd.id_unit))
@@ -1075,7 +1090,7 @@ sioopen(dev, flag, mode, p)
mynor = minor(dev);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL)
+ if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL)
return (ENXIO);
if (com->gone)
return (ENXIO);
@@ -1441,7 +1456,7 @@ siointr(unit)
COM_LOCK();
do {
possibly_more_intrs = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
/*
* XXX COM_LOCK();
@@ -1817,7 +1832,7 @@ siopoll()
if (com_events == 0)
return;
repeat:
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
u_char *buf;
struct com_s *com;
u_char *ibuf;
@@ -2322,7 +2337,7 @@ siodevtotty(dev)
if (mynor & CONTROL_MASK)
return (NULL);
unit = MINOR_TO_UNIT(mynor);
- if ((u_int) unit >= NSIO)
+ if ((u_int) unit >= NSIOTOT)
return (NULL);
return (&sio_tty[unit]);
}
@@ -2398,7 +2413,7 @@ siosettimeout()
untimeout(comwakeup, (void *)NULL);
sio_timeout = hz;
someopen = FALSE;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && com->tp != NULL
&& com->tp->t_state & TS_ISOPEN && !com->gone) {
@@ -2433,7 +2448,7 @@ comwakeup(chan)
* Recover from lost output interrupts.
* Poll any lines that don't use interrupts.
*/
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
com = com_addr(unit);
if (com != NULL && !com->gone
&& (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
@@ -2449,7 +2464,7 @@ comwakeup(chan)
if (--sio_timeouts_until_log > 0)
return;
sio_timeouts_until_log = hz / sio_timeout;
- for (unit = 0; unit < NSIO; ++unit) {
+ for (unit = 0; unit < NSIOTOT; ++unit) {
int errnum;
com = com_addr(unit);
@@ -2873,3 +2888,97 @@ error:
return EIO;
}
#endif /* DSI_SOFT_MODEM */
+
+/*
+ * support PnP cards if we are using 'em
+ */
+
+#if NPNP > 0
+
+static struct siopnp_ids {
+ u_long vend_id;
+ char *id_str;
+} siopnp_ids[] = {
+ { 0x8113b04e, "Supra1381"},
+ { 0x9012b04e, "Supra1290"},
+ { 0x11007256, "USR0011"},
+ { 0 }
+};
+
+static char *siopnp_probe(u_long csn, u_long vend_id);
+static void siopnp_attach(u_long csn, u_long vend_id, char *name,
+ struct isa_device *dev);
+static u_long nsiopnp = NSIO;
+
+static struct pnp_device siopnp = {
+ "siopnp",
+ siopnp_probe,
+ siopnp_attach,
+ &nsiopnp,
+ &tty_imask
+};
+DATA_SET (pnpdevice_set, siopnp);
+
+static char *
+siopnp_probe(u_long csn, u_long vend_id)
+{
+ struct siopnp_ids *ids;
+ char *s = NULL;
+
+ for(ids = siopnp_ids; ids->vend_id != 0; ids++) {
+ if (vend_id == ids->vend_id) {
+ s = ids->id_str;
+ break;
+ }
+ }
+
+ if (s) {
+ struct pnp_cinfo d;
+ read_pnp_parms(&d, 0);
+ if (d.enable == 0 || d.flags & 1) {
+ printf("CSN %d is disabled.\n", csn);
+ return (NULL);
+ }
+
+ }
+
+ return (s);
+}
+
+static void
+siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
+{
+ struct pnp_cinfo d;
+ struct isa_device *dvp;
+
+ if (dev->id_unit >= NSIOTOT)
+ return;
+
+ if (read_pnp_parms(&d, 0) == 0) {
+ printf("failed to read pnp parms\n");
+ return;
+ }
+
+ write_pnp_parms(&d, 0);
+
+ enable_pnp_card();
+
+ dev->id_iobase = d.port[0];
+ dev->id_irq = (1 << d.irq[0]);
+ dev->id_intr = siointr;
+ dev->id_ri_flags = RI_FAST;
+ dev->id_drq = -1;
+
+ if (dev->id_driver == NULL) {
+ dev->id_driver = &siodriver;
+ dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
+ if (dvp != NULL)
+ dev->id_id = dvp->id_id;
+ }
+
+ if ((dev->id_alive = sioprobe(dev)) != 0)
+ sioattach(dev);
+ else
+ printf("sio%d: probe failed\n", dev->id_unit);
+}
+#endif