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