xref: /freebsd/stand/common/pnp.c (revision 56e53cb8ef000c3ef72337a4095987a932cdedef)
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