Make ISA PnP work. This successfully enumerates as many ISA devices as I
can fit into my test machine. - Move to using STAILQs rather than ad-hoc singly-linked lists. - Use a mostly procedural interface to the PnP information. This improves data-hiding. Implement a new linker-set technique (currently on i386 only but should work on Alpha as well). This is a good candidate for replacing the current gensetdefs cruft completely.
This commit is contained in:
parent
7a3f627463
commit
eddbe21def
@ -23,10 +23,11 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: bootstrap.h,v 1.12 1998/10/09 07:09:22 msmith Exp $
|
||||
* $Id: bootstrap.h,v 1.13 1998/10/09 23:11:05 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
/* XXX debugging */
|
||||
extern struct console vidconsole;
|
||||
@ -94,33 +95,36 @@ extern void cons_probe(void);
|
||||
/*
|
||||
* Plug-and-play enumerator/configurator interface.
|
||||
*/
|
||||
struct pnpident
|
||||
{
|
||||
char *id_ident; /* ASCII identifier, actual format varies with bus/handler */
|
||||
struct pnpident *id_next; /* the next identifier */
|
||||
};
|
||||
|
||||
struct pnphandler;
|
||||
struct pnpinfo
|
||||
{
|
||||
struct pnpident *pi_ident; /* list of identifiers */
|
||||
int pi_revision; /* optional revision (or -1) if not supported */
|
||||
char *pi_module; /* module/args nominated to handle device */
|
||||
int pi_argc; /* module arguments */
|
||||
char **pi_argv;
|
||||
struct pnphandler *pi_handler; /* handler which detected this device */
|
||||
struct pnpinfo *pi_next;
|
||||
};
|
||||
|
||||
struct pnphandler
|
||||
{
|
||||
char *pp_name; /* handler/bus name */
|
||||
void (* pp_enumerate)(struct pnpinfo **); /* add detected devices to chain */
|
||||
char *pp_name; /* handler/bus name */
|
||||
void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */
|
||||
};
|
||||
|
||||
struct pnpident
|
||||
{
|
||||
char *id_ident; /* ASCII identifier, actual format varies with bus/handler */
|
||||
STAILQ_ENTRY(pnpident) id_link;
|
||||
};
|
||||
|
||||
struct pnpinfo
|
||||
{
|
||||
char *pi_desc; /* ASCII description, optional */
|
||||
int pi_revision; /* optional revision (or -1) if not supported */
|
||||
char *pi_module; /* module/args nominated to handle device */
|
||||
int pi_argc; /* module arguments */
|
||||
char **pi_argv;
|
||||
struct pnphandler *pi_handler; /* handler which detected this device */
|
||||
STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */
|
||||
STAILQ_ENTRY(pnpinfo) pi_link;
|
||||
};
|
||||
|
||||
extern struct pnphandler *pnphandlers[]; /* provided by MD code */
|
||||
|
||||
extern void pnp_addident(struct pnpinfo *pi, char *ident);
|
||||
extern struct pnpinfo *pnp_allocinfo(void);
|
||||
extern void pnp_freeinfo(struct pnpinfo *pi);
|
||||
extern void pnp_addinfo(struct pnpinfo *pi);
|
||||
|
||||
/*
|
||||
* Module metadata header.
|
||||
@ -180,6 +184,7 @@ extern vm_offset_t aout_findsym(char *name, struct loaded_module *mp);
|
||||
|
||||
extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
|
||||
|
||||
#ifndef NEW_LINKER_SET
|
||||
#if defined(__ELF__)
|
||||
|
||||
/*
|
||||
@ -232,6 +237,50 @@ struct linker_set {
|
||||
const void *ls_items[1]; /* really ls_length of them, trailing NULL */
|
||||
};
|
||||
|
||||
/* XXX just for conversion's sake, until we move to the new linker set code */
|
||||
|
||||
#define SET_FOREACH(pvar, set) \
|
||||
for (pvar = set.ls_items; \
|
||||
pvar < set.ls_items + set.ls_length; \
|
||||
pvar++)
|
||||
|
||||
#else /* NEW_LINKER_SET */
|
||||
|
||||
/*
|
||||
* Private macros, not to be used outside this header file.
|
||||
*/
|
||||
#define __MAKE_SET(set, sym) \
|
||||
static void *__CONCAT(__setentry,__LINE__) \
|
||||
__attribute__((__section__("set_" #set),__unused__)) = &sym
|
||||
#define __SET_BEGIN(set) \
|
||||
({ extern void *__CONCAT(__start_set_,set); \
|
||||
&__CONCAT(__start_set_,set); })
|
||||
#define __SET_END(set) \
|
||||
({ extern void *__CONCAT(__stop_set_,set); \
|
||||
&__CONCAT(__stop_set_,set); })
|
||||
|
||||
/*
|
||||
* Public macros.
|
||||
*/
|
||||
|
||||
/* Add an entry to a set. */
|
||||
#define TEXT_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define DATA_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define BSS_SET(set, sym) __MAKE_SET(set, sym)
|
||||
#define ABS_SET(set, sym) __MAKE_SET(set, sym)
|
||||
|
||||
/*
|
||||
* Iterate over all the elements of a set.
|
||||
*
|
||||
* Sets always contain addresses of things, and "pvar" points to words
|
||||
* containing those addresses. Thus is must be declared as "type **pvar",
|
||||
* and the address of each set item is obtained inside the loop by "*pvar".
|
||||
*/
|
||||
#define SET_FOREACH(pvar, set) \
|
||||
for (pvar = (__typeof__(pvar))__SET_BEGIN(set); \
|
||||
pvar < (__typeof__(pvar))__SET_END(set); pvar++)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Support for commands
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: commands.c,v 1.4 1998/10/07 02:38:26 msmith Exp $
|
||||
* $Id: commands.c,v 1.5 1998/10/09 07:09:22 msmith Exp $
|
||||
*/
|
||||
|
||||
#include <stand.h>
|
||||
@ -59,10 +59,10 @@ command_commandlist(int argc, char *argv[])
|
||||
int i;
|
||||
|
||||
printf("Available commands:\n");
|
||||
cmdp = (struct bootblk_command **)Xcommand_set.ls_items;
|
||||
for (i = 0; i < Xcommand_set.ls_length; i++)
|
||||
if ((cmdp[i]->c_name != NULL) && (cmdp[i]->c_desc != NULL))
|
||||
printf(" %-15s %s\n", cmdp[i]->c_name, cmdp[i]->c_desc);
|
||||
SET_FOREACH(cmdp, Xcommand_set) {
|
||||
if (((*cmdp)->c_name != NULL) && ((*cmdp)->c_desc != NULL))
|
||||
printf(" %-15s %s\n", (*cmdp)->c_name, (*cmdp)->c_desc);
|
||||
}
|
||||
return(CMD_OK);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: interp.c,v 1.5 1998/10/07 02:38:26 msmith Exp $
|
||||
* $Id: interp.c,v 1.6 1998/10/09 07:09:22 msmith Exp $
|
||||
*/
|
||||
/*
|
||||
* Simple commandline interpreter, toplevel and misc.
|
||||
@ -58,10 +58,10 @@ perform(int argc, char *argv[])
|
||||
cmd = NULL;
|
||||
result = CMD_ERROR;
|
||||
|
||||
cmdp = (struct bootblk_command **)Xcommand_set.ls_items;
|
||||
for (i = 0; i < Xcommand_set.ls_length; i++) {
|
||||
if ((cmdp[i]->c_name != NULL) && !strcmp(argv[0], cmdp[i]->c_name))
|
||||
cmd = cmdp[i]->c_fn;
|
||||
/* search the command set for the command */
|
||||
SET_FOREACH(cmdp, Xcommand_set) {
|
||||
if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name))
|
||||
cmd = (*cmdp)->c_fn;
|
||||
}
|
||||
if (cmd != NULL) {
|
||||
result = (cmd)(argc, argv);
|
||||
|
@ -24,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: isapnp.c,v 1.1 1998/09/18 00:24:25 msmith Exp $
|
||||
* $Id: isapnp.c,v 1.2 1998/09/26 01:29:13 msmith Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -43,8 +43,8 @@ static void isapnp_write(int d, u_char r);
|
||||
static u_char isapnp_read(int d);
|
||||
static void isapnp_send_Initiation_LFSR();
|
||||
static int isapnp_get_serial(u_int8_t *p);
|
||||
static int isapnp_isolation_protocol(struct pnpinfo **pnplist);
|
||||
static void isapnp_enumerate(struct pnpinfo **pnplist);
|
||||
static int isapnp_isolation_protocol(void);
|
||||
static void isapnp_enumerate(void);
|
||||
|
||||
/* PnP read data port */
|
||||
static int pnp_rd_port;
|
||||
@ -53,7 +53,7 @@ static int pnp_rd_port;
|
||||
|
||||
struct pnphandler isapnphandler =
|
||||
{
|
||||
"isapnp",
|
||||
"ISA bus",
|
||||
isapnp_enumerate
|
||||
};
|
||||
|
||||
@ -143,61 +143,109 @@ isapnp_format(u_int8_t *data)
|
||||
idbuf[5] = hextoascii[(data[3] >> 4)];
|
||||
idbuf[6] = hextoascii[(data[3] & 0xf)];
|
||||
idbuf[7] = 0;
|
||||
return(idbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to read a compatible device ID from the current device, return
|
||||
* 1 if we found one.
|
||||
* Fills the buffer with resource info from the device.
|
||||
* Returns nonzero if the device fails to report
|
||||
*/
|
||||
#define READ_RSC(c) {while ((isapnp_read(STATUS) & 1) == 0); (c) = isapnp_read(RESOURCE_DATA);}
|
||||
static int
|
||||
isapnp_getid(u_int8_t *data)
|
||||
isapnp_get_resource_info(u_int8_t *buffer, int len)
|
||||
{
|
||||
int discard, pos, len;
|
||||
u_int8_t c, t;
|
||||
|
||||
discard = 0;
|
||||
len = 0;
|
||||
pos = 0;
|
||||
|
||||
for (;;) {
|
||||
READ_RSC(c);
|
||||
/* skipping junk? */
|
||||
if (discard > 0) {
|
||||
discard--;
|
||||
continue;
|
||||
}
|
||||
/* copying data? */
|
||||
if (len > 0) {
|
||||
data[pos++] = c;
|
||||
/* got all data? */
|
||||
if (pos >= len)
|
||||
return(1);
|
||||
}
|
||||
/* resource type */
|
||||
if (c & 0x80) { /* large resource, throw it away */
|
||||
if (c == 0xff)
|
||||
return(0); /* end of resources */
|
||||
READ_RSC(c);
|
||||
discard = c;
|
||||
READ_RSC(c);
|
||||
discard += ((int)c << 8);
|
||||
continue;
|
||||
}
|
||||
/* small resource */
|
||||
t = (c >> 3) & 0xf;
|
||||
if (t == 0xf)
|
||||
return(0); /* end of resources */
|
||||
if ((t == LOG_DEVICE_ID) || (t == COMP_DEVICE_ID)) {
|
||||
len = c & 7;
|
||||
pos = 0;
|
||||
continue;
|
||||
}
|
||||
discard = c & 7; /* unwanted small resource */
|
||||
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(1);
|
||||
}
|
||||
outb(_PNP_ADDRESS, RESOURCE_DATA);
|
||||
temp = inb((pnp_rd_port << 2) | 0x3);
|
||||
if (buffer != NULL)
|
||||
buffer[i] = temp;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan Resource Data for useful information.
|
||||
*
|
||||
* We scan the resource data for compatible device IDs and
|
||||
* identifier strings; we only take the first identifier string
|
||||
* and assume it's for the card as a whole.
|
||||
*
|
||||
* Returns 0 if the scan completed OK, nonzero on error.
|
||||
*/
|
||||
static int
|
||||
isapnp_scan_resdata(struct pnpinfo *pi)
|
||||
{
|
||||
u_char tag, resinfo[8];
|
||||
int large_len, limit;
|
||||
char *str;
|
||||
|
||||
limit = 1000;
|
||||
while ((limit-- > 0) && !isapnp_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 (isapnp_get_resource_info(resinfo, PNP_SRES_LEN(tag)))
|
||||
return(1);
|
||||
pnp_addident(pi, isapnp_format(resinfo));
|
||||
|
||||
case END_TAG:
|
||||
return(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Skip this resource */
|
||||
if (isapnp_get_resource_info(NULL, PNP_SRES_LEN(tag)))
|
||||
return(1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Large resource */
|
||||
if (isapnp_get_resource_info(resinfo, 2))
|
||||
return(1);
|
||||
|
||||
large_len = resinfo[1];
|
||||
large_len = (large_len << 8) + resinfo[0];
|
||||
|
||||
switch(PNP_LRES_NUM(tag)) {
|
||||
|
||||
case ID_STRING_ANSI:
|
||||
str = malloc(large_len + 1);
|
||||
if (isapnp_get_resource_info(str, large_len)) {
|
||||
free(str);
|
||||
return(1);
|
||||
}
|
||||
str[large_len] = 0;
|
||||
if (pi->pi_desc == NULL) {
|
||||
pi->pi_desc = str;
|
||||
} else {
|
||||
free(str);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Large resource, skip it */
|
||||
if (isapnp_get_resource_info(NULL, large_len))
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the isolation protocol. Use pnp_rd_port as the READ_DATA port
|
||||
@ -206,7 +254,7 @@ isapnp_getid(u_int8_t *data)
|
||||
* pnp_rd_port as the READ_DATA port.
|
||||
*/
|
||||
static int
|
||||
isapnp_isolation_protocol(struct pnpinfo **pilist)
|
||||
isapnp_isolation_protocol(void)
|
||||
{
|
||||
int csn;
|
||||
struct pnpinfo *pi;
|
||||
@ -227,24 +275,26 @@ isapnp_isolation_protocol(struct pnpinfo **pilist)
|
||||
|
||||
if (isapnp_get_serial(cardid)) {
|
||||
isapnp_write(SET_CSN, csn);
|
||||
pi = malloc(sizeof(struct pnpinfo));
|
||||
pi->pi_next = *pilist;
|
||||
*pilist = pi;
|
||||
pi = pnp_allocinfo();
|
||||
ndevs++;
|
||||
pnp_addident(pi, isapnp_format(cardid));
|
||||
/* scan the card obtaining all the identifiers it holds */
|
||||
while (isapnp_getid(cardid)) {
|
||||
printf(" %s\n", isapnp_format(cardid));
|
||||
pnp_addident(pi, isapnp_format(cardid));
|
||||
if (isapnp_scan_resdata(pi)) {
|
||||
pnp_freeinfo(pi); /* error getting data, ignore */
|
||||
} else {
|
||||
pnp_addinfo(pi);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Move all cards to wait-for-key state */
|
||||
while (csn >= 0) {
|
||||
while (--csn > 0) {
|
||||
isapnp_send_Initiation_LFSR();
|
||||
isapnp_write(WAKE, csn);
|
||||
isapnp_write(CONFIG_CONTROL, 0x02);
|
||||
delay(1000); /* XXX is it really necessary ? */
|
||||
csn--;
|
||||
}
|
||||
return(ndevs);
|
||||
}
|
||||
@ -253,17 +303,16 @@ isapnp_isolation_protocol(struct pnpinfo **pilist)
|
||||
* Locate ISA-PnP devices and populate the supplied list.
|
||||
*/
|
||||
static void
|
||||
isapnp_enumerate(struct pnpinfo **pnplist)
|
||||
isapnp_enumerate(void)
|
||||
{
|
||||
int devs;
|
||||
|
||||
for (pnp_rd_port = 0x80; pnp_rd_port < 0xff; pnp_rd_port += 0x10) {
|
||||
|
||||
|
||||
/* Look for something, quit when we find it */
|
||||
if ((devs = isapnp_isolation_protocol(pnplist)) > 0)
|
||||
if ((devs = isapnp_isolation_protocol()) > 0)
|
||||
break;
|
||||
}
|
||||
printf("Found %d ISA PnP devices\n", devs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.6 1998/01/10 07:41:43 kato Exp $
|
||||
* $Id: isapnp.h,v 1.1 1998/09/18 00:24:25 msmith 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
|
||||
|
@ -13,9 +13,10 @@
|
||||
#include <string.h>
|
||||
#include <bootstrap.h>
|
||||
|
||||
static struct pnpinfo *pnp_devices = NULL;
|
||||
STAILQ_HEAD(,pnpinfo) pnp_devices;
|
||||
static int pnp_devices_initted = 0;
|
||||
|
||||
static void pnp_discard(struct pnpinfo **list);
|
||||
static void pnp_discard(void);
|
||||
static int pnp_readconf(char *path);
|
||||
static int pnp_scankernel(void);
|
||||
|
||||
@ -28,15 +29,55 @@ COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan);
|
||||
int
|
||||
pnp_scan(int argc, char *argv[])
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
int hdlr;
|
||||
int verbose;
|
||||
int ch;
|
||||
|
||||
if (pnp_devices_initted == 0) {
|
||||
STAILQ_INIT(&pnp_devices);
|
||||
pnp_devices_initted = 1;
|
||||
}
|
||||
|
||||
verbose = 0;
|
||||
optind = 1;
|
||||
while ((ch = getopt(argc, argv, "v")) != -1) {
|
||||
switch(ch) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
/* getopt has already reported an error */
|
||||
return(CMD_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* forget anything we think we knew */
|
||||
pnp_discard(&pnp_devices);
|
||||
pnp_discard();
|
||||
|
||||
if (verbose)
|
||||
pager_open();
|
||||
|
||||
/* iterate over all of the handlers */
|
||||
for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) {
|
||||
printf("Probing bus '%s'...\n", pnphandlers[hdlr]->pp_name);
|
||||
pnphandlers[hdlr]->pp_enumerate(&pnp_devices);
|
||||
if (verbose) {
|
||||
pager_output("Probing ");
|
||||
pager_output(pnphandlers[hdlr]->pp_name);
|
||||
pager_output("...\n");
|
||||
}
|
||||
pnphandlers[hdlr]->pp_enumerate();
|
||||
}
|
||||
if (verbose) {
|
||||
for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) {
|
||||
pager_output(pi->pi_ident.stqh_first->id_ident); /* first ident should be canonical */
|
||||
if (pi->pi_desc != NULL) {
|
||||
pager_output(" : ");
|
||||
pager_output(pi->pi_desc);
|
||||
pager_output("\n");
|
||||
}
|
||||
}
|
||||
pager_close();
|
||||
}
|
||||
return(CMD_OK);
|
||||
}
|
||||
@ -51,7 +92,7 @@ pnp_reload(char *fname)
|
||||
char *modfname;
|
||||
|
||||
/* find anything? */
|
||||
if (pnp_devices != NULL) {
|
||||
if (pnp_devices.stqh_first != NULL) {
|
||||
|
||||
/* check for kernel, assign modules handled by static drivers there */
|
||||
if (pnp_scankernel()) {
|
||||
@ -70,13 +111,13 @@ pnp_reload(char *fname)
|
||||
}
|
||||
|
||||
/* try to load any modules that have been nominated */
|
||||
for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) {
|
||||
for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) {
|
||||
/* Already loaded? */
|
||||
if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) {
|
||||
modfname = malloc(strlen(pi->pi_module + 3));
|
||||
sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */
|
||||
if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv))
|
||||
printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident->id_ident);
|
||||
printf("Could not load module '%s' for device '%s'\n", modfname, pi->pi_ident.stqh_first->id_ident);
|
||||
free(modfname);
|
||||
}
|
||||
}
|
||||
@ -88,24 +129,14 @@ pnp_reload(char *fname)
|
||||
* Throw away anything we think we know about PnP devices on (list)
|
||||
*/
|
||||
static void
|
||||
pnp_discard(struct pnpinfo **list)
|
||||
pnp_discard(void)
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
struct pnpident *id;
|
||||
|
||||
while (*list != NULL) {
|
||||
pi = *list;
|
||||
*list = (*list)->pi_next;
|
||||
while (pi->pi_ident) {
|
||||
id = pi->pi_ident;
|
||||
pi->pi_ident = pi->pi_ident->id_next;
|
||||
free(id);
|
||||
}
|
||||
if (pi->pi_module)
|
||||
free(pi->pi_module);
|
||||
if (pi->pi_argv)
|
||||
free(pi->pi_argv);
|
||||
free(pi);
|
||||
|
||||
while (pnp_devices.stqh_first != NULL) {
|
||||
pi = pnp_devices.stqh_first;
|
||||
STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
|
||||
pnp_freeinfo(pi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,14 +257,14 @@ pnp_readconf(char *path)
|
||||
* assigned.
|
||||
* XXX no revision parse/test here yet.
|
||||
*/
|
||||
for (pi = pnp_devices; pi != NULL; pi = pi->pi_next) {
|
||||
for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) {
|
||||
|
||||
/* no driver assigned, bus matches OK */
|
||||
if ((pi->pi_module == NULL) &&
|
||||
!strcmp(pi->pi_handler->pp_name, currbus)) {
|
||||
|
||||
/* scan idents, take first match */
|
||||
for (id = pi->pi_ident; id != NULL; id = id->id_next)
|
||||
for (id = pi->pi_ident.stqh_first; id != NULL; id = id->id_link.stqe_next)
|
||||
if (!strcmp(id->id_ident, ident))
|
||||
break;
|
||||
|
||||
@ -267,19 +298,60 @@ pnp_scankernel(void)
|
||||
void
|
||||
pnp_addident(struct pnpinfo *pi, char *ident)
|
||||
{
|
||||
struct pnpident *id, **idp;
|
||||
|
||||
if (pi->pi_ident == NULL) {
|
||||
idp = &(pi->pi_ident);
|
||||
} else {
|
||||
for (id = pi->pi_ident; id->id_next != NULL; id = id->id_next)
|
||||
if (!strcmp(id->id_ident, ident))
|
||||
return; /* already have this one */
|
||||
;
|
||||
idp = &(id->id_next);
|
||||
}
|
||||
*idp = malloc(sizeof(struct pnpident));
|
||||
(*idp)->id_next = NULL;
|
||||
(*idp)->id_ident = strdup(ident);
|
||||
struct pnpident *id;
|
||||
|
||||
for (id = pi->pi_ident.stqh_first; id != NULL; id = id->id_link.stqe_next)
|
||||
if (!strcmp(id->id_ident, ident))
|
||||
return; /* already have this one */
|
||||
|
||||
id = malloc(sizeof(struct pnpident));
|
||||
id->id_ident = strdup(ident);
|
||||
STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new pnpinfo struct
|
||||
*/
|
||||
struct pnpinfo *
|
||||
pnp_allocinfo(void)
|
||||
{
|
||||
struct pnpinfo *pi;
|
||||
|
||||
pi = malloc(sizeof(struct pnpinfo));
|
||||
bzero(pi, sizeof(struct pnpinfo));
|
||||
STAILQ_INIT(&pi->pi_ident);
|
||||
return(pi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release storage held by a pnpinfo struct
|
||||
*/
|
||||
void
|
||||
pnp_freeinfo(struct pnpinfo *pi)
|
||||
{
|
||||
struct pnpident *id;
|
||||
|
||||
while (pi->pi_ident.stqh_first != NULL) {
|
||||
id = pi->pi_ident.stqh_first;
|
||||
STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
|
||||
free(id->id_ident);
|
||||
free(id);
|
||||
}
|
||||
if (pi->pi_desc)
|
||||
free(pi->pi_desc);
|
||||
if (pi->pi_module)
|
||||
free(pi->pi_module);
|
||||
if (pi->pi_argv)
|
||||
free(pi->pi_argv);
|
||||
free(pi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new pnpinfo struct to the list.
|
||||
*/
|
||||
void
|
||||
pnp_addinfo(struct pnpinfo *pi)
|
||||
{
|
||||
STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user