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

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.1.3   root       46: #include <device/ds_routines.h>
1.1       root       47: 
                     48: /*
                     49:  * Device structure routines: reference counting, port->device.
                     50:  */
                     51: 
                     52: /*
                     53:  * Lookup/enter by device number.
                     54:  */
                     55: #define        NDEVHASH        8
                     56: #define        DEV_NUMBER_HASH(dev)    ((dev) & (NDEVHASH-1))
                     57: queue_head_t   dev_number_hash_table[NDEVHASH];
                     58: 
                     59: /*
                     60:  * Lock for device-number to device lookup.
                     61:  * Must be held before device-ref_count lock.
                     62:  */
                     63: decl_simple_lock_data(,
                     64:                dev_number_lock)
                     65: 
1.1.1.2   root       66: struct kmem_cache      dev_hdr_cache;
1.1       root       67: 
                     68: /*
                     69:  * Enter device in the number lookup table.
                     70:  * The number table lock must be held.
                     71:  */
                     72: void
                     73: dev_number_enter(device)
1.1.1.3   root       74:        const mach_device_t     device;
1.1       root       75: {
1.1.1.2   root       76:        queue_t q;
1.1       root       77: 
                     78:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     79:        queue_enter(q, device, mach_device_t, number_chain);
                     80: }
                     81: 
                     82: /*
                     83:  * Remove device from the device-number lookup table.
                     84:  * The device-number table lock must be held.
                     85:  */
                     86: void
                     87: dev_number_remove(device)
1.1.1.3   root       88:        const mach_device_t     device;
1.1       root       89: {
1.1.1.2   root       90:        queue_t q;
1.1       root       91: 
                     92:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     93:        queue_remove(q, device, mach_device_t, number_chain);
                     94: }
                     95: 
                     96: /*
                     97:  * Lookup a device by device operations and minor number.
                     98:  * The number table lock must be held.
                     99:  */
                    100: mach_device_t
                    101: dev_number_lookup(ops, devnum)
1.1.1.3   root      102:        const dev_ops_t ops;
1.1       root      103:        int             devnum;
                    104: {
1.1.1.2   root      105:        queue_t q;
                    106:        mach_device_t   device;
1.1       root      107: 
                    108:        q = &dev_number_hash_table[DEV_NUMBER_HASH(devnum)];
                    109:        queue_iterate(q, device, mach_device_t, number_chain) {
                    110:            if (device->dev_ops == ops && device->dev_number == devnum) {
                    111:                return (device);
                    112:            }
                    113:        }
                    114:        return (MACH_DEVICE_NULL);
                    115: }
                    116: 
                    117: /*
                    118:  * Look up a device by name, and create the device structure
                    119:  * if it does not exist.  Enter it in the dev_number lookup
                    120:  * table.
                    121:  */
                    122: mach_device_t
1.1.1.3   root      123: device_lookup(char *name)
1.1       root      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
1.1.1.3   root      200: mach_device_reference(mach_device_t device)
1.1       root      201: {
                    202:        simple_lock(&device->ref_lock);
                    203:        device->ref_count++;
                    204:        simple_unlock(&device->ref_lock);
                    205: }
                    206: 
                    207: /*
                    208:  * Remove a reference to the device, and deallocate the
                    209:  * structure if no references are left.
                    210:  */
                    211: void
1.1.1.3   root      212: mach_device_deallocate(mach_device_t device)
1.1       root      213: {
                    214:        simple_lock(&device->ref_lock);
                    215:        if (--device->ref_count > 0) {
                    216:            simple_unlock(&device->ref_lock);
                    217:            return;
                    218:        }
                    219:        device->ref_count = 1;
                    220:        simple_unlock(&device->ref_lock);
                    221: 
                    222:        simple_lock(&dev_number_lock);
                    223:        simple_lock(&device->ref_lock);
                    224:        if (--device->ref_count > 0) {
                    225:            simple_unlock(&device->ref_lock);
                    226:            simple_unlock(&dev_number_lock);
                    227:            return;
                    228:        }
                    229: 
                    230:        dev_number_remove(device);
                    231:        simple_unlock(&device->ref_lock);
                    232:        simple_unlock(&dev_number_lock);
                    233: 
1.1.1.2   root      234:        kmem_cache_free(&dev_hdr_cache, (vm_offset_t)device);
1.1       root      235: }
                    236: 
                    237: /*
                    238: 
                    239:  */
                    240: /*
                    241:  * port-to-device lookup routines.
                    242:  */
                    243: 
                    244: /*
                    245:  * Enter a port-to-device mapping.
                    246:  */
                    247: void
