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

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>
                     35: #include <kern/zalloc.h>
                     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: 
                     45: #ifdef i386
                     46: #include <i386at/device_emul.h>
                     47: #endif
                     48: 
                     49: /*
                     50:  * Device structure routines: reference counting, port->device.
                     51:  */
                     52: 
                     53: /*
                     54:  * Lookup/enter by device number.
                     55:  */
                     56: #define        NDEVHASH        8
                     57: #define        DEV_NUMBER_HASH(dev)    ((dev) & (NDEVHASH-1))
                     58: queue_head_t   dev_number_hash_table[NDEVHASH];
                     59: 
                     60: /*
                     61:  * Lock for device-number to device lookup.
                     62:  * Must be held before device-ref_count lock.
                     63:  */
                     64: decl_simple_lock_data(,
                     65:                dev_number_lock)
                     66: 
                     67: zone_t         dev_hdr_zone;
                     68: 
                     69: /*
                     70:  * Enter device in the number lookup table.
                     71:  * The number table lock must be held.
                     72:  */
                     73: void
                     74: dev_number_enter(device)
                     75:        register mach_device_t  device;
                     76: {
                     77:        register queue_t        q;
                     78: 
                     79:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     80:        queue_enter(q, device, mach_device_t, number_chain);
                     81: }
                     82: 
                     83: /*
                     84:  * Remove device from the device-number lookup table.
                     85:  * The device-number table lock must be held.
                     86:  */
                     87: void
                     88: dev_number_remove(device)
                     89:        register mach_device_t  device;
                     90: {
                     91:        register queue_t        q;
                     92: 
                     93:        q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
                     94:        queue_remove(q, device, mach_device_t, number_chain);
                     95: }
                     96: 
                     97: /*
                     98:  * Lookup a device by device operations and minor number.
                     99:  * The number table lock must be held.
                    100:  */
                    101: mach_device_t
                    102: dev_number_lookup(ops, devnum)
                    103:        dev_ops_t       ops;
                    104:        int             devnum;
                    105: {
                    106:        register queue_t        q;
                    107:        register mach_device_t  device;
                    108: 
                    109:        q = &dev_number_hash_table[DEV_NUMBER_HASH(devnum)];
                    110:        queue_iterate(q, device, mach_device_t, number_chain) {
                    111:            if (device->dev_ops == ops && device->dev_number == devnum) {
                    112:                return (device);
                    113:            }
                    114:        }
                    115:        return (MACH_DEVICE_NULL);
                    116: }
                    117: 
                    118: /*
                    119:  * Look up a device by name, and create the device structure
                    120:  * if it does not exist.  Enter it in the dev_number lookup
                    121:  * table.
                    122:  */
                    123: mach_device_t
                    124: device_lookup(name)
                    125:        char *          name;
                    126: {
                    127:        dev_ops_t       dev_ops;
                    128:        int             dev_minor;
                    129:        register mach_device_t  device;
                    130:        register mach_device_t  new_device;
                    131: 
                    132:        /*
                    133:         * Get the device and unit number from the name.
                    134:         */
                    135:        if (!dev_name_lookup(name, &dev_ops, &dev_minor))
                    136:            return (MACH_DEVICE_NULL);
                    137: 
                    138:        /*
                    139:         * Look up the device in the hash table.  If it is
                    140:         * not there, enter it.
                    141:         */
                    142:        new_device = MACH_DEVICE_NULL;
                    143:        simple_lock(&dev_number_lock);
                    144:        while ((device = dev_number_lookup(dev_ops, dev_minor))
                    145:                == MACH_DEVICE_NULL) {
                    146:            /*
                    147:             * Must unlock to allocate the structure.  If
                    148:             * the structure has appeared after we have allocated,
                    149:             * release the new structure.
                    150:             */
                    151:            if (new_device != MACH_DEVICE_NULL)
                    152:                break;  /* allocated */
                    153: 
                    154:            simple_unlock(&dev_number_lock);
                    155: 
                    156:            new_device = (mach_device_t) zalloc(dev_hdr_zone);
                    157:            simple_lock_init(&new_device->ref_lock);
                    158:            new_device->ref_count = 1;
                    159:            simple_lock_init(&new_device->lock);
                    160:            new_device->state = DEV_STATE_INIT;
                    161:            new_device->flag = 0;
                    162:            new_device->open_count = 0;
                    163:            new_device->io_in_progress = 0;
                    164:            new_device->io_wait = FALSE;
                    165:            new_device->port = IP_NULL;
                    166:            new_device->dev_ops = dev_ops;
                    167:            new_device->dev_number = dev_minor;
                    168:            new_device->bsize = DEV_BSIZE;      /* change later */
                    169: 
                    170:            simple_lock(&dev_number_lock);
                    171:        }
                    172: 
                    173:        if (device == MACH_DEVICE_NULL) {
                    174:            /*
                    175:             * No existing device structure.  Insert the
                    176:             * new one.
                    177:             */
                    178:            assert(new_device != MACH_DEVICE_NULL);
                    179:            device = new_device;
                    180: 
                    181:            dev_number_enter(device);
                    182:            simple_unlock(&dev_number_lock);
                    183:        }
                    184:        else {
                    185:            /*
                    186:             * Have existing device.
                    187:             */
                    188:            mach_device_reference(device);
                    189:            simple_unlock(&dev_number_lock);
                    190: 
                    191:            if (new_device != MACH_DEVICE_NULL)
                    192:                zfree(dev_hdr_zone, (vm_offset_t)new_device);
                    193:        }
                    194: 
                    195:        return (device);
                    196: }
                    197: 
                    198: /*
                    199:  * Add a reference to the device.
                    200:  */
                    201: void
                    202: mach_device_reference(device)
                    203:        register mach_device_t  device;
                    204: {
                    205:        simple_lock(&device->ref_lock);
                    206:        device->ref_count++;
                    207:        simple_unlock(&device->ref_lock);
                    208: }
                    209: 
                    210: /*
                    211:  * Remove a reference to the device, and deallocate the
                    212:  * structure if no references are left.
                    213:  */
                    214: void
                    215: mach_device_deallocate(device)
                    216:        register mach_device_t  device;
                    217: {
                    218:        simple_lock(&device->ref_lock);
                    219:        if (--device->ref_count > 0) {
                    220:            simple_unlock(&device->ref_lock);
                    221:            return;
                    222:        }
                    223:        device->ref_count = 1;
                    224:        simple_unlock(&device->ref_lock);
                    225: 
                    226:        simple_lock(&dev_number_lock);
                    227:        simple_lock(&device->ref_lock);
                    228:        if (--device->ref_count > 0) {
                    229:            simple_unlock(&device->ref_lock);
                    230:            simple_unlock(&dev_number_lock);
                    231:            return;
                    232:        }
                    233: 
                    234:        dev_number_remove(device);
                    235:        simple_unlock(&device->ref_lock);
                    236:        simple_unlock(&dev_number_lock);
                    237: 
                    238:        zfree(dev_hdr_zone, (vm_offset_t)device);
                    239: }
                    240: 
                    241: /*
                    242: 
                    243:  */
                    244: /*
                    245:  * port-to-device lookup routines.
                    246:  */
                    247: decl_simple_lock_data(,
                    248:        dev_port_lock)
                    249: 
                    250: /*
                    251:  * Enter a port-to-device mapping.
                    252:  */
                    253: void
                    254: dev_port_enter(device)
                    255:        register mach_device_t  device;
                    256: {
                    257:        mach_device_reference(device);
                    258: #ifdef i386
                    259:        ipc_kobject_set(device->port,
                    260:                        (ipc_kobject_t) &device->dev, IKOT_DEVICE);
                    261:        device->dev.emul_data = device;
                    262:        {
                    263:          extern struct device_emulation_ops mach_device_emulation_ops;
                    264: 
                    265:          device->dev.emul_ops = &mach_device_emulation_ops;
                    266:        }
                    267: #else
                    268:        ipc_kobject_set(device->port, (ipc_kobject_t) device, IKOT_DEVICE);
                    269: #endif
                    270: }
                    271: 
                    272: /*
                    273:  * Remove a port-to-device mapping.
                    274:  */
                    275: void
                    276: dev_port_remove(device)
                    277:        register mach_device_t  device;
                    278: {
                    279:        ipc_kobject_set(device->port, IKO_NULL, IKOT_NONE);
                    280:        mach_device_deallocate(device);
                    281: }
                    282: 
                    283: /*
                    284:  * Lookup a device by its port.
                    285:  * Doesn't consume the naked send right; produces a device reference.
                    286:  */
                    287: device_t
                    288: dev_port_lookup(port)
                    289:        ipc_port_t      port;
                    290: {
                    291:        register device_t       device;
                    292: 
                    293:        if (!IP_VALID(port))
                    294:            return (DEVICE_NULL);
                    295: 
                    296:        ip_lock(port);
                    297:        if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
                    298:            device = (device_t) port->ip_kobject;
                    299: #ifdef i386
                    300:            if (device->emul_ops->reference)
                    301:              (*device->emul_ops->reference)(device->emul_data);
                    302: #else
                    303:            mach_device_reference(device);
                    304: #endif
                    305:        }
                    306:        else
                    307:            device = DEVICE_NULL;
                    308: 
                    309:        ip_unlock(port);
                    310:        return (device);
                    311: }
                    312: 
                    313: /*
                    314:  * Get the port for a device.
                    315:  * Consumes a device reference; produces a naked send right.
                    316:  */
                    317: ipc_port_t
                    318: convert_device_to_port(device)
                    319:        register device_t       device;
                    320: {
                    321: #ifndef i386
                    322:        register ipc_port_t     port;
                    323: #endif
                    324: 
                    325:        if (device == DEVICE_NULL)
                    326:            return IP_NULL;
                    327: 
                    328: #ifdef i386
                    329:        return (*device->emul_ops->dev_to_port) (device->emul_data);
                    330: #else
                    331:        device_lock(device);
                    332:        if (device->state == DEV_STATE_OPEN)
                    333:            port = ipc_port_make_send(device->port);
                    334:        else
                    335:            port = IP_NULL;
                    336:        device_unlock(device);
                    337: 
                    338:        mach_device_deallocate(device);
                    339:        return port;
                    340: #endif
                    341: }
                    342: 
                    343: /*
                    344:  * Call a supplied routine on each device, passing it
                    345:  * the port as an argument.  If the routine returns TRUE,
                    346:  * stop the search and return TRUE.  If none returns TRUE,
                    347:  * return FALSE.
                    348:  */
                    349: boolean_t
                    350: dev_map(routine, port)
                    351:        boolean_t       (*routine)();
                    352:        mach_port_t     port;
                    353: {
                    354:        register int            i;
                    355:        register queue_t        q;
                    356:        register mach_device_t  dev, prev_dev;
                    357: 
                    358:        for (i = 0, q = &dev_number_hash_table[0];
                    359:             i < NDEVHASH;
                    360:             i++, q++) {
                    361:            prev_dev = MACH_DEVICE_NULL;
                    362:            simple_lock(&dev_number_lock);
                    363:            queue_iterate(q, dev, mach_device_t, number_chain) {
                    364:                mach_device_reference(dev);
                    365:                simple_unlock(&dev_number_lock);
                    366:                if (prev_dev != MACH_DEVICE_NULL)
                    367:                    mach_device_deallocate(prev_dev);
                    368: 
                    369:                if ((*routine)(dev, port)) {
                    370:                    /*
                    371:                     * Done
                    372:                     */
                    373:                    mach_device_deallocate(dev);
                    374:                    return (TRUE);
                    375:                }
                    376: 
                    377:                simple_lock(&dev_number_lock);
                    378:                prev_dev = dev;
                    379:            }
                    380:            simple_unlock(&dev_number_lock);
                    381:            if (prev_dev != MACH_DEVICE_NULL)
                    382:                mach_device_deallocate(prev_dev);
                    383:        }
                    384:        return (FALSE);
                    385: }
                    386: 
                    387: /*
                    388:  * Initialization
                    389:  */
                    390: #define        NDEVICES        256
                    391: 
                    392: void
                    393: dev_lookup_init()
                    394: {
                    395:        register int    i;
                    396: 
                    397:        simple_lock_init(&dev_number_lock);
                    398: 
                    399:        for (i = 0; i < NDEVHASH; i++)
                    400:            queue_init(&dev_number_hash_table[i]);
                    401: 
                    402:        simple_lock_init(&dev_port_lock);
                    403: 
                    404:        dev_hdr_zone = zinit(sizeof(struct mach_device),
                    405:                             sizeof(struct mach_device) * NDEVICES,
                    406:                             PAGE_SIZE,
                    407:                             FALSE,
                    408:                             "open device entry");
                    409: }

unix.superglobalmegacorp.com

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