Annotation of coherent/b/STREAMS/conf/bin/src/sdev.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.