|
|
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;
1.1.1.5 ! root 102: extern void free_skbuffs (void);
1.1.1.4 root 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)
1.1.1.5 ! root 421: const ipc_port_t reply_port;
1.1 root 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.5 ! root 541: const 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
1.1.1.5 ! root 600: device_close(mach_device_t device)
1.1 root 601: {
602: device_lock(device);
603:
604: /*
605: * If device will remain open, do nothing.
606: */
607: if (--device->open_count > 0) {
608: device_unlock(device);
609: return (D_SUCCESS);
610: }
611:
612: /*
613: * If device is being closed, do nothing.
614: */
615: if (device->state == DEV_STATE_CLOSING) {
616: device_unlock(device);
617: return (D_SUCCESS);
618: }
619:
620: /*
621: * Mark device as closing, to prevent new IO.
622: * Outstanding IO will still be in progress.
623: */
624: device->state = DEV_STATE_CLOSING;
625: device_unlock(device);
626:
627: /*
628: * ? wait for IO to end ?
629: * only if device wants to
630: */
631:
632: /*
633: * Remove the device-port association.
634: */
635: dev_port_remove(device);
636: ipc_port_dealloc_kernel(device->port);
637:
638: /*
639: * Close the device
640: */
1.1.1.5 ! root 641: (*device->dev_ops->d_close)(device->dev_number, 0);
1.1 root 642:
643: /*
644: * Finally mark it closed. If someone else is trying
645: * to open it, the open can now proceed.
646: */
647: device_lock(device);
648: device->state = DEV_STATE_INIT;
649: if (device->io_wait) {
650: device->io_wait = FALSE;
651: thread_wakeup((event_t)device);
652: }
653: device_unlock(device);
654:
655: return (D_SUCCESS);
656: }
657:
658: /*
659: * Write to a device.
660: */
661: static io_return_t
1.1.1.4 root 662: device_write(device, reply_port, reply_port_type, mode, recnum,
1.1 root 663: data, data_count, bytes_written)
1.1.1.4 root 664: mach_device_t device;
1.1.1.5 ! root 665: const ipc_port_t reply_port;
1.1 root 666: mach_msg_type_name_t reply_port_type;
667: dev_mode_t mode;
668: recnum_t recnum;
1.1.1.5 ! root 669: const io_buf_ptr_t data;
1.1 root 670: unsigned int data_count;
671: int *bytes_written; /* out */
672: {
1.1.1.4 root 673: io_req_t ior;
674: io_return_t result;
1.1 root 675:
676: if (device->state != DEV_STATE_OPEN)
677: return (D_NO_SUCH_DEVICE);
678:
679: /*
680: * XXX Need logic to reject ridiculously big requests.
681: */
682:
683: /* XXX note that a CLOSE may proceed at any point */
684:
685: /*
686: * Package the write request for the device driver
687: */
688: io_req_alloc(ior, data_count);
689:
690: ior->io_device = device;
691: ior->io_unit = device->dev_number;
692: ior->io_op = IO_WRITE | IO_CALL;
693: ior->io_mode = mode;
694: ior->io_recnum = recnum;
695: ior->io_data = data;
696: ior->io_count = data_count;
697: ior->io_total = data_count;
698: ior->io_alloc_size = 0;
699: ior->io_residual = 0;
700: ior->io_error = 0;
701: ior->io_done = ds_write_done;
702: ior->io_reply_port = reply_port;
703: ior->io_reply_port_type = reply_port_type;
704: ior->io_copy = VM_MAP_COPY_NULL;
705:
706: /*
707: * The ior keeps an extra reference for the device.
708: */
709: mach_device_reference(device);
710:
711: /*
712: * And do the write ...
713: *
714: * device_write_dealoc returns false if there's more
715: * to do; it has updated the ior appropriately and expects
716: * its caller to reinvoke it on the device.
717: */
718:
719: do {
720:
721: result = (*device->dev_ops->d_write)(device->dev_number, ior);
722:
723: /*
724: * If the IO was queued, delay reply until it is finished.
725: */
726: if (result == D_IO_QUEUED)
727: return (MIG_NO_REPLY);
728:
729: /*
730: * Discard the local mapping of the data.
731: */
732:
733: } while (!device_write_dealloc(ior));
734:
735: /*
736: * Return the number of bytes actually written.
737: */
738: *bytes_written = ior->io_total - ior->io_residual;
739:
740: /*
741: * Remove the extra reference.
742: */
743: mach_device_deallocate(device);
744:
745: io_req_free(ior);
746: return (result);
747: }
748:
749: /*
750: * Write to a device, but memory is in message.
751: */
752: static io_return_t
1.1.1.4 root 753: device_write_inband(device, reply_port, reply_port_type, mode, recnum,
1.1 root 754: data, data_count, bytes_written)
1.1.1.4 root 755: mach_device_t device;
1.1.1.5 ! root 756: const ipc_port_t reply_port;
1.1 root 757: mach_msg_type_name_t reply_port_type;
758: dev_mode_t mode;
759: recnum_t recnum;
760: io_buf_ptr_inband_t data;
761: unsigned int data_count;
762: int *bytes_written; /* out */
763: {
1.1.1.4 root 764: io_req_t ior;
765: io_return_t result;
1.1 root 766:
767: if (device->state != DEV_STATE_OPEN)
768: return (D_NO_SUCH_DEVICE);
769:
770: /* XXX note that a CLOSE may proceed at any point */
771:
772: /*
773: * Package the write request for the device driver.
774: */
775: io_req_alloc(ior, 0);
776:
777: ior->io_device = device;
778: ior->io_unit = device->dev_number;
779: ior->io_op = IO_WRITE | IO_CALL | IO_INBAND;
780: ior->io_mode = mode;
781: ior->io_recnum = recnum;
782: ior->io_data = data;
783: ior->io_count = data_count;
784: ior->io_total = data_count;
785: ior->io_alloc_size = 0;
786: ior->io_residual = 0;
787: ior->io_error = 0;
788: ior->io_done = ds_write_done;
789: ior->io_reply_port = reply_port;
790: ior->io_reply_port_type = reply_port_type;
791:
792: /*
793: * The ior keeps an extra reference for the device.
794: */
795: mach_device_reference(device);
796:
797: /*
798: * And do the write.
799: */
800: result = (*device->dev_ops->d_write)(device->dev_number, ior);
801:
802: /*
803: * If the IO was queued, delay reply until it is finished.
804: */
805: if (result == D_IO_QUEUED)
806: return (MIG_NO_REPLY);
807:
808: /*
809: * Return the number of bytes actually written.
810: */
811: *bytes_written = ior->io_total - ior->io_residual;
812:
813: /*
814: * Remove the extra reference.
815: */
816: mach_device_deallocate(device);
817:
818: io_req_free(ior);
819: return (result);
820: }
821:
822: /*
823: * Wire down incoming memory to give to device.
824: */
825: kern_return_t
1.1.1.5 ! root 826: device_write_get(
! 827: io_req_t ior,
! 828: boolean_t *wait)
1.1 root 829: {
830: vm_map_copy_t io_copy;
831: vm_offset_t new_addr;
1.1.1.4 root 832: kern_return_t result;
1.1 root 833: int bsize;
834: vm_size_t min_size;
835:
836: /*
837: * By default, caller does not have to wait.
838: */
839: *wait = FALSE;
840:
841: /*
842: * Nothing to do if no data.
843: */
844: if (ior->io_count == 0)
845: return (KERN_SUCCESS);
846:
847: /*
848: * Loaned iors already have valid data.
849: */
850: if (ior->io_op & IO_LOANED)
851: return (KERN_SUCCESS);
852:
853: /*
854: * Inband case.
855: */
856: if (ior->io_op & IO_INBAND) {
857: assert(ior->io_count <= sizeof (io_buf_ptr_inband_t));
1.1.1.4 root 858: new_addr = kmem_cache_alloc(&io_inband_cache);
859: memcpy((void*)new_addr, ior->io_data, ior->io_count);
1.1 root 860: ior->io_data = (io_buf_ptr_t)new_addr;
861: ior->io_alloc_size = sizeof (io_buf_ptr_inband_t);
862:
863: return (KERN_SUCCESS);
864: }
865:
866: /*
867: * Figure out how much data to move this time. If the device
868: * won't return a block size, then we have to do the whole
869: * request in one shot (ditto if this is a block fragment),
870: * otherwise, move at least one block's worth.
871: */
872: result = (*ior->io_device->dev_ops->d_dev_info)(
873: ior->io_device->dev_number,
874: D_INFO_BLOCK_SIZE,
875: &bsize);
876:
877: if (result != KERN_SUCCESS || ior->io_count < (vm_size_t) bsize)
878: min_size = (vm_size_t) ior->io_count;
879: else
880: min_size = (vm_size_t) bsize;
881:
882: /*
883: * Map the pages from this page list into memory.
884: * io_data records location of data.
885: * io_alloc_size is the vm size of the region to deallocate.
886: */
887: io_copy = (vm_map_copy_t) ior->io_data;
888: result = kmem_io_map_copyout(device_io_map,
889: (vm_offset_t*)&ior->io_data, &new_addr,
890: &ior->io_alloc_size, io_copy, min_size);
891: if (result != KERN_SUCCESS)
892: return (result);
893:
1.1.1.2 root 894: if ((ior->io_data + ior->io_count) >
1.1 root 895: (((char *)new_addr) + ior->io_alloc_size)) {
896:
897: /*
898: * Operation has to be split. Reset io_count for how
899: * much we can do this time.
900: */
901: assert(vm_map_copy_has_cont(io_copy));
902: assert(ior->io_count == io_copy->size);
903: ior->io_count = ior->io_alloc_size -
904: (ior->io_data - ((char *)new_addr));
905:
906: /*
907: * Caller must wait synchronously.
908: */
909: ior->io_op &= ~IO_CALL;
1.1.1.2 root 910: *wait = TRUE;
1.1 root 911: }
912:
913: ior->io_copy = io_copy; /* vm_map_copy to discard */
914: return (KERN_SUCCESS);
915: }
916:
917: /*
918: * Clean up memory allocated for IO.
919: */
920: boolean_t
1.1.1.5 ! root 921: device_write_dealloc(io_req_t ior)
1.1 root 922: {
923: vm_map_copy_t new_copy = VM_MAP_COPY_NULL;
924: vm_map_copy_t io_copy;
925: kern_return_t result;
926: vm_offset_t size_to_do;
1.1.1.2 root 927: int bsize;
1.1 root 928:
929: if (ior->io_alloc_size == 0)
930: return (TRUE);
931:
932: /*
933: * Inband case.
934: */
935: if (ior->io_op & IO_INBAND) {
1.1.1.4 root 936: kmem_cache_free(&io_inband_cache, (vm_offset_t)ior->io_data);
1.1 root 937:
938: return (TRUE);
939: }
1.1.1.2 root 940:
1.1 root 941: if ((io_copy = ior->io_copy) == VM_MAP_COPY_NULL)
942: return (TRUE);
943:
944: /*
945: * To prevent a possible deadlock with the default pager,
946: * we have to release space in the device_io_map before
947: * we allocate any memory. (Which vm_map_copy_invoke_cont
1.1.1.4 root 948: * might do.) See the discussion in mach_device_init.
1.1 root 949: */
950:
951: kmem_io_map_deallocate(device_io_map,
952: trunc_page(ior->io_data),
1.1.1.4 root 953: ior->io_alloc_size);
1.1 root 954:
955: if (vm_map_copy_has_cont(io_copy)) {
956:
957: /*
1.1.1.2 root 958: * Remember how much is left, then
1.1 root 959: * invoke or abort the continuation.
960: */
961: size_to_do = io_copy->size - ior->io_count;
962: if (ior->io_error == 0) {
963: vm_map_copy_invoke_cont(io_copy, &new_copy, &result);
964: }
965: else {
966: vm_map_copy_abort_cont(io_copy);
967: result = KERN_FAILURE;
968: }
969:
970: if (result == KERN_SUCCESS && new_copy != VM_MAP_COPY_NULL) {
1.1.1.4 root 971: int res;
1.1 root 972:
973: /*
974: * We have a new continuation, reset the ior to
975: * represent the remainder of the request. Must
976: * adjust the recnum because drivers assume
977: * that the residual is zero.
978: */
979: ior->io_op &= ~IO_DONE;
980: ior->io_op |= IO_CALL;
981:
982: res = (*ior->io_device->dev_ops->d_dev_info)(
983: ior->io_device->dev_number,
984: D_INFO_BLOCK_SIZE,
985: &bsize);
986:
987: if (res != D_SUCCESS)
988: panic("device_write_dealloc: No block size");
1.1.1.2 root 989:
1.1 root 990: ior->io_recnum += ior->io_count/bsize;
991: ior->io_count = new_copy->size;
992: }
993: else {
994:
995: /*
996: * No continuation. Add amount we didn't get
997: * to into residual.
998: */
999: ior->io_residual += size_to_do;
1000: }
1001: }
1002:
1003: /*
1004: * Clean up the state for the IO that just completed.
1005: */
1006: vm_map_copy_discard(ior->io_copy);
1007: ior->io_copy = VM_MAP_COPY_NULL;
1008: ior->io_data = (char *) new_copy;
1009:
1010: /*
1011: * Return FALSE if there's more IO to do.
1012: */
1013:
1014: return(new_copy == VM_MAP_COPY_NULL);
1015: }
1016:
1017: /*
1018: * Send write completion message to client, and discard the data.
1019: */
1020: boolean_t
1021: ds_write_done(ior)
1.1.1.5 ! root 1022: const io_req_t ior;
1.1 root 1023: {
1024: /*
1025: * device_write_dealloc discards the data that has been
1026: * written, but may decide that there is more to write.
1027: */
1028: while (!device_write_dealloc(ior)) {
1.1.1.4 root 1029: io_return_t result;
1030: mach_device_t device;
1.1 root 1031:
1032: /*
1033: * More IO to do -- invoke it.
1034: */
1035: device = ior->io_device;
1036: result = (*device->dev_ops->d_write)(device->dev_number, ior);
1037:
1038: /*
1039: * If the IO was queued, return FALSE -- not done yet.
1040: */
1041: if (result == D_IO_QUEUED)
1042: return (FALSE);
1043: }
1044:
1045: /*
1046: * Now the write is really complete. Send reply.
1047: */
1048:
1049: if (IP_VALID(ior->io_reply_port)) {
1050: (void) (*((ior->io_op & IO_INBAND) ?
1051: ds_device_write_reply_inband :
1052: ds_device_write_reply))(ior->io_reply_port,
1053: ior->io_reply_port_type,
1054: ior->io_error,
1055: (int) (ior->io_total -
1056: ior->io_residual));
1057: }
1058: mach_device_deallocate(ior->io_device);
1059:
1060: return (TRUE);
1061: }
1062:
1063: /*
1064: * Read from a device.
1065: */
1066: static io_return_t
1.1.1.4 root 1067: device_read(device, reply_port, reply_port_type, mode, recnum,
1.1 root 1068: bytes_wanted, data, data_count)
1.1.1.4 root 1069: mach_device_t device;
1.1.1.5 ! root 1070: const ipc_port_t reply_port;
1.1 root 1071: mach_msg_type_name_t reply_port_type;
1072: dev_mode_t mode;
1073: recnum_t recnum;
1074: int bytes_wanted;
1075: io_buf_ptr_t *data; /* out */
1076: unsigned int *data_count; /* out */
1077: {
1.1.1.4 root 1078: io_req_t ior;
1079: io_return_t result;
1.1 root 1080:
1081: if (device->state != DEV_STATE_OPEN)
1082: return (D_NO_SUCH_DEVICE);
1083:
1084: /* XXX note that a CLOSE may proceed at any point */
1085:
1086: /*
1087: * There must be a reply port.
1088: */
1089: if (!IP_VALID(reply_port)) {
1090: printf("ds_* invalid reply port\n");
1.1.1.4 root 1091: SoftDebugger("ds_* reply_port");
1.1 root 1092: return (MIG_NO_REPLY); /* no sense in doing anything */
1093: }
1094:
1095: /*
1096: * Package the read request for the device driver
1097: */
1098: io_req_alloc(ior, 0);
1099:
1100: ior->io_device = device;
1101: ior->io_unit = device->dev_number;
1102: ior->io_op = IO_READ | IO_CALL;
1103: ior->io_mode = mode;
1104: ior->io_recnum = recnum;
1105: ior->io_data = 0; /* driver must allocate data */
1106: ior->io_count = bytes_wanted;
1107: ior->io_alloc_size = 0; /* no data allocated yet */
1108: ior->io_residual = 0;
1109: ior->io_error = 0;
1110: ior->io_done = ds_read_done;
1111: ior->io_reply_port = reply_port;
1112: ior->io_reply_port_type = reply_port_type;
1113:
1114: /*
1115: * The ior keeps an extra reference for the device.
1116: */
1117: mach_device_reference(device);
1118:
1119: /*
1120: * And do the read.
1121: */
1122: result = (*device->dev_ops->d_read)(device->dev_number, ior);
1123:
1124: /*
1125: * If the IO was queued, delay reply until it is finished.
1126: */
1127: if (result == D_IO_QUEUED)
1128: return (MIG_NO_REPLY);
1129:
1130: /*
1131: * Return result via ds_read_done.
1132: */
1133: ior->io_error = result;
1134: (void) ds_read_done(ior);
1135: io_req_free(ior);
1136:
1137: return (MIG_NO_REPLY); /* reply has already been sent. */
1138: }
1139:
1140: /*
1141: * Read from a device, but return the data 'inband.'
1142: */
1143: static io_return_t
1.1.1.4 root 1144: device_read_inband(device, reply_port, reply_port_type, mode, recnum,
1.1 root 1145: bytes_wanted, data, data_count)
1.1.1.4 root 1146: mach_device_t device;
1.1.1.5 ! root 1147: const ipc_port_t reply_port;
1.1 root 1148: mach_msg_type_name_t reply_port_type;
1149: dev_mode_t mode;
1150: recnum_t recnum;
1151: int bytes_wanted;
1152: char *data; /* pointer to OUT array */
1153: unsigned int *data_count; /* out */
1154: {
1.1.1.4 root 1155: io_req_t ior;
1156: io_return_t result;
1.1 root 1157:
1158: if (device->state != DEV_STATE_OPEN)
1159: return (D_NO_SUCH_DEVICE);
1160:
1161: /* XXX note that a CLOSE may proceed at any point */
1162:
1163: /*
1164: * There must be a reply port.
1165: */
1166: if (!IP_VALID(reply_port)) {
1167: printf("ds_* invalid reply port\n");
1.1.1.4 root 1168: SoftDebugger("ds_* reply_port");
1.1 root 1169: return (MIG_NO_REPLY); /* no sense in doing anything */
1170: }
1171:
1172: /*
1173: * Package the read for the device driver
1174: */
1175: io_req_alloc(ior, 0);
1176:
1177: ior->io_device = device;
1178: ior->io_unit = device->dev_number;
1179: ior->io_op = IO_READ | IO_CALL | IO_INBAND;
1180: ior->io_mode = mode;
1181: ior->io_recnum = recnum;
1182: ior->io_data = 0; /* driver must allocate data */
1.1.1.2 root 1183: ior->io_count =
1.1 root 1184: ((bytes_wanted < sizeof(io_buf_ptr_inband_t)) ?
1185: bytes_wanted : sizeof(io_buf_ptr_inband_t));
1186: ior->io_alloc_size = 0; /* no data allocated yet */
1187: ior->io_residual = 0;
1188: ior->io_error = 0;
1189: ior->io_done = ds_read_done;
1190: ior->io_reply_port = reply_port;
1191: ior->io_reply_port_type = reply_port_type;
1192:
1193: /*
1194: * The ior keeps an extra reference for the device.
1195: */
1196: mach_device_reference(device);
1197:
1198: /*
1199: * Do the read.
1200: */
1201: result = (*device->dev_ops->d_read)(device->dev_number, ior);
1202:
1203: /*
1204: * If the io was queued, delay reply until it is finished.
1205: */
1206: if (result == D_IO_QUEUED)
1207: return (MIG_NO_REPLY);
1208:
1209: /*
1210: * Return result, via ds_read_done.
1211: */
1212: ior->io_error = result;
1213: (void) ds_read_done(ior);
1214: io_req_free(ior);
1215:
1216: return (MIG_NO_REPLY); /* reply has already been sent. */
1217: }
1218:
1219: /*
1220: * Allocate wired-down memory for device read.
1221: */
1.1.1.5 ! root 1222: kern_return_t device_read_alloc(
! 1223: io_req_t ior,
! 1224: vm_size_t size)
1.1 root 1225: {
1226: vm_offset_t addr;
1227: kern_return_t kr;
1228:
1229: /*
1230: * Nothing to do if no data.
1231: */
1232: if (ior->io_count == 0)
1233: return (KERN_SUCCESS);
1234:
1235: if (ior->io_op & IO_INBAND) {
1.1.1.4 root 1236: ior->io_data = (io_buf_ptr_t) kmem_cache_alloc(&io_inband_cache);
1.1 root 1237: ior->io_alloc_size = sizeof(io_buf_ptr_inband_t);
1238: } else {
1239: size = round_page(size);
1240: kr = kmem_alloc(kernel_map, &addr, size);
1241: if (kr != KERN_SUCCESS)
1242: return (kr);
1243:
1244: ior->io_data = (io_buf_ptr_t) addr;
1245: ior->io_alloc_size = size;
1246: }
1247:
1248: return (KERN_SUCCESS);
1249: }
1250:
1251: boolean_t ds_read_done(ior)
1.1.1.5 ! root 1252: const io_req_t ior;
1.1 root 1253: {
1254: vm_offset_t start_data, end_data;
1255: vm_offset_t start_sent, end_sent;
1.1.1.4 root 1256: vm_size_t size_read;
1.1 root 1257:
1258: if (ior->io_error)
1259: size_read = 0;
1260: else
1261: size_read = ior->io_count - ior->io_residual;
1262:
1263: start_data = (vm_offset_t)ior->io_data;
1264: end_data = start_data + size_read;
1265:
1266: start_sent = (ior->io_op & IO_INBAND) ? start_data :
1267: trunc_page(start_data);
1.1.1.2 root 1268: end_sent = (ior->io_op & IO_INBAND) ?
1.1 root 1269: start_data + ior->io_alloc_size : round_page(end_data);
1270:
1271: /*
1272: * Zero memory that the device did not fill.
1273: */
1274: if (start_sent < start_data)
1.1.1.5 ! root 1275: memset((void *)start_sent, 0, start_data - start_sent);
1.1 root 1276: if (end_sent > end_data)
1.1.1.5 ! root 1277: memset((void *)end_data, 0, end_sent - end_data);
1.1 root 1278:
1279:
1280: /*
1281: * Touch the data being returned, to mark it dirty.
1282: * If the pages were filled by DMA, the pmap module
1283: * may think that they are clean.
1284: */
1285: {
1.1.1.4 root 1286: vm_offset_t touch;
1287: int c;
1.1 root 1288:
1289: for (touch = start_sent; touch < end_sent; touch += PAGE_SIZE) {
1.1.1.2 root 1290: c = *(volatile char *)touch;
1291: *(volatile char *)touch = c;
1.1 root 1292: }
1293: }
1294:
1295: /*
1296: * Send the data to the reply port - this
1297: * unwires and deallocates it.
1298: */
1299: if (ior->io_op & IO_INBAND) {
1300: (void)ds_device_read_reply_inband(ior->io_reply_port,
1301: ior->io_reply_port_type,
1302: ior->io_error,
1303: (char *) start_data,
1304: size_read);
1305: } else {
1306: vm_map_copy_t copy;
1307: kern_return_t kr;
1308:
1309: kr = vm_map_copyin_page_list(kernel_map, start_data,
1310: size_read, TRUE, TRUE,
1311: ©, FALSE);
1312:
1313: if (kr != KERN_SUCCESS)
1314: panic("read_done: vm_map_copyin_page_list failed");
1315:
1316: (void)ds_device_read_reply(ior->io_reply_port,
1317: ior->io_reply_port_type,
1318: ior->io_error,
1319: (char *) copy,
1320: size_read);
1321: }
1322:
1323: /*
1324: * Free any memory that was allocated but not sent.
1325: */
1326: if (ior->io_count != 0) {
1327: if (ior->io_op & IO_INBAND) {
1328: if (ior->io_alloc_size > 0)
1.1.1.4 root 1329: kmem_cache_free(&io_inband_cache, (vm_offset_t)ior->io_data);
1.1 root 1330: } else {
1.1.1.4 root 1331: vm_offset_t end_alloc;
1.1 root 1332:
1333: end_alloc = start_sent + round_page(ior->io_alloc_size);
1334: if (end_alloc > end_sent)
1335: (void) vm_deallocate(kernel_map,
1336: end_sent,
1337: end_alloc - end_sent);
1338: }
1339: }
1340:
1341: mach_device_deallocate(ior->io_device);
1342:
1343: return (TRUE);
1344: }
1345:
1346: static io_return_t
1.1.1.5 ! root 1347: device_set_status(
! 1348: mach_device_t device,
! 1349: dev_flavor_t flavor,
! 1350: dev_status_t status,
! 1351: mach_msg_type_number_t status_count)
1.1 root 1352: {
1353: if (device->state != DEV_STATE_OPEN)
1354: return (D_NO_SUCH_DEVICE);
1355:
1356: /* XXX note that a CLOSE may proceed at any point */
1357:
1358: return ((*device->dev_ops->d_setstat)(device->dev_number,
1359: flavor,
1360: status,
1361: status_count));
1362: }
1363:
1364: io_return_t
1.1.1.5 ! root 1365: mach_device_get_status(
! 1366: mach_device_t device,
! 1367: dev_flavor_t flavor,
! 1368: dev_status_t status, /* pointer to OUT array */
! 1369: mach_msg_type_number_t *status_count) /* out */
1.1 root 1370: {
1371: if (device->state != DEV_STATE_OPEN)
1372: return (D_NO_SUCH_DEVICE);
1373:
1374: /* XXX note that a CLOSE may proceed at any point */
1375:
1376: return ((*device->dev_ops->d_getstat)(device->dev_number,
1377: flavor,
1378: status,
1379: status_count));
1380: }
1381:
1382: static io_return_t
1.1.1.4 root 1383: device_set_filter(device, receive_port, priority, filter, filter_count)
1384: mach_device_t device;
1.1.1.5 ! root 1385: const ipc_port_t receive_port;
1.1 root 1386: int priority;
1387: filter_t filter[]; /* pointer to IN array */
1388: unsigned int filter_count;
1389: {
1390: if (device->state != DEV_STATE_OPEN)
1391: return (D_NO_SUCH_DEVICE);
1392:
1393: /* XXX note that a CLOSE may proceed at any point */
1394:
1395: /*
1396: * Request is absurd if no receive port is specified.
1397: */
1398: if (!IP_VALID(receive_port))
1399: return (D_INVALID_OPERATION);
1400:
1401: return ((*device->dev_ops->d_async_in)(device->dev_number,
1402: receive_port,
1403: priority,
1404: filter,
1405: filter_count));
1406: }
1407:
1408: static io_return_t
1.1.1.5 ! root 1409: device_map(
! 1410: mach_device_t device,
! 1411: vm_prot_t protection,
! 1412: vm_offset_t offset,
! 1413: vm_size_t size,
! 1414: ipc_port_t *pager, /* out */
! 1415: boolean_t unmap) /* ? */
1.1 root 1416: {
1417: if (protection & ~VM_PROT_ALL)
1418: return (KERN_INVALID_ARGUMENT);
1419:
1420: if (device->state != DEV_STATE_OPEN)
1421: return (D_NO_SUCH_DEVICE);
1422:
1423: /* XXX note that a CLOSE may proceed at any point */
1424:
1425: return (device_pager_setup(device, protection, offset, size,
1426: (mach_port_t*)pager));
1427: }
1428:
1429: /*
1430: * Doesn't do anything (yet).
1431: */
1432: static void
1433: ds_no_senders(notification)
1.1.1.5 ! root 1434: const mach_no_senders_notification_t *notification;
1.1 root 1435: {
1.1.1.4 root 1436: printf("ds_no_senders called! device_port=0x%lx count=%d\n",
1.1 root 1437: notification->not_header.msgh_remote_port,
1438: notification->not_count);
1439: }
1440:
1441: queue_head_t io_done_list;
1442: decl_simple_lock_data(, io_done_list_lock)
1443:
1444: #define splio splsched /* XXX must block ALL io devices */
1445:
1.1.1.5 ! root 1446: void iodone(io_req_t ior)
1.1 root 1447: {
1.1.1.4 root 1448: spl_t s;
1.1 root 1449:
1450: /*
1451: * If this ior was loaned to us, return it directly.
1452: */
1453: if (ior->io_op & IO_LOANED) {
1454: (*ior->io_done)(ior);
1455: return;
1456: }
1457: /*
1458: * If !IO_CALL, some thread is waiting for this. Must lock
1459: * structure to interlock correctly with iowait(). Else can
1460: * toss on queue for io_done thread to call completion.
1461: */
1462: s = splio();
1463: if ((ior->io_op & IO_CALL) == 0) {
1464: ior_lock(ior);
1465: ior->io_op |= IO_DONE;
1466: ior->io_op &= ~IO_WANTED;
1467: ior_unlock(ior);
1468: thread_wakeup((event_t)ior);
1469: } else {
1470: ior->io_op |= IO_DONE;
1471: simple_lock(&io_done_list_lock);
1472: enqueue_tail(&io_done_list, (queue_entry_t)ior);
1473: thread_wakeup((event_t)&io_done_list);
1474: simple_unlock(&io_done_list_lock);
1475: }
1476: splx(s);
1477: }
1478:
1.1.1.5 ! root 1479: void __attribute__ ((noreturn)) io_done_thread_continue(void)
1.1 root 1480: {
1481: for (;;) {
1.1.1.4 root 1482: spl_t s;
1483: io_req_t ior;
1.1 root 1484:
1.1.1.4 root 1485: #if defined (LINUX_DEV) && defined (CONFIG_INET)
1.1 root 1486: free_skbuffs ();
1487: #endif
1488: s = splio();
1489: simple_lock(&io_done_list_lock);
1490: while ((ior = (io_req_t)dequeue_head(&io_done_list)) != 0) {
1491: simple_unlock(&io_done_list_lock);
1492: (void) splx(s);
1493:
1494: if ((*ior->io_done)(ior)) {
1495: /*
1496: * IO done - free io_req_elt
1497: */
1498: io_req_free(ior);
1499: }
1500: /* else routine has re-queued it somewhere */
1501:
1502: s = splio();
1503: simple_lock(&io_done_list_lock);
1504: }
1505:
1506: assert_wait(&io_done_list, FALSE);
1507: simple_unlock(&io_done_list_lock);
1508: (void) splx(s);
1509: counter(c_io_done_thread_block++);
1510: thread_block(io_done_thread_continue);
1511: }
1512: }
1513:
1.1.1.5 ! root 1514: void io_done_thread(void)
1.1 root 1515: {
1516: /*
1517: * Set thread privileges and highest priority.
1518: */
1519: current_thread()->vm_privilege = TRUE;
1520: stack_privilege(current_thread());
1521: thread_set_own_priority(0);
1522:
1523: io_done_thread_continue();
1524: /*NOTREACHED*/
1525: }
1526:
1.1.1.4 root 1527: #define DEVICE_IO_MAP_SIZE (16 * 1024 * 1024)
1.1 root 1528:
1.1.1.4 root 1529: static void mach_device_trap_init(void); /* forward */
1.1 root 1530:
1.1.1.5 ! root 1531: void mach_device_init(void)
1.1 root 1532: {
1533: vm_offset_t device_io_min, device_io_max;
1534:
1535: queue_init(&io_done_list);
1536: simple_lock_init(&io_done_list_lock);
1537:
1.1.1.4 root 1538: kmem_submap(device_io_map, kernel_map, &device_io_min, &device_io_max,
1539: DEVICE_IO_MAP_SIZE, FALSE);
1540:
1.1 root 1541: /*
1542: * If the kernel receives many device_write requests, the
1543: * device_io_map might run out of space. To prevent
1544: * device_write_get from failing in this case, we enable
1545: * wait_for_space on the map. This causes kmem_io_map_copyout
1546: * to block until there is sufficient space.
1547: * (XXX Large writes may be starved by small writes.)
1548: *
1549: * There is a potential deadlock problem with this solution,
1550: * if a device_write from the default pager has to wait
1551: * for the completion of a device_write which needs to wait
1552: * for memory allocation. Hence, once device_write_get
1553: * allocates space in device_io_map, no blocking memory
1554: * allocations should happen until device_write_dealloc
1555: * frees the space. (XXX A large write might starve
1556: * a small write from the default pager.)
1557: */
1558: device_io_map->wait_for_space = TRUE;
1559:
1.1.1.4 root 1560: kmem_cache_init(&io_inband_cache, "io_buf_ptr_inband",
1561: sizeof(io_buf_ptr_inband_t), 0, NULL, NULL, NULL, 0);
1.1 root 1562:
1.1.1.4 root 1563: mach_device_trap_init();
1.1 root 1564: }
1565:
1.1.1.5 ! root 1566: void iowait(io_req_t ior)
1.1 root 1567: {
1568: spl_t s;
1569:
1570: s = splio();
1571: ior_lock(ior);
1572: while ((ior->io_op&IO_DONE)==0) {
1573: assert_wait((event_t)ior, FALSE);
1574: ior_unlock(ior);
1575: thread_block((void (*)()) 0);
1576: ior_lock(ior);
1577: }
1578: ior_unlock(ior);
1579: splx(s);
1580: }
1581:
1582:
1583: /*
1584: * Device trap support.
1585: */
1586:
1587: /*
1588: * Memory Management
1589: *
1590: * This currently has a single pool of 2k wired buffers
1591: * since we only handle writes to an ethernet device.
1592: * Should be more general.
1593: */
1594: #define IOTRAP_REQSIZE 2048
1595:
1.1.1.4 root 1596: struct kmem_cache io_trap_cache;
1.1 root 1597:
1598: /*
1.1.1.4 root 1599: * Initialization. Called from mach_device_init().
1.1 root 1600: */
1.1.1.4 root 1601: static void
1602: mach_device_trap_init(void)
1.1 root 1603: {
1.1.1.4 root 1604: kmem_cache_init(&io_trap_cache, "io_req", IOTRAP_REQSIZE, 0,
1605: NULL, NULL, NULL, 0);
1.1 root 1606: }
1607:
1608: /*
1609: * Allocate an io_req_t.
1.1.1.4 root 1610: * Currently allocates from io_trap_cache.
1.1 root 1611: *
1.1.1.4 root 1612: * Could have lists of different size caches.
1.1 root 1613: * Could call a device-specific routine.
1614: */
1615: io_req_t
1.1.1.5 ! root 1616: ds_trap_req_alloc(const mach_device_t device, vm_size_t data_size)
1.1 root 1617: {
1.1.1.4 root 1618: return (io_req_t) kmem_cache_alloc(&io_trap_cache);
1.1 root 1619: }
1620:
1621: /*
1622: * Called by iodone to release ior.
1623: */
1624: boolean_t
1.1.1.5 ! root 1625: ds_trap_write_done(const io_req_t ior)
1.1 root 1626: {
1.1.1.4 root 1627: mach_device_t dev;
1.1 root 1628:
1629: dev = ior->io_device;
1630:
1631: /*
1632: * Should look at reply port and maybe send a message.
1633: */
1.1.1.4 root 1634: kmem_cache_free(&io_trap_cache, (vm_offset_t) ior);
1.1.1.2 root 1635:
1.1 root 1636: /*
1637: * Give up device reference from ds_write_trap.
1638: */
1639: mach_device_deallocate(dev);
1640: return TRUE;
1641: }
1642:
1643: /*
1644: * Like device_write except that data is in user space.
1645: */
1646: static io_return_t
1.1.1.4 root 1647: device_write_trap (mach_device_t device, dev_mode_t mode,
1.1 root 1648: recnum_t recnum, vm_offset_t data, vm_size_t data_count)
1649: {
1650: io_req_t ior;
1651: io_return_t result;
1652:
1653: if (device->state != DEV_STATE_OPEN)
1654: return (D_NO_SUCH_DEVICE);
1.1.1.2 root 1655:
1.1 root 1656: /* XXX note that a CLOSE may proceed at any point */
1.1.1.2 root 1657:
1.1 root 1658: /*
1659: * Get a buffer to hold the ioreq.
1660: */
1661: ior = ds_trap_req_alloc(device, data_count);
1.1.1.2 root 1662:
1.1 root 1663: /*
1664: * Package the write request for the device driver.
1665: */
1666:
1667: ior->io_device = device;
1668: ior->io_unit = device->dev_number;
1669: ior->io_op = IO_WRITE | IO_CALL | IO_LOANED;
1670: ior->io_mode = mode;
1671: ior->io_recnum = recnum;
1672: ior->io_data = (io_buf_ptr_t)
1673: (vm_offset_t)ior + sizeof(struct io_req);
1674: ior->io_count = data_count;
1675: ior->io_total = data_count;
1676: ior->io_alloc_size = 0;
1677: ior->io_residual = 0;
1678: ior->io_error = 0;
1679: ior->io_done = ds_trap_write_done;
1680: ior->io_reply_port = IP_NULL; /* XXX */
1681: ior->io_reply_port_type = 0; /* XXX */
1682:
1683: /*
1684: * Copy the data from user space.
1685: */
1686: if (data_count > 0)
1.1.1.5 ! root 1687: copyin((void *)data, ior->io_data, data_count);
1.1.1.2 root 1688:
1.1 root 1689: /*
1690: * The ior keeps an extra reference for the device.
1691: */
1692: mach_device_reference(device);
1.1.1.2 root 1693:
1.1 root 1694: /*
1695: * And do the write.
1696: */
1697: result = (*device->dev_ops->d_write)(device->dev_number, ior);
1.1.1.2 root 1698:
1.1 root 1699: /*
1700: * If the IO was queued, delay reply until it is finished.
1701: */
1702: if (result == D_IO_QUEUED)
1703: return (MIG_NO_REPLY);
1.1.1.2 root 1704:
1.1 root 1705: /*
1706: * Remove the extra reference.
1707: */
1708: mach_device_deallocate(device);
1.1.1.2 root 1709:
1.1.1.4 root 1710: kmem_cache_free(&io_trap_cache, (vm_offset_t) ior);
1.1 root 1711: return (result);
1712: }
1713:
1714: static io_return_t
1.1.1.4 root 1715: device_writev_trap (mach_device_t device, dev_mode_t mode,
1.1 root 1716: recnum_t recnum, io_buf_vec_t *iovec, vm_size_t iocount)
1717: {
1718: io_req_t ior;
1719: io_return_t result;
1720: io_buf_vec_t stack_iovec[16]; /* XXX */
1721: vm_size_t data_count;
1722: int i;
1723:
1724: if (device->state != DEV_STATE_OPEN)
1725: return (D_NO_SUCH_DEVICE);
1.1.1.2 root 1726:
1.1 root 1727: /* XXX note that a CLOSE may proceed at any point */
1.1.1.2 root 1728:
1.1 root 1729: /*
1730: * Copyin user addresses.
1731: */
1732: if (iocount > 16)
1733: return KERN_INVALID_VALUE; /* lame */
1.1.1.5 ! root 1734: copyin(iovec,
! 1735: stack_iovec,
1.1 root 1736: iocount * sizeof(io_buf_vec_t));
1737: for (data_count = 0, i = 0; i < iocount; i++)
1738: data_count += stack_iovec[i].count;
1739:
1740: /*
1741: * Get a buffer to hold the ioreq.
1742: */
1743: ior = ds_trap_req_alloc(device, data_count);
1.1.1.2 root 1744:
1.1 root 1745: /*
1746: * Package the write request for the device driver.
1747: */
1748:
1749: ior->io_device = device;
1750: ior->io_unit = device->dev_number;
1751: ior->io_op = IO_WRITE | IO_CALL | IO_LOANED;
1752: ior->io_mode = mode;
1753: ior->io_recnum = recnum;
1754: ior->io_data = (io_buf_ptr_t)
1755: (vm_offset_t)ior + sizeof(struct io_req);
1756: ior->io_count = data_count;
1757: ior->io_total = data_count;
1758: ior->io_alloc_size = 0;
1759: ior->io_residual = 0;
1760: ior->io_error = 0;
1761: ior->io_done = ds_trap_write_done;
1762: ior->io_reply_port = IP_NULL; /* XXX */
1763: ior->io_reply_port_type = 0; /* XXX */
1764:
1765: /*
1766: * Copy the data from user space.
1767: */
1768: if (data_count > 0) {
1769: vm_offset_t p;
1770:
1771: p = (vm_offset_t) ior->io_data;
1772: for (i = 0; i < iocount; i++) {
1.1.1.5 ! root 1773: copyin((void *) stack_iovec[i].data,
! 1774: (void *) p,
1.1 root 1775: stack_iovec[i].count);
1776: p += stack_iovec[i].count;
1777: }
1778: }
1.1.1.2 root 1779:
1.1 root 1780: /*
1781: * The ior keeps an extra reference for the device.
1782: */
1783: mach_device_reference(device);
1.1.1.2 root 1784:
1.1 root 1785: /*
1786: * And do the write.
1787: */
1788: result = (*device->dev_ops->d_write)(device->dev_number, ior);
1.1.1.2 root 1789:
1.1 root 1790: /*
1791: * If the IO was queued, delay reply until it is finished.
1792: */
1793: if (result == D_IO_QUEUED)
1794: return (MIG_NO_REPLY);
1.1.1.2 root 1795:
1.1 root 1796: /*
1797: * Remove the extra reference.
1798: */
1799: mach_device_deallocate(device);
1.1.1.2 root 1800:
1.1.1.4 root 1801: kmem_cache_free(&io_trap_cache, (vm_offset_t) ior);
1.1 root 1802: return (result);
1803: }
1804:
1805: struct device_emulation_ops mach_device_emulation_ops =
1806: {
1.1.1.4 root 1807: (void*) mach_device_reference,
1808: (void*) mach_device_deallocate,
1809: (void*) mach_convert_device_to_port,
1.1 root 1810: device_open,
1811: device_close,
1812: device_write,
1813: device_write_inband,
1814: device_read,
1815: device_read_inband,
1816: device_set_status,
1817: mach_device_get_status,
1818: device_set_filter,
1819: device_map,
1820: ds_no_senders,
1.1.1.4 root 1821: (void*) device_write_trap,
1822: (void*) device_writev_trap
1.1 root 1823: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.