Annotation of coherent/b/STREAMS/conf/bin/src/sdev.c, revision 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.