xref: /titanic_51/usr/src/boot/sys/boot/common/pnp.c (revision d5a0772bd7066293674d17391f116c692addc58d)
14a5d661aSToomas Soome /*
24a5d661aSToomas Soome  * mjs copyright
34a5d661aSToomas Soome  *
44a5d661aSToomas Soome  */
54a5d661aSToomas Soome 
64a5d661aSToomas Soome #include <sys/cdefs.h>
74a5d661aSToomas Soome 
84a5d661aSToomas Soome /*
94a5d661aSToomas Soome  * "Plug and Play" functionality.
104a5d661aSToomas Soome  *
114a5d661aSToomas Soome  * We use the PnP enumerators to obtain identifiers for installed hardware,
124a5d661aSToomas Soome  * and the contents of a database to determine modules to be loaded to support
134a5d661aSToomas Soome  * such hardware.
144a5d661aSToomas Soome  */
154a5d661aSToomas Soome 
164a5d661aSToomas Soome #include <stand.h>
174a5d661aSToomas Soome #include <string.h>
184a5d661aSToomas Soome #include <bootstrap.h>
19*d5a0772bSToomas Soome #include "ficl.h"
204a5d661aSToomas Soome 
21*d5a0772bSToomas Soome static struct pnpinfo_stql pnp_devices;
224a5d661aSToomas Soome static int		pnp_devices_initted = 0;
234a5d661aSToomas Soome 
244a5d661aSToomas Soome static void		pnp_discard(void);
254a5d661aSToomas Soome 
264a5d661aSToomas Soome /*
274a5d661aSToomas Soome  * Perform complete enumeration sweep
284a5d661aSToomas Soome  */
294a5d661aSToomas Soome 
304a5d661aSToomas Soome COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan);
314a5d661aSToomas Soome 
324a5d661aSToomas Soome static int
334a5d661aSToomas Soome pnp_scan(int argc, char *argv[])
344a5d661aSToomas Soome {
354a5d661aSToomas Soome     struct pnpinfo	*pi;
364a5d661aSToomas Soome     int			hdlr;
374a5d661aSToomas Soome     int			verbose;
384a5d661aSToomas Soome     int			ch;
394a5d661aSToomas Soome 
404a5d661aSToomas Soome     if (pnp_devices_initted == 0) {
414a5d661aSToomas Soome 	STAILQ_INIT(&pnp_devices);
424a5d661aSToomas Soome 	pnp_devices_initted = 1;
434a5d661aSToomas Soome     }
444a5d661aSToomas Soome 
454a5d661aSToomas Soome     verbose = 0;
464a5d661aSToomas Soome     optind = 1;
474a5d661aSToomas Soome     optreset = 1;
484a5d661aSToomas Soome     while ((ch = getopt(argc, argv, "v")) != -1) {
494a5d661aSToomas Soome 	switch(ch) {
504a5d661aSToomas Soome 	case 'v':
514a5d661aSToomas Soome 	    verbose = 1;
524a5d661aSToomas Soome 	    break;
534a5d661aSToomas Soome 	case '?':
544a5d661aSToomas Soome 	default:
554a5d661aSToomas Soome 	    /* getopt has already reported an error */
564a5d661aSToomas Soome 	    return(CMD_OK);
574a5d661aSToomas Soome 	}
584a5d661aSToomas Soome     }
594a5d661aSToomas Soome 
604a5d661aSToomas Soome     /* forget anything we think we knew */
614a5d661aSToomas Soome     pnp_discard();
624a5d661aSToomas Soome 
634a5d661aSToomas Soome     /* iterate over all of the handlers */
644a5d661aSToomas Soome     for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) {
654a5d661aSToomas Soome 	if (verbose)
664a5d661aSToomas Soome 	    printf("Probing %s...\n", pnphandlers[hdlr]->pp_name);
674a5d661aSToomas Soome 	pnphandlers[hdlr]->pp_enumerate();
684a5d661aSToomas Soome     }
694a5d661aSToomas Soome     if (verbose) {
704a5d661aSToomas Soome 	pager_open();
714a5d661aSToomas Soome 	pager_output("PNP scan summary:\n");
724a5d661aSToomas Soome 	STAILQ_FOREACH(pi, &pnp_devices, pi_link) {
734a5d661aSToomas Soome 	    pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident);	/* first ident should be canonical */
744a5d661aSToomas Soome 	    if (pi->pi_desc != NULL) {
754a5d661aSToomas Soome 		pager_output(" : ");
764a5d661aSToomas Soome 		pager_output(pi->pi_desc);
774a5d661aSToomas Soome 	    }
784a5d661aSToomas Soome 	    pager_output("\n");
794a5d661aSToomas Soome 	}
804a5d661aSToomas Soome 	pager_close();
814a5d661aSToomas Soome     }
824a5d661aSToomas Soome     return(CMD_OK);
834a5d661aSToomas Soome }
844a5d661aSToomas Soome 
854a5d661aSToomas Soome /*
864a5d661aSToomas Soome  * Throw away anything we think we know about PnP devices.
874a5d661aSToomas Soome  */
884a5d661aSToomas Soome static void
894a5d661aSToomas Soome pnp_discard(void)
904a5d661aSToomas Soome {
914a5d661aSToomas Soome     struct pnpinfo	*pi;
924a5d661aSToomas Soome 
934a5d661aSToomas Soome     while (STAILQ_FIRST(&pnp_devices) != NULL) {
944a5d661aSToomas Soome 	pi = STAILQ_FIRST(&pnp_devices);
954a5d661aSToomas Soome 	STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
964a5d661aSToomas Soome 	pnp_freeinfo(pi);
974a5d661aSToomas Soome     }
984a5d661aSToomas Soome }
994a5d661aSToomas Soome 
1004a5d661aSToomas Soome /*
1014a5d661aSToomas Soome  * Add a unique identifier to (pi)
1024a5d661aSToomas Soome  */
1034a5d661aSToomas Soome void
1044a5d661aSToomas Soome pnp_addident(struct pnpinfo *pi, char *ident)
1054a5d661aSToomas Soome {
1064a5d661aSToomas Soome     struct pnpident	*id;
1074a5d661aSToomas Soome 
1084a5d661aSToomas Soome     STAILQ_FOREACH(id, &pi->pi_ident, id_link)
1094a5d661aSToomas Soome 	if (!strcmp(id->id_ident, ident))
1104a5d661aSToomas Soome 	    return;			/* already have this one */
1114a5d661aSToomas Soome 
1124a5d661aSToomas Soome     id = malloc(sizeof(struct pnpident));
1134a5d661aSToomas Soome     id->id_ident = strdup(ident);
1144a5d661aSToomas Soome     STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
1154a5d661aSToomas Soome }
1164a5d661aSToomas Soome 
1174a5d661aSToomas Soome /*
1184a5d661aSToomas Soome  * Allocate a new pnpinfo struct
1194a5d661aSToomas Soome  */
1204a5d661aSToomas Soome struct pnpinfo *
1214a5d661aSToomas Soome pnp_allocinfo(void)
1224a5d661aSToomas Soome {
1234a5d661aSToomas Soome     struct pnpinfo	*pi;
1244a5d661aSToomas Soome 
1254a5d661aSToomas Soome     pi = malloc(sizeof(struct pnpinfo));
1264a5d661aSToomas Soome     bzero(pi, sizeof(struct pnpinfo));
1274a5d661aSToomas Soome     STAILQ_INIT(&pi->pi_ident);
1284a5d661aSToomas Soome     return(pi);
1294a5d661aSToomas Soome }
1304a5d661aSToomas Soome 
1314a5d661aSToomas Soome /*
1324a5d661aSToomas Soome  * Release storage held by a pnpinfo struct
1334a5d661aSToomas Soome  */
1344a5d661aSToomas Soome void
1354a5d661aSToomas Soome pnp_freeinfo(struct pnpinfo *pi)
1364a5d661aSToomas Soome {
1374a5d661aSToomas Soome     struct pnpident	*id;
1384a5d661aSToomas Soome 
1394a5d661aSToomas Soome     while (!STAILQ_EMPTY(&pi->pi_ident)) {
1404a5d661aSToomas Soome 	id = STAILQ_FIRST(&pi->pi_ident);
1414a5d661aSToomas Soome 	STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
1424a5d661aSToomas Soome 	free(id->id_ident);
1434a5d661aSToomas Soome 	free(id);
1444a5d661aSToomas Soome     }
1454a5d661aSToomas Soome     if (pi->pi_desc)
1464a5d661aSToomas Soome 	free(pi->pi_desc);
1474a5d661aSToomas Soome     if (pi->pi_module)
1484a5d661aSToomas Soome 	free(pi->pi_module);
1494a5d661aSToomas Soome     if (pi->pi_argv)
1504a5d661aSToomas Soome 	free(pi->pi_argv);
1514a5d661aSToomas Soome     free(pi);
1524a5d661aSToomas Soome }
1534a5d661aSToomas Soome 
1544a5d661aSToomas Soome /*
1554a5d661aSToomas Soome  * Add a new pnpinfo struct to the list.
1564a5d661aSToomas Soome  */
1574a5d661aSToomas Soome void
1584a5d661aSToomas Soome pnp_addinfo(struct pnpinfo *pi)
1594a5d661aSToomas Soome {
1604a5d661aSToomas Soome     STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
1614a5d661aSToomas Soome }
1624a5d661aSToomas Soome 
1634a5d661aSToomas Soome 
1644a5d661aSToomas Soome /*
1654a5d661aSToomas Soome  * Format an EISA id as a string in standard ISA PnP format, AAAIIRR
1664a5d661aSToomas Soome  * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID.
1674a5d661aSToomas Soome  */
1684a5d661aSToomas Soome char *
1694a5d661aSToomas Soome pnp_eisaformat(u_int8_t *data)
1704a5d661aSToomas Soome {
1714a5d661aSToomas Soome     static char	idbuf[8];
1724a5d661aSToomas Soome     const char	hextoascii[] = "0123456789abcdef";
1734a5d661aSToomas Soome 
1744a5d661aSToomas Soome     idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
1754a5d661aSToomas Soome     idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
1764a5d661aSToomas Soome     idbuf[2] = '@' + (data[1] & 0x1f);
1774a5d661aSToomas Soome     idbuf[3] = hextoascii[(data[2] >> 4)];
1784a5d661aSToomas Soome     idbuf[4] = hextoascii[(data[2] & 0xf)];
1794a5d661aSToomas Soome     idbuf[5] = hextoascii[(data[3] >> 4)];
1804a5d661aSToomas Soome     idbuf[6] = hextoascii[(data[3] & 0xf)];
1814a5d661aSToomas Soome     idbuf[7] = 0;
1824a5d661aSToomas Soome     return(idbuf);
1834a5d661aSToomas Soome }
1844a5d661aSToomas Soome 
185*d5a0772bSToomas Soome void
186*d5a0772bSToomas Soome ficlPnpdevices(ficlVm *pVM)
187*d5a0772bSToomas Soome {
188*d5a0772bSToomas Soome 	static int pnp_devices_initted = 0;
189*d5a0772bSToomas Soome 
190*d5a0772bSToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
191*d5a0772bSToomas Soome 
192*d5a0772bSToomas Soome 	if (!pnp_devices_initted) {
193*d5a0772bSToomas Soome 		STAILQ_INIT(&pnp_devices);
194*d5a0772bSToomas Soome 		pnp_devices_initted = 1;
195*d5a0772bSToomas Soome 	}
196*d5a0772bSToomas Soome 
197*d5a0772bSToomas Soome 	ficlStackPushPointer(ficlVmGetDataStack(pVM), &pnp_devices);
198*d5a0772bSToomas Soome }
199*d5a0772bSToomas Soome 
200*d5a0772bSToomas Soome void
201*d5a0772bSToomas Soome ficlPnphandlers(ficlVm *pVM)
202*d5a0772bSToomas Soome {
203*d5a0772bSToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
204*d5a0772bSToomas Soome 
205*d5a0772bSToomas Soome 	ficlStackPushPointer(ficlVmGetDataStack(pVM), pnphandlers);
206*d5a0772bSToomas Soome }
207*d5a0772bSToomas Soome 
208*d5a0772bSToomas Soome /*
209*d5a0772bSToomas Soome  * Glue function to add the appropriate forth words to access pnp BIOS
210*d5a0772bSToomas Soome  * functionality.
211*d5a0772bSToomas Soome  */
212*d5a0772bSToomas Soome static void
213*d5a0772bSToomas Soome ficlCompilePnp(ficlSystem *pSys)
214*d5a0772bSToomas Soome {
215*d5a0772bSToomas Soome 	ficlDictionary *dp = ficlSystemGetDictionary(pSys);
216*d5a0772bSToomas Soome 
217*d5a0772bSToomas Soome 	FICL_SYSTEM_ASSERT(pSys, dp);
218*d5a0772bSToomas Soome 
219*d5a0772bSToomas Soome 	ficlDictionarySetPrimitive(dp, "pnpdevices", ficlPnpdevices,
220*d5a0772bSToomas Soome 	    FICL_WORD_DEFAULT);
221*d5a0772bSToomas Soome 	ficlDictionarySetPrimitive(dp, "pnphandlers", ficlPnphandlers,
222*d5a0772bSToomas Soome 	    FICL_WORD_DEFAULT);
223*d5a0772bSToomas Soome }
224*d5a0772bSToomas Soome 
225*d5a0772bSToomas Soome FICL_COMPILE_SET(ficlCompilePnp);
226