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

1.1.1.2 ! root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2 ! root        5:  *
1.1       root        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.
1.1.1.2 ! root       11:  *
1.1       root       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.
1.1.1.2 ! root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2 ! root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2 ! root       22:  *
1.1       root       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 <norma_device.h>
                     32: 
                     33: #include <mach/boolean.h>
                     34: #include <mach/kern_return.h>
                     35: #include <mach/mig_errors.h>
                     36: #include <mach/port.h>
                     37: #include <mach/vm_param.h>
                     38: #include <mach/notify.h>
                     39: #include <machine/machspl.h>           /* spl definitions */
                     40: 
                     41: #include <ipc/ipc_port.h>
                     42: #include <ipc/ipc_space.h>
                     43: 
                     44: #include <kern/ast.h>
                     45: #include <kern/counters.h>
                     46: #include <kern/queue.h>
                     47: #include <kern/zalloc.h>
                     48: #include <kern/thread.h>
                     49: #include <kern/task.h>
                     50: #include <kern/sched_prim.h>
                     51: 
                     52: #include <vm/memory_object.h>
                     53: #include <vm/vm_map.h>
                     54: #include <vm/vm_kern.h>
                     55: 
                     56: #include <device/device_types.h>
                     57: #include <device/dev_hdr.h>
                     58: #include <device/conf.h>
                     59: #include <device/io_req.h>
                     60: #include <device/ds_routines.h>
                     61: #include <device/net_status.h>
                     62: #include <device/device_port.h>
                     63: #include "device_reply.h"
                     64: 
                     65: #include <machine/machspl.h>
                     66: 
                     67: #ifdef i386
                     68: #include <i386at/device_emul.h>
1.1.1.2 ! root       69: #ifdef LINUX_DEV
        !            70: #include <i386/linux/device-drivers.h>
        !            71: #endif
