Annotation of coherent/f/etc/conf/bin/src/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: #include "input.h"
                     40: 
                     41: #include "mdev.h"
                     42: 
                     43: 
                     44: LOCAL mdev_t  *        _mdevices;
                     45: 
                     46: 
                     47: /*
                     48:  * Find a device by symbol.
                     49:  */
                     50: 
                     51: #if    USE_PROTO
                     52: mdev_t * (find_mdev) (symbol_t * sym)
                     53: #else
                     54: mdev_t *
                     55: find_mdev ARGS ((sym))
                     56: symbol_t      *        sym;
                     57: #endif
                     58: {
                     59:        mdev_t        * scan;
                     60: 
                     61:        for (scan = _mdevices ; scan != NULL ; scan = scan->md_next) {
                     62: 
                     63:                if (scan->md_devname == sym)
                     64:                        return scan;
                     65:        }
                     66: 
                     67:        return NULL;
                     68: }
                     69: 
                     70: 
                     71: /*
                     72:  * Write a single number or a range of device major numbers.
                     73:  */
                     74: 
                     75: #if    USE_PROTO
                     76: LOCAL int write_range (input_t * input, maj_t major [2])
                     77: #else
                     78: LOCAL int
                     79: write_range (input, major)
                     80: input_t              * input;
                     81: maj_t          major [2];
                     82: #endif
                     83: {
                     84:        if (major [0] == major [1])
                     85:                return (* input->in_filter) (input, "%d\t", major [0]);
                     86: 
                     87:        return (* input->in_filter) (input, "%d-%d\t", major [0], major [1]);
                     88: }
                     89: 
                     90: 
                     91: /*
                     92:  * Regenerate an 'mdevice' line from the stored record.
                     93:  */
                     94: 
                     95: #define        HYPHEN(x)       ((x) == NULL ? (unsigned char *) "-" : (x))
                     96: 
                     97: #if    USE_PROTO
                     98: void (write_mdevice) (mdev_t * mdevp, input_t * input)
                     99: #else
                    100: void
                    101: write_mdevice ARGS ((mdevp, input))
                    102: mdev_t       * mdevp;
                    103: input_t              * input;
                    104: #endif
                    105: {
                    106:        if ((* input->in_filter) (input, "%s<1>%s<2>%s<3>%s<4>",
                    107:                                  mdevp->md_devname->s_data,
                    108:                                  HYPHEN (mdevp->md_functions->s_data),
                    109:                                  HYPHEN (mdevp->md_flags->s_data),
                    110:                                  mdevp->md_prefix->s_data) < 0 ||
                    111:            write_range (input, mdevp->md_blk_maj) < 0 ||
                    112:            write_range (input, mdevp->md_chr_maj) < 0 ||
                    113:            (* input->in_filter) (input, "%d<7>%d<8>%d<9>%d\n",
                    114:                                  mdevp->md_minor_min, mdevp->md_minor_max,
                    115:                                  mdevp->md_dma_chan, mdevp->md_cpu_id) < 0) {
                    116: 
                    117:                throw_error ("Output error");
                    118:        }
                    119: }
                    120: 
                    121: 
                    122: /*
                    123:  * Read lines from an "mdevice" file.
                    124:  *
                    125:  * This code is really messy. My apologies.
                    126:  */
                    127: 
                    128: #if    USE_PROTO
                    129: LOCAL mdev_t * (read_mdevice) (input_t * input, lex_t * lexp, int * end_char)
                    130: #else
                    131: LOCAL mdev_t *
                    132: read_mdevice ARGS ((input, lexp, end_char))
                    133: input_t              * input;
                    134: lex_t         *        lexp;
                    135: int          * end_char;
                    136: #endif
                    137: {
                    138:        VOLATILE int    ch = '\n';
                    139:        mdev_t * VOLATILE mdevp;
                    140:        ehand_t         err;
                    141:        lex_t           functions = { NULL, NULL, "-", MDEV_FUNCS, LEX_WILD };
                    142:        lex_t           flags = { NULL, NULL, "-", MDEV_FLAGS, LEX_WILD };
                    143: 
                    144:        functions.l_prev = lexp;
                    145:        flags.l_prev = lexp;
                    146: 
                    147:        if ((mdevp = (mdev_t *) malloc (sizeof (* mdevp))) == NULL)
                    148:                throw_error ("out of memory in read_mdevice ()");
                    149: 
                    150:        if (PUSH_HANDLER (err) == 0) {
                    151:                /*
                    152:                 * If the first thing on the line works out to be an EOF,
                    153:                 * then bail out without an error.
                    154:                 */
                    155: 
                    156:                ch = read_symbol (input, lexp, & mdevp->md_devname);
                    157: 
                    158:                if (mdevp->md_devname == NULL) {
                    159:                        /*
                    160:                         * We allow an EOF at the beginning of a line and we
                    161:                         * also allow a blank line.
                    162:                         */
                    163: 
                    164:                        free (mdevp);
                    165:                        mdevp = NULL;
                    166:                        goto at_eof;
                    167:                }
                    168:                check_not_eol (ch);
                    169: 
                    170:                if (mdevp->md_devname->s_size > MAX_DEVNAME)
                    171:                        throw_error ("device name must be <= %d characters",
                    172:                                     MAX_DEVNAME);
                    173: 
                    174:                /*
                    175:                 * We read the functions and characteristics field as symbols,
                    176:                 * even though they are really strings, since it makes no
                    177:                 * difference to the result.
                    178:                 */
                    179: 
                    180:                ch = read_symbol (input, & functions, & mdevp->md_functions);
                    181:                if (mdevp->md_functions == NULL && ch != '-')
                    182:                        throw_error ("Unable to read functions");
                    183:                check_not_eol (ch);
                    184: 
                    185:                ch = read_symbol (input, & flags, & mdevp->md_flags);
                    186:                if (mdevp->md_flags == NULL && ch != '-')
                    187:                        throw_error ("Unable to read flags");
                    188:                check_not_eol (ch);
                    189: 
                    190:                if ((mdev_flag (mdevp, MDEV_BLOCK) ||
                    191:                     mdev_flag (mdevp, MDEV_CHAR) ||
                    192:                     mdev_flag (mdevp, MDEV_STREAM)) &&
                    193:                    ! mdev_flag (mdevp, MDEV_DDI_DDK)) {
                    194: 
                    195:                        throw_error ("devices must be DDI/DDK compliant");
                    196:                }
                    197: 
                    198: 
                    199:                /*
                    200:                 * We don't check for a unique device prefix, since there may
                    201:                 * be a legitimate reason to configure the same prefix twice.
                    202:                 *
                    203:                 * If the user installs multiple devices with the same prefix,
                    204:                 * the linker should catch it. Of course, a registration
                    205:                 * system might help. We only enforce the size limit for
                    206:                 * drivers... other kernel facilities can user longer names.
                    207:                 */
                    208: 
                    209:                ch = read_symbol (input, lexp, & mdevp->md_prefix);
                    210:                check_not_eol (ch);
                    211: 
                    212:                if ((mdev_flag (mdevp, MDEV_BLOCK) ||
                    213:                     mdev_flag (mdevp, MDEV_CHAR) ||
                    214:                     mdev_flag (mdevp, MDEV_STREAM)) &&
                    215:                    mdevp->md_prefix->s_size > MAX_PREFIX)
                    216:                        throw_error ("device prefix must be <= %d characters",
                    217:                                     MAX_PREFIX);
                    218: 
                    219: 
                    220:                ch = read_uints (input, lexp, mdevp->md_blk_maj, RANGE);
                    221:                check_not_eol (ch);
                    222: 
                    223:                if (mdev_flag (mdevp, MDEV_BLOCK)) {
                    224: 
                    225:                        if (mdevp->md_blk_maj [0] > mdevp->md_blk_maj [1])
                    226:                                throw_error ("lower range bound higher than upper bound");
                    227: 
                    228:                        if (mdevp->md_blk_maj [0] < MAJOR_RESERVED)
                    229:                                throw_error ("major devices up to %d reserved",
                    230:                                             MAJOR_RESERVED - 1);
                    231: 
                    232:                } else if (mdev_flag (mdevp, MDEV_COHERENT)) {
                    233: 
                    234:                        if (mdevp->md_blk_maj [0] != mdevp->md_blk_maj [1])
                    235:                                throw_error ("Coherent devices occupy a single major number");
                    236: 
                    237:                        if (mdevp->md_blk_maj [0] >= MAJOR_RESERVED)
                    238:                                throw_error ("Coherent devices only in range 0-%d",
                    239:                                             MAJOR_RESERVED - 1);
                    240:                } else
                    241:                        mdevp->md_blk_maj [0] = mdevp->md_blk_maj [1] = 0;
                    242: 
                    243: 
                    244:                ch = read_uints (input, lexp, mdevp->md_chr_maj, RANGE);
                    245:                check_not_eol (ch);
                    246: 
                    247:                if (mdev_flag (mdevp, MDEV_CHAR)) {
                    248: 
                    249:                        if (mdevp->md_chr_maj [0] > mdevp->md_chr_maj [1])
                    250:                                throw_error ("lower range bound higher that upper bound");
                    251: 
                    252:                        if (mdevp->md_chr_maj [0] < MAJOR_RESERVED)
                    253:                                throw_error ("major devices 0-%d reserved",
                    254:                                             MAJOR_RESERVED - 1);
                    255:                } else if (mdev_flag (mdevp, MDEV_COHERENT)) {
                    256: 
                    257:                        if (mdevp->md_chr_maj [0] != mdevp->md_blk_maj [0] ||
                    258:                            mdevp->md_blk_maj [0] != mdevp->md_chr_maj [0])
                    259:                                throw_error ("Coherent drivers must have same "
                    260:                                             "block and character numbers");
                    261:                } else
                    262:                        mdevp->md_chr_maj [0] = mdevp->md_chr_maj [1] = 0;
                    263: 
                    264:                ch = read_uints (input, lexp, & mdevp->md_minor_min,
                    265:                                 NO_RANGE);
                    266:                check_not_eol (ch);
                    267: 
                    268:                ch = read_uints (input, lexp, & mdevp->md_minor_max,
                    269:                                 NO_RANGE);
                    270:                check_not_eol (ch);
                    271: 
                    272:                if (mdevp->md_minor_min > mdevp->md_minor_max)
                    273:                        throw_error ("minor minimum higher than maximum");
                    274: 
                    275:                ch = read_ints (input, lexp, & mdevp->md_dma_chan, NO_RANGE);
                    276: 
                    277:                if (ch != '\n' && ch != SYM_EOF) {
                    278:                        /*
                    279:                         * The "cpu_id" field is optional.
                    280:                         */
                    281: 
                    282:                        ch = read_ints (input, lexp, & mdevp->md_cpu_id,
                    283:                                        NO_RANGE);
                    284:                } else
                    285:                        mdevp->md_cpu_id = -1;
                    286: 
                    287:                ch = expect_eol (input, lexp, ch);
                    288: 
                    289: 
                    290:                /*
                    291:                 * Having passed all the reasonableness checks, we link the
                    292:                 * new entry into the chain.
                    293:                 */
                    294: 
                    295:                mdevp->md_sdevices = NULL;
                    296:                mdevp->md_interrupt = 0;
                    297: 
                    298:                mdevp->md_configure = MD_INSTALLABLE;
                    299:        } else {
                    300: 
                    301:                free (mdevp);
                    302:                CHAIN_ERROR (err);
                    303:        }
                    304: 
                    305: at_eof:
                    306:        POP_HANDLER (err);
                    307: 
                    308:        * end_char = ch;
                    309:        return mdevp;
                    310: }
                    311: 
                    312: 
                    313: /*
                    314:  * This function is passed as a parameter to read_dev_string () to read an
                    315:  * 'mtune' entry (usually a program argument) and hook it into a global list.
                    316:  */
                    317: 
                    318: #if    USE_PROTO
                    319: LOCAL int _read_mdev_string (input_t * input, lex_t * lexp,
                    320:                              mdev_t ** mdlistp)
                    321: #else
                    322: LOCAL int
                    323: _read_mdev_string (input, lexp, mdlistp)
                    324: input_t              * input;
                    325: lex_t        * lexp;
                    326: mdev_t      ** mdlistp;
                    327: #endif
                    328: {
                    329:        mdev_t        * mdevp;
                    330:        int             ch;
                    331: 
                    332:        if ((mdevp = read_mdevice (input, lexp, & ch)) != NULL) {
                    333:                mdevp->md_next = * mdlistp;
                    334:                * mdlistp = mdevp;
                    335:        }
                    336: 
                    337:        return ch;
                    338: }
                    339: 
                    340: 
                    341: /*
                    342:  * Common code from _read_mdevice_file () to link an entry into the global
                    343:  * 'mdevice' chain.
                    344:  */
                    345: 
                    346: #if    USE_PROTO
                    347: LOCAL void (link_mdevice) (mdev_t * mdevp, input_t * input)
                    348: #else
                    349: LOCAL void
                    350: link_mdevice ARGS ((mdevp, input))
                    351: mdev_t       * mdevp;
                    352: input_t              * input;
                    353: #endif
                    354: {
                    355:        if (find_mdev (mdevp->md_devname) != NULL)
                    356:                throw_error ("device name must be unique");
                    357: 
                    358:        mdevp->md_next = _mdevices;
                    359:        _mdevices = mdevp;
                    360: 
                    361:        write_mdevice (mdevp, input);
                    362: }
                    363: 
                    364: 
                    365: /*
                    366:  * This function is passed as a pointer to read_dev_file () to read an
                    367:  * 'mdevice' entry from the input and link it in to the global device list.
                    368:  *
                    369:  * The extra argument is the head of a list of 'mdevice' entries which are to
                    370:  * replace/be added to the existing 'mdevice' entries.
                    371:  */
                    372: 
                    373: #if    USE_PROTO
                    374: LOCAL int _read_mdevice_file (input_t * input, lex_t * lexp, 
                    375:                              mdev_t ** changes)
                    376: #else
                    377: LOCAL int
                    378: _read_mdevice_file (input, lexp, changes)
                    379: input_t              * input;
                    380: lex_t        * lexp;
                    381: mdev_t      ** changes;
                    382: #endif
                    383: {
                    384:        mdev_t        * mdevp;
                    385:        int             ch;
                    386: 
                    387:        if ((mdevp = read_mdevice (input, lexp, & ch)) == NULL) {
                    388:                if (ch == READ_EOF) {
                    389:                        /*
                    390:                         * Blow the remaining changes out as new entries.
                    391:                         */
                    392: 
                    393:                        while ((mdevp = * changes) != NULL) {
                    394:                                * changes = mdevp->md_next;
                    395:                                link_mdevice (mdevp, input);
                    396:                        }
                    397:                }
                    398:                return ch;
                    399:        }
                    400: 
                    401:        /*
                    402:         * Link the newly-allocated mdevice entry into the global
                    403:         * mdevice chain.
                    404:         */
                    405: 
                    406:        if (changes) {
                    407:                mdev_t       ** scan;
                    408: 
                    409:                for (scan = changes ; * scan != NULL ;
                    410:                     scan = & (* scan)->md_next) {
                    411: 
                    412:                        if ((* scan)->md_devname == mdevp->md_devname) {
                    413:                                /*
                    414:                                 * Our current entry is being replaced by a
                    415:                                 * new one; unlink the new entry from the
                    416:                                 * change list and discard the old entry.
                    417:                                 */
                    418: 
                    419:                                free (mdevp);
                    420: 
                    421:                                if (report_mode ())
                    422:                                        return ch;
                    423: 
                    424:                                mdevp = * scan;
                    425:                                * scan = mdevp->md_next;
                    426:                                break;
                    427:                        }
                    428:                }
                    429:        }
                    430: 
                    431:        link_mdevice (mdevp, input);
                    432:        return ch;
                    433: }
                    434: 
                    435: 
                    436: /*
                    437:  * Test a device for a function code; returns 1 if code is present, or 0 if
                    438:  * code is not specified for device.
                    439:  */
                    440: 
                    441: #if    USE_PROTO
                    442: int (mdev_func) (mdev_t * mdevp, char func)
                    443: #else
                    444: int
                    445: mdev_func ARGS ((mdevp, func))
                    446: mdev_t       * mdevp;
                    447: char           func;
                    448: #endif
                    449: {
                    450:        if (mdevp->md_functions == NULL)
                    451:                return 0;
                    452:        return strchr (mdevp->md_functions->s_data, func) != NULL;
                    453: }
                    454: 
                    455: 
                    456: /*
                    457:  * Test device characteristics; returns 1 if characteristic is specified for
                    458:  * device, 0 if it is not.
                    459:  */
                    460: 
                    461: #if    USE_PROTO
                    462: int (mdev_flag) (mdev_t * mdevp, char flag)
                    463: #else
                    464: int
                    465: mdev_flag ARGS ((mdevp, flag))
                    466: mdev_t       * mdevp;
                    467: char           flag;
                    468: #endif
                    469: {
                    470:        if (mdevp->md_flags == NULL)
                    471:                return 0;
                    472:        return strchr (mdevp->md_flags->s_data, flag) != NULL;
                    473: }
                    474: 
                    475: 
                    476: /*
                    477:  * Read in an "mtune" entry from a string and add it to a list.
                    478:  */
                    479: 
                    480: #if    USE_PROTO
                    481: void read_mdev_string (CONST char * string, VOID * extra)
                    482: #else
                    483: void
                    484: read_mdev_string (string, extra)
                    485: CONST char    *        string;
                    486: VOID         * extra;
                    487: #endif
                    488: {
                    489:        read_dev_string (string, (dev_func_p) _read_mdev_string, extra);
                    490: }
                    491: 
                    492: 
                    493: /*
                    494:  * Suck in a complete 'mdevice' file.
                    495:  */
                    496: 
                    497: #if    USE_PROTO
                    498: void (read_mdev_file) (CONST char * inname, CONST char * outname, VOID * extra)
                    499: #else
                    500: void
                    501: read_mdev_file ARGS ((inname, outname, extra))
                    502: CONST char    *        inname;
                    503: CONST char    *        outname;
                    504: VOID         * extra;
                    505: #endif
                    506: {
                    507:        read_dev_file (inname, outname, (dev_func_p) _read_mdevice_file,
                    508:                       extra);
                    509: }
                    510: 
                    511: 
                    512: /*
                    513:  * Iterate over all the mdevices in the system.
                    514:  */
                    515: 
                    516: #if    USE_PROTO
                    517: void (for_all_mdevices) (miter_t iter, VOID * extra)
                    518: #else
                    519: void
                    520: for_all_mdevices ARGS ((iter, extra))
                    521: miter_t                iter;
                    522: VOID         * extra;
                    523: #endif
                    524: {
                    525:        mdev_t        * temp;
                    526: 
                    527:        for (temp = _mdevices ; temp != NULL ; temp = temp->md_next)
                    528:                (* iter) (extra, temp);
                    529: }
                    530: 
                    531: 
                    532: /*
                    533:  * Generic insertion sort algorithm for "mdevice" entries based on a
                    534:  * selection predicate and a comparison predicate.
                    535:  *
                    536:  * So that this can be a reasonably generic function, we pass it the internal
                    537:  * offset of the "mdev_t *" member of the "mdevice" structure which will be
                    538:  * used to link together the sorted entries.
                    539:  *
                    540:  * The return value is the length of the sorted list.
                    541:  */
                    542: 
                    543: #define        LINK(mdevp,off)         (* (mdev_t **) ((char *) (mdevp) + off))
                    544: 
                    545: #if    USE_PROTO
                    546: int (mdev_sort) (mdev_t ** mdlistp, mdev_t ** mdendp, msel_t selpred,
                    547:                 mcmp_t cmppred, size_t ptroff)
                    548: #else
                    549: int
                    550: mdev_sort ARGS ((mdlistp, mdendp, selpred, cmppred, ptroff))
                    551: mdev_t       **        mdlistp;
                    552: mdev_t      ** mdendp;
                    553: msel_t         selpred;
                    554: mcmp_t         cmppred;
                    555: size_t         ptroff;
                    556: #endif
                    557: {
                    558:        mdev_t        * scan;
                    559:        mdev_t        * next;
                    560:        int             count;
                    561: 
                    562:        if (mdlistp == NULL || ptroff > sizeof (mdev_t))
                    563:                throw_error ("bogus parameters to mdev_sort ()");
                    564: 
                    565: 
                    566:        /*
                    567:         * We'll just insert each selected member of the total list of
                    568:         * mdevices into the output list in order by running down the output
                    569:         * list until we compare true.
                    570:         *
                    571:         * We fetch "scan" before initializing the output list in case we are
                    572:         * sorting the master device list.
                    573:         */
                    574: 
                    575:        * mdlistp = NULL;
                    576:        if (mdendp != NULL)
                    577:                * mdendp = NULL;
                    578: 
                    579:        for (count = 0, scan = _mdevices ; scan != NULL ; scan = next) {
                    580:                mdev_t        * findpos;
                    581:                mdev_t        * prev;
                    582: 
                    583:                /*
                    584:                 * We get the "next" entry now in case we are sorting the
                    585:                 * master list. We allow a "selpred" of NULL to select all
                    586:                 * the entries.
                    587:                 */
                    588: 
                    589:                next = scan->md_next;
                    590: 
                    591:                if (selpred != NULL && (* selpred) (scan) == 0)
                    592:                        continue;
                    593: 
                    594: 
                    595:                /*
                    596:                 * Now attempt to find the right place for the new entry and
                    597:                 * insert it there.
                    598:                 */
                    599: 
                    600:                prev = NULL;
                    601: 
                    602:                for (findpos = * mdlistp ; findpos != NULL ;
                    603:                     findpos = LINK ((prev = findpos), ptroff)) {
                    604:                        /*
                    605:                         * A "cmppred" that is NULL means that the order of
                    606:                          * output entries is irrelevant.
                    607:                         */
                    608: 
                    609:                        if (cmppred == NULL ||
                    610:                            (* cmppred) (findpos, scan) == 0)
                    611:                                break;
                    612:                }
                    613: 
                    614:                if (prev == NULL)
                    615:                        * mdlistp = scan;
                    616:                else
                    617:                        LINK (prev, ptroff) = scan;
                    618: 
                    619:                if ((LINK (scan, ptroff) = findpos) == NULL && mdendp != NULL)
                    620:                        * mdendp = scan;
                    621: 
                    622:                count ++;
                    623:        }
                    624: 
                    625:        return count;
                    626: }

unix.superglobalmegacorp.com

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