Annotation of coherent/b/STREAMS/conf_79/assign.c, revision 1.1.1.1

1.1       root        1: #define        _DDI_DKI        1
                      2: #define        _SYSV4          1
                      3: 
                      4: /*
                      5:  * This file assigns device major and minor numbers based on configuration
                      6:  * data read in by "mkdev.c".
                      7:  */
                      8: /*
                      9:  *-IMPORTS:
                     10:  *     <sys/compat.h>
                     11:  *             CONST
                     12:  *             PROTO
                     13:  *             ARGS ()
                     14:  *             LOCAL
                     15:  *     <kernel/v_types.h>
                     16:  *             NODEV
                     17:  *             major_t
                     18:  *             minor_t
                     19:  *     <stddef.h>
                     20:  *             size_t
                     21:  *             offsetof ()
                     22:  *     <stdlib.h>
                     23:  *             NULL
                     24:  *             free ()
                     25:  *             malloc ()
                     26:  *     "ehand.h"
                     27:  *             throw_error ()
                     28:  *     "mdev.h"
                     29:  *             mdev_t
                     30:  *             mdev_sort ()
                     31:  */
                     32: 
                     33: #include <sys/compat.h>
                     34: #include <kernel/v_types.h>
                     35: #include <stddef.h>
                     36: #include <stdlib.h>
                     37: 
                     38: #include "ehand.h"
                     39: #include "mdev.h"
                     40: 
                     41: #include "assign.h"
                     42: 
                     43: /*
                     44:  * Selection predicate for choosing enabled character devices.
                     45:  */
                     46: 
                     47: #ifdef USE_PROTO
                     48: LOCAL int (chr_sel) (mdev_t * mdevp)
                     49: #else
                     50: LOCAL int
                     51: chr_sel ARGS ((mdevp))
                     52: mdev_t       * mdevp;
                     53: #endif
                     54: {
                     55:        return mdevp->md_configure == MD_ENABLED &&
                     56:               mdev_flag (mdevp, MDEV_CHAR);
                     57: }
                     58: 
                     59: 
                     60: /*
                     61:  * Predicate for comparing two mdevice entries on the basis of minimum
                     62:  * external character-device number.
                     63:  */
                     64: 
                     65: #ifdef USE_PROTO
                     66: LOCAL int (chr_pred) (mdev_t * left, mdev_t * right)
                     67: #else
                     68: LOCAL int
                     69: chr_pred ARGS ((left, right))
                     70: mdev_t       * left;
                     71: mdev_t       * right;
                     72: #endif
                     73: {
                     74:        return left->md_chr_maj [0] < right->md_chr_maj [0];
                     75: }
                     76: 
                     77: 
                     78: /*
                     79:  * Selection predicate for choosing enabled block devices.
                     80:  */
                     81: 
                     82: #ifdef USE_PROTO
                     83: LOCAL int (blk_sel) (mdev_t * mdevp)
                     84: #else
                     85: LOCAL int
                     86: blk_sel ARGS ((mdevp))
                     87: mdev_t       * mdevp;
                     88: #endif
                     89: {
                     90:        return mdevp->md_configure == MD_ENABLED &&
                     91:               mdev_flag (mdevp, MDEV_BLOCK);
                     92: }
                     93: 
                     94: 
                     95: /*
                     96:  * Predicate for comparing two mdevice entries on the basis of minimum
                     97:  * external block-device number.
                     98:  */
                     99: 
                    100: #ifdef USE_PROTO
                    101: LOCAL int (blk_pred) (mdev_t * left, mdev_t * right)
                    102: #else
                    103: LOCAL int
                    104: blk_pred ARGS ((left, right))
                    105: mdev_t       * left;
                    106: mdev_t       * right;
                    107: #endif
                    108: {
                    109:        return left->md_blk_maj [0] < right->md_blk_maj [0];
                    110: }
                    111: 
                    112: 
                    113: /*
                    114:  * Predicate for selecting modules (streams drivers that are not devices).
                    115:  */
                    116: 
                    117: #ifdef USE_PROTO
                    118: LOCAL int (mod_sel) (mdev_t * mdevp)
                    119: #else
                    120: LOCAL int
                    121: mod_sel ARGS ((mdevp))
                    122: mdev_t       * mdevp;
                    123: #endif
                    124: {
                    125:        return mdevp->md_configure == MD_ENABLED &&
                    126:               mdev_flag (mdevp, MDEV_STREAM) &&
                    127:               ! mdev_flag (mdevp, MDEV_CHAR);
                    128: }
                    129: 
                    130: 
                    131: /*
                    132:  * This is where we build the external->internal major number mapping table.
                    133:  *
                    134:  * The external->internal device number system becomes immediately useful
                    135:  * under STREAMS, where a) STREAMS cannot use device major numbers lower than
                    136:  * MAJOR_RESERVED under Coherent, and b) Coherent uses old-style 16-bit
                    137:  * dev_t's, so that the ability to transform a range of external majors into
                    138:  * a contiguous sequence of internal minor numbers will be of immediate value
                    139:  * in supporting connection-oriented services (although this is also pending
                    140:  * on the addition of support for cloning to the kernel).
                    141:  *
                    142:  * Mapping between internal and external numbers is not simple; what makes it
                    143:  * worse is that because there is a single mapping that has to be the same
                    144:  * for both block and character tables, the construction of the bdevsw [] and
                    145:  * cdevsw [] internal tables is constrained. This is only a problem if
                    146:  * multiple external major numbers are allowed, and each device is only
                    147:  * permitted to have a single internal major number. The interpretation of the
                    148:  * 'M' flag in this circumstance is unclear.
                    149:  *
                    150:  * The assign_imajors () code should be able to deal with the most complex
                    151:  * case, which is where multiple external majors may actually be mapped to
                    152:  * multiple internal numbers, thus
                    153:  *
                    154:  *     Block external :            |-----scsi-------|
                    155:  *     Character external:   |--tcp--| |-udp-|  |ttys|
                    156:  *
                    157:  * Might map 'tcp' to internal 0, 'udp' to internal 1, 'ttys' to internal 2,
                    158:  * while 'scsi' would have 0, 1, and 2 as internal major numbers.
                    159:  *
                    160:  * This is all hypothetical at the moment, since multiple majors are new to
                    161:  * Coherent anyway. For simplicity, we may constrain the above to be an error
                    162:  * by requiring unique internal number for each device. However, the machinery
                    163:  * in assign_imajors () will have to be flexible enough to deal with the
                    164:  * above.
                    165:  *
                    166:  * NOTE: The complex model is only applicable if a device does not care what
                    167:  * minor numbers are given to it, since there is a single shared table used
                    168:  * to map a range of external major numbers into a range of internal minor
                    169:  * numbers. Since this table is shared, it constrains even more heavily the
                    170:  * circumstances in which numbers can overlap. Without a flag to detect when
                    171:  * a driver doesn't care about minor numbers, we simply forget about the
                    172:  * complex model.
                    173:  */
                    174: 
                    175: /*
                    176:  * Definitions used to control parts of the way assign_imajors () deals with
                    177:  * the external->internal mapping (as discussed above). The main things we
                    178:  * isolate here are the calculations of the upper bounds for table allocations
                    179:  * since the constraint of a common mapping means that the cdevsw [] and
                    180:  * bdevsw [] tables may be larger than a separate mapping would permit.
                    181:  *
                    182:  * In particular, if ncdevs is the number of character devices and nbdevs is
                    183:  * the number of block devices, the upper bound on table size is:
                    184:  *     Simple model:   block = char = max (ncdevs, nbdevs)
                    185:  *     Complex model:  char = ncdevs + max (nbdevs - 1, 0)
                    186:  *                     block = nbdevs + max (ncdevs - 1, 0)
                    187:  */
                    188: 
                    189: #define        MAX(a,b)                ((a) > (b) ? (a) : (b))
                    190: #define        MIN(a,b)                ((a) < (b) ? (a) : (b))
                    191: 
                    192: #define        MAX_CHR_IMAJORS(c,b)    MAX (c, b)
                    193: #define        MAX_BLK_IMAJORS(c,b)    MAX (c, b)
                    194: 
                    195: 
                    196: /*
                    197:  * Assign internal major numbers to devices. For now, this function does not
                    198:  * attempt to deal with assigning major number ranges.
                    199:  */
                    200: 
                    201: #ifdef USE_PROTO
                    202: extinfo_t * (assign_imajors) (void)
                    203: #else
                    204: extinfo_t *
                    205: assign_imajors ARGS (())
                    206: #endif
                    207: {
                    208:        extinfo_t     * extinfop;
                    209:        mdlist_t        blklist;
                    210:        mdlist_t        chrlist;
                    211:        mdlist_t        modlist;
                    212: 
                    213:        int             nemajors;
                    214:        int             i;
                    215: 
                    216: 
                    217:        /*
                    218:         * The algorithm for assigning internal numbers for the block and
                    219:         * character-device tables will be able to run in a single pass if we
                    220:         * are able to provide lists of character and block devices sorted by
                    221:         * beginning external major number. This sort process also provides us
                    222:         * a variety of other useful information directly, such as the maximum
                    223:         * external number used.
                    224:         */
                    225: 
                    226:        mdev_sort (& chrlist, chr_sel, chr_pred, offsetof (mdev_t, md_link1));
                    227:        mdev_sort (& blklist, blk_sel, blk_pred, offsetof (mdev_t, md_link2));
                    228:        mdev_sort (& modlist, mod_sel, NULL, offsetof (mdev_t, md_link3));
                    229: 
                    230:        nemajors = 0;
                    231: 
                    232:        if (chrlist.mdl_last != NULL)
                    233:                nemajors = MAX (nemajors, chrlist.mdl_last->md_chr_maj [1]);
                    234: 
                    235:        if (blklist.mdl_last != NULL)
                    236:                nemajors = MAX (nemajors, blklist.mdl_last->md_blk_maj [1]);
                    237: 
                    238:        nemajors ++;
                    239: 
                    240: 
                    241:        /*
                    242:         * Now we know how many of everything there is, allocate space for
                    243:         * tables.
                    244:         */
                    245: 
                    246:        i = sizeof (* extinfop) +
                    247:            sizeof (mdev_t *) * (MAX_CHR_IMAJORS (chrlist.mdl_count,
                    248:                                                  blklist.mdl_count) +
                    249:                                 MAX_BLK_IMAJORS (chrlist.mdl_count,
                    250:                                                  blklist.mdl_count) +
                    251:                                 modlist.mdl_count) +
                    252:            2 * sizeof (minor_t) * nemajors;
                    253: 
                    254:        if ((extinfop = (extinfo_t *) malloc (i)) == NULL)
                    255:                throw_error ("insufficient memory in assign_imajors ()");
                    256: 
                    257:        extinfop->ei_etoimajor = (minor_t *) (extinfop + 1);
                    258:        extinfop->ei_minoroffset = extinfop->ei_etoimajor + nemajors;
                    259:        extinfop->ei_modules = (mdev_t **) (extinfop->ei_minoroffset +
                    260:                                            nemajors);
                    261:        extinfop->ei_cdevsw = extinfop->ei_modules + modlist.mdl_count;
                    262:        extinfop->ei_bdevsw = extinfop->ei_cdevsw +
                    263:                                MAX_CHR_IMAJORS (chrlist.mdl_count,
                    264:                                                 blklist.mdl_count);
                    265: 
                    266:        /*
                    267:         * Since we allocate space for the maximum number of table entries,
                    268:         * the loops below assign internal numbers which may not be
                    269:         * contiguous, or may be below the upper limit allocated.
                    270:         */
                    271: 
                    272:        extinfop->ei_nemajors = nemajors;
                    273:        extinfop->ei_ncdevs = 0;
                    274:        extinfop->ei_nbdevs = 0;
                    275:        extinfop->ei_nmodules = modlist.mdl_count;
                    276: 
                    277:        for (i = 0 ; i < nemajors ; i ++) {
                    278: 
                    279:                extinfop->ei_etoimajor [i] = NODEV;
                    280:                extinfop->ei_minoroffset [i] = 0;
                    281:        }
                    282: 
                    283: 
                    284:        for (i = 0 ; i < MAX_CHR_IMAJORS (chrlist.mdl_count,
                    285:                                          blklist.mdl_count) ; i ++) {
                    286:                extinfop->ei_cdevsw [i] = NULL;
                    287:        }
                    288: 
                    289:        for (i = 0 ; i < MAX_BLK_IMAJORS (chrlist.mdl_count,
                    290:                                          blklist.mdl_count) ; i ++) {
                    291:                extinfop->ei_bdevsw [i] = NULL;
                    292:        }
                    293: 
                    294: 
                    295: 
                    296:        while (chrlist.mdl_first != NULL || blklist.mdl_first != NULL) {
                    297:                mdev_t        * chrp;
                    298:                mdev_t        * blkp;
                    299:                int             extlo;
                    300:                int             exthi;
                    301:                int             internal;
                    302:                int             minorinc;
                    303:                int             minorofs;
                    304: 
                    305:                /*
                    306:                 * Choose a range of external numbers that we are going to
                    307:                 * assign to a single internal number. If our choice is not
                    308:                 * constrained by an overlap between character and block
                    309:                 * external numbers, then we deal with that.
                    310:                 */
                    311: 
                    312:                blkp = blklist.mdl_first;
                    313: 
                    314:                if ((chrp = chrlist.mdl_first) != NULL) {
                    315: 
                    316:                        extlo = chrp->md_chr_maj [0];
                    317:                        exthi = chrp->md_chr_maj [1];
                    318:                        minorinc = chrp->md_minor_max;
                    319: 
                    320:                        if (blkp != NULL) {
                    321: 
                    322:                                if (blkp->md_blk_maj [1] < extlo) {
                    323: 
                    324:                                        chrp = NULL;
                    325:                                        goto doblock;
                    326:                                }
                    327: 
                    328:                                if (blkp->md_blk_maj [0] > exthi) {
                    329:                                        blkp = NULL;
                    330:                                        goto dochar;
                    331:                                }
                    332: 
                    333:                                /*
                    334:                                 * Because of minor-number mapping, overlap is
                    335:                                 * only valid in special circumstances.
                    336:                                 */
                    337: 
                    338:                                if (blkp->md_blk_maj [0] != extlo ||
                    339:                                    (blkp->md_minor_max != minorinc &&
                    340:                                     blkp->md_blk_maj [1] >
                    341:                                                blkp->md_blk_maj [0] &&
                    342:                                     exthi > extlo)) {
                    343: 
                    344:                                        free (extinfop);
                    345:                                        throw_error ("minor number mapping conflict");
                    346:                                }
                    347: 
                    348: 
                    349:                                /*
                    350:                                 * Choose a suitable internal major number.
                    351:                                 */
                    352: 
                    353:                                if (exthi < blkp->md_blk_maj [1]) {
                    354: 
                    355:                                        exthi = blkp->md_blk_maj [1];
                    356:                                        minorinc = blkp->md_minor_max;
                    357:                                }
                    358: 
                    359:                                internal = MAX (extinfop->ei_ncdevs,
                    360:                                                extinfop->ei_nbdevs);
                    361: 
                    362:                                goto done;
                    363:                        }
                    364: dochar:
                    365:                        /*
                    366:                         * Simple case, select an internal number.
                    367:                         */
                    368: 
                    369:                        for (internal = 0 ;
                    370:                             extinfop->ei_cdevsw [internal] != NULL ;
                    371:                             internal ++)
                    372:                                ;
                    373: 
                    374:                        if (internal > extinfop->ei_ncdevs) {
                    375: 
                    376:                                free (extinfop);
                    377:                                throw_error ("internal check failed, assign_imajors ()");
                    378:                        }
                    379:                } else {
                    380:                        /*
                    381:                         * Simple case for block device, select an internal
                    382:                         * number.
                    383:                         */
                    384: 
                    385: doblock:
                    386:                        extlo = blkp->md_blk_maj [0];
                    387:                        exthi = blkp->md_blk_maj [1];
                    388:                        minorinc = blkp->md_minor_max;
                    389: 
                    390:                        for (internal = 0 ;
                    391:                             extinfop->ei_bdevsw [internal] != NULL ;
                    392:                             internal ++)
                    393:                                ;
                    394: 
                    395:                        if (internal > extinfop->ei_nbdevs) {
                    396: 
                    397:                                free (extinfop);
                    398:                                throw_error ("internal check failed, assign_imajors ()");
                    399:                        }
                    400:                }
                    401: done:
                    402:                /*
                    403:                 * Now we have decided when, where, and how much, fill in the
                    404:                 * table.
                    405:                 */
                    406: 
                    407:                minorofs = 0;
                    408: 
                    409:                while (extlo <= exthi) {
                    410: 
                    411:                        if (extinfop->ei_etoimajor [extlo] != NODEV) {
                    412: 
                    413:                                free (extinfop);
                    414:                                throw_error ("major-number mapping conflict");
                    415:                        }
                    416: 
                    417:                        extinfop->ei_etoimajor [extlo] = internal;
                    418:                        extinfop->ei_minoroffset [extlo] = minorofs;
                    419: 
                    420:                        minorofs += minorinc;
                    421:                        extlo ++;
                    422:                }
                    423: 
                    424:                if ((extinfop->ei_cdevsw [internal] = chrp) != NULL) {
                    425: 
                    426:                        if (internal >= extinfop->ei_ncdevs)
                    427:                                extinfop->ei_ncdevs = internal + 1;
                    428: 
                    429:                        chrlist.mdl_first = chrp->md_link1;
                    430:                }
                    431: 
                    432: 
                    433:                if ((extinfop->ei_bdevsw [internal] = blkp) != NULL) {
                    434: 
                    435:                        if (internal >= extinfop->ei_nbdevs)
                    436:                                extinfop->ei_nbdevs = internal + 1;
                    437: 
                    438:                        blklist.mdl_first = blkp->md_link2;
                    439:                }
                    440:        }
                    441: 
                    442: 
                    443:        /*
                    444:         * Now we can build a table of all the STREAMS modules.
                    445:         */
                    446: 
                    447:        i = 0;
                    448: 
                    449:        while (modlist.mdl_first != NULL) {
                    450: 
                    451:                extinfop->ei_modules [i ++] = modlist.mdl_first;
                    452: 
                    453:                modlist.mdl_first = modlist.mdl_first->md_link3;
                    454:        }
                    455: 
                    456:        if (i != modlist.mdl_count) {
                    457: 
                    458:                free (extinfop);
                    459:                throw_error ("internal consistency check failed in assign_imajors ()");
                    460:         }
                    461: 
                    462:        return extinfop;
                    463: }
                    464: 

unix.superglobalmegacorp.com

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