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