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