aboutsummaryrefslogtreecommitdiff
path: root/sys/i386
diff options
context:
space:
mode:
authorEivind Eklund <eivind@FreeBSD.org>1998-09-13 22:15:44 +0000
committerEivind Eklund <eivind@FreeBSD.org>1998-09-13 22:15:44 +0000
commitdfef928b1ca0fcd23d1c325793a9a85d79e81cdb (patch)
treebda45ec386582a0e35ab6db4b5e0ac26b884583d /sys/i386
parentc7e4247c191bd392a152c960f6de9493e14919c2 (diff)
downloadsrc-dfef928b1ca0fcd23d1c325793a9a85d79e81cdb.tar.gz
src-dfef928b1ca0fcd23d1c325793a9a85d79e81cdb.zip
Support PnP compatibility IDs. This allow e.g. the ed driver to pick
up any PnP NE2000 compatible card, instead of forcing us to always update ID lists. Submitted by: Ugo Paternostro <paterno@dsi.unifi.it>
Notes
Notes: svn path=/head/; revision=39144
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/isa/if_ed.c17
-rw-r--r--sys/i386/isa/pnp.c115
-rw-r--r--sys/i386/isa/pnp.h41
-rw-r--r--sys/i386/isa/sio.c36
4 files changed, 151 insertions, 58 deletions
diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c
index 8f4bfcbbca8c..0fed19a15526 100644
--- a/sys/i386/isa/if_ed.c
+++ b/sys/i386/isa/if_ed.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: if_ed.c,v 1.143 1998/06/21 18:02:35 bde Exp $
+ * $Id: if_ed.c,v 1.144 1998/08/24 02:28:15 bde Exp $
*/
/*
@@ -3401,11 +3401,8 @@ ds_getmcaf(sc, mcaf)
#if NPNP > 0
-static struct edpnp_ids {
- u_long vend_id;
- char *id_str;
-} edpnp_ids[] = {
- { 0x1980635e, "WSC8019"},
+static pnpid_t edpnp_ids[] = {
+ { 0xd680d041, "NE2000"},
{ 0 }
};
@@ -3426,12 +3423,12 @@ DATA_SET (pnpdevice_set, edpnp);
static char *
edpnp_probe(u_long csn, u_long vend_id)
{
- struct edpnp_ids *ids;
+ pnpid_t *id;
char *s = NULL;
- for(ids = edpnp_ids; ids->vend_id != 0; ids++) {
- if (vend_id == ids->vend_id) {
- s = ids->id_str;
+ for(id = edpnp_ids; id->vend_id != 0; id++) {
+ if (vend_id == id->vend_id) {
+ s = id->id_str;
break;
}
}
diff --git a/sys/i386/isa/pnp.c b/sys/i386/isa/pnp.c
index 3bc63ed4b3c6..9b4bb5563374 100644
--- a/sys/i386/isa/pnp.c
+++ b/sys/i386/isa/pnp.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pnp.c,v 1.4 1997/11/18 11:45:26 bde Exp $
+ * $Id: pnp.c,v 1.5 1998/02/09 06:08:38 eivind Exp $
*/
#include <sys/param.h>
@@ -38,6 +38,13 @@
#include <i386/isa/isa_device.h>
#include <i386/isa/pnp.h>
+typedef struct _pnp_id {
+ u_long vendor_id;
+ u_long serial;
+ u_char checksum;
+ u_long comp_id;
+} pnp_id;
+
static int num_pnp_cards = 0;
pnp_id pnp_devices[MAX_PNP_CARDS];
struct pnp_dlist_node *pnp_device_list;
@@ -51,10 +58,10 @@ static struct pnp_dlist_node **pnp_device_list_last_ptr;
*/
struct pnp_cinfo pnp_ldn_overrides[MAX_PNP_LDN] = { { 0 } };
+
/*
* the following is a flag which tells if the data is valid.
*/
-
static int doing_pnp_probe = 0 ;
static int current_csn ;
static int current_pnp_id ;
@@ -100,12 +107,10 @@ nullpnp_attach(u_long csn, u_long vend_id, char *name,
/* The READ_DATA port that we are using currently */
static int pnp_rd_port;
-static void pnp_send_Initiation_LFSR (void);
-static int pnp_get_serial (pnp_id *p);
-static void config_pnp_device (pnp_id *p, int csn);
-static int pnp_isolation_protocol (void);
-void pnp_write(int d, u_char r);
-u_char pnp_read(int d);
+static void pnp_send_Initiation_LFSR (void);
+static int pnp_get_serial (pnp_id *p);
+static void config_pnp_device (pnp_id *p, int csn);
+static int pnp_isolation_protocol (void);
void
pnp_write(int d, u_char r)
@@ -178,6 +183,35 @@ pnp_get_serial(pnp_id *p)
}
/*
+ * Fill's the buffer with resource info from the device.
+ * Returns 0 if the device fails to report
+ */
+static int
+pnp_get_resource_info(u_char *buffer, int len)
+{
+ int i, j;
+ u_char temp;
+
+ for (i = 0; i < len; i++) {
+ outb(_PNP_ADDRESS, STATUS);
+ for (j = 0; j < 100; j++) {
+ if ((inb((pnp_rd_port << 2) | 0x3)) & 0x1)
+ break;
+ DELAY(1);
+ }
+ if (j == 100) {
+ printf("PnP device failed to report resource data\n");
+ return 0;
+ }
+ outb(_PNP_ADDRESS, RESOURCE_DATA);
+ temp = inb((pnp_rd_port << 2) | 0x3);
+ if (buffer != NULL)
+ buffer[i] = temp;
+ }
+ return 1;
+}
+
+/*
* read_pnp_parms loads pnp parameters from the currently selected
* device into the struct pnp_cinfo parameter passed.
* The second argument specifies the Logical Device to use.
@@ -335,15 +369,22 @@ config_pnp_device(pnp_id *p, int csn)
static struct pnp_dlist_node *nod = NULL;
int i;
u_char *data = (u_char *)p;
+ u_char *comp = (u_char *)&p->comp_id;
/* these are for autoconfigure a-la pci */
struct pnp_device *dvp, **dvpp;
char *name ;
- printf("CSN %d Vendor ID: %c%c%c%02x%02x [0x%08lx] Serial 0x%08lx\n", csn,
+ printf("CSN %d Vendor ID: %c%c%c%02x%02x [0x%08x] Serial 0x%08x Comp ID: %c%c%c%02x%02x [0x%08x]\n",
+ csn,
((data[0] & 0x7c) >> 2) + '@',
(((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + '@',
- (data[1] & 0x1f) + '@', data[2], data[3], p->vendor_id, p->serial);
+ (data[1] & 0x1f) + '@', data[2], data[3],
+ p->vendor_id, p->serial,
+ ((comp[0] & 0x7c) >> 2) + '@',
+ (((comp[0] & 0x03) << 3) | ((comp[1] & 0xe0) >> 5)) + '@',
+ (comp[1] & 0x1f) + '@', comp[2], comp[3],
+ p->comp_id);
doing_pnp_probe = 1 ;
current_csn = csn ;
@@ -382,11 +423,13 @@ config_pnp_device(pnp_id *p, int csn)
dvpp = (struct pnp_device **)pnpdevice_set.ls_items;
while ((dvp = *dvpp++)) {
if (dvp->pd_probe) {
- if ((name = (*dvp->pd_probe)(csn, p->vendor_id)))
+ if ( ((name = (*dvp->pd_probe)(csn, p->vendor_id)) && *name) ||
+ (p->comp_id &&
+ (name = (*dvp->pd_probe)(csn, p->comp_id))))
break;
}
}
- if (dvp && name && dvp->pd_count) { /* found a matching device */
+ if (dvp && name && *name && dvp->pd_count) { /* found a matching device */
int unit ;
/* pnpcb->pnpcb_seen |= ( 1ul << csn ) ; */
@@ -467,6 +510,52 @@ config_pnp_device(pnp_id *p, int csn)
doing_pnp_probe = 0 ;
}
+/*
+ * Scan Resource Data for Compatible Device ID.
+ *
+ * This function exits as soon as it gets a Compatible Device ID, an error
+ * reading *ANY* Resource Data or ir reaches the end of Resource Data.
+ * In the first case the return value will be TRUE, FALSE otherwise.
+ */
+static int
+pnp_scan_resdata(pnp_id *p, int csn)
+{
+ u_char tag, resinfo[8];
+ int large_len, scanning = 1024, retval = FALSE;
+
+ while (scanning-- > 0 && pnp_get_resource_info(&tag, 1)) {
+ if (PNP_RES_TYPE(tag) == 0) {
+ /* Small resource */
+ switch (PNP_SRES_NUM(tag)) {
+ case COMP_DEVICE_ID:
+ /* Got a compatible device id resource */
+ if (pnp_get_resource_info(resinfo, PNP_SRES_LEN(tag))) {
+ bcopy(resinfo, &p->comp_id, 4);
+ retval = TRUE;
+ if (bootverbose)
+ printf("PnP: CSN %d COMP_DEVICE_ID = 0x%08x\n", csn, p->comp_id);
+ }
+ /*
+ * We found what we were looking for, or got an error from
+ * pnp_get_resource, => stop scanning (FALLTHROUGH)
+ */
+ case END_TAG:
+ scanning = 0;
+ break;
+ default:
+ /* Skip this resource */
+ if (pnp_get_resource_info(NULL, PNP_SRES_LEN(tag)) == 0)
+ scanning = 0;
+ break;
+ }
+ } else
+ /* Large resource, skip it */
+ if (!(pnp_get_resource_info((u_char *)&large_len, 2) && pnp_get_resource_info(NULL, large_len)))
+ scanning = 0;
+ }
+
+ return retval;
+}
/*
* Run the isolation protocol. Use pnp_rd_port as the READ_DATA port
@@ -497,6 +586,8 @@ pnp_isolation_protocol()
if (pnp_get_serial( &(pnp_devices[csn-1]) ) ) {
pnp_write(SET_CSN, csn);
/* pnp_write(CONFIG_CONTROL, 2); */
+ if (!pnp_scan_resdata(&(pnp_devices[csn-1]), csn))
+ pnp_devices[csn-1].comp_id = NULL;
} else
break;
}
diff --git a/sys/i386/isa/pnp.h b/sys/i386/isa/pnp.h
index 3cc56cc871ba..bb29685129b5 100644
--- a/sys/i386/isa/pnp.h
+++ b/sys/i386/isa/pnp.h
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pnp.h,v 1.5 1997/11/18 11:47:04 bde Exp $
+ * $Id: pnp.h,v 1.6 1998/01/10 07:41:43 kato Exp $
*/
#ifndef _I386_ISA_PNP_H_
@@ -210,6 +210,12 @@
/*** 32-bit memory accesses are at 0x76 ***/
+/* Macros to parse Resource IDs */
+#define PNP_RES_TYPE(a) (a >> 7)
+#define PNP_SRES_NUM(a) (a >> 3)
+#define PNP_SRES_LEN(a) (a & 0x07)
+#define PNP_LRES_NUM(a) (a & 0x7f)
+
/* Small Resource Item names */
#define PNP_VERSION 0x1
#define LOG_DEVICE_ID 0x2
@@ -270,36 +276,37 @@ struct pnp_device {
u_int *imask ;
};
-struct _pnp_id {
- u_long vendor_id;
- u_long serial;
- u_char checksum;
-} ;
-
struct pnp_dlist_node {
struct pnp_device *pnp;
struct isa_device dev;
struct pnp_dlist_node *next;
};
-typedef struct _pnp_id pnp_id;
-extern struct pnp_dlist_node *pnp_device_list;
-extern pnp_id pnp_devices[MAX_PNP_CARDS];
+/*
+ * Used by userconfig
+ */
extern struct pnp_cinfo pnp_ldn_overrides[MAX_PNP_LDN];
-extern int pnp_overrides_valid;
-
-extern struct linker_set pnpdevice_set;
/*
- * these two functions are for use in drivers
+ * The following definitions are for use in drivers
*/
-int read_pnp_parms(struct pnp_cinfo *d, int ldn);
-int write_pnp_parms(struct pnp_cinfo *d, int ldn);
-int enable_pnp_card(void);
+extern struct linker_set pnpdevice_set;
+
+typedef struct _pnpid_t {
+ u_long vend_id; /* Not anly a Vendor ID, also a Compatible Device ID */
+ char *id_str;
+} pnpid_t;
+
+void pnp_write(int d, u_char r); /* used by Luigi's sound driver */
+u_char pnp_read(int d); /* currently unused, but who knows... */
+int read_pnp_parms(struct pnp_cinfo *d, int ldn);
+int write_pnp_parms(struct pnp_cinfo *d, int ldn);
+int enable_pnp_card(void);
/*
* used by autoconfigure to actually probe and attach drivers
*/
+extern struct pnp_dlist_node *pnp_device_list;
void pnp_configure __P((void));
#endif /* KERNEL */
diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c
index 4602e540fc55..b0ad5fc67eea 100644
--- a/sys/i386/isa/sio.c
+++ b/sys/i386/isa/sio.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
- * $Id: sio.c,v 1.213 1998/08/23 08:26:40 bde Exp $
+ * $Id: sio.c,v 1.214 1998/08/23 10:16:26 bde Exp $
*/
#include "opt_comconsole.h"
@@ -42,16 +42,6 @@
#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.
* Mostly rewritten to use pseudo-DMA.
@@ -106,6 +96,16 @@
#define enable_intr() COM_ENABLE_INTR()
#endif /* SMP */
+#ifndef EXTRA_SIO
+#if NPNP > 0
+#define EXTRA_SIO MAX_PNP_CARDS
+#else
+#define EXTRA_SIO 0
+#endif
+#endif
+
+#define NSIOTOT (NSIO + EXTRA_SIO)
+
#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
#define RS_IBUFSIZE 256
@@ -2950,13 +2950,11 @@ error:
#if NPNP > 0
-static struct siopnp_ids {
- u_long vend_id;
- char *id_str;
-} siopnp_ids[] = {
+static pnpid_t siopnp_ids[] = {
{ 0x5015f435, "MOT1550"},
{ 0x8113b04e, "Supra1381"},
{ 0x9012b04e, "Supra1290"},
+ { 0x7121b04e, "SupraExpress 56i Sp"},
{ 0x11007256, "USR0011"},
{ 0x30207256, "USR2030"},
{ 0 }
@@ -2979,12 +2977,12 @@ DATA_SET (pnpdevice_set, siopnp);
static char *
siopnp_probe(u_long csn, u_long vend_id)
{
- struct siopnp_ids *ids;
+ pnpid_t *id;
char *s = NULL;
- for(ids = siopnp_ids; ids->vend_id != 0; ids++) {
- if (vend_id == ids->vend_id) {
- s = ids->id_str;
+ for(id = siopnp_ids; id->vend_id != 0; id++) {
+ if (vend_id == id->vend_id) {
+ s = id->id_str;
break;
}
}