Annotation of coherent/b/STREAMS/conf_79/mdev.c, revision 1.1.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.