|
|
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: /* unixDisk.m 1.0 01/31/91 (c) 1991 NeXT ! 25: * ! 26: * unixDisk.m - Implementation for unix Disk superclass. Provides IODevice ! 27: * interface for current "/dev" disks. ! 28: * ! 29: * HISTORY ! 30: * 31-Jan-91 Doug Mitchell at NeXT ! 31: * Created. ! 32: */ ! 33: ! 34: #import <bsd/sys/types.h> ! 35: #import <mach/mach.h> ! 36: #import <mach/vm_param.h> ! 37: #import <mach/mach_error.h> ! 38: #import <bsd/libc.h> ! 39: #import <bsd/sys/file.h> ! 40: #import <driverkit/return.h> ! 41: #import <driverkit/IODisk.h> ! 42: #import "unixDisk.h" ! 43: #import "unixDiskPrivate.h" ! 44: #import "unixThread.h" ! 45: #import <errno.h> ! 46: #import "unixDiskUxpr.h" ! 47: #import <bsd/dev/disk.h> ! 48: #import <machkit/NXLock.h> ! 49: #import <driverkit/generalFuncs.h> ! 50: #import <remote/NXConnection.h> ! 51: #import <objc/error.h> ! 52: ! 53: #define FAKE_LIVE_PARTITION 1 ! 54: #define NUM_API_THREADS 2 ! 55: ! 56: @implementation unixDisk ! 57: ! 58: +initialize ! 59: { ! 60: [super registerClass:self]; ! 61: return self; ! 62: } ! 63: ! 64: /* ! 65: * Common initialization. Device-specific parameters (dev_size, block_size) ! 66: * must have been initialized before we're called by subclass's *init: ! 67: * routines. ! 68: */ ! 69: - unixInit:(int)numThreads ! 70: { ! 71: int thread_num; ! 72: struct drive_info drive_info; ! 73: ! 74: xpr_ud("unixInit: numThreads %d\n", numThreads, 2,3,4,5); ! 75: ! 76: /* ! 77: * Set up our instance's IOQueue. ! 78: */ ! 79: IOQueue.qlock = [NXConditionLock alloc]; ! 80: [IOQueue.qlock initWith:NO_WORK_AVAILABLE]; ! 81: queue_init(&IOQueue.q_disk); ! 82: queue_init(&IOQueue.q_nodisk); ! 83: IOQueue.device = self; ! 84: IOQueue.ejectLock = [NXConditionLock alloc]; ! 85: [IOQueue.ejectLock initWith:0]; ! 86: IOQueue.numDiskIos = 0; ! 87: IOQueue.ejectPending = FALSE; ! 88: ! 89: /* ! 90: * Log drive name. ! 91: */ ! 92: if(ioctl(unix_fd[0], DKIOCINFO, &drive_info)) { ! 93: xpr_err("%s: unixInit: DKIOCINFO error\n", [self name], ! 94: 2,3,4,5); ! 95: } ! 96: else { ! 97: IOLog("%s: %s\n", [self name], drive_info.di_name); ! 98: } ! 99: ! 100: /* ! 101: * Start up some I/O threads to perform the actual work of this device. ! 102: */ ! 103: for(thread_num=0; thread_num<numThreads; thread_num++) { ! 104: IOForkThread((IOThreadFunc)unix_thread, &IOQueue); ! 105: } ! 106: ! 107: /* ! 108: * Init other instance variables. ! 109: */ ! 110: [self setLastReadyState:IO_Ready]; ! 111: [self setIsPhysical:YES]; ! 112: [super init]; ! 113: return self; ! 114: } ! 115: ! 116: /* ! 117: * Overrides IODisk method of same name; we do this to start up ! 118: * NXConnections for IODiskPartition partitions attached to this physDevice. ! 119: */ ! 120: - (void) setLogicalDisk : diskId ! 121: { ! 122: if([self registerPartition:diskId] == nil) { ! 123: return; ! 124: } ! 125: [super setLogicalDisk : diskId]; ! 126: } ! 127: ! 128: /* ! 129: * Set up an NXConnection for ourself and start up threads to handle ! 130: * incoming I/O requests. ! 131: * Called both from main(), for physical disk, and from setLogicalDisk: ! 132: * for IODiskPartition instances. ! 133: */ ! 134: - registerPartition: partId ! 135: { ! 136: id roserver; ! 137: int threadNum; ! 138: id rtn = self; ! 139: ! 140: NX_DURING { ! 141: roserver = [NXConnection registerRoot:partId ! 142: withName:[partId name]]; ! 143: } NX_HANDLER { ! 144: IOLog("registerRoot raised %d\n", ! 145: NXLocalHandler.code); ! 146: rtn = nil; ! 147: } NX_ENDHANDLER ! 148: ! 149: if(rtn == nil) { ! 150: return rtn; ! 151: } ! 152: if(roserver == nil) { ! 153: IOLog("registerRoot returned nil\n"); ! 154: return nil; ! 155: } ! 156: ! 157: /* ! 158: * Start up "API threads". ! 159: */ ! 160: for(threadNum=0; threadNum<NUM_API_THREADS; threadNum++) { ! 161: NX_DURING { ! 162: [roserver runInNewThread]; ! 163: } NX_HANDLER { ! 164: IOLog("runInNewThread raised %d\n", ! 165: NXLocalHandler.code); ! 166: rtn = nil; ! 167: } NX_ENDHANDLER; ! 168: if(rtn == nil) { ! 169: break; ! 170: } ! 171: } ! 172: return rtn; ! 173: } ! 174: ! 175: /* ! 176: * IODiskDeviceReadingAndWriting protocol implementation. The main task of ! 177: * these methods is: ! 178: * ! 179: * -- verify valid input parameters (can we skip this?) ! 180: * -- set up and enqueue an IOBuf for servicing by the I/O thread. ! 181: * -- Wait for I/O complete if synchronous request. ! 182: */ ! 183: ! 184: - (IOReturn) readAt : (u_int)offset ! 185: length : (u_int)length ! 186: buffer : (unsigned char *)buffer ! 187: actualLength : (u_int *)actualLength ! 188: { ! 189: IOReturn mrtn; ! 190: IOBuf_t *IOBuf; ! 191: ! 192: xpr_ud("unixDisk read: unit %d offset 0x%x " ! 193: "length 0x%x\n", [self unit], offset, length, 4,5); ! 194: ! 195: mrtn = [self readCommon : offset ! 196: length : length ! 197: buffer : buffer ! 198: actualLength : actualLength /* returned */ ! 199: pending : 0 ! 200: caller : nil ! 201: IOBufRtn : &IOBuf]; ! 202: ! 203: /* ! 204: * Wait for I/O complete. ! 205: */ ! 206: if(!mrtn) { ! 207: [IOBuf->wait_lock lockWhen:TRUE]; ! 208: [IOBuf->wait_lock unlock]; ! 209: mrtn = IOBuf->status; ! 210: [self freeIOBuf:IOBuf]; ! 211: } ! 212: xpr_ud("unixDisk read: returning %d\n", mrtn, 2,3,4,5); ! 213: return(mrtn); ! 214: } ! 215: ! 216: - (IOReturn) readAsyncAt : (u_int)offset ! 217: length : (u_int)length ! 218: buffer : (unsigned char *)buffer ! 219: pending : (void *)pending ! 220: { ! 221: return IO_R_UNSUPPORTED; ! 222: } ! 223: ! 224: - (IOReturn) writeAt : (u_int)offset ! 225: length : (u_int)length ! 226: buffer : (unsigned char *)buffer ! 227: actualLength : (u_int *)actualLength ! 228: { ! 229: IOReturn mrtn; ! 230: IOBuf_t *IOBuf; ! 231: ! 232: xpr_ud("unixDisk write: unit %d offset 0x%x " ! 233: "length 0x%x\n", [self unit], offset, length, 4,5); ! 234: ! 235: mrtn = [self writeCommon : offset ! 236: length : length ! 237: buffer : buffer ! 238: actualLength : actualLength /* returned */ ! 239: pending : 0 ! 240: caller : nil ! 241: IOBufRtn : &IOBuf]; ! 242: ! 243: /* ! 244: * Wait for I/O complete. ! 245: */ ! 246: if(!mrtn) { ! 247: [IOBuf->wait_lock lockWhen:TRUE]; ! 248: mrtn = IOBuf->status; ! 249: [self freeIOBuf:IOBuf]; ! 250: } ! 251: xpr_ud("unixDisk write: returning %d\n", mrtn, 2,3,4,5); ! 252: return(mrtn); ! 253: } ! 254: ! 255: - (IOReturn) writeAsyncAt : (u_int)offset ! 256: length : (u_int)length ! 257: buffer : (unsigned char *)buffer ! 258: pending : (void *)pending ! 259: { ! 260: return IO_R_UNSUPPORTED; ! 261: } ! 262: ! 263: - (IODiskReadyState)updateReadyState ! 264: { ! 265: IOBuf_t *IOBuf; ! 266: IODiskReadyState readyState; ! 267: ! 268: xpr_ud("unixDisk updateReadyState: top\n", 1,2,3,4,5); ! 269: ! 270: /* ! 271: * Queue up an IOBuf. ! 272: */ ! 273: IOBuf = [self allocIOBuf]; ! 274: IOBuf->command = @selector(deviceCheckReady:threadNum:); ! 275: IOBuf->offset = 0; ! 276: IOBuf->bytesReq = 0; ! 277: IOBuf->buf = &readyState; ! 278: IOBuf->bytesXfr = NULL; ! 279: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 280: * I/O thread */ ! 281: IOBuf->pending = 0; ! 282: IOBuf->device = self; ! 283: IOBuf->dirRead = 1; ! 284: IOBuf->wait_lock = [NXConditionLock alloc]; ! 285: [IOBuf->wait_lock initWith:FALSE]; ! 286: [self enqueueIoBuf:IOBuf needs_disk:FALSE]; ! 287: ! 288: /* ! 289: * Wait for I/O complete. ! 290: */ ! 291: [IOBuf->wait_lock lockWhen:TRUE]; ! 292: readyState = *(IODiskReadyState *)IOBuf->buf; ! 293: [self freeIOBuf:IOBuf]; ! 294: ! 295: xpr_ud("unixDisk updateReadyState: DONE; state = %s\n", ! 296: IOFindNameForValue(readyState, readyStateValues), 2,3,4,5); ! 297: return(readyState); ! 298: } ! 299: ! 300: /* ! 301: * IOPhysicalDiskMethods protocol methods. ! 302: */ ! 303: /* ! 304: * Device-specific eject. Called by DiskObject's eject:. ! 305: */ ! 306: - (IOReturn) ejectPhysical ! 307: { ! 308: IOReturn mrtn; ! 309: IOBuf_t *IOBuf; ! 310: ! 311: xpr_ud("unixDisk ejectPhysical: top\n", 1,2,3,4,5); ! 312: ! 313: /* ! 314: * Queue up an IOBuf. ! 315: */ ! 316: IOBuf = [self allocIOBuf]; ! 317: IOBuf->command = @selector(deviceEject:threadNum:); ! 318: IOBuf->offset = 0; ! 319: IOBuf->bytesReq = 0; ! 320: IOBuf->buf = NULL; ! 321: IOBuf->bytesXfr = NULL; ! 322: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 323: * I/O thread */ ! 324: IOBuf->pending = 0; ! 325: IOBuf->device = self; ! 326: IOBuf->dirRead = 1; ! 327: IOBuf->wait_lock = [NXConditionLock alloc]; ! 328: [IOBuf->wait_lock initWith:FALSE]; ! 329: [self enqueueIoBuf:IOBuf needs_disk:TRUE]; ! 330: ! 331: /* ! 332: * Wait for I/O complete. ! 333: */ ! 334: [IOBuf->wait_lock lockWhen:TRUE]; ! 335: mrtn = IOBuf->status; ! 336: [self freeIOBuf:IOBuf]; ! 337: ! 338: xpr_ud("unixDisk eject: DONE; status = %d\n", mrtn, 2,3,4,5); ! 339: return(mrtn); ! 340: } ! 341: ! 342: /* ! 343: * Removable media support. ! 344: */ ! 345: ! 346: /* ! 347: * Called by volCheck thread when WS has told us that a requested disk is ! 348: * not present. Pending I/Os which require a disk to be present must be ! 349: * aborted. ! 350: */ ! 351: - (void)abortRequest ! 352: { ! 353: IOReturn mrtn; ! 354: IOBuf_t *IOBuf; ! 355: ! 356: xpr_ud("unixDisk abortRequest: top\n", 1,2,3,4,5); ! 357: ! 358: /* ! 359: * Queue up an IOBuf. ! 360: */ ! 361: IOBuf = [self allocIOBuf]; ! 362: IOBuf->command = @selector(unixDeviceAbort:); ! 363: IOBuf->offset = 0; ! 364: IOBuf->bytesReq = 0; ! 365: IOBuf->buf = NULL; ! 366: IOBuf->bytesXfr = NULL; ! 367: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 368: * I/O thread */ ! 369: IOBuf->pending = 0; ! 370: IOBuf->device = self; ! 371: IOBuf->dirRead = 1; ! 372: IOBuf->wait_lock = [NXConditionLock alloc]; ! 373: [IOBuf->wait_lock initWith:FALSE]; ! 374: [self enqueueIoBuf:IOBuf needs_disk:FALSE]; ! 375: ! 376: /* ! 377: * Wait for I/O complete. ! 378: */ ! 379: [IOBuf->wait_lock lockWhen:TRUE]; ! 380: mrtn = IOBuf->status; ! 381: [self freeIOBuf:IOBuf]; ! 382: ! 383: xpr_ud("unixDisk abortRequest: DONE; status = %d\n", mrtn, 2,3,4,5); ! 384: return; ! 385: } ! 386: ! 387: /* ! 388: * Called by the volCheck thread when a transition to "ready" is detected. ! 389: * Pending I/Os which require a disk may proceed. ! 390: * ! 391: * All we have to do is wake up the I/O threads. ! 392: */ ! 393: - (void)diskBecameReady ! 394: { ! 395: [self ioThreadWakeup]; ! 396: } ! 397: ! 398: /* ! 399: * Inquire if disk is present; if not, and 'prompt' is TRUE, ask for it. ! 400: * Returns IO_R_NO_DISK if: ! 401: * prompt TRUE, disk not present, and user cancels request for disk. ! 402: * prompt FALSE, disk not present. ! 403: * Else returns IO_R_SUCCESS. ! 404: */ ! 405: - (IOReturn)isDiskReady : (BOOL)prompt ! 406: { ! 407: IOReturn mrtn; ! 408: IOBuf_t *IOBuf; ! 409: ! 410: xpr_ud("%s: diskBecameReady\n", [self name], 2,3,4,5); ! 411: if([self lastReadyState] == IO_Ready) { ! 412: /* ! 413: * This one's easy... ! 414: */ ! 415: return(IO_R_SUCCESS); ! 416: } ! 417: if(prompt == NO) { ! 418: return(IO_R_NO_DISK); ! 419: } ! 420: ! 421: /* ! 422: * Queue up an IOBuf. ! 423: */ ! 424: IOBuf = [self allocIOBuf]; ! 425: IOBuf->command = @selector(deviceProbe:); ! 426: IOBuf->offset = 0; ! 427: IOBuf->bytesReq = 0; ! 428: IOBuf->buf = NULL; ! 429: IOBuf->bytesXfr = NULL; ! 430: IOBuf->status = IO_R_INVALID; /* must be filled in by ! 431: * I/O thread */ ! 432: IOBuf->pending = 0; ! 433: IOBuf->device = self; ! 434: IOBuf->dirRead = 1; ! 435: IOBuf->wait_lock = [NXConditionLock alloc]; ! 436: [IOBuf->wait_lock initWith:FALSE]; ! 437: [self enqueueIoBuf:IOBuf needs_disk:TRUE]; ! 438: ! 439: /* ! 440: * Wait for I/O complete. ! 441: */ ! 442: [IOBuf->wait_lock lockWhen:TRUE]; ! 443: mrtn = IOBuf->status; ! 444: [self freeIOBuf:IOBuf]; ! 445: ! 446: xpr_ud("unixDisk isDiskReady: DONE; status = %d\n", mrtn, 2,3,4,5); ! 447: return(mrtn); ! 448: } ! 449: ! 450: /* ! 451: * This must be implemented by subclass. ! 452: */ ! 453: - (IOReturn)updatePhysicalParameters ! 454: { ! 455: IOLog("unixDisk updatePhysicalParameters: NOT IMPLEMENTED\n"); ! 456: return IO_R_UNSUPPORTED; ! 457: } ! 458: ! 459: /* ! 460: * unixDisk-specific Get/set methods. ! 461: */ ! 462: - (int)diskType ! 463: { ! 464: return(_diskType); ! 465: } ! 466: ! 467: - (void)setDiskType : (int)type ! 468: { ! 469: _diskType = type; ! 470: } ! 471: ! 472: /* ! 473: * Distributed Objects R/W protocol. ! 474: */ ! 475: - (IOReturn) readAt : (unsigned)offset // in blocks ! 476: length : (unsigned)length // in bytes ! 477: data : (out IOData **)data ! 478: actualLength : (out unsigned *)actualLength ! 479: { ! 480: IOReturn rtn; ! 481: IOData *ldata = [[IOData alloc] initWithSize:length]; ! 482: ! 483: /* ! 484: * FIXME - when freeFlag is set to YES (which is what we really ! 485: * want), this method crashes with the following error messages ! 486: * when run with the DiskTest app: ! 487: * ! 488: * finishEncoding: send error -101:invalid memory ! 489: * uncaught exception : 11001 ! 490: * objc: FREED(id): message free sent to freed object=0x9c01c ! 491: * ! 492: * When run with the test programs in ../tests, everything works ! 493: * OK... ! 494: * ! 495: * When we set freeFlag to NO, everything works, but the IOStub ! 496: * server leaks memory. ! 497: */ ! 498: [ldata setFreeFlag:NO]; ! 499: rtn = [self readAt:offset ! 500: length:length ! 501: buffer:[ldata data] ! 502: actualLength:actualLength]; ! 503: if(*actualLength) { ! 504: *data = ldata; ! 505: } ! 506: ! 507: return rtn; ! 508: } ! 509: ! 510: - (IOData *)rreadAt : (unsigned)offset ! 511: length : (unsigned)length ! 512: rtn : (out IOReturn *)rtn ! 513: actualLength : (out unsigned *)actualLength ! 514: { ! 515: IOReturn lrtn; ! 516: IOData *ldata = [[IOData alloc] initWithSize:length]; ! 517: ! 518: [ldata setFreeFlag:YES]; ! 519: lrtn = [self readAt:offset ! 520: length:length ! 521: buffer:[ldata data] ! 522: actualLength:actualLength]; ! 523: *rtn = lrtn; ! 524: return ldata; ! 525: } ! 526: ! 527: ! 528: - (IOReturn) readAsyncAt : (unsigned)offset ! 529: length : (unsigned)length ! 530: ioKey : (unsigned)ioKey ! 531: caller : (id)caller ! 532: { ! 533: /* ! 534: * TBD ! 535: */ ! 536: return IO_R_UNSUPPORTED; ! 537: } ! 538: ! 539: ! 540: - (IOReturn) writeAt : (unsigned)offset // in blocks ! 541: length : (unsigned)length // in bytes ! 542: data : (out IOData *)data ! 543: actualLength : (out unsigned *)actualLength ! 544: { ! 545: IOReturn rtn; ! 546: ! 547: if([data size] < length) { ! 548: IOLog("%s writeAt: insufficient memory in IOData\n", ! 549: [self name]); ! 550: } ! 551: rtn = [self writeAt:offset ! 552: length:length ! 553: buffer:[data data] ! 554: actualLength:actualLength]; ! 555: [data free]; ! 556: return rtn; ! 557: } ! 558: ! 559: - (IOReturn)writeAsyncAt : (unsigned)offset // in blocks ! 560: length : (unsigned)length // in bytes ! 561: data : (in IOData *)data ! 562: ioKey : (unsigned)ioKey ! 563: caller : (id)caller ! 564: { ! 565: return IO_R_UNSUPPORTED; ! 566: } ! 567: ! 568: @end ! 569: ! 570: IOReturn errno_to_mio(int Errno) { ! 571: ! 572: IOReturn mrtn; ! 573: ! 574: switch(Errno) { ! 575: case 0: ! 576: mrtn = IO_R_SUCCESS; ! 577: break; ! 578: case EIO: ! 579: mrtn = IO_R_IO; ! 580: break; ! 581: case EPERM: ! 582: case EACCES: ! 583: mrtn = IO_R_PRIVILEGE; ! 584: break; ! 585: default: ! 586: mrtn = IO_R_IO; ! 587: break; ! 588: } ! 589: return(mrtn); ! 590: } ! 591:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.