1.1.1.3   root      248: dev_port_enter(mach_device_t device)
1.1       root      249: {
                    250:        mach_device_reference(device);
1.1.1.2   root      251: 
1.1       root      252:        ipc_kobject_set(device->port,
                    253:                        (ipc_kobject_t) &device->dev, IKOT_DEVICE);
                    254:        device->dev.emul_data = device;
                    255:        {
                    256:          extern struct device_emulation_ops mach_device_emulation_ops;
                    257: 
                    258:          device->dev.emul_ops = &mach_device_emulation_ops;
                    259:        }
                    260: }
                    261: 
                    262: /*
                    263:  * Remove a port-to-device mapping.
                    264:  */
                    265: void
1.1.1.3   root      266: dev_port_remove(mach_device_t device)
1.1       root      267: {
                    268:        ipc_kobject_set(device->port, IKO_NULL, IKOT_NONE);
                    269:        mach_device_deallocate(device);
                    270: }
                    271: 
                    272: /*
                    273:  * Lookup a device by its port.
                    274:  * Doesn't consume the naked send right; produces a device reference.
                    275:  */
                    276: device_t
1.1.1.3   root      277: dev_port_lookup(ipc_port_t port)
1.1       root      278: {
1.1.1.2   root      279:        device_t        device;
1.1       root      280: 
                    281:        if (!IP_VALID(port))
                    282:            return (DEVICE_NULL);
                    283: 
                    284:        ip_lock(port);
                    285:        if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
                    286:            device = (device_t) port->ip_kobject;
                    287:            if (device->emul_ops->reference)
                    288:              (*device->emul_ops->reference)(device->emul_data);
                    289:        }
                    290:        else
                    291:            device = DEVICE_NULL;
                    292: 
                    293:        ip_unlock(port);
                    294:        return (device);
                    295: }
                    296: 
                    297: /*
                    298:  * Get the port for a device.
                    299:  * Consumes a device reference; produces a naked send right.
                    300:  */
                    301: ipc_port_t
                    302: convert_device_to_port(device)
1.1.1.3   root      303:        const device_t  device;
1.1       root      304: {
                    305:        if (device == DEVICE_NULL)
                    306:            return IP_NULL;
                    307: 
                    308:        return (*device->emul_ops->dev_to_port) (device->emul_data);
                    309: }
                    310: 
                    311: /*
                    312:  * Call a supplied routine on each device, passing it
                    313:  * the port as an argument.  If the routine returns TRUE,
                    314:  * stop the search and return TRUE.  If none returns TRUE,
                    315:  * return FALSE.
                    316:  */
                    317: boolean_t
1.1.1.3   root      318: dev_map(
                    319:        boolean_t       (*routine)(),
                    320:        mach_port_t     port)
1.1       root      321: {
1.1.1.2   root      322:        int             i;
                    323:        queue_t         q;
                    324:        mach_device_t   dev, prev_dev;
1.1       root      325: 
                    326:        for (i = 0, q = &dev_number_hash_table[0];
                    327:             i < NDEVHASH;
                    328:             i++, q++) {
                    329:            prev_dev = MACH_DEVICE_NULL;
                    330:            simple_lock(&dev_number_lock);
                    331:            queue_iterate(q, dev, mach_device_t, number_chain) {
                    332:                mach_device_reference(dev);
                    333:                simple_unlock(&dev_number_lock);
                    334:                if (prev_dev != MACH_DEVICE_NULL)
                    335:                    mach_device_deallocate(prev_dev);
                    336: 
                    337:                if ((*routine)(dev, port)) {
                    338:                    /*
                    339:                     * Done
                    340:                     */
                    341:                    mach_device_deallocate(dev);
                    342:                    return (TRUE);
                    343:                }
                    344: 
                    345:                simple_lock(&dev_number_lock);
                    346:                prev_dev = dev;
                    347:            }
                    348:            simple_unlock(&dev_number_lock);
                    349:            if (prev_dev != MACH_DEVICE_NULL)
                    350:                mach_device_deallocate(prev_dev);
                    351:        }
                    352:        return (FALSE);
                    353: }
                    354: 
                    355: /*
                    356:  * Initialization
                    357:  */
                    358: void
1.1.1.3   root      359: dev_lookup_init(void)
1.1       root      360: {
1.1.1.2   root      361:        int     i;
1.1       root      362: 
                    363:        simple_lock_init(&dev_number_lock);
                    364: 
                    365:        for (i = 0; i < NDEVHASH; i++)
                    366:            queue_init(&dev_number_hash_table[i]);
                    367: 
1.1.1.2   root      368:        kmem_cache_init(&dev_hdr_cache, "mach_device",
1.1.1.4 ! root      369:                        sizeof(struct mach_device), 0, NULL, 0);
1.1       root      370: }

unix.superglobalmegacorp.com

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