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