Annotation of Gnu-Mach/device/dev_lookup.c, revision 1.1.1.2

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     Author: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   3/89
                     29:  */
                     30: 
                     31: #include <mach/port.h>
                     32: #include <mach/vm_param.h>
                     33: 
                     34: #include <kern/queue.h>
1.1.1.2 ! root       35: #include <kern/slab.h>
1.1       root       36: 
                     37: #include <device/device_types.h>
                     38: #include <device/dev_hdr.h>
                     39: #include <device/conf.h>
                     40: #include <device/param.h>              /* DEV_BSIZE, as default */
                     41: 
                     42: #include <ipc/ipc_port.h>
                     43: #include <kern/ipc_kobject.h>
                     44: 
1.1.1.2 ! root       45: #include <device/device_emul.h>
1.1       root       46: 
                     47: /*
                     48:  * Device structure routines: reference counting, port->device.
                     49:  */
                     50: 
                     51: /*
                     52:  * Lookup/enter by device number.
                     53:  */
                     54: #define        NDEVHASH        8
                     55: #define        DEV_NUMBER_HASH(dev)    ((dev) & (NDEVHASH-1))
                     56: queue_head_t   dev_number_hash_table[NDEVHASH];
                     57: 
                     58: /*
                     59:  * Lock for device-number to device lookup.
                     60:  * Must be held before device-ref_count lock.
                     61:  */
                     62: decl_simple_lock_data(,
                     63:                dev_number_lock)
                     64: 
1.1.1.2 ! root       65: struct kmem_cache      dev_hdr_cache;
1.1       root       66: 
                     67: /*
                     68:  * Enter device in the number lookup table.
                     69:  * The number table lock must be held.
                     70:  */
                     71: void
                     72: dev_number_enter(device)
1.1.1.2 ! root       73:        mach_device_t   device;
1.1       root       74: {
1.1.1.2 ! root       75:        queue_t q;
1.1       root       76: 
                     77:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     78:        queue_enter(q, device, mach_device_t, number_chain);
                     79: }
                     80: 
                     81: /*
                     82:  * Remove device from the device-number lookup table.
                     83:  * The device-number table lock must be held.
                     84:  */
                     85: void
                     86: dev_number_remove(device)
1.1.1.2 ! root       87:        mach_device_t   device;
1.1       root       88: {
1.1.1.2 ! root       89:        queue_t q;
1.1       root       90: 
                     91:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     92:        queue_remove(q, device, mach_device_t, number_chain);
                     93: }
                     94: 
                     95: /*
                     96:  * Lookup a device by device operations and minor number.
                     97:  * The number table lock must be held.
                     98:  */
                     99: mach_device_t
                    100: dev_number_lookup(ops, devnum)
                    101:        dev_ops_t       ops;
                    102:        int             devnum;
                    103: {
1.1.1.2 ! root      104:        queue_t q;
        !           105:        mach_device_t   device;
1.1       root      106: 
                    107:        q = &dev_number_hash_table[DEV_NUMBER_HASH(devnum)];
                    108:        queue_iterate(q, device, mach_device_t, number_chain) {
                    109:            if (device->dev_ops == ops && device->dev_number == devnum) {
                    110:                return (device);
                    111:            }
                    112:        }
                    113:        return (MACH_DEVICE_NULL);
                    114: }
                    115: 
                    116: /*
                    117:  * Look up a device by name, and create the device structure
                    118:  * if it does not exist.  Enter it in the dev_number lookup
                    119:  * table.
                    120:  */
                    121: mach_device_t
                    122: device_lookup(name)
                    123:        char *          name;
                    124: {
                    125:        dev_ops_t       dev_ops;
                    126:        int             dev_minor;
1.1.1.2 ! root      127:        mach_device_t   device;
        !           128:        mach_device_t   new_device;
1.1       root      129: 
                    130:        /*
                    131:         * Get the device and unit number from the name.
                    132:         */
                    133:        if (!dev_name_lookup(name, &dev_ops, &dev_minor))
                    134:            return (MACH_DEVICE_NULL);
                    135: 
                    136:        /*
                    137:         * Look up the device in the hash table.  If it is
                    138:         * not there, enter it.
                    139:         */
                    140:        new_device = MACH_DEVICE_NULL;
                    141:        simple_lock(&dev_number_lock);
                    142:        while ((device = dev_number_lookup(dev_ops, dev_minor))
                    143:                == MACH_DEVICE_NULL) {
                    144:            /*
                    145:             * Must unlock to allocate the structure.  If
                    146:             * the structure has appeared after we have allocated,
                    147:             * release the new structure.
                    148:             */
                    149:            if (new_device != MACH_DEVICE_NULL)
                    150:                break;  /* allocated */
                    151: 
                    152:            simple_unlock(&dev_number_lock);
                    153: 
1.1.1.2 ! root      154:            new_device = (mach_device_t) kmem_cache_alloc(&dev_hdr_cache);
1.1       root      155:            simple_lock_init(&new_device->ref_lock);
                    156:            new_device->ref_count = 1;
                    157:            simple_lock_init(&new_device->lock);
                    158:            new_device->state = DEV_STATE_INIT;
                    159:            new_device->flag = 0;
                    160:            new_device->open_count = 0;
                    161:            new_device->io_in_progress = 0;
                    162:            new_device->io_wait = FALSE;
                    163:            new_device->port = IP_NULL;
                    164:            new_device->dev_ops = dev_ops;
                    165:            new_device->dev_number = dev_minor;
                    166:            new_device->bsize = DEV_BSIZE;      /* change later */
                    167: 
                    168:            simple_lock(&dev_number_lock);
                    169:        }
                    170: 
                    171:        if (device == MACH_DEVICE_NULL) {
                    172:            /*
                    173:             * No existing device structure.  Insert the
                    174:             * new one.
                    175:             */
                    176:            assert(new_device != MACH_DEVICE_NULL);
                    177:            device = new_device;
                    178: 
                    179:            dev_number_enter(device);
                    180:            simple_unlock(&dev_number_lock);
                    181:        }
                    182:        else {
                    183:            /*
                    184:             * Have existing device.
                    185:             */
                    186:            mach_device_reference(device);
                    187:            simple_unlock(&dev_number_lock);
                    188: 
                    189:            if (new_device != MACH_DEVICE_NULL)
1.1.1.2 ! root      190:                kmem_cache_free(&dev_hdr_cache, (vm_offset_t)new_device);
1.1       root      191:        }
                    192: 
                    193:        return (device);
                    194: }
                    195: 
                    196: /*
                    197:  * Add a reference to the device.
                    198:  */
                    199: void
                    200: mach_device_reference(device)
