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