Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 1998 20:53:20 +0200 (MET DST)
From:      Ugo Paternostro <paterno@dsi.UNIFI.IT>
To:        FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG
Cc:        Eivind Eklund <eivind@FreeBSD.ORG>
Subject:   Re: i386/6792: Backported PnP support for if_ed to -stable
Message-ID:  <XFMail.980621205320.paterno@dsi.unifi.it>
In-Reply-To: <199805300040.RAA04094@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This message is in MIME format
--_=XFMail.1.2.p0.FreeBSD:980621205320:4538=_
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Please discard the original patch included in the PR and commit the attached
one that implements Compatible Device ID scanning.

Please note that devices probe functions now return:

- a NULL if the ID wasn't recognized;
- a pointer to a null string if the ID was recognized, but the LDN was disabled;
- a pointer to a non null string otherwise.

This is to avoid multiple "CSN xxx is disabled" messages at boot time.

Someone else has to supply the Compatible Device IDs for internal PnP modems,
as I don't have one now.

Bye, UP


--_=XFMail.1.2.p0.FreeBSD:980621205320:4538=_
Content-Disposition: attachment; filename="pnp.diffs"
Content-Transfer-Encoding: 7bit
Content-Description: pnp.diffs
Content-Type: text/plain; charset=us-ascii; name=pnp.diffs; SizeOnDisk=16327

Index: src/contrib/pnpinfo/pnpinfo.c
===================================================================
RCS file: /home/ncvs/src/contrib/pnpinfo/pnpinfo.c,v
retrieving revision 1.2
diff -u -r1.2 pnpinfo.c
--- pnpinfo.c	1997/11/12 08:48:13	1.2
+++ pnpinfo.c	1998/06/12 14:21:26
@@ -51,6 +51,7 @@
     outb (_PNP_ADDRESS, d);
     outb (_PNP_WRITE_DATA, r);
 }
+
 /* The READ_DATA port that we are using currently */
 static int rd_port;
 
@@ -487,20 +488,15 @@
     for (i = 0; i < 1024; i++) {
 	if (!get_resource_info(&tag, 1))
 	    break;
-
-#define TYPE	(tag >> 7)
-#define	S_ITEM	(tag >> 3)
-#define S_LEN	(tag & 0x7)
-#define	L_ITEM	(tag & 0x7f)
 
-	if (TYPE == 0) {
+	if (PNP_RES_TYPE(tag) == 0) {
 	    /* Handle small resouce data types */
 
-	    resinfo = malloc(S_LEN);
-	    if (!get_resource_info(resinfo, S_LEN))
+	    resinfo = malloc(PNP_SRES_LEN(tag));
+	    if (!get_resource_info(resinfo, PNP_SRES_LEN(tag)))
 		break;
 
-	    if (handle_small_res(resinfo, S_ITEM, S_LEN) == 1)
+	    if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1)
 		break;
 	    free(resinfo);
 	} else {
@@ -513,7 +509,7 @@
 	    if (!get_resource_info(resinfo, large_len))
 		break;
 
-	    handle_large_res(resinfo, L_ITEM, large_len);
+	    handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len);
 	    free(resinfo);
 	}
     }
Index: src/sys/i386/isa/if_ed.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/if_ed.c,v
retrieving revision 1.107.2.7
diff -u -r1.107.2.7 if_ed.c
--- if_ed.c	1998/04/18 23:25:05	1.107.2.7
+++ if_ed.c	1998/06/17 12:27:19
@@ -39,6 +39,7 @@
 
 #include "ed.h"
 #include "bpfilter.h"
+#include "pnp.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -85,6 +86,20 @@
 #include <i386/isa/icu.h>
 #include <i386/isa/if_edreg.h>
 
+#if NPNP > 0
+#include <i386/isa/pnp.h>
+#endif /* NPNP > 0 */
+
+#ifndef EXTRA_ED
+# if NPNP > 0
+#  define EXTRA_ED MAX_PNP_CARDS
+# else
+#  define EXTRA_ED 0
+# endif
+#endif
+
+#define NEDTOT (NED + EXTRA_ED)
+
 /*
  * ed_softc: per line info and status
  */
@@ -137,7 +152,7 @@
 	struct	ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */
 };
 
-static struct ed_softc ed_softc[NED];
+static struct ed_softc ed_softc[NEDTOT];
 
 static int ed_attach		__P((struct ed_softc *, int, int));
 static int ed_attach_isa	__P((struct isa_device *));
@@ -227,7 +242,7 @@
 	struct ed_softc *sc = &ed_softc[devi->isahd.id_unit];
 
 	/* validate unit number. */