1.1       root       72: #endif
                     73: 
                     74: #ifdef i386
                     75: ipc_port_t
                     76: mach_convert_device_to_port (void *d)
                     77: {
                     78:   ipc_port_t port;
                     79:   mach_device_t device = d;
                     80: 
                     81:   if (! device)
                     82:     return IP_NULL;
                     83:   device_lock(device);
                     84:   if (device->state == DEV_STATE_OPEN)
                     85:     port = ipc_port_make_send(device->port);
                     86:   else
                     87:     port = IP_NULL;
                     88:   device_unlock(device);
                     89:   mach_device_deallocate(device);
                     90:   return port;
                     91: }
                     92: #endif /* i386 */
                     93: 
                     94: #ifdef i386
                     95: static io_return_t
                     96: device_open(reply_port, reply_port_type, mode, name, device_p)
                     97: #else
                     98: io_return_t
                     99: ds_device_open(open_port, reply_port, reply_port_type,
                    100:               mode, name, device_p)
                    101:        ipc_port_t      open_port;
                    102: #endif
                    103:        ipc_port_t      reply_port;
                    104:        mach_msg_type_name_t reply_port_type;
                    105:        dev_mode_t      mode;
                    106:        char *          name;
                    107:        device_t        *device_p;      /* out */
                    108: {
                    109:        register mach_device_t  device;
                    110:        register kern_return_t  result;
                    111:        register io_req_t       ior;
                    112:        char                    namebuf[64];
                    113:        ipc_port_t              notify;
                    114: 
                    115: #ifndef i386
                    116:        /*
                    117:         * Open must be called on the master device port.
                    118:         */
                    119:        if (open_port != master_device_port)
                    120:            return (D_INVALID_OPERATION);
                    121: 
                    122:        /*
                    123:         * There must be a reply port.
                    124:         */
                    125:        if (!IP_VALID(reply_port)) {
                    126:            printf("ds_* invalid reply port\n");
                    127:            Debugger("ds_* reply_port");
                    128:            return (MIG_NO_REPLY);      /* no sense in doing anything */
                    129:        }
                    130: 
                    131: #if    NORMA_DEVICE
                    132:        /*
                    133:         * Map global device name to <node> + local device name.
                    134:         */
                    135:        if (name[0] != '<') {
                    136:                extern char *dev_forward_name();
                    137: 
                    138:                name = dev_forward_name(name, namebuf, sizeof(namebuf));
                    139:        }
                    140:        /*
                    141:         * Look for explicit node specifier, e.g., <2>sd0a.
                    142:         * If found, then forward request to correct device server.
                    143:         * If not found, then remove '<n>' and process locally.
                    144:         *
                    145:         * XXX should handle send-right reply_port as well as send-once XXX
                    146:         */
                    147:        if (name[0] == '<') {
                    148:                char *n;
                    149:                int node = 0;
                    150: 
                    151:                for (n = &name[1]; *n != '>'; n++) {
                    152:                        if (*n >= '0' && *n <= '9') {
                    153:                                node = 10 * node + (*n - '0');
                    154:                        } else {
                    155:                                return (D_NO_SUCH_DEVICE);
                    156:                        }
                    157:                }
                    158:                if (node == node_self()) {
                    159:                        name = &n[1];   /* skip trailing '>' */
                    160:                } else {
                    161:                        forward_device_open_send(remote_device(node),
                    162:                                                 reply_port, mode, name);
                    163:                        return (MIG_NO_REPLY);
                    164:                }
                    165:        }
                    166: #endif NORMA_DEVICE
                    167: #endif /* ! i386 */
                    168: 
                    169:        /*
                    170:         * Find the device.
                    171:         */
                    172:        device = device_lookup(name);
                    173:        if (device == MACH_DEVICE_NULL)
                    174:            return (D_NO_SUCH_DEVICE);
                    175: 
                    176:        /*
                    177:         * If the device is being opened or closed,
                    178:         * wait for that operation to finish.
                    179:         */
                    180:        device_lock(device);
                    181:        while (device->state == DEV_STATE_OPENING ||
                    182:                device->state == DEV_STATE_CLOSING) {
                    183:            device->io_wait = TRUE;
                    184:            thread_sleep((event_t)device, simple_lock_addr(device->lock), TRUE);
                    185:            device_lock(device);
                    186:        }
                    187: 
                    188:        /*
                    189:         * If the device is already open, increment the open count
                    190:         * and return.
                    191:         */
                    192:        if (device->state == DEV_STATE_OPEN) {
                    193: 
                    194:            if (device->flag & D_EXCL_OPEN) {
                    195:                /*
                    196:                 * Cannot open a second time.
                    197:                 */
                    198:                device_unlock(device);
                    199:                mach_device_deallocate(device);
                    200:                return (D_ALREADY_OPEN);
                    201:            }
                    202: 
                    203:            device->open_count++;
                    204:            device_unlock(device);
                    205: #ifdef i386
                    206:            *device_p = &device->dev;
                    207: #else
                    208:            *device_p = device;
                    209: #endif
                    210:            return (D_SUCCESS);
                    211:            /*
                    212:             * Return deallocates device reference while acquiring
                    213:             * port.
                    214:             */
                    215:        }
                    216: 
                    217:        /*
                    218:         * Allocate the device port and register the device before
                    219:         * opening it.
                    220:         */
                    221:        device->state = DEV_STATE_OPENING;
                    222:        device_unlock(device);
                    223: 
                    224:        /*
                    225:         * Allocate port, keeping a reference for it.
                    226:         */
                    227:        device->port = ipc_port_alloc_kernel();
                    228:        if (device->port == IP_NULL) {
                    229:            device_lock(device);
                    230:            device->state = DEV_STATE_INIT;
                    231:            device->port = IP_NULL;
                    232:            if (device->io_wait) {
                    233:                device->io_wait = FALSE;
                    234:                thread_wakeup((event_t)device);
                    235:            }
                    236:            device_unlock(device);
                    237:            mach_device_deallocate(device);
                    238:            return (KERN_RESOURCE_SHORTAGE);
                    239:        }
                    240: 
                    241:        dev_port_enter(device);
                    242: 
                    243:        /*
                    244:         * Request no-senders notifications on device port.
                    245:         */
                    246:        notify = ipc_port_make_sonce(device->port);
                    247:        ip_lock(device->port);
                    248:        ipc_port_nsrequest(device->port, 1, notify, &notify);
                    249:        assert(notify == IP_NULL);
                    250: 
                    251:        /*
                    252:         * Open the device.
                    253:         */
                    254:        io_req_alloc(ior, 0);
                    255: 
                    256:        ior->io_device  = device;
                    257:        ior->io_unit    = device->dev_number;
                    258:        ior->io_op      = IO_OPEN | IO_CALL;
                    259:        ior->io_mode    = mode;
                    260:        ior->io_error   = 0;
                    261:        ior->io_done    = ds_open_done;
                    262:        ior->io_reply_port = reply_port;
                    263:        ior->io_reply_port_type = reply_port_type;
                    264: 
                    265:        result = (*device->dev_ops->d_open)(device->dev_number, (int)mode, ior);
                    266:        if (result == D_IO_QUEUED)
                    267:            return (MIG_NO_REPLY);
                    268: 
                    269:        /*
                    270:         * Return result via ds_open_done.
                    271:         */
                    272:        ior->io_error = result;
                    273:        (void) ds_open_done(ior);
                    274: 
                    275:        io_req_free(ior);
                    276: 
                    277:        return (MIG_NO_REPLY);  /* reply already sent */
                    278: }
                    279: 
                    280: boolean_t
                    281: ds_open_done(ior)
                    282:        register io_req_t       ior;
                    283: {
                    284:        kern_return_t           result;
                    285:        register mach_device_t  device;
                    286: 
                    287:        device = ior->io_device;
                    288:        result = ior->io_error;
                    289: 
                    290:        if (result != D_SUCCESS) {
                    291:            /*
                    292:             * Open failed.  Deallocate port and device.
                    293:             */
                    294:            dev_port_remove(device);
                    295:            ipc_port_dealloc_kernel(device->port);
                    296:            device->port = IP_NULL;
                    297: 
                    298:            device_lock(device);
                    299:            device->state = DEV_STATE_INIT;
                    300:            if (device->io_wait) {
                    301:                device->io_wait = FALSE;
                    302:                thread_wakeup((event_t)device);
                    303:            }
                    304:            device_unlock(device);
                    305: 
                    306:            mach_device_deallocate(device);
                    307:            device = MACH_DEVICE_NULL;
                    308:        }
                    309:        else {
                    310:            /*
                    311:             * Open succeeded.
                    312:             */
                    313:            device_lock(device);
                    314:            device->state = DEV_STATE_OPEN;
                    315:            device->open_count = 1;
                    316:            if (device->io_wait) {
                    317:                device->io_wait = FALSE;
                    318:                thread_wakeup((event_t)device);
                    319:            }
                    320:            device_unlock(device);
                    321: 
                    322:            /* donate device reference to get port */
                    323:        }
                    324:        /*
                    325:         * Must explicitly convert device to port, since
                    326:         * device_reply interface is built as 'user' side
                    327:         * (thus cannot get translation).
                    328:         */
                    329:        if (IP_VALID(ior->io_reply_port)) {
                    330:                (void) ds_device_open_reply(ior->io_reply_port,
                    331:                                            ior->io_reply_port_type,
                    332:                                            result,
                    333: #ifdef i386
                    334:                                            (mach_convert_device_to_port
                    335:                                             (device)));
                    336: #else
                    337:                                            convert_device_to_port(device));
                    338: #endif
                    339:        } else
                    340:                mach_device_deallocate(device);
                    341: 
                    342:        return (TRUE);
                    343: }
                    344: 
                    345: #ifdef i386
                    346: static io_return_t
                    347: device_close(device)
                    348: #else
                    349: io_return_t
                    350: ds_device_close(device)
                    351: #endif
                    352:        register mach_device_t  device;
                    353: {
                    354: #ifndef i386
                    355:        if (device == DEVICE_NULL)
                    356:            return (D_NO_SUCH_DEVICE);
                    357: #endif
                    358: 
                    359:        device_lock(device);
                    360: 
                    361:        /*
                    362:         * If device will remain open, do nothing.
                    363:         */
                    364:        if (--device->open_count > 0) {
                    365:            device_unlock(device);
                    366:            return (D_SUCCESS);
                    367:        }
                    368: 
                    369:        /*
                    370:         * If device is being closed, do nothing.
                    371:         */
                    372:        if (device->state == DEV_STATE_CLOSING) {
                    373:            device_unlock(device);
                    374:            return (D_SUCCESS);
                    375:        }
                    376: 
                    377:        /*
                    378:         * Mark device as closing, to prevent new IO.
                    379:         * Outstanding IO will still be in progress.
                    380:         */
                    381:        device->state = DEV_STATE_CLOSING;
                    382:        device_unlock(device);
                    383: 
                    384:        /*
                    385:         * ? wait for IO to end ?
                    386:         *   only if device wants to
                    387:         */
                    388: 
                    389:        /*
                    390:         * Remove the device-port association.
                    391:         */
                    392:        dev_port_remove(device);
                    393:        ipc_port_dealloc_kernel(device->port);
                    394: 
                    395:        /*
                    396:         * Close the device
                    397:         */
                    398:        (*device->dev_ops->d_close)(device->dev_number);
                    399: 
                    400:        /*
                    401:         * Finally mark it closed.  If someone else is trying
                    402:         * to open it, the open can now proceed.
                    403:         */
                    404:        device_lock(device);
                    405:        device->state = DEV_STATE_INIT;
                    406:        if (device->io_wait) {
                    407:            device->io_wait = FALSE;
                    408:            thread_wakeup((event_t)device);
                    409:        }
                    410:        device_unlock(device);
                    411: 
                    412:        return (D_SUCCESS);
                    413: }
                    414: 
                    415: /*
                    416:  * Write to a device.
                    417:  */
                    418: #ifdef i386
                    419: static io_return_t
                    420: device_write(d, reply_port, reply_port_type, mode, recnum,
                    421:             data, data_count, bytes_written)
                    422:        void *d;
                    423: #else
                    424: io_return_t
                    425: ds_device_write(device, reply_port, reply_port_type, mode, recnum,
                    426:                data, data_count, bytes_written)
                    427:        register mach_device_t  device;
                    428: #endif
                    429:        ipc_port_t              reply_port;
                    430:        mach_msg_type_name_t    reply_port_type;
                    431:        dev_mode_t              mode;
                    432:        recnum_t                recnum;
                    433:        io_buf_ptr_t            data;
                    434:        unsigned int            data_count;
                    435:        int                     *bytes_written; /* out */
                    436: {
                    437: #ifdef i386
                    438:        register mach_device_t  device = d;
                    439: #endif
                    440:        register io_req_t       ior;
                    441:        register io_return_t    result;
                    442: 
                    443: #ifndef i386
                    444:        /*
                    445:         * Refuse if device is dead or not completely open.
                    446:         */
                    447:        if (device == DEVICE_NULL)
                    448:            return (D_NO_SUCH_DEVICE);
                    449: #endif
                    450: 
                    451:        if (device->state != DEV_STATE_OPEN)
                    452:            return (D_NO_SUCH_DEVICE);
                    453: 
                    454: #ifndef i386
                    455:        if (data == 0)
                    456:           return (D_INVALID_SIZE);
                    457: #endif
                    458: 
                    459:        /*
                    460:         * XXX Need logic to reject ridiculously big requests.
                    461:         */
                    462: 
                    463:        /* XXX note that a CLOSE may proceed at any point */
                    464: 
                    465:        /*
                    466:         * Package the write request for the device driver
                    467:         */
                    468:        io_req_alloc(ior, data_count);
                    469: 
                    470:        ior->io_device          = device;
                    471:        ior->io_unit            = device->dev_number;
                    472:        ior->io_op              = IO_WRITE | IO_CALL;
                    473:        ior->io_mode            = mode;
                    474:        ior->io_recnum          = recnum;
                    475:        ior->io_data            = data;
                    476:        ior->io_count           = data_count;
                    477:        ior->io_total           = data_count;
                    478:        ior->io_alloc_size      = 0;
                    479:        ior->io_residual        = 0;
                    480:        ior->io_error           = 0;
                    481:        ior->io_done            = ds_write_done;
                    482:        ior->io_reply_port      = reply_port;
                    483:        ior->io_reply_port_type = reply_port_type;
                    484:        ior->io_copy            = VM_MAP_COPY_NULL;
                    485: 
                    486:        /*
                    487:         * The ior keeps an extra reference for the device.
                    488:         */
                    489:        mach_device_reference(device);
                    490: 
                    491:        /*
                    492:         * And do the write ...
                    493:         *
                    494:         * device_write_dealoc returns false if there's more
                    495:         * to do; it has updated the ior appropriately and expects
                    496:         * its caller to reinvoke it on the device.
                    497:         */
                    498: 
                    499:        do {
                    500: 
                    501:                result = (*device->dev_ops->d_write)(device->dev_number, ior);
                    502: 
                    503:                /*
                    504:                 * If the IO was queued, delay reply until it is finished.
                    505:                 */
                    506:                if (result == D_IO_QUEUED)
                    507:                    return (MIG_NO_REPLY);
                    508: 
                    509:                /*
                    510:                 * Discard the local mapping of the data.
                    511:                 */
                    512: 
                    513:        } while (!device_write_dealloc(ior));
                    514: 
                    515:        /*
                    516:         * Return the number of bytes actually written.
                    517:         */
                    518:        *bytes_written = ior->io_total - ior->io_residual;
                    519: 
                    520:        /*
                    521:         * Remove the extra reference.
                    522:         */
                    523:        mach_device_deallocate(device);
                    524: 
                    525:        io_req_free(ior);
                    526:        return (result);
                    527: }
                    528: 
                    529: /*
                    530:  * Write to a device, but memory is in message.
                    531:  */
                    532: #ifdef i386
                    533: static io_return_t
                    534: device_write_inband(d, reply_port, reply_port_type, mode, recnum,
                    535:                    data, data_count, bytes_written)
                    536:        void *d;
                    537: #else
                    538: io_return_t
                    539: ds_device_write_inband(device, reply_port, reply_port_type, mode, recnum,
                    540:                       data, data_count, bytes_written)
                    541:        register mach_device_t  device;
                    542: #endif
                    543:        ipc_port_t              reply_port;
                    544:        mach_msg_type_name_t    reply_port_type;
                    545:        dev_mode_t              mode;
                    546:        recnum_t                recnum;
                    547:        io_buf_ptr_inband_t     data;
                    548:        unsigned int            data_count;
                    549:        int                     *bytes_written; /* out */
                    550: {
                    551: #ifdef i386
                    552:        register mach_device_t  device = d;
                    553: #endif
                    554:        register io_req_t       ior;
                    555:        register io_return_t    result;
                    556: 
                    557: #ifndef i386
                    558:        /*
                    559:         * Refuse if device is dead or not completely open.
                    560:         */
                    561:        if (device == DEVICE_NULL)
                    562:            return (D_NO_SUCH_DEVICE);
                    563: #endif
                    564: 
                    565:        if (device->state != DEV_STATE_OPEN)
                    566:            return (D_NO_SUCH_DEVICE);
                    567: 
                    568: #ifndef i386
                    569:        if (data == 0)
                    570:           return (D_INVALID_SIZE);
                    571: #endif
                    572: 
                    573:        /* XXX note that a CLOSE may proceed at any point */
                    574: 
                    575:        /*
                    576:         * Package the write request for the device driver.
                    577:         */
                    578:        io_req_alloc(ior, 0);
                    579: 
                    580:        ior->io_device          = device;
                    581:        ior->io_unit            = device->dev_number;
                    582:        ior->io_op              = IO_WRITE | IO_CALL | IO_INBAND;
                    583:        ior->io_mode            = mode;
                    584:        ior->io_recnum          = recnum;
                    585:        ior->io_data            = data;
                    586:        ior->io_count           = data_count;
                    587:        ior->io_total           = data_count;
                    588:        ior->io_alloc_size      = 0;
                    589:        ior->io_residual        = 0;
                    590:        ior->io_error           = 0;
                    591:        ior->io_done            = ds_write_done;
                    592:        ior->io_reply_port      = reply_port;
                    593:        ior->io_reply_port_type = reply_port_type;
                    594: 
                    595:        /*
                    596:         * The ior keeps an extra reference for the device.
                    597:         */
                    598:        mach_device_reference(device);
                    599: 
                    600:        /*
                    601:         * And do the write.
                    602:         */
                    603:        result = (*device->dev_ops->d_write)(device->dev_number, ior);
                    604: 
                    605:        /*
                    606:         * If the IO was queued, delay reply until it is finished.
                    607:         */
                    608:        if (result == D_IO_QUEUED)
                    609:            return (MIG_NO_REPLY);
                    610: 
                    611:        /*
                    612:         * Return the number of bytes actually written.
                    613:         */
                    614:        *bytes_written = ior->io_total - ior->io_residual;
                    615: 
                    616:        /*
                    617:         * Remove the extra reference.
                    618:         */
                    619:        mach_device_deallocate(device);
                    620: 
                    621:        io_req_free(ior);
                    622:        return (result);
                    623: }
                    624: 
                    625: /*
                    626:  * Wire down incoming memory to give to device.
                    627:  */
                    628: kern_return_t
                    629: device_write_get(ior, wait)
                    630:        register io_req_t       ior;
                    631:        boolean_t               *wait;
                    632: {
                    633:        vm_map_copy_t           io_copy;
                    634:        vm_offset_t             new_addr;
                    635:        register kern_return_t  result;
                    636:        int                     bsize;
                    637:        vm_size_t               min_size;
                    638: 
                    639:        /*
                    640:         * By default, caller does not have to wait.
                    641:         */
                    642:        *wait = FALSE;
                    643: 
                    644:        /*
                    645:         * Nothing to do if no data.
                    646:         */
                    647:        if (ior->io_count == 0)
                    648:            return (KERN_SUCCESS);
                    649: 
                    650:        /*
                    651:         * Loaned iors already have valid data.
                    652:         */
                    653:        if (ior->io_op & IO_LOANED)
                    654:            return (KERN_SUCCESS);
                    655: 
                    656:        /*
                    657:         * Inband case.
                    658:         */
                    659:        if (ior->io_op & IO_INBAND) {
                    660:            assert(ior->io_count <= sizeof (io_buf_ptr_inband_t));
                    661:            new_addr = zalloc(io_inband_zone);
                    662:            bcopy((void*)ior->io_data, (void*)new_addr, ior->io_count);
                    663:            ior->io_data = (io_buf_ptr_t)new_addr;
                    664:            ior->io_alloc_size = sizeof (io_buf_ptr_inband_t);
                    665: 
                    666:            return (KERN_SUCCESS);
                    667:        }
                    668: 
                    669:        /*
                    670:         *      Figure out how much data to move this time.  If the device
                    671:         *      won't return a block size, then we have to do the whole
                    672:         *      request in one shot (ditto if this is a block fragment),
                    673:         *      otherwise, move at least one block's worth.
                    674:         */
                    675:        result = (*ior->io_device->dev_ops->d_dev_info)(
                    676:                                        ior->io_device->dev_number,
                    677:                                        D_INFO_BLOCK_SIZE,
                    678:                                        &bsize);
                    679: 
                    680:        if (result != KERN_SUCCESS || ior->io_count < (vm_size_t) bsize)
                    681:                min_size = (vm_size_t) ior->io_count;
                    682:        else
                    683:                min_size = (vm_size_t) bsize;
                    684: 
                    685:        /*
                    686:         *      Map the pages from this page list into memory.
                    687:         *      io_data records location of data.
                    688:         *      io_alloc_size is the vm size of the region to deallocate.
                    689:         */
                    690:        io_copy = (vm_map_copy_t) ior->io_data;
                    691:        result = kmem_io_map_copyout(device_io_map,
                    692:                        (vm_offset_t*)&ior->io_data, &new_addr,
                    693:                        &ior->io_alloc_size, io_copy, min_size);
                    694:        if (result != KERN_SUCCESS)
                    695:            return (result);
                    696: 
1.1.1.2 ! root      697:        if ((ior->io_data + ior->io_count) >
1.1       root      698:            (((char *)new_addr) + ior->io_alloc_size)) {
                    699: 
                    700:                /*
                    701:                 *      Operation has to be split.  Reset io_count for how
                    702:                 *      much we can do this time.
                    703:                 */
                    704:                assert(vm_map_copy_has_cont(io_copy));
                    705:                assert(ior->io_count == io_copy->size);
                    706:                ior->io_count = ior->io_alloc_size -
                    707:                        (ior->io_data - ((char *)new_addr));
                    708: 
                    709:                /*
                    710:                 *      Caller must wait synchronously.
                    711:                 */
                    712:                ior->io_op &= ~IO_CALL;
1.1.1.2 ! root      713:                *wait = TRUE;
1.1       root      714:        }
                    715: 
                    716:        ior->io_copy = io_copy;                 /* vm_map_copy to discard */
                    717:        return (KERN_SUCCESS);
                    718: }
                    719: 
                    720: /*
                    721:  * Clean up memory allocated for IO.
                    722:  */
                    723: boolean_t
                    724: device_write_dealloc(ior)
                    725:        register io_req_t       ior;
                    726: {
                    727:        vm_map_copy_t   new_copy = VM_MAP_COPY_NULL;
                    728:        register
                    729:        vm_map_copy_t   io_copy;
                    730:        kern_return_t   result;
                    731:        vm_offset_t     size_to_do;
1.1.1.2 ! root      732:        int             bsize;
1.1       root      733: 
                    734:        if (ior->io_alloc_size == 0)
                    735:            return (TRUE);
                    736: 
                    737:        /*
                    738:         * Inband case.
                    739:         */
                    740:        if (ior->io_op & IO_INBAND) {
                    741:            zfree(io_inband_zone, (vm_offset_t)ior->io_data);
                    742: 
                    743:            return (TRUE);
                    744:        }
1.1.1.2 ! root      745: 
1.1       root      746:        if ((io_copy = ior->io_copy) == VM_MAP_COPY_NULL)
                    747:            return (TRUE);
                    748: 
                    749:        /*
                    750:         *      To prevent a possible deadlock with the default pager,
                    751:         *      we have to release space in the device_io_map before
                    752:         *      we allocate any memory.  (Which vm_map_copy_invoke_cont
                    753:         *      might do.)  See the discussion in ds_init.
                    754:         */
                    755: 
                    756:        kmem_io_map_deallocate(device_io_map,
                    757:                         trunc_page(ior->io_data),
                    758:                        (vm_size_t) ior->io_alloc_size);
                    759: 
                    760:        if (vm_map_copy_has_cont(io_copy)) {
                    761: 
                    762:                /*
1.1.1.2 ! root      763:                 *      Remember how much is left, then
1.1       root      764:                 *      invoke or abort the continuation.
                    765:                 */
                    766:                size_to_do = io_copy->size - ior->io_count;
                    767:                if (ior->io_error == 0) {
                    768:                        vm_map_copy_invoke_cont(io_copy, &new_copy, &result);
                    769:                }
                    770:                else {
                    771:                        vm_map_copy_abort_cont(io_copy);
                    772:                        result = KERN_FAILURE;
                    773:                }
                    774: 
                    775:                if (result == KERN_SUCCESS && new_copy != VM_MAP_COPY_NULL) {
                    776:                        register int    res;
                    777: 
                    778:                        /*
                    779:                         *      We have a new continuation, reset the ior to
                    780:                         *      represent the remainder of the request.  Must
                    781:                         *      adjust the recnum because drivers assume
                    782:                         *      that the residual is zero.
                    783:                         */
                    784:                        ior->io_op &= ~IO_DONE;
                    785:                        ior->io_op |= IO_CALL;
                    786: 
                    787:                        res = (*ior->io_device->dev_ops->d_dev_info)(
                    788:                                        ior->io_device->dev_number,
                    789:                                        D_INFO_BLOCK_SIZE,
                    790:                                        &bsize);
                    791: 
                    792:                        if (res != D_SUCCESS)
                    793:                                panic("device_write_dealloc: No block size");
1.1.1.2 ! root      794: 
1.1       root      795:                        ior->io_recnum += ior->io_count/bsize;
                    796:                        ior->io_count = new_copy->size;
                    797:                }
                    798:                else {
                    799: 
                    800:                        /*
                    801:                         *      No continuation.  Add amount we didn't get
                    802:                         *      to into residual.
                    803:                         */
                    804:                        ior->io_residual += size_to_do;
                    805:                }
                    806:        }
                    807: 
                    808:        /*
                    809:         *      Clean up the state for the IO that just completed.
                    810:         */
                    811:         vm_map_copy_discard(ior->io_copy);
                    812:        ior->io_copy = VM_MAP_COPY_NULL;
                    813:        ior->io_data = (char *) new_copy;
                    814: 
                    815:        /*
                    816:         *      Return FALSE if there's more IO to do.
                    817:         */
                    818: 
                    819:        return(new_copy == VM_MAP_COPY_NULL);
                    820: }
                    821: 
                    822: /*
                    823:  * Send write completion message to client, and discard the data.
                    824:  */
                    825: boolean_t
                    826: ds_write_done(ior)
                    827:        register io_req_t       ior;
                    828: {
                    829:        /*
                    830:         *      device_write_dealloc discards the data that has been
                    831:         *      written, but may decide that there is more to write.
                    832:         */
                    833:        while (!device_write_dealloc(ior)) {
                    834:                register io_return_t    result;
                    835:                register mach_device_t  device;
                    836: 
                    837:                /*
                    838:                 *     More IO to do -- invoke it.
                    839:                 */
                    840:                device = ior->io_device;
                    841:                result = (*device->dev_ops->d_write)(device->dev_number, ior);
                    842: 
                    843:                /*
                    844:                 * If the IO was queued, return FALSE -- not done yet.
                    845:                 */
                    846:                if (result == D_IO_QUEUED)
                    847:                    return (FALSE);
                    848:        }
                    849: 
                    850:        /*
                    851:         *      Now the write is really complete.  Send reply.
                    852:         */
                    853: 
                    854:        if (IP_VALID(ior->io_reply_port)) {
                    855:            (void) (*((ior->io_op & IO_INBAND) ?
                    856:                      ds_device_write_reply_inband :
                    857:                      ds_device_write_reply))(ior->io_reply_port,
                    858:                                              ior->io_reply_port_type,
                    859:                                              ior->io_error,
                    860:                                              (int) (ior->io_total -
                    861:                                                     ior->io_residual));
                    862:        }
                    863:        mach_device_deallocate(ior->io_device);
                    864: 
                    865:        return (TRUE);
                    866: }
                    867: 
                    868: /*
                    869:  * Read from a device.
                    870:  */
                    871: #ifdef i386
                    872: static io_return_t
                    873: device_read(d, reply_port, reply_port_type, mode, recnum,
                    874:            bytes_wanted, data, data_count)
                    875:        void *d;
                    876: #else
                    877: io_return_t
                    878: ds_device_read(device, reply_port, reply_port_type, mode, recnum,
                    879:               bytes_wanted, data, data_count)
                    880:        register mach_device_t  device;
                    881: #endif
                    882:        ipc_port_t              reply_port;
                    883:        mach_msg_type_name_t    reply_port_type;
                    884:        dev_mode_t              mode;
                    885:        recnum_t                recnum;
                    886:        int                     bytes_wanted;
                    887:        io_buf_ptr_t            *data;          /* out */
                    888:        unsigned int            *data_count;    /* out */
                    889: {
                    890: #ifdef i386
                    891:        register mach_device_t  device = d;
                    892: #endif
                    893:        register io_req_t       ior;
                    894:        register io_return_t    result;
                    895: 
                    896: #ifdef lint
                    897:        *data = *data;
                    898:        *data_count = *data_count;
                    899: #endif lint
                    900: 
                    901: #ifndef i386
                    902:        /*
                    903:         * Refuse if device is dead or not completely open.
                    904:         */
                    905:        if (device == DEVICE_NULL)
                    906:            return (D_NO_SUCH_DEVICE);
                    907: #endif
                    908: 
                    909:        if (device->state != DEV_STATE_OPEN)
                    910:            return (D_NO_SUCH_DEVICE);
                    911: 
                    912:        /* XXX note that a CLOSE may proceed at any point */
                    913: 
                    914:        /*
                    915:         * There must be a reply port.
                    916:         */
                    917:        if (!IP_VALID(reply_port)) {
                    918:            printf("ds_* invalid reply port\n");
                    919:            Debugger("ds_* reply_port");
                    920:            return (MIG_NO_REPLY);      /* no sense in doing anything */
                    921:        }
                    922: 
                    923:        /*
                    924:         * Package the read request for the device driver
                    925:         */
                    926:        io_req_alloc(ior, 0);
                    927: 
                    928:        ior->io_device          = device;
                    929:        ior->io_unit            = device->dev_number;
                    930:        ior->io_op              = IO_READ | IO_CALL;
                    931:        ior->io_mode            = mode;
                    932:        ior->io_recnum          = recnum;
                    933:        ior->io_data            = 0;            /* driver must allocate data */
                    934:        ior->io_count           = bytes_wanted;
                    935:        ior->io_alloc_size      = 0;            /* no data allocated yet */
                    936:        ior->io_residual        = 0;
                    937:        ior->io_error           = 0;
                    938:        ior->io_done            = ds_read_done;
                    939:        ior->io_reply_port      = reply_port;
                    940:        ior->io_reply_port_type = reply_port_type;
                    941: 
                    942:        /*
                    943:         * The ior keeps an extra reference for the device.
                    944:         */
                    945:        mach_device_reference(device);
                    946: 
                    947:        /*
                    948:         * And do the read.
                    949:         */
                    950:        result = (*device->dev_ops->d_read)(device->dev_number, ior);
                    951: 
                    952:        /*
                    953:         * If the IO was queued, delay reply until it is finished.
                    954:         */
                    955:        if (result == D_IO_QUEUED)
                    956:            return (MIG_NO_REPLY);
                    957: 
                    958:        /*
                    959:         * Return result via ds_read_done.
                    960:         */
                    961:        ior->io_error = result;
                    962:        (void) ds_read_done(ior);
                    963:        io_req_free(ior);
                    964: 
                    965:        return (MIG_NO_REPLY);  /* reply has already been sent. */
                    966: }
                    967: 
                    968: /*
                    969:  * Read from a device, but return the data 'inband.'
                    970:  */
                    971: #ifdef i386
                    972: static io_return_t
                    973: device_read_inband(d, reply_port, reply_port_type, mode, recnum,
                    974:                   bytes_wanted, data, data_count)
                    975:        void *d;
                    976: #else
                    977: io_return_t
                    978: ds_device_read_inband(device, reply_port, reply_port_type, mode, recnum,
                    979:                      bytes_wanted, data, data_count)
                    980:        register mach_device_t  device;
                    981: #endif
                    982:        ipc_port_t              reply_port;
                    983:        mach_msg_type_name_t    reply_port_type;
                    984:        dev_mode_t              mode;
                    985:        recnum_t                recnum;
                    986:        int                     bytes_wanted;
                    987:        char                    *data;          /* pointer to OUT array */
                    988:        unsigned int            *data_count;    /* out */
                    989: {
                    990: #ifdef i386
                    991:        register mach_device_t  device = d;
                    992: #endif
                    993:        register io_req_t       ior;
                    994:        register io_return_t    result;
                    995: 
                    996: #ifdef lint
                    997:        *data = *data;
                    998:        *data_count = *data_count;
                    999: #endif lint
                   1000: 
                   1001: #ifndef i386
                   1002:        /*
                   1003:         * Refuse if device is dead or not completely open.
                   1004:         */
                   1005:        if (device == DEVICE_NULL)
                   1006:            return (D_NO_SUCH_DEVICE);
                   1007: #endif
                   1008: 
                   1009:        if (device->state != DEV_STATE_OPEN)
                   1010:            return (D_NO_SUCH_DEVICE);
                   1011: 
                   1012:        /* XXX note that a CLOSE may proceed at any point */
                   1013: 
                   1014:        /*
                   1015:         * There must be a reply port.
                   1016:         */
                   1017:        if (!IP_VALID(reply_port)) {
                   1018:            printf("ds_* invalid reply port\n");
                   1019:            Debugger("ds_* reply_port");
                   1020:            return (MIG_NO_REPLY);      /* no sense in doing anything */
                   1021:        }
                   1022: 
                   1023:        /*
                   1024:         * Package the read for the device driver
                   1025:         */
                   1026:        io_req_alloc(ior, 0);
                   1027: 
                   1028:        ior->io_device          = device;
                   1029:        ior->io_unit            = device->dev_number;
                   1030:        ior->io_op              = IO_READ | IO_CALL | IO_INBAND;
                   1031:        ior->io_mode            = mode;
                   1032:        ior->io_recnum          = recnum;
                   1033:        ior->io_data            = 0;            /* driver must allocate data */
1.1.1.2 ! root     1034:        ior->io_count           =
1.1       root     1035:            ((bytes_wanted < sizeof(io_buf_ptr_inband_t)) ?
                   1036:                bytes_wanted : sizeof(io_buf_ptr_inband_t));
                   1037:        ior->io_alloc_size      = 0;            /* no data allocated yet */
                   1038:        ior->io_residual        = 0;
                   1039:        ior->io_error           = 0;
                   1040:        ior->io_done            = ds_read_done;
                   1041:        ior->io_reply_port      = reply_port;
                   1042:        ior->io_reply_port_type = reply_port_type;
                   1043: 
                   1044:        /*
                   1045:         * The ior keeps an extra reference for the device.
                   1046:         */
                   1047:        mach_device_reference(device);
                   1048: 
                   1049:        /*
                   1050:         * Do the read.
                   1051:         */
                   1052:        result = (*device->dev_ops->d_read)(device->dev_number, ior);
                   1053: 
                   1054:        /*
                   1055:         * If the io was queued, delay reply until it is finished.
                   1056:         */
                   1057:        if (result == D_IO_QUEUED)
                   1058:            return (MIG_NO_REPLY);
                   1059: 
                   1060:        /*
                   1061:         * Return result, via ds_read_done.
                   1062:         */
                   1063:        ior->io_error = result;
                   1064:        (void) ds_read_done(ior);
                   1065:        io_req_free(ior);
                   1066: 
                   1067:        return (MIG_NO_REPLY);  /* reply has already been sent. */
                   1068: }
                   1069: 
                   1070: 
                   1071: /*
                   1072:  * Allocate wired-down memory for device read.
                   1073:  */
                   1074: kern_return_t device_read_alloc(ior, size)
                   1075:        register io_req_t       ior;
                   1076:        register vm_size_t      size;
                   1077: {
                   1078:        vm_offset_t             addr;
                   1079:        kern_return_t           kr;
                   1080: 
                   1081:        /*
                   1082:         * Nothing to do if no data.
                   1083:         */
                   1084:        if (ior->io_count == 0)
                   1085:            return (KERN_SUCCESS);
                   1086: 
                   1087:        if (ior->io_op & IO_INBAND) {
                   1088:            ior->io_data = (io_buf_ptr_t) zalloc(io_inband_zone);
                   1089:            ior->io_alloc_size = sizeof(io_buf_ptr_inband_t);
                   1090:        } else {
                   1091:            size = round_page(size);
                   1092:            kr = kmem_alloc(kernel_map, &addr, size);
                   1093:            if (kr != KERN_SUCCESS)
                   1094:                return (kr);
                   1095: 
                   1096:            ior->io_data = (io_buf_ptr_t) addr;
                   1097:            ior->io_alloc_size = size;
                   1098:        }
                   1099: 
                   1100:        return (KERN_SUCCESS);
                   1101: }
                   1102: 
                   1103: boolean_t ds_read_done(ior)
                   1104:        io_req_t        ior;
                   1105: {
                   1106:        vm_offset_t             start_data, end_data;
                   1107:        vm_offset_t             start_sent, end_sent;
                   1108:        register vm_size_t      size_read;
                   1109: 
                   1110:        if (ior->io_error)
                   1111:            size_read = 0;
                   1112:        else
                   1113:            size_read = ior->io_count - ior->io_residual;
                   1114: 
                   1115:        start_data  = (vm_offset_t)ior->io_data;
                   1116:        end_data    = start_data + size_read;
                   1117: 
                   1118:        start_sent  = (ior->io_op & IO_INBAND) ? start_data :
                   1119:                                                trunc_page(start_data);
1.1.1.2 ! root     1120:        end_sent    = (ior->io_op & IO_INBAND) ?
1.1       root     1121:                start_data + ior->io_alloc_size : round_page(end_data);
                   1122: 
                   1123:        /*
                   1124:         * Zero memory that the device did not fill.
                   1125:         */
                   1126:        if (start_sent < start_data)
                   1127:            bzero((char *)start_sent, start_data - start_sent);
                   1128:        if (end_sent > end_data)
                   1129:            bzero((char *)end_data, end_sent - end_data);
                   1130: 
                   1131: 
                   1132:        /*
                   1133:         * Touch the data being returned, to mark it dirty.
                   1134:         * If the pages were filled by DMA, the pmap module
                   1135:         * may think that they are clean.
                   1136:         */
                   1137:        {
                   1138:            register vm_offset_t        touch;
                   1139:            register int                c;
                   1140: 
                   1141:            for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) {
1.1.1.2 ! root     1142:                c = *(volatile char *)touch;
        !          1143:                *(volatile char *)touch = c;
1.1       root     1144:            }
                   1145:        }
                   1146: 
                   1147:        /*
                   1148:         * Send the data to the reply port - this
                   1149:         * unwires and deallocates it.
                   1150:         */
                   1151:        if (ior->io_op & IO_INBAND) {
                   1152:            (void)ds_device_read_reply_inband(ior->io_reply_port,
                   1153:                                              ior->io_reply_port_type,
                   1154:                                              ior->io_error,
                   1155:                                              (char *) start_data,
                   1156:                                              size_read);
                   1157:        } else {
                   1158:            vm_map_copy_t copy;
                   1159:            kern_return_t kr;
                   1160: 
                   1161:            kr = vm_map_copyin_page_list(kernel_map, start_data,
                   1162:                                                 size_read, TRUE, TRUE,
                   1163:                                                 &copy, FALSE);
                   1164: 
                   1165:            if (kr != KERN_SUCCESS)
                   1166:                panic("read_done: vm_map_copyin_page_list failed");
                   1167: 
                   1168:            (void)ds_device_read_reply(ior->io_reply_port,
                   1169:                                       ior->io_reply_port_type,
                   1170:                                       ior->io_error,
                   1171:                                       (char *) copy,
                   1172:                                       size_read);
                   1173:        }
                   1174: 
                   1175:        /*
                   1176:         * Free any memory that was allocated but not sent.
                   1177:         */
                   1178:        if (ior->io_count != 0) {
                   1179:            if (ior->io_op & IO_INBAND) {
                   1180:                if (ior->io_alloc_size > 0)
                   1181:                    zfree(io_inband_zone, (vm_offset_t)ior->io_data);
                   1182:            } else {
                   1183:                register vm_offset_t    end_alloc;
                   1184: 
                   1185:                end_alloc = start_sent + round_page(ior->io_alloc_size);
                   1186:                if (end_alloc > end_sent)
                   1187:                    (void) vm_deallocate(kernel_map,
                   1188:                                         end_sent,
                   1189:                                         end_alloc - end_sent);
                   1190:            }
                   1191:        }
                   1192: 
                   1193:        mach_device_deallocate(ior->io_device);
                   1194: 
                   1195:        return (TRUE);
                   1196: }
                   1197: 
                   1198: #ifdef i386
                   1199: static io_return_t
                   1200: device_set_status(d, flavor, status, status_count)
                   1201:        void *d;
                   1202: #else
                   1203: io_return_t
                   1204: ds_device_set_status(device, flavor, status, status_count)
                   1205:        register mach_device_t  device;
                   1206: #endif
                   1207:        dev_flavor_t            flavor;
                   1208:        dev_status_t            status;
                   1209:        mach_msg_type_number_t  status_count;
                   1210: {
                   1211: #ifdef i386
                   1212:        register mach_device_t device = d;
                   1213: #endif
                   1214: 
                   1215: #ifndef i386
                   1216:        /*
                   1217:         * Refuse if device is dead or not completely open.
                   1218:         */
                   1219:        if (device == DEVICE_NULL)
                   1220:            return (D_NO_SUCH_DEVICE);
                   1221: #endif
                   1222: 
                   1223:        if (device->state != DEV_STATE_OPEN)
                   1224:            return (D_NO_SUCH_DEVICE);
                   1225: 
                   1226:        /* XXX note that a CLOSE may proceed at any point */
                   1227: 
                   1228:        return ((*device->dev_ops->d_setstat)(device->dev_number,
                   1229:                                              flavor,
                   1230:                                              status,
                   1231:                                              status_count));
                   1232: }
                   1233: 
                   1234: #ifdef i386
                   1235: io_return_t
                   1236: mach_device_get_status(d, flavor, status, status_count)
                   1237:        void *d;
                   1238: #else
                   1239: io_return_t
                   1240: ds_device_get_status(device, flavor, status, status_count)
                   1241:        register mach_device_t  device;
                   1242: #endif
                   1243:        dev_flavor_t            flavor;
                   1244:        dev_status_t            status;         /* pointer to OUT array */
                   1245:        mach_msg_type_number_t  *status_count;  /* out */
                   1246: {
                   1247: #ifdef i386
                   1248:        register mach_device_t  device = d;
                   1249: #endif
                   1250: 
                   1251: #ifndef i386
                   1252:        /*
                   1253:         * Refuse if device is dead or not completely open.
                   1254:         */
                   1255:        if (device == DEVICE_NULL)
                   1256:            return (D_NO_SUCH_DEVICE);
                   1257: #endif
                   1258: 
                   1259:        if (device->state != DEV_STATE_OPEN)
                   1260:            return (D_NO_SUCH_DEVICE);
                   1261: 
                   1262:        /* XXX note that a CLOSE may proceed at any point */
                   1263: 
                   1264:        return ((*device->dev_ops->d_getstat)(device->dev_number,
                   1265:                                              flavor,
                   1266:                                              status,
                   1267:                                              status_count));
                   1268: }
                   1269: 
                   1270: #ifdef i386
                   1271: static io_return_t
                   1272: device_set_filter(d, receive_port, priority, filter, filter_count)
                   1273:        void *d;
                   1274: #else
                   1275: io_return_t
                   1276: ds_device_set_filter(device, receive_port, priority, filter, filter_count)
                   1277:        register mach_device_t  device;
                   1278: #endif
                   1279:        ipc_port_t              receive_port;
                   1280:        int                     priority;
                   1281:        filter_t                filter[];       /* pointer to IN array */
                   1282:        unsigned int            filter_count;
                   1283: {
                   1284: #ifdef i386
                   1285:        register mach_device_t  device = d;
                   1286: #endif
                   1287: 
                   1288: #ifndef i386
                   1289:        /*
                   1290:         * Refuse if device is dead or not completely open.
                   1291:         */
                   1292:        if (device == DEVICE_NULL)
                   1293:            return (D_NO_SUCH_DEVICE);
                   1294: #endif
                   1295: 
                   1296:        if (device->state != DEV_STATE_OPEN)
                   1297:            return (D_NO_SUCH_DEVICE);
                   1298: 
                   1299:        /* XXX note that a CLOSE may proceed at any point */
                   1300: 
                   1301:        /*
                   1302:         * Request is absurd if no receive port is specified.
                   1303:         */
                   1304:        if (!IP_VALID(receive_port))
                   1305:            return (D_INVALID_OPERATION);
                   1306: 
                   1307:        return ((*device->dev_ops->d_async_in)(device->dev_number,
                   1308:                                               receive_port,
                   1309:                                               priority,
                   1310:                                               filter,
                   1311:                                               filter_count));
                   1312: }
                   1313: 
                   1314: #ifdef i386
                   1315: static io_return_t
                   1316: device_map(d, protection, offset, size, pager, unmap)
                   1317:        void *d;
                   1318: #else
                   1319: io_return_t
                   1320: ds_device_map(device, protection, offset, size, pager, unmap)
                   1321:        register mach_device_t  device;
                   1322: #endif
                   1323:        vm_prot_t               protection;
                   1324:        vm_offset_t             offset;
                   1325:        vm_size_t               size;
                   1326:        ipc_port_t              *pager; /* out */
                   1327:        boolean_t               unmap;  /* ? */
                   1328: {
                   1329: #ifdef i386
                   1330:        register mach_device_t device = d;
                   1331: #endif
                   1332: 
                   1333: #ifdef lint
                   1334:        unmap = unmap;
                   1335: #endif lint
                   1336:        if (protection & ~VM_PROT_ALL)
                   1337:                return (KERN_INVALID_ARGUMENT);
                   1338: 
                   1339: #ifndef i386
                   1340:        /*
                   1341:         * Refuse if device is dead or not completely open.
                   1342:         */
                   1343:        if (device == DEVICE_NULL)
                   1344:            return (D_NO_SUCH_DEVICE);
                   1345: #endif
                   1346: 
                   1347:        if (device->state != DEV_STATE_OPEN)
                   1348:            return (D_NO_SUCH_DEVICE);
                   1349: 
                   1350:        /* XXX note that a CLOSE may proceed at any point */
                   1351: 
                   1352:        return (device_pager_setup(device, protection, offset, size,
                   1353:                                    (mach_port_t*)pager));
                   1354: }
                   1355: 
                   1356: /*
                   1357:  * Doesn't do anything (yet).
                   1358:  */
                   1359: #ifdef i386
                   1360: static void
                   1361: #else
                   1362: void
                   1363: #endif
                   1364: ds_no_senders(notification)
                   1365:        mach_no_senders_notification_t *notification;
                   1366: {
                   1367:        printf("ds_no_senders called! device_port=0x%x count=%d\n",
                   1368:               notification->not_header.msgh_remote_port,
                   1369:               notification->not_count);
                   1370: }
                   1371: 
                   1372: #ifndef i386
                   1373: boolean_t
                   1374: ds_notify(msg)
                   1375:        mach_msg_header_t *msg;
                   1376: {
                   1377:        switch (msg->msgh_id) {
                   1378:                case MACH_NOTIFY_NO_SENDERS:
                   1379:                ds_no_senders((mach_no_senders_notification_t *) msg);
                   1380:                return TRUE;
                   1381: 
                   1382:                default:
                   1383:                printf("ds_notify: strange notification %d\n", msg->msgh_id);
                   1384:                return FALSE;
                   1385:        }
                   1386: }
                   1387: #endif
                   1388: 
                   1389: queue_head_t           io_done_list;
                   1390: decl_simple_lock_data(,        io_done_list_lock)
                   1391: 
                   1392: #define        splio   splsched        /* XXX must block ALL io devices */
                   1393: 
                   1394: void iodone(ior)
                   1395:        register io_req_t       ior;
                   1396: {
                   1397:        register spl_t  s;
                   1398: 
                   1399:        /*
                   1400:         * If this ior was loaned to us, return it directly.
                   1401:         */
                   1402:        if (ior->io_op & IO_LOANED) {
                   1403:                (*ior->io_done)(ior);
                   1404:                return;
                   1405:        }
                   1406:        /*
                   1407:         * If !IO_CALL, some thread is waiting for this.  Must lock
                   1408:         * structure to interlock correctly with iowait().  Else can
                   1409:         * toss on queue for io_done thread to call completion.
                   1410:         */
                   1411:        s = splio();
                   1412:        if ((ior->io_op & IO_CALL) == 0) {
                   1413:            ior_lock(ior);
                   1414:            ior->io_op |= IO_DONE;
                   1415:            ior->io_op &= ~IO_WANTED;
                   1416:            ior_unlock(ior);
                   1417:            thread_wakeup((event_t)ior);
                   1418:        } else {
                   1419:            ior->io_op |= IO_DONE;
                   1420:            simple_lock(&io_done_list_lock);
                   1421:            enqueue_tail(&io_done_list, (queue_entry_t)ior);
                   1422:            thread_wakeup((event_t)&io_done_list);
                   1423:            simple_unlock(&io_done_list_lock);
                   1424:        }
                   1425:        splx(s);
                   1426: }
                   1427: 
                   1428: void io_done_thread_continue()
                   1429: {
                   1430:        for (;;) {
                   1431:            register spl_t      s;
                   1432:            register io_req_t   ior;
                   1433: 
                   1434: #if defined (i386) && defined (LINUX_DEV) && defined (CONFIG_INET)
                   1435:            free_skbuffs ();
                   1436: #endif
                   1437:            s = splio();
                   1438:            simple_lock(&io_done_list_lock);
                   1439:            while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) {
                   1440:                simple_unlock(&io_done_list_lock);
                   1441:                (void) splx(s);
                   1442: 
                   1443:                if ((*ior->io_done)(ior)) {
                   1444:                    /*
                   1445:                     * IO done - free io_req_elt
                   1446:                     */
                   1447:                    io_req_free(ior);
                   1448:                }
                   1449:                /* else routine has re-queued it somewhere */
                   1450: 
                   1451:                s = splio();
                   1452:                simple_lock(&io_done_list_lock);
                   1453:            }
                   1454: 
                   1455:            assert_wait(&io_done_list, FALSE);
                   1456:            simple_unlock(&io_done_list_lock);
                   1457:            (void) splx(s);
                   1458:            counter(c_io_done_thread_block++);
                   1459:            thread_block(io_done_thread_continue);
                   1460:        }
                   1461: }
                   1462: 
                   1463: void io_done_thread()
                   1464: {
                   1465:        /*
                   1466:         * Set thread privileges and highest priority.
                   1467:         */
                   1468:        current_thread()->vm_privilege = TRUE;
                   1469:        stack_privilege(current_thread());
                   1470:        thread_set_own_priority(0);
                   1471: 
                   1472:        io_done_thread_continue();
                   1473:        /*NOTREACHED*/
                   1474: }
                   1475: 
                   1476: #define        DEVICE_IO_MAP_SIZE      (2 * 1024 * 1024)
                   1477: 
                   1478: extern void ds_trap_init(void);                /* forward */
                   1479: 
                   1480: void ds_init()
                   1481: {
                   1482:        vm_offset_t     device_io_min, device_io_max;
                   1483: 
                   1484:        queue_init(&io_done_list);
                   1485:        simple_lock_init(&io_done_list_lock);
                   1486: 
                   1487:        device_io_map = kmem_suballoc(kernel_map,
                   1488:                                      &device_io_min,
                   1489:                                      &device_io_max,
                   1490:                                      DEVICE_IO_MAP_SIZE,
                   1491:                                      FALSE);
                   1492:        /*
                   1493:         *      If the kernel receives many device_write requests, the
                   1494:         *      device_io_map might run out of space.  To prevent
                   1495:         *      device_write_get from failing in this case, we enable
                   1496:         *      wait_for_space on the map.  This causes kmem_io_map_copyout
                   1497:         *      to block until there is sufficient space.
                   1498:         *      (XXX Large writes may be starved by small writes.)
                   1499:         *
                   1500:         *      There is a potential deadlock problem with this solution,
                   1501:         *      if a device_write from the default pager has to wait
                   1502:         *      for the completion of a device_write which needs to wait
                   1503:         *      for memory allocation.  Hence, once device_write_get
                   1504:         *      allocates space in device_io_map, no blocking memory
                   1505:         *      allocations should happen until device_write_dealloc
                   1506:         *      frees the space.  (XXX A large write might starve
                   1507:         *      a small write from the default pager.)
                   1508:         */
                   1509:        device_io_map->wait_for_space = TRUE;
                   1510: 
                   1511:        io_inband_zone = zinit(sizeof(io_buf_ptr_inband_t),
                   1512:                            1000 * sizeof(io_buf_ptr_inband_t),
                   1513:                            10 * sizeof(io_buf_ptr_inband_t),
                   1514:                            FALSE,
                   1515:                            "io inband read buffers");
                   1516: 
                   1517:        ds_trap_init();
                   1518: }
                   1519: 
                   1520: void iowait(ior)
                   1521:     io_req_t ior;
                   1522: {
                   1523:     spl_t s;
                   1524: 
                   1525:     s = splio();
                   1526:     ior_lock(ior);
                   1527:     while ((ior->io_op&IO_DONE)==0) {
                   1528:        assert_wait((event_t)ior, FALSE);
                   1529:        ior_unlock(ior);
                   1530:        thread_block((void (*)()) 0);
                   1531:         ior_lock(ior);
                   1532:     }
                   1533:     ior_unlock(ior);
                   1534:     splx(s);
                   1535: }
                   1536: 
                   1537: 
                   1538: /*
                   1539:  * Device trap support.
                   1540:  */
                   1541: 
                   1542: /*
                   1543:  * Memory Management
                   1544:  *
                   1545:  * This currently has a single pool of 2k wired buffers
                   1546:  * since we only handle writes to an ethernet device.
                   1547:  * Should be more general.
                   1548:  */
                   1549: #define IOTRAP_REQSIZE 2048
                   1550: 
                   1551: zone_t io_trap_zone;
                   1552: 
                   1553: /*
                   1554:  * Initialization.  Called from ds_init().
                   1555:  */
                   1556: void
                   1557: ds_trap_init(void)
                   1558: {
                   1559:        io_trap_zone = zinit(IOTRAP_REQSIZE,
                   1560:                             256 * IOTRAP_REQSIZE,
                   1561:                             16 * IOTRAP_REQSIZE,
                   1562:                             FALSE,
                   1563:                             "wired device trap buffers");
                   1564: }
                   1565: 
                   1566: /*
                   1567:  * Allocate an io_req_t.
                   1568:  * Currently zalloc's from io_trap_zone.
                   1569:  *
                   1570:  * Could have lists of different size zones.
                   1571:  * Could call a device-specific routine.
                   1572:  */
                   1573: io_req_t
                   1574: ds_trap_req_alloc(mach_device_t device, vm_size_t data_size)
                   1575: {
                   1576:        return (io_req_t) zalloc(io_trap_zone);
                   1577: }
                   1578: 
                   1579: /*
                   1580:  * Called by iodone to release ior.
                   1581:  */
                   1582: boolean_t
                   1583: ds_trap_write_done(io_req_t ior)
                   1584: {
                   1585:        register mach_device_t dev;
                   1586: 
                   1587:        dev = ior->io_device;
                   1588: 
                   1589:        /*
                   1590:         * Should look at reply port and maybe send a message.
                   1591:         */
1.1.1.2 ! root     1592:        zfree(io_trap_zone, (vm_offset_t) ior);
        !          1593: 
1.1       root     1594:        /*
                   1595:         * Give up device reference from ds_write_trap.
                   1596:         */
                   1597:        mach_device_deallocate(dev);
                   1598:        return TRUE;
                   1599: }
                   1600: 
                   1601: /*
                   1602:  * Like device_write except that data is in user space.
                   1603:  */
                   1604: #ifdef i386
                   1605: static io_return_t
                   1606: device_write_trap (void *d, dev_mode_t mode,
                   1607:                   recnum_t recnum, vm_offset_t data, vm_size_t data_count)
                   1608: #else
                   1609: io_return_t
                   1610: ds_device_write_trap(device_t          device,
                   1611:                     dev_mode_t         mode,
                   1612:                     recnum_t           recnum,
                   1613:                     vm_offset_t        data,
                   1614:                     vm_size_t          data_count)
                   1615: #endif
                   1616: {
                   1617: #ifdef i386
                   1618:        mach_device_t device = d;
                   1619: #endif
                   1620:        io_req_t ior;
                   1621:        io_return_t result;
                   1622: 
                   1623: #ifndef i386
                   1624:        /*
                   1625:         * Refuse if device is dead or not completely open.
                   1626:         */
                   1627:        if (device == DEVICE_NULL)
                   1628:                return (D_NO_SUCH_DEVICE);
                   1629: #endif
                   1630: 
                   1631:        if (device->state != DEV_STATE_OPEN)
                   1632:                return (D_NO_SUCH_DEVICE);
1.1.1.2 ! root     1633: 
1.1       root     1634:        /* XXX note that a CLOSE may proceed at any point */
1.1.1.2 ! root     1635: 
1.1       root     1636:        /*
                   1637:         * Get a buffer to hold the ioreq.
                   1638:         */
                   1639:        ior = ds_trap_req_alloc(device, data_count);
1.1.1.2 ! root     1640: 
1.1       root     1641:        /*
                   1642:         * Package the write request for the device driver.
                   1643:         */
                   1644: 
                   1645:        ior->io_device          = device;
                   1646:        ior->io_unit            = device->dev_number;
                   1647:        ior->io_op              = IO_WRITE | IO_CALL | IO_LOANED;
                   1648:        ior->io_mode            = mode;
                   1649:        ior->io_recnum          = recnum;
                   1650:        ior->io_data            = (io_buf_ptr_t)
                   1651:                (vm_offset_t)ior + sizeof(struct io_req);
                   1652:        ior->io_count           = data_count;
                   1653:        ior->io_total           = data_count;
                   1654:        ior->io_alloc_size      = 0;
                   1655:        ior->io_residual        = 0;
                   1656:        ior->io_error           = 0;
                   1657:        ior->io_done            = ds_trap_write_done;
                   1658:        ior->io_reply_port      = IP_NULL;      /* XXX */
                   1659:        ior->io_reply_port_type = 0;            /* XXX */
                   1660: 
                   1661:        /*
                   1662:         * Copy the data from user space.
                   1663:         */
                   1664:        if (data_count > 0)
                   1665:                copyin((char *)data, (char *)ior->io_data, data_count);
1.1.1.2 ! root     1666: 
1.1       root     1667:        /*
                   1668:         * The ior keeps an extra reference for the device.
                   1669:         */
                   1670:        mach_device_reference(device);
1.1.1.2 ! root     1671: 
1.1       root     1672:        /*
                   1673:         * And do the write.
                   1674:         */
                   1675:        result = (*device->dev_ops->d_write)(device->dev_number, ior);
1.1.1.2 ! root     1676: 
1.1       root     1677:        /*
                   1678:         * If the IO was queued, delay reply until it is finished.
                   1679:         */
                   1680:        if (result == D_IO_QUEUED)
                   1681:                return (MIG_NO_REPLY);
1.1.1.2 ! root     1682: 
1.1       root     1683:        /*
                   1684:         * Remove the extra reference.
                   1685:         */
                   1686:        mach_device_deallocate(device);
1.1.1.2 ! root     1687: 
        !          1688:        zfree(io_trap_zone, (vm_offset_t) ior);
1.1       root     1689:        return (result);
                   1690: }
                   1691: 
                   1692: #ifdef i386
                   1693: static io_return_t
                   1694: device_writev_trap (void *d, dev_mode_t mode,
                   1695:                    recnum_t recnum, io_buf_vec_t *iovec, vm_size_t iocount)
                   1696: #else
                   1697: io_return_t
                   1698: ds_device_writev_trap(device_t         device,
                   1699:                      dev_mode_t        mode,
                   1700:                      recnum_t          recnum,
                   1701:                      io_buf_vec_t      *iovec,
                   1702:                      vm_size_t         iocount)
                   1703: #endif
                   1704: {
                   1705: #ifdef i386
                   1706:        mach_device_t device = d;
                   1707: #endif
                   1708:        io_req_t ior;
                   1709:        io_return_t result;
                   1710:        io_buf_vec_t    stack_iovec[16]; /* XXX */
                   1711:        vm_size_t data_count;
                   1712:        int i;
                   1713: 
                   1714: #ifndef i386
                   1715:        /*
                   1716:         * Refuse if device is dead or not completely open.
                   1717:         */
                   1718:        if (device == DEVICE_NULL)
                   1719:                return (D_NO_SUCH_DEVICE);
                   1720: #endif
                   1721: 
                   1722:        if (device->state != DEV_STATE_OPEN)
                   1723:                return (D_NO_SUCH_DEVICE);
1.1.1.2 ! root     1724: 
1.1       root     1725:        /* XXX note that a CLOSE may proceed at any point */
1.1.1.2 ! root     1726: 
1.1       root     1727:        /*
                   1728:         * Copyin user addresses.
                   1729:         */
                   1730:        if (iocount > 16)
                   1731:                return KERN_INVALID_VALUE; /* lame */
                   1732:        copyin((char *)iovec,
                   1733:               (char *)stack_iovec,
                   1734:               iocount * sizeof(io_buf_vec_t));
                   1735:        for (data_count = 0, i = 0; i < iocount; i++)
                   1736:                data_count += stack_iovec[i].count;
                   1737: 
                   1738:        /*
                   1739:         * Get a buffer to hold the ioreq.
                   1740:         */
                   1741:        ior = ds_trap_req_alloc(device, data_count);
1.1.1.2 ! root     1742: 
1.1       root     1743:        /*
                   1744:         * Package the write request for the device driver.
                   1745:         */
                   1746: 
                   1747:        ior->io_device          = device;
                   1748:        ior->io_unit            = device->dev_number;
                   1749:        ior->io_op              = IO_WRITE | IO_CALL | IO_LOANED;
                   1750:        ior->io_mode            = mode;
                   1751:        ior->io_recnum          = recnum;
                   1752:        ior->io_data            = (io_buf_ptr_t)
                   1753:                (vm_offset_t)ior + sizeof(struct io_req);
                   1754:        ior->io_count           = data_count;
                   1755:        ior->io_total           = data_count;
                   1756:        ior->io_alloc_size      = 0;
                   1757:        ior->io_residual        = 0;
                   1758:        ior->io_error           = 0;
                   1759:        ior->io_done            = ds_trap_write_done;
                   1760:        ior->io_reply_port      = IP_NULL;      /* XXX */
                   1761:        ior->io_reply_port_type = 0;            /* XXX */
                   1762: 
                   1763:        /*
                   1764:         * Copy the data from user space.
                   1765:         */
                   1766:        if (data_count > 0) {
                   1767:                vm_offset_t p;
                   1768: 
                   1769:                p = (vm_offset_t) ior->io_data;
                   1770:                for (i = 0; i < iocount; i++) {
                   1771:                        copyin((char *) stack_iovec[i].data,
                   1772:                               (char *) p,
                   1773:                               stack_iovec[i].count);
                   1774:                        p += stack_iovec[i].count;
                   1775:                }
                   1776:        }
1.1.1.2 ! root     1777: 
1.1       root     1778:        /*
                   1779:         * The ior keeps an extra reference for the device.
                   1780:         */
                   1781:        mach_device_reference(device);
1.1.1.2 ! root     1782: 
1.1       root     1783:        /*
                   1784:         * And do the write.
                   1785:         */
                   1786:        result = (*device->dev_ops->d_write)(device->dev_number, ior);
1.1.1.2 ! root     1787: 
1.1       root     1788:        /*
                   1789:         * If the IO was queued, delay reply until it is finished.
                   1790:         */
                   1791:        if (result == D_IO_QUEUED)
                   1792:                return (MIG_NO_REPLY);
1.1.1.2 ! root     1793: 
1.1       root     1794:        /*
                   1795:         * Remove the extra reference.
                   1796:         */
                   1797:        mach_device_deallocate(device);
1.1.1.2 ! root     1798: 
        !          1799:        zfree(io_trap_zone, (vm_offset_t) ior);
1.1       root     1800:        return (result);
                   1801: }
                   1802: 
                   1803: #ifdef i386
                   1804: struct device_emulation_ops mach_device_emulation_ops =
                   1805: {
                   1806:   mach_device_reference,
                   1807:   mach_device_deallocate,
                   1808:   mach_convert_device_to_port,
                   1809:   device_open,
                   1810:   device_close,
                   1811:   device_write,
                   1812:   device_write_inband,
                   1813:   device_read,
                   1814:   device_read_inband,
                   1815:   device_set_status,
                   1816:   mach_device_get_status,
                   1817:   device_set_filter,
                   1818:   device_map,
                   1819:   ds_no_senders,
                   1820:   device_write_trap,
                   1821:   device_writev_trap
                   1822: };
                   1823: #endif

unix.superglobalmegacorp.com

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