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