-	if (devi->isahd.id_unit >= NED)
+	if (devi->isahd.id_unit >= NEDTOT)
 		return(ENODEV);
 	/*
 	 * Probe the device. If a value is returned, the
@@ -3415,3 +3430,92 @@
 		ETHER_NEXT_MULTI(step, enm);
 	}
 }
+
+/*
+ * support PnP cards if we are using 'em
+ */ 
+    
+#if NPNP > 0 
+    
+static drvpnp_id edpnp_ids[] = {
+	{ 0x1980635e, "WSC8019"},
+	{ 0xd680d041, "NE2000 Compatible"},
+	{ 0 }
+};
+
+static char *edpnp_probe(u_long csn, u_long vend_id);
+static void edpnp_attach(u_long csn, u_long vend_id, char *name,
+	struct isa_device *dev);
+static u_long nedpnp = NED;
+
+static struct pnp_device edpnp = {
+	"edpnp",
+	edpnp_probe,
+	edpnp_attach,
+	&nedpnp,
+	&net_imask
+};
+DATA_SET (pnpdevice_set, edpnp);
+
+static char *
+edpnp_probe(u_long csn, u_long vend_id)
+{
+	drvpnp_id *id;
+	char *s = NULL;
+
+	for(id = edpnp_ids; id->vend_id != 0; id++) {
+		if (vend_id == id->vend_id) {
+			s = id->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 "";
+		}
+
+	}
+
+	return (s);
+}
+
+static void
+edpnp_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 >= NEDTOT)
+		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 = edintr;
+	dev->id_drq = -1;
+
+	if (dev->id_driver == NULL) {
+		dev->id_driver = &eddriver;
+		dvp = find_isadev(isa_devtab_net, &eddriver, 0);
+		if (dvp != NULL)
+			dev->id_id = dvp->id_id;
+	}
+
+	if ((dev->id_alive = ed_probe(dev)) != 0)
+		ed_attach_isa(dev);
+	else
+		printf("ed%d: probe failed\n", dev->id_unit);
+}
+#endif
Index: src/sys/i386/isa/pnp.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/pnp.c,v
retrieving revision 1.4.2.2
diff -u -r1.4.2.2 pnp.c
--- pnp.c	1998/01/10 15:13:04	1.4.2.2
+++ pnp.c	1998/06/21 18:43:26
@@ -41,8 +41,16 @@
 #endif
 #include <i386/isa/icu.h>
 
+typedef struct _pnp_id {
+    u_long vendor_id;
+    u_long serial;
+    u_char checksum;
+    u_long comp_id;
+} pnp_id;
+
 int num_pnp_cards = 0;
 pnp_id pnp_devices[MAX_PNP_CARDS];
+
 /*
  * these entries are initialized using the autoconfig menu
  * The struct is invalid (and must be initialized) if the first
@@ -51,15 +59,18 @@
  */
 
 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 ;
 static int current_pnp_serial ;
 
+/* The READ_DATA port that we are using currently */
+static int pnp_rd_port;
+
 /*
  * the following block is an example on what is needed for
  * a PnP device driver.
@@ -91,16 +102,17 @@
 {
     return;
 }
-
-/* The READ_DATA port that we are using currently */
-static int pnp_rd_port;
 
-void pnp_send_Initiation_LFSR (void);
-int pnp_get_serial (pnp_id *p);
-void config_pnp_device (pnp_id *p, int csn);
-int pnp_isolation_protocol (void);
-void pnp_write(int d, u_char r);
-u_char pnp_read(int d);
+/*
+ * Function prototypes
+ */
+static void pnp_send_Initiation_LFSR (void);
+static int pnp_get_serial(pnp_id *p);
+static int pnp_get_resource_info(u_char *buffer, int len);
+
+static void config_pnp_device(pnp_id *p, int csn);
+static int pnp_scan_resdata(pnp_id *p, int csn);
+static int pnp_isolation_protocol(void);
 
 void
 pnp_write(int d, u_char r)
@@ -120,7 +132,7 @@
  * Send Initiation LFSR as described in "Plug and Play ISA Specification",
  * Intel May 94.
  */
-void
+static void
 pnp_send_Initiation_LFSR()
 {
     int cur, i;
@@ -142,7 +154,7 @@
 /*
  * Get the device's serial number.  Returns 1 if the serial is valid.
  */
-int
+static int
 pnp_get_serial(pnp_id *p)
 {
     int i, bit, valid = 0, sum = 0x6a;
@@ -173,6 +185,35 @@
 }
 
 /*
+ * 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.
@@ -325,23 +366,27 @@
  *	4 bytes: board serial number (often 0 or -1 ?)
  */
 
-void
+static void
 config_pnp_device(pnp_id *p, int csn)
 {
     struct pnp_cinfo *ci;
     int i;
-    u_char *data = (u_char *)p;
+    u_char *data = (u_char *)p, *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%08x] Serial 0x%08x\n",
+    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);
+	    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 ;
@@ -378,11 +423,13 @@
     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) ||
