|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: ! 23: #include <IOKit/IOLib.h> ! 24: #include <IOKit/IOReturn.h> ! 25: #include <IOKit/storage/IOMedia.h> ! 26: #include <IOKit/assert.h> ! 27: #include <IOKit/storage/IOHDDrive.h> ! 28: #include <IOKit/storage/IOHDDriveNub.h> ! 29: ! 30: #define super IODrive ! 31: OSDefineMetaClassAndStructors(IOHDDrive,IODrive) ! 32: ! 33: void ! 34: gc_glue(IOService *target,void *param,UInt64 actualTransferCount,IOReturn result); ! 35: ! 36: /* Accept a new piece of media, doing whatever's necessary to make it ! 37: * show up properly to the system. ! 38: */ ! 39: IOReturn ! 40: IOHDDrive::acceptNewMedia(void) ! 41: { ! 42: IOReturn result; ! 43: bool ok; ! 44: UInt64 nbytes; ! 45: UInt64 nformats; ! 46: char name[128]; ! 47: bool nameSep; ! 48: ! 49: lockForArbitration(); ! 50: ! 51: /* Since the kernel printf doesn't handle 64-bit integers, we ! 52: * simply make an assumption that the block count and size ! 53: * will be 32-bit values max. ! 54: */ ! 55: ! 56: #ifdef moreDebug ! 57: IOLog("%s[IOHDDrive]::%s media: %ld blocks, %ld bytes each, write-%s.\n", ! 58: getName(), ! 59: getDeviceTypeName(), ! 60: (UInt32)_maxBlockNumber + 1,(UInt32)getMediaBlockSize(), ! 61: (_writeProtected ? "protected" : "enabled")); ! 62: #else ! 63: IOLog("%s media: %ld blocks, %ld bytes each, write-%s.\n", ! 64: getName(), ! 65: (UInt32)_maxBlockNumber + 1,(UInt32)getMediaBlockSize(), ! 66: (_writeProtected ? "protected" : "enabled")); ! 67: #endif ! 68: ! 69: /* Instantiate a media object and attach it to ourselves. */ ! 70: ! 71: nformats = getFormatCapacities(&nbytes,1); /* get byte size of media */ ! 72: ! 73: name[0] = 0; ! 74: nameSep = false; ! 75: if (_provider->getVendorString()) { ! 76: strcat(name, _provider->getVendorString()); ! 77: nameSep = true; ! 78: } ! 79: if (_provider->getProductString()) { ! 80: if (nameSep == true) strcat(name, " "); ! 81: strcat(name, _provider->getProductString()); ! 82: nameSep = true; ! 83: } ! 84: if (nameSep == true) strcat(name, " "); ! 85: strcat(name, "Media"); ! 86: ! 87: result = instantiateMediaObject(&_mediaObject,0,nbytes,_mediaBlockSize,true,name); ! 88: ! 89: if (result == kIOReturnSuccess) { ! 90: _mediaPresent = true; ! 91: ok = _mediaObject->attach(this); /* attach media object above us */ ! 92: if (ok) { ! 93: // IOLog("IOHDDrive: registering media object\n"); ! 94: _mediaObject->registerService(); /* enable matching */ ! 95: } ! 96: } else { ! 97: IOLog("%s[IOHDDrive]::acceptNewMedia; couldn't instantiate media object.\n",getName()); ! 98: } ! 99: ! 100: unlockForArbitration(); ! 101: ! 102: return(result); ! 103: } ! 104: ! 105: /* Allocate a new context struct. */ ! 106: struct IOHDDrive::context * ! 107: IOHDDrive::allocateContext(void) ! 108: { ! 109: struct IOHDDrive::context *cx; ! 110: ! 111: cx = IONew(struct IOHDDrive::context,1); ! 112: if (cx == NULL) { ! 113: return(NULL); ! 114: } ! 115: ! 116: bzero(cx,sizeof(struct IOHDDrive::context)); ! 117: ! 118: return(cx); ! 119: } ! 120: ! 121: IOReturn ! 122: IOHDDrive::checkForMedia(void) ! 123: { ! 124: IOReturn result; ! 125: bool currentState; ! 126: bool changed; ! 127: ! 128: IOTakeLock(_mediaStateLock); ! 129: ! 130: result = _provider->reportMediaState(¤tState,&changed); ! 131: if (result != kIOReturnSuccess) { /* the poll operation failed */ ! 132: IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from reportMediaState\n", ! 133: getName(),stringFromReturn(result)); ! 134: ! 135: IOUnlock(_mediaStateLock); ! 136: return(result); ! 137: } ! 138: ! 139: /* The poll succeeded. */ ! 140: ! 141: if (!changed) { /* media state hasn't changed */ ! 142: IOUnlock(_mediaStateLock); ! 143: return(kIOReturnSuccess); ! 144: } ! 145: ! 146: /* The media has changed state. See if it's just inserted or removed. */ ! 147: ! 148: if (currentState == true) { /* media is now present */ ! 149: ! 150: // IOLog("%s[IOHDDrive]::checkForMedia; changed = %s, mediaPresent = %s\n", ! 151: // getName(),changed ? "Y" : "N",currentState ? "Y" : "N"); ! 152: ! 153: /* Allow a subclass to decide whether we accept the media. Such a decision ! 154: * might be based on things like password-protection, etc. ! 155: */ ! 156: ! 157: if (validateNewMedia() == false) { /* we're told to reject it */ ! 158: rejectMedia(); /* so let subclass do whatever it wants */ ! 159: IOUnlock(_mediaStateLock); ! 160: return(kIOReturnSuccess); /* pretend nothing happened */ ! 161: } ! 162: ! 163: result = recordMediaParameters(); /* learn about media */ ! 164: if (result != kIOReturnSuccess) { /* couldn't record params */ ! 165: initMediaStates(); /* deny existence of new media */ ! 166: IOLog("%s[IOHDDrive]::checkForMedia: err '%s' from recordMediaParameters\n", ! 167: getName(),stringFromReturn(result)); ! 168: IOUnlock(_mediaStateLock); ! 169: return(result); ! 170: } ! 171: ! 172: /* Now we do what's necessary to make the new media ! 173: * show up properly in the system. ! 174: */ ! 175: ! 176: result = acceptNewMedia(); ! 177: if (result != kIOReturnSuccess) { ! 178: initMediaStates(); /* deny existence of new media */ ! 179: IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from acceptNewMedia\n", ! 180: getName(),stringFromReturn(result)); ! 181: IOUnlock(_mediaStateLock); ! 182: return(result); ! 183: } ! 184: ! 185: IOUnlock(_mediaStateLock); ! 186: return(kIOReturnSuccess); /* all done, new media is ready */ ! 187: ! 188: } else { /* media is now absent */ ! 189: ! 190: result = decommissionMedia(true); /* force a teardown */ ! 191: if (result != kIOReturnSuccess && result != kIOReturnNoMedia) { ! 192: IOLog("%s[IOHDDrive]::checkForMedia; err '%s' from decommissionNewMedia\n", ! 193: getName(),stringFromReturn(result)); ! 194: IOUnlock(_mediaStateLock); ! 195: return(result); ! 196: } ! 197: ! 198: IOUnlock(_mediaStateLock); ! 199: return(kIOReturnSuccess); /* all done; media is gone */ ! 200: } ! 201: } ! 202: ! 203: UInt64 ! 204: IOHDDrive::constrainByteCount(UInt64 /* requestedCount */ ,bool isWrite) ! 205: { ! 206: if (isWrite) { ! 207: return(_maxWriteByteTransfer); ! 208: } else { ! 209: return(_maxReadByteTransfer); ! 210: } ! 211: } ! 212: ! 213: OSDictionary * ! 214: IOHDDrive::constructMediaProperties(void) ! 215: { ! 216: #ifdef notyet //xxx ! 217: ! 218: OSDictionary *propTable; ! 219: OSData *prop; ! 220: ! 221: propTable = OSDictionary::withCapacity(6); ! 222: ! 223: if (propTable) { ! 224: ! 225: prop = OSData::withBytes((void *)(&_mediaBlockSize),sizeof(UInt64)); ! 226: if (prop) { ! 227: propTable->setObject(prop,"phys-blocksize"); ! 228: prop->release(); // XXX -- svail: added. ! 229: } ! 230: ! 231: prop = OSData::withBytes((void *)(&_maxBlockNumber),sizeof(UInt64)); ! 232: if (prop) { ! 233: propTable->setObject(prop,"highest-block"); ! 234: prop->relase(); // XXX -- svail: added. ! 235: } ! 236: ! 237: prop = OSData::withBytes((void *)(&_writeProtected),sizeof(bool)); ! 238: if (prop) { ! 239: propTable->setObject(prop,"write-protected"); ! 240: prop->release(); // XXX -- svail: added. ! 241: } ! 242: } ! 243: ! 244: return(propTable); ! 245: ! 246: #else ! 247: return(0); ! 248: #endif //xxx ! 249: } ! 250: ! 251: /* Decommission a piece of media that has become unavailable either due to ! 252: * ejection or some outside force (e.g. the Giant Hand of the User). ! 253: * (I prefer the term "decommission" rather than "abandon." The former implies ! 254: * a well-determined procedure, whereas the latter implies leaving the media ! 255: * in an orphaned state.) ! 256: */ ! 257: /* Tear down the stack above the specified object. Usually these objects will ! 258: * be of type IOMedia, but they could be any IOService. ! 259: */ ! 260: IOReturn ! 261: IOHDDrive::decommissionMedia(bool forcible) ! 262: { ! 263: IOReturn result; ! 264: ! 265: result = tearDown(_mediaObject); ! 266: ! 267: /* If this is a forcible decommission (i.e. media is gone), we don't care ! 268: * whether the teardown worked; we forget about the media. ! 269: */ ! 270: ! 271: if (forcible || (result == kIOReturnSuccess)) { /* then it tore down successfully */ ! 272: _mediaObject = 0; ! 273: initMediaStates(); /* deny existence of any media */ ! 274: } ! 275: ! 276: return(result); ! 277: } ! 278: ! 279: void ! 280: IOHDDrive::deleteContext(struct IOHDDrive::context *cx) ! 281: { ! 282: if (cx->buffer) { ! 283: cx->buffer->release(); /* reduce retain count on Memory Descriptor */ ! 284: } ! 285: IODelete(cx,struct IOHDDrive::context,1); ! 286: } ! 287: ! 288: IOReturn ! 289: IOHDDrive::ejectMedia(void) ! 290: { ! 291: IOReturn result; ! 292: ! 293: if (_removable) { ! 294: ! 295: IOTakeLock(_mediaStateLock); ! 296: ! 297: result = decommissionMedia(false); /* try to teardown */ ! 298: ! 299: if (result == kIOReturnSuccess) { /* eject */ ! 300: (void)_provider->doEjectMedia(); /* ignore any error */ ! 301: } ! 302: ! 303: IOUnlock(_mediaStateLock); ! 304: ! 305: return(result); ! 306: ! 307: } else { ! 308: return(kIOReturnUnsupported); ! 309: } ! 310: } ! 311: ! 312: void ! 313: IOHDDrive::executeRequest(UInt64 byteStart, ! 314: IOMemoryDescriptor * buffer, ! 315: IOStorageCompletion completion) ! 316: { ! 317: struct IOHDDrive::context *cx; ! 318: UInt32 block; ! 319: UInt32 nblks; ! 320: IOReturn result; ! 321: ! 322: _stats.clientReceived++; ! 323: ! 324: if (!_mediaPresent) { /* no media? you lose */ ! 325: _stats.clientCompletionsSent++; ! 326: complete(completion, kIOReturnNoMedia,0); ! 327: _stats.clientCompletionsDone++; ! 328: return; ! 329: } ! 330: ! 331: result = buffer->prepare(); // (prepare the buffer) ! 332: if ( result != kIOReturnSuccess ) { ! 333: // (wiring or permissions failure?) ! 334: _stats.clientCompletionsSent++; ! 335: complete(completion, result,0); ! 336: _stats.clientCompletionsDone++; ! 337: return; ! 338: } ! 339: ! 340: /* We know that we are never called with a request too large, ! 341: * nor one that is misaligned with a block. ! 342: */ ! 343: assert((byteStart % _mediaBlockSize) == 0); ! 344: assert((buffer->getLength() % _mediaBlockSize) == 0); ! 345: ! 346: block = byteStart / _mediaBlockSize; ! 347: nblks = buffer->getLength() / _mediaBlockSize; ! 348: ! 349: cx = allocateContext(); ! 350: if (cx == NULL) { ! 351: if (buffer) { ! 352: buffer->complete(); ! 353: } ! 354: _stats.clientCompletionsSent++; ! 355: complete(completion,kIOReturnNoResources,0); ! 356: _stats.clientCompletionsDone++; ! 357: return; ! 358: } ! 359: ! 360: /* Copy our params to our context. */ ! 361: ! 362: cx->completion = completion; ! 363: cx->buffer = buffer; ! 364: cx->buffer->retain(); ! 365: cx->byteStart = byteStart; ! 366: cx->byteCount = buffer->getLength(); ! 367: ! 368: /*** ! 369: if (isWrite) { ! 370: assert(buffer->getDirection() == kIODirectionOut); ! 371: } else { ! 372: assert(buffer->getDirection() == kIODirectionIn); ! 373: } ! 374: ***/ ! 375: /** ! 376: IOLog("%s[IOHDDrive]::executeRequest; blk %d, nblks %d\n",getName(), ! 377: (int)block,(int)nblks); ! 378: **/ ! 379: /* Now the protocol-specific provider implements the actual ! 380: * start of the data transfer: */ ! 381: ! 382: _stats.providerSent++; ! 383: result = _provider->doAsyncReadWrite(cx->buffer, ! 384: block,nblks, ! 385: gc_glue, ! 386: this,(void *)cx); ! 387: ! 388: if (result != kIOReturnSuccess) { /* it failed to start */ ! 389: _stats.providerReject++; ! 390: IOLog("%s[IOHDDrive]; executeRequest: request failed to start!\n",getName()); ! 391: if (buffer) { ! 392: buffer->complete(); ! 393: } ! 394: _stats.clientCompletionsSent++; ! 395: complete(completion,result,0); ! 396: _stats.clientCompletionsDone++; ! 397: deleteContext(cx); ! 398: return; ! 399: } ! 400: ! 401: if (showStats()) { ! 402: IOLog("%s[IOHDDrive]; executeRequest: cr=%5d,ps=%5d,pr=%5d,pcr=%5d,ccs=%5d,ccd=%5d\n", ! 403: getName(), ! 404: _stats.clientReceived, ! 405: _stats.providerSent, ! 406: _stats.providerReject, ! 407: _stats.providerCompletionsRcvd, ! 408: _stats.clientCompletionsSent, ! 409: _stats.clientCompletionsDone); ! 410: } ! 411: } ! 412: ! 413: IOReturn ! 414: IOHDDrive::formatMedia(UInt64 byteCapacity) ! 415: { ! 416: if (!_mediaPresent) { ! 417: return(kIOReturnNoMedia); ! 418: } ! 419: ! 420: return(_provider->doFormatMedia(byteCapacity)); ! 421: } ! 422: ! 423: void ! 424: IOHDDrive::free(void) ! 425: { ! 426: if (_mediaStateLock) { ! 427: IOLockFree(_mediaStateLock); ! 428: } ! 429: ! 430: super::free(); ! 431: } ! 432: ! 433: /* The Callback (C) entry from our provider. We just glue ! 434: * right into C++. ! 435: */ ! 436: ! 437: void ! 438: gc_glue(IOService *target,void *param,UInt64 actualTransferCount,IOReturn result) ! 439: { ! 440: IOHDDrive *self; ! 441: struct IOHDDrive::context *cx; ! 442: ! 443: self = (IOHDDrive *) target; ! 444: cx = (struct IOHDDrive::context *)param; ! 445: cx->result = result; ! 446: cx->actualTransferCount = actualTransferCount; ! 447: ! 448: if (cx->result == kIOReturnSuccess) { ! 449: assert(cx->byteCount == cx->actualTransferCount); ! 450: } ! 451: ! 452: self->RWCompletion(cx); ! 453: } ! 454: ! 455: const char * ! 456: IOHDDrive::getDeviceTypeName(void) ! 457: { ! 458: return(kDeviceTypeHardDisk); ! 459: } ! 460: ! 461: UInt32 ! 462: IOHDDrive::getFormatCapacities(UInt64 * capacities, ! 463: UInt32 capacitiesMaxCount) const ! 464: { ! 465: return(_provider->doGetFormatCapacities(capacities,capacitiesMaxCount)); ! 466: } ! 467: ! 468: UInt64 ! 469: IOHDDrive::getMediaBlockSize() const ! 470: { ! 471: return(_mediaBlockSize); ! 472: } ! 473: ! 474: IODrive::IOMediaState ! 475: IOHDDrive::getMediaState() const ! 476: { ! 477: if (_mediaPresent) { ! 478: return(kMediaOnline); ! 479: } else { ! 480: return(kMediaOffline); ! 481: } ! 482: } ! 483: ! 484: bool ! 485: IOHDDrive::handleStart(IOService * provider) ! 486: { ! 487: IOReturn result; ! 488: ! 489: /* Print device name/type information on the console: */ ! 490: ! 491: // IOLog("%s[IOHDDrive] ",getName()); ! 492: IOLog("%s drive: %s, %s, rev %s %s.\n",getName(), ! 493: _provider->getVendorString(), ! 494: _provider->getProductString(), ! 495: _provider->getRevisionString(), ! 496: _provider->getAdditionalDeviceInfoString()); ! 497: ! 498: /*The protocol-specific provider determines whether the media is removable. */ ! 499: ! 500: result = _provider->reportRemovability(&_removable); ! 501: if (result != kIOReturnSuccess) { ! 502: IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportRemovability\n", ! 503: getName(),stringFromReturn(result)); ! 504: return(false); ! 505: } ! 506: ! 507: if (_removable) { ! 508: ! 509: /* The protocol-specific provider determines whether we must poll to detect ! 510: * media insertion. Nonremovable devices never need polling. ! 511: */ ! 512: ! 513: result = _provider->reportPollRequirements(&_pollIsRequired,&_pollIsExpensive); ! 514: /** ! 515: IOLog("%s[IOHDDrive]::handleStart; pollIsRequired = %s\n", ! 516: getName(),_pollIsRequired ? "Y" : "N"); ! 517: **/ ! 518: if (result != kIOReturnSuccess) { ! 519: IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportPollRequirements\n", ! 520: getName(),stringFromReturn(result)); ! 521: return(false); ! 522: } ! 523: ! 524: /* The protocol-specific provider determines whether the media is ejectable ! 525: * under software control. ! 526: */ ! 527: result = _provider->reportEjectability(&_ejectable); ! 528: if (result != kIOReturnSuccess) { ! 529: IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportEjectability\n", ! 530: getName(),stringFromReturn(result)); ! 531: return(false); ! 532: } ! 533: ! 534: /* The protocol-specific provider determines whether the media is lockable ! 535: * under software control. ! 536: */ ! 537: result = _provider->reportLockability(&_lockable); ! 538: if (result != kIOReturnSuccess) { ! 539: IOLog("%s[IOHDDrive]::handleStart; err '%s' from reportLockability\n", ! 540: getName(),stringFromReturn(result)); ! 541: return(false); ! 542: } ! 543: ! 544: } else { /* fixed drive: not ejectable, not lockable */ ! 545: _ejectable = false; ! 546: _lockable = false; ! 547: _pollIsRequired = true; /* polling detects device disappearance */ ! 548: } ! 549: ! 550: /* Check for the device being ready with media inserted: */ ! 551: ! 552: // IOLog("%s[IOHDDrive]::handleStart; calling checkForMedia\n",getName()); ! 553: ! 554: result = checkForMedia(); ! 555: ! 556: /* The poll should never fail for nonremovable media: */ ! 557: ! 558: if (result != kIOReturnSuccess && !_removable) { ! 559: IOLog("%s[IOHDDrive]::handleStart: err '%s' from checkForMedia\n", ! 560: getName(),stringFromReturn(result)); ! 561: return(false); ! 562: } ! 563: ! 564: return(true); ! 565: } ! 566: ! 567: /* The driver has been instructed to stop. If the media is writable, issue a ! 568: * Synchronize Cache command to ensure that all blocks have been written to ! 569: * the media. Then attempt to eject it. ! 570: */ ! 571: void ! 572: IOHDDrive::handleStop(IOService * provider) ! 573: { ! 574: if (_mediaPresent) { ! 575: if (!_writeProtected) { ! 576: (void)_provider->doSynchronizeCache(); /* ignore any error */ ! 577: } ! 578: (void)ejectMedia(); /* eject media if it's removable */ ! 579: } ! 580: ! 581: super::detach(provider); ! 582: } ! 583: ! 584: bool ! 585: IOHDDrive::init(OSDictionary * properties) ! 586: { ! 587: /* Do minimal initialization: */ ! 588: ! 589: initMediaStates(); ! 590: ! 591: _removable = false; ! 592: _ejectable = false; ! 593: _lockable = false; ! 594: _pollIsExpensive = false; ! 595: _pollIsRequired = false; ! 596: ! 597: _mediaBlockSize = 0; ! 598: _maxBlockNumber = 0; ! 599: _maxReadByteTransfer = 0; ! 600: _maxWriteByteTransfer = 0; ! 601: ! 602: bzero(&_stats,sizeof(struct stats)); ! 603: ! 604: _mediaStateLock = IOLockAlloc(); ! 605: if (_mediaStateLock == 0) { ! 606: return false; ! 607: } ! 608: IOLockInit(_mediaStateLock); ! 609: ! 610: return(super::init(properties)); ! 611: } ! 612: ! 613: void ! 614: IOHDDrive::initMediaStates(void) ! 615: { ! 616: _mediaPresent = false; ! 617: _writeProtected = false; ! 618: } ! 619: ! 620: IOMedia * ! 621: IOHDDrive::instantiateDesiredMediaObject(void) ! 622: { ! 623: return(new IOMedia); ! 624: } ! 625: ! 626: IOReturn ! 627: IOHDDrive::instantiateMediaObject(IOMedia **media,UInt64 base,UInt64 byteSize,UInt32 blockSize, ! 628: bool isWholeMedia,char *mediaName) ! 629: { ! 630: IOMedia *m; ! 631: bool result; ! 632: ! 633: *media = NULL; /* just for safety */ ! 634: ! 635: m = instantiateDesiredMediaObject(); ! 636: if (m == NULL) { ! 637: return(kIOReturnNoMemory); ! 638: } ! 639: ! 640: result = m->init( base, /* base byte offset */ ! 641: byteSize, /* byte size */ ! 642: blockSize, /* preferred block size */ ! 643: _ejectable, /* TRUE if ejectable */ ! 644: isWholeMedia, /* TRUE if whole physical media */ ! 645: !_writeProtected, /* TRUE if writable */ ! 646: ""); /* content hint */ ! 647: ! 648: if (result) { ! 649: *media = m; ! 650: m->setName(mediaName); ! 651: return(kIOReturnSuccess); ! 652: ! 653: } else { /* some init error */ ! 654: m->release(); ! 655: return(kIOReturnBadArgument); /* beats me...call it this error */ ! 656: } ! 657: } ! 658: ! 659: bool ! 660: IOHDDrive::isMediaEjectable(void) const ! 661: { ! 662: return(_ejectable); ! 663: } ! 664: ! 665: bool ! 666: IOHDDrive::isMediaPollExpensive(void) const ! 667: { ! 668: return(_pollIsExpensive); ! 669: } ! 670: ! 671: bool ! 672: IOHDDrive::isMediaPollRequired(void) const ! 673: { ! 674: return(_pollIsRequired); ! 675: } ! 676: ! 677: IOReturn ! 678: IOHDDrive::lockMedia(bool locked) ! 679: { ! 680: if (_lockable) { ! 681: return(_provider->doLockUnlockMedia(locked)); ! 682: } else { ! 683: return(kIOReturnUnsupported); ! 684: } ! 685: } ! 686: ! 687: IOReturn ! 688: IOHDDrive::pollMedia(void) ! 689: { ! 690: if (!_pollIsRequired) { /* shouldn't poll; it's an error */ ! 691: ! 692: return(kIOReturnUnsupported); ! 693: ! 694: } else { /* poll is required...do it */ ! 695: ! 696: return(checkForMedia()); ! 697: ! 698: } ! 699: } ! 700: ! 701: IOService * ! 702: IOHDDrive::probe(IOService * provider,SInt32 * score) ! 703: { ! 704: OSObject *object; ! 705: OSString *prop; ! 706: const char *string; ! 707: ! 708: if (!super::probe(provider,score)) { ! 709: return(NULL); ! 710: } ! 711: ! 712: /* Make sure the device type is what we expect. We can't simply use ! 713: * the class type because many nubs are subclasses of the same superclass. ! 714: */ ! 715: ! 716: object = provider->getProperty(kDeviceTypeProperty); ! 717: if (object == NULL) { ! 718: IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' has no device-type property\n", ! 719: getName(),provider->getName()); ! 720: return(NULL); ! 721: } ! 722: ! 723: prop = OSDynamicCast(OSString,provider->getProperty(kDeviceTypeProperty)); ! 724: ! 725: if (prop == NULL) { /* the property doesn't exist */ ! 726: IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' device-type property is wrong type\n", ! 727: getName(),provider->getName()); ! 728: return(NULL); ! 729: ! 730: } else { /* we got the property */ ! 731: string = prop->getCStringNoCopy(); ! 732: /** ! 733: IOLog("%s[IOHDDrive]:;probe; provider '%s' device-type property is '%s'\n", ! 734: getName(),provider->getName(),string); ! 735: **/ ! 736: if (strcmp(string,getDeviceTypeName()) != 0) { /* the value isn't what we want */ ! 737: /*** ! 738: IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' device type '%s' is wrong\n", ! 739: getName(),provider->getName(),string); ! 740: ***/ ! 741: return(NULL); ! 742: } ! 743: ! 744: /* The device type is right; now make sure the class is. */ ! 745: ! 746: if (setProvider(provider)) { /* the provider's class is what we expect */ ! 747: // IOLog("%s[IOHDDrive]:;probe; matching provider '%s'\n",getName(),_provider->getName()); ! 748: return(this); ! 749: } else { /* the provider's class is wrong, ignore it */ ! 750: IOLog("%s[IOHDDrive]:;probe; match failed: provider '%s' is wrong class\n", ! 751: getName(),provider->getName()); ! 752: return(NULL); ! 753: } ! 754: } ! 755: } ! 756: ! 757: IOReturn ! 758: IOHDDrive::recordAdditionalMediaParameters(void) ! 759: { ! 760: return(kIOReturnSuccess); /* default does nothing */ ! 761: } ! 762: ! 763: IOReturn ! 764: IOHDDrive::recordMediaParameters(void) ! 765: { ! 766: IOReturn result; ! 767: OSDictionary *propTable; ! 768: ! 769: /* Determine the device's block size and max block number. ! 770: * What should an unformatted device report? All zeroes, or an error? ! 771: */ ! 772: ! 773: result = _provider->reportBlockSize(&_mediaBlockSize); ! 774: if (result != kIOReturnSuccess) { ! 775: goto err; ! 776: } ! 777: ! 778: result = _provider->reportMaxValidBlock(&_maxBlockNumber); ! 779: if (result != kIOReturnSuccess) { ! 780: goto err; ! 781: } ! 782: ! 783: /* Calculate the maximum allowed byte transfers for reads and writes. */ ! 784: ! 785: result = _provider->reportMaxReadTransfer(_mediaBlockSize,&_maxReadByteTransfer); ! 786: if (result != kIOReturnSuccess) { ! 787: goto err; ! 788: } ! 789: ! 790: result = _provider->reportMaxWriteTransfer(_mediaBlockSize,&_maxWriteByteTransfer); ! 791: if (result != kIOReturnSuccess) { ! 792: goto err; ! 793: } ! 794: ! 795: /* Is the media write-protected? */ ! 796: ! 797: result = _provider->reportWriteProtection(&_writeProtected); ! 798: if (result != kIOReturnSuccess) { ! 799: goto err; ! 800: } ! 801: ! 802: /* Create media-related properties: */ ! 803: ! 804: propTable = constructMediaProperties(); ! 805: ! 806: // xxx what to do with propTable? xxx ! 807: ! 808: /* Record additional media-related information, ! 809: * and perhaps create properties. ! 810: */ ! 811: ! 812: result = recordAdditionalMediaParameters(); ! 813: if (result != kIOReturnSuccess) { ! 814: goto err; ! 815: } ! 816: ! 817: return(kIOReturnSuccess); /* everything was successful */ ! 818: ! 819: /* If we fall thru to here, we had some kind of error. Set everything to ! 820: * a reasonable state since we haven't got any real information. ! 821: */ ! 822: ! 823: err:; ! 824: _mediaPresent = false; ! 825: _writeProtected = true; ! 826: ! 827: return(result); ! 828: } ! 829: ! 830: void ! 831: IOHDDrive::rejectMedia(void) ! 832: { ! 833: (void)_provider->doEjectMedia(); /* eject it, ignoring any error */ ! 834: initMediaStates(); /* deny existence of new media */ ! 835: } ! 836: ! 837: void ! 838: IOHDDrive::RWCompletion(struct IOHDDrive::context *cx) ! 839: { ! 840: bool isWrite; ! 841: ! 842: _stats.providerCompletionsRcvd++; ! 843: ! 844: if (cx->result == kIOReturnSuccess) { ! 845: assert(cx->byteCount == cx->actualTransferCount); ! 846: } else { ! 847: IOLog("%s[IOHDDrive]::RWCompletion; result = %s, req=%d, actual=%d\n", ! 848: getName(),stringFromReturn(cx->result),(int)cx->byteCount, ! 849: (int)cx->actualTransferCount); ! 850: } ! 851: ! 852: if (cx->buffer->getDirection() == kIODirectionOut) { ! 853: isWrite = true; ! 854: } else { ! 855: isWrite = false; ! 856: } ! 857: ! 858: addToBytesTransferred(cx->actualTransferCount,0,0,isWrite); ! 859: if (cx->result != kIOReturnSuccess) { ! 860: incrementErrors(isWrite); ! 861: } ! 862: ! 863: if (cx->buffer) { ! 864: cx->buffer->complete(); ! 865: } ! 866: ! 867: /* Complete the client request, which was issued at executeRequest: */ ! 868: ! 869: assert(cx->completion.action); ! 870: ! 871: _stats.clientCompletionsSent++; ! 872: complete(cx->completion,cx->result,cx->actualTransferCount); ! 873: _stats.clientCompletionsDone++; ! 874: ! 875: if (showStats()) { ! 876: IOLog("%s[IOHDDrive]; RWCompletion: cr=%5d,ps=%5d,pr=%5d,pcr=%5d,ccs=%5d,ccd=%5d\n", ! 877: getName(), ! 878: _stats.clientReceived, ! 879: _stats.providerSent, ! 880: _stats.providerReject, ! 881: _stats.providerCompletionsRcvd, ! 882: _stats.clientCompletionsSent, ! 883: _stats.clientCompletionsDone); ! 884: } ! 885: deleteContext(cx); ! 886: } ! 887: ! 888: bool ! 889: IOHDDrive::setProvider(IOService * provider) ! 890: { ! 891: _provider = OSDynamicCast(IOHDDriveNub,provider); ! 892: ! 893: if (_provider == NULL) { ! 894: return(false); ! 895: } else { ! 896: return(true); ! 897: } ! 898: } ! 899: ! 900: bool ! 901: IOHDDrive::showStats(void) ! 902: { ! 903: return(false); ! 904: } ! 905: ! 906: /* Tear down the stack above the specified object. Usually these objects will ! 907: * be of type IOMedia, but they could be any IOService. ! 908: */ ! 909: IOReturn ! 910: IOHDDrive::tearDown(IOService *media) ! 911: { ! 912: IOReturn result; ! 913: ! 914: lockForArbitration(); ! 915: ! 916: if (media) { ! 917: if (media->terminate()) { ! 918: media->release(); ! 919: ! 920: initMediaStates(); /* clear all knowledge of the media */ ! 921: result = kIOReturnSuccess; ! 922: ! 923: } else { ! 924: result = kIOReturnBusy; ! 925: } ! 926: } else { ! 927: result = kIOReturnNoMedia; ! 928: } ! 929: ! 930: unlockForArbitration(); ! 931: ! 932: return(result); ! 933: } ! 934: ! 935: bool ! 936: IOHDDrive::validateNewMedia(void) ! 937: { ! 938: return(true); ! 939: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.