xref: /titanic_52/usr/src/uts/intel/io/acpica/master_ops.c (revision c61d8baa39b367ff34e75d386cd4982896306860)
1ae115bc7Smrj /*
2ae115bc7Smrj  * CDDL HEADER START
3ae115bc7Smrj  *
4ae115bc7Smrj  * The contents of this file are subject to the terms of the
5ae8fa80cSmyers  * Common Development and Distribution License (the "License").
6ae8fa80cSmyers  * You may not use this file except in compliance with the License.
7ae115bc7Smrj  *
8ae115bc7Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ae115bc7Smrj  * or http://www.opensolaris.org/os/licensing.
10ae115bc7Smrj  * See the License for the specific language governing permissions
11ae115bc7Smrj  * and limitations under the License.
12ae115bc7Smrj  *
13ae115bc7Smrj  * When distributing Covered Code, include this CDDL HEADER in each
14ae115bc7Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ae115bc7Smrj  * If applicable, add the following below this CDDL HEADER, with the
16ae115bc7Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
17ae115bc7Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
18ae115bc7Smrj  *
19ae115bc7Smrj  * CDDL HEADER END
20ae115bc7Smrj  */
21ae115bc7Smrj /*
22*c61d8baaSDana Myers  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23ae115bc7Smrj  */
24ae115bc7Smrj 
25ae115bc7Smrj #include <sys/kobj.h>
26ae115bc7Smrj #include <sys/kobj_lex.h>
27ae115bc7Smrj #include <sys/ddi.h>
28ae115bc7Smrj #include <sys/sunddi.h>
29ae115bc7Smrj #include <sys/sunndi.h>
30aa2aa9a6SDana Myers #include <sys/acpi/acpi.h>
31aa2aa9a6SDana Myers #include <sys/acpica.h>
32ae115bc7Smrj 
33ae115bc7Smrj #define	masterfile "/boot/solaris/devicedb/master"
34ae115bc7Smrj 
35aa2aa9a6SDana Myers /*
36aa2aa9a6SDana Myers  * Internal definitions
37aa2aa9a6SDana Myers  */
38ae115bc7Smrj 
39aa2aa9a6SDana Myers typedef enum {
40aa2aa9a6SDana Myers 	MF_UNEXPECTED = -1,
41aa2aa9a6SDana Myers 	MF_IDENT,
42aa2aa9a6SDana Myers 	MF_STRING,
43aa2aa9a6SDana Myers 	MF_EOF,
44aa2aa9a6SDana Myers 	MF_NEWLINE,
45aa2aa9a6SDana Myers 	MF_EQUALS,
46aa2aa9a6SDana Myers 	MF_BIT_OR
47aa2aa9a6SDana Myers } mftoken_t;
48aa2aa9a6SDana Myers 
49aa2aa9a6SDana Myers typedef enum {
50aa2aa9a6SDana Myers 	MF_INIT,
51aa2aa9a6SDana Myers 	MF_DEVID,
52aa2aa9a6SDana Myers 	MF_NAME,
53aa2aa9a6SDana Myers 	MF_DEVTYPE,
54aa2aa9a6SDana Myers 	MF_BUSTYPE,
55aa2aa9a6SDana Myers 	MF_BEFNAME,
56aa2aa9a6SDana Myers 	MF_DESCRIPTION,
57aa2aa9a6SDana Myers 	MF_PROPNAME,
58aa2aa9a6SDana Myers 	MF_PROPASSIGN,
59aa2aa9a6SDana Myers 	MF_PROPVAL,
60aa2aa9a6SDana Myers 	MF_VERSION_DONE,
61aa2aa9a6SDana Myers 	MF_VALID_DONE,
62aa2aa9a6SDana Myers 	MF_ERROR_DONE
63aa2aa9a6SDana Myers } mfparse_t;
64aa2aa9a6SDana Myers 
65aa2aa9a6SDana Myers 
66aa2aa9a6SDana Myers static master_rec_t *master_list = NULL;
67aa2aa9a6SDana Myers 
68aa2aa9a6SDana Myers device_id_t *
69aa2aa9a6SDana Myers mf_alloc_device_id()
70aa2aa9a6SDana Myers {
71aa2aa9a6SDana Myers 	return ((device_id_t *)kmem_zalloc(sizeof (device_id_t), KM_SLEEP));
72aa2aa9a6SDana Myers }
73aa2aa9a6SDana Myers 
74aa2aa9a6SDana Myers void
75aa2aa9a6SDana Myers mf_free_device_id(device_id_t *d)
76aa2aa9a6SDana Myers {
77aa2aa9a6SDana Myers 	if (d->id != NULL)
78aa2aa9a6SDana Myers 		strfree(d->id);
79aa2aa9a6SDana Myers 
80aa2aa9a6SDana Myers 	kmem_free(d, sizeof (device_id_t));
81aa2aa9a6SDana Myers }
82aa2aa9a6SDana Myers 
83aa2aa9a6SDana Myers static property_t *
84aa2aa9a6SDana Myers mf_alloc_property()
85aa2aa9a6SDana Myers {
86aa2aa9a6SDana Myers 	return ((property_t *)kmem_zalloc(sizeof (property_t), KM_SLEEP));
87aa2aa9a6SDana Myers }
88ae115bc7Smrj 
89ae115bc7Smrj static void
90aa2aa9a6SDana Myers mf_free_property(property_t *p)
91aa2aa9a6SDana Myers {
92aa2aa9a6SDana Myers 	if (p->name != NULL)
93aa2aa9a6SDana Myers 		strfree(p->name);
94ae115bc7Smrj 
95aa2aa9a6SDana Myers 	if (p->value != NULL)
96aa2aa9a6SDana Myers 		strfree(p->value);
97aa2aa9a6SDana Myers 
98aa2aa9a6SDana Myers 	kmem_free(p, sizeof (property_t));
99ae115bc7Smrj }
100aa2aa9a6SDana Myers 
101aa2aa9a6SDana Myers static master_rec_t *
102aa2aa9a6SDana Myers mf_alloc_master_rec()
103aa2aa9a6SDana Myers {
104aa2aa9a6SDana Myers 	return ((master_rec_t *)kmem_zalloc(sizeof (master_rec_t), KM_SLEEP));
105ae115bc7Smrj }
106aa2aa9a6SDana Myers 
107aa2aa9a6SDana Myers static void
108aa2aa9a6SDana Myers mf_free_master_rec(master_rec_t *m)
109aa2aa9a6SDana Myers {
110aa2aa9a6SDana Myers 	device_id_t *d;
111aa2aa9a6SDana Myers 	property_t *p;
112aa2aa9a6SDana Myers 
113aa2aa9a6SDana Myers 	if (m->name != NULL)
114aa2aa9a6SDana Myers 		strfree(m->name);
115aa2aa9a6SDana Myers 
116aa2aa9a6SDana Myers 	if (m->description != NULL)
117aa2aa9a6SDana Myers 		strfree(m->description);
118aa2aa9a6SDana Myers 
119aa2aa9a6SDana Myers 	d = m->device_ids;
120aa2aa9a6SDana Myers 	while (d != NULL) {
121aa2aa9a6SDana Myers 		device_id_t *next;
122aa2aa9a6SDana Myers 
123aa2aa9a6SDana Myers 		next = d->next;
124aa2aa9a6SDana Myers 		mf_free_device_id(d);
125aa2aa9a6SDana Myers 		d = next;
126ae115bc7Smrj 	}
127aa2aa9a6SDana Myers 
128aa2aa9a6SDana Myers 	p = m->properties;
129aa2aa9a6SDana Myers 	while (p != NULL) {
130aa2aa9a6SDana Myers 		property_t *next;
131aa2aa9a6SDana Myers 
132aa2aa9a6SDana Myers 		next = p->next;
133aa2aa9a6SDana Myers 		mf_free_property(p);
134aa2aa9a6SDana Myers 		p = next;
135ae115bc7Smrj 	}
136aa2aa9a6SDana Myers 
137aa2aa9a6SDana Myers 	kmem_free(m, sizeof (master_rec_t));
138ae115bc7Smrj }
139aa2aa9a6SDana Myers 
140aa2aa9a6SDana Myers void
141aa2aa9a6SDana Myers free_master_data()
142aa2aa9a6SDana Myers {
143aa2aa9a6SDana Myers 	master_rec_t *m;
144aa2aa9a6SDana Myers 
145aa2aa9a6SDana Myers 	m = master_list;
146aa2aa9a6SDana Myers 	while (m != NULL) {
147aa2aa9a6SDana Myers 		master_rec_t *next;
148aa2aa9a6SDana Myers 
149aa2aa9a6SDana Myers 		next = m->next;
150aa2aa9a6SDana Myers 		mf_free_master_rec(m);
151aa2aa9a6SDana Myers 		m = next;
152aa2aa9a6SDana Myers 	}
153aa2aa9a6SDana Myers 	master_list = NULL;
154ae115bc7Smrj }
155ae115bc7Smrj 
156ae115bc7Smrj /*
157aa2aa9a6SDana Myers  * Unfortunately, kobj_lex() is too sophisticated for our needs
158ae115bc7Smrj  */
159aa2aa9a6SDana Myers static mftoken_t
160aa2aa9a6SDana Myers mf_lex(struct _buf *file, char *val, size_t size)
161aa2aa9a6SDana Myers {
162ae115bc7Smrj 	char *cp;
163aa2aa9a6SDana Myers 	int ch, badquote;
164aa2aa9a6SDana Myers 	size_t remain;
165aa2aa9a6SDana Myers 	mftoken_t token = MF_UNEXPECTED;
166aa2aa9a6SDana Myers 
167aa2aa9a6SDana Myers 	if (size < 2)
168aa2aa9a6SDana Myers 		return (token);	/* MF_UNEXPECTED */
169ae115bc7Smrj 
170ae115bc7Smrj 	cp = val;
171aa2aa9a6SDana Myers 
172aa2aa9a6SDana Myers 	/* skip leading whitespace */
173aa2aa9a6SDana Myers 	while ((ch = kobj_getc(file)) == ' ' || ch == '\t')
174ae115bc7Smrj 		;
175aa2aa9a6SDana Myers 
176aa2aa9a6SDana Myers 	/* strip comments */
177aa2aa9a6SDana Myers 	if (ch == '#') {
178aa2aa9a6SDana Myers 		while ((ch = kobj_getc(file)) != '\n' && ch != '\r' &&
179aa2aa9a6SDana Myers 		    ch != -1)
180aa2aa9a6SDana Myers 			;
181ae115bc7Smrj 	}
182aa2aa9a6SDana Myers 
183aa2aa9a6SDana Myers 	remain = size - 1;
184ae115bc7Smrj 	*cp++ = (char)ch;
185ae115bc7Smrj 	switch (ch) {
186aa2aa9a6SDana Myers 	case -1:
187aa2aa9a6SDana Myers 		token = MF_EOF;
188ae115bc7Smrj 		break;
189ae115bc7Smrj 	case '\n':
190ae115bc7Smrj 	case '\r':
191aa2aa9a6SDana Myers 		token = MF_NEWLINE;
192aa2aa9a6SDana Myers 		break;
193aa2aa9a6SDana Myers 	case '=':
194aa2aa9a6SDana Myers 		token = MF_EQUALS;
195aa2aa9a6SDana Myers 		break;
196aa2aa9a6SDana Myers 	case '|':
197aa2aa9a6SDana Myers 		token = MF_BIT_OR;
198ae115bc7Smrj 		break;
199ae115bc7Smrj 	case '"':
200aa2aa9a6SDana Myers 		remain++;
201ae115bc7Smrj 		cp--;
202aa2aa9a6SDana Myers 		badquote = 0;
203aa2aa9a6SDana Myers 		while (!badquote && (ch  = kobj_getc(file)) != '"') {
204aa2aa9a6SDana Myers 			switch (ch) {
205aa2aa9a6SDana Myers 			case '\n':
206aa2aa9a6SDana Myers 			case -1:
207aa2aa9a6SDana Myers 				remain = size - 1;
208aa2aa9a6SDana Myers 				cp = val;
209aa2aa9a6SDana Myers 				*cp++ = '\n';
210aa2aa9a6SDana Myers 				badquote = 1;
211aa2aa9a6SDana Myers 				/* since we consumed the newline/EOF */
212aa2aa9a6SDana Myers 				(void) kobj_ungetc(file);
213ae115bc7Smrj 				break;
214ae115bc7Smrj 			default:
215aa2aa9a6SDana Myers 				if (--remain == 0) {
216aa2aa9a6SDana Myers 					token = MF_UNEXPECTED;
217aa2aa9a6SDana Myers 					goto out;
218ae115bc7Smrj 				}
219aa2aa9a6SDana Myers 				*cp++ = (char)ch;
220ae115bc7Smrj 				break;
221ae115bc7Smrj 			}
222aa2aa9a6SDana Myers 		}
223aa2aa9a6SDana Myers 		token = MF_STRING;
224aa2aa9a6SDana Myers 		break;
225aa2aa9a6SDana Myers 	default:
226aa2aa9a6SDana Myers 		do {
227aa2aa9a6SDana Myers 			if (--remain == 0) {
228aa2aa9a6SDana Myers 				token = MF_UNEXPECTED;
229aa2aa9a6SDana Myers 				break;
230aa2aa9a6SDana Myers 			}
231aa2aa9a6SDana Myers 
232aa2aa9a6SDana Myers 			token = MF_IDENT;
233aa2aa9a6SDana Myers 			*cp++ = (char)(ch = kobj_getc(file));
234aa2aa9a6SDana Myers 
235aa2aa9a6SDana Myers 			/* if terminating character, break out */
236aa2aa9a6SDana Myers 			if ((ch == -1) || (ch == ' ') || (ch == '\t') ||
237aa2aa9a6SDana Myers 			    (ch == '\n') || (ch == '\r') || (ch == '=') ||
238aa2aa9a6SDana Myers 			    (ch == '|')) {
239aa2aa9a6SDana Myers 				(void) kobj_ungetc(file);
240aa2aa9a6SDana Myers 				remain++;
241aa2aa9a6SDana Myers 				cp--;
242aa2aa9a6SDana Myers 				break;
243aa2aa9a6SDana Myers 			}
244aa2aa9a6SDana Myers 
245aa2aa9a6SDana Myers 			if ((ch == '#') || (ch == '"'))
246aa2aa9a6SDana Myers 				token = MF_UNEXPECTED;
247aa2aa9a6SDana Myers 		} while (token != MF_UNEXPECTED);
248aa2aa9a6SDana Myers 		break;
249aa2aa9a6SDana Myers 	}
250aa2aa9a6SDana Myers out:
251ae115bc7Smrj 	*cp = '\0';
252aa2aa9a6SDana Myers 
253ae115bc7Smrj 	return (token);
254ae115bc7Smrj }
255ae115bc7Smrj 
256aa2aa9a6SDana Myers static master_rec_t *
257aa2aa9a6SDana Myers get_line(struct _buf *file)
258ae115bc7Smrj {
259aa2aa9a6SDana Myers 	master_rec_t *m = NULL;
260aa2aa9a6SDana Myers 	device_id_t *d = NULL;
261aa2aa9a6SDana Myers 	property_t *p = NULL;
262aa2aa9a6SDana Myers 	mftoken_t token;
263aa2aa9a6SDana Myers 	char tokval[MAXPATHLEN];
264aa2aa9a6SDana Myers 	mfparse_t parse_state;
265ae115bc7Smrj 
266aa2aa9a6SDana Myers 	parse_state = MF_INIT;
267aa2aa9a6SDana Myers 	token = mf_lex(file, tokval, sizeof (tokval));
268aa2aa9a6SDana Myers 	while (token != MF_EOF) {
269aa2aa9a6SDana Myers 		switch (parse_state) {
270aa2aa9a6SDana Myers 		case MF_INIT:
271aa2aa9a6SDana Myers 			m = mf_alloc_master_rec();
272aa2aa9a6SDana Myers 			parse_state = MF_DEVID;
273aa2aa9a6SDana Myers 			/*FALLTHROUGH*/
274aa2aa9a6SDana Myers 		case MF_DEVID:
275aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
276aa2aa9a6SDana Myers 				d = mf_alloc_device_id();
277aa2aa9a6SDana Myers 				d->id = strdup(tokval);
278aa2aa9a6SDana Myers 				d->next = m->device_ids;
279aa2aa9a6SDana Myers 				m->device_ids = d;
280aa2aa9a6SDana Myers 				parse_state = MF_NAME;
281aa2aa9a6SDana Myers 			} else if (token != MF_NEWLINE)
282aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
283aa2aa9a6SDana Myers 			break;
284aa2aa9a6SDana Myers 		case MF_NAME:
285aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
286aa2aa9a6SDana Myers 				m->name = strdup(tokval);
287aa2aa9a6SDana Myers 				parse_state = MF_DEVTYPE;
288aa2aa9a6SDana Myers 			} else if (token == MF_BIT_OR) {
289aa2aa9a6SDana Myers 				parse_state = MF_DEVID;
290aa2aa9a6SDana Myers 			} else
291aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
292aa2aa9a6SDana Myers 			break;
293aa2aa9a6SDana Myers 		case MF_DEVTYPE:
294aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
295aa2aa9a6SDana Myers 				/* device_type not used */
296aa2aa9a6SDana Myers 				parse_state = MF_BUSTYPE;
297aa2aa9a6SDana Myers 			} else if (token == MF_NEWLINE) {
298aa2aa9a6SDana Myers 				/* version line ignored */
299aa2aa9a6SDana Myers 				parse_state = MF_VERSION_DONE;
300aa2aa9a6SDana Myers 			} else
301aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
302aa2aa9a6SDana Myers 			break;
303aa2aa9a6SDana Myers 		case MF_BUSTYPE:
304aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
305aa2aa9a6SDana Myers 				/* bus_type ignored */
306aa2aa9a6SDana Myers 				parse_state = MF_BEFNAME;
307aa2aa9a6SDana Myers 			} else
308aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
309aa2aa9a6SDana Myers 			break;
310aa2aa9a6SDana Myers 		case MF_BEFNAME:
311aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
312aa2aa9a6SDana Myers 				/* realmode driver name ignored */
313aa2aa9a6SDana Myers 				parse_state = MF_DESCRIPTION;
314aa2aa9a6SDana Myers 			} else
315aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
316aa2aa9a6SDana Myers 			break;
317aa2aa9a6SDana Myers 		case MF_DESCRIPTION:
318aa2aa9a6SDana Myers 			if (token == MF_STRING) {
319aa2aa9a6SDana Myers 				m->description = strdup(tokval);
320aa2aa9a6SDana Myers 				parse_state = MF_PROPNAME;
321aa2aa9a6SDana Myers 			} else
322aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
323aa2aa9a6SDana Myers 			break;
324aa2aa9a6SDana Myers 		case MF_PROPNAME:
325aa2aa9a6SDana Myers 			if (token == MF_IDENT) {
326aa2aa9a6SDana Myers 				p = mf_alloc_property();
327aa2aa9a6SDana Myers 				p->name = strdup(tokval);
328aa2aa9a6SDana Myers 				parse_state = MF_PROPASSIGN;
329aa2aa9a6SDana Myers 			} else if (token == MF_NEWLINE) {
330aa2aa9a6SDana Myers 				parse_state = MF_VALID_DONE;
331aa2aa9a6SDana Myers 			} else
332aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
333aa2aa9a6SDana Myers 			break;
334aa2aa9a6SDana Myers 		case MF_PROPASSIGN:
335aa2aa9a6SDana Myers 			if (token == MF_EQUALS) {
336aa2aa9a6SDana Myers 				parse_state = MF_PROPVAL;
337aa2aa9a6SDana Myers 			} else
338aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
339aa2aa9a6SDana Myers 			break;
340aa2aa9a6SDana Myers 		case MF_PROPVAL:
341aa2aa9a6SDana Myers 			if (token == MF_STRING || token == MF_IDENT) {
342aa2aa9a6SDana Myers 				p->value = strdup(tokval);
343aa2aa9a6SDana Myers 				p->next = m->properties;
344aa2aa9a6SDana Myers 				/* delete properties which begin with '$' */
345aa2aa9a6SDana Myers 				if (*p->name == '$') {
346aa2aa9a6SDana Myers 					mf_free_property(p);
347aa2aa9a6SDana Myers 				} else
348aa2aa9a6SDana Myers 					m->properties = p;
349aa2aa9a6SDana Myers 				p = NULL;
350aa2aa9a6SDana Myers 				parse_state = MF_PROPNAME;
351aa2aa9a6SDana Myers 			} else
352aa2aa9a6SDana Myers 				parse_state = MF_ERROR_DONE;
353aa2aa9a6SDana Myers 			break;
354aa2aa9a6SDana Myers 		case MF_VERSION_DONE:
355aa2aa9a6SDana Myers 		case MF_VALID_DONE:
356aa2aa9a6SDana Myers 		case MF_ERROR_DONE:
357aa2aa9a6SDana Myers 			/* terminating states handled outside switch() */
358aa2aa9a6SDana Myers 			break;
359ae115bc7Smrj 		}
360ae115bc7Smrj 
361aa2aa9a6SDana Myers 		if (parse_state == MF_VERSION_DONE) {
362aa2aa9a6SDana Myers 			/* ignore version line */
363aa2aa9a6SDana Myers 			mf_free_master_rec(m);
364aa2aa9a6SDana Myers 			parse_state = MF_INIT;
365aa2aa9a6SDana Myers 		} else if (parse_state == MF_VALID_DONE) {
366aa2aa9a6SDana Myers 			/* valid line */
367aa2aa9a6SDana Myers 			break;
368aa2aa9a6SDana Myers 		} else if (parse_state == MF_ERROR_DONE) {
369aa2aa9a6SDana Myers 			mf_free_master_rec(m);
370aa2aa9a6SDana Myers 			if (p != NULL)
371aa2aa9a6SDana Myers 				mf_free_property(p);
372ae115bc7Smrj 			/*
373aa2aa9a6SDana Myers 			 * Error in master file.  Should never happen
374aa2aa9a6SDana Myers 			 * since master file is not user-edited.  Eat rest
375aa2aa9a6SDana Myers 			 * of line to attempt error recovery
376ae115bc7Smrj 			 */
377aa2aa9a6SDana Myers 			cmn_err(CE_NOTE, "!error in %s", masterfile);
378aa2aa9a6SDana Myers 			while (token != MF_NEWLINE && token != MF_EOF)
379aa2aa9a6SDana Myers 				token = mf_lex(file, tokval, sizeof (tokval));
380aa2aa9a6SDana Myers 			parse_state = MF_INIT;
381aa2aa9a6SDana Myers 			continue;
382aa2aa9a6SDana Myers 		}
383aa2aa9a6SDana Myers 
384aa2aa9a6SDana Myers 		token = mf_lex(file, tokval, sizeof (tokval));
385aa2aa9a6SDana Myers 	}
386aa2aa9a6SDana Myers 
387aa2aa9a6SDana Myers 	return (m);
388aa2aa9a6SDana Myers }
389aa2aa9a6SDana Myers 
390ae115bc7Smrj void
391aa2aa9a6SDana Myers process_master_file()
392aa2aa9a6SDana Myers {
393aa2aa9a6SDana Myers 	struct _buf *file;
394aa2aa9a6SDana Myers 	master_rec_t *m;
395ae115bc7Smrj 
396*c61d8baaSDana Myers 	if ((file = kobj_open_file(masterfile)) == (struct _buf *)-1) {
397ae115bc7Smrj 		cmn_err(CE_WARN, "!cannot open master file: %s", masterfile);
398ae115bc7Smrj 		return;
399ae115bc7Smrj 	}
400aa2aa9a6SDana Myers 
401aa2aa9a6SDana Myers 	while ((m = get_line(file)) != NULL) {
402aa2aa9a6SDana Myers 		m->next = master_list;
403aa2aa9a6SDana Myers 		master_list = m;
404ae115bc7Smrj 	}
405aa2aa9a6SDana Myers 
406ae115bc7Smrj 	kobj_close_file(file);
407ae115bc7Smrj }
408ae115bc7Smrj 
409ae115bc7Smrj /*
410aa2aa9a6SDana Myers  * Return the first master file record found matching pnpid list
411ae115bc7Smrj  */
412aa2aa9a6SDana Myers const master_rec_t *
413aa2aa9a6SDana Myers master_file_lookup(device_id_t *pnpid)
414ae115bc7Smrj {
415aa2aa9a6SDana Myers 	master_rec_t *m;
416aa2aa9a6SDana Myers 	device_id_t *d;
417ae115bc7Smrj 
418aa2aa9a6SDana Myers 	while (pnpid != NULL) {
419aa2aa9a6SDana Myers 		m = master_list;
420aa2aa9a6SDana Myers 		while (m != NULL) {
421aa2aa9a6SDana Myers 			d = m->device_ids;
422aa2aa9a6SDana Myers 			while (d != NULL) {
423aa2aa9a6SDana Myers 				if (strcmp(pnpid->id, d->id) == 0)
424aa2aa9a6SDana Myers 					return (m);
425aa2aa9a6SDana Myers 				d = d->next;
426ae115bc7Smrj 			}
427aa2aa9a6SDana Myers 			m = m->next;
428ae115bc7Smrj 		}
429aa2aa9a6SDana Myers 		pnpid = pnpid->next;
430ae115bc7Smrj 	}
431ae115bc7Smrj 
432aa2aa9a6SDana Myers 	return (NULL);
433ae115bc7Smrj }
434