|
|
1.1 root 1: /*
2: *-IMPORTS:
3: * <sys/compat.h>
4: * LOCAL
5: * USE_PROTO
6: * ARGS ()
7: * <stdlib.h>
8: * NULL
9: * free ()
10: * malloc ()
11: * "ehand.h"
12: * ehand_t
13: * CHAIN_ERROR ();
14: * POP_HANDLER ();
15: * PUSH_HANDLER ();
16: * throw_error ();
17: * "mdev.h"
18: * mdev_t
19: * check_errs ()
20: * find_mdev ()
21: * "symbol.h"
22: * LEX_WILD
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:
34: #include "ehand.h"
35: #include "mdev.h"
36: #include "symbol.h"
37: #include "read.h"
38: #include "lex.h"
39:
40: #include "sdev.h"
41:
42: #include <string.h>
43:
44:
45: LOCAL sdev_t * sdevices;
46:
47:
48: /*
49: * Simple local function for testing to see if IOA or CMA ranges intersect.
50: */
51:
52: #ifdef USE_PROTO
53: LOCAL int (intersect) (CONST unsigned long * left, CONST unsigned long * right)
54: #else
55: LOCAL int
56: intersect ARGS ((left, right))
57: CONST int * left;
58: CONST int * right;
59: #endif
60: {
61: return (left [0] >= right [0] && left [0] <= right [1]) ||
62: (left [1] >= right [0] && left [1] <= right [1]);
63: }
64:
65:
66: /*
67: * This function checks all existing 'sdevice' entries to see if there is an
68: * IOA conflict.
69: *
70: * The value returned is the same value that would be returned by the matching
71: * check performed by the idcheck(1M) utility, namely:
72: * 0 if no conflict.
73: * 1 if there is a conflict.
74: * 3 if there is a conflict, but the 'mdevice' entry has the O flag set.
75: *
76: * As usual, the specification does not take into account the possibility that
77: * an IOA range may conflict with several devices with a different setting of
78: * the 'O' flag. This routine returns 3 if and only if all devices which have
79: * IOA conflicts have the 'O' flag set.
80: *
81: * If "who" is non-NULL, it will be written with the address of the sdevice
82: * entry which caused the conflict which caused the non-zero return.
83: */
84:
85: #ifdef __USE_PROTO__
86: int (sdev_check_ioa) (CONST ioa_t * check, sdev_t ** who)
87: #else
88: int
89: sdev_check_ioa ARGS ((check, who))
90: CONST int * check;
91: sdev_t ** who;
92: #endif
93: {
94: sdev_t * sdevp;
95: int share_conflict = 0;
96:
97: if (check == NULL)
98: throw_error ("check argument is NULL in sdev_check_ioa ()");
99:
100: if (check [1] == 0)
101: return 0;
102:
103: for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
104:
105: if (sdevp->sd_ioa [1] > 0 &&
106: intersect (sdevp->sd_ioa, check)) {
107:
108: if (mdev_flag (sdevp->sd_mdevp,
109: MDEV_ALLOW_IOA_OVERLAP)) {
110: /*
111: * Since multiple entries can cause a shared
112: * IOA conflict, return the first.
113: */
114:
115: if (who != NULL && share_conflict == 0)
116: * who = sdevp;
117:
118: share_conflict = 3;
119: } else {
120: /*
121: * Since this 'sdevice' entry caused a fatal
122: * conflict, we always return that one.
123: */
124:
125: if (who != NULL)
126: * who = sdevp;
127:
128: return 1;
129: }
130: }
131: }
132:
133: return share_conflict;
134: }
135:
136:
137: /*
138: * This function checks all existing 'sdevice' entries for a CMA conflict.
139: *
140: * The value returned will be 1 if there is a conflict and 0 if no conflict
141: * occurs. If the "who" parameter is non-NULL, it will be written with the
142: * address of the 'sdevice' entry that caused the conflict (if any).
143: */
144:
145: #ifdef __USE_PROTO__
146: int (sdev_check_cma) (CONST cma_t * check, sdev_t ** who)
147: #else
148: int
149: sdev_check_cma ARGS ((check, who))
150: CONST int * check;
151: sdev_t ** who;
152: #endif
153: {
154: sdev_t * sdevp;
155:
156: if (check == NULL)
157: throw_error ("check argument is NULL in sdev_check_cma ()");
158:
159: if (check [1] == 0)
160: return 0;
161:
162: for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
163:
164: if (sdevp->sd_cma [1] > 0 &&
165: intersect (sdevp->sd_cma, check)) {
166:
167: /*
168: * Since this 'sdevice' entry caused a fatal
169: * conflict, we always return that one.
170: */
171:
172: if (who != NULL)
173: * who = sdevp;
174:
175: return 1;
176: }
177: }
178:
179: return 0;
180: }
181:
182:
183: /*
184: * This function checks all existing 'sdevice' entries to see if the interrupt
185: * vector 'vec' is in use by any of them. If any other devices are using the
186: * vector, the lowest non-zero 'type' value specified by any of them is
187: * returned. If the "who" entry is non-NULL, the address of the first entry
188: * responsible for the return value is returned.
189: */
190:
191: #ifdef __USE_PROTO__
192: int (sdev_check_vector) (int vec, sdev_t ** who)
193: #else
194: int
195: sdev_check_vector ARGS ((vec, who))
196: int vec;
197: sdev_t ** who;
198: #endif
199: {
200: sdev_t * sdevp;
201: int itype = MAX_ITYPE + 1;
202:
203: if (vec == 0)
204: return 0;
205:
206: for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
207:
208: if (sdevp->sd_vector == vec && sdevp->sd_itype < itype) {
209:
210: if (who != NULL)
211: * who = sdevp;
212:
213: itype = sdevp->sd_itype;
214: }
215: }
216:
217: return itype <= MAX_ITYPE ? itype : 0;
218: }
219:
220:
221: /*
222: * Read a line from an "sdevice" file.
223: *
224: * This code is really messy. My apologies.
225: */
226:
227: #ifdef USE_PROTO
228: LOCAL int (read_sdevice) (input_t * input, lex_t * lexp)
229: #else
230: LOCAL int
231: read_sdevice ARGS ((input, lexp))
232: input_t * input;
233: lex_t * lexp;
234: #endif
235: {
236: int ch = '\n';
237: sdev_t * sdevp;
238: sdev_t * serr;
239: ehand_t err;
240: lex_t yesno = { NULL, NULL, "-", "ynYN", LEX_WILD };
241: symbol_t * config_flag;
242:
243: yesno.l_prev = lexp;
244:
245: if ((sdevp = (sdev_t *) malloc (sizeof (* sdevp))) == NULL)
246: throw_error ("out of memory in read_sdevice ()");
247:
248: if (PUSH_HANDLER (err) == 0) {
249: /*
250: * If the first thing on the line is EOF, that's not an error,
251: * just bail out.
252: */
253:
254: ch = read_symbol (input, lexp, & sdevp->sd_devname);
255:
256: if (sdevp->sd_devname == NULL)
257: goto at_eof;
258:
259: check_not_eol (ch);
260:
261: if (sdevp->sd_devname->s_size > MAX_DEVNAME)
262: throw_error ("device name must be <= %d characters",
263: MAX_DEVNAME);
264:
265: if ((sdevp->sd_mdevp = find_mdev (sdevp->sd_devname)) == NULL)
266: throw_error ("device name does not match any master device entry");
267:
268: if (mdev_flag (sdevp->sd_mdevp, MDEV_ONE_SDEVICE) &&
269: sdevp->sd_mdevp->md_sdevices != NULL)
270: throw_error ("only one sdevice entry permitted for this device");
271:
272:
273: /*
274: * We read the yes/no field as a symbol, since most of the
275: * entries will be identical.
276: */
277:
278: ch = read_symbol (input, & yesno, & config_flag);
279: check_not_eol (ch);
280:
281: if (config_flag->s_size > 1)
282: throw_error ("a single Y or N is required");
283:
284: sdevp->sd_config = (config_flag->s_data [0] == 'y' ||
285: config_flag->s_data [0] == 'Y');
286:
287:
288: ch = read_uints (input, lexp, & sdevp->sd_unit, NO_RANGE);
289: check_not_eol (ch);
290:
291: if (sdevp->sd_unit < sdevp->sd_mdevp->md_minor_min ||
292: sdevp->sd_unit > sdevp->sd_mdevp->md_minor_max)
293: throw_error ("unit number out of range for device");
294:
295: ch = read_uints (input, lexp, & sdevp->sd_ipl, NO_RANGE);
296: check_not_eol (ch);
297:
298: if (sdevp->sd_ipl > MAX_IPL)
299: throw_error ("IPL must be in the range 0 through %d",
300: MAX_IPL);
301:
302: ch = read_uints (input, lexp, & sdevp->sd_itype, NO_RANGE);
303: check_not_eol (ch);
304:
305: if (sdevp->sd_itype > MAX_ITYPE)
306: throw_error ("interrupt type must be in the range 0 to %d",
307: MAX_ITYPE);
308:
309: ch = read_uints (input, lexp, & sdevp->sd_vector, NO_RANGE);
310: check_not_eol (ch);
311:
312: /*
313: * The clock device is special-cased as the only thing that
314: * can use vector 0.
315: */
316:
317: if (strcmp (sdevp->sd_devname->s_data, "clock") != 0 &&
318: ((sdevp->sd_ipl > 0 && sdevp->sd_vector == 0) ||
319: (sdevp->sd_ipl == 0 && sdevp->sd_vector > 0))) {
320: throw_error ("IPL and vector must both be either zero or non-zero");
321: }
322:
323: if (sdevp->sd_vector > MAX_VECTOR)
324: throw_error ("vector numbers run from 0 (no vector) through %d",
325: MAX_VECTOR);
326:
327: switch (sdev_check_vector (sdevp->sd_vector, & serr)) {
328:
329: case INT_SHAREABLE:
330: if (sdevp->sd_itype == INT_SHAREABLE)
331: break;
332:
333: /* FALL THROUGH */
334:
335: case INT_PER_DEVICE:
336: if (serr->sd_devname == sdevp->sd_devname &&
337: sdevp->sd_itype >= INT_PER_DEVICE)
338: break;
339:
340: /* FALL THROUGH */
341:
342: case INT_PER_CHANNEL:
343: throw_error ("vector conflict with device %s",
344: serr->sd_devname->s_data);
345: break;
346:
347: case INT_NONE:
348: break;
349: }
350:
351: ch = read_ulongs (input, lexp, & sdevp->sd_ioa [0], NO_RANGE);
352: check_not_eol (ch);
353:
354: ch = read_ulongs (input, lexp, & sdevp->sd_ioa [1], NO_RANGE);
355: check_not_eol (ch);
356:
357: if (sdevp->sd_ioa [0] > sdevp->sd_ioa [1])
358: throw_error ("lower bound of address range higher than upper bound");
359:
360: if (sdevp->sd_ioa [1] > 0 &&
361: ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
362: throw_error ("software-only device cannot access I/O ports");
363:
364: switch (sdev_check_ioa (sdevp->sd_ioa, & serr)) {
365:
366: case 3:
367: if (mdev_flag (sdevp->sd_mdevp,
368: MDEV_ALLOW_IOA_OVERLAP)) {
369: /*
370: * Every device we might conflict with has the
371: * 'O' flag set and so do we.
372: */
373:
374: break;
375: }
376:
377: /* FALL THROUGH */
378:
379: default:
380: throw_error ("IOA conflict with device %s",
381: serr->sd_devname->s_data);
382: break;
383:
384: case 0:
385: break;
386: }
387:
388: ch = read_ulongs (input, lexp, & sdevp->sd_cma [0], NO_RANGE);
389: check_not_eol (ch);
390:
391: ch = read_ulongs (input, lexp, & sdevp->sd_cma [1], NO_RANGE);
392:
393: if (sdevp->sd_cma [0] > sdevp->sd_cma [1])
394: throw_error ("lower bound of address range higher than upper bound");
395:
396: if (sdevp->sd_cma [1] > 0 &&
397: ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
398: throw_error ("software-only device cannot access controller memory");
399:
400: if (sdev_check_cma (sdevp->sd_cma, & serr) != 0)
401: throw_error ("CMA conflict with device %s",
402: serr->sd_devname->s_data);
403:
404: ch = expect_eol (input, lexp, ch);
405:
406:
407: /*
408: * Having passed all the reasonableness checks, we link the
409: * new entry into the chain.
410: */
411:
412: sdevp->sd_next = sdevices;
413: sdevices = sdevp;
414:
415: sdevp->sd_mnext = sdevp->sd_mdevp->md_sdevices;
416: sdevp->sd_mdevp->md_sdevices = sdevp;
417:
418: if (sdevp->sd_mdevp->md_configure == MD_INSTALLABLE &&
419: sdevp->sd_config)
420: sdevp->sd_mdevp->md_configure = MD_ENABLED;
421:
422: if (sdevp->sd_itype > 0) {
423:
424: if (! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
425: throw_error ("software-only device cannot have a vector");
426:
427: sdevp->sd_mdevp->md_interrupt = 1;
428: }
429: } else {
430:
431: free (sdevp);
432: CHAIN_ERROR (err);
433: }
434:
435: at_eof:
436: POP_HANDLER (err);
437: return ch;
438: }
439:
440:
441: #if 0
442: /*
443: * Regenerate an 'sdevice' entry from the stored record.
444: */
445:
446: #ifdef USE_PROTO
447: void (write_sdevice) (sdev_t * sdevp, FILE * out)
448: #else
449: void
450: write_sdevice ARGS ((sdevp, out))
451: sdev_t * sdevp;
452: FILE * out;
453: #endif
454: {
455: (void) fprintf (out, "%-10s %c %-3d %-3d %-3d 0x%-6x 0x%-6x 0x%-10x 0x%-10x\n",
456: sdevp->sd_devname->s_data, sdevp->sd_config ? 'Y' : 'N',
457: sdevp->sd_ipl, sdevp->sd_itype, sdevp->sd_vector,
458: sdevp->sd_ioa [0], sdevp->sd_ioa [1], sdevp->sd_cma [0],
459: sdevp->sd_cma [1]);
460: }
461: #endif
462:
463:
464: /*
465: * Suck in a complete 'sdevice' file.
466: */
467:
468: #ifdef USE_PROTO
469: void (read_sdev_file) (CONST char * name)
470: #else
471: void
472: read_sdev_file ARGS ((name))
473: CONST char * name;
474: #endif
475: {
476: read_dev_file (name, read_sdevice);
477: }
478:
479:
480: /*
481: * Generic insertion sort algorithm for "sdevice" entries based on a
482: * selection predicate and a comparison predicate.
483: *
484: * So that this can be a reasonably generic function, we pass it the internal
485: * offset of the "sdev_t *" member of the "sdevice" structure which will be
486: * used to link together the sorted entries.
487: */
488:
489: #define LINK(sdevp,off) (* (sdev_t **) ((char *) (sdevp) + off))
490:
491: #ifdef USE_PROTO
492: void (sdev_sort) (sdlist_t * sdlistp, ssel_t selpred, scmp_t cmppred,
493: size_t ptroff)
494: #else
495: void
496: sdev_sort ARGS ((sdlistp, selpred, cmppred, ptroff))
497: sdlist_t * sdlistp;
498: ssel_t selpred;
499: scmp_t cmppred;
500: size_t ptroff;
501: #endif
502: {
503: sdev_t * scan;
504: sdev_t * next;
505:
506: if (sdlistp == NULL || ptroff > sizeof (sdev_t))
507: throw_error ("bogus parameters to sdev_sort ()");
508:
509:
510: /*
511: * We'll just insert each selected member of the total list of
512: * mdevices into the output list in order by running down the output
513: * list until we compare true.
514: *
515: * We fetch "scan" before initializing the output list in case we are
516: * sorting the master device list.
517: */
518:
519: scan = sdevices;
520:
521: sdlistp->sdl_first = sdlistp->sdl_last = NULL;
522: sdlistp->sdl_count = 0;
523:
524: for (; scan != NULL ; scan = next) {
525: sdev_t * findpos;
526: sdev_t * prev;
527:
528: /*
529: * We get the "next" entry now in case we are sorting the
530: * master list. We allow a "selpred" of NULL to select all
531: * the entries.
532: */
533:
534: next = scan->sd_next;
535:
536: if (selpred != NULL && (* selpred) (scan) == 0)
537: continue;
538:
539:
540: /*
541: * Now attempt to find the right place for the new entry and
542: * insert it there.
543: */
544:
545: prev = NULL;
546:
547: for (findpos = sdlistp->sdl_first ; findpos != NULL ;
548: findpos = LINK ((prev = findpos), ptroff)) {
549: /*
550: * A "cmppred" that is NULL means that the order of
551: * output entries is irrelevant.
552: */
553:
554: if (cmppred == NULL ||
555: (* cmppred) (findpos, scan) == 0)
556: break;
557: }
558:
559: if (prev == NULL)
560: sdlistp->sdl_first = scan;
561: else
562: LINK (prev, ptroff) = scan;
563:
564: if ((LINK (scan, ptroff) = findpos) == NULL)
565: sdlistp->sdl_last = scan;
566:
567: sdlistp->sdl_count ++;
568: }
569: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.