|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* IOStub.m 1.0 01/29/91 (c) 1991 NeXT ! 25: * ! 26: * IOStub.m - Implementation for trivial I/O device subclass. ! 27: * ! 28: * HISTORY ! 29: * 29-Jan-91 Doug Mitchell at NeXT ! 30: * Created. ! 31: */ ! 32: ! 33: #import <bsd/sys/types.h> ! 34: #import <mach/mach.h> ! 35: #import <mach/vm_param.h> ! 36: #import <mach/mach_error.h> ! 37: #import <bsd/libc.h> ! 38: #import <driverkit/return.h> ! 39: #import <driverkit/IODevice.h> ! 40: #import "IOStub.h" ! 41: #import "IOStubThread.h" ! 42: #import "IOStubDevice.h" ! 43: #import "IOStubUxpr.h" ! 44: #import <machkit/NXLock.h> ! 45: ! 46: @implementation IOStub ! 47: ! 48: /* ! 49: * Initialize current instance. Returns non-zero on error. ! 50: */ ! 51: - initStub : (int)unitNum ! 52: { ! 53: int data_size; ! 54: int i; ! 55: char *cp; ! 56: kern_return_t krtn; ! 57: u_int block_size, dev_size; ! 58: ! 59: xpr_stub("IOStub : init: unitNum %d\n", unitNum, 2,3,4,5); ! 60: ! 61: ! 62: [self setUnit:unitNum]; ! 63: if(unitNum == 0) { ! 64: /* ! 65: * read/write. ! 66: */ ! 67: block_size = 0x20; ! 68: dev_size = 0x1000; ! 69: [self setName : "IOStub0"]; ! 70: [self setWriteProtected:NO]; ! 71: } ! 72: else { ! 73: /* ! 74: * Make this one read-only, non-queuing. ! 75: */ ! 76: block_size = 0x40; ! 77: dev_size = 0x800; ! 78: [self setName : "IOStub1"]; ! 79: [self setWriteProtected:YES]; ! 80: } ! 81: [self setDeviceKind:"Stub Device"]; ! 82: [self setLocation:NULL]; ! 83: [self setDiskSize:dev_size]; ! 84: [self setBlockSize:block_size]; ! 85: [self setFormattedInternal:1]; ! 86: ! 87: /* ! 88: * allocate and initialize data for writing and reading. ! 89: */ ! 90: data_size = block_size * dev_size; ! 91: krtn = vm_allocate(task_self(), ! 92: (vm_address_t *)&stub_data, ! 93: (vm_size_t)round_page(data_size), ! 94: YES); ! 95: if(krtn != KERN_SUCCESS) { ! 96: mach_error("***IOStub init: vm_allocate", krtn); ! 97: return(self); ! 98: } ! 99: ! 100: /* ! 101: * initial data: incrementing bytes for unit 0, decrementing ! 102: * bytes for others. ! 103: */ ! 104: cp = (char *)stub_data; ! 105: for(i=0; i<data_size; i++) { ! 106: if(unitNum) ! 107: *cp++ = 0 - (char)i; ! 108: else ! 109: *cp++ = i; ! 110: } ! 111: ! 112: /* ! 113: * Set up our instance's IOQueue. ! 114: */ ! 115: ioQLock = [NXConditionLock alloc]; ! 116: [ioQLock initWith:NO_WORK_AVAILABLE]; ! 117: queue_init(&ioQueue); ! 118: ! 119: /* ! 120: * Start up an I/O thread to perform the actual work of this device. ! 121: */ ! 122: IOForkThread((IOThreadFunc)IOStub_thread, self); ! 123: ! 124: [self registerDevice]; ! 125: ! 126: /* ! 127: * Let superclass take care of initializing inherited instance ! 128: * variables. ! 129: */ ! 130: [super init]; ! 131: return self; ! 132: } ! 133: ! 134: /* ! 135: * Free resources consumed by this instance. ! 136: */ ! 137: - free ! 138: { ! 139: int data_size; ! 140: kern_return_t krtn; ! 141: u_int block_size, dev_size; ! 142: IOBuf_t *IOBuf; ! 143: ! 144: /* ! 145: * Kill the I/O thread. ! 146: */ ! 147: IOBuf = IOMalloc(sizeof(*IOBuf)); ! 148: IOBuf->cmd = STUB_ABORT; ! 149: IOBuf->pending = 0; ! 150: IOBuf->waitLock = [NXConditionLock alloc]; ! 151: [IOBuf->waitLock initWith:NO]; ! 152: [self enqueueIoBuf:IOBuf]; ! 153: ! 154: /* ! 155: * Wait for I/O complete. ! 156: */ ! 157: [IOBuf->waitLock lockWhen:YES]; ! 158: [IOBuf->waitLock unlock]; ! 159: [IOBuf->waitLock free]; ! 160: IOFree(IOBuf, sizeof(IOBuf_t)); ! 161: ! 162: /* ! 163: * Free up our VM. ! 164: */ ! 165: block_size = [self blockSize]; ! 166: dev_size = [self diskSize]; ! 167: data_size = block_size * dev_size; ! 168: krtn = vm_deallocate(task_self(), ! 169: (vm_address_t)stub_data, ! 170: (vm_size_t)round_page(data_size)); ! 171: if(krtn != KERN_SUCCESS) { ! 172: mach_error("***IOStub free: vm_deallocate", krtn); ! 173: } ! 174: return([super free]); ! 175: } ! 176: ! 177: /* ! 178: * These override the superclass's methods which are no-op stubs. ! 179: */ ! 180: ! 181: - (int)deviceOpen:(u_int)intentions ! 182: { ! 183: xpr_stub("IOStub deviceOpen: unit %d\n", [self unit], 2,3,4,5); ! 184: return(IO_R_SUCCESS); ! 185: } ! 186: ! 187: - (void)deviceClose ! 188: { ! 189: xpr_stub("IOStub deviceClose: unit %d\n", [self unit], 2,3,4,5); ! 190: } ! 191: ! 192: /* ! 193: * These are the exported I/O methods, from the ! 194: * IODiskDeviceReadingAndWriting category. Their main task is: ! 195: * ! 196: * -- verify valid input parameters. ! 197: * -- set up and enqueue an IOBuf for servicing by the I/O thread. ! 198: * -- Wait for I/O complete if synchronous request. ! 199: */ ! 200: ! 201: - (IOReturn) readAt : (unsigned)offset ! 202: length : (unsigned)length ! 203: buffer : (unsigned char *)buffer ! 204: actualLength : (unsigned *)actualLength ! 205: { ! 206: IOReturn mrtn; ! 207: char *source; ! 208: IOBuf_t *IOBuf; ! 209: u_int block_size; ! 210: u_int dev_size; ! 211: ! 212: xpr_stub("IOStub read: unit %d offset 0x%x length 0x%x\n", ! 213: [self unit], offset, length, 4,5); ! 214: ! 215: block_size = [self blockSize]; ! 216: dev_size = [self diskSize]; ! 217: ! 218: /* ! 219: * Verify legal parameters. ! 220: */ ! 221: source = stub_data + offset * block_size; ! 222: if((source + length) > (stub_data + (block_size * dev_size))) { ! 223: ! 224: xpr_stub("IOStub read: invalid offset/byte count\n", ! 225: 1,2,3,4,5); ! 226: return(IO_R_INVALID_ARG); ! 227: } ! 228: ! 229: /* ! 230: * OK, queue up an IOBuf. ! 231: */ ! 232: IOBuf = IOMalloc(sizeof(*IOBuf)); ! 233: IOBuf->cmd = STUB_READ; ! 234: IOBuf->offset = offset; ! 235: IOBuf->bytesReq = length; ! 236: IOBuf->buf = buffer; ! 237: IOBuf->bytesXfr = actualLength; ! 238: IOBuf->status = IO_R_INVALID; ! 239: IOBuf->pending = 0; ! 240: IOBuf->waitLock = [NXConditionLock alloc]; ! 241: [IOBuf->waitLock initWith:NO]; ! 242: IOBuf->dirRead = 1; ! 243: [self enqueueIoBuf:IOBuf]; ! 244: ! 245: /* ! 246: * Wait for I/O complete. ! 247: */ ! 248: [IOBuf->waitLock lockWhen:YES]; ! 249: [IOBuf->waitLock unlock]; ! 250: xpr_stub("stub read: DONE\n", 1,2,3,4,5); ! 251: mrtn = IOBuf->status; ! 252: [IOBuf->waitLock free]; ! 253: IOFree(IOBuf, sizeof(*IOBuf)); ! 254: return(mrtn); ! 255: } ! 256: ! 257: - (IOReturn) readAsyncAt : (unsigned)offset ! 258: length : (unsigned)length ! 259: buffer : (unsigned char *)buffer ! 260: pending : (void *)pending ! 261: { ! 262: char *source; ! 263: IOBuf_t *IOBuf; ! 264: unsigned block_size; ! 265: unsigned dev_size; ! 266: ! 267: xpr_stub("IOStub readAsync: unit %d offset 0x%x length 0x%x\n", ! 268: [self unit], offset, length, 4,5); ! 269: ! 270: block_size = [self blockSize]; ! 271: dev_size = [self diskSize]; ! 272: ! 273: /* ! 274: * Verify legal parameters. ! 275: */ ! 276: source = stub_data + offset * block_size; ! 277: if((source + length) > (stub_data + (block_size * dev_size))) { ! 278: ! 279: xpr_stub("IOStub read: invalid offset/byte count\n", ! 280: 1,2,3,4,5); ! 281: return(IO_R_INVALID_ARG); ! 282: } ! 283: ! 284: /* ! 285: * Just queue up an IOBuf. ! 286: */ ! 287: IOBuf = IOMalloc(sizeof(*IOBuf)); ! 288: IOBuf->cmd = STUB_READ; ! 289: IOBuf->offset = offset; ! 290: IOBuf->bytesReq = length; ! 291: IOBuf->buf = buffer; ! 292: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 293: * I/O thread */ ! 294: IOBuf->pending = pending; ! 295: IOBuf->dirRead = 1; ! 296: [self enqueueIoBuf:IOBuf]; ! 297: ! 298: xpr_stub("stub readAsync: DONE\n", 1,2,3,4,5); ! 299: return(IO_R_SUCCESS); ! 300: } ! 301: ! 302: - (IOReturn) writeAt : (unsigned)offset ! 303: length : (unsigned)length ! 304: buffer : (unsigned char *)buffer ! 305: actualLength : (unsigned *)actualLength ! 306: { ! 307: IOReturn mrtn; ! 308: char *dest; ! 309: IOBuf_t *IOBuf; ! 310: unsigned block_size; ! 311: unsigned dev_size; ! 312: ! 313: xpr_stub("IOStub write: unit %d offset 0x%x length 0x%x\n", ! 314: [self unit], offset, length, 4,5); ! 315: ! 316: block_size = [self blockSize]; ! 317: dev_size = [self diskSize]; ! 318: ! 319: /* ! 320: * Verify legal parameters. ! 321: */ ! 322: if([self isWriteProtected]) { ! 323: return IO_R_NOT_WRITABLE; ! 324: } ! 325: dest = stub_data + offset * block_size; ! 326: if((dest + length) > (stub_data + (block_size * dev_size))) { ! 327: ! 328: xpr_stub("IOStub dest: invalid offset/byte count\n", ! 329: 1,2,3,4,5); ! 330: return(IO_R_INVALID_ARG); ! 331: } ! 332: ! 333: /* ! 334: * OK, queue up an IOBuf. ! 335: */ ! 336: IOBuf = IOMalloc(sizeof(*IOBuf)); ! 337: IOBuf->cmd = STUB_WRITE; ! 338: IOBuf->offset = offset; ! 339: IOBuf->bytesReq = length; ! 340: IOBuf->buf = buffer; ! 341: IOBuf->bytesXfr = actualLength; ! 342: IOBuf->status = IO_R_INVALID; ! 343: IOBuf->pending = 0; ! 344: IOBuf->waitLock = [NXConditionLock alloc]; ! 345: [IOBuf->waitLock initWith:NO]; ! 346: IOBuf->dirRead = 0; ! 347: [self enqueueIoBuf:IOBuf]; ! 348: ! 349: /* ! 350: * Wait for I/O complete. ! 351: */ ! 352: [IOBuf->waitLock lockWhen:YES]; ! 353: [IOBuf->waitLock unlock]; ! 354: xpr_stub("stub write: DONE\n", 1,2,3,4,5); ! 355: mrtn = IOBuf->status; ! 356: [IOBuf->waitLock free]; ! 357: IOFree(IOBuf, sizeof(*IOBuf)); ! 358: return(mrtn); ! 359: } ! 360: ! 361: - (IOReturn) writeAsyncAt : (unsigned)offset ! 362: length : (unsigned)length ! 363: buffer : (unsigned char *)buffer ! 364: pending : (void *)pending; ! 365: { ! 366: char *source; ! 367: IOBuf_t *IOBuf; ! 368: unsigned block_size; ! 369: unsigned dev_size; ! 370: ! 371: xpr_stub("IOStub writeAsync: unit %d offset 0x%x length 0x%x\n", ! 372: [self unit], offset, length, 4,5); ! 373: ! 374: block_size = [self blockSize]; ! 375: dev_size = [self diskSize]; ! 376: ! 377: /* ! 378: * Verify legal parameters. ! 379: */ ! 380: if([self isWriteProtected]) { ! 381: return IO_R_NOT_WRITABLE; ! 382: } ! 383: source = stub_data + offset * block_size; ! 384: if((source + length) > (stub_data + (block_size * dev_size))) { ! 385: ! 386: xpr_stub("IOStub write: invalid offset/byte count\n", ! 387: 1,2,3,4,5); ! 388: return(IO_R_INVALID_ARG); ! 389: } ! 390: ! 391: /* ! 392: * Just queue up an IOBuf. ! 393: */ ! 394: IOBuf = IOMalloc(sizeof(*IOBuf)); ! 395: IOBuf->cmd = STUB_WRITE; ! 396: IOBuf->offset = offset; ! 397: IOBuf->bytesReq = length; ! 398: IOBuf->buf = buffer; ! 399: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 400: * I/O thread */ ! 401: IOBuf->pending = pending; ! 402: IOBuf->dirRead = 0; ! 403: [self enqueueIoBuf:IOBuf]; ! 404: ! 405: xpr_stub("stub writeAsync: DONE\n", 1,2,3,4,5); ! 406: return(IO_R_SUCCESS); ! 407: } ! 408: ! 409: /* ! 410: * Distributed Objects R/W protocol. ! 411: */ ! 412: - (IOReturn) readAt : (unsigned)offset // in blocks ! 413: length : (unsigned)length // in bytes ! 414: data : (out IOData **)data ! 415: actualLength : (out unsigned *)actualLength ! 416: { ! 417: IOReturn rtn; ! 418: IOData *ldata = [[IOData alloc] initWithSize:length]; ! 419: ! 420: /* ! 421: * FIXME - when freeFlag is set to YES (which is what we really ! 422: * want), this method crashes with the following error messages ! 423: * when run with the DiskTest app: ! 424: * ! 425: * finishEncoding: send error -101:invalid memory ! 426: * uncaught exception : 11001 ! 427: * objc: FREED(id): message free sent to freed object=0x9c01c ! 428: * ! 429: * When run with the test programs in ../tests, everything works ! 430: * OK... ! 431: * ! 432: * When we set freeFlag to NO, everything works, but the IOStub ! 433: * server leaks memory. ! 434: * ! 435: * Update 15-Oct-92 - this error only happens when moving at least ! 436: * one entire page of data. Moving less than a page is OK. ! 437: */ ! 438: [ldata setFreeFlag:YES]; ! 439: rtn = [self readAt:offset ! 440: length:length ! 441: buffer:[ldata data] ! 442: actualLength:actualLength]; ! 443: if(*actualLength) { ! 444: *data = ldata; ! 445: } ! 446: ! 447: /* ! 448: * FIXME - when does the IOData get deallocated?? ! 449: */ ! 450: return rtn; ! 451: } ! 452: ! 453: /* ! 454: * DiskRwDistributed protocol. ! 455: */ ! 456: - (IOData *)rreadAt : (unsigned)offset ! 457: length : (unsigned)length ! 458: rtn : (out IOReturn *)rtn ! 459: actualLength : (out unsigned *)actualLength ! 460: { ! 461: IOReturn lrtn; ! 462: IOData *ldata = [[IOData alloc] initWithSize:length]; ! 463: ! 464: [ldata setFreeFlag:YES]; ! 465: lrtn = [self readAt:offset ! 466: length:length ! 467: buffer:[ldata data] ! 468: actualLength:actualLength]; ! 469: *rtn = lrtn; ! 470: return ldata; ! 471: } ! 472: ! 473: - (IOReturn) readAsyncAt : (unsigned)offset ! 474: length : (unsigned)length ! 475: ioKey : (unsigned)ioKey ! 476: caller : (id)caller ! 477: { ! 478: /* TBD */ ! 479: return IO_R_UNSUPPORTED; ! 480: } ! 481: ! 482: ! 483: - (IOReturn) writeAt : (unsigned)offset // in blocks ! 484: length : (unsigned)length // in bytes ! 485: data : (in IOData *)data ! 486: actualLength : (out unsigned *)actualLength ! 487: { ! 488: IOReturn rtn; ! 489: ! 490: if([data size] < length) { ! 491: IOLog("%s writeAt: insufficient memory in IOData\n", ! 492: [self name]); ! 493: } ! 494: rtn = [self writeAt:offset ! 495: length:length ! 496: buffer:[data data] ! 497: actualLength:actualLength]; ! 498: [data free]; ! 499: return rtn; ! 500: } ! 501: ! 502: - (IOReturn)writeAsyncAt : (unsigned)offset // in blocks ! 503: length : (unsigned)length // in bytes ! 504: data : (in IOData *)data ! 505: ioKey : (unsigned)ioKey ! 506: caller : (id)caller ! 507: { ! 508: return IO_R_UNSUPPORTED; ! 509: } ! 510: @end ! 511:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.