|
|
1.1 root 1: /*
2: *-IMPORT:
3: * <sys/compat.h>
4: * CONST
5: * LOCAL
6: * USE_PROTO
7: * ARGS ()
8: * <stdlib.h>
9: * NULL
10: * free ()
11: * malloc ()
12: * <string.h>
13: * strchr ()
14: * "ehand.h"
15: * ehand_t
16: * CHAIN_ERROR ()
17: * POP_HANDLER ()
18: * PUSH_HANDLER ()
19: * throw_error ()
20: * "symbol.h"
21: * LEX_WILD
22: * RANGE
23: * SIGNED
24: * SYM_EOF
25: * UNSIGNED
26: * read_dev_file ()
27: * read_number ()
28: * read_symbol ()
29: */
30:
31: #include <sys/compat.h>
32: #include <stdlib.h>
33: #include <string.h>
34:
35: #include "ehand.h"
36: #include "symbol.h"
37: #include "read.h"
38: #include "lex.h"
39:
40: #include "mdev.h"
41:
42:
43: LOCAL mdev_t * _mdevices;
44:
45:
46: /*
47: * Simple local function for testing to see if major-number ranges intersect.
48: */
49:
50: #ifdef USE_PROTO
51: LOCAL int (intersect) (CONST unsigned int * left, CONST unsigned int * right)
52: #else
53: LOCAL int
54: intersect ARGS ((left, right))
55: CONST int * left;
56: CONST int * right;
57: #endif
58: {
59: return (left [0] >= right [0] && left [0] <= right [1]) ||
60: (left [1] >= right [0] && left [1] <= right [1]);
61: }
62:
63:
64: /*
65: * Find a device by symbol.
66: */
67:
68: #ifdef USE_PROTO
69: mdev_t * (find_mdev) (symbol_t * sym)
70: #else
71: mdev_t *
72: find_mdev ARGS ((sym))
73: symbol_t * sym;
74: #endif
75: {
76: mdev_t * scan;
77:
78: for (scan = _mdevices ; scan != NULL ; scan = scan->md_next) {
79:
80: if (scan->md_devname == sym)
81: return scan;
82: }
83:
84: return NULL;
85: }
86:
87:
88: /*
89: * Read lines from an "mdevice" file.
90: *
91: * This code is really messy. My apologies.
92: */
93:
94: #ifdef USE_PROTO
95: LOCAL int (read_mdevice) (input_t * input, lex_t * lexp)
96: #else
97: LOCAL int
98: read_mdevice ARGS ((input, lexp))
99: input_t * input;
100: lex_t * lexp;
101: #endif
102: {
103: int ch = '\n';
104: mdev_t * mdevp;
105: mdev_t * scan;
106: ehand_t err;
107: lex_t functions = { NULL, NULL, "-", MDEV_FUNCS, LEX_WILD };
108: lex_t flags = { NULL, NULL, "-", MDEV_FLAGS, LEX_WILD };
109:
110: functions.l_prev = lexp;
111: flags.l_prev = lexp;
112:
113: if ((mdevp = (mdev_t *) malloc (sizeof (* mdevp))) == NULL)
114: throw_error ("out of memory in read_mdevice ()");
115:
116: if (PUSH_HANDLER (err) == 0) {
117: /*
118: * If the first thing on the line works out to be an EOF,
119: * then bail out without an error.
120: */
121:
122: ch = read_symbol (input, lexp, & mdevp->md_devname);
123:
124: if (mdevp->md_devname == NULL) {
125: /*
126: * We allow an EOF at the beginning of a line and we
127: * also allow a blank line.
128: */
129:
130: goto at_eof;
131: }
132: check_not_eol (ch);
133:
134: if (mdevp->md_devname->s_size > MAX_DEVNAME)
135: throw_error ("device name must be <= %d characters",
136: MAX_DEVNAME);
137:
138: if (find_mdev (mdevp->md_devname) != NULL)
139: throw_error ("device name must be unique");
140:
141:
142: /*
143: * We read the functions and characteristics field as symbols,
144: * even though they are really strings, since it makes no
145: * difference to the result.
146: */
147:
148: ch = read_symbol (input, & functions, & mdevp->md_functions);
149: if (mdevp->md_functions == NULL && ch != '-')
150: throw_error ("Unable to read functions");
151: check_not_eol (ch);
152:
153: ch = read_symbol (input, & flags, & mdevp->md_flags);
154: if (mdevp->md_flags == NULL && ch != '-')
155: throw_error ("Unable to read flags");
156: check_not_eol (ch);
157:
158: if ((mdev_flag (mdevp, MDEV_BLOCK) ||
159: mdev_flag (mdevp, MDEV_CHAR) ||
160: mdev_flag (mdevp, MDEV_STREAM)) &&
161: ! mdev_flag (mdevp, MDEV_DDI_DDK)) {
162:
163: throw_error ("devices must be DDI/DDK compliant");
164: }
165:
166:
167: /*
168: * We don't check for a unique device prefix, since there may
169: * be a legitimate reason to configure the same prefix twice.
170: *
171: * If the user installs multiple devices with the same prefix,
172: * the linker should catch it. Of course, a registration
173: * system might help. We only enforce the size limit for
174: * drivers... other kernel facilities can user longer names.
175: */
176:
177: ch = read_symbol (input, lexp, & mdevp->md_prefix);
178: check_not_eol (ch);
179:
180: if ((mdev_flag (mdevp, MDEV_BLOCK) ||
181: mdev_flag (mdevp, MDEV_CHAR) ||
182: mdev_flag (mdevp, MDEV_STREAM)) &&
183: mdevp->md_prefix->s_size > MAX_PREFIX)
184: throw_error ("device prefix must be <= %d characters",
185: MAX_PREFIX);
186:
187:
188: ch = read_uints (input, lexp, mdevp->md_blk_maj, RANGE);
189: check_not_eol (ch);
190:
191: if (mdev_flag (mdevp, MDEV_BLOCK)) {
192:
193: if (mdevp->md_blk_maj [0] > mdevp->md_blk_maj [1])
194: throw_error ("lower range bound higher that upper bound");
195:
196: if (mdevp->md_blk_maj [0] > 0 &&
197: mdevp->md_blk_maj [0] < MAJOR_RESERVED)
198: throw_error ("major devices up to %d reserved",
199: MAJOR_RESERVED);
200:
201: for (scan = _mdevices ; scan != NULL ;
202: scan = scan->md_next) {
203:
204: if (! mdev_flag (scan, MDEV_BLOCK))
205: continue;
206:
207: if (intersect (scan->md_blk_maj,
208: mdevp->md_blk_maj))
209: throw_error ("duplicate block major numbers");
210: }
211: } else
212: mdevp->md_blk_maj [0] = mdevp->md_blk_maj [1] = 0;
213:
214:
215: ch = read_uints (input, lexp, mdevp->md_chr_maj, RANGE);
216: check_not_eol (ch);
217:
218: if (mdev_flag (mdevp, MDEV_CHAR)) {
219:
220: if (mdevp->md_chr_maj [0] > mdevp->md_chr_maj [1])
221: throw_error ("lower range bound higher that upper bound");
222:
223: if (mdevp->md_chr_maj [0] > 0 &&
224: mdevp->md_chr_maj [0] < MAJOR_RESERVED)
225: throw_error ("major devices 0-%d reserved",
226: MAJOR_RESERVED - 1);
227:
228: for (scan = _mdevices ; scan != NULL ;
229: scan = scan->md_next) {
230:
231: if (! mdev_flag (scan, MDEV_CHAR))
232: continue;
233:
234: if (intersect (scan->md_chr_maj,
235: mdevp->md_chr_maj))
236: throw_error ("duplicate character major numbers");
237: }
238: } else
239: mdevp->md_chr_maj [0] = mdevp->md_chr_maj [1] = 0;
240:
241: ch = read_uints (input, lexp, & mdevp->md_minor_min,
242: NO_RANGE);
243: check_not_eol (ch);
244:
245: ch = read_uints (input, lexp, & mdevp->md_minor_max,
246: NO_RANGE);
247: check_not_eol (ch);
248:
249: if (mdevp->md_minor_min > mdevp->md_minor_max)
250: throw_error ("minor minimum higher than maximum");
251:
252: ch = read_ints (input, lexp, & mdevp->md_dma_chan, NO_RANGE);
253:
254: if (ch != '\n' && ch != SYM_EOF) {
255: /*
256: * The "cpu_id" field is optional.
257: */
258:
259: ch = read_ints (input, lexp, & mdevp->md_cpu_id,
260: NO_RANGE);
261: } else
262: mdevp->md_cpu_id = -1;
263:
264: ch = expect_eol (input, lexp, ch);
265:
266:
267: /*
268: * Having passed all the reasonableness checks, we link the
269: * new entry into the chain.
270: */
271:
272: mdevp->md_sdevices = NULL;
273: mdevp->md_interrupt = 0;
274:
275: mdevp->md_configure = mdev_flag (mdevp, MDEV_INSTALLABLE) ?
276: MD_INSTALLABLE : MD_DISABLED;
277:
278: mdevp->md_next = _mdevices;
279: _mdevices = mdevp;
280: } else {
281:
282: free (mdevp);
283: CHAIN_ERROR (err);
284: }
285:
286: at_eof:
287: POP_HANDLER (err);
288: return ch;
289: }
290:
291:
292: /*
293: * Test a device for a function code; returns 1 if code is present, or 0 if
294: * code is not specified for device.
295: */
296:
297: #ifdef USE_PROTO
298: int (mdev_func) (mdev_t * mdevp, char func)
299: #else
300: int
301: mdev_func ARGS ((mdevp, func))
302: mdev_t * mdevp;
303: char func;
304: #endif
305: {
306: if (mdevp->md_functions == NULL)
307: return 0;
308: return strchr (mdevp->md_functions->s_data, func) != NULL;
309: }
310:
311:
312: /*
313: * Test device characteristics; returns 1 if characteristic is specified for
314: * device, 0 if it is not.
315: */
316:
317: #ifdef USE_PROTO
318: int (mdev_flag) (mdev_t * mdevp, char flag)
319: #else
320: int
321: mdev_flag ARGS ((mdevp, flag))
322: mdev_t * mdevp;
323: char flag;
324: #endif
325: {
326: if (mdevp->md_flags == NULL)
327: return 0;
328: return strchr (mdevp->md_flags->s_data, flag) != NULL;
329: }
330:
331:
332: #if 0
333: /*
334: * Regenerate an 'mdevice' line from the stored record.
335: */
336:
337: #ifdef USE_PROTO
338: void (write_mdevice) (mdev_t * mdevp, FILE * out)
339: #else
340: void
341: write_mdevice ARGS ((mdevp, out))
342: mdev_t * mdevp;
343: FILE * out;
344: #endif
345: {
346: (void) fprintf (out, "%-8s %-16s %-16s %-4s ",
347: mdevp->md_devname->s_data,
348: mdevp->md_functions->s_data, mdevp->md_flags->s_data,
349: mdevp->md_prefix->s_data);
350:
351: if (mdevp->md_blk_maj [0] == mdevp->md_blk_maj [1])
352: (void) fprintf (out, "%-7d ", mdevp->md_blk_maj [0]);
353: else
354: (void) fprintf (out, "%3d-%-3d ", mdevp->md_blk_maj [0],
355: mdevp->md_blk_maj [1]);
356:
357: if (mdevp->md_chr_maj [0] == mdevp->md_chr_maj [1])
358: (void) fprintf (out, "%-7d ", mdevp->md_chr_maj [0]);
359: else
360: (void) fprintf (out, "%3d-%-3d ", mdevp->md_chr_maj [0],
361: mdevp->md_chr_maj [1]);
362:
363: (void) fprintf (out, "%-3d %-3d %-3d %d\n", mdevp->md_minor_min,
364: mdevp->md_minor_max, mdevp->md_dma_chan,
365: mdevp->md_cpu_id);
366: }
367: #endif
368:
369:
370: /*
371: * Suck in a complete 'mdevice' file.
372: */
373:
374: #ifdef USE_PROTO
375: void (read_mdev_file) (CONST char * name)
376: #else
377: void
378: read_mdev_file ARGS ((name))
379: CONST char * name;
380: #endif
381: {
382: read_dev_file (name, read_mdevice);
383: }
384:
385:
386: /*
387: * Return the head of the global list of all read "mdevice" entries.
388: */
389:
390: #ifdef USE_PROTO
391: mdev_t * (mdevices) (void)
392: #else
393: mdev_t *
394: mdevices ARGS (())
395: #endif
396: {
397: return _mdevices;
398: }
399:
400:
401: /*
402: * Generic insertion sort algorithm for "mdevice" entries based on a
403: * selection predicate and a comparison predicate.
404: *
405: * So that this can be a reasonably generic function, we pass it the internal
406: * offset of the "mdev_t *" member of the "mdevice" structure which will be
407: * used to link together the sorted entries.
408: */
409:
410: #define LINK(mdevp,off) (* (mdev_t **) ((char *) (mdevp) + off))
411:
412: #ifdef USE_PROTO
413: void (mdev_sort) (mdlist_t * mdlistp, msel_t selpred, mcmp_t cmppred,
414: size_t ptroff)
415: #else
416: void
417: mdev_sort ARGS ((mdlistp, selpred, cmppred, ptroff))
418: mdlist_t * mdlistp;
419: msel_t selpred;
420: mcmp_t cmppred;
421: size_t ptroff;
422: #endif
423: {
424: mdev_t * scan;
425: mdev_t * next;
426:
427: if (mdlistp == NULL || ptroff > sizeof (mdev_t))
428: throw_error ("bogus parameters to mdev_sort ()");
429:
430:
431: /*
432: * We'll just insert each selected member of the total list of
433: * mdevices into the output list in order by running down the output
434: * list until we compare true.
435: *
436: * We fetch "scan" before initializing the output list in case we are
437: * sorting the master device list.
438: */
439:
440: scan = mdevices ();
441:
442: mdlistp->mdl_first = mdlistp->mdl_last = NULL;
443: mdlistp->mdl_count = 0;
444:
445: for (; scan != NULL ; scan = next) {
446: mdev_t * findpos;
447: mdev_t * prev;
448:
449: /*
450: * We get the "next" entry now in case we are sorting the
451: * master list. We allow a "selpred" of NULL to select all
452: * the entries.
453: */
454:
455: next = scan->md_next;
456:
457: if (selpred != NULL && (* selpred) (scan) == 0)
458: continue;
459:
460:
461: /*
462: * Now attempt to find the right place for the new entry and
463: * insert it there.
464: */
465:
466: prev = NULL;
467:
468: for (findpos = mdlistp->mdl_first ; findpos != NULL ;
469: findpos = LINK ((prev = findpos), ptroff)) {
470: /*
471: * A "cmppred" that is NULL means that the order of
472: * output entries is irrelevant.
473: */
474:
475: if (cmppred == NULL ||
476: (* cmppred) (findpos, scan) == 0)
477: break;
478: }
479:
480: if (prev == NULL)
481: mdlistp->mdl_first = scan;
482: else
483: LINK (prev, ptroff) = scan;
484:
485: if ((LINK (scan, ptroff) = findpos) == NULL)
486: mdlistp->mdl_last = scan;
487:
488: mdlistp->mdl_count ++;
489: }
490: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.