1/* 2 * Copyright (c) 1998-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <IOKit/assert.h> 25#include <IOKit/IODeviceTreeSupport.h> 26#include <IOKit/IOKitKeys.h> 27#include <IOKit/IOLib.h> 28#include <IOKit/IOMapper.h> 29#include <IOKit/IOMemoryDescriptor.h> 30#include <IOKit/IOSubMemoryDescriptor.h> 31#include <IOKit/pwr_mgt/RootDomain.h> 32#include <IOKit/storage/IOBlockStorageDevice.h> 33#include <IOKit/storage/IOBlockStorageDriver.h> 34#include <IOKit/storage/IOMedia.h> 35#include <kern/thread_call.h> 36 37#define super IOStorage 38OSDefineMetaClassAndStructors(IOBlockStorageDriver, IOStorage) 39 40#ifdef __LP64__ 41#define original request 42#else /* !__LP64__ */ 43#define isMediaRemovable() _removable 44#endif /* !__LP64__ */ 45 46#ifndef __LP64__ 47#define kIOBlockStorageDriverAttributesUnsupported ( ( IOStorage::ExpansionData * ) 2 ) 48 49extern IOStorageAttributes gIOStorageAttributesUnsupported; 50 51extern "C" void _ZN20IOBlockStorageDriver14prepareRequestEyP18IOMemoryDescriptor19IOStorageCompletion( IOBlockStorageDriver *, UInt64, IOMemoryDescriptor *, IOStorageCompletion ); 52 53#define prepareRequestAttributes( driver ) ( OSMemberFunctionCast( void *, driver, ( void ( IOBlockStorageDriver::* )( UInt64, IOMemoryDescriptor *, IOStorageCompletion ) ) &IOBlockStorageDriver::prepareRequest ) == _ZN20IOBlockStorageDriver14prepareRequestEyP18IOMemoryDescriptor19IOStorageCompletion ) 54#endif /* !__LP64__ */ 55 56static char * strclean(char * s) 57{ 58 // 59 // strclean() trims any spaces at either end of the string, strips any 60 // control characters within the string, and collapses any sequence of 61 // spaces within the string into a single space. 62 // 63 64 int sourceIndex = 0, targetIndex = 0, targetLength = 0; 65 66 for ( ; s[sourceIndex] > '\0' && s[sourceIndex] <= ' '; sourceIndex++ ); 67 68 for ( ; s[sourceIndex]; sourceIndex++ ) 69 { 70 if ( s[sourceIndex] < '\0' || s[sourceIndex] >= ' ' ) 71 { 72 if ( s[sourceIndex] != ' ' ) 73 { 74 if ( targetLength < targetIndex ) 75 { 76 targetIndex = targetLength + 1; 77 } 78 79 targetLength = targetIndex + 1; 80 } 81 82 s[targetIndex++] = s[sourceIndex]; 83 } 84 } 85 86 s[targetLength] = '\0'; 87 88 return s; 89} 90 91IOBlockStorageDevice * IOBlockStorageDriver::getProvider() const 92{ 93 // 94 // Obtain this object's provider. We override the superclass's method to 95 // return a more specific subclass of IOService -- IOBlockStorageDevice. 96 // This method serves simply as a convenience to subclass developers. 97 // 98 99 return (IOBlockStorageDevice *) IOService::getProvider(); 100} 101 102bool IOBlockStorageDriver::init(OSDictionary * properties) 103{ 104 // 105 // Initialize this object's minimal state. 106 // 107 108#ifndef __LP64__ 109 if (prepareRequestAttributes(this) == false) 110 IOStorage::_expansionData = kIOBlockStorageDriverAttributesUnsupported; 111#endif /* !__LP64__ */ 112 113 // Ask our superclass' opinion. 114 115 if (super::init(properties) == false) return false; 116 117 // Initialize our state. 118 119 _expansionData = IONew(ExpansionData, 1); 120 if (_expansionData == 0) return false; 121 122 initMediaState(); 123 124 _ejectable = false; 125 _removable = false; 126 127 _mediaBlockSize = 0; 128 _maxBlockNumber = 0; 129 _writeProtected = false; 130 131 _maxReadBlockTransfer = 0; 132 _maxWriteBlockTransfer = 0; 133 _maxReadByteTransfer = 0; 134 _maxWriteByteTransfer = 0; 135 _maxReadSegmentTransfer = 0; 136 _maxWriteSegmentTransfer = 0; 137 _maxReadSegmentByteTransfer = 0; 138 _maxWriteSegmentByteTransfer = 0; 139 _minSegmentAlignmentByteTransfer = 4; 140 _maxSegmentWidthByteTransfer = 0; 141 142 _contexts = NULL; 143 _contextsLock = IOSimpleLockAlloc(); 144 _contextsCount = 0; 145 _contextsMaxCount = 32; 146 147 if (_contextsLock == 0) 148 return false; 149 150 _deblockRequestWriteLock = IOLockAlloc(); 151 _deblockRequestWriteLockCount = 0; 152 _openAssertions = 0; 153 _openClients = OSSet::withCapacity(2); 154 _powerEventNotifier = 0; 155 156 for (unsigned index = 0; index < kStatisticsCount; index++) 157 _statistics[index] = OSNumber::withNumber(0ULL, 64); 158 159 if (_deblockRequestWriteLock == 0 || _openClients == 0) 160 return false; 161 162 for (unsigned index = 0; index < kStatisticsCount; index++) 163 if (_statistics[index] == 0) return false; 164 165 // Create our registry properties. 166 167 OSDictionary * statistics = OSDictionary::withCapacity(kStatisticsCount); 168 169 if (statistics == 0) return false; 170 171 statistics->setObject( kIOBlockStorageDriverStatisticsBytesReadKey, 172 _statistics[kStatisticsBytesRead] ); 173 statistics->setObject( kIOBlockStorageDriverStatisticsBytesWrittenKey, 174 _statistics[kStatisticsBytesWritten] ); 175 statistics->setObject( kIOBlockStorageDriverStatisticsReadErrorsKey, 176 _statistics[kStatisticsReadErrors] ); 177 statistics->setObject( kIOBlockStorageDriverStatisticsWriteErrorsKey, 178 _statistics[kStatisticsWriteErrors] ); 179 statistics->setObject( kIOBlockStorageDriverStatisticsLatentReadTimeKey, 180 _statistics[kStatisticsLatentReadTime] ); 181 statistics->setObject( kIOBlockStorageDriverStatisticsLatentWriteTimeKey, 182 _statistics[kStatisticsLatentWriteTime] ); 183 statistics->setObject( kIOBlockStorageDriverStatisticsReadsKey, 184 _statistics[kStatisticsReads] ); 185 statistics->setObject( kIOBlockStorageDriverStatisticsWritesKey, 186 _statistics[kStatisticsWrites] ); 187 statistics->setObject( kIOBlockStorageDriverStatisticsReadRetriesKey, 188 _statistics[kStatisticsReadRetries] ); 189 statistics->setObject( kIOBlockStorageDriverStatisticsWriteRetriesKey, 190 _statistics[kStatisticsWriteRetries] ); 191 statistics->setObject( kIOBlockStorageDriverStatisticsTotalReadTimeKey, 192 _statistics[kStatisticsTotalReadTime] ); 193 statistics->setObject( kIOBlockStorageDriverStatisticsTotalWriteTimeKey, 194 _statistics[kStatisticsTotalWriteTime] ); 195 196 setProperty(kIOBlockStorageDriverStatisticsKey, statistics); 197 198 statistics->release(); 199 200 return true; 201} 202 203bool IOBlockStorageDriver::start(IOService * provider) 204{ 205 // 206 // This method is called once we have been attached to the provider object. 207 // 208 209 bool success; 210 211 // Open the block storage device. 212 213 success = open(this); 214 215 if (success) 216 { 217 // Prepare the block storage driver for operation. 218 219 success = handleStart(provider); 220 221 // Close the block storage device. 222 223 close(this); 224 } 225 226 if (success) 227 { 228 // Register this object so it can be found via notification requests. It is 229 // not being registered to have I/O Kit attempt to have drivers match on it, 230 // which is the reason most other services are registered -- that's not the 231 // intention of this registerService call. 232 233 registerService(); 234 } 235 236 return success; 237} 238 239bool IOBlockStorageDriver::didTerminate(IOService * provider, 240 IOOptionBits options, 241 bool * defer) 242{ 243 // Try to teardown. 244 245 decommissionMedia(false); 246 247 return super::didTerminate(provider, options, defer); 248} 249 250bool IOBlockStorageDriver::yield(IOService * provider, 251 IOOptionBits options, 252 void * argument) 253{ 254 return false; 255} 256 257void IOBlockStorageDriver::free() 258{ 259 // 260 // Free all of this object's outstanding resources. 261 // 262 263 while (_contexts) 264 { 265 Context * context = _contexts; 266 267 _contexts = context->next; 268 _contextsCount--; 269 270 IODelete(context, Context, 1); 271 } 272 273 if (_contextsLock) IOSimpleLockFree(_contextsLock); 274 275 if (_deblockRequestWriteLock) IOLockFree(_deblockRequestWriteLock); 276 if (_openClients) _openClients->release(); 277 278 for (unsigned index = 0; index < kStatisticsCount; index++) 279 if (_statistics[index]) _statistics[index]->release(); 280 281 if (_expansionData) IODelete(_expansionData, ExpansionData, 1); 282 283 super::free(); 284} 285 286bool IOBlockStorageDriver::handleOpen(IOService * client, 287 IOOptionBits options, 288 void * argument) 289{ 290 // 291 // The handleOpen method grants or denies permission to access this object 292 // to an interested client. The argument is an IOStorageAccess value that 293 // specifies the level of access desired -- reader or reader-writer. 294 // 295 // This method can be invoked to upgrade or downgrade the access level for 296 // an existing client as well. The previous access level will prevail for 297 // upgrades that fail, of course. A downgrade should never fail. If the 298 // new access level should be the same as the old for a given client, this 299 // method will do nothing and return success. In all cases, one, singular 300 // close-per-client is expected for all opens-per-client received. 301 // 302 // This method assumes that the arbitration lock is held. 303 // 304 305 assert(client); 306 307 // Ensure there is media in the block storage device. 308 309 if (client != this) 310 { 311 if (_mediaObject == NULL) 312 { 313 return false; 314 } 315 } 316 317 // Handle the first open in a special case. 318 319 if (_openClients->getCount() == 0) 320 { 321 // Open the block storage device. 322 323 if (getProvider()->open(this) == false) 324 { 325 return false; 326 } 327 } 328 329 // Process the open. 330 331 if (client != this) 332 { 333 _openClients->setObject(client); 334 } 335 else 336 { 337 if (_openAssertions == 0) 338 { 339 _openClients->setObject(client); 340 } 341 342 _openAssertions++; 343 } 344 345 return true; 346} 347 348bool IOBlockStorageDriver::handleIsOpen(const IOService * client) const 349{ 350 // 351 // The handleIsOpen method determines whether the specified client, or any 352 // client if none is specificed, presently has an open on this object. 353 // 354 // This method assumes that the arbitration lock is held. 355 // 356 357 if (client) 358 { 359 return _openClients->containsObject(client); 360 } 361 else 362 { 363 return _openClients->getCount() ? true : false; 364 } 365} 366 367void IOBlockStorageDriver::handleClose(IOService * client, IOOptionBits options) 368{ 369 // 370 // The handleClose method drops the incoming client's access to this object. 371 // 372 // This method assumes that the arbitration lock is held. 373 // 374 375 assert(client); 376 377 // Process the close. 378 379 if (client != this) 380 { 381 _openClients->removeObject(client); 382 } 383 else 384 { 385 _openAssertions--; 386 387 if (_openAssertions == 0) 388 { 389 _openClients->removeObject(client); 390 } 391 } 392 393 // Handle the last close in a special case. 394 395 if (_openClients->getCount() == 0) 396 { 397 if (_mediaObject) 398 { 399 if (_mediaObject->isInactive()) 400 { 401 message(kIOMessageServiceIsRequestingClose, getProvider(), 0); 402 } 403 } 404 405 // Close the block storage device. 406 407 getProvider()->close(this); 408 } 409} 410 411void IOBlockStorageDriver::read(IOService * client, 412 UInt64 byteStart, 413 IOMemoryDescriptor * buffer, 414 IOStorageAttributes * attributes, 415 IOStorageCompletion * completion) 416{ 417 // 418 // The read method is the receiving end for all read requests from the 419 // storage framework, ie. via the media object created by this driver. 420 // 421 // This method initiates a sequence of methods (stages) for each read/write 422 // request. The first is prepareRequest, which allocates and prepares some 423 // context for the transfer; the second is deblockRequest, which aligns the 424 // transfer at the media's block boundaries; third is breakUpRequest, which 425 // breaks up the transfer into multiple sub-transfers when certain hardware 426 // constraints are exceeded; fourth is executeRequest, which implements the 427 // actual transfer from the block storage device. 428 // 429 430 // State our assumptions. 431 432 assert( buffer->getDirection( ) == kIODirectionIn ); 433 434 // Prepare the transfer. 435 436#ifndef __LP64__ 437 if ( IOStorage::_expansionData ) 438 { 439 if ( attributes == &gIOStorageAttributesUnsupported ) 440 { 441 attributes = NULL; 442 443 if ( IOStorage::_expansionData == kIOBlockStorageDriverAttributesUnsupported ) 444 { 445 prepareRequest( byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 446 447 return; 448 } 449 } 450 else 451 { 452 if ( attributes && attributes->options ) 453 { 454 complete( completion, kIOReturnUnsupported ); 455 } 456 else 457 { 458 if ( IOStorage::_expansionData == kIOBlockStorageDriverAttributesUnsupported ) 459 { 460 prepareRequest( byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 461 } 462 else 463 { 464 read( client, byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 465 } 466 } 467 468 return; 469 } 470 } 471#endif /* !__LP64__ */ 472 473 prepareRequest( byteStart, buffer, attributes, completion ); 474} 475 476void IOBlockStorageDriver::write(IOService * client, 477 UInt64 byteStart, 478 IOMemoryDescriptor * buffer, 479 IOStorageAttributes * attributes, 480 IOStorageCompletion * completion) 481{ 482 // 483 // The write method is the receiving end for all write requests from the 484 // storage framework, ie. via the media object created by this driver. 485 // 486 // This method initiates a sequence of methods (stages) for each read/write 487 // request. The first is prepareRequest, which allocates and prepares some 488 // context for the transfer; the second is deblockRequest, which aligns the 489 // transfer at the media's block boundaries; third is breakUpRequest, which 490 // breaks up the transfer into multiple sub-transfers when certain hardware 491 // constraints are exceeded; fourth is executeRequest, which implements the 492 // actual transfer from the block storage device. 493 // 494 495 // State our assumptions. 496 497 assert( buffer->getDirection( ) == kIODirectionOut ); 498 499 // Prepare the transfer. 500 501#ifndef __LP64__ 502 if ( IOStorage::_expansionData ) 503 { 504 if ( attributes == &gIOStorageAttributesUnsupported ) 505 { 506 attributes = NULL; 507 508 if ( IOStorage::_expansionData == kIOBlockStorageDriverAttributesUnsupported ) 509 { 510 prepareRequest( byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 511 512 return; 513 } 514 } 515 else 516 { 517 if ( attributes && attributes->options ) 518 { 519 complete( completion, kIOReturnUnsupported ); 520 } 521 else 522 { 523 if ( IOStorage::_expansionData == kIOBlockStorageDriverAttributesUnsupported ) 524 { 525 prepareRequest( byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 526 } 527 else 528 { 529 write( client, byteStart, buffer, completion ? *completion : ( IOStorageCompletion ) { 0 } ); 530 } 531 } 532 533 return; 534 } 535 } 536#endif /* !__LP64__ */ 537 538 prepareRequest( byteStart, buffer, attributes, completion ); 539} 540 541void IOBlockStorageDriver::addToBytesTransferred(UInt64 bytesTransferred, 542 UInt64 totalTime, // (ns) 543 UInt64 latentTime, // (ns) 544 bool isWrite) 545{ 546 // 547 // Update the total number of bytes transferred, the total transfer time, 548 // and the total latency time -- used for statistics. 549 // 550 551 if (isWrite) 552 { 553 _statistics[kStatisticsWrites]->addValue(1); 554 _statistics[kStatisticsBytesWritten]->addValue(bytesTransferred); 555 _statistics[kStatisticsTotalWriteTime]->addValue(totalTime); 556 _statistics[kStatisticsLatentWriteTime]->addValue(latentTime); 557 } 558 else 559 { 560 _statistics[kStatisticsReads]->addValue(1); 561 _statistics[kStatisticsBytesRead]->addValue(bytesTransferred); 562 _statistics[kStatisticsTotalReadTime]->addValue(totalTime); 563 _statistics[kStatisticsLatentReadTime]->addValue(latentTime); 564 } 565} 566 567void IOBlockStorageDriver::incrementRetries(bool isWrite) 568{ 569 // 570 // Update the total retry count -- used for statistics. 571 // 572 573 if (isWrite) 574 _statistics[kStatisticsWriteRetries]->addValue(1); 575 else 576 _statistics[kStatisticsReadRetries]->addValue(1); 577} 578 579void IOBlockStorageDriver::incrementErrors(bool isWrite) 580{ 581 // 582 // Update the total error count -- used for statistics. 583 // 584 585 if (isWrite) 586 _statistics[kStatisticsWriteErrors]->addValue(1); 587 else 588 _statistics[kStatisticsReadErrors]->addValue(1); 589} 590 591UInt32 IOBlockStorageDriver::getStatistics(UInt64 * statistics, 592 UInt32 statisticsMaxCount) const 593{ 594 // 595 // Ask the driver to report its operating statistics. 596 // 597 // The statistics are each indexed by IOBlockStorageDriver::Statistics 598 // indices. This routine fills the caller's buffer, up to the maximum 599 // count specified if the real number of statistics would overflow the 600 // buffer. The return value indicates the actual number of statistics 601 // copied to the buffer. 602 // 603 // If the statistics buffer is not supplied or if the maximum count is 604 // zero, the routine returns the proposed count of statistics instead. 605 // 606 607 if (statistics == 0) 608 return kStatisticsCount; 609 610 UInt32 statisticsCount = min(kStatisticsCount, statisticsMaxCount); 611 612 for (unsigned index = 0; index < statisticsCount; index++) 613 statistics[index] = _statistics[index]->unsigned64BitValue(); 614 615 return statisticsCount; 616} 617 618UInt64 IOBlockStorageDriver::getStatistic(Statistics statistic) const 619{ 620 // 621 // Ask the driver to report one of its operating statistics. 622 // 623 624 if ((UInt32) statistic >= kStatisticsCount) return 0; 625 626 return _statistics[statistic]->unsigned64BitValue(); 627} 628 629IOBlockStorageDriver::Context * IOBlockStorageDriver::allocateContext() 630{ 631 // 632 // Allocate a context structure for a read/write operation. 633 // 634 635 Context * context; 636 637 IOSimpleLockLock(_contextsLock); 638 639 context = _contexts; 640 641 if (context) 642 { 643 _contexts = context->next; 644 _contextsCount--; 645 } 646 647 IOSimpleLockUnlock(_contextsLock); 648 649 if (context == 0) 650 { 651 context = IONew(Context, 1); 652 } 653 654 if (context) 655 { 656 bzero(context, sizeof(Context)); 657 } 658 659 return context; 660} 661 662void IOBlockStorageDriver::deleteContext( 663 IOBlockStorageDriver::Context * context) 664{ 665 // 666 // Delete a context structure from a read/write operation. 667 // 668 669 IOSimpleLockLock(_contextsLock); 670 671 if (_contextsCount < _contextsMaxCount) 672 { 673 context->next = _contexts; 674 675 _contexts = context; 676 _contextsCount++; 677 678 context = 0; 679 } 680 681 IOSimpleLockUnlock(_contextsLock); 682 683 if (context) 684 { 685 IODelete(context, Context, 1); 686 } 687} 688 689#ifndef __LP64__ 690void IOBlockStorageDriver::prepareRequest(UInt64 byteStart, 691 IOMemoryDescriptor * buffer, 692 IOStorageCompletion completion) 693{ 694 // 695 // The prepareRequest method allocates and prepares state for the transfer. 696 // 697 // This method is part of a sequence of methods invoked for each read/write 698 // request. The first is prepareRequest, which allocates and prepares some 699 // context for the transfer; the second is deblockRequest, which aligns the 700 // transfer at the media's block boundaries; third is breakUpRequest, which 701 // breaks up the transfer into multiple sub-transfers when certain hardware 702 // constraints are exceeded; fourth is executeRequest, which implements the 703 // actual transfer from the block storage device. 704 // 705 706 prepareRequest( byteStart, buffer, NULL, &completion ); 707} 708#endif /* !__LP64__ */ 709 710void IOBlockStorageDriver::prepareRequestCompletion(void * target, 711 void * parameter, 712 IOReturn status, 713 UInt64 actualByteCount) 714{ 715 // 716 // This is the completion routine for the prepared request. It updates 717 // the driver's statistics, performs some clean up work, then calls the 718 // original request's completion routine. 719 // 720 721 Context * context = (Context *) parameter; 722 IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; 723 bool isWrite; 724 AbsoluteTime time; 725 UInt64 timeInNanoseconds; 726 727 isWrite = (context->original.buffer->getDirection() == kIODirectionOut); 728 729 // Update the error state, on a short transfer. 730 731 if (actualByteCount < context->original.buffer->getLength()) 732 { 733 if (status == kIOReturnSuccess) 734 { 735 status = kIOReturnUnderrun; 736 } 737 } 738 739 // Update the total number of bytes transferred and the total transfer time. 740 741 clock_get_uptime(&time); 742 SUB_ABSOLUTETIME(&time, &context->timeStart); 743 absolutetime_to_nanoseconds(time, &timeInNanoseconds); 744 745 driver->addToBytesTransferred(actualByteCount, timeInNanoseconds, 0, isWrite); 746 747 // Update the total error count. 748 749 if (status != kIOReturnSuccess) 750 { 751 driver->incrementErrors(isWrite); 752 } 753 754 // Complete the transfer request. 755 756 IOStorage::complete(&context->original.completion, status, actualByteCount); 757 758 // Release our resources. 759 760 context->original.buffer->release(); 761 762 driver->deleteContext(context); 763} 764 765void IOBlockStorageDriver::schedulePoller() 766{ 767 768} 769 770void IOBlockStorageDriver::unschedulePoller() 771{ 772 773} 774 775IOReturn IOBlockStorageDriver::message(UInt32 type, 776 IOService * provider, 777 void * argument) 778{ 779 // 780 // Generic entry point for calls from the provider. A return value of 781 // kIOReturnSuccess indicates that the message was received, and where 782 // applicable, that it was successful. 783 // 784 785 switch (type) 786 { 787 case kIOMessageMediaParametersHaveChanged: 788 { 789 IOReturn status; 790 if (open(this)) { 791 status = recordMediaParameters(); 792 if (status == kIOReturnSuccess) { 793 UInt64 nbytes; 794 IOMedia *m; 795 if (_maxBlockNumber) { 796 nbytes = _mediaBlockSize * (_maxBlockNumber + 1); 797 } else { 798 nbytes = 0; 799 } 800 m = instantiateMediaObject(0,nbytes,_mediaBlockSize,NULL); 801 if (m) { 802 lockForArbitration(); 803 if (_mediaObject) { 804 _mediaObject->init( m->getBase(), 805 m->getSize(), 806 m->getPreferredBlockSize(), 807 m->getAttributes(), 808 m->isWhole(), 809 m->isWritable(), 810 m->getContentHint() ); 811 _mediaObject->messageClients(kIOMessageServicePropertyChange); 812 } else { 813 status = kIOReturnNoMedia; 814 } 815 unlockForArbitration(); 816 m->release(); 817 } else { 818 status = kIOReturnBadArgument; 819 } 820 } 821 close(this); 822 } else { 823 status = kIOReturnNotAttached; 824 } 825 return status; 826 } 827 case kIOMessageMediaStateHasChanged: 828 { 829 IOReturn status; 830 if (open(this)) { 831 status = mediaStateHasChanged((uintptr_t) argument); 832 close(this); 833 } else { 834 status = kIOReturnNotAttached; 835 } 836 return status; 837 } 838 case kIOMessageServiceIsRequestingClose: 839 { 840 IOReturn status; 841 status = decommissionMedia(false); 842 return status; 843 } 844 default: 845 { 846 return super::message(type, provider, argument); 847 } 848 } 849} 850 851/* Accept a new piece of media, doing whatever's necessary to make it 852 * show up properly to the system. The arbitration lock is assumed to 853 * be held during the call. 854 */ 855IOReturn 856IOBlockStorageDriver::acceptNewMedia(void) 857{ 858 IOReturn result; 859 bool ok; 860 UInt64 nbytes; 861 char name[128]; 862 bool nameSep; 863 IOMedia *m; 864 865 if (_maxBlockNumber) { 866 nbytes = _mediaBlockSize * (_maxBlockNumber + 1); 867 } else { 868 nbytes = 0; 869 } 870 871 /* Instantiate a media object and attach it to ourselves. */ 872 873 name[0] = 0; 874 nameSep = false; 875 if (getProvider()->getVendorString()) { 876 strlcat(name, getProvider()->getVendorString(), sizeof(name) - strlen(name)); 877 nameSep = true; 878 } 879 if (getProvider()->getProductString()) { 880 if (nameSep == true) strlcat(name, " ", sizeof(name) - strlen(name)); 881 strlcat(name, getProvider()->getProductString(), sizeof(name) - strlen(name)); 882 nameSep = true; 883 } 884 if (nameSep == true) strlcat(name, " ", sizeof(name) - strlen(name)); 885 strlcat(name, "Media", sizeof(name) - strlen(name)); 886 strclean(name); 887 888 m = instantiateMediaObject(0,nbytes,_mediaBlockSize,name); 889 result = (m) ? kIOReturnSuccess : kIOReturnBadArgument; 890 891 if (result == kIOReturnSuccess) { 892 if (getProperty(kIOMediaIconKey, gIOServicePlane)) { 893 m->removeProperty(kIOMediaIconKey); 894 } 895 ok = m->attach(this); /* attach media object above us */ 896 if (ok) { 897 IOService *parent = this; 898 OSNumber *unit = NULL; 899 OSNumber *unitLUN = NULL; 900 OSString *unitName = NULL; 901 902 /* Wire the media object to the device tree. */ 903 904 while ((parent = parent->getProvider())) { 905 if (!unit) { 906 unit = OSDynamicCast(OSNumber, parent->getProperty("IOUnit")); 907 } 908 if (!unitLUN) { 909 unitLUN = OSDynamicCast(OSNumber, parent->getProperty("IOUnitLUN")); 910 } 911 if (!unitName) { 912 unitName = OSDynamicCast(OSString, parent->getProperty("IOUnitName")); 913 } 914 if (parent->inPlane(gIODTPlane)) { 915 IORegistryEntry *child; 916 IORegistryIterator *children; 917 if (!unit || !parent->getProvider()) { 918 break; 919 } 920 921 children = IORegistryIterator::iterateOver(parent, gIODTPlane); 922 if (!children) { 923 break; 924 } 925 while ((child = children->getNextObject())) { 926 if (!OSDynamicCast(IOMedia, child)) { 927 child->detachAll(gIODTPlane); 928 } 929 } 930 children->release(); 931 932 if (m->attachToParent(parent, gIODTPlane)) { 933 char location[ 32 ]; 934 if (unitLUN && unitLUN->unsigned32BitValue()) { 935 snprintf(location, sizeof(location), "%x,%x:0", unit->unsigned32BitValue(), unitLUN->unsigned32BitValue()); 936 } else { 937 snprintf(location, sizeof(location), "%x:0", unit->unsigned32BitValue()); 938 } 939 m->setLocation(location, gIODTPlane); 940 m->setName(unitName ? unitName->getCStringNoCopy() : "", gIODTPlane); 941 } 942 break; 943 } 944 } 945 946 lockForArbitration(); 947 _mediaObject = m; 948 _mediaObject->retain(); 949 unlockForArbitration(); 950 951 m->registerService(kIOServiceAsynchronous); /* enable matching */ 952 } else { 953 result = kIOReturnNoMemory; /* give up now */ 954 } 955 m->release(); 956 } 957 958 return(result); 959} 960 961IOReturn 962IOBlockStorageDriver::checkForMedia(void) 963{ 964 IOReturn result; 965 bool currentState; 966 bool changed; 967 968 result = getProvider()->reportMediaState(¤tState,&changed); 969 if (result != kIOReturnSuccess) { /* the poll operation failed */ 970 IOLog("%s[IOBlockStorageDriver]::checkForMedia; err '%s' from reportMediaState\n", 971 getName(),stringFromReturn(result)); 972 } else { 973 changed = _mediaObject ? !currentState : currentState; 974 if (changed) { /* the poll succeeded, media state has changed */ 975 result = mediaStateHasChanged(currentState ? kIOMediaStateOnline 976 : kIOMediaStateOffline); 977 } 978 } 979 980 return(result); 981} 982 983IOReturn 984IOBlockStorageDriver::mediaStateHasChanged(IOMediaState state) 985{ 986 IOReturn result; 987 988 /* The media has changed state. See if it's just inserted or removed. */ 989 990 if (state == kIOMediaStateOnline) { /* media is now present */ 991 992 if (_mediaObject) { 993 return(kIOReturnBadArgument); 994 } 995 996 initMediaState(); /* clear all knowledge of the media */ 997 998 /* Allow a subclass to decide whether we accept the media. Such a 999 * decision might be based on things like password-protection, etc. 1000 */ 1001 1002 if (validateNewMedia() == false) { /* we're told to reject it */ 1003 rejectMedia(); /* so let subclass do whatever it wants */ 1004 return(kIOReturnSuccess); /* pretend nothing happened */ 1005 } 1006 1007 result = recordMediaParameters(); /* learn about media */ 1008 if (result != kIOReturnSuccess) { /* couldn't record params */ 1009 IOLog("%s[IOBlockStorageDriver]::mediaStateHasChanged: err '%s' from recordMediaParameters\n", 1010 getName(),stringFromReturn(result)); 1011 return(result); 1012 } 1013 1014 /* Now we do what's necessary to make the new media 1015 * show up properly in the system. 1016 */ 1017 1018 result = acceptNewMedia(); 1019 if (result != kIOReturnSuccess) { 1020 IOLog("%s[IOBlockStorageDriver]::mediaStateHasChanged; err '%s' from acceptNewMedia\n", 1021 getName(),stringFromReturn(result)); 1022 } 1023 1024 return(result); /* all done, new media is ready */ 1025 1026 } else { /* media is now absent */ 1027 1028 result = decommissionMedia(true); /* force a teardown */ 1029 if (result != kIOReturnSuccess && result != kIOReturnNoMedia) { 1030 IOLog("%s[IOBlockStorageDriver]::mediaStateHasChanged; err '%s' from decommissionNewMedia\n", 1031 getName(),stringFromReturn(result)); 1032 return(result); 1033 } 1034 1035 return(kIOReturnSuccess); /* all done; media is gone */ 1036 } 1037} 1038 1039UInt64 1040IOBlockStorageDriver::constrainByteCount(UInt64 /* requestedCount */ ,bool isWrite) 1041{ 1042 if (isWrite) { 1043 return(_maxWriteByteTransfer); 1044 } else { 1045 return(_maxReadByteTransfer); 1046 } 1047} 1048 1049/* Decommission a piece of media that has become unavailable either due to 1050 * ejection or some outside force (e.g. the Giant Hand of the User). 1051 * (I prefer the term "decommission" rather than "abandon." The former implies 1052 * a well-determined procedure, whereas the latter implies leaving the media 1053 * in an orphaned state.) 1054 */ 1055/* Tear down the stack above the specified object. Usually these objects will 1056 * be of type IOMedia, but they could be any IOService. 1057 */ 1058IOReturn 1059IOBlockStorageDriver::decommissionMedia(bool forcible) 1060{ 1061 IOMedia *m = NULL; 1062 IOReturn result; 1063 1064 lockForArbitration(); 1065 1066 if (_mediaObject) { 1067 /* If this is a forcible decommission (i.e. media is gone), we 1068 * forget about the media. 1069 */ 1070 if (forcible || !_openClients->containsObject(_mediaObject)) { 1071 m = _mediaObject; 1072 _mediaObject = 0; 1073 1074 result = kIOReturnSuccess; 1075 } else { 1076 result = kIOReturnBusy; 1077 } 1078 } else { 1079 result = kIOReturnNoMedia; 1080 } 1081 1082 unlockForArbitration(); 1083 1084 if (m) { 1085 IORegistryEntry * parent; 1086 1087 /* Unwire the media object from the device tree. */ 1088 1089 if ( (parent = m->getParentEntry(gIODTPlane)) ) { 1090 m->detachFromParent(parent, gIODTPlane); 1091 } 1092 1093 if (!m->isInactive()) { 1094 m->terminate(); 1095 } 1096 1097 m->release(); 1098 } 1099 1100 return(result); 1101} 1102 1103IOReturn 1104IOBlockStorageDriver::ejectMedia(void) 1105{ 1106 IOReturn result; 1107 1108 if (_ejectable) 1109 { 1110 result = decommissionMedia(false); /* try to teardown */ 1111 } 1112 else 1113 { 1114 lockForArbitration(); 1115 1116 if (_mediaObject) { 1117 if (!_openClients->containsObject(_mediaObject)) { 1118 result = kIOReturnSuccess; 1119 } else { 1120 result = kIOReturnBusy; 1121 } 1122 } else { 1123 result = kIOReturnNoMedia; 1124 } 1125 1126 unlockForArbitration(); 1127 } 1128 1129 if (result == kIOReturnSuccess) { /* eject */ 1130 if (!_writeProtected) { 1131 (void)getProvider()->doSynchronizeCache(); 1132 } 1133 1134 (void)getProvider()->doEjectMedia(); /* ignore any error */ 1135 } 1136 1137 return(result); 1138} 1139 1140void 1141IOBlockStorageDriver::executeRequest(UInt64 byteStart, 1142 IOMemoryDescriptor * buffer, 1143#ifdef __LP64__ 1144 IOStorageAttributes * attributes, 1145 IOStorageCompletion * completion, 1146#else /* !__LP64__ */ 1147 IOStorageCompletion completion, 1148#endif /* !__LP64__ */ 1149 IOBlockStorageDriver::Context * context) 1150{ 1151 UInt64 block; 1152 UInt64 nblks; 1153 IOReturn result; 1154 1155 if (!_mediaObject) { /* no media? you lose */ 1156 complete(completion,kIOReturnNoMedia,0); 1157 return; 1158 } 1159 1160 /* We know that we are never called with a request too large, 1161 * nor one that is misaligned with a block. 1162 */ 1163 assert((byteStart % context->block.size) == 0); 1164 assert((buffer->getLength() % context->block.size) == 0); 1165 1166 block = byteStart / context->block.size; 1167 nblks = buffer->getLength() / context->block.size; 1168 1169 /* Now the protocol-specific provider implements the actual 1170 * start of the data transfer: */ 1171 1172#if TARGET_OS_EMBEDDED 1173 // This is where we adjust the offset for this access to the nand layer. 1174 // We already maintain this buffer's file offset in attributes.fileOffset 1175#ifdef __LP64__ 1176 if (!attributes) { 1177 attributes = &context->request.attributes; 1178 } 1179 attributes->adjustedOffset = ((SInt64)byteStart - (SInt64)context->original.byteStart); 1180#else /* !__LP64__ */ 1181 context->request.attributes.adjustedOffset = ((SInt64)byteStart - (SInt64)context->original.byteStart); 1182#endif /* !__LP64__ */ 1183#endif /* TARGET_OS_EMBEDDED */ 1184#ifdef __LP64__ 1185 result = getProvider()->doAsyncReadWrite(buffer,block,nblks,attributes,completion); 1186#else /* !__LP64__ */ 1187 result = getProvider()->doAsyncReadWrite(buffer,block,nblks,&context->request.attributes,&completion); 1188#endif /* !__LP64__ */ 1189 1190 if (result != kIOReturnSuccess) { /* it failed to start */ 1191 if (result != kIOReturnNotPermitted) { /* expected error from content protection */ 1192 IOLog("%s[IOBlockStorageDriver]; executeRequest: request failed to start!\n",getName()); 1193 } 1194 complete(completion,result); 1195 return; 1196 } 1197} 1198 1199IOReturn 1200IOBlockStorageDriver::formatMedia(UInt64 byteCapacity) 1201{ 1202 IOReturn result; 1203 1204 result = decommissionMedia(false); /* try to teardown */ 1205 1206 if (result == kIOReturnSuccess) { /* format */ 1207 result = getProvider()->doFormatMedia(byteCapacity); 1208 1209 if (result == kIOReturnSuccess) { 1210 result = mediaStateHasChanged(kIOMediaStateOnline); 1211 } else { 1212 (void)mediaStateHasChanged(kIOMediaStateOnline); 1213 } 1214 } 1215 1216 return(result); 1217} 1218 1219const char * 1220IOBlockStorageDriver::getDeviceTypeName(void) 1221{ 1222 return(kIOBlockStorageDeviceTypeGeneric); 1223} 1224 1225UInt32 1226IOBlockStorageDriver::getFormatCapacities(UInt64 * capacities, 1227 UInt32 capacitiesMaxCount) const 1228{ 1229 return(getProvider()->doGetFormatCapacities(capacities,capacitiesMaxCount)); 1230} 1231 1232UInt64 1233IOBlockStorageDriver::getMediaBlockSize() const 1234{ 1235 return(_mediaBlockSize); 1236} 1237 1238IOMediaState 1239IOBlockStorageDriver::getMediaState() const 1240{ 1241 if (_mediaObject) { 1242 return(kIOMediaStateOnline); 1243 } else { 1244 return(kIOMediaStateOffline); 1245 } 1246} 1247 1248IOReturn 1249IOBlockStorageDriver::handlePowerEvent(void *target,void *refCon, 1250 UInt32 messageType,IOService *provider, 1251 void *messageArgument,vm_size_t argSize) 1252{ 1253 IOBlockStorageDriver *driver = (IOBlockStorageDriver *)target; 1254 IOReturn result; 1255 1256 switch (messageType) { 1257 case kIOMessageSystemWillPowerOff: 1258 case kIOMessageSystemWillRestart: 1259 if (driver->open(driver)) { 1260 if (driver->_mediaObject) { 1261 if (!driver->_writeProtected) { 1262 driver->getProvider()->doSynchronizeCache(); 1263 } 1264 if (!driver->_removable && (messageType == kIOMessageSystemWillPowerOff)) { 1265 driver->getProvider()->doEjectMedia(); 1266 } 1267 } 1268 driver->close(driver); 1269 } 1270 result = kIOReturnSuccess; 1271 break; 1272 1273 default: 1274 result = kIOReturnUnsupported; 1275 break; 1276 } 1277 1278 return(result); 1279} 1280 1281bool 1282IOBlockStorageDriver::handleStart(IOService * provider) 1283{ 1284 OSObject *object; 1285 OSNumber *number; 1286 IOReturn result; 1287 1288 /* The protocol-specific provider determines whether the media is removable. */ 1289 1290 result = getProvider()->reportRemovability(&_removable); 1291 if (result != kIOReturnSuccess) { 1292 IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportRemovability\n", 1293 getName(),stringFromReturn(result)); 1294 return(false); 1295 } 1296 1297 if (_removable) { 1298 1299 /* The protocol-specific provider determines whether the media is ejectable 1300 * under software control. 1301 */ 1302 result = getProvider()->reportEjectability(&_ejectable); 1303 if (result != kIOReturnSuccess) { 1304 IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportEjectability\n", 1305 getName(),stringFromReturn(result)); 1306 return(false); 1307 } 1308 1309 } else { /* fixed disk: not ejectable */ 1310 _ejectable = false; 1311 } 1312 1313 /* Obtain the constraint values for reads and writes. */ 1314 1315 object = copyProperty(kIOMaximumBlockCountReadKey, gIOServicePlane); 1316 if (object) { 1317 1318 number = OSDynamicCast(OSNumber, object); 1319 if (number) { 1320 _maxReadBlockTransfer = number->unsigned64BitValue(); 1321 } 1322 1323 object->release(); 1324 } 1325#ifndef __LP64__ 1326 if (object == 0) { 1327 UInt64 maxReadTransfer; 1328 1329 result = getProvider()->reportMaxReadTransfer(512, &maxReadTransfer); 1330 if (result == kIOReturnSuccess) { 1331 _maxReadBlockTransfer = maxReadTransfer / 512; 1332 } 1333 1334 getProvider()->setProperty(kIOMaximumBlockCountReadKey, _maxReadBlockTransfer, 64); 1335 } 1336#endif /* !__LP64__ */ 1337 1338 object = copyProperty(kIOMaximumBlockCountWriteKey, gIOServicePlane); 1339 if (object) { 1340 1341 number = OSDynamicCast(OSNumber, object); 1342 if (number) { 1343 _maxWriteBlockTransfer = number->unsigned64BitValue(); 1344 } 1345 1346 object->release(); 1347 } 1348#ifndef __LP64__ 1349 if (object == 0) { 1350 UInt64 maxWriteTransfer; 1351 1352 result = getProvider()->reportMaxWriteTransfer(512, &maxWriteTransfer); 1353 if (result == kIOReturnSuccess) { 1354 _maxWriteBlockTransfer = maxWriteTransfer / 512; 1355 } 1356 1357 getProvider()->setProperty(kIOMaximumBlockCountWriteKey, _maxWriteBlockTransfer, 64); 1358 } 1359#endif /* !__LP64__ */ 1360 1361 object = copyProperty(kIOMaximumByteCountReadKey, gIOServicePlane); 1362 if (object) { 1363 1364 number = OSDynamicCast(OSNumber, object); 1365 if (number) { 1366 _maxReadByteTransfer = number->unsigned64BitValue(); 1367 } 1368 1369 object->release(); 1370 } 1371 1372 object = copyProperty(kIOMaximumByteCountWriteKey, gIOServicePlane); 1373 if (object) { 1374 1375 number = OSDynamicCast(OSNumber, object); 1376 if (number) { 1377 _maxWriteByteTransfer = number->unsigned64BitValue(); 1378 } 1379 1380 object->release(); 1381 } 1382 1383 object = copyProperty(kIOMaximumSegmentCountReadKey, gIOServicePlane); 1384 if (object) { 1385 1386 number = OSDynamicCast(OSNumber, object); 1387 if (number) { 1388 _maxReadSegmentTransfer = number->unsigned64BitValue(); 1389 } 1390 1391 object->release(); 1392 } 1393 1394 object = copyProperty(kIOMaximumSegmentCountWriteKey, gIOServicePlane); 1395 if (object) { 1396 1397 number = OSDynamicCast(OSNumber, object); 1398 if (number) { 1399 _maxWriteSegmentTransfer = number->unsigned64BitValue(); 1400 } 1401 1402 object->release(); 1403 } 1404 1405 object = copyProperty(kIOMaximumSegmentByteCountReadKey, gIOServicePlane); 1406 if (object) { 1407 1408 number = OSDynamicCast(OSNumber, object); 1409 if (number) { 1410 _maxReadSegmentByteTransfer = number->unsigned64BitValue(); 1411 } 1412 1413 object->release(); 1414 } 1415 1416 object = copyProperty(kIOMaximumSegmentByteCountWriteKey, gIOServicePlane); 1417 if (object) { 1418 1419 number = OSDynamicCast(OSNumber, object); 1420 if (number) { 1421 _maxWriteSegmentByteTransfer = number->unsigned64BitValue(); 1422 } 1423 1424 object->release(); 1425 } 1426 1427 object = copyProperty(kIOMinimumSegmentAlignmentByteCountKey, gIOServicePlane); 1428 if (object) { 1429 1430 number = OSDynamicCast(OSNumber, object); 1431 if (number) { 1432 _minSegmentAlignmentByteTransfer = number->unsigned64BitValue(); 1433 } 1434 1435 object->release(); 1436 } else { 1437 getProvider()->setProperty(kIOMinimumSegmentAlignmentByteCountKey, _minSegmentAlignmentByteTransfer, 64); 1438 } 1439 1440 object = copyProperty(kIOMaximumSegmentAddressableBitCountKey, gIOServicePlane); 1441 if (object) { 1442 1443 number = OSDynamicCast(OSNumber, object); 1444 if (number) { 1445 if (number->unsigned64BitValue()) { 1446 if (number->unsigned64BitValue() < 64) { 1447 _maxSegmentWidthByteTransfer = 1ULL << number->unsigned64BitValue(); 1448 } 1449 } 1450 } 1451 1452 object->release(); 1453 } 1454 1455 object = copyProperty(kIOCommandPoolSizeKey, gIOServicePlane); 1456 if (object) { 1457 1458 number = OSDynamicCast(OSNumber, object); 1459 if (number) { 1460 _contextsMaxCount = number->unsigned32BitValue(); 1461 } 1462 1463 object->release(); 1464 } 1465 1466 /* Check for the device being ready with media inserted: */ 1467 1468 result = checkForMedia(); 1469 1470 /* The poll should never fail for nonremovable media: */ 1471 1472 if (result != kIOReturnSuccess && !_removable) { 1473 IOLog("%s[IOBlockStorageDriver]::handleStart: err '%s' from checkForMedia\n", 1474 getName(),stringFromReturn(result)); 1475 return(false); 1476 } 1477 1478 /* Set up the power event handler for restarts and shutdowns: */ 1479 1480 _powerEventNotifier = registerPrioritySleepWakeInterest(handlePowerEvent,this); 1481 if (_powerEventNotifier) { 1482 retain(); 1483 } 1484 1485 return(true); 1486} 1487 1488bool 1489IOBlockStorageDriver::handleYield(IOService * provider, 1490 IOOptionBits options, 1491 void * argument) 1492{ 1493 return false; 1494} 1495 1496void 1497IOBlockStorageDriver::initMediaState(void) 1498{ 1499 _mediaType = 0; 1500} 1501 1502IOMedia * 1503IOBlockStorageDriver::instantiateDesiredMediaObject(void) 1504{ 1505 return(new IOMedia); 1506} 1507 1508IOMedia * 1509IOBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize, 1510 UInt32 blockSize,char *mediaName) 1511{ 1512 IOMediaAttributeMask attributes = 0; 1513 IOMedia *m; 1514 bool result; 1515 1516 m = instantiateDesiredMediaObject(); 1517 if (m == NULL) { 1518 return(NULL); 1519 } 1520 1521 attributes |= _ejectable ? kIOMediaAttributeEjectableMask : 0; 1522 attributes |= _removable ? kIOMediaAttributeRemovableMask : 0; 1523 1524 result = m->init( base, /* base byte offset */ 1525 byteSize, /* byte size */ 1526 blockSize, /* preferred block size */ 1527 attributes, /* attributes */ 1528 true, /* TRUE if whole physical media */ 1529 !_writeProtected, /* TRUE if writable */ 1530 ""); /* content hint */ 1531 1532 if (result) { 1533 const char *picture = "External.icns"; 1534 1535 if (_removable) { 1536 picture = "Removable.icns"; 1537 } else { 1538 OSDictionary *dictionary = OSDynamicCast(OSDictionary, getProvider()->getProperty(kIOPropertyProtocolCharacteristicsKey)); 1539 1540 if (dictionary) { 1541 OSString *string = OSDynamicCast(OSString, dictionary->getObject(kIOPropertyPhysicalInterconnectLocationKey)); 1542 1543 if (string) { 1544 if (string->isEqualTo(kIOPropertyExternalKey)) { 1545 picture = "External.icns"; 1546 } else { 1547 picture = "Internal.icns"; 1548 } 1549 } 1550 } 1551 } 1552 1553 if (picture) { 1554 OSDictionary *dictionary = OSDictionary::withCapacity(2); 1555 OSString *identifier = OSString::withCString("com.apple.iokit.IOStorageFamily"); 1556 OSString *resourceFile = OSString::withCString(picture); 1557 1558 if (dictionary && identifier && resourceFile) { 1559 dictionary->setObject("CFBundleIdentifier", identifier); 1560 dictionary->setObject("IOBundleResourceFile", resourceFile); 1561 } 1562 1563 m->setProperty(kIOMediaIconKey, dictionary); 1564 1565 if (resourceFile) { 1566 resourceFile->release(); 1567 } 1568 if (identifier) { 1569 identifier->release(); 1570 } 1571 if (dictionary) { 1572 dictionary->release(); 1573 } 1574 } 1575 1576 if (mediaName) { 1577 m->setName(mediaName); 1578 } 1579 1580 return(m); 1581 1582 } else { /* some init error */ 1583 m->release(); 1584 return(NULL); /* beats me...call it this error */ 1585 } 1586} 1587 1588bool 1589IOBlockStorageDriver::isMediaEjectable(void) const 1590{ 1591 return(_ejectable); 1592} 1593 1594#ifdef __LP64__ 1595bool 1596IOBlockStorageDriver::isMediaRemovable(void) const 1597{ 1598 return(_removable); 1599} 1600#endif /* __LP64__ */ 1601 1602bool 1603IOBlockStorageDriver::isMediaPollExpensive(void) const 1604{ 1605 return(false); 1606} 1607 1608bool 1609IOBlockStorageDriver::isMediaPollRequired(void) const 1610{ 1611 return(false); 1612} 1613 1614bool 1615IOBlockStorageDriver::isMediaWritable(void) const 1616{ 1617 return(!_writeProtected); 1618} 1619 1620IOReturn 1621IOBlockStorageDriver::lockMedia(bool locked) 1622{ 1623 return(kIOReturnUnsupported); 1624} 1625 1626IOReturn 1627IOBlockStorageDriver::pollMedia(void) 1628{ 1629 return(kIOReturnUnsupported); 1630} 1631 1632IOReturn 1633IOBlockStorageDriver::recordMediaParameters(void) 1634{ 1635 IOReturn result; 1636 1637 /* Determine the device's block size and max block number. 1638 * What should an unformatted device report? All zeroes. 1639 */ 1640 1641 result = getProvider()->reportBlockSize(&_mediaBlockSize); 1642 if (result != kIOReturnSuccess) { 1643 goto err; 1644 } 1645 1646 result = getProvider()->reportMaxValidBlock(&_maxBlockNumber); 1647 if (result != kIOReturnSuccess) { 1648 goto err; 1649 } 1650 1651 /* Is the media write-protected? */ 1652 1653 result = getProvider()->reportWriteProtection(&_writeProtected); 1654 if (result != kIOReturnSuccess) { 1655 goto err; 1656 } 1657 1658 return(kIOReturnSuccess); /* everything was successful */ 1659 1660 /* If we fall thru to here, we had some kind of error. Set everything to 1661 * a reasonable state since we haven't got any real information. 1662 */ 1663 1664err: 1665 return(result); 1666} 1667 1668void 1669IOBlockStorageDriver::rejectMedia(void) 1670{ 1671 (void)getProvider()->doEjectMedia(); /* eject it, ignoring any error */ 1672} 1673 1674void 1675IOBlockStorageDriver::stop(IOService * provider) 1676{ 1677 if (_powerEventNotifier) { 1678 _powerEventNotifier->remove(); 1679 _powerEventNotifier = NULL; 1680 release(); 1681 } 1682 super::stop(provider); 1683} 1684 1685IOReturn 1686IOBlockStorageDriver::synchronizeCache(IOService *client) 1687{ 1688 return(getProvider()->doSynchronizeCache()); 1689} 1690 1691IOReturn 1692IOBlockStorageDriver::unmap(IOService * client, 1693 IOStorageExtent * extents, 1694 UInt32 extentsCount, 1695 UInt32 options) 1696{ 1697 UInt32 extentsIndex; 1698 IOBlockStorageDeviceExtent * extentsOut; 1699 UInt32 extentsOutCount; 1700 1701 assert( sizeof( IOStorageExtent ) == sizeof( IOBlockStorageDeviceExtent ) ); 1702 1703 extentsOut = ( IOBlockStorageDeviceExtent * ) extents; 1704 extentsOutCount = 0; 1705 1706 for ( extentsIndex = 0; extentsIndex < extentsCount; extentsIndex++ ) 1707 { 1708 UInt64 blockStart; 1709 UInt64 blockCount; 1710 1711 blockStart = ( extents[ extentsIndex ].byteStart + _mediaBlockSize - 1 ) / _mediaBlockSize; 1712 blockCount = ( extents[ extentsIndex ].byteStart + extents[ extentsIndex ].byteCount ) / _mediaBlockSize; 1713 1714 if ( blockCount > blockStart ) 1715 { 1716 blockCount = blockCount - blockStart; 1717 1718 extentsOut[ extentsOutCount ].blockStart = blockStart; 1719 extentsOut[ extentsOutCount ].blockCount = blockCount; 1720 1721 extentsOutCount++; 1722 } 1723 } 1724 1725 if ( extentsOutCount ) 1726 { 1727 return getProvider( )->doUnmap( extentsOut, extentsOutCount, options ); 1728 } 1729 else 1730 { 1731 return kIOReturnSuccess; 1732 } 1733} 1734 1735bool IOBlockStorageDriver::lockPhysicalExtents(IOService * client) 1736{ 1737 // 1738 // Lock the contents of the storage object against relocation temporarily, 1739 // for the purpose of getting physical extents. 1740 // 1741 1742 return(true); 1743} 1744 1745IOStorage * IOBlockStorageDriver::copyPhysicalExtent(IOService * client, 1746 UInt64 * byteStart, 1747 UInt64 * byteCount) 1748{ 1749 // 1750 // Convert the specified byte offset into a physical byte offset, relative 1751 // to a physical storage object. This call should only be made within the 1752 // context of lockPhysicalExtents(). 1753 // 1754 1755 IOMedia *m; 1756 1757 lockForArbitration(); 1758 m = _mediaObject; 1759 if (m) { 1760 m->retain(); 1761 } 1762 unlockForArbitration(); 1763 1764 return(m); 1765} 1766 1767void IOBlockStorageDriver::unlockPhysicalExtents(IOService * client) 1768{ 1769 // 1770 // Unlock the contents of the storage object for relocation again. This 1771 // call must balance a successful call to lockPhysicalExtents(). 1772 // 1773 1774 return; 1775} 1776 1777bool 1778IOBlockStorageDriver::validateNewMedia(void) 1779{ 1780 return(true); 1781} 1782 1783// ----------------------------------------------------------------------------- 1784// Deblocker Implementation 1785 1786#include <IOKit/IOBufferMemoryDescriptor.h> 1787 1788class IODeblocker : public IOMemoryDescriptor 1789{ 1790 OSDeclareDefaultStructors(IODeblocker); 1791 1792protected: 1793 1794 UInt64 _blockSize; 1795 1796 struct 1797 { 1798 IOMemoryDescriptor * buffer; 1799 UInt32 offset; 1800 UInt32 length; 1801 } _chunks[3]; 1802 UInt32 _chunksCount; 1803 1804 IOBufferMemoryDescriptor * _excessBuffer; 1805 UInt64 _excessCountFinal; 1806 UInt64 _excessCountStart; 1807 1808 IOMemoryDescriptor * _requestBuffer; 1809 IOStorageAttributes _requestAttributes; 1810 IOStorageCompletion _requestCompletion; 1811 void * _requestContext; 1812 UInt64 _requestCount; 1813 bool _requestIsOneBlock; 1814 UInt64 _requestStart; 1815 1816 UInt64 _byteStart; 1817 1818 thread_call_t _threadCallback; 1819 1820 enum 1821 { 1822 kStageInit, 1823 kStagePrepareExcessStart, 1824 kStagePrepareExcessFinal, 1825 kStageLast, 1826 kStageDone 1827 } _stage; 1828 1829 virtual void free(); 1830 1831public: 1832 1833 static IODeblocker * withBlockSize( 1834 UInt64 blockSize, 1835 UInt64 withRequestStart, 1836 IOMemoryDescriptor * withRequestBuffer, 1837 IOStorageAttributes * withRequestAttributes, 1838 IOStorageCompletion * withRequestCompletion, 1839 void * withRequestContext ); 1840 1841 virtual bool initWithBlockSize( 1842 UInt64 blockSize, 1843 UInt64 withRequestStart, 1844 IOMemoryDescriptor * withRequestBuffer, 1845 IOStorageAttributes * withRequestAttributes, 1846 IOStorageCompletion * withRequestCompletion, 1847 void * withRequestContext ); 1848 1849 virtual addr64_t getPhysicalSegment( IOByteCount offset, 1850 IOByteCount * length, 1851 IOOptionBits options = 0 ); 1852 1853 virtual IOReturn prepare(IODirection forDirection = kIODirectionNone); 1854 1855 virtual IOReturn complete(IODirection forDirection = kIODirectionNone); 1856 1857 virtual bool getNextStage(); 1858 1859 virtual IOStorageAttributes * getRequestAttributes(); 1860 1861 virtual IOStorageCompletion * getRequestCompletion(UInt64 * actualByteCount); 1862 1863 virtual IOMemoryDescriptor * getRequestBuffer(); 1864 1865 virtual void * getRequestContext(); 1866 1867 virtual UInt64 getByteStart(); 1868 1869 virtual thread_call_t getThreadCallback(); 1870 1871 virtual bool setThreadCallback(thread_call_func_t callback); 1872}; 1873 1874#undef super 1875#define super IOMemoryDescriptor 1876OSDefineMetaClassAndStructors(IODeblocker, IOMemoryDescriptor) 1877 1878IODeblocker * IODeblocker::withBlockSize( 1879 UInt64 blockSize, 1880 UInt64 withRequestStart, 1881 IOMemoryDescriptor * withRequestBuffer, 1882 IOStorageAttributes * withRequestAttributes, 1883 IOStorageCompletion * withRequestCompletion, 1884 void * withRequestContext ) 1885{ 1886 // 1887 // Create a new IODeblocker. 1888 // 1889 1890 IODeblocker * me = new IODeblocker; 1891 1892 if ( me && me->initWithBlockSize( 1893 /* blockSize */ blockSize, 1894 /* withRequestStart */ withRequestStart, 1895 /* withRequestBuffer */ withRequestBuffer, 1896 /* withRequestAttributes */ withRequestAttributes, 1897 /* withRequestCompletion */ withRequestCompletion, 1898 /* withRequestContext */ withRequestContext ) == false ) 1899 { 1900 me->release(); 1901 me = 0; 1902 } 1903 1904 return me; 1905} 1906 1907bool IODeblocker::initWithBlockSize( 1908 UInt64 blockSize, 1909 UInt64 withRequestStart, 1910 IOMemoryDescriptor * withRequestBuffer, 1911 IOStorageAttributes * withRequestAttributes, 1912 IOStorageCompletion * withRequestCompletion, 1913 void * withRequestContext ) 1914{ 1915 // 1916 // Initialize an IODeblocker. 1917 // 1918 // _excessCountStart = byte count from media boundary to start of request 1919 // _excessCountFinal = byte count from end of request to a media boundary 1920 // 1921 1922 UInt32 excessBufferSize = 0; 1923 1924 // Ask our superclass' opinion. 1925 1926 if ( super::init() == false ) return false; 1927 1928 // Initialize our minimal state. 1929 1930 _blockSize = blockSize; 1931 _chunksCount = 0; 1932 _flags = kIODirectionNone; 1933 _length = 0; 1934 1935 _requestBuffer = withRequestBuffer; 1936 _requestBuffer->retain(); 1937 1938 if (withRequestAttributes) _requestAttributes = *withRequestAttributes; 1939 if (withRequestCompletion) _requestCompletion = *withRequestCompletion; 1940 1941 _requestContext = withRequestContext; 1942 _requestCount = withRequestBuffer->getLength(); 1943 _requestStart = withRequestStart; 1944 1945 _excessCountStart = (withRequestStart ) % blockSize; 1946 _excessCountFinal = (withRequestStart + _requestCount) % blockSize; 1947 if ( _excessCountFinal ) _excessCountFinal = blockSize - _excessCountFinal; 1948 1949 _requestIsOneBlock = (_excessCountStart + _requestCount <= blockSize); 1950 1951 // Determine the necessary size for our scratch buffer. 1952 1953 switch ( _requestBuffer->getDirection() ) 1954 { 1955 case kIODirectionIn: // (read) 1956 { 1957 excessBufferSize = max(_excessCountStart, _excessCountFinal); 1958 } break; 1959 1960 case kIODirectionOut: // (write) 1961 { 1962 if ( _excessCountStart ) excessBufferSize += blockSize; 1963 if ( _excessCountFinal ) excessBufferSize += blockSize; 1964 1965 // If there is excess both ends of the original request, but both 1966 // ends reside within the same media block, then we could shorten 1967 // our buffer size to just one block. 1968 1969 if ( _excessCountStart && _excessCountFinal && _requestIsOneBlock ) 1970 { 1971 excessBufferSize -= blockSize; 1972 } 1973 } break; 1974 1975 default: 1976 { 1977 assert(0); 1978 } break; 1979 } 1980 1981 // Allocate our scratch buffer. 1982 1983 if ( excessBufferSize ) 1984 { 1985 _excessBuffer = IOBufferMemoryDescriptor::withCapacity( 1986 /* capacity */ excessBufferSize, 1987 /* withDirection */ kIODirectionNone ); 1988 if ( _excessBuffer == 0 ) return false; 1989 } 1990 1991 return true; 1992} 1993 1994void IODeblocker::free() 1995{ 1996 // 1997 // Free all of this object's outstanding resources. 1998 // 1999 2000 if ( _requestBuffer ) _requestBuffer->release(); 2001 if ( _excessBuffer ) _excessBuffer->release(); 2002 if ( _threadCallback ) thread_call_free(_threadCallback); 2003 2004 super::free(); 2005} 2006 2007IOReturn IODeblocker::prepare(IODirection forDirection) 2008{ 2009 // 2010 // Prepare the memory for an I/O transfer. 2011 // 2012 // This involves paging in the memory and wiring it down for the duration 2013 // of the transfer. The complete() method finishes the processing of the 2014 // memory after the I/O transfer finishes. 2015 // 2016 2017 unsigned index; 2018 IOReturn status = kIOReturnInternalError; 2019 IOReturn statusUndo; 2020 2021 if ( forDirection == kIODirectionNone ) 2022 { 2023 forDirection = (IODirection) (_flags & kIOMemoryDirectionMask); 2024 } 2025 2026 for ( index = 0; index < _chunksCount; index++ ) 2027 { 2028 status = _chunks[index].buffer->prepare(forDirection); 2029 if ( status != kIOReturnSuccess ) break; 2030 } 2031 2032 if ( status != kIOReturnSuccess ) 2033 { 2034 for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ ) 2035 { 2036 statusUndo = _chunks[index].buffer->complete(forDirection); 2037 assert(statusUndo == kIOReturnSuccess); 2038 } 2039 } 2040 2041 return status; 2042} 2043 2044IOReturn IODeblocker::complete(IODirection forDirection) 2045{ 2046 // 2047 // Complete processing of the memory after an I/O transfer finishes. 2048 // 2049 // This method shouldn't be called unless a prepare() was previously issued; 2050 // the prepare() and complete() must occur in pairs, before and after an I/O 2051 // transfer. 2052 // 2053 2054 IOReturn status; 2055 IOReturn statusFinal = kIOReturnSuccess; 2056 2057 if ( forDirection == kIODirectionNone ) 2058 { 2059 forDirection = (IODirection) (_flags & kIOMemoryDirectionMask); 2060 } 2061 2062 for ( unsigned index = 0; index < _chunksCount; index++ ) 2063 { 2064 status = _chunks[index].buffer->complete(forDirection); 2065 if ( status != kIOReturnSuccess ) statusFinal = status; 2066 assert(status == kIOReturnSuccess); 2067 } 2068 2069 return statusFinal; 2070} 2071 2072addr64_t IODeblocker::getPhysicalSegment( IOByteCount offset, 2073 IOByteCount * length, 2074 IOOptionBits options ) 2075{ 2076 // 2077 // This method returns the physical address of the byte at the given offset 2078 // into the memory, and optionally the length of the physically contiguous 2079 // segment from that offset. 2080 // 2081 2082 assert(offset <= _length); 2083 2084 for ( unsigned index = 0; index < _chunksCount; index++ ) 2085 { 2086 if ( offset < _chunks[index].length ) 2087 { 2088 addr64_t address; 2089 address = _chunks[index].buffer->getPhysicalSegment( 2090 /* offset */ offset + _chunks[index].offset, 2091 /* length */ length, 2092 /* options */ options ); 2093 if ( length ) *length = min(*length, _chunks[index].length); 2094 return address; 2095 } 2096 offset -= _chunks[index].length; 2097 } 2098 2099 if ( length ) *length = 0; 2100 2101 return 0; 2102} 2103 2104bool IODeblocker::getNextStage() 2105{ 2106 // 2107 // Obtain the next stage of the transfer. The transfer buffer will be the 2108 // deblocker object itself and the byte start will be returned in getByteStart(). 2109 // 2110 // This method must not be called if the current stage failed with an error 2111 // or a short byte count, but instead getRequestCompletion() must be called 2112 // to adjust the status and actual byte count (with respect to the original 2113 // request) and return the original request's completion routine. The same 2114 // call to getRequestCompletion() should also be done if the getNextStage() 2115 // method returns false. 2116 // 2117 2118 _chunksCount = 0; 2119 _flags = (_flags & ~kIOMemoryDirectionMask) | kIODirectionNone; 2120 _length = 0; 2121 2122 switch ( _requestBuffer->getDirection() ) 2123 { 2124 case kIODirectionIn: // (read) 2125 { 2126 switch ( _stage ) 2127 { 2128 case kStageInit: 2129 { 2130 _stage = kStageLast; 2131 _excessBuffer->setDirection(kIODirectionIn); 2132 _flags = (_flags & ~kIOMemoryDirectionMask) | kIODirectionIn; 2133 _byteStart = _requestStart - _excessCountStart; 2134 2135 if ( _excessCountStart ) 2136 { 2137 _chunks[_chunksCount].buffer = _excessBuffer; 2138 _chunks[_chunksCount].offset = 0; 2139 _chunks[_chunksCount].length = _excessCountStart; 2140 _chunksCount++; 2141 } 2142 2143 _chunks[_chunksCount].buffer = _requestBuffer; 2144 _chunks[_chunksCount].offset = 0; 2145 _chunks[_chunksCount].length = _requestBuffer->getLength(); 2146 _chunksCount++; 2147 2148 if ( _excessCountFinal ) 2149 { 2150 _chunks[_chunksCount].buffer = _excessBuffer; 2151 _chunks[_chunksCount].offset = 0; 2152 _chunks[_chunksCount].length = _excessCountFinal; 2153 _chunksCount++; 2154 } 2155 } break; 2156 2157 case kStageLast: 2158 { 2159 _stage = kStageDone; 2160 } break; 2161 2162 default: 2163 { 2164 assert(0); 2165 } break; 2166 } // (switch) 2167 } break; 2168 2169 case kIODirectionOut: // (write) 2170 { 2171 switch ( _stage ) 2172 { 2173 case kStageInit: 2174 { 2175 if ( _excessCountStart ) 2176 { 2177 _stage = kStagePrepareExcessStart; 2178 _excessBuffer->setDirection(kIODirectionIn); 2179 _flags = (_flags & ~kIOMemoryDirectionMask) | kIODirectionIn; 2180 _byteStart = _requestStart - _excessCountStart; 2181 2182 _chunks[_chunksCount].buffer = _excessBuffer; 2183 _chunks[_chunksCount].offset = 0; 2184 _chunks[_chunksCount].length = _blockSize; 2185 _chunksCount++; 2186 break; 2187 } 2188 } // (fall thru) 2189 2190 case kStagePrepareExcessStart: 2191 { 2192 if ( _excessCountFinal ) 2193 { 2194 // We do not issue this stage if the original transfer 2195 // resides within one media block, and we already read 2196 // that block into our buffer in the previous stage. 2197 2198 if ( !_excessCountStart || !_requestIsOneBlock ) 2199 { 2200 _stage = kStagePrepareExcessFinal; 2201 _excessBuffer->setDirection(kIODirectionIn); 2202 _flags = (_flags & ~kIOMemoryDirectionMask) | kIODirectionIn; 2203 _byteStart = _requestStart + _requestCount + 2204 _excessCountFinal - _blockSize; 2205 2206 _chunks[_chunksCount].buffer = _excessBuffer; 2207 _chunks[_chunksCount].offset = (_requestIsOneBlock) 2208 ? 0 2209 : (_excessCountStart) 2210 ? _blockSize 2211 : 0; 2212 _chunks[_chunksCount].length = _blockSize; 2213 _chunksCount++; 2214 break; 2215 } 2216 } 2217 } // (fall thru) 2218 2219 case kStagePrepareExcessFinal: 2220 { 2221 _stage = kStageLast; 2222 _excessBuffer->setDirection(kIODirectionOut); 2223 _flags = (_flags & ~kIOMemoryDirectionMask) | kIODirectionOut; 2224 _byteStart = _requestStart - _excessCountStart; 2225 2226 if ( _excessCountStart ) 2227 { 2228 _chunks[_chunksCount].buffer = _excessBuffer; 2229 _chunks[_chunksCount].offset = 0; 2230 _chunks[_chunksCount].length = _excessCountStart; 2231 _chunksCount++; 2232 } 2233 2234 _chunks[_chunksCount].buffer = _requestBuffer; 2235 _chunks[_chunksCount].offset = 0; 2236 _chunks[_chunksCount].length = _requestBuffer->getLength(); 2237 _chunksCount++; 2238 2239 if ( _excessCountFinal ) 2240 { 2241 _chunks[_chunksCount].buffer = _excessBuffer; 2242 _chunks[_chunksCount].offset = (_requestIsOneBlock) 2243 ? 0 2244 : (_excessCountStart) 2245 ? _blockSize 2246 : 0; 2247 _chunks[_chunksCount].offset += ( _blockSize - 2248 _excessCountFinal ); 2249 _chunks[_chunksCount].length = _excessCountFinal; 2250 _chunksCount++; 2251 } 2252 } break; 2253 2254 case kStageLast: 2255 { 2256 _stage = kStageDone; 2257 } break; 2258 2259 default: 2260 { 2261 assert(0); 2262 } break; 2263 } // (switch) 2264 } break; 2265 2266 default: 2267 { 2268 assert(0); 2269 } break; 2270 } // (switch) 2271 2272 // Determine whether we have an abort or completion condition. 2273 2274 if ( _chunksCount == 0 ) return false; 2275 2276 // Compute the total length of the descriptor over all chunks. 2277 2278 for ( unsigned index = 0; index < _chunksCount; index++ ) 2279 { 2280 _length += _chunks[index].length; 2281 } 2282 2283 return true; 2284} 2285 2286IOStorageAttributes * IODeblocker::getRequestAttributes() 2287{ 2288 // 2289 // Obtain the attributes for the original request. 2290 // 2291 2292 return &_requestAttributes; 2293} 2294 2295IOStorageCompletion * IODeblocker::getRequestCompletion(UInt64 * actualByteCount) 2296{ 2297 // 2298 // Obtain the completion information for the original request, taking 2299 // into account the actual byte count of the current stage. 2300 // 2301 2302 switch ( _stage ) 2303 { 2304 case kStageInit: // (inital stage) 2305 { 2306 *actualByteCount = 0; 2307 } break; 2308 2309 case kStagePrepareExcessStart: // (write preparation stage) 2310 case kStagePrepareExcessFinal: 2311 { 2312 *actualByteCount = 0; 2313 } break; 2314 2315 case kStageLast: // (last stage) 2316 case kStageDone: 2317 { 2318 if ( *actualByteCount > _excessCountStart ) 2319 *actualByteCount -= _excessCountStart; 2320 else 2321 *actualByteCount = 0; 2322 2323 if ( *actualByteCount > _requestBuffer->getLength() ) 2324 *actualByteCount = _requestBuffer->getLength(); 2325 } break; 2326 2327 default: 2328 { 2329 assert(0); 2330 } break; 2331 } 2332 2333 return &_requestCompletion; 2334} 2335 2336IOMemoryDescriptor * IODeblocker::getRequestBuffer() 2337{ 2338 // 2339 // Obtain the buffer for the original request. 2340 // 2341 2342 return _requestBuffer; 2343} 2344 2345void * IODeblocker::getRequestContext() 2346{ 2347 // 2348 // Obtain the context for the original request. 2349 // 2350 2351 return _requestContext; 2352} 2353 2354UInt64 IODeblocker::getByteStart() 2355{ 2356 // 2357 // Obtain the byte start for the current stage. 2358 // 2359 2360 return _byteStart; 2361} 2362 2363thread_call_t IODeblocker::getThreadCallback() 2364{ 2365 // 2366 // Obtain the thread callback. 2367 // 2368 2369 return _threadCallback; 2370} 2371 2372bool IODeblocker::setThreadCallback(thread_call_func_t callback) 2373{ 2374 // 2375 // Allocate a thread callback. 2376 // 2377 2378 _threadCallback = thread_call_allocate(callback, this); 2379 2380 return _threadCallback ? true : false; 2381} 2382 2383void IOBlockStorageDriver::deblockRequest( 2384 UInt64 byteStart, 2385 IOMemoryDescriptor * buffer, 2386#ifdef __LP64__ 2387 IOStorageAttributes * attributes, 2388 IOStorageCompletion * completion, 2389#else /* !__LP64__ */ 2390 IOStorageCompletion completion, 2391#endif /* !__LP64__ */ 2392 IOBlockStorageDriver::Context * context ) 2393{ 2394 // 2395 // The deblockRequest method checks to see if the incoming request rests 2396 // on the media's block boundaries, and if not, deblocks it. Deblocking 2397 // involves rounding out the request to the nearest block boundaries and 2398 // transferring the excess bytes into a scratch buffer. 2399 // 2400 // This method is part of a sequence of methods invoked for each read/write 2401 // request. The first is prepareRequest, which allocates and prepares some 2402 // context for the transfer; the second is deblockRequest, which aligns the 2403 // transfer at the media's block boundaries; third is breakUpRequest, which 2404 // breaks up the transfer into multiple sub-transfers when certain hardware 2405 // constraints are exceeded; fourth is executeRequest, which implements the 2406 // actual transfer from the block storage device. 2407 // 2408 // The current implementation of deblockRequest is asynchronous. 2409 // 2410 2411 IODeblocker * deblocker; 2412 2413 // If the request is aligned with the media's block boundaries, we 2414 // do short-circuit the deblocker and call breakUpRequest directly. 2415 2416 if ( (byteStart % context->block.size) == 0 && 2417 (buffer->getLength() % context->block.size) == 0 ) 2418 { 2419#ifdef __LP64__ 2420 breakUpRequest(byteStart, buffer, attributes, completion, context); 2421#else /* !__LP64__ */ 2422 breakUpRequest(byteStart, buffer, completion, context); 2423#endif /* !__LP64__ */ 2424 return; 2425 } 2426 2427 // Build a deblocker object. 2428 2429 deblocker = IODeblocker::withBlockSize( 2430 /* blockSize */ context->block.size, 2431 /* withRequestStart */ byteStart, 2432 /* withRequestBuffer */ buffer, 2433#ifdef __LP64__ 2434 /* withRequestAttributes */ attributes, 2435 /* withRequestCompletion */ completion, 2436#else /* !__LP64__ */ 2437 /* withRequestAttributes */ NULL, 2438 /* withRequestCompletion */ &completion, 2439#endif /* !__LP64__ */ 2440 /* withRequestContext */ context ); 2441 2442 if ( deblocker == 0 ) 2443 { 2444 complete(completion, kIOReturnNoMemory); 2445 return; 2446 } 2447 2448 // This implementation of the deblocker permits only one read-modify-write 2449 // at any given time. Note that other write requests can, and do, proceed 2450 // simultaneously so long as they do not require the deblocker. 2451 2452 if ( buffer->getDirection() == kIODirectionOut ) 2453 { 2454 IOLockLock(_deblockRequestWriteLock); 2455 2456 _deblockRequestWriteLockCount++; 2457 2458 if ( _deblockRequestWriteLockCount > 1 ) 2459 { 2460 while ( IOLockSleep( /* lock */ _deblockRequestWriteLock, 2461 /* event */ _deblockRequestWriteLock, 2462 /* interruptible */ THREAD_UNINT ) ); 2463 } 2464 2465 IOLockUnlock(_deblockRequestWriteLock); 2466 } 2467 2468 // Execute the transfer (for the next stage). 2469 2470 deblockRequestCompletion(this, deblocker, kIOReturnSuccess, 0); 2471} 2472 2473void IOBlockStorageDriver::deblockRequestCompletion( void * target, 2474 void * parameter, 2475 IOReturn status, 2476 UInt64 actualByteCount ) 2477{ 2478 // 2479 // This is the completion routine for the aligned deblocker subrequests. 2480 // It verifies the success of the just-completed stage, transitions to 2481 // the next stage, then builds and issues a transfer for the next stage. 2482 // 2483 2484 thread_call_t callback; 2485 IODeblocker * deblocker = (IODeblocker *) parameter; 2486 IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; 2487 2488 // Allocate a thread callback. 2489 2490 callback = deblocker->getThreadCallback(); 2491 2492#if !TARGET_OS_EMBEDDED 2493 if ( callback == 0 ) 2494 { 2495 if ( deblocker->setThreadCallback(deblockRequestExecute) == false ) 2496 { 2497 status = kIOReturnNoMemory; 2498 } 2499 } 2500#endif /* !TARGET_OS_EMBEDDED */ 2501 2502 // Determine whether an error occurred or whether there are no more stages. 2503 2504 if ( actualByteCount < deblocker->getLength() || 2505 status != kIOReturnSuccess || 2506 deblocker->getNextStage() == false ) 2507 { 2508 IOStorageCompletion * completion; 2509 2510 // Unlock the write-lock in order to allow the next write to proceed. 2511 2512 if ( deblocker->getRequestBuffer()->getDirection() == kIODirectionOut ) 2513 { 2514 IOLockLock(driver->_deblockRequestWriteLock); 2515 2516 driver->_deblockRequestWriteLockCount--; 2517 2518 if ( driver->_deblockRequestWriteLockCount > 0 ) 2519 { 2520 IOLockWakeup( /* lock */ driver->_deblockRequestWriteLock, 2521 /* event */ driver->_deblockRequestWriteLock, 2522 /* one */ true ); 2523 } 2524 2525 IOLockUnlock(driver->_deblockRequestWriteLock); 2526 } 2527 2528 // Obtain the completion information for the original request, taking 2529 // into account the actual byte count of the current stage. 2530 2531 completion = deblocker->getRequestCompletion(&actualByteCount); 2532 2533 // Complete the original request. 2534 2535 IOStorage::complete(completion, status, actualByteCount); 2536 2537 // Release our resources. 2538 2539 deblocker->release(); 2540 } 2541 else 2542 { 2543 // Execute the transfer (for the next stage). 2544 2545 if ( callback ) 2546 { 2547 thread_call_enter1(callback, driver); 2548 } 2549 else 2550 { 2551 deblockRequestExecute(deblocker, driver); 2552 } 2553 } 2554} 2555 2556void IOBlockStorageDriver::deblockRequestExecute(void * parameter, void * target) 2557{ 2558 // 2559 // Execute the transfer (for the next stage). 2560 // 2561 2562 IOStorageAttributes * attributes; 2563 UInt64 byteStart; 2564 IOStorageCompletion completion; 2565 Context * context; 2566 IODeblocker * deblocker = (IODeblocker *) parameter; 2567 IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; 2568 2569 attributes = deblocker->getRequestAttributes(); 2570 2571 byteStart = deblocker->getByteStart(); 2572 2573 completion.target = driver; 2574 completion.action = deblockRequestCompletion; 2575 completion.parameter = deblocker; 2576 2577 context = (Context *) deblocker->getRequestContext(); 2578 2579#ifdef __LP64__ 2580 driver->breakUpRequest(byteStart, deblocker, attributes, &completion, context); 2581#else /* !__LP64__ */ 2582 driver->breakUpRequest(byteStart, deblocker, completion, context); 2583#endif /* !__LP64__ */ 2584} 2585 2586// ----------------------------------------------------------------------------- 2587// Breaker Implementation 2588 2589class IOBreaker : public IOSubMemoryDescriptor 2590{ 2591 OSDeclareDefaultStructors(IOBreaker); 2592 2593protected: 2594 2595 UInt64 _breakSize; 2596 2597 UInt64 _maximumBlockCount; 2598 UInt64 _maximumByteCount; 2599 UInt64 _maximumSegmentCount; 2600 UInt64 _maximumSegmentByteCount; 2601 UInt64 _minimumSegmentAlignmentByteCount; 2602 UInt64 _maximumSegmentWidthByteCount; 2603 2604 UInt64 _requestBlockSize; 2605 IOMemoryDescriptor * _requestBuffer; 2606 IOStorageAttributes _requestAttributes; 2607 IOStorageCompletion _requestCompletion; 2608 void * _requestContext; 2609 UInt64 _requestCount; 2610 UInt64 _requestStart; 2611 2612 UInt64 _byteStart; 2613 2614 thread_call_t _threadCallback; 2615 2616 virtual void free(); 2617 2618public: 2619 2620 static UInt64 getBreakSize( 2621 UInt64 withMaximumBlockCount, 2622 UInt64 withMaximumByteCount, 2623 UInt64 withMaximumSegmentCount, 2624 UInt64 withMaximumSegmentByteCount, 2625 UInt64 withMinimumSegmentAlignmentByteCount, 2626 UInt64 withMaximumSegmentWidthByteCount, 2627 UInt64 withRequestBlockSize, 2628 IOMemoryDescriptor * withRequestBuffer, 2629 UInt64 withRequestBufferOffset ); 2630 2631 static IOBreaker * withBreakSize( 2632 UInt64 breakSize, 2633 UInt64 withMaximumBlockCount, 2634 UInt64 withMaximumByteCount, 2635 UInt64 withMaximumSegmentCount, 2636 UInt64 withMaximumSegmentByteCount, 2637 UInt64 withMinimumSegmentAlignmentByteCount, 2638 UInt64 withMaximumSegmentWidthByteCount, 2639 UInt64 withRequestBlockSize, 2640 UInt64 withRequestStart, 2641 IOMemoryDescriptor * withRequestBuffer, 2642 IOStorageAttributes * withRequestAttributes, 2643 IOStorageCompletion * withRequestCompletion, 2644 void * withRequestContext ); 2645 2646 virtual bool initWithBreakSize( 2647 UInt64 breakSize, 2648 UInt64 withMaximumBlockCount, 2649 UInt64 withMaximumByteCount, 2650 UInt64 withMaximumSegmentCount, 2651 UInt64 withMaximumSegmentByteCount, 2652 UInt64 withMinimumSegmentAlignmentByteCount, 2653 UInt64 withMaximumSegmentWidthByteCount, 2654 UInt64 withRequestBlockSize, 2655 UInt64 withRequestStart, 2656 IOMemoryDescriptor * withRequestBuffer, 2657 IOStorageAttributes * withRequestAttributes, 2658 IOStorageCompletion * withRequestCompletion, 2659 void * withRequestContext ); 2660 2661 virtual bool getNextStage(); 2662 2663 virtual IOStorageAttributes * getRequestAttributes(); 2664 2665 virtual IOStorageCompletion * getRequestCompletion(UInt64 * actualByteCount); 2666 2667 virtual IOMemoryDescriptor * getRequestBuffer(); 2668 2669 virtual void * getRequestContext(); 2670 2671 virtual UInt64 getByteStart(); 2672 2673 virtual thread_call_t getThreadCallback(); 2674 2675 virtual bool setThreadCallback(thread_call_func_t callback); 2676}; 2677 2678#undef super 2679#define super IOSubMemoryDescriptor 2680OSDefineMetaClassAndStructors(IOBreaker, IOSubMemoryDescriptor) 2681 2682UInt64 IOBreaker::getBreakSize( 2683 UInt64 withMaximumBlockCount, 2684 UInt64 withMaximumByteCount, 2685 UInt64 withMaximumSegmentCount, 2686 UInt64 withMaximumSegmentByteCount, 2687 UInt64 withMinimumSegmentAlignmentByteCount, 2688 UInt64 withMaximumSegmentWidthByteCount, 2689 UInt64 withRequestBlockSize, 2690 IOMemoryDescriptor * withRequestBuffer, 2691 UInt64 withRequestBufferOffset ) 2692{ 2693 // 2694 // Determine where the next break point is given our constraints. 2695 // 2696 2697 UInt64 breakSize = 0; 2698 IOMemoryDescriptor * buffer = withRequestBuffer; 2699 IOByteCount bufferLength = withRequestBuffer->getLength(); 2700 IOByteCount bufferOffset = withRequestBufferOffset; 2701 addr64_t chunk = 0; 2702 UInt32 chunkSize = 0; 2703 addr64_t segment = 0; 2704 UInt32 segmentCount = 0; 2705 IOByteCount segmentSize = 0; 2706 2707 // Prepare segment alignment mask. 2708 2709 if ( withMinimumSegmentAlignmentByteCount ) 2710 { 2711 withMinimumSegmentAlignmentByteCount--; 2712 } 2713 2714 // Constrain block count. 2715 2716 if ( withMaximumBlockCount ) 2717 { 2718 UInt64 blockCountInBytes; 2719 2720 blockCountInBytes = withMaximumBlockCount * withRequestBlockSize; 2721 2722 if ( withMaximumByteCount ) 2723 { 2724 withMaximumByteCount = min(blockCountInBytes, withMaximumByteCount); 2725 } 2726 else 2727 { 2728 withMaximumByteCount = blockCountInBytes; 2729 } 2730 } 2731 2732 // Scan the buffer's segments. 2733 2734 while ( segment || bufferOffset < bufferLength ) 2735 { 2736 // Obtain a new segment. 2737 2738 if ( segment == 0 ) 2739 { 2740 segment = buffer->getPhysicalSegment(bufferOffset, &segmentSize, 0); 2741 2742 assert(segment); 2743 assert(segmentSize); 2744 2745 bufferOffset += segmentSize; 2746 } 2747 2748 // Fold in a segment. 2749 2750 if ( chunk == 0 ) 2751 { 2752 breakSize += segmentSize; 2753 2754 chunk = segment; 2755 chunkSize = segmentSize; 2756 2757 segment = 0; 2758 segmentSize = 0; 2759 2760 segmentCount++; 2761 } 2762 else if ( chunk + chunkSize == segment ) 2763 { 2764 breakSize += segmentSize; 2765 chunkSize += segmentSize; 2766 2767 segment = 0; 2768 segmentSize = 0; 2769 } 2770 2771 // Trim a complete segment. 2772 2773 if ( segment == 0 ) 2774 { 2775 // Constrain segment byte count. 2776 2777 if ( withMaximumSegmentByteCount ) 2778 { 2779 if ( chunkSize > withMaximumSegmentByteCount ) 2780 { 2781 segmentSize = chunkSize - withMaximumSegmentByteCount; 2782 } 2783 } 2784 2785 // Constrain segment alignment byte count. 2786 2787 if ( withMinimumSegmentAlignmentByteCount ) 2788 { 2789 if ( ( chunk & withMinimumSegmentAlignmentByteCount ) || ( chunkSize & withMinimumSegmentAlignmentByteCount ) ) 2790 { 2791 if ( chunkSize > PAGE_SIZE ) 2792 { 2793 segmentSize = max(chunkSize - PAGE_SIZE, segmentSize); 2794 } 2795 } 2796 } 2797 2798 // Constrain segment width byte count. 2799 2800 if ( withMaximumSegmentWidthByteCount ) 2801 { 2802 if ( chunk >= withMaximumSegmentWidthByteCount ) 2803 { 2804 if ( chunkSize > PAGE_SIZE ) 2805 { 2806 segmentSize = max(chunkSize - PAGE_SIZE, segmentSize); 2807 } 2808 } 2809 else if ( chunk + chunkSize > withMaximumSegmentWidthByteCount ) 2810 { 2811 segmentSize = max(chunk + chunkSize - withMaximumSegmentWidthByteCount, segmentSize); 2812 } 2813 } 2814 2815 if ( segmentSize ) 2816 { 2817 segment = chunk + chunkSize - segmentSize; 2818 2819 breakSize -= segmentSize; 2820 chunkSize -= segmentSize; 2821 } 2822 2823 // Constrain byte count. 2824 2825 if ( withMaximumByteCount ) 2826 { 2827 if ( breakSize >= withMaximumByteCount ) 2828 { 2829 breakSize = withMaximumByteCount; 2830 break; 2831 } 2832 } 2833 } 2834 2835 // Commit a complete segment. 2836 2837 if ( segment ) 2838 { 2839 // Constrain segment count. 2840 2841 if ( withMaximumSegmentCount ) 2842 { 2843 if ( segmentCount == withMaximumSegmentCount ) 2844 { 2845 break; 2846 } 2847 } 2848 2849 chunk = 0; 2850 chunkSize = 0; 2851 } 2852 } 2853 2854 breakSize = IOTrunc(breakSize, withRequestBlockSize); 2855 2856 return breakSize; 2857} 2858 2859IOBreaker * IOBreaker::withBreakSize( 2860 UInt64 breakSize, 2861 UInt64 withMaximumBlockCount, 2862 UInt64 withMaximumByteCount, 2863 UInt64 withMaximumSegmentCount, 2864 UInt64 withMaximumSegmentByteCount, 2865 UInt64 withMinimumSegmentAlignmentByteCount, 2866 UInt64 withMaximumSegmentWidthByteCount, 2867 UInt64 withRequestBlockSize, 2868 UInt64 withRequestStart, 2869 IOMemoryDescriptor * withRequestBuffer, 2870 IOStorageAttributes * withRequestAttributes, 2871 IOStorageCompletion * withRequestCompletion, 2872 void * withRequestContext ) 2873{ 2874 // 2875 // Create a new IOBreaker. 2876 // 2877 2878 IOBreaker * me = new IOBreaker; 2879 2880 if ( me && me->initWithBreakSize( 2881 /* breakSize */ breakSize, 2882 /* withMaximumBlockCount */ withMaximumBlockCount, 2883 /* withMaximumByteCount */ withMaximumByteCount, 2884 /* withMaximumSegmentCount */ withMaximumSegmentCount, 2885 /* withMaximumSegmentByteCount */ withMaximumSegmentByteCount, 2886 /* withMinimumSegmentAlignmentByteCount */ withMinimumSegmentAlignmentByteCount, 2887 /* withMaximumSegmentWidthByteCount */ withMaximumSegmentWidthByteCount, 2888 /* withRequestBlockSize */ withRequestBlockSize, 2889 /* withRequestStart */ withRequestStart, 2890 /* withRequestBuffer */ withRequestBuffer, 2891 /* withRequestAttributes */ withRequestAttributes, 2892 /* withRequestCompletion */ withRequestCompletion, 2893 /* withRequestContext */ withRequestContext ) == false ) 2894 { 2895 me->release(); 2896 me = 0; 2897 } 2898 2899 return me; 2900} 2901 2902bool IOBreaker::initWithBreakSize( 2903 UInt64 breakSize, 2904 UInt64 withMaximumBlockCount, 2905 UInt64 withMaximumByteCount, 2906 UInt64 withMaximumSegmentCount, 2907 UInt64 withMaximumSegmentByteCount, 2908 UInt64 withMinimumSegmentAlignmentByteCount, 2909 UInt64 withMaximumSegmentWidthByteCount, 2910 UInt64 withRequestBlockSize, 2911 UInt64 withRequestStart, 2912 IOMemoryDescriptor * withRequestBuffer, 2913 IOStorageAttributes * withRequestAttributes, 2914 IOStorageCompletion * withRequestCompletion, 2915 void * withRequestContext ) 2916{ 2917 // 2918 // Initialize an IOBreaker. 2919 // 2920 2921 // Ask our superclass' opinion. 2922 2923 if ( super::initSubRange( 2924 /* parent */ withRequestBuffer, 2925 /* withOffset */ 0, 2926 /* withLength */ withRequestBuffer->getLength(), 2927 /* withDirection */ withRequestBuffer->getDirection() ) == false ) 2928 { 2929 return false; 2930 } 2931 2932 // Initialize our minimal state. 2933 2934 _breakSize = breakSize; 2935 _length = 0; 2936 2937 _maximumBlockCount = withMaximumBlockCount; 2938 _maximumByteCount = withMaximumByteCount; 2939 _maximumSegmentCount = withMaximumSegmentCount; 2940 _maximumSegmentByteCount = withMaximumSegmentByteCount; 2941 _minimumSegmentAlignmentByteCount = withMinimumSegmentAlignmentByteCount; 2942 _maximumSegmentWidthByteCount = withMaximumSegmentWidthByteCount; 2943 2944 _requestBlockSize = withRequestBlockSize; 2945 _requestBuffer = withRequestBuffer; 2946 _requestBuffer->retain(); 2947 2948 if (withRequestAttributes) _requestAttributes = *withRequestAttributes; 2949 if (withRequestCompletion) _requestCompletion = *withRequestCompletion; 2950 2951 _requestContext = withRequestContext; 2952 _requestCount = withRequestBuffer->getLength(); 2953 _requestStart = withRequestStart; 2954 2955 return true; 2956} 2957 2958void IOBreaker::free() 2959{ 2960 // 2961 // Free all of this object's outstanding resources. 2962 // 2963 2964 if ( _requestBuffer ) _requestBuffer->release(); 2965 if ( _threadCallback ) thread_call_free(_threadCallback); 2966 2967 super::free(); 2968} 2969 2970bool IOBreaker::getNextStage() 2971{ 2972 // 2973 // Obtain the next stage of the transfer. The transfer buffer will be the 2974 // breaker object itself and the byte start will be returned in getByteStart(). 2975 // 2976 // This method must not be called if the current stage failed with an error 2977 // or a short byte count, but instead getRequestCompletion() must be called 2978 // to adjust the status and actual byte count (with respect to the original 2979 // request) and return the original request's completion routine. The same 2980 // call to getRequestCompletion() should also be done if the getNextStage() 2981 // method returns false. 2982 // 2983 2984 if ( _start + _length < _requestCount ) 2985 { 2986 _start += _length; 2987 _length = min(_breakSize, _requestCount - _start); 2988 2989 _breakSize = getBreakSize( 2990 /* withMaximumBlockCount */ _maximumBlockCount, 2991 /* withMaximumByteCount */ _maximumByteCount, 2992 /* withMaximumSegmentCount */ _maximumSegmentCount, 2993 /* withMaximumSegmentByteCount */ _maximumSegmentByteCount, 2994 /* withMinimumSegmentAlignmentByteCount */ _minimumSegmentAlignmentByteCount, 2995 /* withMaximumSegmentWidthByteCount */ _maximumSegmentWidthByteCount, 2996 /* withRequestBlockSize */ _requestBlockSize, 2997 /* withRequestBuffer */ _requestBuffer, 2998 /* withRequestBufferOffset */ _start + _length ); 2999 } 3000 else 3001 { 3002 return false; 3003 } 3004 3005 _byteStart = _requestStart + _start; 3006 3007 return true; 3008} 3009 3010IOStorageAttributes * IOBreaker::getRequestAttributes() 3011{ 3012 // 3013 // Obtain the attributes for the original request. 3014 // 3015 3016 return &_requestAttributes; 3017} 3018 3019IOStorageCompletion * IOBreaker::getRequestCompletion(UInt64 * actualByteCount) 3020{ 3021 // 3022 // Obtain the completion information for the original request, taking 3023 // into account the actual byte count of the current stage. 3024 // 3025 3026 *actualByteCount += _start; 3027 3028 return &_requestCompletion; 3029} 3030 3031IOMemoryDescriptor * IOBreaker::getRequestBuffer() 3032{ 3033 // 3034 // Obtain the buffer for the original request. 3035 // 3036 3037 return _requestBuffer; 3038} 3039 3040void * IOBreaker::getRequestContext() 3041{ 3042 // 3043 // Obtain the context for the original request. 3044 // 3045 3046 return _requestContext; 3047} 3048 3049UInt64 IOBreaker::getByteStart() 3050{ 3051 // 3052 // Obtain the byte start for the current stage. 3053 // 3054 3055 return _byteStart; 3056} 3057 3058thread_call_t IOBreaker::getThreadCallback() 3059{ 3060 // 3061 // Obtain the thread callback. 3062 // 3063 3064 return _threadCallback; 3065} 3066 3067bool IOBreaker::setThreadCallback(thread_call_func_t callback) 3068{ 3069 // 3070 // Allocate a thread callback. 3071 // 3072 3073 _threadCallback = thread_call_allocate(callback, this); 3074 3075 return _threadCallback ? true : false; 3076} 3077 3078void IOBlockStorageDriver::breakUpRequest( 3079 UInt64 byteStart, 3080 IOMemoryDescriptor * buffer, 3081#ifdef __LP64__ 3082 IOStorageAttributes * attributes, 3083 IOStorageCompletion * completion, 3084#else /* !__LP64__ */ 3085 IOStorageCompletion completion, 3086#endif /* !__LP64__ */ 3087 IOBlockStorageDriver::Context * context ) 3088{ 3089 // 3090 // The breakUpRequest method checks to see if the incoming request exceeds 3091 // our transfer constraints, and if so, breaks up the request into smaller 3092 // sub-requests. 3093 // 3094 // This method is part of a sequence of methods invoked for each read/write 3095 // request. The first is prepareRequest, which allocates and prepares some 3096 // context for the transfer; the second is deblockRequest, which aligns the 3097 // transfer at the media's block boundaries; third is breakUpRequest, which 3098 // breaks up the transfer into multiple sub-transfers when certain hardware 3099 // constraints are exceeded; fourth is executeRequest, which implements the 3100 // actual transfer from the block storage device. 3101 // 3102 // The current implementation of breakUpRequest is asynchronous. 3103 // 3104 3105 IOBreaker * breaker; 3106 UInt64 breakSize; 3107 3108 // State our assumptions. 3109 3110 assert((byteStart % context->block.size) == 0); 3111 assert((buffer->getLength() % context->block.size) == 0); 3112 3113 // Determine the transfer constraint, based on direction. 3114 3115 if ( buffer->getDirection() == kIODirectionIn ) 3116 { 3117 breakSize = IOBreaker::getBreakSize( 3118 /* withMaximumBlockCount */ _maxReadBlockTransfer, 3119 /* withMaximumByteCount */ _maxReadByteTransfer, 3120 /* withMaximumSegmentCount */ _maxReadSegmentTransfer, 3121 /* withMaximumSegmentByteCount */ _maxReadSegmentByteTransfer, 3122 /* withMinimumSegmentAlignmentByteCount */ _minSegmentAlignmentByteTransfer, 3123 /* withMaximumSegmentWidthByteCount */ _maxSegmentWidthByteTransfer, 3124 /* withRequestBlockSize */ context->block.size, 3125 /* withRequestBuffer */ buffer, 3126 /* withRequestBufferOffset */ 0 ); 3127 } 3128 else 3129 { 3130 breakSize = IOBreaker::getBreakSize( 3131 /* withMaximumBlockCount */ _maxWriteBlockTransfer, 3132 /* withMaximumByteCount */ _maxWriteByteTransfer, 3133 /* withMaximumSegmentCount */ _maxWriteSegmentTransfer, 3134 /* withMaximumSegmentByteCount */ _maxWriteSegmentByteTransfer, 3135 /* withMinimumSegmentAlignmentByteCount */ _minSegmentAlignmentByteTransfer, 3136 /* withMaximumSegmentWidthByteCount */ _maxSegmentWidthByteTransfer, 3137 /* withRequestBlockSize */ context->block.size, 3138 /* withRequestBuffer */ buffer, 3139 /* withRequestBufferOffset */ 0 ); 3140 } 3141 3142 if ( breakSize == 0 ) 3143 { 3144 complete(completion, kIOReturnDMAError); 3145 return; 3146 } 3147 3148 // If the request doesn't exceed our transfer constaints, we do 3149 // short-circuit the break-up and call executeRequest directly. 3150 3151 if ( buffer->getLength() <= breakSize ) 3152 { 3153#ifdef __LP64__ 3154 executeRequest(byteStart, buffer, attributes, completion, context); 3155#else /* !__LP64__ */ 3156 executeRequest(byteStart, buffer, completion, context); 3157#endif /* !__LP64__ */ 3158 return; 3159 } 3160 3161 // Build a breaker object. 3162 3163 if ( buffer->getDirection() == kIODirectionIn ) 3164 { 3165 breaker = IOBreaker::withBreakSize( 3166 /* breakSize */ breakSize, 3167 /* withMaximumBlockCount */ _maxReadBlockTransfer, 3168 /* withMaximumByteCount */ _maxReadByteTransfer, 3169 /* withMaximumSegmentCount */ _maxReadSegmentTransfer, 3170 /* withMaximumSegmentByteCount */ _maxReadSegmentByteTransfer, 3171 /* withMinimumSegmentAlignmentByteCount */ _minSegmentAlignmentByteTransfer, 3172 /* withMaximumSegmentWidthByteCount */ _maxSegmentWidthByteTransfer, 3173 /* withRequestBlockSize */ context->block.size, 3174 /* withRequestStart */ byteStart, 3175 /* withRequestBuffer */ buffer, 3176#ifdef __LP64__ 3177 /* withRequestAttributes */ attributes, 3178 /* withRequestCompletion */ completion, 3179#else /* !__LP64__ */ 3180 /* withRequestAttributes */ NULL, 3181 /* withRequestCompletion */ &completion, 3182#endif /* !__LP64__ */ 3183 /* withRequestContext */ context ); 3184 } 3185 else 3186 { 3187 breaker = IOBreaker::withBreakSize( 3188 /* breakSize */ breakSize, 3189 /* withMaximumBlockCount */ _maxWriteBlockTransfer, 3190 /* withMaximumByteCount */ _maxWriteByteTransfer, 3191 /* withMaximumSegmentCount */ _maxWriteSegmentTransfer, 3192 /* withMaximumSegmentByteCount */ _maxWriteSegmentByteTransfer, 3193 /* withMinimumSegmentAlignmentByteCount */ _minSegmentAlignmentByteTransfer, 3194 /* withMaximumSegmentWidthByteCount */ _maxSegmentWidthByteTransfer, 3195 /* withRequestBlockSize */ context->block.size, 3196 /* withRequestStart */ byteStart, 3197 /* withRequestBuffer */ buffer, 3198#ifdef __LP64__ 3199 /* withRequestAttributes */ attributes, 3200 /* withRequestCompletion */ completion, 3201#else /* !__LP64__ */ 3202 /* withRequestAttributes */ NULL, 3203 /* withRequestCompletion */ &completion, 3204#endif /* !__LP64__ */ 3205 /* withRequestContext */ context ); 3206 } 3207 3208 if ( breaker == 0 ) 3209 { 3210 complete(completion, kIOReturnNoMemory); 3211 return; 3212 } 3213 3214 // Execute the transfer (for the next stage). 3215 3216 breakUpRequestCompletion(this, breaker, kIOReturnSuccess, 0); 3217} 3218 3219void IOBlockStorageDriver::breakUpRequestCompletion( void * target, 3220 void * parameter, 3221 IOReturn status, 3222 UInt64 actualByteCount ) 3223{ 3224 // 3225 // This is the completion routine for the broken-up breaker subrequests. 3226 // It verifies the success of the just-completed stage, transitions to 3227 // the next stage, then builds and issues a transfer for the next stage. 3228 // 3229 3230 IOBreaker * breaker = (IOBreaker *) parameter; 3231 thread_call_t callback; 3232 IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; 3233 3234 // Allocate a thread callback. 3235 3236 callback = breaker->getThreadCallback(); 3237 3238#if !TARGET_OS_EMBEDDED 3239 if ( callback == 0 ) 3240 { 3241 if ( breaker->setThreadCallback(breakUpRequestExecute) == false ) 3242 { 3243 status = kIOReturnNoMemory; 3244 } 3245 } 3246#endif /* !TARGET_OS_EMBEDDED */ 3247 3248 // Determine whether an error occurred or whether there are no more stages. 3249 3250 if ( actualByteCount < breaker->getLength() || 3251 status != kIOReturnSuccess || 3252 breaker->getNextStage() == false ) 3253 { 3254 IOStorageCompletion * completion; 3255 3256 // Obtain the completion information for the original request, taking 3257 // into account the actual byte count of the current stage. 3258 3259 completion = breaker->getRequestCompletion(&actualByteCount); 3260 3261 // Complete the original request. 3262 3263 IOStorage::complete(completion, status, actualByteCount); 3264 3265 // Release our resources. 3266 3267 breaker->release(); 3268 } 3269 else 3270 { 3271 // Execute the transfer (for the next stage). 3272 3273 if ( callback ) 3274 { 3275 thread_call_enter1(callback, driver); 3276 } 3277 else 3278 { 3279 breakUpRequestExecute(breaker, driver); 3280 } 3281 } 3282} 3283 3284void IOBlockStorageDriver::breakUpRequestExecute(void * parameter, void * target) 3285{ 3286 // 3287 // Execute the transfer (for the next stage). 3288 // 3289 3290 IOStorageAttributes * attributes; 3291 IOBreaker * breaker = (IOBreaker *) parameter; 3292 UInt64 byteStart; 3293 IOStorageCompletion completion; 3294 Context * context; 3295 IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; 3296 3297 attributes = breaker->getRequestAttributes(); 3298 3299 byteStart = breaker->getByteStart(); 3300 3301 completion.target = driver; 3302 completion.action = breakUpRequestCompletion; 3303 completion.parameter = breaker; 3304 3305 context = (Context *) breaker->getRequestContext(); 3306 3307#ifdef __LP64__ 3308 driver->executeRequest(byteStart, breaker, attributes, &completion, context); 3309#else /* !__LP64__ */ 3310 driver->executeRequest(byteStart, breaker, completion, context); 3311#endif /* !__LP64__ */ 3312} 3313 3314void IOBlockStorageDriver::prepareRequest(UInt64 byteStart, 3315 IOMemoryDescriptor * buffer, 3316 IOStorageAttributes * attributes, 3317 IOStorageCompletion * completion) 3318{ 3319 // 3320 // The prepareRequest method allocates and prepares state for the transfer. 3321 // 3322 // This method is part of a sequence of methods invoked for each read/write 3323 // request. The first is prepareRequest, which allocates and prepares some 3324 // context for the transfer; the second is deblockRequest, which aligns the 3325 // transfer at the media's block boundaries; third is breakUpRequest, which 3326 // breaks up the transfer into multiple sub-transfers when certain hardware 3327 // constraints are exceeded; fourth is executeRequest, which implements the 3328 // actual transfer from the block storage device. 3329 // 3330 3331 IOStorageCompletion completionOut; 3332 Context * context; 3333 3334 // Determine whether the attributes are valid. 3335 3336 if (attributes) 3337 { 3338 if ((attributes->options & kIOStorageOptionReserved)) 3339 { 3340 complete(completion, kIOReturnBadArgument); 3341 return; 3342 } 3343 3344#ifdef __LP64__ 3345 if (attributes->reserved0032 || attributes->reserved0064 || attributes->reserved0128) 3346 { 3347 complete(completion, kIOReturnBadArgument); 3348 return; 3349 } 3350#else /* !__LP64__ */ 3351#if !TARGET_OS_EMBEDDED 3352 if (attributes->reserved0064) 3353 { 3354 complete(completion, kIOReturnBadArgument); 3355 return; 3356 } 3357#endif /* !TARGET_OS_EMBEDDED */ 3358#endif /* !__LP64__ */ 3359 } 3360 3361 // Allocate a context structure to hold some of our state. 3362 3363 context = allocateContext(); 3364 3365 if (context == 0) 3366 { 3367 complete(completion, kIOReturnNoMemory); 3368 return; 3369 } 3370 3371 // Fill in the context structure with some of our state. 3372 3373 context->block.size = getMediaBlockSize(); 3374 context->block.type = kBlockTypeStandard; 3375 3376 context->original.byteStart = byteStart; 3377 context->original.buffer = buffer; 3378 context->original.buffer->retain(); 3379 3380 if (attributes) context->request.attributes = *attributes; 3381 if (completion) context->original.completion = *completion; 3382 3383 clock_get_uptime(&context->timeStart); 3384 3385 completionOut.target = this; 3386 completionOut.action = prepareRequestCompletion; 3387 completionOut.parameter = context; 3388 3389 // Deblock the transfer. 3390 3391#ifdef __LP64__ 3392 deblockRequest(byteStart, buffer, attributes, &completionOut, context); 3393#else /* !__LP64__ */ 3394 deblockRequest(byteStart, buffer, completionOut, context); 3395#endif /* !__LP64__ */ 3396} 3397 3398IOReturn 3399IOBlockStorageDriver::requestIdle(void) 3400{ 3401 return(getProvider()->requestIdle()); 3402} 3403 3404#ifdef __LP64__ 3405OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 0); 3406OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 1); 3407OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 2); 3408#else /* !__LP64__ */ 3409OSMetaClassDefineReservedUsed(IOBlockStorageDriver, 0); 3410OSMetaClassDefineReservedUsed(IOBlockStorageDriver, 1); 3411OSMetaClassDefineReservedUsed(IOBlockStorageDriver, 2); 3412#endif /* !__LP64__ */ 3413OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 3); 3414OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 4); 3415OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 5); 3416OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 6); 3417OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 7); 3418OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 8); 3419OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 9); 3420OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 10); 3421OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 11); 3422OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 12); 3423OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 13); 3424OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 14); 3425OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 15); 3426OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 16); 3427OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 17); 3428OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 18); 3429OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 19); 3430OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 20); 3431OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 21); 3432OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 22); 3433OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 23); 3434OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 24); 3435OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 25); 3436OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 26); 3437OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 27); 3438OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 28); 3439OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 29); 3440OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 30); 3441OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 31); 3442 3443#ifndef __LP64__ 3444extern "C" void _ZN20IOBlockStorageDriver4readEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOBlockStorageDriver * driver, IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageCompletion completion ) 3445{ 3446 driver->read( client, byteStart, buffer, NULL, &completion ); 3447} 3448 3449extern "C" void _ZN20IOBlockStorageDriver5writeEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOBlockStorageDriver * driver, IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageCompletion completion ) 3450{ 3451 driver->write( client, byteStart, buffer, NULL, &completion ); 3452} 3453#endif /* !__LP64__ */ 3454