+		((!name || !*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 ) ; */
@@ -425,7 +472,53 @@
     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_i
nfo(NULL, large_len)))
+		scanning = 0;
+    }
+
+    return retval;
+}
+
 /*
  * Run the isolation protocol. Use pnp_rd_port as the READ_DATA port
  * value (caller should try multiple READ_DATA locations before giving
@@ -436,7 +529,7 @@
  * are saved to an array, pnp_devices. In the second pass, each
  * card is woken up and the device configuration is called.
  */
-int
+static int
 pnp_isolation_protocol()
 {
     int csn;
@@ -455,6 +548,8 @@
 	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;
     }
Index: src/sys/i386/isa/pnp.h
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/pnp.h,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 pnp.h
--- pnp.h	1998/01/10 15:13:12	1.5.2.2
+++ pnp.h	1998/06/17 23:04:47
@@ -211,6 +211,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
@@ -273,26 +279,27 @@
     u_int *imask ;
     struct isa_device dev ;
 };
-
-struct _pnp_id {
-    u_long vendor_id;
-    u_long serial;
-    u_char checksum;
-} ;
 
-typedef struct _pnp_id pnp_id;
-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 _drvpnp_id {
+	u_long vend_id; /* Not anly a Vendor ID, also a Compatible Device ID */
+	char *id_str;
+} drvpnp_id;
+
+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
Index: src/sys/i386/isa/sio.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/isa/sio.c,v
retrieving revision 1.147.2.16
diff -u -r1.147.2.16 sio.c
--- sio.c	1998/06/16 12:51:17	1.147.2.16
+++ sio.c	1998/06/21 15:58:32
@@ -40,16 +40,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.
@@ -98,6 +88,16 @@
 #include <i386/isa/pnp.h>
 #endif
 
+#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	RB_I_HIGH_WATER	(TTYHOG - 2 * RS_IBUFSIZE)
 #define	RS_IBUFSIZE	256
@@ -2691,12 +2691,10 @@
 
 #if NPNP > 0
 
-static struct siopnp_ids {
-	u_long vend_id;
-	char *id_str;
-} siopnp_ids[] = {
+static drvpnp_id siopnp_ids[] = {
 	{ 0x8113b04e, "Supra1381"},
 	{ 0x9012b04e, "Supra1290"},
+	{ 0x7121b04e, "SupraExpress 56i Sp"},
 	{ 0x11007256, "USR0011"},
 	{ 0 }
 };
@@ -2718,12 +2716,12 @@
 static char *
 siopnp_probe(u_long csn, u_long vend_id)
 {
-	struct siopnp_ids *ids;
+	drvpnp_id *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;
 		}
 	}
@@ -2733,7 +2731,7 @@
 		read_pnp_parms(&d, 0);
 		if (d.enable == 0 || d.flags & 1) {
 			printf("CSN %d is disabled.\n", csn);
-			return (NULL);
+			return "";
 		}
 
 	}
Index: src/sys/pc98/pc98/sio.c
===================================================================
RCS file: /home/ncvs/src/sys/pc98/pc98/sio.c,v
retrieving revision 1.8.2.19
diff -u -r1.8.2.19 sio.c
--- sio.c	1998/06/18 07:55:14	1.8.2.19
+++ sio.c	1998/06/21 15:59:12
@@ -40,16 +40,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.
@@ -176,6 +166,16 @@
 #include <i386/isa/pnp.h>
 #endif
 
+#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	RB_I_HIGH_WATER	(TTYHOG - 2 * RS_IBUFSIZE)
 #define	RS_IBUFSIZE	256
@@ -3427,10 +3427,7 @@
 
 #if NPNP > 0
 
-static struct siopnp_ids {
-	u_long vend_id;
-	char *id_str;
-} siopnp_ids[] = {
+static drvpnp_id siopnp_ids[] = {
 	{ 0x8113b04e, "Supra1381"},
 	{ 0x9012b04e, "Supra1290"},
 	{ 0x11007256, "USR0011"},
@@ -3454,12 +3451,12 @@
 static char *
 siopnp_probe(u_long csn, u_long vend_id)
 {
-	struct siopnp_ids *ids;
+	drvpnp_id *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_id; id->vend_id != 0; id++) {
+		if (vend_id == id->vend_id) {
+			s = id->id_str;
 			break;
 		}
 	}
@@ -3469,7 +3466,7 @@
 		read_pnp_parms(&d, 0);
 		if (d.enable == 0 || d.flags & 1) {
 			printf("CSN %d is disabled.\n", csn);
-			return (NULL);
+			return "";
 		}
 
 	}

--_=XFMail.1.2.p0.FreeBSD:980621205320:4538=_--
End of MIME message

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.980621205320.paterno>