1ca987d46SWarner Losh /*
2ca987d46SWarner Losh * mjs copyright
3ca987d46SWarner Losh *
4ca987d46SWarner Losh */
5ca987d46SWarner Losh
6ca987d46SWarner Losh /*
7ca987d46SWarner Losh * "Plug and Play" functionality.
8ca987d46SWarner Losh *
9ca987d46SWarner Losh * We use the PnP enumerators to obtain identifiers for installed hardware,
10ca987d46SWarner Losh * and the contents of a database to determine modules to be loaded to support
11ca987d46SWarner Losh * such hardware.
12ca987d46SWarner Losh */
13ca987d46SWarner Losh
14ca987d46SWarner Losh #include <stand.h>
15ca987d46SWarner Losh #include <string.h>
16ca987d46SWarner Losh #include <bootstrap.h>
17ca987d46SWarner Losh
18ca987d46SWarner Losh static struct pnpinfo_stql pnp_devices;
19ca987d46SWarner Losh static int pnp_devices_initted = 0;
20ca987d46SWarner Losh
21ca987d46SWarner Losh static void pnp_discard(void);
22ca987d46SWarner Losh
23ca987d46SWarner Losh /*
24ca987d46SWarner Losh * Perform complete enumeration sweep
25ca987d46SWarner Losh */
26ca987d46SWarner Losh
27ca987d46SWarner Losh COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan);
28ca987d46SWarner Losh
29ca987d46SWarner Losh static int
pnp_scan(int argc,char * argv[])30ca987d46SWarner Losh pnp_scan(int argc, char *argv[])
31ca987d46SWarner Losh {
32ca987d46SWarner Losh struct pnpinfo *pi;
33ca987d46SWarner Losh int hdlr;
34ca987d46SWarner Losh int verbose;
35ca987d46SWarner Losh int ch;
36ca987d46SWarner Losh
37ca987d46SWarner Losh if (pnp_devices_initted == 0) {
38ca987d46SWarner Losh STAILQ_INIT(&pnp_devices);
39ca987d46SWarner Losh pnp_devices_initted = 1;
40ca987d46SWarner Losh }
41ca987d46SWarner Losh
42ca987d46SWarner Losh verbose = 0;
43ca987d46SWarner Losh optind = 1;
44ca987d46SWarner Losh optreset = 1;
45ca987d46SWarner Losh while ((ch = getopt(argc, argv, "v")) != -1) {
46ca987d46SWarner Losh switch(ch) {
47ca987d46SWarner Losh case 'v':
48ca987d46SWarner Losh verbose = 1;
49ca987d46SWarner Losh break;
50ca987d46SWarner Losh case '?':
51ca987d46SWarner Losh default:
52ca987d46SWarner Losh /* getopt has already reported an error */
53ca987d46SWarner Losh return(CMD_OK);
54ca987d46SWarner Losh }
55ca987d46SWarner Losh }
56ca987d46SWarner Losh
57ca987d46SWarner Losh /* forget anything we think we knew */
58ca987d46SWarner Losh pnp_discard();
59ca987d46SWarner Losh
60ca987d46SWarner Losh /* iterate over all of the handlers */
61ca987d46SWarner Losh for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) {
62ca987d46SWarner Losh if (verbose)
63ca987d46SWarner Losh printf("Probing %s...\n", pnphandlers[hdlr]->pp_name);
64ca987d46SWarner Losh pnphandlers[hdlr]->pp_enumerate();
65ca987d46SWarner Losh }
66ca987d46SWarner Losh if (verbose) {
67ca987d46SWarner Losh pager_open();
68ca987d46SWarner Losh if (pager_output("PNP scan summary:\n"))
69ca987d46SWarner Losh goto out;
70ca987d46SWarner Losh STAILQ_FOREACH(pi, &pnp_devices, pi_link) {
71ca987d46SWarner Losh pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */
72ca987d46SWarner Losh if (pi->pi_desc != NULL) {
73ca987d46SWarner Losh pager_output(" : ");
74ca987d46SWarner Losh pager_output(pi->pi_desc);
75ca987d46SWarner Losh }
76ca987d46SWarner Losh if (pager_output("\n"))
77ca987d46SWarner Losh break;
78ca987d46SWarner Losh }
79ca987d46SWarner Losh out:
80ca987d46SWarner Losh pager_close();
81ca987d46SWarner Losh }
82ca987d46SWarner Losh return(CMD_OK);
83ca987d46SWarner Losh }
84ca987d46SWarner Losh
85ca987d46SWarner Losh /*
86ca987d46SWarner Losh * Throw away anything we think we know about PnP devices.
87ca987d46SWarner Losh */
88ca987d46SWarner Losh static void
pnp_discard(void)89ca987d46SWarner Losh pnp_discard(void)
90ca987d46SWarner Losh {
91ca987d46SWarner Losh struct pnpinfo *pi;
92ca987d46SWarner Losh
93ca987d46SWarner Losh while (STAILQ_FIRST(&pnp_devices) != NULL) {
94ca987d46SWarner Losh pi = STAILQ_FIRST(&pnp_devices);
95ca987d46SWarner Losh STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
96ca987d46SWarner Losh pnp_freeinfo(pi);
97ca987d46SWarner Losh }
98ca987d46SWarner Losh }
99ca987d46SWarner Losh
100ca987d46SWarner Losh /*
101ca987d46SWarner Losh * Add a unique identifier to (pi)
102ca987d46SWarner Losh */
103ca987d46SWarner Losh void
pnp_addident(struct pnpinfo * pi,char * ident)104ca987d46SWarner Losh pnp_addident(struct pnpinfo *pi, char *ident)
105ca987d46SWarner Losh {
106ca987d46SWarner Losh struct pnpident *id;
107ca987d46SWarner Losh
108ca987d46SWarner Losh STAILQ_FOREACH(id, &pi->pi_ident, id_link)
109ca987d46SWarner Losh if (!strcmp(id->id_ident, ident))
110ca987d46SWarner Losh return; /* already have this one */
111ca987d46SWarner Losh
112ca987d46SWarner Losh id = malloc(sizeof(struct pnpident));
113ca987d46SWarner Losh id->id_ident = strdup(ident);
114ca987d46SWarner Losh STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
115ca987d46SWarner Losh }
116ca987d46SWarner Losh
117ca987d46SWarner Losh /*
118ca987d46SWarner Losh * Allocate a new pnpinfo struct
119ca987d46SWarner Losh */
120ca987d46SWarner Losh struct pnpinfo *
pnp_allocinfo(void)121ca987d46SWarner Losh pnp_allocinfo(void)
122ca987d46SWarner Losh {
123ca987d46SWarner Losh struct pnpinfo *pi;
124ca987d46SWarner Losh
125ca987d46SWarner Losh pi = malloc(sizeof(struct pnpinfo));
126ca987d46SWarner Losh bzero(pi, sizeof(struct pnpinfo));
127ca987d46SWarner Losh STAILQ_INIT(&pi->pi_ident);
128ca987d46SWarner Losh return(pi);
129ca987d46SWarner Losh }
130ca987d46SWarner Losh
131ca987d46SWarner Losh /*
132ca987d46SWarner Losh * Release storage held by a pnpinfo struct
133ca987d46SWarner Losh */
134ca987d46SWarner Losh void
pnp_freeinfo(struct pnpinfo * pi)135ca987d46SWarner Losh pnp_freeinfo(struct pnpinfo *pi)
136ca987d46SWarner Losh {
137ca987d46SWarner Losh struct pnpident *id;
138ca987d46SWarner Losh
139ca987d46SWarner Losh while (!STAILQ_EMPTY(&pi->pi_ident)) {
140ca987d46SWarner Losh id = STAILQ_FIRST(&pi->pi_ident);
141ca987d46SWarner Losh STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
142ca987d46SWarner Losh free(id->id_ident);
143ca987d46SWarner Losh free(id);
144ca987d46SWarner Losh }
145ca987d46SWarner Losh if (pi->pi_desc)
146ca987d46SWarner Losh free(pi->pi_desc);
147ca987d46SWarner Losh if (pi->pi_module)
148ca987d46SWarner Losh free(pi->pi_module);
149ca987d46SWarner Losh if (pi->pi_argv)
150ca987d46SWarner Losh free(pi->pi_argv);
151ca987d46SWarner Losh free(pi);
152ca987d46SWarner Losh }
153ca987d46SWarner Losh
154ca987d46SWarner Losh /*
155ca987d46SWarner Losh * Add a new pnpinfo struct to the list.
156ca987d46SWarner Losh */
157ca987d46SWarner Losh void
pnp_addinfo(struct pnpinfo * pi)158ca987d46SWarner Losh pnp_addinfo(struct pnpinfo *pi)
159ca987d46SWarner Losh {
160ca987d46SWarner Losh STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
161ca987d46SWarner Losh }
162ca987d46SWarner Losh
163ca987d46SWarner Losh
164ca987d46SWarner Losh /*
165ca987d46SWarner Losh * Format an EISA id as a string in standard ISA PnP format, AAAIIRR
166ca987d46SWarner Losh * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID.
167ca987d46SWarner Losh */
168ca987d46SWarner Losh char *
pnp_eisaformat(uint8_t * data)169*56e53cb8SWarner Losh pnp_eisaformat(uint8_t *data)
170ca987d46SWarner Losh {
171ca987d46SWarner Losh static char idbuf[8];
172ca987d46SWarner Losh const char hextoascii[] = "0123456789abcdef";
173ca987d46SWarner Losh
174ca987d46SWarner Losh idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
175ca987d46SWarner Losh idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
176ca987d46SWarner Losh idbuf[2] = '@' + (data[1] & 0x1f);
177ca987d46SWarner Losh idbuf[3] = hextoascii[(data[2] >> 4)];
178ca987d46SWarner Losh idbuf[4] = hextoascii[(data[2] & 0xf)];
179ca987d46SWarner Losh idbuf[5] = hextoascii[(data[3] >> 4)];
180ca987d46SWarner Losh idbuf[6] = hextoascii[(data[3] & 0xf)];
181ca987d46SWarner Losh idbuf[7] = 0;
182ca987d46SWarner Losh return(idbuf);
183ca987d46SWarner Losh }
184