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