|
|
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: } 166: #endif NORMA_DEVICE 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; 899: #endif lint 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; 999: #endif lint 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; 1335: #endif lint 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.