Annotation of coherent/b/STREAMS/conf_79/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: 
        !            40: #include "sdev.h"
        !            41: 
        !            42: #include <string.h>
        !            43: 
        !            44: 
        !            45: LOCAL sdev_t  *        sdevices;
        !            46: 
        !            47: 
        !            48: /*
        !            49:  * Simple local function for testing to see if IOA or CMA ranges intersect.
        !            50:  */
        !            51: 
        !            52: #ifdef USE_PROTO
        !            53: LOCAL int (intersect) (CONST unsigned long * left, CONST unsigned long * right)
        !            54: #else
        !            55: LOCAL int
        !            56: intersect ARGS ((left, right))
        !            57: CONST int     *        left;
        !            58: CONST int     *        right;
        !            59: #endif
        !            60: {
        !            61:        return (left [0] >= right [0] && left [0] <= right [1]) ||
        !            62:               (left [1] >= right [0] && left [1] <= right [1]);
        !            63: }
        !            64: 
        !            65: 
        !            66: /*
        !            67:  * This function checks all existing 'sdevice' entries to see if there is an
        !            68:  * IOA conflict.
        !            69:  *
        !            70:  * The value returned is the same value that would be returned by the matching
        !            71:  * check performed by the idcheck(1M) utility, namely:
        !            72:  *     0 if no conflict.
        !            73:  *     1 if there is a conflict.
        !            74:  *     3 if there is a conflict, but the 'mdevice' entry has the O flag set.
        !            75:  *
        !            76:  * As usual, the specification does not take into account the possibility that
        !            77:  * an IOA range may conflict with several devices with a different setting of
        !            78:  * the 'O' flag. This routine returns 3 if and only if all devices which have
        !            79:  * IOA conflicts have the 'O' flag set.
        !            80:  *
        !            81:  * If "who" is non-NULL, it will be written with the address of the sdevice
        !            82:  * entry which caused the conflict which caused the non-zero return.
        !            83:  */
        !            84: 
        !            85: #ifdef __USE_PROTO__
        !            86: int (sdev_check_ioa) (CONST ioa_t * check, sdev_t ** who)
        !            87: #else
        !            88: int
        !            89: sdev_check_ioa ARGS ((check, who))
        !            90: CONST int     *        check;
        !            91: sdev_t      ** who;
        !            92: #endif
        !            93: {
        !            94:        sdev_t        * sdevp;
        !            95:        int             share_conflict = 0;
        !            96: 
        !            97:        if (check == NULL)
        !            98:                throw_error ("check argument is NULL in sdev_check_ioa ()");
        !            99: 
        !           100:        if (check [1] == 0)
        !           101:                return 0;
        !           102: 
        !           103:        for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
        !           104: 
        !           105:                if (sdevp->sd_ioa [1] > 0 &&
        !           106:                    intersect (sdevp->sd_ioa, check)) {
        !           107: 
        !           108:                        if (mdev_flag (sdevp->sd_mdevp,
        !           109:                                       MDEV_ALLOW_IOA_OVERLAP)) {
        !           110:                                /*
        !           111:                                 * Since multiple entries can cause a shared
        !           112:                                 * IOA conflict, return the first.
        !           113:                                 */
        !           114: 
        !           115:                                if (who != NULL && share_conflict == 0)
        !           116:                                        * who = sdevp;
        !           117: 
        !           118:                                share_conflict  = 3;
        !           119:                        } else {
        !           120:                                /*
        !           121:                                 * Since this 'sdevice' entry caused a fatal
        !           122:                                 * conflict, we always return that one.
        !           123:                                 */
        !           124: 
        !           125:                                if (who != NULL)
        !           126:                                        * who = sdevp;
        !           127: 
        !           128:                                return 1;
        !           129:                        }
        !           130:                }
        !           131:        }
        !           132: 
        !           133:        return share_conflict;
        !           134: }
        !           135: 
        !           136: 
        !           137: /*
        !           138:  * This function checks all existing 'sdevice' entries for a CMA conflict.
        !           139:  *
        !           140:  * The value returned will be 1 if there is a conflict and 0 if no conflict
        !           141:  * occurs. If the "who" parameter is non-NULL, it will be written with the
        !           142:  * address of the 'sdevice' entry that caused the conflict (if any).
        !           143:  */
        !           144: 
        !           145: #ifdef __USE_PROTO__
        !           146: int (sdev_check_cma) (CONST cma_t * check, sdev_t ** who)
        !           147: #else
        !           148: int
        !           149: sdev_check_cma ARGS ((check, who))
        !           150: CONST int     *        check;
        !           151: sdev_t      ** who;
        !           152: #endif
        !           153: {
        !           154:        sdev_t        * sdevp;
        !           155: 
        !           156:        if (check == NULL)
        !           157:                throw_error ("check argument is NULL in sdev_check_cma ()");
        !           158: 
        !           159:        if (check [1] == 0)
        !           160:                return 0;
        !           161: 
        !           162:        for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
        !           163: 
        !           164:                if (sdevp->sd_cma [1] > 0 &&
        !           165:                    intersect (sdevp->sd_cma, check)) {
        !           166: 
        !           167:                        /*
        !           168:                         * Since this 'sdevice' entry caused a fatal
        !           169:                         * conflict, we always return that one.
        !           170:                         */
        !           171: 
        !           172:                        if (who != NULL)
        !           173:                                * who = sdevp;
        !           174: 
        !           175:                        return 1;
        !           176:                }
        !           177:        }
        !           178: 
        !           179:        return 0;
        !           180: }
        !           181: 
        !           182: 
        !           183: /*
        !           184:  * This function checks all existing 'sdevice' entries to see if the interrupt
        !           185:  * vector 'vec' is in use by any of them. If any other devices are using the
        !           186:  * vector, the lowest non-zero 'type' value specified by any of them is
        !           187:  * returned. If the "who" entry is non-NULL, the address of the first entry
        !           188:  * responsible for the return value is returned.
        !           189:  */
        !           190: 
        !           191: #ifdef __USE_PROTO__
        !           192: int (sdev_check_vector) (int vec, sdev_t ** who)
        !           193: #else
        !           194: int
        !           195: sdev_check_vector ARGS ((vec, who))
        !           196: int            vec;
        !           197: sdev_t      ** who;
        !           198: #endif
        !           199: {
        !           200:        sdev_t        * sdevp;
        !           201:        int             itype = MAX_ITYPE + 1;
        !           202: 
        !           203:        if (vec == 0)
        !           204:                return 0;
        !           205: 
        !           206:        for (sdevp = sdevices ; sdevp != NULL ; sdevp = sdevp->sd_next) {
        !           207: 
        !           208:                if (sdevp->sd_vector == vec && sdevp->sd_itype < itype) {
        !           209: 
        !           210:                        if (who != NULL)
        !           211:                                * who = sdevp;
        !           212: 
        !           213:                        itype = sdevp->sd_itype;
        !           214:                }
        !           215:        }
        !           216: 
        !           217:        return itype <= MAX_ITYPE ? itype : 0;
        !           218: }
        !           219: 
        !           220: 
        !           221: /*
        !           222:  * Read a line from an "sdevice" file.
        !           223:  *
        !           224:  * This code is really messy. My apologies.
        !           225:  */
        !           226: 
        !           227: #ifdef USE_PROTO
        !           228: LOCAL int (read_sdevice) (input_t * input, lex_t * lexp)
        !           229: #else
        !           230: LOCAL int
        !           231: read_sdevice ARGS ((input, lexp))
        !           232: input_t              * input;
        !           233: lex_t        * lexp;
        !           234: #endif
        !           235: {
        !           236:        int             ch = '\n';
        !           237:        sdev_t        * sdevp;
        !           238:        sdev_t        * serr;
        !           239:        ehand_t         err;
        !           240:        lex_t           yesno = { NULL, NULL, "-", "ynYN", LEX_WILD };
        !           241:        symbol_t      * config_flag;
        !           242: 
        !           243:        yesno.l_prev = lexp;
        !           244: 
        !           245:        if ((sdevp = (sdev_t *) malloc (sizeof (* sdevp))) == NULL)
        !           246:                throw_error ("out of memory in read_sdevice ()");
        !           247: 
        !           248:        if (PUSH_HANDLER (err) == 0) {
        !           249:                /*
        !           250:                 * If the first thing on the line is EOF, that's not an error,
        !           251:                 * just bail out.
        !           252:                 */
        !           253: 
        !           254:                ch = read_symbol (input, lexp, & sdevp->sd_devname);
        !           255: 
        !           256:                if (sdevp->sd_devname == NULL)
        !           257:                        goto at_eof;
        !           258: 
        !           259:                check_not_eol (ch);
        !           260: 
        !           261:                if (sdevp->sd_devname->s_size > MAX_DEVNAME)
        !           262:                        throw_error ("device name must be <= %d characters",
        !           263:                                     MAX_DEVNAME);
        !           264: 
        !           265:                if ((sdevp->sd_mdevp = find_mdev (sdevp->sd_devname)) == NULL)
        !           266:                        throw_error ("device name does not match any master device entry");
        !           267: 
        !           268:                if (mdev_flag (sdevp->sd_mdevp, MDEV_ONE_SDEVICE) &&
        !           269:                    sdevp->sd_mdevp->md_sdevices != NULL)
        !           270:                        throw_error ("only one sdevice entry permitted for this device");
        !           271: 
        !           272: 
        !           273:                /*
        !           274:                 * We read the yes/no field as a symbol, since most of the
        !           275:                 * entries will be identical.
        !           276:                 */
        !           277: 
        !           278:                ch = read_symbol (input, & yesno, & config_flag);
        !           279:                check_not_eol (ch);
        !           280: 
        !           281:                if (config_flag->s_size > 1)
        !           282:                        throw_error ("a single Y or N is required");
        !           283: 
        !           284:                sdevp->sd_config = (config_flag->s_data [0] == 'y' ||
        !           285:                                    config_flag->s_data [0] == 'Y');
        !           286: 
        !           287: 
        !           288:                ch = read_uints (input, lexp, & sdevp->sd_unit, NO_RANGE);
        !           289:                check_not_eol (ch);
        !           290: 
        !           291:                if (sdevp->sd_unit < sdevp->sd_mdevp->md_minor_min ||
        !           292:                    sdevp->sd_unit > sdevp->sd_mdevp->md_minor_max)
        !           293:                        throw_error ("unit number out of range for device");
        !           294: 
        !           295:                ch = read_uints (input, lexp, & sdevp->sd_ipl, NO_RANGE);
        !           296:                check_not_eol (ch);
        !           297: 
        !           298:                if (sdevp->sd_ipl > MAX_IPL)
        !           299:                        throw_error ("IPL must be in the range 0 through %d",
        !           300:                                     MAX_IPL);
        !           301: 
        !           302:                ch = read_uints (input, lexp, & sdevp->sd_itype, NO_RANGE);
        !           303:                check_not_eol (ch);
        !           304: 
        !           305:                if (sdevp->sd_itype > MAX_ITYPE)
        !           306:                        throw_error ("interrupt type must be in the range 0 to %d",
        !           307:                                     MAX_ITYPE);
        !           308: 
        !           309:                ch = read_uints (input, lexp, & sdevp->sd_vector, NO_RANGE);
        !           310:                check_not_eol (ch);
        !           311: 
        !           312:                /*
        !           313:                 * The clock device is special-cased as the only thing that
        !           314:                 * can use vector 0.
        !           315:                 */
        !           316: 
        !           317:                if (strcmp (sdevp->sd_devname->s_data, "clock") != 0 &&
        !           318:                    ((sdevp->sd_ipl > 0 && sdevp->sd_vector == 0) ||
        !           319:                     (sdevp->sd_ipl == 0 && sdevp->sd_vector > 0))) {
        !           320:                        throw_error ("IPL and vector must both be either zero or non-zero");
        !           321:                }
        !           322: 
        !           323:                if (sdevp->sd_vector > MAX_VECTOR)
        !           324:                        throw_error ("vector numbers run from 0 (no vector) through %d",
        !           325:                                     MAX_VECTOR);
        !           326: 
        !           327:                switch (sdev_check_vector (sdevp->sd_vector, & serr)) {
        !           328: 
        !           329:                case INT_SHAREABLE:
        !           330:                        if (sdevp->sd_itype == INT_SHAREABLE)
        !           331:                                break;
        !           332: 
        !           333:                        /* FALL THROUGH */
        !           334: 
        !           335:                case INT_PER_DEVICE:
        !           336:                        if (serr->sd_devname == sdevp->sd_devname &&
        !           337:                            sdevp->sd_itype >= INT_PER_DEVICE)
        !           338:                                break;
        !           339: 
        !           340:                        /* FALL THROUGH */
        !           341: 
        !           342:                case INT_PER_CHANNEL:
        !           343:                        throw_error ("vector conflict with device %s",
        !           344:                                     serr->sd_devname->s_data);
        !           345:                        break;
        !           346: 
        !           347:                case INT_NONE:
        !           348:                        break;
        !           349:                }
        !           350: 
        !           351:                ch = read_ulongs (input, lexp, & sdevp->sd_ioa [0], NO_RANGE);
        !           352:                check_not_eol (ch);
        !           353: 
        !           354:                ch = read_ulongs (input, lexp, & sdevp->sd_ioa [1], NO_RANGE);
        !           355:                check_not_eol (ch);
        !           356: 
        !           357:                if (sdevp->sd_ioa [0] > sdevp->sd_ioa [1])
        !           358:                        throw_error ("lower bound of address range higher than upper bound");
        !           359: 
        !           360:                if (sdevp->sd_ioa [1] > 0 &&
        !           361:                    ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
        !           362:                        throw_error ("software-only device cannot access I/O ports");
        !           363: 
        !           364:                switch (sdev_check_ioa (sdevp->sd_ioa, & serr)) {
        !           365: 
        !           366:                case 3:
        !           367:                        if (mdev_flag (sdevp->sd_mdevp,
        !           368:                                       MDEV_ALLOW_IOA_OVERLAP)) {
        !           369:                                /*
        !           370:                                 * Every device we might conflict with has the
        !           371:                                 * 'O' flag set and so do we.
        !           372:                                 */
        !           373: 
        !           374:                                break;
        !           375:                        }
        !           376: 
        !           377:                        /* FALL THROUGH */
        !           378: 
        !           379:                default:
        !           380:                        throw_error ("IOA conflict with device %s",
        !           381:                                     serr->sd_devname->s_data);
        !           382:                        break;
        !           383: 
        !           384:                case 0:
        !           385:                        break;
        !           386:                }
        !           387: 
        !           388:                ch = read_ulongs (input, lexp, & sdevp->sd_cma [0], NO_RANGE);
        !           389:                check_not_eol (ch);
        !           390: 
        !           391:                ch = read_ulongs (input, lexp, & sdevp->sd_cma [1], NO_RANGE);
        !           392: 
        !           393:                if (sdevp->sd_cma [0] > sdevp->sd_cma [1])
        !           394:                        throw_error ("lower bound of address range higher than upper bound");
        !           395: 
        !           396:                if (sdevp->sd_cma [1] > 0 &&
        !           397:                    ! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
        !           398:                        throw_error ("software-only device cannot access controller memory");
        !           399: 
        !           400:                if (sdev_check_cma (sdevp->sd_cma, & serr) != 0)
        !           401:                        throw_error ("CMA conflict with device %s",
        !           402:                                     serr->sd_devname->s_data);
        !           403: 
        !           404:                ch = expect_eol (input, lexp, ch);
        !           405: 
        !           406: 
        !           407:                /*
        !           408:                 * Having passed all the reasonableness checks, we link the
        !           409:                 * new entry into the chain.
        !           410:                 */
        !           411: 
        !           412:                sdevp->sd_next = sdevices;
        !           413:                sdevices = sdevp;
        !           414: 
        !           415:                sdevp->sd_mnext = sdevp->sd_mdevp->md_sdevices;
        !           416:                sdevp->sd_mdevp->md_sdevices = sdevp;
        !           417: 
        !           418:                if (sdevp->sd_mdevp->md_configure == MD_INSTALLABLE &&
        !           419:                    sdevp->sd_config)
        !           420:                        sdevp->sd_mdevp->md_configure = MD_ENABLED;
        !           421: 
        !           422:                if (sdevp->sd_itype > 0) {
        !           423: 
        !           424:                        if (! mdev_flag (sdevp->sd_mdevp, MDEV_HARDWARE))
        !           425:                                throw_error ("software-only device cannot have a vector");
        !           426: 
        !           427:                        sdevp->sd_mdevp->md_interrupt = 1;
        !           428:                }
        !           429:        } else {
        !           430: 
        !           431:                free (sdevp);
        !           432:                CHAIN_ERROR (err);
        !           433:        }
        !           434: 
        !           435: at_eof:
        !           436:        POP_HANDLER (err);
        !           437:        return ch;
        !           438: }
        !           439: 
        !           440: 
        !           441: #if 0
        !           442: /*
        !           443:  * Regenerate an 'sdevice' entry from the stored record.
        !           444:  */
        !           445: 
        !           446: #ifdef USE_PROTO
        !           447: void (write_sdevice) (sdev_t * sdevp, FILE * out)
        !           448: #else
        !           449: void
        !           450: write_sdevice ARGS ((sdevp, out))
        !           451: sdev_t       * sdevp;
        !           452: FILE         * out;
        !           453: #endif
        !           454: {
        !           455:        (void) fprintf (out, "%-10s %c %-3d %-3d %-3d 0x%-6x 0x%-6x 0x%-10x 0x%-10x\n",
        !           456:                        sdevp->sd_devname->s_data, sdevp->sd_config ? 'Y' : 'N',
        !           457:                        sdevp->sd_ipl, sdevp->sd_itype, sdevp->sd_vector,
        !           458:                        sdevp->sd_ioa [0], sdevp->sd_ioa [1], sdevp->sd_cma [0],
        !           459:                        sdevp->sd_cma [1]);
        !           460: }
        !           461: #endif
        !           462: 
        !           463: 
        !           464: /*
        !           465:  * Suck in a complete 'sdevice' file.
        !           466:  */
        !           467: 
        !           468: #ifdef USE_PROTO
        !           469: void (read_sdev_file) (CONST char * name)
        !           470: #else
        !           471: void
        !           472: read_sdev_file ARGS ((name))
        !           473: CONST char    *        name;
        !           474: #endif
        !           475: {
        !           476:        read_dev_file (name, read_sdevice);
        !           477: }
        !           478: 
        !           479: 
        !           480: /*
        !           481:  * Generic insertion sort algorithm for "sdevice" entries based on a
        !           482:  * selection predicate and a comparison predicate.
        !           483:  *
        !           484:  * So that this can be a reasonably generic function, we pass it the internal
        !           485:  * offset of the "sdev_t *" member of the "sdevice" structure which will be
        !           486:  * used to link together the sorted entries.
        !           487:  */
        !           488: 
        !           489: #define        LINK(sdevp,off)         (* (sdev_t **) ((char *) (sdevp) + off))
        !           490: 
        !           491: #ifdef USE_PROTO
        !           492: void (sdev_sort) (sdlist_t * sdlistp, ssel_t selpred, scmp_t cmppred,
        !           493:                  size_t ptroff)
        !           494: #else
        !           495: void
        !           496: sdev_sort ARGS ((sdlistp, selpred, cmppred, ptroff))
        !           497: sdlist_t             * sdlistp;
        !           498: ssel_t         selpred;
        !           499: scmp_t         cmppred;
        !           500: size_t         ptroff;
        !           501: #endif
        !           502: {
        !           503:        sdev_t        * scan;
        !           504:        sdev_t        * next;
        !           505: 
        !           506:        if (sdlistp == NULL || ptroff > sizeof (sdev_t))
        !           507:                throw_error ("bogus parameters to sdev_sort ()");
        !           508: 
        !           509: 
        !           510:        /*
        !           511:         * We'll just insert each selected member of the total list of
        !           512:         * mdevices into the output list in order by running down the output
        !           513:         * list until we compare true.
        !           514:         *
        !           515:         * We fetch "scan" before initializing the output list in case we are
        !           516:         * sorting the master device list.
        !           517:         */
        !           518: 
        !           519:        scan = sdevices;
        !           520: 
        !           521:        sdlistp->sdl_first = sdlistp->sdl_last = NULL;
        !           522:        sdlistp->sdl_count = 0;
        !           523: 
        !           524:        for (; scan != NULL ; scan = next) {
        !           525:                sdev_t        * findpos;
        !           526:                sdev_t        * prev;
        !           527: 
        !           528:                /*
        !           529:                 * We get the "next" entry now in case we are sorting the
        !           530:                 * master list. We allow a "selpred" of NULL to select all
        !           531:                 * the entries.
        !           532:                 */
        !           533: 
        !           534:                next = scan->sd_next;
        !           535: 
        !           536:                if (selpred != NULL && (* selpred) (scan) == 0)
        !           537:                        continue;
        !           538: 
        !           539: 
        !           540:                /*
        !           541:                 * Now attempt to find the right place for the new entry and
        !           542:                 * insert it there.
        !           543:                 */
        !           544: 
        !           545:                prev = NULL;
        !           546: 
        !           547:                for (findpos = sdlistp->sdl_first ; findpos != NULL ;
        !           548:                     findpos = LINK ((prev = findpos), ptroff)) {
        !           549:                        /*
        !           550:                         * A "cmppred" that is NULL means that the order of
        !           551:                         * output entries is irrelevant.
        !           552:                         */
        !           553: 
        !           554:                        if (cmppred == NULL ||
        !           555:                           (* cmppred) (findpos, scan) == 0)
        !           556:                                break;
        !           557:                }
        !           558: 
        !           559:                if (prev == NULL)
        !           560:                        sdlistp->sdl_first = scan;
        !           561:                else
        !           562:                        LINK (prev, ptroff) = scan;
        !           563: 
        !           564:                if ((LINK (scan, ptroff) = findpos) == NULL)
        !           565:                        sdlistp->sdl_last = scan;
        !           566: 
        !           567:                sdlistp->sdl_count ++;
        !           568:        }
        !           569: }

unix.superglobalmegacorp.com

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