|
|
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: #include "input.h" ! 40: ! 41: #include "sdev.h" ! 42: ! 43: #include <string.h> ! 44: ! 45: ! 46: LOCAL sdev_t * _sdevices; ! 47: ! 48: ! 49: /* ! 50: * Macro to test whether some number ranges intersect; the arguments could be ! 51: * either a pointer to a pair of longs or a pair of ints. ! 52: */ ! 53: ! 54: #define INTERSECT(left,right) \ ! 55: (((left) [0] >= (right) [0] && (left) [0] <= (right) [1]) || \ ! 56: ((left) [1] >= (right) [0] && (left) [1] <= (right) [1])) ! 57: ! 58: ! 59: /* ! 60: * This function checks all existing 'sdevice' entries to see if there is an ! 61: * IOA conflict. ! 62: * ! 63: * The value returned is the same value that would be returned by the matching ! 64: * check performed by the idcheck(1M) utility, namely: ! 65: * 0 if no conflict. ! 66: * 1 if there is a conflict. ! 67: * 3 if there is a conflict, but the 'mdevice' entry has the O flag set. ! 68: * ! 69: * As usual, the specification does not take into account the possibility that ! 70: * an IOA range may conflict with several devices with a different setting of ! 71: * the 'O' flag. This routine returns 3 if and only if all devices which have ! 72: * IOA conflicts have the 'O' flag set. ! 73: * ! 74: * If "who" is non-NULL, it will be written with the address of the sdevice ! 75: * entry which caused the conflict which caused the non-zero return. ! 76: */ ! 77: ! 78: #ifdef __USE_PROTO__ ! 79: LOCAL int (sdev_check_ioa) (sdev_t * check) ! 80: #else ! 81: LOCAL int ! 82: sdev_check_ioa ARGS ((check)) ! 83: sdev_t * check; ! 84: #endif ! 85: { ! 86: sdev_t * sdevp; ! 87: int share_conflict = 0; ! 88: ! 89: if (check == NULL) ! 90: throw_error ("check argument is NULL in sdev_check_ioa ()"); ! 91: ! 92: if (check->sd_ioa [1] == 0) ! 93: return 0; ! 94: ! 95: for (sdevp = _sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) { ! 96: ! 97: if (sdevp->sd_ioa [1] == 0 || ! 98: ! INTERSECT (sdevp->sd_ioa, check->sd_ioa)) ! 99: continue; ! 100: ! 101: if (mdev_flag (sdevp->sd_mdevp, MDEV_ALLOW_IOA_OVERLAP) && ! 102: mdev_flag (check->sd_mdevp, MDEV_ALLOW_IOA_OVERLAP)) { ! 103: if (share_conflict == 0) ! 104: share_conflict = 3; ! 105: } else { ! 106: report_conflict (check->sd_devname->s_data, ! 107: sdevp->sd_devname->s_data, ! 108: "IOA overlap"); ! 109: share_conflict = 1; ! 110: } ! 111: } ! 112: return share_conflict; ! 113: } ! 114: ! 115: ! 116: /* ! 117: * This function checks all existing 'sdevice' entries for a CMA conflict. ! 118: * ! 119: * The value returned will be 1 if there is a conflict and 0 if no conflict ! 120: * occurs. If the "who" parameter is non-NULL, it will be written with the ! 121: * address of the 'sdevice' entry that caused the conflict (if any). ! 122: */ ! 123: ! 124: #ifdef __USE_PROTO__ ! 125: LOCAL int (sdev_check_cma) (sdev_t * check) ! 126: #else ! 127: LOCAL int ! 128: sdev_check_cma ARGS ((check)) ! 129: sdev_t * check; ! 130: #endif ! 131: { ! 132: sdev_t * sdevp; ! 133: int conflict = 0; ! 134: ! 135: if (check == NULL) ! 136: throw_error ("check argument is NULL in sdev_check_cma ()"); ! 137: ! 138: if (check->sd_cma [1] == 0) ! 139: return 0; ! 140: ! 141: for (sdevp = _sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) { ! 142: ! 143: if (sdevp->sd_cma [1] > 0 && ! 144: INTERSECT (sdevp->sd_cma, check->sd_cma)) { ! 145: ! 146: report_conflict (check->sd_devname->s_data, ! 147: sdevp->sd_devname->s_data, ! 148: "CMA overlap"); ! 149: conflict = 1; ! 150: } ! 151: } ! 152: ! 153: return conflict; ! 154: } ! 155: ! 156: ! 157: /* ! 158: * This function checks all existing 'sdevice' entries to see if the interrupt ! 159: * vector 'vec' is in use by any of them. ! 160: */ ! 161: ! 162: #ifdef __USE_PROTO__ ! 163: LOCAL int (sdev_check_vector) (sdev_t * check) ! 164: #else ! 165: LOCAL int ! 166: sdev_check_vector ARGS ((check)) ! 167: sdev_t * check; ! 168: #endif ! 169: { ! 170: sdev_t * sdevp; ! 171: int conflict = 0; ! 172: ! 173: if (check->sd_vector == 0) ! 174: return 0; ! 175: ! 176: for (sdevp = _sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) { ! 177: ! 178: if (sdevp->sd_vector != check->sd_vector) ! 179: continue; ! 180: ! 181: switch (sdevp->sd_itype) { ! 182: ! 183: case INT_SHAREABLE: ! 184: if (check->sd_itype == INT_SHAREABLE) ! 185: break; ! 186: ! 187: /* FALL THROUGH */ ! 188: ! 189: case INT_PER_DEVICE: ! 190: if (sdevp->sd_devname == check->sd_devname && ! 191: check->sd_itype >= INT_PER_DEVICE) ! 192: break; ! 193: ! 194: /* FALL THROUGH */ ! 195: ! 196: case INT_PER_CHANNEL: ! 197: report_conflict (check->sd_devname->s_data, ! 198: sdevp->sd_devname->s_data, ! 199: "Interrupt vector conflict"); ! 200: ! 201: conflict = 1; ! 202: break; ! 203: ! 204: case INT_NONE: ! 205: break; ! 206: } ! 207: } ! 208: ! 209: return conflict; ! 210: } ! 211: ! 212: ! 213: /* ! 214: * Regenerate an 'sdevice' entry from the stored record. ! 215: */ ! 216: ! 217: #if USE_PROTO ! 218: void (write_sdevice) (sdev_t * sdevp, input_t * input) ! 219: #else ! 220: void ! 221: write_sdevice ARGS ((sdevp, input)) ! 222: sdev_t * sdevp; ! 223: input_t * input; ! 224: #endif ! 225: { ! 226: if ((* input->in_filter) (input, "%s<1>%c<2>%d<3>%d<4>%d<5>%d<6>" ! 227: "0x%x<7>0x%x<8>0x%x<9>0x%x\n", ! 228: sdevp->sd_devname->s_data, ! 229: sdevp->sd_config ? 'Y' : 'N', ! 230: sdevp->sd_unit, sdevp->sd_ipl, ! 231: sdevp->sd_itype, sdevp->sd_vector, ! 232: sdevp->sd_ioa [0], sdevp->sd_ioa [1], ! 233: sdevp->sd_cma [0], sdevp->sd_cma [1]) < 0) { ! 234: ! 235: throw_error ("Output error"); ! 236: } ! 237: } ! 238: ! 239: ! 240: /* ! 241: * Read a line from an "sdevice" file. ! 242: * ! 243: * This code is really messy. My apologies. ! 244: */ ! 245: ! 246: #if USE_PROTO ! 247: LOCAL sdev_t * (read_sdevice) (input_t * input, lex_t * lexp, int * end_char) ! 248: #else ! 249: LOCAL sdev_t * ! 250: read_sdevice ARGS ((input, lexp, end_char)) ! 251: input_t * input; ! 252: lex_t * lexp; ! 253: int * end_char; ! 254: #endif ! 255: { ! 256: VOLATILE int ch = '\n'; ! 257: sdev_t * VOLATILE sdevp; ! 258: sdev_t * scan; ! 259: ehand_t err; ! 260: lex_t yesno = { NULL, NULL, "-", "ynYN", LEX_WILD }; ! 261: symbol_t * config_flag; ! 262: ! 263: yesno.l_prev = lexp; ! 264: ! 265: if ((sdevp = (sdev_t *) malloc (sizeof (* sdevp))) == NULL) ! 266: throw_error ("out of memory in read_sdevice ()"); ! 267: ! 268: if (PUSH_HANDLER (err) == 0) { ! 269: /* ! 270: * If the first thing on the line is EOF, that's not an error, ! 271: * just bail out. ! 272: */ ! 273: ! 274: ch = read_symbol (input, lexp, & sdevp->sd_devname); ! 275: ! 276: if (sdevp->sd_devname == NULL) { ! 277: ! 278: free (sdevp); ! 279: sdevp = NULL; ! 280: goto at_eof; ! 281: } ! 282: ! 283: check_not_eol (ch); ! 284: ! 285: if (sdevp->sd_devname->s_size > MAX_DEVNAME) ! 286: throw_error ("device name must be <= %d characters", ! 287: MAX_DEVNAME); ! 288: ! 289: /* ! 290: * We read the yes/no field as a symbol, since most of the ! 291: * entries will be identical. ! 292: */ ! 293: ! 294: ch = read_symbol (input, & yesno, & config_flag); ! 295: check_not_eol (ch); ! 296: ! 297: if (config_flag->s_size > 1) ! 298: throw_error ("a single Y or N is required"); ! 299: ! 300: sdevp->sd_config = (config_flag->s_data [0] == 'y' || ! 301: config_flag->s_data [0] == 'Y'); ! 302: ! 303: /* ! 304: * Read the unit number; since we match both the unit number ! 305: * and the device name when changing an entry, we only allow ! 306: * one sdevice entry per unit/device combination. ! 307: */ ! 308: ! 309: ch = read_uints (input, lexp, & sdevp->sd_unit, NO_RANGE); ! 310: check_not_eol (ch); ! 311: ! 312: for (scan = _sdevices ; scan != NULL ; scan = scan->sd_next) ! 313: if (scan->sd_devname == sdevp->sd_devname && ! 314: scan->sd_unit == sdevp->sd_unit) { ! 315: throw_error ("Only one sdevice entry per device unit allowed"); ! 316: } ! 317: ! 318: ! 319: ch = read_uints (input, lexp, & sdevp->sd_ipl, NO_RANGE); ! 320: check_not_eol (ch); ! 321: ! 322: if (sdevp->sd_ipl > MAX_IPL) ! 323: throw_error ("IPL must be in the range 0 through %d", ! 324: MAX_IPL); ! 325: ! 326: ch = read_uints (input, lexp, & sdevp->sd_itype, NO_RANGE); ! 327: check_not_eol (ch); ! 328: ! 329: if (sdevp->sd_itype > MAX_ITYPE) ! 330: throw_error ("interrupt type must be in the range 0 to %d", ! 331: MAX_ITYPE); ! 332: ! 333: ch = read_uints (input, lexp, & sdevp->sd_vector, NO_RANGE); ! 334: check_not_eol (ch); ! 335: ! 336: ! 337: /* ! 338: * The clock device is special-cased as the only thing that ! 339: * can use vector 0. ! 340: */ ! 341: ! 342: if (strcmp (sdevp->sd_devname->s_data, "clock") != 0 && ! 343: ((sdevp->sd_ipl > 0 && sdevp->sd_vector == 0) || ! 344: (sdevp->sd_ipl == 0 && sdevp->sd_vector > 0))) { ! 345: throw_error ("IPL and vector must both be either zero or non-zero"); ! 346: } ! 347: ! 348: if (sdevp->sd_vector > MAX_VECTOR) ! 349: throw_error ("vector numbers run from 0 (no vector) through %d", ! 350: MAX_VECTOR); ! 351: ! 352: ch = read_ulongs (input, lexp, & sdevp->sd_ioa [0], NO_RANGE); ! 353: check_not_eol (ch); ! 354: ! 355: ch = read_ulongs (input, lexp, & sdevp->sd_ioa [1], NO_RANGE); ! 356: check_not_eol (ch); ! 357: ! 358: if (sdevp->sd_ioa [0] > sdevp->sd_ioa [1]) ! 359: throw_error ("lower bound of address range higher than upper bound"); ! 360: ! 361: ch = read_ulongs (input, lexp, & sdevp->sd_cma [0], NO_RANGE); ! 362: check_not_eol (ch); ! 363: ! 364: ch = read_ulongs (input, lexp, & sdevp->sd_cma [1], NO_RANGE); ! 365: ! 366: if (sdevp->sd_cma [0] > sdevp->sd_cma [1]) ! 367: throw_error ("lower bound of address range higher than upper bound"); ! 368: ! 369: ch = expect_eol (input, lexp, ch); ! 370: } else { ! 371: ! 372: free (sdevp); ! 373: CHAIN_ERROR (err); ! 374: } ! 375: ! 376: at_eof: ! 377: POP_HANDLER (err); ! 378: ! 379: * end_char = ch; ! 380: return sdevp; ! 381: } ! 382: ! 383: ! 384: /* ! 385: * This function is passed as a pointer to for_all_mdevices () to aid in ! 386: * checking to see that enabled devices have unique major numbers. ! 387: */ ! 388: ! 389: #if USE_PROTO ! 390: LOCAL void check_major (mdev_t * mdevp, mdev_t * enabled) ! 391: #else ! 392: LOCAL void ! 393: check_major (mdevp, enabled) ! 394: mdev_t * mdevp; ! 395: mdev_t * enabled; ! 396: #endif ! 397: { ! 398: CONST char * msg; ! 399: ! 400: if (mdevp == enabled || enabled->md_configure != MD_ENABLED) ! 401: return; ! 402: ! 403: if (mdev_flag (enabled, MDEV_BLOCK) && mdev_flag (mdevp, MDEV_BLOCK)) ! 404: if (INTERSECT (mdevp->md_blk_maj, enabled->md_blk_maj)) { ! 405: msg = "Block major number overlap"; ! 406: conflict: ! 407: report_conflict (mdevp->md_devname->s_data, ! 408: enabled->md_devname->s_data, ! 409: msg); ! 410: mdevp->md_configure = MD_DISABLED; ! 411: return; ! 412: } ! 413: ! 414: if (mdev_flag (enabled, MDEV_CHAR) && mdev_flag (mdevp, MDEV_CHAR)) ! 415: if (INTERSECT (mdevp->md_chr_maj, enabled->md_chr_maj)) { ! 416: msg = "Character major number overlap"; ! 417: goto conflict; ! 418: } ! 419: ! 420: if (mdev_flag (enabled, MDEV_COHERENT) && ! 421: mdev_flag (mdevp, MDEV_COHERENT)) ! 422: if (INTERSECT (mdevp->md_chr_maj, enabled->md_chr_maj)) { ! 423: msg = "Major number overlap"; ! 424: goto conflict; ! 425: } ! 426: } ! 427: ! 428: ! 429: /* ! 430: * This function is passed as a parameter to read_dev_string () to read an ! 431: * 'mtune' entry (usually a program argument) and hook it into a global list. ! 432: */ ! 433: ! 434: #if USE_PROTO ! 435: LOCAL int _read_sdev_string (input_t * input, lex_t * lexp, ! 436: sdev_t ** sdlistp) ! 437: #else ! 438: LOCAL int ! 439: _read_sdev_string (input, lexp, sdlistp) ! 440: input_t * input; ! 441: lex_t * lexp; ! 442: sdev_t ** sdlistp; ! 443: #endif ! 444: { ! 445: sdev_t * sdevp; ! 446: int ch; ! 447: ! 448: if ((sdevp = read_sdevice (input, lexp, & ch)) != NULL) { ! 449: sdevp->sd_next = * sdlistp; ! 450: * sdlistp = sdevp; ! 451: } ! 452: ! 453: return ch; ! 454: } ! 455: ! 456: ! 457: /* ! 458: * This function is used by _read_sdevice_file () to handle the details of ! 459: * linking an 'sdevice' entry into the global data structures and checking the ! 460: * data consistency. ! 461: */ ! 462: ! 463: #if USE_PROTO ! 464: LOCAL void (link_sdevice) (sdev_t * sdevp, input_t * input) ! 465: #else ! 466: LOCAL void ! 467: link_sdevice ARGS ((sdevp, input)) ! 468: sdev_t * sdevp; ! 469: input_t * input; ! 470: #endif ! 471: { ! 472: CONST char * errmsg; ! 473: ! 474: if ((sdevp->sd_mdevp = find_mdev (sdevp->sd_devname)) == NULL) { ! 475: errmsg = "device name does not match any master device entry"; ! 476: have_error: ! 477: report_error (errmsg); ! 478: free (sdevp); ! 479: return; ! 480: } ! 481: ! 482: if (mdev_flag (sdevp->sd_mdevp, MDEV_ONE_SDEVICE) && ! 483: sdevp->sd_mdevp->md_sdevices != NULL) { ! 484: errmsg = "only one sdevice entry permitted for this device"; ! 485: goto have_error; ! 486: } ! 487: ! 488: if (sdevp->sd_unit < sdevp->sd_mdevp->md_minor_min || ! 489: sdevp->sd_unit > sdevp->sd_mdevp->md_minor_max) { ! 490: errmsg = "unit number out of range for device"; ! 491: goto have_error; ! 492: } ! 493: ! 494: if (sdevp->sd_ioa [1] > 0 && ! 495: ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE)) { ! 496: errmsg = "software-only device cannot access I/O ports"; ! 497: goto have_error; ! 498: } ! 499: ! 500: switch (sdev_check_ioa (sdevp)) { ! 501: case 3: ! 502: case 0: ! 503: /* ! 504: * Every device we might conflict with has the 'O' flag set ! 505: * and so do we, or there is no conflict. ! 506: */ ! 507: break; ! 508: ! 509: default: ! 510: free (sdevp); ! 511: return; ! 512: } ! 513: ! 514: if (sdevp->sd_cma [1] > 0 && ! 515: ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE)) { ! 516: errmsg = "software-only device cannot have controller memory"; ! 517: goto have_error; ! 518: } ! 519: ! 520: if (sdev_check_cma (sdevp) != 0) { ! 521: free (sdevp); ! 522: return; ! 523: } ! 524: ! 525: if (sdevp->sd_itype > 0) { ! 526: ! 527: if (! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE)) { ! 528: errmsg = "software-only device cannot have a vector"; ! 529: goto have_error; ! 530: } ! 531: ! 532: sdevp->sd_mdevp->md_interrupt = 1; ! 533: } ! 534: ! 535: ! 536: if (sdev_check_vector (sdevp)) { ! 537: free (sdevp); ! 538: return; ! 539: } ! 540: ! 541: ! 542: /* ! 543: * After we have passed all the checks above, we commit to linking the ! 544: * entry in... no more gotos after this point! ! 545: */ ! 546: ! 547: sdevp->sd_next = _sdevices; ! 548: _sdevices = sdevp; ! 549: ! 550: sdevp->sd_mnext = sdevp->sd_mdevp->md_sdevices; ! 551: sdevp->sd_mdevp->md_sdevices = sdevp; ! 552: ! 553: if (sdevp->sd_config) { ! 554: /* ! 555: * Check enabled devices for major number clashes. ! 556: */ ! 557: ! 558: for_all_mdevices ((miter_t) check_major, ! 559: sdevp->sd_mdevp); ! 560: sdevp->sd_mdevp->md_configure = MD_ENABLED; ! 561: } ! 562: ! 563: write_sdevice (sdevp, input); ! 564: } ! 565: ! 566: ! 567: /* ! 568: * This function is passed as a pointer to read_dev_file () in order to read ! 569: * an 'sdevice' entry and link it into a global chain. ! 570: */ ! 571: ! 572: #if USE_PROTO ! 573: LOCAL int _read_sdevice_file (input_t * input, lex_t * lexp, ! 574: sdev_t ** changes) ! 575: #else ! 576: LOCAL int ! 577: _read_sdevice_file ARGS ((input, lexp, changes)) ! 578: input_t * input; ! 579: lex_t * lexp; ! 580: sdev_t ** changes; ! 581: #endif ! 582: { ! 583: sdev_t * sdevp; ! 584: int ch; ! 585: ! 586: if ((sdevp = read_sdevice (input, lexp, & ch)) == NULL) { ! 587: if (ch == READ_EOF) { ! 588: /* ! 589: * Blow remaining changes out as new entries. ! 590: */ ! 591: ! 592: while ((sdevp = * changes) != NULL) { ! 593: * changes = sdevp->sd_next; ! 594: link_sdevice (sdevp, input); ! 595: } ! 596: } ! 597: return ch; ! 598: } ! 599: ! 600: ! 601: /* ! 602: * Link the newly-read entry into the global lists. ! 603: */ ! 604: ! 605: if (changes) { ! 606: sdev_t ** scan; ! 607: ! 608: for (scan = changes ; * scan != NULL ; ! 609: scan = & (* scan)->sd_next) { ! 610: ! 611: if ((* scan)->sd_devname == sdevp->sd_devname && ! 612: (* scan)->sd_unit == sdevp->sd_unit) { ! 613: /* ! 614: * Our current entry is being replaced by a ! 615: * new one. ! 616: */ ! 617: ! 618: free (sdevp); ! 619: ! 620: if (report_mode ()) ! 621: return ch; ! 622: ! 623: sdevp = * scan; ! 624: * scan = sdevp->sd_next; ! 625: break; ! 626: } ! 627: } ! 628: } ! 629: ! 630: link_sdevice (sdevp, input); ! 631: return ch; ! 632: } ! 633: ! 634: ! 635: /* ! 636: * Read in an "mtune" entry from a string and add it to a list. ! 637: */ ! 638: ! 639: #if USE_PROTO ! 640: void read_sdev_string (CONST char * string, VOID * extra) ! 641: #else ! 642: void ! 643: read_sdev_string (string, extra) ! 644: CONST char * string; ! 645: VOID * extra; ! 646: #endif ! 647: { ! 648: read_dev_string (string, (dev_func_p) _read_sdev_string, extra); ! 649: } ! 650: ! 651: ! 652: /* ! 653: * Suck in a complete 'sdevice' file. ! 654: */ ! 655: ! 656: #if USE_PROTO ! 657: void (read_sdev_file) (CONST char * inname, CONST char * outname, VOID * extra) ! 658: #else ! 659: void ! 660: read_sdev_file ARGS ((inname, outname, extra)) ! 661: CONST char * inname; ! 662: CONST char * outname; ! 663: VOID * extra; ! 664: #endif ! 665: { ! 666: read_dev_file (inname, outname, (dev_func_p) _read_sdevice_file, ! 667: extra); ! 668: } ! 669: ! 670: ! 671: /* ! 672: * Generic insertion sort algorithm for "sdevice" entries based on a ! 673: * selection predicate and a comparison predicate. ! 674: * ! 675: * So that this can be a reasonably generic function, we pass it the internal ! 676: * offset of the "sdev_t *" member of the "sdevice" structure which will be ! 677: * used to link together the sorted entries. ! 678: * ! 679: * The return value is the number of items in the target list. ! 680: */ ! 681: ! 682: #define LINK(sdevp,off) (* (sdev_t **) ((char *) (sdevp) + off)) ! 683: ! 684: #if USE_PROTO ! 685: int (sdev_sort) (sdev_t ** sdlistp, sdev_t ** sdendp, ssel_t selpred, ! 686: scmp_t cmppred, size_t ptroff) ! 687: #else ! 688: int ! 689: sdev_sort ARGS ((sdlistp, sdendp, selpred, cmppred, ptroff)) ! 690: sdev_t **sdlistp; ! 691: sdev_t **sdendp; ! 692: ssel_t selpred; ! 693: scmp_t cmppred; ! 694: size_t ptroff; ! 695: #endif ! 696: { ! 697: sdev_t * scan; ! 698: sdev_t * next; ! 699: int count; ! 700: ! 701: if (sdlistp == NULL || ptroff > sizeof (sdev_t)) ! 702: throw_error ("bogus parameters to sdev_sort ()"); ! 703: ! 704: ! 705: /* ! 706: * We'll just insert each selected member of the total list of ! 707: * mdevices into the output list in order by running down the output ! 708: * list until we compare true. ! 709: * ! 710: * We fetch "scan" before initializing the output list in case we are ! 711: * sorting the master device list. ! 712: */ ! 713: ! 714: * sdlistp = NULL; ! 715: if (sdendp != NULL) ! 716: * sdendp = NULL; ! 717: ! 718: for (count = 0, scan = _sdevices ; scan != NULL ; scan = next) { ! 719: sdev_t * findpos; ! 720: sdev_t * prev; ! 721: ! 722: /* ! 723: * We get the "next" entry now in case we are sorting the ! 724: * master list. We allow a "selpred" of NULL to select all ! 725: * the entries. ! 726: */ ! 727: ! 728: next = scan->sd_next; ! 729: ! 730: if (selpred != NULL && (* selpred) (scan) == 0) ! 731: continue; ! 732: ! 733: /* ! 734: * Now attempt to find the right place for the new entry and ! 735: * insert it there. ! 736: */ ! 737: ! 738: prev = NULL; ! 739: ! 740: for (findpos = * sdlistp ; findpos != NULL ; ! 741: findpos = LINK ((prev = findpos), ptroff)) { ! 742: /* ! 743: * A "cmppred" that is NULL means that the order of ! 744: * output entries is irrelevant. ! 745: */ ! 746: ! 747: if (cmppred == NULL || ! 748: (* cmppred) (findpos, scan) == 0) ! 749: break; ! 750: } ! 751: ! 752: if (prev == NULL) ! 753: * sdlistp = scan; ! 754: else ! 755: LINK (prev, ptroff) = scan; ! 756: ! 757: if ((LINK (scan, ptroff) = findpos) == NULL && sdendp != NULL) ! 758: * sdendp = scan; ! 759: ! 760: count ++; ! 761: } ! 762: ! 763: return count; ! 764: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.