1 /*
2 * mjs copyright
3 *
4 */
5
6 #include <sys/cdefs.h>
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 static 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
pnp_scan(int argc,char * argv[])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 if (pager_output("PNP scan summary:\n"))
70 goto out;
71 STAILQ_FOREACH(pi, &pnp_devices, pi_link) {
72 pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */
73 if (pi->pi_desc != NULL) {
74 pager_output(" : ");
75 pager_output(pi->pi_desc);
76 }
77 if (pager_output("\n"))
78 break;
79 }
80 out:
81 pager_close();
82 }
83 return(CMD_OK);
84 }
85
86 /*
87 * Throw away anything we think we know about PnP devices.
88 */
89 static void
pnp_discard(void)90 pnp_discard(void)
91 {
92 struct pnpinfo *pi;
93
94 while (STAILQ_FIRST(&pnp_devices) != NULL) {
95 pi = STAILQ_FIRST(&pnp_devices);
96 STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
97 pnp_freeinfo(pi);
98 }
99 }
100
101 /*
102 * Add a unique identifier to (pi)
103 */
104 void
pnp_addident(struct pnpinfo * pi,char * ident)105 pnp_addident(struct pnpinfo *pi, char *ident)
106 {
107 struct pnpident *id;
108
109 STAILQ_FOREACH(id, &pi->pi_ident, id_link)
110 if (!strcmp(id->id_ident, ident))
111 return; /* already have this one */
112
113 id = malloc(sizeof(struct pnpident));
114 id->id_ident = strdup(ident);
115 STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
116 }
117
118 /*
119 * Allocate a new pnpinfo struct
120 */
121 struct pnpinfo *
pnp_allocinfo(void)122 pnp_allocinfo(void)
123 {
124 struct pnpinfo *pi;
125
126 pi = malloc(sizeof(struct pnpinfo));
127 bzero(pi, sizeof(struct pnpinfo));
128 STAILQ_INIT(&pi->pi_ident);
129 return(pi);
130 }
131
132 /*
133 * Release storage held by a pnpinfo struct
134 */
135 void
pnp_freeinfo(struct pnpinfo * pi)136 pnp_freeinfo(struct pnpinfo *pi)
137 {
138 struct pnpident *id;
139
140 while (!STAILQ_EMPTY(&pi->pi_ident)) {
141 id = STAILQ_FIRST(&pi->pi_ident);
142 STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
143 free(id->id_ident);
144 free(id);
145 }
146 if (pi->pi_desc)
147 free(pi->pi_desc);
148 if (pi->pi_module)
149 free(pi->pi_module);
150 if (pi->pi_argv)
151 free(pi->pi_argv);
152 free(pi);
153 }
154
155 /*
156 * Add a new pnpinfo struct to the list.
157 */
158 void
pnp_addinfo(struct pnpinfo * pi)159 pnp_addinfo(struct pnpinfo *pi)
160 {
161 STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
162 }
163
164
165 /*
166 * Format an EISA id as a string in standard ISA PnP format, AAAIIRR
167 * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID.
168 */
169 char *
pnp_eisaformat(uint8_t * data)170 pnp_eisaformat(uint8_t *data)
171 {
172 static char idbuf[8];
173 const char hextoascii[] = "0123456789abcdef";
174
175 idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
176 idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
177 idbuf[2] = '@' + (data[1] & 0x1f);
178 idbuf[3] = hextoascii[(data[2] >> 4)];
179 idbuf[4] = hextoascii[(data[2] & 0xf)];
180 idbuf[5] = hextoascii[(data[3] >> 4)];
181 idbuf[6] = hextoascii[(data[3] & 0xf)];
182 idbuf[7] = 0;
183 return(idbuf);
184 }
185