|
|
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: /* unixDiskPrivate.m 1.0 02/07/91 (c) 1991 NeXT ! 25: * ! 26: * unixDiskPrivate.m - unixDisk Private methods. ! 27: * ! 28: * HISTORY ! 29: * 07-Feb-91 Doug Mitchell at NeXT ! 30: * Created. ! 31: */ ! 32: ! 33: #import <bsd/sys/types.h> ! 34: #import <mach/cthreads.h> ! 35: #import <bsd/libc.h> ! 36: #import <bsd/sys/file.h> ! 37: #import <driverkit/IODevice.h> ! 38: #import "unixDisk.h" ! 39: #import "unixThread.h" ! 40: #import "unixDiskPrivate.h" ! 41: #import <bsd/dev/disk.h> ! 42: #import "unixDiskUxpr.h" ! 43: #import <errno.h> ! 44: #import <driverkit/generalFuncs.h> ! 45: #import <machkit/NXLock.h> ! 46: ! 47: @implementation unixDisk(Private) ! 48: ! 49: /* ! 50: * readCommon: and writeCommon: are invoked by the exported flavors of ! 51: * read: and write:. ! 52: */ ! 53: - (IOReturn) readCommon : (u_int)block ! 54: length : (u_int)length ! 55: buffer : (void *)bufp ! 56: actualLength : (u_int *)actualLength /* returned */ ! 57: pending : (void *)pending ! 58: caller : (id)caller ! 59: IOBufRtn : (IOBuf_t **)IOBufRtn ! 60: { ! 61: IOReturn mrtn; ! 62: IOBuf_t *IOBuf; ! 63: u_int block_size, dev_size; ! 64: ! 65: /* ! 66: * We have to 'fault in' a possible non-present disk in ! 67: * order to get its physical parameters... ! 68: */ ! 69: mrtn = [self isDiskReady:TRUE]; ! 70: switch(mrtn) { ! 71: case IO_R_SUCCESS: ! 72: break; ! 73: case IO_R_NO_DISK: ! 74: xpr_err("%s readCommon: disk not present\n", ! 75: [self name], 2,3,4,5); ! 76: return(mrtn); ! 77: default: ! 78: IOLog("%s readCommon: bogus return from isDiskReady" ! 79: " (%s)\n", ! 80: [self name], [self stringFromReturn:mrtn]); ! 81: return(mrtn); ! 82: } ! 83: if(![self isFormatted]) ! 84: return(IO_R_UNFORMATTED); ! 85: ! 86: /* ! 87: * Verify legal parameters. ! 88: */ ! 89: block_size = [self blockSize]; ! 90: dev_size = [self diskSize]; ! 91: if(block >= dev_size) { ! 92: xpr_ud("unixDisk readCommon: invalid " ! 93: "deviceBlock/byte count\n", 1,2,3,4,5); ! 94: return(IO_R_INVALID_ARG); ! 95: } ! 96: ! 97: if(length % block_size) { ! 98: xpr_ud("unixDisk readCommon: byteCount not block_size " ! 99: "multiple\n", 1,2,3,4,5); ! 100: return(IO_R_INVALID_ARG); ! 101: } ! 102: ! 103: /* ! 104: * Queue up an IOBuf. ! 105: */ ! 106: IOBuf = [self allocIOBuf]; ! 107: IOBuf->command = @selector(unixDeviceRead:threadNum:); ! 108: IOBuf->offset = block; ! 109: IOBuf->bytesReq = length; ! 110: IOBuf->buf = bufp; ! 111: IOBuf->bytesXfr = actualLength; ! 112: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 113: * I/O thread */ ! 114: IOBuf->pending = pending; ! 115: IOBuf->caller = caller; ! 116: IOBuf->device = self; ! 117: IOBuf->dirRead = 1; ! 118: *IOBufRtn = IOBuf; ! 119: if(!pending) { ! 120: IOBuf->wait_lock = [NXConditionLock alloc]; ! 121: [IOBuf->wait_lock initWith:FALSE]; ! 122: } ! 123: else { ! 124: IOBuf->wait_lock = nil; ! 125: } ! 126: [self enqueueIoBuf:IOBuf needs_disk:TRUE]; ! 127: return(IO_R_SUCCESS); ! 128: } ! 129: ! 130: - (IOReturn) writeCommon : (u_int)block ! 131: length : (u_int)length ! 132: buffer : (void *)bufp ! 133: actualLength : (u_int *)actualLength /* returned */ ! 134: pending : (void *)pending ! 135: caller : (id)caller // for DO only ! 136: IOBufRtn : (IOBuf_t **)IOBufRtn ! 137: { ! 138: IOReturn mrtn; ! 139: IOBuf_t *IOBuf; ! 140: u_int block_size, dev_size; ! 141: ! 142: /* ! 143: * We have to 'fault in' a possible non-present disk in ! 144: * order to get its physical parameters... ! 145: */ ! 146: mrtn = [self isDiskReady:TRUE]; ! 147: switch(mrtn) { ! 148: case IO_R_SUCCESS: ! 149: break; ! 150: case IO_R_NO_DISK: ! 151: xpr_err("%s writeCommon: disk not present\n", ! 152: [self name], 2,3,4,5); ! 153: return(mrtn); ! 154: default: ! 155: IOLog("%s writeCommon: bogus return from isDiskReady" ! 156: " (%s)\n", ! 157: [self name], [self stringFromReturn:mrtn]); ! 158: return(mrtn); ! 159: } ! 160: ! 161: /* ! 162: * Verify access and legal parameters. ! 163: */ ! 164: if([self isWriteProtected]) { ! 165: return IO_R_NOT_WRITABLE; ! 166: } ! 167: block_size = [self blockSize]; ! 168: dev_size = [self diskSize]; ! 169: if(block >= dev_size) { ! 170: xpr_ud("unixDisk writeCommon: invalid " ! 171: "deviceBlock/byte count\n", 1,2,3,4,5); ! 172: return(IO_R_INVALID_ARG); ! 173: } ! 174: if(length % block_size) { ! 175: xpr_ud("unixDisk writeCommon: byteCount not block_size " ! 176: "multiple\n", 1,2,3,4,5); ! 177: return(IO_R_INVALID_ARG); ! 178: } ! 179: ! 180: /* ! 181: * Queue up an IOBuf. ! 182: */ ! 183: IOBuf = [self allocIOBuf]; ! 184: IOBuf->command = @selector(unixDeviceWrite:threadNum:); ! 185: IOBuf->offset = block; ! 186: IOBuf->bytesReq = length; ! 187: IOBuf->buf = bufp; ! 188: IOBuf->bytesXfr = actualLength; ! 189: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 190: * I/O thread */ ! 191: IOBuf->pending = pending; ! 192: IOBuf->caller = caller; ! 193: IOBuf->device = self; ! 194: IOBuf->dirRead = 1; ! 195: *IOBufRtn = IOBuf; ! 196: if(!pending) { ! 197: IOBuf->wait_lock = [NXConditionLock alloc]; ! 198: [IOBuf->wait_lock initWith:FALSE]; ! 199: } ! 200: else { ! 201: IOBuf->wait_lock = nil; ! 202: } ! 203: [self enqueueIoBuf:IOBuf needs_disk:TRUE]; ! 204: return(IO_R_SUCCESS); ! 205: } ! 206: ! 207: - (IOBuf_t *)allocIOBuf ! 208: { ! 209: return(IOMalloc(sizeof(IOBuf_t))); ! 210: } ! 211: ! 212: - (void)freeIOBuf:(IOBuf_t *)IOBuf ! 213: { ! 214: if(IOBuf->wait_lock != nil) { ! 215: /* ! 216: * This was used for async I/O; free these resources... ! 217: */ ! 218: [IOBuf->wait_lock free]; ! 219: } ! 220: IOFree(IOBuf, sizeof(*IOBuf)); ! 221: } ! 222: ! 223: /* ! 224: * Wakeup thread waiting on IOBuf. ! 225: */ ! 226: - (void)IOBufDone : (IOBuf_t *)IOBuf ! 227: status : (IOReturn)status ! 228: { ! 229: [IOBuf->wait_lock lock]; ! 230: IOBuf->status = status; ! 231: [IOBuf->wait_lock unlockWith:TRUE]; ! 232: } ! 233: ! 234: /* ! 235: * These methods are invoked by a unix_thread; they do the actual work of ! 236: * reading and writing. ! 237: */ ! 238: - (void)unixDeviceRead : (IOBuf_t *)IOBuf ! 239: threadNum:(int)threadNum ! 240: { ! 241: int rtn; ! 242: int position; ! 243: IOReturn status; ! 244: u_int block_size; ! 245: ! 246: xpr_uth("unix deviceRead: thread %d offset %d\n", ! 247: threadNum, IOBuf->offset, 3,4,5); ! 248: ! 249: /* ! 250: * lseek to appropriate place. ! 251: */ ! 252: block_size = [self blockSize]; ! 253: position = IOBuf->offset * block_size; ! 254: rtn = lseek(unix_fd[threadNum], position, L_SET); ! 255: if(rtn != position) { ! 256: xpr_uth("unixDisk deviceRead lseek(): errno %d\n", errno, ! 257: 2,3,4,5); ! 258: status = errno_to_mio(errno); ! 259: goto done; ! 260: } ! 261: ! 262: /* ! 263: * Go for it. ! 264: */ ! 265: xpr_uth("unix deviceRead read(): thread %d offset %d\n", ! 266: threadNum, IOBuf->offset, 3,4,5); ! 267: rtn = read(unix_fd[threadNum], IOBuf->buf, IOBuf->bytesReq); ! 268: if(rtn > 0) { ! 269: *IOBuf->bytesXfr = rtn; ! 270: status = IO_R_SUCCESS; ! 271: } ! 272: else ! 273: status = errno_to_mio(errno); ! 274: done: ! 275: /* ! 276: * Any time we successfully complete a read or a write, we go to ! 277: * "formatted" state. ! 278: */ ! 279: if(status == IO_R_SUCCESS) ! 280: [self setFormattedInternal:1]; ! 281: if(IOBuf->pending) { ! 282: /* ! 283: * Async I/O. Notify client. ! 284: */ ! 285: IOData *rdata = [[IOData alloc] initWithData:IOBuf->buf ! 286: size:*IOBuf->bytesXfr ! 287: dealloc:NO]; ! 288: ! 289: [rdata setFreeFlag:NO]; ! 290: [IOBuf->caller readIoComplete:(unsigned)IOBuf->pending ! 291: // ioKey ! 292: device:self ! 293: data:rdata ! 294: status:IOBuf->status]; ! 295: [rdata free]; ! 296: [self freeIOBuf:IOBuf]; ! 297: } ! 298: else { ! 299: /* ! 300: * Synchronous I/O. Notify sleeping thread. ! 301: */ ! 302: [self IOBufDone:IOBuf status:status]; ! 303: } ! 304: xpr_uth("unixDeviceRead thread %d: DONE, status %s\n", ! 305: threadNum, [self stringFromReturn:IOBuf->status], 3,4,5); ! 306: } ! 307: ! 308: - (void)unixDeviceWrite : (IOBuf_t *)IOBuf ! 309: threadNum:(int)threadNum ! 310: { ! 311: int rtn; ! 312: int position; ! 313: IOReturn status; ! 314: u_int block_size; ! 315: ! 316: xpr_uth("unix deviceWrite: thread %d offset %d\n", ! 317: threadNum, IOBuf->offset, 3,4,5); ! 318: ! 319: /* ! 320: * lseek to appropriate place. ! 321: */ ! 322: block_size = [self blockSize]; ! 323: position = IOBuf->offset * block_size; ! 324: rtn = lseek(unix_fd[threadNum], position, L_SET); ! 325: if(rtn != position) { ! 326: xpr_uth("unixDisk deviceWrite lseek(): errno %d\n", errno, ! 327: 2,3,4,5); ! 328: status = errno_to_mio(errno); ! 329: goto done; ! 330: } ! 331: ! 332: /* ! 333: * Go for it. ! 334: */ ! 335: rtn = write(unix_fd[threadNum], IOBuf->buf, IOBuf->bytesReq); ! 336: if(rtn > 0) { ! 337: *IOBuf->bytesXfr = rtn; ! 338: status = IO_R_SUCCESS; ! 339: } ! 340: else ! 341: status = errno_to_mio(errno); ! 342: done: ! 343: /* ! 344: * Any time we successfully complete a read or a write, we go to ! 345: * "formatted" state. ! 346: */ ! 347: if(status == IO_R_SUCCESS) ! 348: [self setFormattedInternal:1]; ! 349: if(IOBuf->pending) { ! 350: /* ! 351: * Async I/O. Notify client. ! 352: */ ! 353: [IOBuf->caller writeIoComplete:(unsigned)IOBuf->pending ! 354: device:self ! 355: actualLength:*IOBuf->bytesXfr ! 356: status:IOBuf->status]; ! 357: [self freeIOBuf:IOBuf]; ! 358: } ! 359: else { ! 360: /* ! 361: * Synchronous I/O. Notify sleeping thread. ! 362: */ ! 363: [self IOBufDone:IOBuf status:status]; ! 364: } ! 365: xpr_uth("unixDeviceWrite thread %d: DONE, status %s\n", ! 366: threadNum, [self stringFromReturn:IOBuf->status], 3,4,5); ! 367: } ! 368: ! 369: - (void)deviceEject : (IOBuf_t *)IOBuf ! 370: threadNum:(int)threadNum ! 371: { ! 372: int rtn; ! 373: IOReturn status; ! 374: ! 375: xpr_uth("unixDisk deviceEject: thread %d\n", threadNum, 2,3,4,5); ! 376: ! 377: /* ! 378: * Wait until we're the only thread doing disk access. ! 379: */ ! 380: [IOQueue.ejectLock lockWhen:1]; ! 381: [IOQueue.ejectLock unlock]; ! 382: ! 383: rtn = ioctl(unix_fd[threadNum], DKIOCEJECT, NULL); ! 384: if(rtn) ! 385: status = errno_to_mio(errno); ! 386: else ! 387: status = IO_R_SUCCESS; ! 388: ! 389: /* ! 390: * We go to unformatted state until we successfully complete a ! 391: * read or a write. ! 392: */ ! 393: [self setFormattedInternal:0]; ! 394: IOQueue.ejectPending = FALSE; ! 395: [self IOBufDone:IOBuf status:status]; ! 396: xpr_uth("unixDeviceEject thread %d: DONE, status %s\n", ! 397: threadNum, [self stringFromReturn:IOBuf->status], 3,4,5); ! 398: } ! 399: ! 400: /* ! 401: * Requested disk is not available. ioComplete everything in this ! 402: * device's q_disk queue with IO_R_NO_DISK status. ! 403: */ ! 404: - (void)unixDeviceAbort : (IOBuf_t *)IOBuf ! 405: { ! 406: IOBuf_t *abortBuf; ! 407: queue_head_t *q = &IOQueue.q_disk; ! 408: ! 409: xpr_uth("unixDeviceAbort\n", 1,2,3,4,5); ! 410: [IOQueue.qlock lock]; ! 411: while(!queue_empty(q)) { ! 412: abortBuf = (IOBuf_t *)queue_first(q); ! 413: queue_remove(q, abortBuf, IOBuf_t *, ioChain); ! 414: ! 415: /* ! 416: * Note we don't change condition variable of qlock... ! 417: */ ! 418: [IOQueue.qlock unlock]; ! 419: xpr_uth("unixDeviceAbort: ABORTING IOBuf 0x%x\n", abortBuf, ! 420: 2,3,4,5); ! 421: [self IOBufDone:abortBuf status:IO_R_NO_DISK]; ! 422: [IOQueue.qlock lock]; ! 423: } ! 424: [IOQueue.qlock unlock]; ! 425: ! 426: /* ! 427: * One more thing - I/O complete the abort command itself. ! 428: */ ! 429: [self IOBufDone:IOBuf status:IO_R_SUCCESS]; ! 430: } ! 431: ! 432: /* ! 433: * See if disk is present. If we got this far, it is; otherwise this request ! 434: * would have been ioComplete'd in unixDeviceAbort:. ! 435: */ ! 436: - (void)deviceProbe : (IOBuf_t *)IOBuf ! 437: { ! 438: [self IOBufDone:IOBuf status:IO_R_SUCCESS]; ! 439: } ! 440: ! 441: /* ! 442: * Test ready. We do this by trying to do a new open , with O_NDELAY. If that ! 443: * succeeds, it's ready. ! 444: */ ! 445: - (void)deviceCheckReady : (IOBuf_t *)IOBuf ! 446: threadNum:(int)threadNum ! 447: { ! 448: int newfd; ! 449: IODiskReadyState *readyState = (IODiskReadyState *)IOBuf->buf; ! 450: ! 451: newfd = open(unix_name, O_RDONLY|O_NDELAY, 0); ! 452: if(newfd <=0) { ! 453: *readyState = IO_NotReady; ! 454: xpr_uth("deviceCheckReady: NOT READY\n", 1,2,3,4,5); ! 455: } ! 456: else { ! 457: *readyState = IO_Ready; ! 458: close(newfd); ! 459: xpr_uth("deviceCheckReady: READY\n", 1,2,3,4,5); ! 460: } ! 461: [self IOBufDone:IOBuf status:IO_R_SUCCESS]; ! 462: } ! 463: ! 464: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.