|
|
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.