8748 loader: ptblread() is broken with >512B sectors
[unleashed.git] / usr / src / boot / sys / boot / common / pnp.c
blob14b0b965f0aaf46404a690a24e55b8f6754d4fdf
1 /*
2 * mjs copyright
4 */
6 #include <sys/cdefs.h>
8 /*
9 * "Plug and Play" functionality.
11 * We use the PnP enumerators to obtain identifiers for installed hardware,
12 * and the contents of a database to determine modules to be loaded to support
13 * such hardware.
16 #include <stand.h>
17 #include <string.h>
18 #include <bootstrap.h>
19 #include "ficl.h"
21 static struct pnpinfo_stql pnp_devices;
22 static int pnp_devices_initted = 0;
24 static void pnp_discard(void);
27 * Perform complete enumeration sweep
30 COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan);
32 static int
33 pnp_scan(int argc, char *argv[])
35 struct pnpinfo *pi;
36 int hdlr;
37 int verbose;
38 int ch;
40 if (pnp_devices_initted == 0) {
41 STAILQ_INIT(&pnp_devices);
42 pnp_devices_initted = 1;
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);
60 /* forget anything we think we knew */
61 pnp_discard();
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();
69 if (verbose) {
70 pager_open();
71 pager_output("PNP scan summary:\n");
72 STAILQ_FOREACH(pi, &pnp_devices, pi_link) {
73 pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */
74 if (pi->pi_desc != NULL) {
75 pager_output(" : ");
76 pager_output(pi->pi_desc);
78 pager_output("\n");
80 pager_close();
82 return(CMD_OK);
86 * Throw away anything we think we know about PnP devices.
88 static void
89 pnp_discard(void)
91 struct pnpinfo *pi;
93 while (STAILQ_FIRST(&pnp_devices) != NULL) {
94 pi = STAILQ_FIRST(&pnp_devices);
95 STAILQ_REMOVE_HEAD(&pnp_devices, pi_link);
96 pnp_freeinfo(pi);
101 * Add a unique identifier to (pi)
103 void
104 pnp_addident(struct pnpinfo *pi, char *ident)
106 struct pnpident *id;
108 STAILQ_FOREACH(id, &pi->pi_ident, id_link)
109 if (!strcmp(id->id_ident, ident))
110 return; /* already have this one */
112 id = malloc(sizeof(struct pnpident));
113 id->id_ident = strdup(ident);
114 STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link);
118 * Allocate a new pnpinfo struct
120 struct pnpinfo *
121 pnp_allocinfo(void)
123 struct pnpinfo *pi;
125 pi = malloc(sizeof(struct pnpinfo));
126 bzero(pi, sizeof(struct pnpinfo));
127 STAILQ_INIT(&pi->pi_ident);
128 return(pi);
132 * Release storage held by a pnpinfo struct
134 void
135 pnp_freeinfo(struct pnpinfo *pi)
137 struct pnpident *id;
139 while (!STAILQ_EMPTY(&pi->pi_ident)) {
140 id = STAILQ_FIRST(&pi->pi_ident);
141 STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link);
142 free(id->id_ident);
143 free(id);
145 if (pi->pi_desc)
146 free(pi->pi_desc);
147 if (pi->pi_module)
148 free(pi->pi_module);
149 if (pi->pi_argv)
150 free(pi->pi_argv);
151 free(pi);
155 * Add a new pnpinfo struct to the list.
157 void
158 pnp_addinfo(struct pnpinfo *pi)
160 STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link);
165 * Format an EISA id as a string in standard ISA PnP format, AAAIIRR
166 * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID.
168 char *
169 pnp_eisaformat(u_int8_t *data)
171 static char idbuf[8];
172 const char hextoascii[] = "0123456789abcdef";
174 idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
175 idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
176 idbuf[2] = '@' + (data[1] & 0x1f);
177 idbuf[3] = hextoascii[(data[2] >> 4)];
178 idbuf[4] = hextoascii[(data[2] & 0xf)];
179 idbuf[5] = hextoascii[(data[3] >> 4)];
180 idbuf[6] = hextoascii[(data[3] & 0xf)];
181 idbuf[7] = 0;
182 return(idbuf);
185 void
186 ficlPnpdevices(ficlVm *pVM)
188 static int pnp_devices_initted = 0;
190 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
192 if (!pnp_devices_initted) {
193 STAILQ_INIT(&pnp_devices);
194 pnp_devices_initted = 1;
197 ficlStackPushPointer(ficlVmGetDataStack(pVM), &pnp_devices);
200 void
201 ficlPnphandlers(ficlVm *pVM)
203 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
205 ficlStackPushPointer(ficlVmGetDataStack(pVM), pnphandlers);
209 * Glue function to add the appropriate forth words to access pnp BIOS
210 * functionality.
212 static void
213 ficlCompilePnp(ficlSystem *pSys)
215 ficlDictionary *dp = ficlSystemGetDictionary(pSys);
217 FICL_SYSTEM_ASSERT(pSys, dp);
219 ficlDictionarySetPrimitive(dp, "pnpdevices", ficlPnpdevices,
220 FICL_WORD_DEFAULT);
221 ficlDictionarySetPrimitive(dp, "pnphandlers", ficlPnphandlers,
222 FICL_WORD_DEFAULT);
225 FICL_COMPILE_SET(ficlCompilePnp);