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