xref: /illumos-gate/usr/src/boot/common/pnp.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
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