1/* 2 * Copyright (c) 2002-2007 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 25//----------------------------------------------------------------------------- 26// Includes 27//----------------------------------------------------------------------------- 28 29 30// SCSI Parallel Family includes 31#include "IOSCSIParallelInterfaceController.h" 32#include "IOSCSIParallelInterfaceDevice.h" 33#include "SCSIParallelTask.h" 34#include "SCSIParallelTimer.h" 35#include "SCSIParallelWorkLoop.h" 36 37// Libkern includes 38#include <libkern/OSAtomic.h> 39#include <libkern/c++/OSData.h> 40#include <libkern/c++/OSDictionary.h> 41#include <libkern/c++/OSNumber.h> 42#include <libkern/c++/OSString.h> 43 44// Generic IOKit includes 45#include <IOKit/IOLib.h> 46#include <IOKit/IOService.h> 47#include <IOKit/IOFilterInterruptEventSource.h> 48#include <IOKit/IOKitKeys.h> 49#include <IOKit/IOCommandPool.h> 50#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 51#include <IOKit/storage/IOStorageDeviceCharacteristics.h> 52 53 54//----------------------------------------------------------------------------- 55// Macros 56//----------------------------------------------------------------------------- 57 58 59#define DEBUG 0 60#define DEBUG_ASSERT_COMPONENT_NAME_STRING "SPI Controller" 61 62#if DEBUG 63#define SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL 0 64#endif 65 66#include "IOSCSIParallelFamilyDebugging.h" 67 68#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 1 ) 69#define PANIC_NOW(x) panic x 70#else 71#define PANIC_NOW(x) 72#endif 73 74#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 2 ) 75#define ERROR_LOG(x) IOLog x 76#else 77#define ERROR_LOG(x) 78#endif 79 80#if ( SCSI_PARALLEL_INTERFACE_CONTROLLER_DEBUGGING_LEVEL >= 3 ) 81#define STATUS_LOG(x) IOLog x 82#else 83#define STATUS_LOG(x) 84#endif 85 86 87#define super IOService 88OSDefineMetaClass ( IOSCSIParallelInterfaceController, IOService ); 89OSDefineAbstractStructors ( IOSCSIParallelInterfaceController, IOService ); 90 91 92//----------------------------------------------------------------------------- 93// Constants 94//----------------------------------------------------------------------------- 95 96#define kIOPropertySCSIInitiatorManagesTargets "Manages Targets" 97#define kIOPropertyControllerCharacteristicsKey "Controller Characteristics" 98#define kIOPropertyDeviceTreeEntryKey "IODeviceTreeEntry" 99 100enum 101{ 102 kWorldWideNameDataSize = 8, 103 kAddressIdentifierDataSize = 3, 104 kALPADataSize = 1, 105 kSASAddressDataSize = 8 106}; 107 108enum 109{ 110 kPhysicalInterconnectDictionaryEntryCount = 3, 111 kHBAContraintsDictionaryEntryCount = 7 112}; 113 114 115//----------------------------------------------------------------------------- 116// Static initialization 117//----------------------------------------------------------------------------- 118 119SInt32 IOSCSIParallelInterfaceController::fSCSIParallelDomainCount = 0; 120 121 122//----------------------------------------------------------------------------- 123// Prototypes 124//----------------------------------------------------------------------------- 125 126static IOSCSIParallelInterfaceDevice * 127GetDevice ( SCSIParallelTaskIdentifier parallelTask ); 128 129static void 130CopyProtocolCharacteristicsProperties ( OSDictionary * dict, IOService * service ); 131 132 133#if 0 134#pragma mark - 135#pragma mark IOKit Member Routines 136#pragma mark - 137#endif 138 139 140//----------------------------------------------------------------------------- 141// handleOpen - Handles opens on the object [PRIVATE] 142//----------------------------------------------------------------------------- 143 144bool 145IOSCSIParallelInterfaceController::handleOpen ( IOService * client, 146 IOOptionBits options, 147 void * arg ) 148{ 149 150 bool result = false; 151 152 STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::handleOpen\n" ) ); 153 154 result = fClients->setObject ( client ); 155 156 STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::handleOpen\n" ) ); 157 158 return result; 159 160} 161 162 163//----------------------------------------------------------------------------- 164// handleClose - Handles closes on the object [PRIVATE] 165//----------------------------------------------------------------------------- 166 167void 168IOSCSIParallelInterfaceController::handleClose ( 169 IOService * client, 170 IOOptionBits options ) 171{ 172 173 STATUS_LOG ( ( "IOSCSIParallelInterfaceController::handleClose\n" ) ); 174 fClients->removeObject ( client ); 175 176} 177 178 179//----------------------------------------------------------------------------- 180// handleIsOpen - Figures out if there are any opens on this object. [PRIVATE] 181//----------------------------------------------------------------------------- 182 183bool 184IOSCSIParallelInterfaceController::handleIsOpen ( const IOService * client ) const 185{ 186 187 bool result = false; 188 189 STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::handleIsOpen\n" ) ); 190 191 // Are they asking if a specific object has us open? 192 if ( client != NULL ) 193 { 194 result = fClients->containsObject ( client ); 195 } 196 197 // They're asking if we are open for any client 198 else 199 { 200 result = ( fClients->getCount ( ) > 0 ) ? true : false; 201 } 202 203 STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::handleIsOpen\n" ) ); 204 205 return result; 206 207} 208 209 210//----------------------------------------------------------------------------- 211// start - Begins provided services. [PRIVATE] 212//----------------------------------------------------------------------------- 213 214bool 215IOSCSIParallelInterfaceController::start ( IOService * provider ) 216{ 217 218 OSDictionary * dict = NULL; 219 OSDictionary * copyDict = NULL; 220 OSNumber * number = NULL; 221 bool result = false; 222 223 STATUS_LOG ( ( "IOSCSIParallelInterfaceController start.\n" ) ); 224 225 fSCSIDomainIdentifier = OSIncrementAtomic ( &fSCSIParallelDomainCount ); 226 227 result = super::start ( provider ); 228 require ( result, PROVIDER_START_FAILURE ); 229 230 require_nonzero ( provider, PROVIDER_START_FAILURE ); 231 232 result = provider->open ( this ); 233 require ( result, PROVIDER_START_FAILURE ); 234 235 fProvider = provider; 236 fWorkLoop = NULL; 237 fTimerEvent = NULL; 238 fDispatchEvent = NULL; 239 fControllerGate = NULL; 240 fHBAHasBeenInitialized = false; 241 fHBACanAcceptClientRequests = false; 242 fClients = OSSet::withCapacity ( 1 ); 243 244 fDeviceLock = IOSimpleLockAlloc ( ); 245 require_nonzero ( fDeviceLock, DEVICE_LOCK_ALLOC_FAILURE ); 246 247 result = CreateWorkLoop ( provider ); 248 require ( result, WORKLOOP_CREATE_FAILURE ); 249 250 dict = OSDictionary::withCapacity ( 1 ); 251 require_nonzero ( dict, CONTROLLER_DICT_FAILURE ); 252 253 setProperty ( kIOPropertyControllerCharacteristicsKey, dict ); 254 dict->release ( ); 255 dict = NULL; 256 257 // See if a protocol characteristics property already exists for the controller 258 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 259 if ( copyDict != NULL ) 260 { 261 262 // Create a deep copy of the dictionary. 263 dict = ( OSDictionary * ) copyDict->copyCollection ( ); 264 copyDict->release ( ); 265 266 } 267 268 else 269 { 270 271 // A Protocol Characteristics dictionary could not be retrieved, so one 272 // will be created. 273 dict = OSDictionary::withCapacity ( kPhysicalInterconnectDictionaryEntryCount ); 274 275 } 276 277 if ( dict != NULL ) 278 { 279 280 OSNumber * number = NULL; 281 282 // Copy any relevant properties from the IOService into the dictionary. 283 CopyProtocolCharacteristicsProperties ( dict, this ); 284 285 // Set the domain ID. 286 number = OSNumber::withNumber ( fSCSIDomainIdentifier, 32 ); 287 if ( number != NULL ) 288 { 289 290 dict->setObject ( kIOPropertySCSIDomainIdentifierKey, number ); 291 number->release ( ); 292 number = NULL; 293 294 } 295 296 setProperty ( kIOPropertyProtocolCharacteristicsKey, dict ); 297 298 // Release it since we created it. 299 dict->release ( ); 300 301 } 302 303 // All the necessary preparation work has been done 304 // for this superclass, now Initialize the chip driver. 305 result = InitializeController ( ); 306 require ( result, INIT_CONTROLLER_FAILURE ); 307 308 // Retrieve the Initiator Identifier for this HBA. 309 fInitiatorIdentifier = ReportInitiatorIdentifier ( ); 310 number = OSNumber::withNumber ( fInitiatorIdentifier, 64 ); 311 if ( number != NULL ) 312 { 313 314 setProperty ( kIOPropertySCSIInitiatorIdentifierKey, number ); 315 number->release ( ); 316 number = NULL; 317 318 } 319 320 // Now that the controller has been succesfully initialized, retrieve the 321 // necessary HBA specific information. 322 fHighestSupportedDeviceID = ReportHighestSupportedDeviceID ( ); 323 324 // Set the Device List structure to an initial value 325 InitializeDeviceList ( ); 326 327 fSupportedTaskCount = ReportMaximumTaskCount ( ); 328 329 // Allocate the SCSIParallelTasks and the pool 330 result = AllocateSCSIParallelTasks ( ); 331 require ( result, TASK_ALLOCATE_FAILURE ); 332 333 // The HBA has been fully initialized and is now ready to provide 334 // its services to the system. 335 fHBAHasBeenInitialized = true; 336 337 result = StartController ( ); 338 require ( result, START_CONTROLLER_FAILURE ); 339 340 // The controller is now ready to accept requests, set the flag so 341 // that the commands will be accepted 342 fHBACanAcceptClientRequests = true; 343 344 // Enable interrupts for the work loop as the 345 // HBA child class may need it to start the controller. 346 fWorkLoop->enableAllInterrupts ( ); 347 348 // Now create SCSI Device objects 349 result = DoesHBAPerformDeviceManagement ( ); 350 351 // Set the property 352 setProperty ( kIOPropertySCSIInitiatorManagesTargets, result ); 353 354 if ( result == false ) 355 { 356 357 // This HBA does not support a mechanism for device attach/detach 358 // notification, go ahead and create target devices. 359 for ( UInt32 index = 0; index <= fHighestSupportedDeviceID; index++ ) 360 { 361 362 CreateTargetForID ( index ); 363 364 } 365 366 } 367 368 registerService ( ); 369 result = true; 370 371 // The controller has been initialized and can accept requests. Target 372 // devices have either been created, or the HBA will create them as needed. 373 return result; 374 375 376START_CONTROLLER_FAILURE: 377 // START_CONTROLLER_FAILURE: 378 // If execution jumped to this label, the HBA child class was unsuccessful 379 // at starting its sevices. 380 381 // First step is to release the allocated SCSI Parallel Tasks 382 DeallocateSCSIParallelTasks ( ); 383 384 385TASK_ALLOCATE_FAILURE: 386 // TASK_ALLOCATE_FAILURE: 387 // If execution jumped to this label, SCSI Parallel Tasks failed to be 388 // allocated. 389 390 // Since the HBA child class was initialized, it needs to be terminated. 391 fHBAHasBeenInitialized = false; 392 TerminateController ( ); 393 394 395INIT_CONTROLLER_FAILURE: 396 // INIT_CONTROLLER_FAILURE: 397 // If execution jumped to this label, the HBA child class failed to 398 // properly initialize. Nothing to clean up, so fall through this label to 399 // next exception handling point. 400 401 402CONTROLLER_DICT_FAILURE: 403 // If execution jumped to this label, the HBA child class failed to 404 // create its controller characteristics dictionary. 405 406 // Release the workloop and associated objects. 407 ReleaseWorkLoop ( ); 408 409 410WORKLOOP_CREATE_FAILURE: 411 // WORKLOOP_CREATE_FAILURE: 412 // If execution jumped to this label, the workloop or associated objects 413 // could not be allocated. 414 IOSimpleLockFree ( fDeviceLock ); 415 fDeviceLock = NULL; 416 417 418DEVICE_LOCK_ALLOC_FAILURE: 419 // DEVICE_LOCK_ALLOC_FAILURE: 420 // Call the superclass to stop. 421 super::stop ( provider ); 422 423 424PROVIDER_START_FAILURE: 425 // PROVIDER_START_FAILURE: 426 // If execution jumped to this label, the Provider was not successfully 427 // started, no cleanup needs to be done. 428 429 // Since the start attempt was not successful, report that by 430 // returning false. 431 return false; 432 433} 434 435 436//----------------------------------------------------------------------------- 437// stop - Ends provided services. [PRIVATE] 438//----------------------------------------------------------------------------- 439 440void 441IOSCSIParallelInterfaceController::stop ( IOService * provider ) 442{ 443 444 // Halt all services from the subclass. 445 StopController ( ); 446 447 if ( fHBAHasBeenInitialized == true ) 448 { 449 450 fHBAHasBeenInitialized = false; 451 452 // Inform the subclass to terminate all allocated resources 453 TerminateController ( ); 454 455 } 456 457 // Free all of the SCSIParallelTasks and the pool. 458 DeallocateSCSIParallelTasks ( ); 459 460 // Release all WorkLoop related resources 461 ReleaseWorkLoop ( ); 462 463 super::stop ( provider ); 464 465} 466 467 468 469//----------------------------------------------------------------------------- 470// free - Frees resources. [PROTECTED] 471//----------------------------------------------------------------------------- 472 473void 474IOSCSIParallelInterfaceController::free ( void ) 475{ 476 477 if ( fDeviceLock != NULL ) 478 { 479 480 IOSimpleLockFree ( fDeviceLock ); 481 fDeviceLock = NULL; 482 483 } 484 485 super::free ( ); 486 487} 488 489 490//----------------------------------------------------------------------------- 491// willTerminate - Prevent HBA from accepting any further commands. 492// [PROTECTED] 493//----------------------------------------------------------------------------- 494 495bool 496IOSCSIParallelInterfaceController::willTerminate ( 497 IOService * provider, 498 IOOptionBits options ) 499{ 500 501 SCSITargetIdentifier index = 0; 502 503 // Prevent any new requests from being sent to the controller. 504 fHBACanAcceptClientRequests = false; 505 506 for ( index = 0; index < fHighestSupportedDeviceID; index++ ) 507 { 508 DestroyTargetForID ( index ); 509 } 510 511 return true; 512 513} 514 515 516//----------------------------------------------------------------------------- 517// didTerminate - Closes provider if all outstanding I/O is complete. 518// [PROTECTED] 519//----------------------------------------------------------------------------- 520 521bool 522IOSCSIParallelInterfaceController::didTerminate ( 523 IOService * provider, 524 IOOptionBits options, 525 bool * defer ) 526{ 527 528 if ( fProvider->isOpen ( this ) == true ) 529 { 530 fProvider->close ( this ); 531 } 532 533 return true; 534 535} 536 537 538//----------------------------------------------------------------------------- 539// getWorkLoop - Gets the workloop. [PRIVATE] 540//----------------------------------------------------------------------------- 541 542IOWorkLoop * 543IOSCSIParallelInterfaceController::getWorkLoop ( void ) const 544{ 545 return GetWorkLoop ( ); 546} 547 548 549//----------------------------------------------------------------------------- 550// GetProvider - Gets the provider object. [PROTECTED] 551//----------------------------------------------------------------------------- 552 553IOService * 554IOSCSIParallelInterfaceController::GetProvider ( void ) 555{ 556 return fProvider; 557} 558 559 560//----------------------------------------------------------------------------- 561// GetSCSIDomainIdentifier - Gets the domain identifier. [PROTECTED] 562//----------------------------------------------------------------------------- 563 564SInt32 565IOSCSIParallelInterfaceController::GetSCSIDomainIdentifier ( void ) 566{ 567 return fSCSIDomainIdentifier; 568} 569 570 571#if 0 572#pragma mark - 573#pragma mark Property Management 574#pragma mark - 575#endif 576 577 578//----------------------------------------------------------------------------- 579// SetHBAProperty - Sets a property for this object. [PUBLIC] 580//----------------------------------------------------------------------------- 581 582bool 583IOSCSIParallelInterfaceController::SetHBAProperty ( 584 const char * key, 585 OSObject * value ) 586{ 587 588 bool result = false; 589 OSDictionary * hbaDict = NULL; 590 OSDictionary * copyDict = NULL; 591 592 require_nonzero ( key, ErrorExit ); 593 require_nonzero ( value, ErrorExit ); 594 595 // We should be within a synchronized context (i.e. holding the workloop lock), 596 if ( fWorkLoop->inGate ( ) == false ) 597 { 598 599 // Let's make sure to grab the lock and call this routine again. 600 result = fControllerGate->runAction ( 601 OSMemberFunctionCast ( 602 IOCommandGate::Action, 603 this, 604 &IOSCSIParallelInterfaceController::SetHBAProperty ), 605 ( void * ) key, 606 ( void * ) value ); 607 608 goto ErrorExit; 609 610 } 611 612 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) ); 613 require_nonzero ( copyDict, ErrorExit ); 614 615 hbaDict = ( OSDictionary * ) copyDict->copyCollection ( ); 616 copyDict->release ( ); 617 618 require_nonzero ( hbaDict, ErrorExit ); 619 620 if ( strcmp ( key, kIOPropertyVendorNameKey ) == 0 ) 621 { 622 result = hbaDict->setObject ( key, value ); 623 } 624 625 else if ( strcmp ( key, kIOPropertyProductNameKey ) == 0 ) 626 { 627 result = hbaDict->setObject ( key, value ); 628 } 629 630 else if ( strcmp ( key, kIOPropertyProductRevisionLevelKey ) == 0 ) 631 { 632 result = hbaDict->setObject ( key, value ); 633 } 634 635 else if ( strcmp ( key, kIOPropertyPortDescriptionKey ) == 0 ) 636 { 637 result = hbaDict->setObject ( key, value ); 638 } 639 640 else if ( strcmp ( key, kIOPropertyPortSpeedKey ) == 0 ) 641 { 642 result = hbaDict->setObject ( key, value ); 643 } 644 645 else if ( strcmp ( key, kIOPropertySCSIParallelSignalingTypeKey ) == 0 ) 646 { 647 result = hbaDict->setObject ( key, value ); 648 } 649 650 else if ( strcmp ( key, kIOPropertyFibreChannelCableDescriptionKey ) == 0 ) 651 { 652 result = hbaDict->setObject ( key, value ); 653 } 654 655 else if ( strcmp ( key, kIOPropertyFibreChannelPortWorldWideNameKey ) == 0 ) 656 { 657 658 OSData * data = OSDynamicCast ( OSData, value ); 659 660 require_nonzero ( data, ErrorExit ); 661 require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit ); 662 result = hbaDict->setObject ( key, value ); 663 result = hbaDict->setObject ( kIOPropertySCSIPortIdentifierKey, value ); 664 665 } 666 667 else if ( strcmp ( key, kIOPropertyFibreChannelNodeWorldWideNameKey ) == 0 ) 668 { 669 670 OSData * data = OSDynamicCast ( OSData, value ); 671 672 require_nonzero ( data, ErrorExit ); 673 require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit ); 674 result = hbaDict->setObject ( key, value ); 675 676 } 677 678 else if ( strcmp ( key, kIOPropertyFibreChannelAddressIdentifierKey ) == 0 ) 679 { 680 681 OSData * data = OSDynamicCast ( OSData, value ); 682 683 require_nonzero ( data, ErrorExit ); 684 require ( ( data->getLength ( ) == kAddressIdentifierDataSize ), ErrorExit ); 685 result = hbaDict->setObject ( key, value ); 686 687 } 688 689 else if ( strcmp ( key, kIOPropertyFibreChannelALPAKey ) == 0 ) 690 { 691 692 OSData * data = OSDynamicCast ( OSData, value ); 693 694 require_nonzero ( data, ErrorExit ); 695 require ( ( data->getLength ( ) == kALPADataSize ), ErrorExit ); 696 result = hbaDict->setObject ( key, value ); 697 698 } 699 700 else if ( strcmp ( key, kIOPropertyPortTopologyKey ) == 0 ) 701 { 702 result = hbaDict->setObject ( key, value ); 703 } 704 705 else if ( strcmp ( key, kIOPropertySASAddressKey ) == 0 ) 706 { 707 708 OSData * data = OSDynamicCast ( OSData, value ); 709 710 require_nonzero ( data, ErrorExit ); 711 require ( ( data->getLength ( ) == kSASAddressDataSize ), ErrorExit ); 712 result = hbaDict->setObject ( key, value ); 713 result = hbaDict->setObject ( kIOPropertySCSIPortIdentifierKey, value ); 714 715 } 716 717 else 718 { 719 ERROR_LOG ( ( "SetHBAProperty: Unrecognized property key = %s", key ) ); 720 } 721 722 setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict ); 723 hbaDict->release ( ); 724 hbaDict = NULL; 725 726 messageClients ( kIOMessageServicePropertyChange ); 727 728 729ErrorExit: 730 731 732 return result; 733 734} 735 736 737//----------------------------------------------------------------------------- 738// RemoveHBAProperty - Removes a property for this object. [PUBLIC] 739//----------------------------------------------------------------------------- 740 741void 742IOSCSIParallelInterfaceController::RemoveHBAProperty ( const char * key ) 743{ 744 745 OSDictionary * hbaDict = NULL; 746 OSDictionary * copyDict = NULL; 747 748 require_nonzero ( key, ErrorExit ); 749 750 // We should be within a synchronized context (i.e. holding the workloop lock), 751 if ( fWorkLoop->inGate ( ) == false ) 752 { 753 754 // Let's make sure to grab the lock and call this routine again. 755 fControllerGate->runAction ( 756 OSMemberFunctionCast ( 757 IOCommandGate::Action, 758 this, 759 &IOSCSIParallelInterfaceController::RemoveHBAProperty ), 760 ( void * ) key ); 761 762 goto ErrorExit; 763 764 } 765 766 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) ); 767 require_nonzero ( copyDict, ErrorExit ); 768 769 hbaDict = ( OSDictionary * ) copyDict->copyCollection ( ); 770 copyDict->release ( ); 771 772 require_nonzero ( hbaDict, ErrorExit ); 773 774 if ( hbaDict->getObject ( key ) != NULL ) 775 { 776 777 hbaDict->removeObject ( key ); 778 779 } 780 781 setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict ); 782 hbaDict->release ( ); 783 hbaDict = NULL; 784 785 messageClients ( kIOMessageServicePropertyChange ); 786 787 788ErrorExit: 789 790 791 return; 792 793} 794 795 796#if 0 797#pragma mark - 798#pragma mark WorkLoop Management 799#pragma mark - 800#endif 801 802 803//----------------------------------------------------------------------------- 804// GetWorkLoop - Gets the workloop. [PROTECTED] 805//----------------------------------------------------------------------------- 806 807IOWorkLoop * 808IOSCSIParallelInterfaceController::GetWorkLoop ( void ) const 809{ 810 return fWorkLoop; 811} 812 813 814//----------------------------------------------------------------------------- 815// GetCommandGate - Gets the command gate. [PROTECTED] 816//----------------------------------------------------------------------------- 817 818IOCommandGate * 819IOSCSIParallelInterfaceController::GetCommandGate ( void ) 820{ 821 return fControllerGate; 822} 823 824 825//----------------------------------------------------------------------------- 826// CreateWorkLoop - Creates the workloop and associated objects. [PRIVATE] 827//----------------------------------------------------------------------------- 828 829bool 830IOSCSIParallelInterfaceController::CreateWorkLoop ( IOService * provider ) 831{ 832 833 bool result = false; 834 IOReturn status = kIOReturnSuccess; 835 char lockGroupName[64]; 836 837 bzero ( lockGroupName, sizeof ( lockGroupName ) ); 838 839 snprintf ( lockGroupName, 64, "SCSI Domain %d", ( int ) fSCSIDomainIdentifier ); 840 841 if ( fWorkLoop == NULL ) 842 { 843 844 fWorkLoop = SCSIParallelWorkLoop::Create ( lockGroupName ); 845 require_nonzero ( fWorkLoop, CREATE_WORKLOOP_FAILURE ); 846 847 } 848 849 // Create a timer. 850 fTimerEvent = SCSIParallelTimer::CreateTimerEventSource ( this, 851 ( IOTimerEventSource::Action ) &IOSCSIParallelInterfaceController::TimeoutOccurred ); 852 require_nonzero ( fTimerEvent, TIMER_CREATION_FAILURE ); 853 854 // Add the timer to the workloop. 855 status = fWorkLoop->addEventSource ( fTimerEvent ); 856 require_success ( status, ADD_TES_FAILURE ); 857 858 // Ask the subclass to create the device interrupt. 859 fDispatchEvent = CreateDeviceInterrupt ( 860 &IOSCSIParallelInterfaceController::ServiceInterrupt, 861 &IOSCSIParallelInterfaceController::FilterInterrupt, 862 provider ); 863 864 // Virtual HBAs or HBAs that want to handle interrupts differently might 865 // return NULL. We'll allow that, but they'll have to deal with things 866 // themselves. 867 if ( fDispatchEvent != NULL ) 868 { 869 870 // Add the interrupt event source to the workloop. 871 status = fWorkLoop->addEventSource ( fDispatchEvent ); 872 require_success ( status, ADD_ISR_EVENT_FAILURE ); 873 874 } 875 876 // Create a command gate. 877 fControllerGate = IOCommandGate::commandGate ( this, NULL ); 878 require_nonzero ( fControllerGate, ALLOCATE_COMMAND_GATE_FAILURE ); 879 880 // Add the command gate to the workloop. 881 status = fWorkLoop->addEventSource ( fControllerGate ); 882 require_success ( status, ADD_GATE_EVENT_FAILURE ); 883 884 result = true; 885 886 return result; 887 888 889ADD_GATE_EVENT_FAILURE: 890 891 892 require_nonzero_quiet ( fControllerGate, ALLOCATE_COMMAND_GATE_FAILURE ); 893 fControllerGate->release ( ); 894 fControllerGate = NULL; 895 896 897ALLOCATE_COMMAND_GATE_FAILURE: 898 899 900 if ( fDispatchEvent != NULL ) 901 { 902 fWorkLoop->removeEventSource ( fDispatchEvent ); 903 } 904 905 906ADD_ISR_EVENT_FAILURE: 907 908 909 if ( fDispatchEvent != NULL ) 910 { 911 912 fDispatchEvent->release ( ); 913 fDispatchEvent = NULL; 914 915 } 916 917 fWorkLoop->removeEventSource ( fTimerEvent ); 918 919 920ADD_TES_FAILURE: 921 922 923 require_nonzero_quiet ( fTimerEvent, TIMER_CREATION_FAILURE ); 924 fTimerEvent->release ( ); 925 fTimerEvent = NULL; 926 927 928TIMER_CREATION_FAILURE: 929 930 931 require_nonzero_quiet ( fWorkLoop, CREATE_WORKLOOP_FAILURE ); 932 fWorkLoop->release ( ); 933 fWorkLoop = NULL; 934 935 936CREATE_WORKLOOP_FAILURE: 937 938 939 return result; 940 941} 942 943 944//----------------------------------------------------------------------------- 945// ReleaseWorkLoop - Releases the workloop and associated objects. [PRIVATE] 946//----------------------------------------------------------------------------- 947 948void 949IOSCSIParallelInterfaceController::ReleaseWorkLoop ( void ) 950{ 951 952 // Make sure we have a workloop. 953 if ( fWorkLoop != NULL ) 954 { 955 956 // Remove all the event sources from the workloop 957 // and deallocate them. 958 959 if ( fControllerGate != NULL ) 960 { 961 962 fWorkLoop->removeEventSource ( fControllerGate ); 963 fControllerGate->release ( ); 964 fControllerGate = NULL; 965 966 } 967 968 if ( fTimerEvent != NULL ) 969 { 970 971 fWorkLoop->removeEventSource ( fTimerEvent ); 972 fTimerEvent->release ( ); 973 fTimerEvent = NULL; 974 975 } 976 977 if ( fDispatchEvent != NULL ) 978 { 979 980 fWorkLoop->removeEventSource ( fDispatchEvent ); 981 fDispatchEvent->release ( ); 982 fDispatchEvent = NULL; 983 984 } 985 986 fWorkLoop->release ( ); 987 fWorkLoop = NULL; 988 989 } 990 991} 992 993 994#if 0 995#pragma mark - 996#pragma mark SCSI Parallel Task Management 997#pragma mark - 998#endif 999 1000 1001//----------------------------------------------------------------------------- 1002// GetSCSIParallelTask - Gets a parallel task from the pool. [PUBLIC] 1003//----------------------------------------------------------------------------- 1004 1005SCSIParallelTaskIdentifier 1006IOSCSIParallelInterfaceController::GetSCSIParallelTask ( bool blockForCommand ) 1007{ 1008 1009 SCSIParallelTask * parallelTask = NULL; 1010 1011 parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( blockForCommand ); 1012 if ( parallelTask != NULL ) 1013 { 1014 parallelTask->ResetForNewTask ( ); 1015 } 1016 1017 return ( SCSIParallelTaskIdentifier ) parallelTask; 1018 1019} 1020 1021 1022//----------------------------------------------------------------------------- 1023// FreeSCSIParallelTask - Returns a parallel task to the pool. [PUBLIC] 1024//----------------------------------------------------------------------------- 1025 1026void 1027IOSCSIParallelInterfaceController::FreeSCSIParallelTask ( 1028 SCSIParallelTaskIdentifier returnTask ) 1029{ 1030 1031 SCSIParallelTask * parallelTask = NULL; 1032 IOReturn status = kIOReturnSuccess; 1033 1034 parallelTask = OSDynamicCast ( SCSIParallelTask, returnTask ); 1035 1036 require_nonzero ( parallelTask, ERROR_EXIT_NULL_TASK ); 1037 1038 parallelTask->SetSCSITaskIdentifier ( NULL ); 1039 1040 status = parallelTask->clearMemoryDescriptor ( false ); 1041 1042 if ( status != kIOReturnSuccess ) 1043 { 1044 1045 ERROR_LOG ( ( "FreeSCSIParallelTask: Task %p seems to be still active. " 1046 "IODMACommand::complete ( ) may not have been called for " 1047 "this task.", returnTask ) ); 1048 1049 } 1050 1051 fParallelTaskPool->returnCommand ( ( IOCommand * ) returnTask ); 1052 1053 return; 1054 1055 1056ERROR_EXIT_NULL_TASK: 1057 1058 1059 STATUS_LOG ( ( "FreeSCSIParallelTask: Encountered a NULL task pointer!\n" ) ); 1060 1061 return; 1062 1063} 1064 1065 1066//----------------------------------------------------------------------------- 1067// AllocateSCSIParallelTasks - Allocates parallel tasks for the pool. 1068// [PRIVATE] 1069//----------------------------------------------------------------------------- 1070 1071bool 1072IOSCSIParallelInterfaceController::AllocateSCSIParallelTasks ( void ) 1073{ 1074 1075 bool result = false; 1076 SCSIParallelTask * parallelTask = NULL; 1077 UInt32 taskSize = 0; 1078 UInt32 index = 0; 1079 UInt64 mask = 0; 1080 OSNumber * value = NULL; 1081 OSDictionary * constraints = NULL; 1082 OSObject * obj = NULL; 1083 1084 // Default alignment is 16-byte aligned, 32-bit memory only. 1085 taskSize = ReportHBASpecificTaskDataSize ( ); 1086 constraints = OSDictionary::withCapacity ( kHBAContraintsDictionaryEntryCount ); 1087 1088 require_nonzero ( constraints, ERROR_EXIT ); 1089 1090 ReportHBAConstraints ( constraints ); 1091 1092 // Set constraints for cluster layer / IOBlockStorageDriver. 1093 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentCountReadKey ) ); 1094 if ( value != NULL ) 1095 { 1096 setProperty ( kIOMaximumSegmentCountReadKey, value ); 1097 } 1098 1099 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentCountWriteKey ) ); 1100 if ( value != NULL ) 1101 { 1102 setProperty ( kIOMaximumSegmentCountWriteKey, value ); 1103 } 1104 1105 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentByteCountReadKey ) ); 1106 if ( value != NULL ) 1107 { 1108 setProperty ( kIOMaximumSegmentByteCountReadKey, value ); 1109 } 1110 1111 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentByteCountWriteKey ) ); 1112 if ( value != NULL ) 1113 { 1114 setProperty ( kIOMaximumSegmentByteCountWriteKey, value ); 1115 } 1116 1117 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMinimumSegmentAlignmentByteCountKey ) ); 1118 if ( value != NULL ) 1119 { 1120 setProperty ( kIOMinimumSegmentAlignmentByteCountKey, value ); 1121 } 1122 1123 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMaximumSegmentAddressableBitCountKey ) ); 1124 if ( value != NULL ) 1125 { 1126 setProperty ( kIOMaximumSegmentAddressableBitCountKey, value ); 1127 } 1128 1129 value = OSDynamicCast ( OSNumber, constraints->getObject ( kIOMinimumHBADataAlignmentMaskKey ) ); 1130 mask = value->unsigned64BitValue ( ); 1131 1132 obj = constraints->getObject ( kIOHierarchicalLogicalUnitSupportKey ); 1133 if ( obj != NULL ) 1134 { 1135 setProperty ( kIOHierarchicalLogicalUnitSupportKey, obj ); 1136 } 1137 1138 constraints->release ( ); 1139 constraints = NULL; 1140 1141 fParallelTaskPool = IOCommandPool::withWorkLoop ( fWorkLoop ); 1142 require_nonzero ( fParallelTaskPool, POOL_CREATION_FAILURE ); 1143 1144 // As long as a single SCSI Parallel Task can be allocated, the HBA 1145 // can function. Check to see if the first one can be allocated. 1146 parallelTask = SCSIParallelTask::Create ( taskSize, mask ); 1147 require_nonzero ( parallelTask, TASK_CREATION_FAILURE ); 1148 1149 result = InitializeDMASpecification ( parallelTask ); 1150 require ( result, TASK_INIT_FAILURE ); 1151 1152 // Send the single command into the pool. 1153 fParallelTaskPool->returnCommand ( parallelTask ); 1154 1155 // Now try to allocate the remaining Tasks that the HBA reports that it 1156 // can support. 1157 for ( index = 1; index < fSupportedTaskCount; index++ ) 1158 { 1159 1160 // Allocate the command with enough space for the HBA specific data 1161 parallelTask = SCSIParallelTask::Create ( taskSize, mask ); 1162 if ( parallelTask != NULL ) 1163 { 1164 1165 result = InitializeDMASpecification ( parallelTask ); 1166 if ( result == false ) 1167 { 1168 1169 parallelTask->release ( ); 1170 break; 1171 1172 } 1173 1174 // Send the next command into the pool. 1175 fParallelTaskPool->returnCommand ( parallelTask ); 1176 1177 } 1178 1179 } 1180 1181 // Did the subclass override the command pool size? 1182 value = OSDynamicCast ( OSNumber, getProperty ( kIOCommandPoolSizeKey ) ); 1183 if ( value == NULL ) 1184 { 1185 1186 // No, set the default to be the number of commands we allocated. 1187 setProperty ( kIOCommandPoolSizeKey, index, 32 ); 1188 1189 } 1190 1191 // Since at least a single SCSI Parallel Task was allocated, this 1192 // HBA can function. 1193 result = true; 1194 1195 return result; 1196 1197 1198TASK_INIT_FAILURE: 1199 1200 1201 require_nonzero ( parallelTask, TASK_CREATION_FAILURE ); 1202 parallelTask->release ( ); 1203 parallelTask = NULL; 1204 1205 1206TASK_CREATION_FAILURE: 1207 1208 1209 require_nonzero ( fParallelTaskPool, POOL_CREATION_FAILURE ); 1210 fParallelTaskPool->release ( ); 1211 fParallelTaskPool = NULL; 1212 1213 1214POOL_CREATION_FAILURE: 1215ERROR_EXIT: 1216 1217 1218 return result; 1219 1220} 1221 1222 1223//----------------------------------------------------------------------------- 1224// DeallocateSCSIParallelTasks - Deallocates parallel tasks in the pool. 1225// [PRIVATE] 1226//----------------------------------------------------------------------------- 1227 1228void 1229IOSCSIParallelInterfaceController::DeallocateSCSIParallelTasks ( void ) 1230{ 1231 1232 SCSIParallelTask * parallelTask = NULL; 1233 1234 require_nonzero ( fParallelTaskPool, Exit ); 1235 1236 parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( false ); 1237 while ( parallelTask != NULL ) 1238 { 1239 1240 parallelTask->release ( ); 1241 parallelTask = ( SCSIParallelTask * ) fParallelTaskPool->getCommand ( false ); 1242 1243 } 1244 1245 fParallelTaskPool->release ( ); 1246 fParallelTaskPool = NULL; 1247 1248 1249Exit: 1250 1251 1252 return; 1253 1254} 1255 1256 1257#if 0 1258#pragma mark - 1259#pragma mark SCSI Parallel Task Execution 1260#pragma mark - 1261#endif 1262 1263 1264//----------------------------------------------------------------------------- 1265// ExecuteParallelTask - Executes a parallel task. [PUBLIC] 1266//----------------------------------------------------------------------------- 1267 1268SCSIServiceResponse 1269IOSCSIParallelInterfaceController::ExecuteParallelTask ( 1270 SCSIParallelTaskIdentifier parallelRequest ) 1271{ 1272 1273 SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1274 1275 // If the controller has requested a suspend, 1276 // return the command and let it add it back to the queue. 1277 if ( fHBACanAcceptClientRequests == true ) 1278 { 1279 1280 // If the controller has not suspended, send the task now. 1281 serviceResponse = ProcessParallelTask ( parallelRequest ); 1282 1283 } 1284 1285 return serviceResponse; 1286 1287} 1288 1289 1290//----------------------------------------------------------------------------- 1291// CompleteParallelTask - Completes a parallel task. [PROTECTED] 1292//----------------------------------------------------------------------------- 1293 1294void 1295IOSCSIParallelInterfaceController::CompleteParallelTask ( 1296 SCSIParallelTaskIdentifier parallelRequest, 1297 SCSITaskStatus completionStatus, 1298 SCSIServiceResponse serviceResponse ) 1299{ 1300 1301 IOSCSIParallelInterfaceDevice * target = NULL; 1302 1303 STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::CompleteParallelTask\n" ) ); 1304 1305 // We should be within a synchronized context (i.e. holding the workloop lock), 1306 // but some subclassers aren't so bright. <sigh> 1307 if ( fWorkLoop->inGate ( ) == false ) 1308 { 1309 1310 // Let's make sure to grab the lock and call this routine again. 1311 fControllerGate->runAction ( 1312 OSMemberFunctionCast ( 1313 IOCommandGate::Action, 1314 this, 1315 &IOSCSIParallelInterfaceController::CompleteParallelTask ), 1316 parallelRequest, 1317 ( void * ) completionStatus, 1318 ( void * ) serviceResponse ); 1319 1320 goto Exit; 1321 1322 } 1323 1324 // Remove the task from the timeout list. 1325 ( ( SCSIParallelTimer * ) fTimerEvent )->RemoveTask ( parallelRequest ); 1326 1327 target = GetDevice ( parallelRequest ); 1328 require_nonzero ( target, Exit ); 1329 1330 // Complete the command 1331 target->CompleteSCSITask ( parallelRequest, 1332 serviceResponse, 1333 completionStatus ); 1334 1335 1336Exit: 1337 1338 1339 STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::CompleteParallelTask\n" ) ); 1340 return; 1341 1342} 1343 1344 1345//----------------------------------------------------------------------------- 1346// FindTaskForAddress - Finds a task by its address (ITLQ nexus) [PUBLIC] 1347//----------------------------------------------------------------------------- 1348 1349SCSIParallelTaskIdentifier 1350IOSCSIParallelInterfaceController::FindTaskForAddress ( 1351 SCSIDeviceIdentifier theT, 1352 SCSILogicalUnitNumber theL, 1353 SCSITaggedTaskIdentifier theQ ) 1354{ 1355 1356 SCSIParallelTaskIdentifier task = NULL; 1357 IOSCSIParallelInterfaceDevice * target = NULL; 1358 1359 target = GetTargetForID ( theT ); 1360 require_nonzero ( target, Exit ); 1361 1362 // A valid object exists for the target ID, request that it find 1363 // the task on its outstanding queue. 1364 task = target->FindTaskForAddress ( theL, theQ ); 1365 1366 1367Exit: 1368 1369 1370 return task; 1371 1372} 1373 1374 1375//----------------------------------------------------------------------------- 1376// FindTaskForControllerIdentifier - Finds a task by its unique ID [PUBLIC] 1377//----------------------------------------------------------------------------- 1378 1379SCSIParallelTaskIdentifier 1380IOSCSIParallelInterfaceController::FindTaskForControllerIdentifier ( 1381 SCSIDeviceIdentifier theTarget, 1382 UInt64 theIdentifier ) 1383{ 1384 1385 SCSIParallelTaskIdentifier task = NULL; 1386 IOSCSIParallelInterfaceDevice * target = NULL; 1387 1388 target = GetTargetForID ( theTarget ); 1389 require_nonzero ( target, Exit ); 1390 1391 // A valid object exists for the target ID, request that it find 1392 // the task on its outstanding queue. 1393 task = target->FindTaskForControllerIdentifier ( theIdentifier ); 1394 1395 1396Exit: 1397 1398 1399 return task; 1400 1401} 1402 1403// The completion callback for the SAM-2 Task Management functions. 1404// The implementation for these will be added when the support for these 1405// are added in the SCSI Parallel Interface Device object 1406 1407//----------------------------------------------------------------------------- 1408// CompleteAbortTask - Completes the AbortTaskRequest. [PROTECTED] 1409//----------------------------------------------------------------------------- 1410 1411void 1412IOSCSIParallelInterfaceController::CompleteAbortTask ( 1413 SCSITargetIdentifier theT, 1414 SCSILogicalUnitNumber theL, 1415 SCSITaggedTaskIdentifier theQ, 1416 SCSIServiceResponse serviceResponse ) 1417{ 1418} 1419 1420 1421//----------------------------------------------------------------------------- 1422// CompleteAbortTaskSet - Completes the AbortTaskSetRequest. [PROTECTED] 1423//----------------------------------------------------------------------------- 1424 1425void 1426IOSCSIParallelInterfaceController::CompleteAbortTaskSet ( 1427 SCSITargetIdentifier theT, 1428 SCSILogicalUnitNumber theL, 1429 SCSIServiceResponse serviceResponse ) 1430{ 1431} 1432 1433 1434//----------------------------------------------------------------------------- 1435// CompleteClearACA - Completes the ClearACARequest. [PROTECTED] 1436//----------------------------------------------------------------------------- 1437 1438void 1439IOSCSIParallelInterfaceController::CompleteClearACA ( 1440 SCSITargetIdentifier theT, 1441 SCSILogicalUnitNumber theL, 1442 SCSIServiceResponse serviceResponse ) 1443{ 1444} 1445 1446 1447//----------------------------------------------------------------------------- 1448// CompleteClearTaskSet - Completes the ClearTaskSetRequest. [PROTECTED] 1449//----------------------------------------------------------------------------- 1450 1451void 1452IOSCSIParallelInterfaceController::CompleteClearTaskSet ( 1453 SCSITargetIdentifier theT, 1454 SCSILogicalUnitNumber theL, 1455 SCSIServiceResponse serviceResponse ) 1456{ 1457} 1458 1459 1460//----------------------------------------------------------------------------- 1461// CompleteLogicalUnitReset - Completes the LogicalUnitResetRequest. 1462// [PROTECTED] 1463//----------------------------------------------------------------------------- 1464 1465void 1466IOSCSIParallelInterfaceController::CompleteLogicalUnitReset ( 1467 SCSITargetIdentifier theT, 1468 SCSILogicalUnitNumber theL, 1469 SCSIServiceResponse serviceResponse ) 1470{ 1471} 1472 1473 1474//----------------------------------------------------------------------------- 1475// CompleteTargetReset - Completes the TargetResetRequest [PROTECTED] 1476//----------------------------------------------------------------------------- 1477 1478void 1479IOSCSIParallelInterfaceController::CompleteTargetReset ( 1480 SCSITargetIdentifier theT, 1481 SCSIServiceResponse serviceResponse ) 1482{ 1483} 1484 1485 1486//----------------------------------------------------------------------------- 1487// ServiceInterrupt - Calls the registered interrupt handler. [PRIVATE] 1488//----------------------------------------------------------------------------- 1489 1490void 1491IOSCSIParallelInterfaceController::ServiceInterrupt ( 1492 OSObject * theObject, 1493 IOInterruptEventSource * theSource, 1494 int count ) 1495{ 1496 ( ( IOSCSIParallelInterfaceController * ) theObject )->HandleInterruptRequest ( ); 1497} 1498 1499 1500//----------------------------------------------------------------------------- 1501// FilterInterrupt - Calls the registered interrupt filter. [PRIVATE] 1502//----------------------------------------------------------------------------- 1503 1504bool 1505IOSCSIParallelInterfaceController::FilterInterrupt ( 1506 OSObject * theObject, 1507 IOFilterInterruptEventSource * theSource ) 1508{ 1509 return ( ( IOSCSIParallelInterfaceController * ) theObject )->FilterInterruptRequest ( ); 1510} 1511 1512 1513//----------------------------------------------------------------------------- 1514// FilterInterruptRequest - Default filter routine. [PROTECTED] 1515//----------------------------------------------------------------------------- 1516 1517bool 1518IOSCSIParallelInterfaceController::FilterInterruptRequest ( void ) 1519{ 1520 return true; 1521} 1522 1523 1524//----------------------------------------------------------------------------- 1525// EnableInterrupt - Enables the interrupt event source. [PROTECTED] 1526//----------------------------------------------------------------------------- 1527 1528void 1529IOSCSIParallelInterfaceController::EnableInterrupt ( void ) 1530{ 1531 1532 if ( fDispatchEvent != NULL ) 1533 { 1534 fDispatchEvent->enable ( ); 1535 } 1536 1537} 1538 1539 1540//----------------------------------------------------------------------------- 1541// DisableInterrupt - Disables the interrupt event source. [PROTECTED] 1542//----------------------------------------------------------------------------- 1543 1544void 1545IOSCSIParallelInterfaceController::DisableInterrupt ( void ) 1546{ 1547 1548 if ( fDispatchEvent != NULL ) 1549 { 1550 fDispatchEvent->disable ( ); 1551 } 1552 1553} 1554 1555 1556//----------------------------------------------------------------------------- 1557// SignalInterrupt - Cause the work loop to schedule the interrupt action 1558// even if the filter routine returns false. [PROTECTED] 1559//----------------------------------------------------------------------------- 1560 1561void 1562IOSCSIParallelInterfaceController::SignalInterrupt ( void ) 1563{ 1564 1565 if ( fDispatchEvent != NULL ) 1566 { 1567 ( ( IOFilterInterruptEventSource * ) fDispatchEvent )->signalInterrupt ( ); 1568 } 1569 1570} 1571 1572 1573#if 0 1574#pragma mark - 1575#pragma mark Timeout Management 1576#pragma mark - 1577#endif 1578 1579 1580//----------------------------------------------------------------------------- 1581// SetTimeoutForTask - Sets the timeout. [PROTECTED] 1582//----------------------------------------------------------------------------- 1583 1584void 1585IOSCSIParallelInterfaceController::SetTimeoutForTask ( 1586 SCSIParallelTaskIdentifier parallelTask, 1587 UInt32 timeoutOverride ) 1588{ 1589 1590 ( ( SCSIParallelTimer * ) fTimerEvent )->SetTimeout ( parallelTask, 1591 timeoutOverride ); 1592 1593} 1594 1595 1596//----------------------------------------------------------------------------- 1597// TimeoutOccurred - Calls the timeout handler. [PRIVATE] 1598//----------------------------------------------------------------------------- 1599 1600void 1601IOSCSIParallelInterfaceController::TimeoutOccurred ( 1602 OSObject * theObject, 1603 IOTimerEventSource * theSender ) 1604{ 1605 1606 SCSIParallelTimer * timer = NULL; 1607 SCSIParallelTaskIdentifier expiredTask = NULL; 1608 1609 timer = OSDynamicCast ( SCSIParallelTimer, theSender ); 1610 if ( timer != NULL ) 1611 { 1612 1613 timer->BeginTimeoutContext ( ); 1614 1615 expiredTask = timer->GetExpiredTask ( ); 1616 while ( expiredTask != NULL ) 1617 { 1618 1619 ( ( IOSCSIParallelInterfaceController * ) theObject )->HandleTimeout ( expiredTask ); 1620 expiredTask = timer->GetExpiredTask ( ); 1621 1622 } 1623 1624 timer->EndTimeoutContext ( ); 1625 1626 // Rearm the timer 1627 timer->Rearm ( ); 1628 1629 } 1630 1631} 1632 1633 1634//----------------------------------------------------------------------------- 1635// HandleTimeout - Generic timeout handler. Subclasses should override. 1636// [PROTECTED] 1637//----------------------------------------------------------------------------- 1638 1639void 1640IOSCSIParallelInterfaceController::HandleTimeout ( 1641 SCSIParallelTaskIdentifier parallelRequest ) 1642{ 1643 1644 check ( parallelRequest != NULL ); 1645 CompleteParallelTask ( parallelRequest, 1646 kSCSITaskStatus_TaskTimeoutOccurred, 1647 kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE ); 1648 1649} 1650 1651 1652#if 0 1653#pragma mark - 1654#pragma mark SCSI Parallel Device Management 1655#pragma mark - 1656#endif 1657 1658 1659//----------------------------------------------------------------------------- 1660// CreateTargetForID - Creates a target device for the ID specified. 1661// [PROTECTED] 1662//----------------------------------------------------------------------------- 1663 1664bool 1665IOSCSIParallelInterfaceController::CreateTargetForID ( 1666 SCSITargetIdentifier targetID ) 1667{ 1668 1669 OSDictionary * dict = NULL; 1670 bool result = false; 1671 1672 dict = OSDictionary::withCapacity ( 0 ); 1673 require_nonzero ( dict, DICT_CREATION_FAILED ); 1674 1675 result = CreateTargetForID ( targetID, dict ); 1676 1677 dict->release ( ); 1678 dict = NULL; 1679 1680 1681DICT_CREATION_FAILED: 1682 1683 1684 return result; 1685 1686} 1687 1688 1689//----------------------------------------------------------------------------- 1690// CreateTargetForID - Creates a target device for the ID specified. 1691// [PROTECTED] 1692//----------------------------------------------------------------------------- 1693 1694bool 1695IOSCSIParallelInterfaceController::CreateTargetForID ( 1696 SCSITargetIdentifier targetID, 1697 OSDictionary * properties ) 1698{ 1699 1700 IOSCSIParallelInterfaceDevice * newDevice = NULL; 1701 IORegistryEntry * entry = NULL; 1702 bool result = false; 1703 1704 // Some subclasses like to create targets from within the StartController() override. 1705 // In those cases, fHBACanAcceptClientRequests is still false. We force it to true 1706 // in this case since a target is getting created - the HBA must be ready for I/O 1707 // by that time... 1708 if ( fHBACanAcceptClientRequests == false ) 1709 fHBACanAcceptClientRequests = true; 1710 1711 // Verify that the device ID is not that of the initiator. 1712 require ( ( targetID != fInitiatorIdentifier ), INVALID_PARAMETER_EXIT ); 1713 1714 // First check to see if this device already exists 1715 require ( ( GetTargetForID ( targetID ) == NULL ), INVALID_PARAMETER_EXIT ); 1716 1717 // See if the controller has a device tree entry it wants us to hook this 1718 // target upto (e.g. to get io-device-location keys). 1719 entry = OSDynamicCast ( IORegistryEntry, properties->getObject ( kIOPropertyDeviceTreeEntryKey ) ); 1720 1721 // Create the IOSCSIParallelInterfaceDevice object 1722 newDevice = IOSCSIParallelInterfaceDevice::CreateTarget ( 1723 targetID, 1724 ReportHBASpecificDeviceDataSize ( ), 1725 entry ); 1726 require_nonzero ( newDevice, DEVICE_CREATION_FAILED_EXIT ); 1727 1728 AddDeviceToTargetList ( newDevice ); 1729 1730 result = newDevice->attach ( this ); 1731 require ( result, ATTACH_FAILED_EXIT ); 1732 1733 result = newDevice->SetInitialTargetProperties ( properties ); 1734 require ( result, START_FAILED_EXIT ); 1735 1736 result = newDevice->start ( this ); 1737 require ( result, START_FAILED_EXIT ); 1738 1739 newDevice->release ( ); 1740 1741 // The SCSI Device was successfully created. 1742 result = true; 1743 1744 return result; 1745 1746 1747START_FAILED_EXIT: 1748 1749 1750 // Detach the target device 1751 newDevice->detach ( this ); 1752 1753 1754ATTACH_FAILED_EXIT: 1755 1756 1757 RemoveDeviceFromTargetList ( newDevice ); 1758 1759 // The device can now be destroyed. 1760 newDevice->DestroyTarget ( ); 1761 1762 1763DEVICE_CREATION_FAILED_EXIT: 1764INVALID_PARAMETER_EXIT: 1765 1766 1767 return result; 1768 1769} 1770 1771 1772//----------------------------------------------------------------------------- 1773// DestroyTargetForID - Destroys a target device for the ID specified. 1774// [PROTECTED] 1775//----------------------------------------------------------------------------- 1776 1777void 1778IOSCSIParallelInterfaceController::DestroyTargetForID ( 1779 SCSITargetIdentifier targetID ) 1780{ 1781 1782 IOSCSIParallelInterfaceDevice * victimDevice = NULL; 1783 1784 victimDevice = GetTargetForID ( targetID ); 1785 if ( victimDevice == NULL ) 1786 { 1787 1788 // There is no object for this target in the device list, 1789 // so return without doing anything. 1790 return; 1791 1792 } 1793 1794 // Remove the IOSCSIParallelInterfaceDevice from the device list. 1795 RemoveDeviceFromTargetList ( victimDevice ); 1796 1797 // The device can now be destroyed. 1798 victimDevice->DestroyTarget ( ); 1799 victimDevice->terminate ( ); 1800 1801} 1802 1803 1804//----------------------------------------------------------------------------- 1805// SetTargetProperty - Sets a property for the specified target. [PROTECTED] 1806//----------------------------------------------------------------------------- 1807 1808bool 1809IOSCSIParallelInterfaceController::SetTargetProperty ( 1810 SCSIDeviceIdentifier targetID, 1811 const char * key, 1812 OSObject * value ) 1813{ 1814 1815 bool result = false; 1816 IOSCSIParallelInterfaceDevice * device = NULL; 1817 1818 device = GetTargetForID ( targetID ); 1819 1820 require_nonzero ( device, ErrorExit ); 1821 result = device->SetTargetProperty ( key, value ); 1822 1823 1824ErrorExit: 1825 1826 1827 return result; 1828 1829} 1830 1831 1832//----------------------------------------------------------------------------- 1833// RemoveTargetProperty - Removes a property from the specified target. 1834// [PROTECTED] 1835//----------------------------------------------------------------------------- 1836 1837void 1838IOSCSIParallelInterfaceController::RemoveTargetProperty ( 1839 SCSIDeviceIdentifier targetID, 1840 const char * key ) 1841{ 1842 1843 IOSCSIParallelInterfaceDevice * device = NULL; 1844 1845 device = GetTargetForID ( targetID ); 1846 1847 require_nonzero ( device, ErrorExit ); 1848 device->RemoveTargetProperty ( key ); 1849 1850 1851ErrorExit: 1852 1853 1854 return; 1855 1856} 1857 1858 1859#if 0 1860#pragma mark - 1861#pragma mark Device List Management 1862#pragma mark - 1863#endif 1864 1865/* 1866 * The following member routines are used to manage the array of linked lists, the Device 1867 * List, that allow quick access to the SCSI Parallel Device objects. These routines 1868 * have intricate knowledge about the layout of the Device List since they are responsible 1869 * for managing it and so they are the only ones that are allowed to directly access that 1870 * structure. Any other routine that needs to retrieve an element from the Device List 1871 * must use these routines to obtain it so that if necessity causes to the Device List 1872 * structure to change, they are not broken. 1873 */ 1874 1875 1876//----------------------------------------------------------------------------- 1877// InitializeDeviceList - Initializes device list. [PRIVATE] 1878//----------------------------------------------------------------------------- 1879 1880void 1881IOSCSIParallelInterfaceController::InitializeDeviceList ( void ) 1882{ 1883 1884 // Initialize the SCSI Parallel Device Array to all NULL pointers 1885 for ( UInt32 i = 0; i < kSCSIParallelDeviceListArrayCount; i++ ) 1886 { 1887 fParallelDeviceList[i] = NULL; 1888 } 1889 1890} 1891 1892 1893//----------------------------------------------------------------------------- 1894// GetTargetForID - Gets the device object for the specified targetID. 1895// [PROTECTED] 1896//----------------------------------------------------------------------------- 1897 1898IOSCSIParallelInterfaceDevice * 1899IOSCSIParallelInterfaceController::GetTargetForID ( SCSITargetIdentifier targetID ) 1900{ 1901 1902 IOSCSIParallelInterfaceDevice * device = NULL; 1903 IOInterruptState lockState = 0; 1904 UInt8 indexID = 0; 1905 1906 require ( ( targetID >= 0 ), INVALID_PARAMETER_FAILURE ); 1907 require ( ( targetID <= fHighestSupportedDeviceID ), INVALID_PARAMETER_FAILURE ); 1908 require ( ( targetID != fInitiatorIdentifier ), INVALID_PARAMETER_FAILURE ); 1909 1910 lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock ); 1911 1912 // Hash the index. 1913 indexID = targetID & kSCSIParallelDeviceListIndexMask; 1914 1915 // Walk the list for the indexID 1916 device = fParallelDeviceList[indexID]; 1917 1918 while ( device != NULL ) 1919 { 1920 1921 if ( device->GetTargetIdentifier ( ) == targetID ) 1922 { 1923 1924 // This is the device in which the client is interested, break 1925 // so that the current pointer will be returned. 1926 break; 1927 1928 } 1929 1930 // Get the next element in the list 1931 device = device->GetNextDeviceInList ( ); 1932 1933 } 1934 1935 IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState ); 1936 1937 1938INVALID_PARAMETER_FAILURE: 1939 1940 1941 return device; 1942 1943} 1944 1945 1946//----------------------------------------------------------------------------- 1947// AddDeviceToTargetList - Adds a device to the target list. [PRIVATE] 1948//----------------------------------------------------------------------------- 1949 1950void 1951IOSCSIParallelInterfaceController::AddDeviceToTargetList ( 1952 IOSCSIParallelInterfaceDevice * newDevice ) 1953{ 1954 1955 UInt8 indexID = 0; 1956 IOInterruptState lockState = 0; 1957 1958 STATUS_LOG ( ( "+IOSCSIParallelInterfaceController::AddDeviceToTargetList\n" ) ); 1959 1960 lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock ); 1961 1962 // Hash the index. 1963 indexID = newDevice->GetTargetIdentifier ( ) & kSCSIParallelDeviceListIndexMask; 1964 1965 // Set the pointer in the SCSI Device array 1966 if ( fParallelDeviceList[indexID] == NULL ) 1967 { 1968 1969 // This is the first device object created for this 1970 // index, set the array pointer to the new object. 1971 fParallelDeviceList[indexID] = newDevice; 1972 newDevice->SetNextDeviceInList ( NULL ); 1973 newDevice->SetPreviousDeviceInList ( NULL ); 1974 1975 } 1976 1977 else 1978 { 1979 1980 // This is not the first device object for this index, 1981 // walk the list at this index and add it to the end. 1982 IOSCSIParallelInterfaceDevice * currentDevice; 1983 1984 currentDevice = fParallelDeviceList[indexID]; 1985 while ( currentDevice->GetNextDeviceInList ( ) != NULL ) 1986 { 1987 currentDevice = currentDevice->GetNextDeviceInList ( ); 1988 } 1989 1990 currentDevice->SetNextDeviceInList ( newDevice ); 1991 newDevice->SetNextDeviceInList ( NULL ); 1992 newDevice->SetPreviousDeviceInList ( currentDevice ); 1993 1994 } 1995 1996 IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState ); 1997 1998 STATUS_LOG ( ( "-IOSCSIParallelInterfaceController::AddDeviceToTargetList\n" ) ); 1999 2000} 2001 2002 2003//----------------------------------------------------------------------------- 2004// RemoveDeviceFromTargetList - Removes a device from the target list. 2005// [PRIVATE] 2006//----------------------------------------------------------------------------- 2007 2008void 2009IOSCSIParallelInterfaceController::RemoveDeviceFromTargetList ( 2010 IOSCSIParallelInterfaceDevice * victimDevice ) 2011{ 2012 2013 IOSCSIParallelInterfaceDevice * nextDevice = NULL; 2014 IOSCSIParallelInterfaceDevice * prevDevice = NULL; 2015 IOInterruptState lockState = 0; 2016 2017 lockState = IOSimpleLockLockDisableInterrupt ( fDeviceLock ); 2018 2019 nextDevice = victimDevice->GetNextDeviceInList ( ); 2020 prevDevice = victimDevice->GetPreviousDeviceInList ( ); 2021 2022 if ( prevDevice != NULL ) 2023 { 2024 2025 // There is a previous device, set it to the victim's next device 2026 prevDevice->SetNextDeviceInList ( nextDevice ); 2027 2028 } 2029 2030 else 2031 { 2032 2033 // There is not a previous device, set the pointer in the array 2034 // to the victim's next device. 2035 UInt8 indexID = 0; 2036 2037 // Hash the index. 2038 indexID = victimDevice->GetTargetIdentifier ( ) & kSCSIParallelDeviceListIndexMask; 2039 2040 // Set the Device List element to point at the device object that was following 2041 // the device object that is being removed. If there was no next device, 2042 // the nextDevice pointer will be NULL causing the Device List no longer have 2043 // any devices at this index. 2044 fParallelDeviceList[indexID] = nextDevice; 2045 2046 } 2047 2048 if ( nextDevice != NULL ) 2049 { 2050 2051 // The next device is not NULL, set it to the victim's previous 2052 nextDevice->SetPreviousDeviceInList ( prevDevice ); 2053 2054 } 2055 2056 // Clear out the victim's previous and next pointers 2057 victimDevice->SetNextDeviceInList ( NULL ); 2058 victimDevice->SetPreviousDeviceInList ( NULL ); 2059 2060 IOSimpleLockUnlockEnableInterrupt ( fDeviceLock, lockState ); 2061 2062} 2063 2064 2065#if 0 2066#pragma mark - 2067#pragma mark Controller Child Class 2068#pragma mark - 2069#endif 2070 2071 2072//----------------------------------------------------------------------------- 2073// DoesHBAPerformAutoSense - Default implementation. [PUBLIC] 2074//----------------------------------------------------------------------------- 2075 2076bool 2077IOSCSIParallelInterfaceController::DoesHBAPerformAutoSense ( void ) 2078{ 2079 return false; 2080} 2081 2082 2083//----------------------------------------------------------------------------- 2084// DoesHBASupportMultiPathing - Default implementation. [PUBLIC] 2085//----------------------------------------------------------------------------- 2086 2087bool 2088IOSCSIParallelInterfaceController::DoesHBASupportMultiPathing ( void ) 2089{ 2090 2091 OSString * interface = NULL; 2092 OSDictionary * dict = NULL; 2093 bool result = true; 2094 2095 2096 // Get Protocol Characteristics. 2097 dict = OSDynamicCast ( OSDictionary, getProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 2098 2099 if ( dict != NULL ) 2100 { 2101 2102 interface = OSDynamicCast ( OSString, dict->getObject ( kIOPropertyPhysicalInterconnectTypeKey ) ); 2103 2104 if ( interface != NULL ) 2105 { 2106 2107 if ( ( interface->isEqualTo ( kIOPropertyPhysicalInterconnectTypeSCSIParallel ) ) || 2108 ( interface->isEqualTo ( kIOPropertyPhysicalInterconnectTypeSerialAttachedSCSI ) ) ) 2109 { 2110 2111 // No Multipathing for parallel SCSI and SAS by default. 2112 result = false; 2113 2114 } 2115 2116 } 2117 2118 } 2119 2120 return result; 2121} 2122 2123 2124//----------------------------------------------------------------------------- 2125// ReportHBAConstraints - Default implementation. [PUBLIC] 2126//----------------------------------------------------------------------------- 2127 2128void 2129IOSCSIParallelInterfaceController::ReportHBAConstraints ( 2130 OSDictionary * constraints ) 2131{ 2132 2133 UInt64 value = 0; 2134 OSNumber * number = NULL; 2135 2136 // Default alignment is 16-byte aligned, 32-bit memory only. 2137 value = 0x00000000FFFFFFF0ULL; 2138 2139 number = OSNumber::withNumber ( value, 64 ); 2140 if ( number != NULL ) 2141 { 2142 2143 constraints->setObject ( kIOMinimumHBADataAlignmentMaskKey, number ); 2144 number->release ( ); 2145 2146 } 2147 2148 // 32-bit addressing by default. 2149 value = 32; 2150 number = OSNumber::withNumber ( value, 64 ); 2151 if ( number != NULL ) 2152 { 2153 2154 constraints->setObject ( kIOMaximumSegmentAddressableBitCountKey, number ); 2155 number->release ( ); 2156 2157 } 2158 2159 // 4-byte alignment by default. 2160 value = 4; 2161 number = OSNumber::withNumber ( value, 64 ); 2162 if ( number != NULL ) 2163 { 2164 2165 constraints->setObject ( kIOMinimumSegmentAlignmentByteCountKey, number ); 2166 number->release ( ); 2167 2168 } 2169 2170} 2171 2172 2173//----------------------------------------------------------------------------- 2174// InitializeDMASpecification - Default implementation. [PROTECTED] 2175//----------------------------------------------------------------------------- 2176 2177bool 2178IOSCSIParallelInterfaceController::InitializeDMASpecification ( 2179 IODMACommand * command ) 2180{ 2181 2182 bool result = false; 2183 2184 result = command->initWithSpecification ( 2185 kIODMACommandOutputHost32, 2186 32, // addressBits 2187 4096, // PAGE_SIZE 2188 IODMACommand::kMapped, 2189 1048576, // 1MB I/O 2190 4 // 4-byte aligned segments 2191 ); 2192 2193 return result; 2194 2195} 2196 2197 2198//----------------------------------------------------------------------------- 2199// CreateDeviceInterrupt - Default implementation. [PROTECTED] 2200//----------------------------------------------------------------------------- 2201 2202IOInterruptEventSource * 2203IOSCSIParallelInterfaceController::CreateDeviceInterrupt ( 2204 IOInterruptEventSource::Action action, 2205 IOFilterInterruptEventSource::Filter filter, 2206 IOService * provider ) 2207{ 2208 2209 IOInterruptEventSource * ies = NULL; 2210 2211 ies = IOFilterInterruptEventSource::filterInterruptEventSource ( 2212 this, 2213 action, 2214 filter, 2215 provider, 2216 0 ); 2217 2218 check ( ies != NULL ); 2219 2220 return ies; 2221 2222} 2223 2224 2225//----------------------------------------------------------------------------- 2226// SuspendServices - Suspends services temporarily. [PROTECTED] 2227//----------------------------------------------------------------------------- 2228 2229void 2230IOSCSIParallelInterfaceController::SuspendServices ( void ) 2231{ 2232 2233 // The HBA child class has requested the suspension of tasks. 2234 fHBACanAcceptClientRequests = false; 2235 2236} 2237 2238 2239//----------------------------------------------------------------------------- 2240// ResumeServices - Resume services temporarily. [PROTECTED] 2241//----------------------------------------------------------------------------- 2242 2243void 2244IOSCSIParallelInterfaceController::ResumeServices ( void ) 2245{ 2246 2247 // The HBA child class has allowed the submission of tasks. 2248 fHBACanAcceptClientRequests = true; 2249 2250} 2251 2252 2253//----------------------------------------------------------------------------- 2254// NotifyClientsOfBusReset - Notifies clients of bus resets. [PROTECTED] 2255//----------------------------------------------------------------------------- 2256 2257void 2258IOSCSIParallelInterfaceController::NotifyClientsOfBusReset ( void ) 2259{ 2260 messageClients ( kSCSIControllerNotificationBusReset ); 2261} 2262 2263 2264//----------------------------------------------------------------------------- 2265// NotifyClientsOfPortStatusChange - Notifies clients of port status changes. 2266// [PROTECTED] 2267//----------------------------------------------------------------------------- 2268 2269void 2270IOSCSIParallelInterfaceController::NotifyClientsOfPortStatusChange ( 2271 SCSIPortStatus newStatus ) 2272{ 2273 2274 OSDictionary * hbaDict = NULL; 2275 OSDictionary * copyDict = NULL; 2276 OSString * string = NULL; 2277 char * linkStatus = NULL; 2278 2279 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyControllerCharacteristicsKey ) ); 2280 require_nonzero ( copyDict, ErrorExit ); 2281 2282 hbaDict = ( OSDictionary * ) copyDict->copyCollection ( ); 2283 copyDict->release ( ); 2284 2285 require_nonzero ( hbaDict, ErrorExit ); 2286 2287 switch ( newStatus ) 2288 { 2289 2290 case kSCSIPort_StatusOnline: 2291 linkStatus = ( char * ) kIOPropertyPortStatusLinkEstablishedKey; 2292 break; 2293 2294 case kSCSIPort_StatusOffline: 2295 linkStatus = ( char * ) kIOPropertyPortStatusNoLinkEstablishedKey; 2296 break; 2297 2298 case kSCSIPort_StatusFailure: 2299 linkStatus = ( char * ) kIOPropertyPortStatusLinkFailedKey; 2300 break; 2301 2302 default: 2303 break; 2304 2305 } 2306 2307 string = OSString::withCString ( linkStatus ); 2308 if ( string != NULL ) 2309 { 2310 2311 hbaDict->setObject ( kIOPropertyPortStatusKey, string ); 2312 string->release ( ); 2313 string = NULL; 2314 2315 } 2316 2317 setProperty ( kIOPropertyControllerCharacteristicsKey, hbaDict ); 2318 hbaDict->release ( ); 2319 hbaDict = NULL; 2320 2321 2322ErrorExit: 2323 2324 2325 messageClients ( kSCSIPort_NotificationStatusChange, ( void * ) newStatus ); 2326 2327} 2328 2329 2330#if 0 2331#pragma mark - 2332#pragma mark SCSI Parallel Task Object Accessors 2333#pragma mark - 2334#endif 2335 2336 2337//----------------------------------------------------------------------------- 2338// GetSCSITaskIdentifier - Gets SCSITaskIdentifier for task. [PROTECTED] 2339//----------------------------------------------------------------------------- 2340 2341SCSITaskIdentifier 2342IOSCSIParallelInterfaceController::GetSCSITaskIdentifier ( 2343 SCSIParallelTaskIdentifier parallelTask ) 2344{ 2345 2346 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2347 2348 if ( tempTask == NULL ) 2349 { 2350 return NULL; 2351 } 2352 2353 return tempTask->GetSCSITaskIdentifier ( ); 2354 2355} 2356 2357 2358//----------------------------------------------------------------------------- 2359// GetTargetIdentifier - Gets SCSITargetIdentifier for task. [PROTECTED] 2360//----------------------------------------------------------------------------- 2361 2362SCSITargetIdentifier 2363IOSCSIParallelInterfaceController::GetTargetIdentifier ( 2364 SCSIParallelTaskIdentifier parallelTask ) 2365{ 2366 2367 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2368 2369 if ( tempTask == NULL ) 2370 { 2371 return NULL; 2372 } 2373 2374 return tempTask->GetTargetIdentifier ( ); 2375 2376} 2377 2378 2379//----------------------------------------------------------------------------- 2380// GetDevice - Gets Device for task. [STATIC] 2381//----------------------------------------------------------------------------- 2382 2383static IOSCSIParallelInterfaceDevice * 2384GetDevice ( SCSIParallelTaskIdentifier parallelTask ) 2385{ 2386 2387 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2388 2389 if ( tempTask == NULL ) 2390 { 2391 return NULL; 2392 } 2393 2394 return tempTask->GetDevice ( ); 2395 2396} 2397 2398 2399//----------------------------------------------------------------------------- 2400// CopyProtocolCharacteristicsProperties - Copies properties from object 2401// to dictionary. [STATIC] 2402//----------------------------------------------------------------------------- 2403 2404static void 2405CopyProtocolCharacteristicsProperties ( OSDictionary * dict, IOService * service ) 2406{ 2407 2408 OSString * string = NULL; 2409 OSNumber * number = NULL; 2410 2411 // Set the Physical Interconnect property if it doesn't already exist. 2412 if ( dict->getObject ( kIOPropertyPhysicalInterconnectTypeKey ) == NULL ) 2413 { 2414 2415 string = OSDynamicCast ( OSString, service->getProperty ( kIOPropertyPhysicalInterconnectTypeKey ) ); 2416 if ( string == NULL ) 2417 { 2418 2419 string = OSString::withCString ( kIOPropertyPhysicalInterconnectTypeSCSIParallel ); 2420 if ( string != NULL ) 2421 { 2422 2423 dict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, string ); 2424 string->release ( ); 2425 string = NULL; 2426 2427 } 2428 2429 } 2430 2431 else 2432 { 2433 2434 dict->setObject ( kIOPropertyPhysicalInterconnectTypeKey, string ); 2435 2436 } 2437 2438 } 2439 2440 // Set the Physical Interconnect Location property if it doesn't already exist. 2441 if ( dict->getObject ( kIOPropertyPhysicalInterconnectLocationKey ) == NULL ) 2442 { 2443 2444 string = OSDynamicCast ( OSString, service->getProperty ( kIOPropertyPhysicalInterconnectLocationKey ) ); 2445 if ( string == NULL ) 2446 { 2447 2448 string = OSString::withCString ( kIOPropertyInternalExternalKey ); 2449 if ( string != NULL ) 2450 { 2451 2452 dict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, string ); 2453 string->release ( ); 2454 string = NULL; 2455 2456 } 2457 2458 } 2459 2460 else 2461 { 2462 2463 dict->setObject ( kIOPropertyPhysicalInterconnectLocationKey, string ); 2464 2465 } 2466 2467 } 2468 2469 // Set the Timeout Duration properties if they don't already exist. 2470 if ( dict->getObject ( kIOPropertyReadTimeOutDurationKey ) == NULL ) 2471 { 2472 2473 number = OSDynamicCast ( OSNumber, service->getProperty ( kIOPropertyReadTimeOutDurationKey ) ); 2474 if ( number != NULL ) 2475 { 2476 2477 dict->setObject ( kIOPropertyReadTimeOutDurationKey, number ); 2478 2479 } 2480 2481 } 2482 2483 if ( dict->getObject ( kIOPropertyWriteTimeOutDurationKey ) == NULL ) 2484 { 2485 2486 number = OSDynamicCast ( OSNumber, service->getProperty ( kIOPropertyWriteTimeOutDurationKey ) ); 2487 if ( number != NULL ) 2488 { 2489 2490 dict->setObject ( kIOPropertyWriteTimeOutDurationKey, number ); 2491 2492 } 2493 2494 } 2495 2496} 2497 2498 2499// ---- Methods for Accessing data in the client's SCSI Task Object ---- 2500// Method to retrieve the LUN that identifies the Logical Unit whose Task 2501// Set to which this task is to be added. 2502// --> Currently this only supports Level 1 Addressing, complete 2503// Hierachal LUN addressing will need to be added to the SCSI Task object 2504// and the Peripheral Device Type objects which will represent Logical Units. 2505// Since that will be completed before this is released, this method will be 2506// changed at that time. 2507 2508 2509//----------------------------------------------------------------------------- 2510// GetLogicalUnitNumber - Gets SCSILogicalUnitNumber for task. [PROTECTED] 2511//----------------------------------------------------------------------------- 2512 2513SCSILogicalUnitNumber 2514IOSCSIParallelInterfaceController::GetLogicalUnitNumber ( 2515 SCSIParallelTaskIdentifier parallelTask ) 2516{ 2517 2518 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2519 2520 if ( tempTask == NULL ) 2521 { 2522 return 0; 2523 } 2524 2525 return tempTask->GetLogicalUnitNumber ( ); 2526 2527} 2528 2529 2530//----------------------------------------------------------------------------- 2531// GetLogicalUnitBytes - Gets SCSILogicalUnitBytes for task. [PROTECTED] 2532//----------------------------------------------------------------------------- 2533void 2534IOSCSIParallelInterfaceController::GetLogicalUnitBytes ( 2535 SCSIParallelTaskIdentifier parallelTask, 2536 SCSILogicalUnitBytes * logicalUnitBytes ) 2537{ 2538 2539 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2540 2541 if ( tempTask == NULL ) 2542 { 2543 return; 2544 } 2545 2546 return tempTask->GetLogicalUnitBytes ( logicalUnitBytes ); 2547 2548} 2549 2550 2551 2552//----------------------------------------------------------------------------- 2553// GetTaggedTaskIdentifier - Gets SCSITaggedTaskIdentifier for task. 2554// [PROTECTED] 2555//----------------------------------------------------------------------------- 2556 2557SCSITaggedTaskIdentifier 2558IOSCSIParallelInterfaceController::GetTaggedTaskIdentifier ( 2559 SCSIParallelTaskIdentifier parallelTask ) 2560{ 2561 2562 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2563 2564 if ( tempTask == NULL ) 2565 { 2566 return kSCSIUntaggedTaskIdentifier; 2567 } 2568 2569 return tempTask->GetTaggedTaskIdentifier ( ); 2570 2571} 2572 2573 2574//----------------------------------------------------------------------------- 2575// GetTaskAttribute - Gets SCSITaskAttribute for task. [PROTECTED] 2576//----------------------------------------------------------------------------- 2577 2578SCSITaskAttribute 2579IOSCSIParallelInterfaceController::GetTaskAttribute ( 2580 SCSIParallelTaskIdentifier parallelTask ) 2581{ 2582 2583 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2584 2585 if ( tempTask == NULL ) 2586 { 2587 return kSCSITask_SIMPLE; 2588 } 2589 2590 return tempTask->GetTaskAttribute ( ); 2591 2592} 2593 2594 2595//----------------------------------------------------------------------------- 2596// GetCommandDescriptorBlockSize - Gets CDB size for task. [PROTECTED] 2597//----------------------------------------------------------------------------- 2598 2599UInt8 2600IOSCSIParallelInterfaceController::GetCommandDescriptorBlockSize ( 2601 SCSIParallelTaskIdentifier parallelTask ) 2602{ 2603 2604 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2605 2606 if ( tempTask == NULL ) 2607 { 2608 return 0; 2609 } 2610 2611 return tempTask->GetCommandDescriptorBlockSize ( ); 2612 2613} 2614 2615 2616//----------------------------------------------------------------------------- 2617// GetCommandDescriptorBlock - This will always return a 16 Byte CDB. 2618// [PROTECTED] 2619//----------------------------------------------------------------------------- 2620 2621bool 2622IOSCSIParallelInterfaceController::GetCommandDescriptorBlock ( 2623 SCSIParallelTaskIdentifier parallelTask, 2624 SCSICommandDescriptorBlock * cdbData ) 2625{ 2626 2627 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2628 2629 if ( tempTask == NULL ) 2630 { 2631 return false; 2632 } 2633 2634 return tempTask->GetCommandDescriptorBlock ( cdbData ); 2635 2636} 2637 2638 2639//----------------------------------------------------------------------------- 2640// GetDataTransferDirection - Gets data transfer direction. [PROTECTED] 2641//----------------------------------------------------------------------------- 2642 2643UInt8 2644IOSCSIParallelInterfaceController::GetDataTransferDirection ( 2645 SCSIParallelTaskIdentifier parallelTask ) 2646{ 2647 2648 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2649 2650 if ( tempTask == NULL ) 2651 { 2652 return kSCSIDataTransfer_NoDataTransfer; 2653 } 2654 2655 return tempTask->GetDataTransferDirection ( ); 2656 2657} 2658 2659 2660//----------------------------------------------------------------------------- 2661// GetRequestedDataTransferCount - Gets requested transfer count. [PROTECTED] 2662//----------------------------------------------------------------------------- 2663 2664UInt64 2665IOSCSIParallelInterfaceController::GetRequestedDataTransferCount ( 2666 SCSIParallelTaskIdentifier parallelTask ) 2667{ 2668 2669 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2670 2671 if ( tempTask == NULL ) 2672 { 2673 return 0; 2674 } 2675 2676 return tempTask->GetRequestedDataTransferCount ( ); 2677 2678} 2679 2680 2681//----------------------------------------------------------------------------- 2682// GetRealizedDataTransferCount - Gets realized transfer count. [PROTECTED] 2683//----------------------------------------------------------------------------- 2684 2685UInt64 2686IOSCSIParallelInterfaceController::GetRealizedDataTransferCount ( 2687 SCSIParallelTaskIdentifier parallelTask ) 2688{ 2689 2690 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2691 2692 if ( tempTask == NULL ) 2693 { 2694 return 0; 2695 } 2696 2697 return tempTask->GetRealizedDataTransferCount ( ); 2698 2699} 2700 2701 2702//----------------------------------------------------------------------------- 2703// SetRealizedDataTransferCount - Sets realized transfer count. [PROTECTED] 2704//----------------------------------------------------------------------------- 2705 2706bool 2707IOSCSIParallelInterfaceController::SetRealizedDataTransferCount ( 2708 SCSIParallelTaskIdentifier parallelTask, 2709 UInt64 realizedTransferCountInBytes ) 2710{ 2711 2712 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2713 2714 if ( tempTask == NULL ) 2715 { 2716 return false; 2717 } 2718 2719 return tempTask->SetRealizedDataTransferCount ( realizedTransferCountInBytes ); 2720 2721} 2722 2723 2724//----------------------------------------------------------------------------- 2725// IncrementRealizedDataTransferCount - Adjusts realized transfer count. 2726// [PROTECTED] 2727//----------------------------------------------------------------------------- 2728 2729void 2730IOSCSIParallelInterfaceController::IncrementRealizedDataTransferCount ( 2731 SCSIParallelTaskIdentifier parallelTask, 2732 UInt64 realizedTransferCountInBytes ) 2733{ 2734 2735 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2736 2737 if ( tempTask == NULL ) 2738 { 2739 return; 2740 } 2741 2742 return tempTask->IncrementRealizedDataTransferCount ( realizedTransferCountInBytes ); 2743 2744} 2745 2746 2747//----------------------------------------------------------------------------- 2748// GetDataBuffer - Gets data buffer associated with this task. [PROTECTED] 2749//----------------------------------------------------------------------------- 2750 2751IOMemoryDescriptor * 2752IOSCSIParallelInterfaceController::GetDataBuffer ( 2753 SCSIParallelTaskIdentifier parallelTask ) 2754{ 2755 2756 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2757 2758 if ( tempTask == NULL ) 2759 { 2760 return NULL; 2761 } 2762 2763 return tempTask->GetDataBuffer ( ); 2764 2765} 2766 2767 2768//----------------------------------------------------------------------------- 2769// GetDataBufferOffset - Gets data buffer offset associated with this task. 2770// [PROTECTED] 2771//----------------------------------------------------------------------------- 2772 2773UInt64 2774IOSCSIParallelInterfaceController::GetDataBufferOffset ( 2775 SCSIParallelTaskIdentifier parallelTask ) 2776{ 2777 2778 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2779 2780 if ( tempTask == NULL ) 2781 { 2782 return 0; 2783 } 2784 2785 return tempTask->GetDataBufferOffset ( ); 2786 2787} 2788 2789 2790//----------------------------------------------------------------------------- 2791// GetDMACommand - Gets IODMACommand associated with this task. [PROTECTED] 2792//----------------------------------------------------------------------------- 2793 2794IODMACommand * 2795IOSCSIParallelInterfaceController::GetDMACommand ( 2796 SCSIParallelTaskIdentifier parallelTask ) 2797{ 2798 return ( IODMACommand * ) parallelTask; 2799} 2800 2801 2802//----------------------------------------------------------------------------- 2803// GetTimeoutDuration - Gets timeout duration in milliseconds associated. 2804// with this task. [PROTECTED] 2805//----------------------------------------------------------------------------- 2806 2807UInt32 2808IOSCSIParallelInterfaceController::GetTimeoutDuration ( 2809 SCSIParallelTaskIdentifier parallelTask ) 2810{ 2811 2812 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2813 2814 if ( tempTask == NULL ) 2815 { 2816 return 0; 2817 } 2818 2819 return tempTask->GetTimeoutDuration ( ); 2820 2821} 2822 2823 2824//----------------------------------------------------------------------------- 2825// SetAutoSenseData - Sets autosense data in task. [PROTECTED] 2826//----------------------------------------------------------------------------- 2827 2828bool 2829IOSCSIParallelInterfaceController::SetAutoSenseData ( 2830 SCSIParallelTaskIdentifier parallelTask, 2831 SCSI_Sense_Data * newSenseData, 2832 UInt8 senseDataSize ) 2833{ 2834 2835 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2836 2837 if ( tempTask == NULL ) 2838 { 2839 return false; 2840 } 2841 2842 return tempTask->SetAutoSenseData ( newSenseData, senseDataSize ); 2843 2844} 2845 2846 2847//----------------------------------------------------------------------------- 2848// GetAutoSenseData - Gets autosense data in task. [PROTECTED] 2849//----------------------------------------------------------------------------- 2850 2851bool 2852IOSCSIParallelInterfaceController::GetAutoSenseData ( 2853 SCSIParallelTaskIdentifier parallelTask, 2854 SCSI_Sense_Data * receivingBuffer, 2855 UInt8 senseDataSize ) 2856{ 2857 2858 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2859 2860 if ( tempTask == NULL ) 2861 { 2862 return false; 2863 } 2864 2865 return tempTask->GetAutoSenseData ( receivingBuffer, senseDataSize ); 2866 2867} 2868 2869 2870//----------------------------------------------------------------------------- 2871// GetAutoSenseDataSize - Gets autosense data size. [PROTECTED] 2872//----------------------------------------------------------------------------- 2873 2874UInt8 2875IOSCSIParallelInterfaceController::GetAutoSenseDataSize ( 2876 SCSIParallelTaskIdentifier parallelTask ) 2877{ 2878 2879 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2880 2881 if ( tempTask == NULL ) 2882 { 2883 return 0; 2884 } 2885 2886 return tempTask->GetAutoSenseDataSize ( ); 2887 2888} 2889 2890 2891//----------------------------------------------------------------------------- 2892// GetSCSIParallelFeatureNegotiation - Gets SCSIParallelFeatureRequest status 2893// for specified feature. [PROTECTED] 2894//----------------------------------------------------------------------------- 2895 2896SCSIParallelFeatureRequest 2897IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiation ( 2898 SCSIParallelTaskIdentifier parallelTask, 2899 SCSIParallelFeature requestedFeature ) 2900{ 2901 2902 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2903 2904 if ( tempTask == NULL ) 2905 { 2906 return kSCSIParallelFeature_NoNegotiation; 2907 } 2908 2909 return tempTask->GetSCSIParallelFeatureNegotiation ( requestedFeature ); 2910 2911} 2912 2913 2914//----------------------------------------------------------------------------- 2915// GetSCSIParallelFeatureNegotiationCount - Gets SCSIParallelFeatureRequest 2916// count. [PROTECTED] 2917//----------------------------------------------------------------------------- 2918 2919UInt64 2920IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationCount ( 2921 SCSIParallelTaskIdentifier parallelTask) 2922{ 2923 2924 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2925 2926 if ( tempTask == NULL ) 2927 { 2928 return 0; 2929 } 2930 2931 return tempTask->GetSCSIParallelFeatureNegotiationCount ( ); 2932 2933} 2934 2935 2936//----------------------------------------------------------------------------- 2937// SetSCSIParallelFeatureNegotiationResult - Sets SCSIParallelFeatureResult 2938// status for specified feature. 2939// [PROTECTED] 2940//----------------------------------------------------------------------------- 2941 2942void 2943IOSCSIParallelInterfaceController::SetSCSIParallelFeatureNegotiationResult ( 2944 SCSIParallelTaskIdentifier parallelTask, 2945 SCSIParallelFeature requestedFeature, 2946 SCSIParallelFeatureResult newResult ) 2947{ 2948 2949 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2950 2951 if ( tempTask == NULL ) 2952 { 2953 return; 2954 } 2955 2956 return tempTask->SetSCSIParallelFeatureNegotiationResult ( requestedFeature, newResult ); 2957 2958} 2959 2960 2961//----------------------------------------------------------------------------- 2962// GetSCSIParallelFeatureNegotiationResult - Gets SCSIParallelFeatureResult 2963// for requested feature. 2964// [PROTECTED] 2965//----------------------------------------------------------------------------- 2966 2967SCSIParallelFeatureResult 2968IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationResult ( 2969 SCSIParallelTaskIdentifier parallelTask, 2970 SCSIParallelFeature requestedFeature ) 2971{ 2972 2973 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2974 2975 if ( tempTask == NULL ) 2976 { 2977 return kSCSIParallelFeature_NegotitiationUnchanged; 2978 } 2979 2980 return tempTask->GetSCSIParallelFeatureNegotiationResult ( requestedFeature ); 2981 2982} 2983 2984 2985//----------------------------------------------------------------------------- 2986// GetSCSIParallelFeatureNegotiationResultCount - Gets SCSIParallelFeatureResult 2987// count. [PROTECTED] 2988//----------------------------------------------------------------------------- 2989 2990UInt64 2991IOSCSIParallelInterfaceController::GetSCSIParallelFeatureNegotiationResultCount ( 2992 SCSIParallelTaskIdentifier parallelTask ) 2993{ 2994 2995 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 2996 2997 if ( tempTask == NULL ) 2998 { 2999 return 0; 3000 } 3001 3002 return tempTask->GetSCSIParallelFeatureNegotiationResultCount ( ); 3003 3004} 3005 3006 3007//----------------------------------------------------------------------------- 3008// SetControllerTaskIdentifier - Sets the unique identifier for the task. 3009// [PROTECTED] 3010//----------------------------------------------------------------------------- 3011 3012void 3013IOSCSIParallelInterfaceController::SetControllerTaskIdentifier ( 3014 SCSIParallelTaskIdentifier parallelTask, 3015 UInt64 newIdentifier ) 3016{ 3017 3018 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 3019 3020 if ( tempTask == NULL ) 3021 { 3022 return; 3023 } 3024 3025 return tempTask->SetControllerTaskIdentifier ( newIdentifier ); 3026 3027} 3028 3029 3030//----------------------------------------------------------------------------- 3031// GetControllerTaskIdentifier - Gets the unique identifier for the task. 3032// [PROTECTED] 3033//----------------------------------------------------------------------------- 3034 3035UInt64 3036IOSCSIParallelInterfaceController::GetControllerTaskIdentifier ( 3037 SCSIParallelTaskIdentifier parallelTask ) 3038{ 3039 3040 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 3041 3042 if ( tempTask == NULL ) 3043 { 3044 return 0; 3045 } 3046 3047 return tempTask->GetControllerTaskIdentifier ( ); 3048 3049} 3050 3051 3052//----------------------------------------------------------------------------- 3053// GetHBADataSize - Gets size of HBA data allocated in the task. [PROTECTED] 3054//----------------------------------------------------------------------------- 3055 3056UInt32 3057IOSCSIParallelInterfaceController::GetHBADataSize ( 3058 SCSIParallelTaskIdentifier parallelTask ) 3059{ 3060 3061 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 3062 3063 if ( tempTask == NULL ) 3064 { 3065 return 0; 3066 } 3067 3068 return tempTask->GetHBADataSize ( ); 3069 3070} 3071 3072 3073//----------------------------------------------------------------------------- 3074// GetHBADataPointer - Gets pointer to HBA data. [PROTECTED] 3075//----------------------------------------------------------------------------- 3076 3077void * 3078IOSCSIParallelInterfaceController::GetHBADataPointer ( 3079 SCSIParallelTaskIdentifier parallelTask ) 3080{ 3081 3082 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 3083 3084 if ( tempTask == NULL ) 3085 { 3086 return NULL; 3087 } 3088 3089 return tempTask->GetHBADataPointer ( ); 3090 3091} 3092 3093 3094//----------------------------------------------------------------------------- 3095// GetHBADataDescriptor - Gets IOMemoryDescriptor for HBA data. [PROTECTED] 3096//----------------------------------------------------------------------------- 3097 3098IOMemoryDescriptor * 3099IOSCSIParallelInterfaceController::GetHBADataDescriptor ( 3100 SCSIParallelTaskIdentifier parallelTask ) 3101{ 3102 3103 SCSIParallelTask * tempTask = ( SCSIParallelTask * ) parallelTask; 3104 3105 if ( tempTask == NULL ) 3106 { 3107 return NULL; 3108 } 3109 3110 return tempTask->GetHBADataDescriptor ( ); 3111 3112} 3113 3114 3115#if 0 3116#pragma mark - 3117#pragma mark SCSI Parallel Device Object Accessors 3118#pragma mark - 3119#endif 3120 3121 3122//----------------------------------------------------------------------------- 3123// GetHBATargetDataSize - Gets size of HBA data for the target. [PROTECTED] 3124//----------------------------------------------------------------------------- 3125 3126UInt32 3127IOSCSIParallelInterfaceController::GetHBATargetDataSize ( 3128 SCSITargetIdentifier targetID ) 3129{ 3130 3131 IOSCSIParallelInterfaceDevice * targetDevice; 3132 3133 targetDevice = GetTargetForID ( targetID ); 3134 if ( targetDevice == NULL ) 3135 { 3136 return 0; 3137 } 3138 3139 return targetDevice->GetHBADataSize ( ); 3140 3141} 3142 3143 3144//----------------------------------------------------------------------------- 3145// GetHBATargetDataPointer - Gets size of HBA data for the target. [PROTECTED] 3146//----------------------------------------------------------------------------- 3147 3148void * 3149IOSCSIParallelInterfaceController::GetHBATargetDataPointer ( 3150 SCSITargetIdentifier targetID ) 3151{ 3152 3153 IOSCSIParallelInterfaceDevice * targetDevice; 3154 3155 targetDevice = GetTargetForID ( targetID ); 3156 if ( targetDevice == NULL ) 3157 { 3158 return NULL; 3159 } 3160 3161 return targetDevice->GetHBADataPointer ( ); 3162 3163} 3164 3165 3166#if 0 3167#pragma mark - 3168#pragma mark VTable Padding 3169#pragma mark - 3170#endif 3171 3172 3173// Space reserved for future expansion. 3174OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 1 ); // Used for DoesHBAPerformAutoSense 3175OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 2 ); // Used for ReportHBAConstraints 3176 3177OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 3 ); // Used for DoesHBASupportMultiPathing 3178OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 4 ); 3179OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 5 ); 3180OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 6 ); 3181OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 7 ); 3182OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 8 ); 3183 3184OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 9 ); // Used for HandleTimeout 3185OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 10 ); // Used for FilterInterruptRequest 3186OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 11 ); // Used for InitializeDMASpecification 3187OSMetaClassDefineReservedUsed ( IOSCSIParallelInterfaceController, 12 ); // Used for CreateDeviceInterrupt 3188 3189OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 13 ); 3190OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 14 ); 3191OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 15 ); 3192OSMetaClassDefineReservedUnused ( IOSCSIParallelInterfaceController, 16 ); 3193