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