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

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

unix.superglobalmegacorp.com

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