1.1.1.2 ! root      201:        mach_device_t   device;
1.1       root      202: {
                    203:        simple_lock(&device->ref_lock);
                    204:        device->ref_count++;
                    205:        simple_unlock(&device->ref_lock);
                    206: }
                    207: 
                    208: /*
                    209:  * Remove a reference to the device, and deallocate the
                    210:  * structure if no references are left.
                    211:  */
                    212: void
                    213: mach_device_deallocate(device)
1.1.1.2 ! root      214:        mach_device_t   device;
1.1       root      215: {
                    216:        simple_lock(&device->ref_lock);
                    217:        if (--device->ref_count > 0) {
                    218:            simple_unlock(&device->ref_lock);
                    219:            return;
                    220:        }
                    221:        device->ref_count = 1;
                    222:        simple_unlock(&device->ref_lock);
                    223: 
                    224:        simple_lock(&dev_number_lock);
                    225:        simple_lock(&device->ref_lock);
                    226:        if (--device->ref_count > 0) {
                    227:            simple_unlock(&device->ref_lock);
                    228:            simple_unlock(&dev_number_lock);
                    229:            return;
                    230:        }
                    231: 
                    232:        dev_number_remove(device);
                    233:        simple_unlock(&device->ref_lock);
                    234:        simple_unlock(&dev_number_lock);
                    235: 
1.1.1.2 ! root      236:        kmem_cache_free(&dev_hdr_cache, (vm_offset_t)device);
1.1       root      237: }
                    238: 
                    239: /*
                    240: 
                    241:  */
                    242: /*
                    243:  * port-to-device lookup routines.
                    244:  */
                    245: decl_simple_lock_data(,
                    246:        dev_port_lock)
                    247: 
                    248: /*
                    249:  * Enter a port-to-device mapping.
                    250:  */
                    251: void
                    252: dev_port_enter(device)
1.1.1.2 ! root      253:        mach_device_t   device;
1.1       root      254: {
                    255:        mach_device_reference(device);
1.1.1.2 ! root      256: 
1.1       root      257:        ipc_kobject_set(device->port,
                    258:                        (ipc_kobject_t) &device->dev, IKOT_DEVICE);
                    259:        device->dev.emul_data = device;
                    260:        {
                    261:          extern struct device_emulation_ops mach_device_emulation_ops;
                    262: 
                    263:          device->dev.emul_ops = &mach_device_emulation_ops;
                    264:        }
                    265: }
                    266: 
                    267: /*
                    268:  * Remove a port-to-device mapping.
                    269:  */
                    270: void
                    271: dev_port_remove(device)
