|
|
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, ¬ify);
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: ©, 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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.