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

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

unix.superglobalmegacorp.com

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