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>
This commit is contained in:
Eivind Eklund 1998-09-13 22:15:44 +00:00
parent c7e4247c19
commit dfef928b1c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=39144
8 changed files with 199 additions and 117 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: pnpinfo.c,v 1.1.1.1 1997/09/19 15:36:00 jmg Exp $
* $Id: pnpinfo.c,v 1.2 1997/11/12 08:48:13 jmg Exp $
*/
#include <sys/time.h>
@ -51,6 +51,7 @@ pnp_write(int d, u_char r)
outb (_PNP_ADDRESS, d);
outb (_PNP_WRITE_DATA, r);
}
/* The READ_DATA port that we are using currently */
static int rd_port;
@ -488,19 +489,14 @@ dump_resdata(u_char *data, int csn)
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 @@ dump_resdata(u_char *data, int csn)
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);
}
}

View File

@ -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;
}
}

View File

@ -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 @@ LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
#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;
}
}

View File

@ -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;
}
}

View File

@ -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)
@ -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;
}

View File

@ -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 */

View File

@ -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 @@ LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
#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;
}
}

View File

@ -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 @@ LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
#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;
}
}