From owner-freebsd-bugs Sun Jun 21 17:32:38 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id RAA04734 for freebsd-bugs-outgoing; Sun, 21 Jun 1998 17:32:38 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from cesit1.unifi.it (cesit1.unifi.it [150.217.1.31]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id RAA04485; Sun, 21 Jun 1998 17:31:58 -0700 (PDT) (envelope-from ugo@dsi.UNIFI.IT) Received: from aguirre.dsi.unifi.it by CESIT1.UNIFI.IT (PMDF V5.1-10 #23168) with SMTP id <01IYIRKWXGFW0004VD@CESIT1.UNIFI.IT>; Mon, 22 Jun 1998 02:32:06 MET Received: from by aguirre.dsi.unifi.it (4.1/SMI-4.1) id AB11559; Sun, 21 Jun 1998 18:57:00 +0200 Received: from pegasus.home.net (pegasus.home.net [192.168.1.3]) by dsi.unifi.it (8.8.8/8.8.8) with ESMTP id UAA22538; Sun, 21 Jun 1998 20:53:21 +0200 (MET DST envelope-from ugo) Received: (from ugo@localhost) by pegasus.home.net (8.8.8/8.8.8) id UAA04546; Sun, 21 Jun 1998 20:53:21 +0200 (MET DST envelope-from ugo) Date: Sun, 21 Jun 1998 20:53:20 +0200 (MET DST) From: Ugo Paternostro Subject: Re: i386/6792: Backported PnP support for if_ed to -stable In-reply-to: <199805300040.RAA04094@freefall.freebsd.org> To: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG Cc: Eivind Eklund Message-id: Organization: Not an organization MIME-version: 1.0 X-Mailer: XFMail 1.2 [p0] on FreeBSD Content-type: multipart/mixed; boundary="_=XFMail.1.2.p0.FreeBSD:980621205320:4538=_" X-Priority: 3 (Normal) Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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 #include @@ -85,6 +86,20 @@ #include #include +#if NPNP > 0 +#include +#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 +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 #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 #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