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