Annotation of Gnu-Mach/device/dev_lookup.c, revision 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.