|
|
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 <machine/limits.h> // (ULONG_MAX, ...) ! 24: #include <IOKit/IODeviceTreeSupport.h> // (gIODTPlane, ...) ! 25: #include <IOKit/storage/IOMedia.h> ! 26: ! 27: #define super IOStorage ! 28: OSDefineMetaClassAndStructors(IOMedia, IOStorage) ! 29: ! 30: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 31: ! 32: bool IOMedia::init(UInt64 base, ! 33: UInt64 size, ! 34: UInt64 preferredBlockSize, ! 35: bool isEjectable, ! 36: bool isWhole, ! 37: bool isWritable, ! 38: const char * contentHint = 0, ! 39: OSDictionary * properties = 0) ! 40: { ! 41: // ! 42: // Initialize this object's minimal state. ! 43: // ! 44: ! 45: if (super::init(properties) == false) return false; ! 46: ! 47: _mediaBase = base; ! 48: _mediaSize = size; ! 49: _isEjectable = isEjectable; ! 50: _isWhole = isWhole; ! 51: _isWritable = isWritable; ! 52: _openLevel = kAccessNone; ! 53: _openReaders = OSSet::withCapacity(1); ! 54: _openReaderWriter = 0; ! 55: _preferredBlockSize = preferredBlockSize; ! 56: ! 57: if (_openReaders == 0) return false; ! 58: ! 59: // ! 60: // Create the standard media registry properties. ! 61: // ! 62: ! 63: setProperty(kIOMediaContent, contentHint ? contentHint : ""); ! 64: setProperty(kIOMediaContentHint, contentHint ? contentHint : ""); ! 65: setProperty(kIOMediaEjectable, isEjectable); ! 66: setProperty(kIOMediaLeaf, true); ! 67: setProperty(kIOMediaSize, size, 64); ! 68: setProperty(kIOMediaWhole, isWhole); ! 69: setProperty(kIOMediaWritable, isWritable); ! 70: ! 71: return true; ! 72: } ! 73: ! 74: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 75: ! 76: void IOMedia::free(void) ! 77: { ! 78: // ! 79: // Free all of this object's outstanding resources. ! 80: // ! 81: ! 82: if (_openReaders) _openReaders->release(); ! 83: ! 84: super::free(); ! 85: } ! 86: ! 87: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 88: ! 89: bool IOMedia::attachToChild(IORegistryEntry * client, ! 90: const IORegistryPlane * plane) ! 91: { ! 92: // ! 93: // This method is called for each client interested in the services we ! 94: // provide. The superclass links us as a parent to this client in the ! 95: // I/O Kit registry on success. ! 96: // ! 97: ! 98: OSString * s; ! 99: ! 100: // Ask our superclass' opinion. ! 101: ! 102: if (super::attachToChild(client, plane) == false) return false; ! 103: ! 104: // ! 105: // Determine whether the client is a storage object, which we consider ! 106: // to be a consumer of this storage object's content and a producer of ! 107: // new content. A storage object need not be an IOStorage subclass, so ! 108: // long as it identifies itself with a match category of "IOStorage". ! 109: // ! 110: // If the client is indeed a storage object, we reset the media's Leaf ! 111: // property to false and replace the media's Content property with the ! 112: // client's Content Mask property, if any. ! 113: // ! 114: ! 115: s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey)); ! 116: ! 117: if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory)) ! 118: { ! 119: setProperty(kIOMediaLeaf, false); ! 120: ! 121: s = OSDynamicCast(OSString, client->getProperty(kIOMediaContentMask)); ! 122: if (s) setProperty(kIOMediaContent, s->getCStringNoCopy()); ! 123: } ! 124: ! 125: return true; ! 126: } ! 127: ! 128: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 129: ! 130: void IOMedia::detachFromChild(IORegistryEntry * client, ! 131: const IORegistryPlane * plane) ! 132: { ! 133: // ! 134: // This method is called for each client that loses interest in the ! 135: // services we provide. The superclass unlinks us from this client ! 136: // in the I/O Kit registry on success. ! 137: // ! 138: // Note that this method is called at a nondeterministic time after ! 139: // our client is terminated, which means another client may already ! 140: // have arrived and attached in the meantime. This is not an issue ! 141: // should the termination be issued synchrnously, however, which we ! 142: // take advantage of when this media needs to eliminate one of its ! 143: // clients. If the termination was issued on this media or farther ! 144: // below in the hierarchy, we don't really care that the properties ! 145: // would not be consistent since this media object is going to die ! 146: // anyway. ! 147: // ! 148: ! 149: OSString * s; ! 150: ! 151: // ! 152: // Determine whether the client is a storage object, which we consider ! 153: // to be a consumer of this storage object's content and a producer of ! 154: // new content. A storage object need not be an IOStorage subclass, so ! 155: // long as it identifies itself with a match category of "IOStorage". ! 156: // ! 157: // If the client is indeed a storage object, we reset the media's Leaf ! 158: // property to true and reset the media's Content property to the hint ! 159: // we obtained when this media was initialized. ! 160: // ! 161: ! 162: s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey)); ! 163: ! 164: if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory)) ! 165: { ! 166: setProperty(kIOMediaContent, getContentHint()); ! 167: setProperty(kIOMediaLeaf, true); ! 168: } ! 169: ! 170: // Pass the call onto our superclass. ! 171: ! 172: super::detachFromChild(client, plane); ! 173: } ! 174: ! 175: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 176: ! 177: bool IOMedia::handleOpen(IOService * client, ! 178: IOOptionBits options, ! 179: void * argument) ! 180: { ! 181: // ! 182: // The handleOpen method grants or denies permission to access this object ! 183: // to an interested client. The argument is an IOStorageAccess value that ! 184: // specifies the level of access desired -- reader or reader-writer. ! 185: // ! 186: // This method can be invoked to upgrade or downgrade the access level for ! 187: // an existing client as well. The previous access level will prevail for ! 188: // upgrades that fail, of course. A downgrade should never fail. If the ! 189: // new access level should be the same as the old for a given client, this ! 190: // method will do nothing and return success. In all cases, one, singular ! 191: // close-per-client is expected for all opens-per-client received. ! 192: // ! 193: // This method will work even when the media is in the terminated state. ! 194: // ! 195: // We are guaranteed that no other opens or closes will be processed until ! 196: // we make our decision, change our state, and return from this method. ! 197: // ! 198: ! 199: IOStorageAccess access = (IOStorageAccess) (int) argument; ! 200: IOStorageAccess level; ! 201: ! 202: assert(client); ! 203: ! 204: // ! 205: // Chart our course of action. ! 206: // ! 207: ! 208: switch (access) ! 209: { ! 210: case kAccessReader: ! 211: { ! 212: if (_openReaders->containsObject(client)) // (access: no change) ! 213: return true; ! 214: else if (_openReaderWriter == client) // (access: downgrade) ! 215: level = kAccessReader; ! 216: else // (access: new reader) ! 217: level = _openReaderWriter ? kAccessReaderWriter : kAccessReader; ! 218: break; ! 219: } ! 220: case kAccessReaderWriter: ! 221: { ! 222: if (_openReaders->containsObject(client)) // (access: upgrade) ! 223: level = kAccessReaderWriter; ! 224: else if (_openReaderWriter == client) // (access: no change) ! 225: return true; ! 226: else // (access: new writer) ! 227: level = kAccessReaderWriter; ! 228: ! 229: if (_isWritable == false) // (is this media object writable?) ! 230: return false; ! 231: ! 232: if (_openReaderWriter) // (does a reader-writer already exist?) ! 233: return false; ! 234: ! 235: break; ! 236: } ! 237: default: ! 238: { ! 239: assert(0); ! 240: return false; ! 241: } ! 242: } ! 243: ! 244: // ! 245: // If we are in the terminated state, we only accept downgrades. ! 246: // ! 247: ! 248: if (isInactive() && _openReaderWriter != client) // (dead? not a downgrade?) ! 249: return false; ! 250: ! 251: // ! 252: // Determine whether the storage objects above us can be torn down, should ! 253: // this be a new reader-writer open or an upgrade into a reader-writer (if ! 254: // the client issuing the open is not a storage object itself, of course). ! 255: // ! 256: ! 257: if (access == kAccessReaderWriter) // (a new reader-writer or an upgrade?) ! 258: { ! 259: const OSSymbol * category = OSSymbol::withCString(kIOStorageCategory); ! 260: ! 261: if (category) ! 262: { ! 263: IOService * storageObject = getClientWithCategory(category); ! 264: category->release(); ! 265: ! 266: if (storageObject && storageObject != client) ! 267: { ! 268: if (storageObject->terminate(kIOServiceSynchronous) == false) ! 269: return false; ! 270: } ! 271: } ! 272: } ! 273: ! 274: // ! 275: // Determine whether the storage objects below us accept this open at this ! 276: // multiplexed level of access -- new opens, upgrades, and downgrades (and ! 277: // no changes in access) all enter through the same open api. ! 278: // ! 279: ! 280: if (_openLevel != level) // (has open level changed?) ! 281: { ! 282: IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); ! 283: ! 284: if (provider && provider->open(this, options, level) == false) ! 285: { ! 286: // ! 287: // We were unable to open the storage objects below us. We must ! 288: // recover from the terminate we issued above before bailing out, ! 289: // if applicable, by re-registering the media object for matching. ! 290: // ! 291: ! 292: if (access == kAccessReaderWriter) ! 293: registerService(kIOServiceSynchronous); // (re-register media) ! 294: ! 295: return false; ! 296: } ! 297: } ! 298: ! 299: // ! 300: // Process the open. ! 301: // ! 302: // We make sure our open state is consistent before calling registerService ! 303: // (if applicable) since this method can be called again on the same thread ! 304: // (the lock protecting handleOpen is recursive, so access would be given). ! 305: // ! 306: ! 307: _openLevel = level; ! 308: ! 309: if (access == kAccessReader) ! 310: { ! 311: _openReaders->setObject(client); ! 312: ! 313: if (_openReaderWriter == client) // (for a downgrade) ! 314: { ! 315: _openReaderWriter = 0; ! 316: registerService(kIOServiceSynchronous); // (re-register media) ! 317: } ! 318: } ! 319: else // (access == kAccessReaderWriter) ! 320: { ! 321: _openReaderWriter = client; ! 322: ! 323: _openReaders->removeObject(client); // (for an upgrade) ! 324: } ! 325: ! 326: return true; ! 327: } ! 328: ! 329: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 330: ! 331: bool IOMedia::handleIsOpen(const IOService * client) const ! 332: { ! 333: // ! 334: // The handleIsOpen method determines whether the specified client, or any ! 335: // client if none is specificed, presently has an open on this object. ! 336: // ! 337: // This method will work even when the media is in the terminated state. ! 338: // ! 339: // We are guaranteed that no other opens or closes will be processed until ! 340: // we return from this method. ! 341: // ! 342: ! 343: if (client == 0) return (_openLevel != kAccessNone); ! 344: ! 345: return ( _openReaderWriter == client || ! 346: _openReaders->containsObject(client) ); ! 347: } ! 348: ! 349: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 350: ! 351: void IOMedia::handleClose(IOService * client, IOOptionBits options) ! 352: { ! 353: // ! 354: // A client is informing us that it is giving up access to our contents. ! 355: // ! 356: // This method will work even when the media is in the terminated state. ! 357: // ! 358: // We are guaranteed that no other opens or closes will be processed until ! 359: // we change our state and return from this method. ! 360: // ! 361: ! 362: assert(client); ! 363: ! 364: // ! 365: // Process the close. ! 366: // ! 367: ! 368: bool reregister = (_openReaderWriter == client) && (isInactive() == false); ! 369: ! 370: if (_openReaderWriter == client) // (is the client a reader-writer?) ! 371: { ! 372: _openReaderWriter = 0; ! 373: } ! 374: else if (_openReaders->containsObject(client)) // (is the client a reader?) ! 375: { ! 376: _openReaders->removeObject(client); ! 377: } ! 378: else // (is the client is an imposter?) ! 379: { ! 380: assert(0); ! 381: return; ! 382: } ! 383: ! 384: // ! 385: // Reevaluate the open we have on the level below us. If no opens remain, ! 386: // we close, or if no reader-writer remains, but readers do, we downgrade. ! 387: // ! 388: ! 389: IOStorageAccess level; ! 390: ! 391: if (_openReaderWriter) level = kAccessReaderWriter; ! 392: else if (_openReaders->getCount()) level = kAccessReader; ! 393: else level = kAccessNone; ! 394: ! 395: if (_openLevel != level) // (has open level changed?) ! 396: { ! 397: IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); ! 398: ! 399: assert(level != kAccessReaderWriter); ! 400: ! 401: if (provider) ! 402: { ! 403: if (level == kAccessNone) // (is a close in order?) ! 404: { ! 405: provider->close(this, options); ! 406: } ! 407: else // (is a downgrade in order?) ! 408: { ! 409: bool success; ! 410: success = provider->open(this, 0, level); ! 411: assert(success); // (should never fail, unless avoided deadlock) ! 412: } ! 413: } ! 414: ! 415: _openLevel = level; // (set new open level) ! 416: } ! 417: ! 418: // ! 419: // If the reader-writer just closeed, re-register the media so that I/O Kit ! 420: // will attempt to match storage objects that may now be interested in this ! 421: // media. ! 422: // ! 423: // We make sure our open state is consistent before calling registerService ! 424: // (if applicable) since this method can be called again on the same thread ! 425: // (the lock protecting handleClose is recursive, so access would be given). ! 426: // ! 427: ! 428: if (reregister) ! 429: registerService(kIOServiceSynchronous); // (re-register media) ! 430: } ! 431: ! 432: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 433: ! 434: void IOMedia::read(IOService * /* client */, ! 435: UInt64 byteStart, ! 436: IOMemoryDescriptor * buffer, ! 437: IOStorageCompletion completion) ! 438: { ! 439: // ! 440: // Read data from the storage object at the specified byte offset into the ! 441: // specified buffer, asynchronously. When the read completes, the caller ! 442: // will be notified via the specified completion action. ! 443: // ! 444: // The buffer will be retained for the duration of the read. ! 445: // ! 446: // This method will work even when the media is in the terminated state. ! 447: // ! 448: ! 449: if (isInactive()) ! 450: { ! 451: complete(completion, kIOReturnNoMedia); ! 452: return; ! 453: } ! 454: ! 455: if (_openLevel == kAccessNone) // (instantaneous value, no lock) ! 456: { ! 457: complete(completion, kIOReturnNotOpen); ! 458: return; ! 459: } ! 460: ! 461: if (_mediaSize == 0 || _preferredBlockSize == 0) ! 462: { ! 463: complete(completion, kIOReturnUnformattedMedia); ! 464: return; ! 465: } ! 466: ! 467: if (_mediaSize < byteStart + buffer->getLength()) ! 468: { ! 469: complete(completion, kIOReturnBadArgument); ! 470: return; ! 471: } ! 472: ! 473: byteStart += _mediaBase; ! 474: getProvider()->read(this, byteStart, buffer, completion); ! 475: } ! 476: ! 477: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 478: ! 479: void IOMedia::write(IOService * client, ! 480: UInt64 byteStart, ! 481: IOMemoryDescriptor * buffer, ! 482: IOStorageCompletion completion) ! 483: { ! 484: // ! 485: // Write data into the storage object at the specified byte offset from the ! 486: // specified buffer, asynchronously. When the write completes, the caller ! 487: // will be notified via the specified completion action. ! 488: // ! 489: // The buffer will be retained for the duration of the write. ! 490: // ! 491: // This method will work even when the media is in the terminated state. ! 492: // ! 493: ! 494: if (isInactive()) ! 495: { ! 496: complete(completion, kIOReturnNoMedia); ! 497: return; ! 498: } ! 499: ! 500: if (_openLevel == kAccessNone) // (instantaneous value, no lock) ! 501: { ! 502: complete(completion, kIOReturnNotOpen); ! 503: return; ! 504: } ! 505: ! 506: if (_openReaderWriter != client) // (instantaneous value, no lock) ! 507: { ! 508: ///m:2425148:workaround:commented:start ! 509: // complete(completion, kIOReturnNotPrivileged); ! 510: // return; ! 511: ///m:2425148:workaround:commented:stop ! 512: } ! 513: ! 514: if (_isWritable == 0) ! 515: { ! 516: complete(completion, kIOReturnLockedWrite); ! 517: return; ! 518: } ! 519: ! 520: if (_mediaSize == 0 || _preferredBlockSize == 0) ! 521: { ! 522: complete(completion, kIOReturnUnformattedMedia); ! 523: return; ! 524: } ! 525: ! 526: if (_mediaSize < byteStart + buffer->getLength()) ! 527: { ! 528: complete(completion, kIOReturnBadArgument); ! 529: return; ! 530: } ! 531: ! 532: byteStart += _mediaBase; ! 533: getProvider()->write(this, byteStart, buffer, completion); ! 534: } ! 535: ! 536: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 537: ! 538: UInt64 IOMedia::getPreferredBlockSize() const ! 539: { ! 540: // ! 541: // Ask the media object for its natural block size. This information ! 542: // is useful to clients that want to optimize access to the media. ! 543: // ! 544: ! 545: return _preferredBlockSize; ! 546: } ! 547: ! 548: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 549: ! 550: UInt64 IOMedia::getSize() const ! 551: { ! 552: // ! 553: // Ask the media object for its total length in bytes. ! 554: // ! 555: ! 556: return _mediaSize; ! 557: } ! 558: ! 559: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 560: ! 561: UInt64 IOMedia::getBase() const ! 562: { ! 563: // ! 564: // Ask the media object for its byte offset relative to its provider media ! 565: // object below it in the storage hierarchy. ! 566: // ! 567: ! 568: return _mediaBase; ! 569: } ! 570: ! 571: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 572: ! 573: bool IOMedia::isEjectable() const ! 574: { ! 575: // ! 576: // Ask the media object whether it is ejectable. ! 577: // ! 578: ! 579: return _isEjectable; ! 580: } ! 581: ! 582: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 583: ! 584: bool IOMedia::isFormatted() const ! 585: { ! 586: // ! 587: // Ask the media object whether it is formatted. ! 588: // ! 589: ! 590: return (_mediaSize && _preferredBlockSize); ! 591: } ! 592: ! 593: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 594: ! 595: bool IOMedia::isWritable() const ! 596: { ! 597: // ! 598: // Ask the media object whether it is writable. ! 599: // ! 600: ! 601: return _isWritable; ! 602: } ! 603: ! 604: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 605: ! 606: bool IOMedia::isWhole() const ! 607: { ! 608: // ! 609: // Ask the media object whether it represents the whole disk. ! 610: // ! 611: ! 612: return _isWhole; ! 613: } ! 614: ! 615: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 616: ! 617: const char * IOMedia::getContent() const ! 618: { ! 619: // ! 620: // Ask the media object for a description of its contents. The description ! 621: // is the same as the hint at the time of the object's creation, but it is ! 622: // possible that the description be overrided by a client (which has probed ! 623: // the media and identified the content correctly) of the media object. It ! 624: // is more accurate than the hint for this reason. The string is formed in ! 625: // the likeness of Apple's "Apple_HFS" strings. ! 626: // ! 627: // The content description can be overrided by any client that matches onto ! 628: // this media object with a match category of kIOStorageCategory. The media ! 629: // object checks for a kIOMediaContentMask property in the client, and if it ! 630: // finds one, it copies it into kIOMediaContent property. ! 631: // property with it. ! 632: // ! 633: ! 634: OSString * string; ! 635: ! 636: string = OSDynamicCast(OSString, getProperty(kIOMediaContent)); ! 637: if (string == 0) return ""; ! 638: return string->getCStringNoCopy(); ! 639: } ! 640: ! 641: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 642: ! 643: const char * IOMedia::getContentHint() const ! 644: { ! 645: // ! 646: // Ask the media object for a hint of its contents. The hint is set at the ! 647: // time of the object's creation, should the creator have a clue as to what ! 648: // it may contain. The hint string does not change for the lifetime of the ! 649: // object and is also formed in the likeness of Apple's "Apple_HFS" strings. ! 650: // ! 651: ! 652: OSString * string; ! 653: ! 654: string = OSDynamicCast(OSString, getProperty(kIOMediaContentHint)); ! 655: if (string == 0) return ""; ! 656: return string->getCStringNoCopy(); ! 657: } ! 658: ! 659: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 660: ! 661: IOService * IOMedia::matchLocation(IOService * client) ! 662: { ! 663: // ! 664: // I/O Kit is in the process of searching for a candidate object that wishes ! 665: // to match against an IOLocation={x} dictionary of properties. This is the ! 666: // method called to determine whether this object wants to be the candidate. ! 667: // ! 668: // The matchLocation method should return "this" if it decides to match with ! 669: // the IOLocation={x} dictionary, otherwise it should call the superclass to ! 670: // continue with the search and skip this object as a candidate. ! 671: // ! 672: // If this object chooses to match, the dictionary {x} will be passed to the ! 673: // standard (passive) matching method matchPropertyTable for comparison. ! 674: // ! 675: ! 676: if (isWhole() == false) ! 677: { ! 678: // We elect to be the candidate object for the IOLocation={x} dictionary ! 679: // only if we are a non-whole media; whole medias have no "location" per ! 680: // se. ! 681: ! 682: assert(getLocation() && strcmp(getLocation(), "")); ! 683: return this; // ("please compare us") ! 684: } ! 685: ! 686: return super::matchLocation(client); // ("please skip over us") ! 687: } ! 688: ! 689: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 690: ! 691: bool IOMedia::matchPropertyTable(OSDictionary * table) ! 692: { ! 693: // ! 694: // Compare the properties in the supplied table to this object's properties. ! 695: // ! 696: ! 697: OSString * string; ! 698: ! 699: // Ask our superclass' opinion. ! 700: ! 701: if (super::matchPropertyTable(table) == false) return false; ! 702: ! 703: // Determine whether the "IOPath Extension" property is in the comparison ! 704: // dictionary. If it is, we compare this media's location against it. ! 705: ! 706: string = OSDynamicCast(OSString, table->getObject("IOPath Extension")); ! 707: ! 708: if (string) // (does "IOPath Extension" exist?) ! 709: { ! 710: const char * location = getLocation(); ! 711: ! 712: if (location == 0 && isWhole() == false) return false; ! 713: ! 714: UInt32 value1 = location ? strtoul(location, 0, 10) : 0; ! 715: UInt32 value2 = strtoul(string->getCStringNoCopy(), 0, 10); ! 716: ! 717: if (value1 == ULONG_MAX || value2 == ULONG_MAX) return false; ! 718: if (value1 != value2) return false; ! 719: } ! 720: ! 721: // Ensure the "IOProviderClass" property is present in the comparison ! 722: // dictionary, and that the given class name belongs to this object's ! 723: // inheritance chain. ! 724: ! 725: string = OSDynamicCast(OSString, table->getObject(gIOProviderClassKey)); ! 726: ! 727: if (string == 0 || metaCast(string) == 0) return false; ! 728: ! 729: // We return success if the following expression is true -- individual ! 730: // comparisions evaluate to truth if the named property is not present ! 731: // in the supplied table. ! 732: ! 733: return compareProperty(table, kIOMediaContent) && ! 734: compareProperty(table, kIOMediaContentHint) && ! 735: compareProperty(table, kIOMediaEjectable) && ! 736: compareProperty(table, kIOMediaLeaf) && ! 737: compareProperty(table, kIOMediaSize) && ! 738: compareProperty(table, kIOMediaWhole) && ! 739: compareProperty(table, kIOMediaWritable) ; ! 740: } ! 741: ! 742: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 743: ! 744: bool IOMedia::getPath( char * path, ! 745: int * length, ! 746: const IORegistryPlane * plane ) const ! 747: { ! 748: // ! 749: // Obtain a path to this service object. ! 750: // ! 751: // This method will work even when the media is in the terminated state. ! 752: // ! 753: ! 754: IOMedia * media; ! 755: IOService * next; ! 756: OSNumber * number; ! 757: bool success = false; ! 758: int unit = -1, partition = 0; ! 759: int len, maxlen; ! 760: ! 761: if ( isInactive() ) return false; ! 762: ! 763: if ( (plane == gIODTPlane) && length ) ! 764: { ! 765: maxlen = *length; ! 766: ! 767: for (next = (IOService *) this; next; next = next->getProvider()) ! 768: { ! 769: *length = maxlen; ! 770: media = OSDynamicCast(IOMedia, next); ! 771: ! 772: if ( media && media->isWhole() == false && media->getLocation() ) ! 773: partition = strtoul(media->getLocation(), 0, 10); ! 774: else if ( (number = (OSNumber *) next->getProperty("IOUnit")) ) ! 775: unit = number->unsigned32BitValue(); ! 776: else if( !media && next->getPath( path, length, plane )) ! 777: break; ! 778: } ! 779: ! 780: if (next && (unit != -1) && (partition != -1)) { ! 781: // add the @unit:partition ! 782: len = *length; ! 783: maxlen -= len; ! 784: success = (maxlen > 20); ! 785: if( success ) { ! 786: len += sprintf( path + len, "/@%x:%d", unit, partition ); ! 787: *length = len; ! 788: } ! 789: } ! 790: ! 791: } ! 792: else ! 793: { ! 794: success = super::getPath(path, length, plane); ! 795: } ! 796: ! 797: return success; ! 798: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.