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