1.1.1.2 ! root      272:        mach_device_t   device;
1.1       root      273: {
                    274:        ipc_kobject_set(device->port, IKO_NULL, IKOT_NONE);
                    275:        mach_device_deallocate(device);
                    276: }
                    277: 
                    278: /*
                    279:  * Lookup a device by its port.
                    280:  * Doesn't consume the naked send right; produces a device reference.
                    281:  */
                    282: device_t
                    283: dev_port_lookup(port)
                    284:        ipc_port_t      port;
                    285: {
1.1.1.2 ! root      286:        device_t        device;
1.1       root      287: 
                    288:        if (!IP_VALID(port))
                    289:            return (DEVICE_NULL);
                    290: 
                    291:        ip_lock(port);
                    292:        if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
                    293:            device = (device_t) port->ip_kobject;
                    294:            if (device->emul_ops->reference)
                    295:              (*device->emul_ops->reference)(device->emul_data);
                    296:        }
                    297:        else
                    298:            device = DEVICE_NULL;
                    299: 
                    300:        ip_unlock(port);
                    301:        return (device);
                    302: }
                    303: 
                    304: /*
                    305:  * Get the port for a device.
                    306:  * Consumes a device reference; produces a naked send right.
                    307:  */
                    308: ipc_port_t
                    309: convert_device_to_port(device)
1.1.1.2 ! root      310:        device_t        device;
1.1       root      311: {
                    312:        if (device == DEVICE_NULL)
                    313:            return IP_NULL;
                    314: 
                    315:        return (*device->emul_ops->dev_to_port) (device->emul_data);
                    316: }
                    317: 
                    318: /*
                    319:  * Call a supplied routine on each device, passing it
                    320:  * the port as an argument.  If the routine returns TRUE,
                    321:  * stop the search and return TRUE.  If none returns TRUE,
                    322:  * return FALSE.
                    323:  */
                    324: boolean_t
                    325: dev_map(routine, port)
                    326:        boolean_t       (*routine)();
                    327:        mach_port_t     port;
                    328: {
1.1.1.2 ! root      329:        int             i;
        !           330:        queue_t         q;
        !           331:        mach_device_t   dev, prev_dev;
1.1       root      332: 
                    333:        for (i = 0, q = &dev_number_hash_table[0];
                    334:             i < NDEVHASH;
                    335:             i++, q++) {
                    336:            prev_dev = MACH_DEVICE_NULL;
                    337:            simple_lock(&dev_number_lock);
                    338:            queue_iterate(q, dev, mach_device_t, number_chain) {
                    339:                mach_device_reference(dev);
                    340:                simple_unlock(&dev_number_lock);
                    341:                if (prev_dev != MACH_DEVICE_NULL)
                    342:                    mach_device_deallocate(prev_dev);
                    343: 
                    344:                if ((*routine)(dev, port)) {
                    345:                    /*
                    346:                     * Done
                    347:                     */
                    348:                    mach_device_deallocate(dev);
                    349:                    return (TRUE);
                    350:                }
                    351: 
                    352:                simple_lock(&dev_number_lock);
                    353:                prev_dev = dev;
                    354:            }
                    355:            simple_unlock(&dev_number_lock);
                    356:            if (prev_dev != MACH_DEVICE_NULL)
                    357:                mach_device_deallocate(prev_dev);
                    358:        }
                    359:        return (FALSE);
                    360: }
                    361: 
                    362: /*
                    363:  * Initialization
                    364:  */
                    365: void
                    366: dev_lookup_init()
                    367: {
1.1.1.2 ! root      368:        int     i;
1.1       root      369: 
                    370:        simple_lock_init(&dev_number_lock);
                    371: 
                    372:        for (i = 0; i < NDEVHASH; i++)
                    373:            queue_init(&dev_number_hash_table[i]);
                    374: 
                    375:        simple_lock_init(&dev_port_lock);
                    376: 
1.1.1.2 ! root      377:        kmem_cache_init(&dev_hdr_cache, "mach_device",
        !           378:                        sizeof(struct mach_device), 0, NULL, NULL, NULL, 0);
1.1       root      379: }

unix.superglobalmegacorp.com

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