|
|
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: #include "input.h" ! 40: ! 41: #include "mdev.h" ! 42: ! 43: ! 44: LOCAL mdev_t * _mdevices; ! 45: ! 46: ! 47: /* ! 48: * Find a device by symbol. ! 49: */ ! 50: ! 51: #if USE_PROTO ! 52: mdev_t * (find_mdev) (symbol_t * sym) ! 53: #else ! 54: mdev_t * ! 55: find_mdev ARGS ((sym)) ! 56: symbol_t * sym; ! 57: #endif ! 58: { ! 59: mdev_t * scan; ! 60: ! 61: for (scan = _mdevices ; scan != NULL ; scan = scan->md_next) { ! 62: ! 63: if (scan->md_devname == sym) ! 64: return scan; ! 65: } ! 66: ! 67: return NULL; ! 68: } ! 69: ! 70: ! 71: /* ! 72: * Write a single number or a range of device major numbers. ! 73: */ ! 74: ! 75: #if USE_PROTO ! 76: LOCAL int write_range (input_t * input, maj_t major [2]) ! 77: #else ! 78: LOCAL int ! 79: write_range (input, major) ! 80: input_t * input; ! 81: maj_t major [2]; ! 82: #endif ! 83: { ! 84: if (major [0] == major [1]) ! 85: return (* input->in_filter) (input, "%d\t", major [0]); ! 86: ! 87: return (* input->in_filter) (input, "%d-%d\t", major [0], major [1]); ! 88: } ! 89: ! 90: ! 91: /* ! 92: * Regenerate an 'mdevice' line from the stored record. ! 93: */ ! 94: ! 95: #define HYPHEN(x) ((x) == NULL ? (unsigned char *) "-" : (x)) ! 96: ! 97: #if USE_PROTO ! 98: void (write_mdevice) (mdev_t * mdevp, input_t * input) ! 99: #else ! 100: void ! 101: write_mdevice ARGS ((mdevp, input)) ! 102: mdev_t * mdevp; ! 103: input_t * input; ! 104: #endif ! 105: { ! 106: if ((* input->in_filter) (input, "%s<1>%s<2>%s<3>%s<4>", ! 107: mdevp->md_devname->s_data, ! 108: HYPHEN (mdevp->md_functions->s_data), ! 109: HYPHEN (mdevp->md_flags->s_data), ! 110: mdevp->md_prefix->s_data) < 0 || ! 111: write_range (input, mdevp->md_blk_maj) < 0 || ! 112: write_range (input, mdevp->md_chr_maj) < 0 || ! 113: (* input->in_filter) (input, "%d<7>%d<8>%d<9>%d\n", ! 114: mdevp->md_minor_min, mdevp->md_minor_max, ! 115: mdevp->md_dma_chan, mdevp->md_cpu_id) < 0) { ! 116: ! 117: throw_error ("Output error"); ! 118: } ! 119: } ! 120: ! 121: ! 122: /* ! 123: * Read lines from an "mdevice" file. ! 124: * ! 125: * This code is really messy. My apologies. ! 126: */ ! 127: ! 128: #if USE_PROTO ! 129: LOCAL mdev_t * (read_mdevice) (input_t * input, lex_t * lexp, int * end_char) ! 130: #else ! 131: LOCAL mdev_t * ! 132: read_mdevice ARGS ((input, lexp, end_char)) ! 133: input_t * input; ! 134: lex_t * lexp; ! 135: int * end_char; ! 136: #endif ! 137: { ! 138: VOLATILE int ch = '\n'; ! 139: mdev_t * VOLATILE mdevp; ! 140: ehand_t err; ! 141: lex_t functions = { NULL, NULL, "-", MDEV_FUNCS, LEX_WILD }; ! 142: lex_t flags = { NULL, NULL, "-", MDEV_FLAGS, LEX_WILD }; ! 143: ! 144: functions.l_prev = lexp; ! 145: flags.l_prev = lexp; ! 146: ! 147: if ((mdevp = (mdev_t *) malloc (sizeof (* mdevp))) == NULL) ! 148: throw_error ("out of memory in read_mdevice ()"); ! 149: ! 150: if (PUSH_HANDLER (err) == 0) { ! 151: /* ! 152: * If the first thing on the line works out to be an EOF, ! 153: * then bail out without an error. ! 154: */ ! 155: ! 156: ch = read_symbol (input, lexp, & mdevp->md_devname); ! 157: ! 158: if (mdevp->md_devname == NULL) { ! 159: /* ! 160: * We allow an EOF at the beginning of a line and we ! 161: * also allow a blank line. ! 162: */ ! 163: ! 164: free (mdevp); ! 165: mdevp = NULL; ! 166: goto at_eof; ! 167: } ! 168: check_not_eol (ch); ! 169: ! 170: if (mdevp->md_devname->s_size > MAX_DEVNAME) ! 171: throw_error ("device name must be <= %d characters", ! 172: MAX_DEVNAME); ! 173: ! 174: /* ! 175: * We read the functions and characteristics field as symbols, ! 176: * even though they are really strings, since it makes no ! 177: * difference to the result. ! 178: */ ! 179: ! 180: ch = read_symbol (input, & functions, & mdevp->md_functions); ! 181: if (mdevp->md_functions == NULL && ch != '-') ! 182: throw_error ("Unable to read functions"); ! 183: check_not_eol (ch); ! 184: ! 185: ch = read_symbol (input, & flags, & mdevp->md_flags); ! 186: if (mdevp->md_flags == NULL && ch != '-') ! 187: throw_error ("Unable to read flags"); ! 188: check_not_eol (ch); ! 189: ! 190: if ((mdev_flag (mdevp, MDEV_BLOCK) || ! 191: mdev_flag (mdevp, MDEV_CHAR) || ! 192: mdev_flag (mdevp, MDEV_STREAM)) && ! 193: ! mdev_flag (mdevp, MDEV_DDI_DDK)) { ! 194: ! 195: throw_error ("devices must be DDI/DDK compliant"); ! 196: } ! 197: ! 198: ! 199: /* ! 200: * We don't check for a unique device prefix, since there may ! 201: * be a legitimate reason to configure the same prefix twice. ! 202: * ! 203: * If the user installs multiple devices with the same prefix, ! 204: * the linker should catch it. Of course, a registration ! 205: * system might help. We only enforce the size limit for ! 206: * drivers... other kernel facilities can user longer names. ! 207: */ ! 208: ! 209: ch = read_symbol (input, lexp, & mdevp->md_prefix); ! 210: check_not_eol (ch); ! 211: ! 212: if ((mdev_flag (mdevp, MDEV_BLOCK) || ! 213: mdev_flag (mdevp, MDEV_CHAR) || ! 214: mdev_flag (mdevp, MDEV_STREAM)) && ! 215: mdevp->md_prefix->s_size > MAX_PREFIX) ! 216: throw_error ("device prefix must be <= %d characters", ! 217: MAX_PREFIX); ! 218: ! 219: ! 220: ch = read_uints (input, lexp, mdevp->md_blk_maj, RANGE); ! 221: check_not_eol (ch); ! 222: ! 223: if (mdev_flag (mdevp, MDEV_BLOCK)) { ! 224: ! 225: if (mdevp->md_blk_maj [0] > mdevp->md_blk_maj [1]) ! 226: throw_error ("lower range bound higher than upper bound"); ! 227: ! 228: if (mdevp->md_blk_maj [0] < MAJOR_RESERVED) ! 229: throw_error ("major devices up to %d reserved", ! 230: MAJOR_RESERVED - 1); ! 231: ! 232: } else if (mdev_flag (mdevp, MDEV_COHERENT)) { ! 233: ! 234: if (mdevp->md_blk_maj [0] != mdevp->md_blk_maj [1]) ! 235: throw_error ("Coherent devices occupy a single major number"); ! 236: ! 237: if (mdevp->md_blk_maj [0] >= MAJOR_RESERVED) ! 238: throw_error ("Coherent devices only in range 0-%d", ! 239: MAJOR_RESERVED - 1); ! 240: } else ! 241: mdevp->md_blk_maj [0] = mdevp->md_blk_maj [1] = 0; ! 242: ! 243: ! 244: ch = read_uints (input, lexp, mdevp->md_chr_maj, RANGE); ! 245: check_not_eol (ch); ! 246: ! 247: if (mdev_flag (mdevp, MDEV_CHAR)) { ! 248: ! 249: if (mdevp->md_chr_maj [0] > mdevp->md_chr_maj [1]) ! 250: throw_error ("lower range bound higher that upper bound"); ! 251: ! 252: if (mdevp->md_chr_maj [0] < MAJOR_RESERVED) ! 253: throw_error ("major devices 0-%d reserved", ! 254: MAJOR_RESERVED - 1); ! 255: } else if (mdev_flag (mdevp, MDEV_COHERENT)) { ! 256: ! 257: if (mdevp->md_chr_maj [0] != mdevp->md_blk_maj [0] || ! 258: mdevp->md_blk_maj [0] != mdevp->md_chr_maj [0]) ! 259: throw_error ("Coherent drivers must have same " ! 260: "block and character numbers"); ! 261: } else ! 262: mdevp->md_chr_maj [0] = mdevp->md_chr_maj [1] = 0; ! 263: ! 264: ch = read_uints (input, lexp, & mdevp->md_minor_min, ! 265: NO_RANGE); ! 266: check_not_eol (ch); ! 267: ! 268: ch = read_uints (input, lexp, & mdevp->md_minor_max, ! 269: NO_RANGE); ! 270: check_not_eol (ch); ! 271: ! 272: if (mdevp->md_minor_min > mdevp->md_minor_max) ! 273: throw_error ("minor minimum higher than maximum"); ! 274: ! 275: ch = read_ints (input, lexp, & mdevp->md_dma_chan, NO_RANGE); ! 276: ! 277: if (ch != '\n' && ch != SYM_EOF) { ! 278: /* ! 279: * The "cpu_id" field is optional. ! 280: */ ! 281: ! 282: ch = read_ints (input, lexp, & mdevp->md_cpu_id, ! 283: NO_RANGE); ! 284: } else ! 285: mdevp->md_cpu_id = -1; ! 286: ! 287: ch = expect_eol (input, lexp, ch); ! 288: ! 289: ! 290: /* ! 291: * Having passed all the reasonableness checks, we link the ! 292: * new entry into the chain. ! 293: */ ! 294: ! 295: mdevp->md_sdevices = NULL; ! 296: mdevp->md_interrupt = 0; ! 297: ! 298: mdevp->md_configure = MD_INSTALLABLE; ! 299: } else { ! 300: ! 301: free (mdevp); ! 302: CHAIN_ERROR (err); ! 303: } ! 304: ! 305: at_eof: ! 306: POP_HANDLER (err); ! 307: ! 308: * end_char = ch; ! 309: return mdevp; ! 310: } ! 311: ! 312: ! 313: /* ! 314: * This function is passed as a parameter to read_dev_string () to read an ! 315: * 'mtune' entry (usually a program argument) and hook it into a global list. ! 316: */ ! 317: ! 318: #if USE_PROTO ! 319: LOCAL int _read_mdev_string (input_t * input, lex_t * lexp, ! 320: mdev_t ** mdlistp) ! 321: #else ! 322: LOCAL int ! 323: _read_mdev_string (input, lexp, mdlistp) ! 324: input_t * input; ! 325: lex_t * lexp; ! 326: mdev_t ** mdlistp; ! 327: #endif ! 328: { ! 329: mdev_t * mdevp; ! 330: int ch; ! 331: ! 332: if ((mdevp = read_mdevice (input, lexp, & ch)) != NULL) { ! 333: mdevp->md_next = * mdlistp; ! 334: * mdlistp = mdevp; ! 335: } ! 336: ! 337: return ch; ! 338: } ! 339: ! 340: ! 341: /* ! 342: * Common code from _read_mdevice_file () to link an entry into the global ! 343: * 'mdevice' chain. ! 344: */ ! 345: ! 346: #if USE_PROTO ! 347: LOCAL void (link_mdevice) (mdev_t * mdevp, input_t * input) ! 348: #else ! 349: LOCAL void ! 350: link_mdevice ARGS ((mdevp, input)) ! 351: mdev_t * mdevp; ! 352: input_t * input; ! 353: #endif ! 354: { ! 355: if (find_mdev (mdevp->md_devname) != NULL) ! 356: throw_error ("device name must be unique"); ! 357: ! 358: mdevp->md_next = _mdevices; ! 359: _mdevices = mdevp; ! 360: ! 361: write_mdevice (mdevp, input); ! 362: } ! 363: ! 364: ! 365: /* ! 366: * This function is passed as a pointer to read_dev_file () to read an ! 367: * 'mdevice' entry from the input and link it in to the global device list. ! 368: * ! 369: * The extra argument is the head of a list of 'mdevice' entries which are to ! 370: * replace/be added to the existing 'mdevice' entries. ! 371: */ ! 372: ! 373: #if USE_PROTO ! 374: LOCAL int _read_mdevice_file (input_t * input, lex_t * lexp, ! 375: mdev_t ** changes) ! 376: #else ! 377: LOCAL int ! 378: _read_mdevice_file (input, lexp, changes) ! 379: input_t * input; ! 380: lex_t * lexp; ! 381: mdev_t ** changes; ! 382: #endif ! 383: { ! 384: mdev_t * mdevp; ! 385: int ch; ! 386: ! 387: if ((mdevp = read_mdevice (input, lexp, & ch)) == NULL) { ! 388: if (ch == READ_EOF) { ! 389: /* ! 390: * Blow the remaining changes out as new entries. ! 391: */ ! 392: ! 393: while ((mdevp = * changes) != NULL) { ! 394: * changes = mdevp->md_next; ! 395: link_mdevice (mdevp, input); ! 396: } ! 397: } ! 398: return ch; ! 399: } ! 400: ! 401: /* ! 402: * Link the newly-allocated mdevice entry into the global ! 403: * mdevice chain. ! 404: */ ! 405: ! 406: if (changes) { ! 407: mdev_t ** scan; ! 408: ! 409: for (scan = changes ; * scan != NULL ; ! 410: scan = & (* scan)->md_next) { ! 411: ! 412: if ((* scan)->md_devname == mdevp->md_devname) { ! 413: /* ! 414: * Our current entry is being replaced by a ! 415: * new one; unlink the new entry from the ! 416: * change list and discard the old entry. ! 417: */ ! 418: ! 419: free (mdevp); ! 420: ! 421: if (report_mode ()) ! 422: return ch; ! 423: ! 424: mdevp = * scan; ! 425: * scan = mdevp->md_next; ! 426: break; ! 427: } ! 428: } ! 429: } ! 430: ! 431: link_mdevice (mdevp, input); ! 432: return ch; ! 433: } ! 434: ! 435: ! 436: /* ! 437: * Test a device for a function code; returns 1 if code is present, or 0 if ! 438: * code is not specified for device. ! 439: */ ! 440: ! 441: #if USE_PROTO ! 442: int (mdev_func) (mdev_t * mdevp, char func) ! 443: #else ! 444: int ! 445: mdev_func ARGS ((mdevp, func)) ! 446: mdev_t * mdevp; ! 447: char func; ! 448: #endif ! 449: { ! 450: if (mdevp->md_functions == NULL) ! 451: return 0; ! 452: return strchr (mdevp->md_functions->s_data, func) != NULL; ! 453: } ! 454: ! 455: ! 456: /* ! 457: * Test device characteristics; returns 1 if characteristic is specified for ! 458: * device, 0 if it is not. ! 459: */ ! 460: ! 461: #if USE_PROTO ! 462: int (mdev_flag) (mdev_t * mdevp, char flag) ! 463: #else ! 464: int ! 465: mdev_flag ARGS ((mdevp, flag)) ! 466: mdev_t * mdevp; ! 467: char flag; ! 468: #endif ! 469: { ! 470: if (mdevp->md_flags == NULL) ! 471: return 0; ! 472: return strchr (mdevp->md_flags->s_data, flag) != NULL; ! 473: } ! 474: ! 475: ! 476: /* ! 477: * Read in an "mtune" entry from a string and add it to a list. ! 478: */ ! 479: ! 480: #if USE_PROTO ! 481: void read_mdev_string (CONST char * string, VOID * extra) ! 482: #else ! 483: void ! 484: read_mdev_string (string, extra) ! 485: CONST char * string; ! 486: VOID * extra; ! 487: #endif ! 488: { ! 489: read_dev_string (string, (dev_func_p) _read_mdev_string, extra); ! 490: } ! 491: ! 492: ! 493: /* ! 494: * Suck in a complete 'mdevice' file. ! 495: */ ! 496: ! 497: #if USE_PROTO ! 498: void (read_mdev_file) (CONST char * inname, CONST char * outname, VOID * extra) ! 499: #else ! 500: void ! 501: read_mdev_file ARGS ((inname, outname, extra)) ! 502: CONST char * inname; ! 503: CONST char * outname; ! 504: VOID * extra; ! 505: #endif ! 506: { ! 507: read_dev_file (inname, outname, (dev_func_p) _read_mdevice_file, ! 508: extra); ! 509: } ! 510: ! 511: ! 512: /* ! 513: * Iterate over all the mdevices in the system. ! 514: */ ! 515: ! 516: #if USE_PROTO ! 517: void (for_all_mdevices) (miter_t iter, VOID * extra) ! 518: #else ! 519: void ! 520: for_all_mdevices ARGS ((iter, extra)) ! 521: miter_t iter; ! 522: VOID * extra; ! 523: #endif ! 524: { ! 525: mdev_t * temp; ! 526: ! 527: for (temp = _mdevices ; temp != NULL ; temp = temp->md_next) ! 528: (* iter) (extra, temp); ! 529: } ! 530: ! 531: ! 532: /* ! 533: * Generic insertion sort algorithm for "mdevice" entries based on a ! 534: * selection predicate and a comparison predicate. ! 535: * ! 536: * So that this can be a reasonably generic function, we pass it the internal ! 537: * offset of the "mdev_t *" member of the "mdevice" structure which will be ! 538: * used to link together the sorted entries. ! 539: * ! 540: * The return value is the length of the sorted list. ! 541: */ ! 542: ! 543: #define LINK(mdevp,off) (* (mdev_t **) ((char *) (mdevp) + off)) ! 544: ! 545: #if USE_PROTO ! 546: int (mdev_sort) (mdev_t ** mdlistp, mdev_t ** mdendp, msel_t selpred, ! 547: mcmp_t cmppred, size_t ptroff) ! 548: #else ! 549: int ! 550: mdev_sort ARGS ((mdlistp, mdendp, selpred, cmppred, ptroff)) ! 551: mdev_t ** mdlistp; ! 552: mdev_t ** mdendp; ! 553: msel_t selpred; ! 554: mcmp_t cmppred; ! 555: size_t ptroff; ! 556: #endif ! 557: { ! 558: mdev_t * scan; ! 559: mdev_t * next; ! 560: int count; ! 561: ! 562: if (mdlistp == NULL || ptroff > sizeof (mdev_t)) ! 563: throw_error ("bogus parameters to mdev_sort ()"); ! 564: ! 565: ! 566: /* ! 567: * We'll just insert each selected member of the total list of ! 568: * mdevices into the output list in order by running down the output ! 569: * list until we compare true. ! 570: * ! 571: * We fetch "scan" before initializing the output list in case we are ! 572: * sorting the master device list. ! 573: */ ! 574: ! 575: * mdlistp = NULL; ! 576: if (mdendp != NULL) ! 577: * mdendp = NULL; ! 578: ! 579: for (count = 0, scan = _mdevices ; scan != NULL ; scan = next) { ! 580: mdev_t * findpos; ! 581: mdev_t * prev; ! 582: ! 583: /* ! 584: * We get the "next" entry now in case we are sorting the ! 585: * master list. We allow a "selpred" of NULL to select all ! 586: * the entries. ! 587: */ ! 588: ! 589: next = scan->md_next; ! 590: ! 591: if (selpred != NULL && (* selpred) (scan) == 0) ! 592: continue; ! 593: ! 594: ! 595: /* ! 596: * Now attempt to find the right place for the new entry and ! 597: * insert it there. ! 598: */ ! 599: ! 600: prev = NULL; ! 601: ! 602: for (findpos = * mdlistp ; findpos != NULL ; ! 603: findpos = LINK ((prev = findpos), ptroff)) { ! 604: /* ! 605: * A "cmppred" that is NULL means that the order of ! 606: * output entries is irrelevant. ! 607: */ ! 608: ! 609: if (cmppred == NULL || ! 610: (* cmppred) (findpos, scan) == 0) ! 611: break; ! 612: } ! 613: ! 614: if (prev == NULL) ! 615: * mdlistp = scan; ! 616: else ! 617: LINK (prev, ptroff) = scan; ! 618: ! 619: if ((LINK (scan, ptroff) = findpos) == NULL && mdendp != NULL) ! 620: * mdendp = scan; ! 621: ! 622: count ++; ! 623: } ! 624: ! 625: return count; ! 626: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.