Annotation of coherent/b/STREAMS/conf_79/mdev.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *-IMPORT:
        !             3:  *     <sys/compat.h>
        !             4:  *             CONST
        !             5:  *             LOCAL
        !             6:  *             USE_PROTO
        !             7:  *             ARGS ()
        !             8:  *     <stdlib.h>
        !             9:  *             NULL
        !            10:  *             free ()
        !            11:  *             malloc ()
        !            12:  *     <string.h>
        !            13:  *             strchr ()
        !            14:  *     "ehand.h"
        !            15:  *             ehand_t
        !            16:  *             CHAIN_ERROR ()
        !            17:  *             POP_HANDLER ()
        !            18:  *             PUSH_HANDLER ()
        !            19:  *             throw_error ()
        !            20:  *     "symbol.h"
        !            21:  *             LEX_WILD
        !            22:  *             RANGE
        !            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: #include <string.h>
        !            34: 
        !            35: #include "ehand.h"
        !            36: #include "symbol.h"
        !            37: #include "read.h"
        !            38: #include "lex.h"
        !            39: 
        !            40: #include "mdev.h"
        !            41: 
        !            42: 
        !            43: LOCAL mdev_t  *        _mdevices;
        !            44: 
        !            45: 
        !            46: /*
        !            47:  * Simple local function for testing to see if major-number ranges intersect.
        !            48:  */
        !            49: 
        !            50: #ifdef USE_PROTO
        !            51: LOCAL int (intersect) (CONST unsigned int * left, CONST unsigned int * right)
        !            52: #else
        !            53: LOCAL int
        !            54: intersect ARGS ((left, right))
        !            55: CONST int     *        left;
        !            56: CONST int     *        right;
        !            57: #endif
        !            58: {
        !            59:        return (left [0] >= right [0] && left [0] <= right [1]) ||
        !            60:               (left [1] >= right [0] && left [1] <= right [1]);
        !            61: }
        !            62: 
        !            63: 
        !            64: /*
        !            65:  * Find a device by symbol.
        !            66:  */
        !            67: 
        !            68: #ifdef USE_PROTO
        !            69: mdev_t * (find_mdev) (symbol_t * sym)
        !            70: #else
        !            71: mdev_t *
        !            72: find_mdev ARGS ((sym))
        !            73: symbol_t      *        sym;
        !            74: #endif
        !            75: {
        !            76:        mdev_t        * scan;
        !            77: 
        !            78:        for (scan = _mdevices ; scan != NULL ; scan = scan->md_next) {
        !            79: 
        !            80:                if (scan->md_devname == sym)
        !            81:                        return scan;
        !            82:        }
        !            83: 
        !            84:        return NULL;
        !            85: }
        !            86: 
        !            87: 
        !            88: /*
        !            89:  * Read lines from an "mdevice" file.
        !            90:  *
        !            91:  * This code is really messy. My apologies.
        !            92:  */
        !            93: 
        !            94: #ifdef USE_PROTO
        !            95: LOCAL int (read_mdevice) (input_t * input, lex_t * lexp)
        !            96: #else
        !            97: LOCAL int
        !            98: read_mdevice ARGS ((input, lexp))
        !            99: input_t              * input;
        !           100: lex_t         *        lexp;
        !           101: #endif
        !           102: {
        !           103:        int             ch = '\n';
        !           104:        mdev_t        * mdevp;
        !           105:        mdev_t        * scan;
        !           106:        ehand_t         err;
        !           107:        lex_t           functions = { NULL, NULL, "-", MDEV_FUNCS, LEX_WILD };
        !           108:        lex_t           flags = { NULL, NULL, "-", MDEV_FLAGS, LEX_WILD };
        !           109: 
        !           110:        functions.l_prev = lexp;
        !           111:        flags.l_prev = lexp;
        !           112: 
        !           113:        if ((mdevp = (mdev_t *) malloc (sizeof (* mdevp))) == NULL)
        !           114:                throw_error ("out of memory in read_mdevice ()");
        !           115: 
        !           116:        if (PUSH_HANDLER (err) == 0) {
        !           117:                /*
        !           118:                 * If the first thing on the line works out to be an EOF,
        !           119:                 * then bail out without an error.
        !           120:                 */
        !           121: 
        !           122:                ch = read_symbol (input, lexp, & mdevp->md_devname);
        !           123: 
        !           124:                if (mdevp->md_devname == NULL) {
        !           125:                        /*
        !           126:                         * We allow an EOF at the beginning of a line and we
        !           127:                         * also allow a blank line.
        !           128:                         */
        !           129: 
        !           130:                        goto at_eof;
        !           131:                }
        !           132:                check_not_eol (ch);
        !           133: 
        !           134:                if (mdevp->md_devname->s_size > MAX_DEVNAME)
        !           135:                        throw_error ("device name must be <= %d characters",
        !           136:                                     MAX_DEVNAME);
        !           137: 
        !           138:                if (find_mdev (mdevp->md_devname) != NULL)
        !           139:                        throw_error ("device name must be unique");
        !           140: 
        !           141: 
        !           142:                /*
        !           143:                 * We read the functions and characteristics field as symbols,
        !           144:                 * even though they are really strings, since it makes no
        !           145:                 * difference to the result.
        !           146:                 */
        !           147: 
        !           148:                ch = read_symbol (input, & functions, & mdevp->md_functions);
        !           149:                if (mdevp->md_functions == NULL && ch != '-')
        !           150:                        throw_error ("Unable to read functions");
        !           151:                check_not_eol (ch);
        !           152: 
        !           153:                ch = read_symbol (input, & flags, & mdevp->md_flags);
        !           154:                if (mdevp->md_flags == NULL && ch != '-')
        !           155:                        throw_error ("Unable to read flags");
        !           156:                check_not_eol (ch);
        !           157: 
        !           158:                if ((mdev_flag (mdevp, MDEV_BLOCK) ||
        !           159:                     mdev_flag (mdevp, MDEV_CHAR) ||
        !           160:                     mdev_flag (mdevp, MDEV_STREAM)) &&
        !           161:                    ! mdev_flag (mdevp, MDEV_DDI_DDK)) {
        !           162: 
        !           163:                        throw_error ("devices must be DDI/DDK compliant");
        !           164:                }
        !           165: 
        !           166: 
        !           167:                /*
        !           168:                 * We don't check for a unique device prefix, since there may
        !           169:                 * be a legitimate reason to configure the same prefix twice.
        !           170:                 *
        !           171:                 * If the user installs multiple devices with the same prefix,
        !           172:                 * the linker should catch it. Of course, a registration
        !           173:                 * system might help. We only enforce the size limit for
        !           174:                 * drivers... other kernel facilities can user longer names.
        !           175:                 */
        !           176: 
        !           177:                ch = read_symbol (input, lexp, & mdevp->md_prefix);
        !           178:                check_not_eol (ch);
        !           179: 
        !           180:                if ((mdev_flag (mdevp, MDEV_BLOCK) ||
        !           181:                     mdev_flag (mdevp, MDEV_CHAR) ||
        !           182:                     mdev_flag (mdevp, MDEV_STREAM)) &&
        !           183:                    mdevp->md_prefix->s_size > MAX_PREFIX)
        !           184:                        throw_error ("device prefix must be <= %d characters",
        !           185:                                     MAX_PREFIX);
        !           186: 
        !           187: 
        !           188:                ch = read_uints (input, lexp, mdevp->md_blk_maj, RANGE);
        !           189:                check_not_eol (ch);
        !           190: 
        !           191:                if (mdev_flag (mdevp, MDEV_BLOCK)) {
        !           192: 
        !           193:                        if (mdevp->md_blk_maj [0] > mdevp->md_blk_maj [1])
        !           194:                                throw_error ("lower range bound higher that upper bound");
        !           195: 
        !           196:                        if (mdevp->md_blk_maj [0] > 0 &&
        !           197:                            mdevp->md_blk_maj [0] < MAJOR_RESERVED)
        !           198:                                throw_error ("major devices up to %d reserved",
        !           199:                                             MAJOR_RESERVED);
        !           200: 
        !           201:                        for (scan = _mdevices ; scan != NULL ;
        !           202:                             scan = scan->md_next) {
        !           203: 
        !           204:                                if (! mdev_flag (scan, MDEV_BLOCK))
        !           205:                                        continue;
        !           206: 
        !           207:                                if (intersect (scan->md_blk_maj,
        !           208:                                               mdevp->md_blk_maj))
        !           209:                                        throw_error ("duplicate block major numbers");
        !           210:                        }
        !           211:                } else
        !           212:                        mdevp->md_blk_maj [0] = mdevp->md_blk_maj [1] = 0;
        !           213: 
        !           214: 
        !           215:                ch = read_uints (input, lexp, mdevp->md_chr_maj, RANGE);
        !           216:                check_not_eol (ch);
        !           217: 
        !           218:                if (mdev_flag (mdevp, MDEV_CHAR)) {
        !           219: 
        !           220:                        if (mdevp->md_chr_maj [0] > mdevp->md_chr_maj [1])
        !           221:                                throw_error ("lower range bound higher that upper bound");
        !           222: 
        !           223:                        if (mdevp->md_chr_maj [0] > 0 &&
        !           224:                            mdevp->md_chr_maj [0] < MAJOR_RESERVED)
        !           225:                                throw_error ("major devices 0-%d reserved",
        !           226:                                             MAJOR_RESERVED - 1);
        !           227: 
        !           228:                        for (scan = _mdevices ; scan != NULL ;
        !           229:                             scan = scan->md_next) {
        !           230: 
        !           231:                                if (! mdev_flag (scan, MDEV_CHAR))
        !           232:                                        continue;
        !           233: 
        !           234:                                if (intersect (scan->md_chr_maj,
        !           235:                                               mdevp->md_chr_maj))
        !           236:                                        throw_error ("duplicate character major numbers");
        !           237:                        }
        !           238:                } else
        !           239:                        mdevp->md_chr_maj [0] = mdevp->md_chr_maj [1] = 0;
        !           240: 
        !           241:                ch = read_uints (input, lexp, & mdevp->md_minor_min,
        !           242:                                 NO_RANGE);
        !           243:                check_not_eol (ch);
        !           244: 
        !           245:                ch = read_uints (input, lexp, & mdevp->md_minor_max,
        !           246:                                 NO_RANGE);
        !           247:                check_not_eol (ch);
        !           248: 
        !           249:                if (mdevp->md_minor_min > mdevp->md_minor_max)
        !           250:                        throw_error ("minor minimum higher than maximum");
        !           251: 
        !           252:                ch = read_ints (input, lexp, & mdevp->md_dma_chan, NO_RANGE);
        !           253: 
        !           254:                if (ch != '\n' && ch != SYM_EOF) {
        !           255:                        /*
        !           256:                         * The "cpu_id" field is optional.
        !           257:                         */
        !           258: 
        !           259:                        ch = read_ints (input, lexp, & mdevp->md_cpu_id,
        !           260:                                        NO_RANGE);
        !           261:                } else
        !           262:                        mdevp->md_cpu_id = -1;
        !           263: 
        !           264:                ch = expect_eol (input, lexp, ch);
        !           265: 
        !           266: 
        !           267:                /*
        !           268:                 * Having passed all the reasonableness checks, we link the
        !           269:                 * new entry into the chain.
        !           270:                 */
        !           271: 
        !           272:                mdevp->md_sdevices = NULL;
        !           273:                mdevp->md_interrupt = 0;
        !           274: 
        !           275:                mdevp->md_configure = mdev_flag (mdevp, MDEV_INSTALLABLE) ?
        !           276:                                                MD_INSTALLABLE : MD_DISABLED;
        !           277: 
        !           278:                mdevp->md_next = _mdevices;
        !           279:                _mdevices = mdevp;
        !           280:        } else {
        !           281: 
        !           282:                free (mdevp);
        !           283:                CHAIN_ERROR (err);
        !           284:        }
        !           285: 
        !           286: at_eof:
        !           287:        POP_HANDLER (err);
        !           288:        return ch;
        !           289: }
        !           290: 
        !           291: 
        !           292: /*
        !           293:  * Test a device for a function code; returns 1 if code is present, or 0 if
        !           294:  * code is not specified for device.
        !           295:  */
        !           296: 
        !           297: #ifdef USE_PROTO
        !           298: int (mdev_func) (mdev_t * mdevp, char func)
        !           299: #else
        !           300: int
        !           301: mdev_func ARGS ((mdevp, func))
        !           302: mdev_t       * mdevp;
        !           303: char           func;
        !           304: #endif
        !           305: {
        !           306:        if (mdevp->md_functions == NULL)
        !           307:                return 0;
        !           308:        return strchr (mdevp->md_functions->s_data, func) != NULL;
        !           309: }
        !           310: 
        !           311: 
        !           312: /*
        !           313:  * Test device characteristics; returns 1 if characteristic is specified for
        !           314:  * device, 0 if it is not.
        !           315:  */
        !           316: 
        !           317: #ifdef USE_PROTO
        !           318: int (mdev_flag) (mdev_t * mdevp, char flag)
        !           319: #else
        !           320: int
        !           321: mdev_flag ARGS ((mdevp, flag))
        !           322: mdev_t       * mdevp;
        !           323: char           flag;
        !           324: #endif
        !           325: {
        !           326:        if (mdevp->md_flags == NULL)
        !           327:                return 0;
        !           328:        return strchr (mdevp->md_flags->s_data, flag) != NULL;
        !           329: }
        !           330: 
        !           331: 
        !           332: #if 0
        !           333: /*
        !           334:  * Regenerate an 'mdevice' line from the stored record.
        !           335:  */
        !           336: 
        !           337: #ifdef USE_PROTO
        !           338: void (write_mdevice) (mdev_t * mdevp, FILE * out)
        !           339: #else
        !           340: void
        !           341: write_mdevice ARGS ((mdevp, out))
        !           342: mdev_t       * mdevp;
        !           343: FILE         * out;
        !           344: #endif
        !           345: {
        !           346:        (void) fprintf (out, "%-8s %-16s %-16s %-4s ",
        !           347:                        mdevp->md_devname->s_data,
        !           348:                        mdevp->md_functions->s_data, mdevp->md_flags->s_data,
        !           349:                        mdevp->md_prefix->s_data);
        !           350: 
        !           351:        if (mdevp->md_blk_maj [0] == mdevp->md_blk_maj [1])
        !           352:                (void) fprintf (out, "%-7d ", mdevp->md_blk_maj [0]);
        !           353:        else
        !           354:                (void) fprintf (out, "%3d-%-3d ", mdevp->md_blk_maj [0],
        !           355:                                mdevp->md_blk_maj [1]);
        !           356: 
        !           357:        if (mdevp->md_chr_maj [0] == mdevp->md_chr_maj [1])
        !           358:                (void) fprintf (out, "%-7d ", mdevp->md_chr_maj [0]);
        !           359:        else
        !           360:                (void) fprintf (out, "%3d-%-3d ", mdevp->md_chr_maj [0],
        !           361:                                mdevp->md_chr_maj [1]);
        !           362: 
        !           363:        (void) fprintf (out, "%-3d %-3d %-3d %d\n", mdevp->md_minor_min,
        !           364:                        mdevp->md_minor_max, mdevp->md_dma_chan,
        !           365:                        mdevp->md_cpu_id);
        !           366: }
        !           367: #endif
        !           368: 
        !           369: 
        !           370: /*
        !           371:  * Suck in a complete 'mdevice' file.
        !           372:  */
        !           373: 
        !           374: #ifdef USE_PROTO
        !           375: void (read_mdev_file) (CONST char * name)
        !           376: #else
        !           377: void
        !           378: read_mdev_file ARGS ((name))
        !           379: CONST char    *        name;
        !           380: #endif
        !           381: {
        !           382:        read_dev_file (name, read_mdevice);
        !           383: }
        !           384: 
        !           385: 
        !           386: /*
        !           387:  * Return the head of the global list of all read "mdevice" entries.
        !           388:  */
        !           389: 
        !           390: #ifdef USE_PROTO
        !           391: mdev_t * (mdevices) (void)
        !           392: #else
        !           393: mdev_t *
        !           394: mdevices ARGS (())
        !           395: #endif
        !           396: {
        !           397:        return _mdevices;
        !           398: }
        !           399: 
        !           400: 
        !           401: /*
        !           402:  * Generic insertion sort algorithm for "mdevice" entries based on a
        !           403:  * selection predicate and a comparison predicate.
        !           404:  *
        !           405:  * So that this can be a reasonably generic function, we pass it the internal
        !           406:  * offset of the "mdev_t *" member of the "mdevice" structure which will be
        !           407:  * used to link together the sorted entries.
        !           408:  */
        !           409: 
        !           410: #define        LINK(mdevp,off)         (* (mdev_t **) ((char *) (mdevp) + off))
        !           411: 
        !           412: #ifdef USE_PROTO
        !           413: void (mdev_sort) (mdlist_t * mdlistp, msel_t selpred, mcmp_t cmppred,
        !           414:                  size_t ptroff)
        !           415: #else
        !           416: void
        !           417: mdev_sort ARGS ((mdlistp, selpred, cmppred, ptroff))
        !           418: mdlist_t      *        mdlistp;
        !           419: msel_t         selpred;
        !           420: mcmp_t         cmppred;
        !           421: size_t         ptroff;
        !           422: #endif
        !           423: {
        !           424:        mdev_t        * scan;
        !           425:        mdev_t        * next;
        !           426: 
        !           427:        if (mdlistp == NULL || ptroff > sizeof (mdev_t))
        !           428:                throw_error ("bogus parameters to mdev_sort ()");
        !           429: 
        !           430: 
        !           431:        /*
        !           432:         * We'll just insert each selected member of the total list of
        !           433:         * mdevices into the output list in order by running down the output
        !           434:         * list until we compare true.
        !           435:         *
        !           436:         * We fetch "scan" before initializing the output list in case we are
        !           437:         * sorting the master device list.
        !           438:         */
        !           439: 
        !           440:        scan = mdevices ();
        !           441: 
        !           442:        mdlistp->mdl_first = mdlistp->mdl_last = NULL;
        !           443:        mdlistp->mdl_count = 0;
        !           444: 
        !           445:        for (; scan != NULL ; scan = next) {
        !           446:                mdev_t        * findpos;
        !           447:                mdev_t        * prev;
        !           448: 
        !           449:                /*
        !           450:                 * We get the "next" entry now in case we are sorting the
        !           451:                 * master list. We allow a "selpred" of NULL to select all
        !           452:                 * the entries.
        !           453:                 */
        !           454: 
        !           455:                next = scan->md_next;
        !           456: 
        !           457:                if (selpred != NULL && (* selpred) (scan) == 0)
        !           458:                        continue;
        !           459: 
        !           460: 
        !           461:                /*
        !           462:                 * Now attempt to find the right place for the new entry and
        !           463:                 * insert it there.
        !           464:                 */
        !           465: 
        !           466:                prev = NULL;
        !           467: 
        !           468:                for (findpos = mdlistp->mdl_first ; findpos != NULL ;
        !           469:                     findpos = LINK ((prev = findpos), ptroff)) {
        !           470:                        /*
        !           471:                         * A "cmppred" that is NULL means that the order of
        !           472:                          * output entries is irrelevant.
        !           473:                         */
        !           474: 
        !           475:                        if (cmppred == NULL ||
        !           476:                           (* cmppred) (findpos, scan) == 0)
        !           477:                                break;
        !           478:                }
        !           479: 
        !           480:                if (prev == NULL)
        !           481:                        mdlistp->mdl_first = scan;
        !           482:                else
        !           483:                        LINK (prev, ptroff) = scan;
        !           484: 
        !           485:                if ((LINK (scan, ptroff) = findpos) == NULL)
        !           486:                        mdlistp->mdl_last = scan;
        !           487: 
        !           488:                mdlistp->mdl_count ++;
        !           489:        }
        !           490: }

unix.superglobalmegacorp.com

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