From dfef928b1ca0fcd23d1c325793a9a85d79e81cdb Mon Sep 17 00:00:00 2001 From: Eivind Eklund Date: Sun, 13 Sep 1998 22:15:44 +0000 Subject: 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 --- sys/i386/isa/if_ed.c | 17 ++++---- sys/i386/isa/pnp.c | 115 +++++++++++++++++++++++++++++++++++++++++++++------ sys/i386/isa/pnp.h | 41 ++++++++++-------- sys/i386/isa/sio.c | 36 ++++++++-------- 4 files changed, 151 insertions(+), 58 deletions(-) (limited to 'sys/i386') 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 @@ -38,6 +38,13 @@ #include #include +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) @@ -177,6 +182,35 @@ pnp_get_serial(pnp_id *p) return valid; } +/* + * 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. @@ -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; } } -- cgit v1.2.3