1/* 2 * Copyright (c) 2002-2008 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// Libkern includes 30#include <libkern/c++/OSData.h> 31#include <libkern/c++/OSDictionary.h> 32 33// General IOKit includes 34#include <IOKit/IOBufferMemoryDescriptor.h> 35#include <IOKit/IOMessage.h> 36#include <IOKit/IODeviceTreeSupport.h> 37 38// IOKit storage includes 39#include <IOKit/storage/IOStorageDeviceCharacteristics.h> 40#include <IOKit/storage/IOStorageProtocolCharacteristics.h> 41 42// SCSI Architecture Model Family includes 43#include <IOKit/scsi/SCSICommandOperationCodes.h> 44#include <IOKit/scsi/SCSICmds_INQUIRY_Definitions.h> 45 46// SCSI Parallel Family includes 47#include "IOSCSIParallelInterfaceDevice.h" 48 49 50//----------------------------------------------------------------------------- 51// Macros 52//----------------------------------------------------------------------------- 53 54#define DEBUG 0 55#define DEBUG_ASSERT_COMPONENT_NAME_STRING "SPI Device" 56 57#if DEBUG 58#define SCSI_PARALLEL_DEVICE_DEBUGGING_LEVEL 0 59#endif 60 61#include "IOSCSIParallelFamilyDebugging.h" 62 63#if ( SCSI_PARALLEL_DEVICE_DEBUGGING_LEVEL >= 1 ) 64#define PANIC_NOW(x) panic x 65#else 66#define PANIC_NOW(x) 67#endif 68 69#if ( SCSI_PARALLEL_DEVICE_DEBUGGING_LEVEL >= 2 ) 70#define ERROR_LOG(x) IOLog x 71#else 72#define ERROR_LOG(x) 73#endif 74 75#if ( SCSI_PARALLEL_DEVICE_DEBUGGING_LEVEL >= 3 ) 76#define STATUS_LOG(x) IOLog x 77#else 78#define STATUS_LOG(x) 79#endif 80 81 82#define super IOSCSIProtocolServices 83OSDefineMetaClassAndStructors ( IOSCSIParallelInterfaceDevice, IOSCSIProtocolServices ); 84 85 86//----------------------------------------------------------------------------- 87// Constants 88//----------------------------------------------------------------------------- 89 90#define kIOPropertyIOUnitKey "IOUnit" 91#define kIODeviceLocationKey "io-device-location" 92 93#define kMaxTaskRetryCount 3 94 95enum 96{ 97 kWorldWideNameDataSize = 8, 98 kAddressIdentifierDataSize = 3, 99 kALPADataSize = 1, 100 kSASAddressDataSize = 8, 101 kSCSIPortIdentifierDataSize = 8 102}; 103 104// Used by power manager to figure out what states we support 105// The default implementation supports two basic states: ON and OFF 106// ON state means the device can be used on this transport layer 107// OFF means the device cannot receive any I/O on this transport layer 108static IOPMPowerState sPowerStates[kSCSIProtocolLayerNumDefaultStates] = 109{ 110 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 111 { 1, (IOPMDeviceUsable | IOPMMaxPerformance), IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } 112}; 113 114 115#if 0 116#pragma mark - 117#pragma mark IOKit Member Routines 118#pragma mark - 119#endif 120 121 122//----------------------------------------------------------------------------- 123// SetInitialTargetProperties [PUBLIC] 124//----------------------------------------------------------------------------- 125 126bool 127IOSCSIParallelInterfaceDevice::SetInitialTargetProperties ( 128 OSDictionary * properties ) 129{ 130 131 OSDictionary * protocolDict = NULL; 132 OSObject * value = NULL; 133 bool result = false; 134 135 protocolDict = OSDictionary::withCapacity ( properties->getCount ( ) ); 136 require_nonzero ( protocolDict, INIT_FAILURE ); 137 138 setProperty ( kIOPropertyProtocolCharacteristicsKey, protocolDict ); 139 protocolDict->release ( ); 140 protocolDict = NULL; 141 142 // Set the properties from the dictionary 143 value = properties->getObject ( kIOPropertyFibreChannelNodeWorldWideNameKey ); 144 SetTargetProperty ( kIOPropertyFibreChannelNodeWorldWideNameKey, value ); 145 146 value = properties->getObject ( kIOPropertyFibreChannelPortWorldWideNameKey ); 147 SetTargetProperty ( kIOPropertyFibreChannelPortWorldWideNameKey, value ); 148 149 value = properties->getObject ( kIOPropertyFibreChannelAddressIdentifierKey ); 150 SetTargetProperty ( kIOPropertyFibreChannelAddressIdentifierKey, value ); 151 152 value = properties->getObject ( kIOPropertyFibreChannelALPAKey ); 153 SetTargetProperty ( kIOPropertyFibreChannelALPAKey, value ); 154 155 value = properties->getObject ( kIOPropertySASAddressKey ); 156 SetTargetProperty ( kIOPropertySASAddressKey, value ); 157 158 value = properties->getObject ( kIOPropertyRetryCountKey ); 159 SetTargetProperty ( kIOPropertyRetryCountKey, value ); 160 161 result = true; 162 163 164INIT_FAILURE: 165 166 167 return result; 168 169} 170 171 172//----------------------------------------------------------------------------- 173// start [PUBLIC] 174//----------------------------------------------------------------------------- 175 176bool 177IOSCSIParallelInterfaceDevice::start ( IOService * provider ) 178{ 179 180 OSDictionary * protocolDict = NULL; 181 OSDictionary * copyDict = NULL; 182 bool result = false; 183 char unit[10]; 184 185 // Save access to the controller object so that Tasks can be sent 186 // for execution. 187 fController = OSDynamicCast ( IOSCSIParallelInterfaceController, provider ); 188 require_nonzero ( fController, PROVIDER_CAST_FAILURE ); 189 190 // Retain the controller. 191 fController->retain ( ); 192 193 // Execute the inherited start 194 result = super::start ( provider ); 195 require ( result, PROVIDER_START_FAILURE ); 196 197 // Open the controller, the provider. 198 result = fController->open ( this ); 199 require ( result, CONTROLLER_OPEN_FAILURE ); 200 201 result = fController->InitializeTargetForID ( fTargetIdentifier ); 202 require ( result, CONTROLLER_INIT_FAILURE ); 203 204 // Check if controller supports Multipathing 205 fMultiPathSupport = fController->DoesHBASupportMultiPathing ( ); 206 207 // Setup power management for this object. 208 InitializePowerManagement ( provider ); 209 210 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 211 if ( copyDict != NULL ) 212 { 213 214 protocolDict = ( OSDictionary * ) copyDict->copyCollection ( ); 215 copyDict->release ( ); 216 copyDict = NULL; 217 218 } 219 220 if ( protocolDict != NULL ) 221 { 222 223 OSNumber * targetID = NULL; 224 225 // Create an OSNumber object with the SCSI Target Identifier 226 targetID = OSNumber::withNumber ( fTargetIdentifier, 64 ); 227 if ( targetID != NULL ) 228 { 229 230 protocolDict->setObject ( kIOPropertySCSITargetIdentifierKey, targetID ); 231 232 // Set the Unit number used to build the device tree path 233 setProperty ( kIOPropertyIOUnitKey, targetID ); 234 235 targetID->release ( ); 236 237 } 238 239 setProperty ( kIOPropertyProtocolCharacteristicsKey, protocolDict ); 240 protocolDict->release ( ); 241 protocolDict = NULL; 242 243 } 244 245 // Set the location to allow booting 246 snprintf ( unit, 10, "%x", ( int ) fTargetIdentifier ); 247 setLocation ( unit ); 248 249 // The device and this driver have been succesfully configured 250 // and are ready to provide their services, call CreateSCSITargetDevice(). 251 CreateSCSITargetDevice ( ); 252 253 return true; 254 255 256CONTROLLER_INIT_FAILURE: 257CONTROLLER_OPEN_FAILURE: 258PROVIDER_START_FAILURE: 259PROVIDER_CAST_FAILURE: 260 261 262 return false; 263 264} 265 266 267//----------------------------------------------------------------------------- 268// stop [PUBLIC] 269//----------------------------------------------------------------------------- 270 271void 272IOSCSIParallelInterfaceDevice::stop ( IOService * provider ) 273{ 274 super::stop ( provider ); 275} 276 277 278//----------------------------------------------------------------------------- 279// finalize [PUBLIC] 280//----------------------------------------------------------------------------- 281 282bool 283IOSCSIParallelInterfaceDevice::finalize ( IOOptionBits options ) 284{ 285 286 if ( ( fController != NULL ) && ( fController->isOpen ( this ) == true ) ) 287 { 288 289 fController->close ( this ); 290 291 } 292 293 return super::finalize ( options ); 294 295} 296 297 298//----------------------------------------------------------------------------- 299// free [PUBLIC] 300//----------------------------------------------------------------------------- 301 302void 303IOSCSIParallelInterfaceDevice::free ( void ) 304{ 305 306 // Release the HBA specific data 307 if ( fHBAData != NULL ) 308 { 309 310 IOFree ( fHBAData, fHBADataSize ); 311 fHBAData = NULL; 312 fHBADataSize = 0; 313 314 } 315 316 // Release the lock for the Task Queue. 317 if ( fQueueLock != NULL ) 318 { 319 320 // Free the SCSI Task queue access lock. 321 IOSimpleLockFree ( fQueueLock ); 322 fQueueLock = NULL; 323 324 } 325 326 if ( fController != NULL ) 327 { 328 329 fController->release ( ); 330 fController = NULL; 331 332 } 333 334 super::free ( ); 335 336} 337 338 339//----------------------------------------------------------------------------- 340// message [PUBLIC] 341//----------------------------------------------------------------------------- 342 343IOReturn 344IOSCSIParallelInterfaceDevice::message ( 345 UInt32 type, 346 IOService * provider, 347 void * argument ) 348{ 349 350 IOReturn result = kIOReturnSuccess; 351 352 switch ( type ) 353 { 354 355 case kSCSIControllerNotificationBusReset: 356 { 357 358 // Bus reset occurred, disavow all negotiation settings 359 // and force renegotiation 360 for ( int index = 0; index < kSCSIParallelFeature_TotalFeatureCount; index++ ) 361 { 362 363 // Set each one to false. 364 fFeatureIsNegotiated[index] = false; 365 366 } 367 368 // Message the SAM drivers to verify their device's state 369 SendNotification_VerifyDeviceState ( ); 370 371 } 372 break; 373 374 case kSCSIPort_NotificationStatusChange: 375 { 376 377 // Port status is changing, let target device object know 378 // about it. 379 messageClients ( kSCSIPort_NotificationStatusChange, argument ); 380 381 } 382 383 default: 384 { 385 result = super::message ( type, provider, argument ); 386 } 387 break; 388 389 } 390 391 return result; 392 393} 394 395 396//----------------------------------------------------------------------------- 397// requestProbe [PUBLIC] 398//----------------------------------------------------------------------------- 399 400IOReturn 401IOSCSIParallelInterfaceDevice::requestProbe ( IOOptionBits options ) 402{ 403 404 // See if this device already has any opens on it. 405 if ( isOpen ( ) == false ) 406 { 407 408 // The device and this driver have been succesfully configured 409 // and are ready to provide their services, call CreateSCSITargetDevice(). 410 CreateSCSITargetDevice ( ); 411 412 return kIOReturnSuccess; 413 414 } 415 416 else 417 { 418 return kIOReturnNotPermitted; 419 } 420 421} 422 423//----------------------------------------------------------------------------- 424// InitializePowerManagement - Register the driver with our policy-maker 425// (also in the same class). [PROTECTED] 426//----------------------------------------------------------------------------- 427 428void 429IOSCSIParallelInterfaceDevice::InitializePowerManagement ( IOService * provider ) 430{ 431 432 PMinit ( ); 433 434 temporaryPowerClampOn ( ); 435 436 provider->joinPMtree ( this ); 437 438 // Call makeUsable here to tell the power manager to put us in our 439 // highest power state when we call registerPowerDriver(). 440 makeUsable ( ); 441 442 fPowerManagementInitialized = true; 443 444 fCurrentPowerState = kSCSIProtocolLayerPowerStateOn; 445 446 // Register this piece with power management as the "policy maker" 447 // i.e. the thing that controls power management for the protocol layer 448 registerPowerDriver ( this, sPowerStates, kSCSIProtocolLayerNumDefaultStates ); 449 450 // make sure we default to on state 451 changePowerStateTo ( kSCSIProtocolLayerPowerStateOn ); 452 453 fCurrentPowerState = kSCSIProtocolLayerPowerStateOn; 454 fProposedPowerState = kSCSIProtocolLayerPowerStateOn; 455 456} 457 458#if 0 459#pragma mark - 460#pragma mark Device Object Management Member routines 461#pragma mark - 462#endif 463 464 465//----------------------------------------------------------------------------- 466// CreateTarget - Creates an IOSCSIParallelInterfaceDevice for the 467// specified target ID. [STATIC][PUBLIC] 468//----------------------------------------------------------------------------- 469 470IOSCSIParallelInterfaceDevice * 471IOSCSIParallelInterfaceDevice::CreateTarget ( 472 SCSITargetIdentifier targetID, 473 UInt32 sizeOfHBAData, 474 IORegistryEntry * entry ) 475{ 476 477 IOSCSIParallelInterfaceDevice * newDevice = NULL; 478 bool result = false; 479 480 newDevice = OSTypeAlloc ( IOSCSIParallelInterfaceDevice ); 481 require_nonzero ( newDevice, DEVICE_CREATION_FAILURE ); 482 483 result = newDevice->InitTarget ( targetID, sizeOfHBAData, entry ); 484 require ( result, RELEASE_DEVICE ); 485 486 return newDevice; 487 488 489RELEASE_DEVICE: 490 491 492 require_nonzero_quiet ( newDevice, DEVICE_CREATION_FAILURE ); 493 newDevice->release ( ); 494 newDevice = NULL; 495 496 497DEVICE_CREATION_FAILURE: 498 499 500 return NULL; 501 502} 503 504 505//----------------------------------------------------------------------------- 506// InitTarget -Initializes a target device. [PROTECTED] 507//----------------------------------------------------------------------------- 508 509bool 510IOSCSIParallelInterfaceDevice::InitTarget ( 511 SCSITargetIdentifier targetID, 512 UInt32 sizeOfHBAData, 513 IORegistryEntry * entry ) 514{ 515 516 bool result = false; 517 518 result = super::init ( 0 ); 519 require ( result, ERROR_EXIT ); 520 521 queue_init ( &fOutstandingTaskList ); 522 queue_init ( &fResendTaskList ); 523 524 // Allocate the lock for the Task Queue 525 fQueueLock = IOSimpleLockAlloc ( ); 526 require_nonzero ( fQueueLock, ERROR_EXIT ); 527 528 if ( entry != NULL ) 529 { 530 531 OSObject * value = NULL; 532 533 lockForArbitration ( ); 534 result = attachToParent ( entry, gIODTPlane ); 535 unlockForArbitration ( ); 536 537 require ( result, ATTACH_TO_PARENT_FAILURE ); 538 539 value = entry->copyProperty ( kIODeviceLocationKey ); 540 if ( value != NULL ) 541 { 542 setProperty ( kIODeviceLocationKey, value ); 543 } 544 545 } 546 547 // Set all of the fields to their defaults 548 fHBADataSize = sizeOfHBAData; 549 fTargetIdentifier = targetID; 550 551 fAllowResends = true; 552 553 // Set Multipath support to 'true' by default. 554 // The HBA driver will be queried and this will be 555 // updated. 556 fMultiPathSupport = true; 557 558 if ( sizeOfHBAData != 0 ) 559 { 560 561 // Allocate the HBA specific data for the device object 562 fHBAData = IOMalloc ( sizeOfHBAData ); 563 require_nonzero ( fHBAData, HBA_DATA_ALLOC_FAILURE ); 564 bzero ( fHBAData, sizeOfHBAData ); 565 566 } 567 568 return true; 569 570 571HBA_DATA_ALLOC_FAILURE: 572ATTACH_TO_PARENT_FAILURE: 573 574 575 require_nonzero_quiet ( fQueueLock, ERROR_EXIT ); 576 IOSimpleLockFree ( fQueueLock ); 577 fQueueLock = NULL; 578 579 580ERROR_EXIT: 581 582 583 return false; 584 585} 586 587 588//----------------------------------------------------------------------------- 589// DestroyTarget - Destroys an IOSCSIParallelInterfaceDevice. [PUBLIC] 590//----------------------------------------------------------------------------- 591 592void 593IOSCSIParallelInterfaceDevice::DestroyTarget ( void ) 594{ 595 596 IORegistryEntry * parent = NULL; 597 598 SendNotification_DeviceRemoved ( ); 599 600 // Get rid of the io-device-location property first. 601 removeProperty ( kIODeviceLocationKey ); 602 603 // Remove anything from the "resend queue". 604 IOSimpleLockLock ( fQueueLock ); 605 606 fAllowResends = false; 607 608 IOSimpleLockUnlock ( fQueueLock ); 609 610 // Remove this entry from the IODeviceTree plane. 611 lockForArbitration ( ); 612 613 parent = getParentEntry ( gIODTPlane ); 614 615 if ( parent != NULL ) 616 { 617 detachFromParent ( parent, gIODTPlane ); 618 } 619 620 unlockForArbitration ( ); 621 622} 623 624 625//----------------------------------------------------------------------------- 626// GetPreviousDeviceInList - Retrieves previous device in linked list. 627// [PUBLIC] 628//----------------------------------------------------------------------------- 629 630IOSCSIParallelInterfaceDevice * 631IOSCSIParallelInterfaceDevice::GetPreviousDeviceInList ( void ) 632{ 633 return fPreviousParallelDevice; 634} 635 636 637//----------------------------------------------------------------------------- 638// SetPreviousDeviceInList - Sets previous device in linked list. [PUBLIC] 639//----------------------------------------------------------------------------- 640 641void 642IOSCSIParallelInterfaceDevice::SetPreviousDeviceInList ( 643 IOSCSIParallelInterfaceDevice * newPrev ) 644{ 645 fPreviousParallelDevice = newPrev; 646} 647 648 649//----------------------------------------------------------------------------- 650// GetNextDeviceInList - Retrieves next device in linked list. [PUBLIC] 651//----------------------------------------------------------------------------- 652 653IOSCSIParallelInterfaceDevice * 654IOSCSIParallelInterfaceDevice::GetNextDeviceInList ( void ) 655{ 656 return fNextParallelDevice; 657} 658 659 660//----------------------------------------------------------------------------- 661// SetNextDeviceInList - Sets next device in linked list. [PUBLIC] 662//----------------------------------------------------------------------------- 663 664void 665IOSCSIParallelInterfaceDevice::SetNextDeviceInList ( 666 IOSCSIParallelInterfaceDevice * newNext ) 667{ 668 fNextParallelDevice = newNext; 669} 670 671 672//----------------------------------------------------------------------------- 673// DetermineParallelFeatures - Determines parallel protocol features based 674// on INQUIRY data. [PRIVATE] 675//----------------------------------------------------------------------------- 676 677void 678IOSCSIParallelInterfaceDevice::DetermineParallelFeatures ( UInt8 * inqData ) 679{ 680 681 OSDictionary * dict = NULL; 682 OSDictionary * copyDict = NULL; 683 OSNumber * features = NULL; 684 UInt64 deviceFeatures = 0; 685 UInt64 ITNexusFeatures = 0; 686 bool supported = false; 687 UInt8 inqSCSIVersion = 0; 688 UInt8 inqDataLength = 0; 689 690 inqSCSIVersion = ( ( SCSICmd_INQUIRY_StandardData * ) inqData )->VERSION & kINQUIRY_ANSI_VERSION_Mask; 691 inqDataLength = ( ( SCSICmd_INQUIRY_StandardData * ) inqData )->ADDITIONAL_LENGTH + 5; 692 693 // Verify that the device is SCSI-2 compliant and the INQUIRY data is large 694 // enough to contain the SCSI-2 feature flags 695 if ( ( inqSCSIVersion >= kINQUIRY_ANSI_VERSION_SCSI_2_Compliant ) && 696 ( inqDataLength > kINQUIRY_Byte7_Offset ) ) 697 { 698 699 if ( inqData[kINQUIRY_Byte7_Offset] & kINQUIRY_Byte7_SYNC_Mask ) 700 { 701 702 deviceFeatures |= (1 << kSCSIParallelFeature_SynchronousDataTransfer); 703 supported = DoesHBASupportSCSIParallelFeature ( kSCSIParallelFeature_SynchronousDataTransfer ); 704 if ( supported == true ) 705 { 706 707 fITNexusSupportsFeature[kSCSIParallelFeature_SynchronousDataTransfer] = true; 708 ITNexusFeatures |= (1 << kSCSIParallelFeature_SynchronousDataTransfer); 709 710 } 711 712 } 713 714 if ( inqData[kINQUIRY_Byte7_Offset] & kINQUIRY_Byte7_WBUS16_Mask ) 715 { 716 717 deviceFeatures |= (1 << kSCSIParallelFeature_WideDataTransfer); 718 supported = DoesHBASupportSCSIParallelFeature ( kSCSIParallelFeature_WideDataTransfer ); 719 if ( supported == true ) 720 { 721 722 fITNexusSupportsFeature[kSCSIParallelFeature_WideDataTransfer] = true; 723 ITNexusFeatures |= (1 << kSCSIParallelFeature_WideDataTransfer); 724 725 } 726 727 } 728 729 } 730 731 // Verify that the device is SPC compliant and the INQUIRY data is large 732 // enough to contain the SPI-3 feature flags 733 if ( ( inqSCSIVersion >= kINQUIRY_ANSI_VERSION_SCSI_SPC_Compliant ) && 734 ( inqDataLength > kINQUIRY_Byte56_Offset ) ) 735 { 736 737 if ( inqData[kINQUIRY_Byte56_Offset] & kINQUIRY_Byte56_IUS_Mask ) 738 { 739 740 deviceFeatures |= (1 << kSCSIParallelFeature_InformationUnitTransfers); 741 supported = DoesHBASupportSCSIParallelFeature ( kSCSIParallelFeature_InformationUnitTransfers ); 742 if ( supported == true ) 743 { 744 745 fITNexusSupportsFeature[kSCSIParallelFeature_InformationUnitTransfers] = true; 746 ITNexusFeatures |= (1 << kSCSIParallelFeature_InformationUnitTransfers); 747 748 } 749 750 } 751 752 if ( inqData[kINQUIRY_Byte56_Offset] & kINQUIRY_Byte56_QAS_Mask ) 753 { 754 755 deviceFeatures |= (1 << kSCSIParallelFeature_QuickArbitrationAndSelection); 756 supported = DoesHBASupportSCSIParallelFeature( kSCSIParallelFeature_QuickArbitrationAndSelection ); 757 if ( supported == true ) 758 { 759 760 fITNexusSupportsFeature[kSCSIParallelFeature_QuickArbitrationAndSelection] = true; 761 ITNexusFeatures |= (1 << kSCSIParallelFeature_QuickArbitrationAndSelection); 762 763 } 764 765 } 766 767 if ( ( ( inqData[kINQUIRY_Byte56_Offset] & kINQUIRY_Byte56_CLOCKING_Mask ) == kINQUIRY_Byte56_CLOCKING_ONLY_DT ) || 768 ( ( inqData[kINQUIRY_Byte56_Offset] & kINQUIRY_Byte56_CLOCKING_Mask ) == kINQUIRY_Byte56_CLOCKING_ST_AND_DT ) ) 769 { 770 771 deviceFeatures |= (1 << kSCSIParallelFeature_DoubleTransitionDataTransfers); 772 supported = DoesHBASupportSCSIParallelFeature ( kSCSIParallelFeature_DoubleTransitionDataTransfers ); 773 if ( supported == true ) 774 { 775 776 fITNexusSupportsFeature[kSCSIParallelFeature_DoubleTransitionDataTransfers] = true; 777 ITNexusFeatures |= (1 << kSCSIParallelFeature_DoubleTransitionDataTransfers); 778 779 } 780 781 } 782 783 } 784 785 copyDict = ( OSDictionary * ) copyProperty ( kIOPropertyProtocolCharacteristicsKey ); 786 if ( copyDict != NULL ) 787 { 788 789 dict = ( OSDictionary * ) copyDict->copyCollection ( ); 790 copyDict->release ( ); 791 792 } 793 794 if ( dict != NULL ) 795 { 796 797 features = OSNumber::withNumber ( deviceFeatures, 64 ); 798 if ( features != NULL ) 799 { 800 801 dict->setObject ( kIOPropertySCSIDeviceFeaturesKey, features ); 802 features->release ( ); 803 features = NULL; 804 805 } 806 807 features = OSNumber::withNumber ( ITNexusFeatures, 64 ); 808 if ( features != NULL ) 809 { 810 811 dict->setObject ( kIOPropertySCSI_I_T_NexusFeaturesKey, features ); 812 features->release ( ); 813 features = NULL; 814 815 } 816 817 setProperty ( kIOPropertyProtocolCharacteristicsKey, dict ); 818 dict->release ( ); 819 dict = NULL; 820 821 } 822 823} 824 825 826//----------------------------------------------------------------------------- 827// GetTargetIdentifier - Retrieves the SCSITargetIdentifier for this device. 828// [PUBLIC] 829//----------------------------------------------------------------------------- 830 831SCSITargetIdentifier 832IOSCSIParallelInterfaceDevice::GetTargetIdentifier ( void ) 833{ 834 return fTargetIdentifier; 835} 836 837 838//----------------------------------------------------------------------------- 839// GetHBADataPointer - Retrieves the pointer to the HBA Data for this device. 840// [PUBLIC] 841//----------------------------------------------------------------------------- 842 843void * 844IOSCSIParallelInterfaceDevice::GetHBADataPointer ( void ) 845{ 846 return fHBAData; 847} 848 849 850//----------------------------------------------------------------------------- 851// GetHBADataSize - Retrieves the HBA Data size for this device. [PUBLIC] 852//----------------------------------------------------------------------------- 853 854UInt32 855IOSCSIParallelInterfaceDevice::GetHBADataSize ( void ) 856{ 857 return fHBADataSize; 858} 859 860 861//----------------------------------------------------------------------------- 862// IsFeatureNegotiationNecessary - Checks if a feature negotiation is 863// necessary. [PUBLIC] 864//----------------------------------------------------------------------------- 865 866bool 867IOSCSIParallelInterfaceDevice::IsFeatureNegotiationNecessary ( 868 SCSIParallelFeature feature ) 869{ 870 // Verify that the requested feature is one that is known to 871 // the device object. 872 if ( feature >= kSCSIParallelFeature_TotalFeatureCount ) 873 { 874 return false; 875 } 876 877 return ( fITNexusSupportsFeature[feature] && 878 ( fFeatureIsNegotiated[feature] == false ) ); 879 880} 881 882 883//----------------------------------------------------------------------------- 884// FindTaskForAddress - Find the outstanding task for the Task Address of 885// this Target and the specified Lun and Tag. 886// [PUBLIC] 887//----------------------------------------------------------------------------- 888 889SCSIParallelTaskIdentifier 890IOSCSIParallelInterfaceDevice::FindTaskForAddress ( 891 SCSILogicalUnitNumber theL, 892 SCSITaggedTaskIdentifier theQ ) 893{ 894 895 SCSIParallelTask * task = NULL; 896 bool found = false; 897 898 // Grab the queue lock. 899 IOSimpleLockLock ( fQueueLock ); 900 901 // Iterate over all the commands in the list, looking for one that matches. 902 queue_iterate ( &fOutstandingTaskList, task, SCSIParallelTask *, fCommandChain ) 903 { 904 905 // Does this one match? 906 if ( ( GetLogicalUnitNumber ( task ) == theL ) && ( GetTaggedTaskIdentifier ( task ) == theQ ) ) 907 { 908 909 // Yes, stop searching. 910 found = true; 911 break; 912 913 } 914 915 } 916 917 IOSimpleLockUnlock ( fQueueLock ); 918 919 if ( found == false ) 920 { 921 task = NULL; 922 } 923 924 return task; 925 926} 927 928 929//----------------------------------------------------------------------------- 930// FindTaskForControllerIdentifier - Find the outstanding task for the 931// identifier. [PUBLIC] 932//----------------------------------------------------------------------------- 933 934SCSIParallelTaskIdentifier 935IOSCSIParallelInterfaceDevice::FindTaskForControllerIdentifier ( 936 UInt64 theIdentifier ) 937{ 938 939 940 SCSIParallelTask * task = NULL; 941 bool found = false; 942 943 // Grab the queue lock. 944 IOSimpleLockLock ( fQueueLock ); 945 946 // Iterate over all the commands in the list, looking for one that matches. 947 queue_iterate ( &fOutstandingTaskList, task, SCSIParallelTask *, fCommandChain ) 948 { 949 950 // Check if the request is to return the first element on the queue. 951 if ( theIdentifier == kSCSIParallelTaskControllerIDQueueHead ) 952 { 953 954 // The request is for the first element on the queue, this will 955 // break the first time through the while loop. 956 found = true; 957 break; 958 959 } 960 961 // Does this one match? 962 if ( GetControllerTaskIdentifier ( task ) == theIdentifier ) 963 { 964 965 // Yes, stop searching. 966 found = true; 967 break; 968 969 } 970 971 } 972 973 IOSimpleLockUnlock ( fQueueLock ); 974 975 if ( found == false ) 976 { 977 task = NULL; 978 } 979 980 return task; 981 982} 983 984 985//----------------------------------------------------------------------------- 986// SetTargetProperty - Sets a target property. [PUBLIC] 987//----------------------------------------------------------------------------- 988 989bool 990IOSCSIParallelInterfaceDevice::SetTargetProperty ( 991 const char * key, 992 OSObject * value ) 993{ 994 995 bool result = false; 996 OSDictionary * protocolDict = NULL; 997 OSDictionary * copyDict = NULL; 998 999 require_nonzero ( key, ErrorExit ); 1000 require_nonzero ( value, ErrorExit ); 1001 1002 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 1003 require_nonzero ( copyDict, ErrorExit ); 1004 1005 protocolDict = ( OSDictionary * ) copyDict->copyCollection ( ); 1006 copyDict->release ( ); 1007 1008 require_nonzero ( protocolDict, ErrorExit ); 1009 1010 if ( strcmp ( key, kIOPropertyFibreChannelPortWorldWideNameKey ) == 0 ) 1011 { 1012 1013 OSData * data = OSDynamicCast ( OSData, value ); 1014 1015 require_nonzero ( data, ErrorExit ); 1016 require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit ); 1017 result = protocolDict->setObject ( key, value ); 1018 result = protocolDict->setObject ( kIOPropertySCSIPortIdentifierKey, value ); 1019 1020 } 1021 1022 else if ( strcmp ( key, kIOPropertyFibreChannelNodeWorldWideNameKey ) == 0 ) 1023 { 1024 1025 OSData * data = OSDynamicCast ( OSData, value ); 1026 char name[27] = { 0 }; 1027 1028 require_nonzero ( data, ErrorExit ); 1029 require ( ( data->getLength ( ) == kWorldWideNameDataSize ), ErrorExit ); 1030 result = protocolDict->setObject ( key, value ); 1031 1032 snprintf ( name, sizeof ( name ), "FC Target %016qX", OSSwapHostToBigInt64 ( *( UInt64 * ) data->getBytesNoCopy ( ) ) ); 1033 setName ( name, gIOServicePlane ); 1034 1035 } 1036 1037 else if ( strcmp ( key, kIOPropertyFibreChannelAddressIdentifierKey ) == 0 ) 1038 { 1039 1040 OSData * data = OSDynamicCast ( OSData, value ); 1041 1042 require_nonzero ( data, ErrorExit ); 1043 require ( ( data->getLength ( ) == kAddressIdentifierDataSize ), ErrorExit ); 1044 result = protocolDict->setObject ( key, value ); 1045 1046 } 1047 1048 else if ( strcmp ( key, kIOPropertyFibreChannelALPAKey ) == 0 ) 1049 { 1050 1051 OSData * data = OSDynamicCast ( OSData, value ); 1052 1053 require_nonzero ( data, ErrorExit ); 1054 require ( ( data->getLength ( ) == kALPADataSize ), ErrorExit ); 1055 result = protocolDict->setObject ( key, value ); 1056 1057 } 1058 1059 else if ( strcmp ( key, kIOPropertySASAddressKey ) == 0 ) 1060 { 1061 1062 OSData * data = OSDynamicCast ( OSData, value ); 1063 char name[28] = { 0 }; 1064 1065 require_nonzero ( data, ErrorExit ); 1066 require ( ( data->getLength ( ) == kSASAddressDataSize ), ErrorExit ); 1067 result = protocolDict->setObject ( key, value ); 1068 result = protocolDict->setObject ( kIOPropertySCSIPortIdentifierKey, value ); 1069 1070 snprintf ( name, sizeof ( name ), "SAS Target %016qX", OSSwapHostToBigInt64 ( *( UInt64 * ) data->getBytesNoCopy ( ) ) ); 1071 setName ( name, gIOServicePlane ); 1072 1073 } 1074 1075 else if ( strcmp ( key, kIOPropertyRetryCountKey ) == 0 ) 1076 { 1077 1078 result = protocolDict->setObject ( key, value ); 1079 1080 } 1081 1082 setProperty ( kIOPropertyProtocolCharacteristicsKey, protocolDict ); 1083 protocolDict->release ( ); 1084 protocolDict = NULL; 1085 1086 1087ErrorExit: 1088 1089 1090 return result; 1091 1092} 1093 1094 1095//----------------------------------------------------------------------------- 1096// RemoveTargetProperty - Removes a property for this object. [PUBLIC] 1097//----------------------------------------------------------------------------- 1098 1099void 1100IOSCSIParallelInterfaceDevice::RemoveTargetProperty ( const char * key ) 1101{ 1102 1103 OSDictionary * protocolDict = NULL; 1104 OSDictionary * copyDict = NULL; 1105 1106 require_nonzero ( key, ErrorExit ); 1107 1108 copyDict = OSDynamicCast ( OSDictionary, copyProperty ( kIOPropertyProtocolCharacteristicsKey ) ); 1109 require_nonzero ( copyDict, ErrorExit ); 1110 1111 protocolDict = ( OSDictionary * ) copyDict->copyCollection ( ); 1112 copyDict->release ( ); 1113 1114 require_nonzero ( protocolDict, ErrorExit ); 1115 1116 if ( protocolDict->getObject ( key ) != NULL ) 1117 { 1118 1119 protocolDict->removeObject ( key ); 1120 1121 } 1122 1123 setProperty ( kIOPropertyProtocolCharacteristicsKey, protocolDict ); 1124 protocolDict->release ( ); 1125 protocolDict = NULL; 1126 1127 1128ErrorExit: 1129 1130 1131 return; 1132 1133} 1134 1135 1136#if 0 1137#pragma mark - 1138#pragma mark SCSI Protocol Services Member Routines 1139#pragma mark - 1140#endif 1141 1142 1143//----------------------------------------------------------------------------- 1144// SendSCSICommand - Sends a command to the controller. [PUBLIC] 1145//----------------------------------------------------------------------------- 1146 1147bool 1148IOSCSIParallelInterfaceDevice::SendSCSICommand ( 1149 SCSITaskIdentifier request, 1150 SCSIServiceResponse * serviceResponse, 1151 SCSITaskStatus * taskStatus ) 1152{ 1153 1154 SCSIParallelTaskIdentifier parallelTask = NULL; 1155 IOMemoryDescriptor * buffer = NULL; 1156 IOReturn status = kIOReturnBadArgument; 1157 IOWorkLoop * workLoop = NULL; 1158 bool block = true; 1159 1160 // Set the defaults to an error state. 1161 *taskStatus = kSCSITaskStatus_No_Status; 1162 *serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; 1163 1164 if ( isInactive ( ) == true ) 1165 { 1166 1167 return false; 1168 1169 } 1170 1171 // Check if there is an SCSIParallelTask available to allow the request 1172 // to be sent to the device. If we don't block on the client thread, we 1173 // risk the chance of never being able to send an I/O to the controller for 1174 // this device. 1175 // 1176 // But, we can't block the ISR either. Depending on what thread we're on, 1177 // we have to make the right decision here. 1178 workLoop = getWorkLoop ( ); 1179 if ( workLoop != NULL ) 1180 { 1181 1182 if ( workLoop->onThread ( ) ) 1183 { 1184 block = false; 1185 } 1186 1187 } 1188 1189 parallelTask = GetSCSIParallelTask ( block ); 1190 if ( parallelTask == NULL ) 1191 { 1192 1193 // A SCSI Parallel Task could not be obtained, report 1194 // that the task was not executed and wait for a task to complete. 1195 return false; 1196 1197 } 1198 1199 SetTargetIdentifier ( parallelTask, fTargetIdentifier ); 1200 SetDevice ( parallelTask, this ); 1201 1202 // Do the 2-way association, so that we can reference the SCSITask from 1203 // SCSIParallelTask and vice-versa. 1204 SetSCSITaskIdentifier ( parallelTask, request ); 1205 SetProtocolLayerReference ( request, parallelTask ); 1206 1207 // Set the Parallel SCSI transfer features. 1208 for ( UInt32 index = 0; index < kSCSIParallelFeature_TotalFeatureCount; index++ ) 1209 { 1210 1211 // Set each one to false. 1212 if ( IsFeatureNegotiationNecessary ( ( SCSIParallelFeature ) index ) == true ) 1213 { 1214 1215 SetSCSIParallelFeatureNegotiation ( 1216 parallelTask, 1217 ( SCSIParallelFeature ) index, 1218 kSCSIParallelFeature_AttemptNegotiation ); 1219 1220 } 1221 1222 } 1223 1224 // Add the task to the outstanding task list. 1225 AddToOutstandingTaskList ( parallelTask ); 1226 1227 // Set the buffer for IODMACommand. 1228 buffer = GetDataBuffer ( parallelTask ); 1229 if ( buffer != NULL ) 1230 { 1231 1232 status = SetDMABuffer ( parallelTask, buffer ); 1233 if ( status != kIOReturnSuccess ) 1234 { 1235 1236 ERROR_LOG ( ( "SetDMABuffer failed, status = 0x%08x\n", status ) ); 1237 1238 RemoveFromOutstandingTaskList ( parallelTask ); 1239 1240 // Release the SCSI Parallel Task object 1241 FreeSCSIParallelTask ( parallelTask ); 1242 1243 CommandCompleted ( request, *serviceResponse, *taskStatus ); 1244 1245 return true; 1246 1247 } 1248 1249 } 1250 1251 *serviceResponse = ExecuteParallelTask ( parallelTask ); 1252 if ( *serviceResponse != kSCSIServiceResponse_Request_In_Process ) 1253 { 1254 1255 // The task has already completed 1256 RemoveFromOutstandingTaskList ( parallelTask ); 1257 1258 // Release the SCSI Parallel Task object 1259 FreeSCSIParallelTask ( parallelTask ); 1260 1261 // Since we are completing the command IOSCSIProtocolServices 1262 // should not process the command any more 1263 *serviceResponse = kSCSIServiceResponse_Request_In_Process; 1264 1265 if ( isInactive ( ) == true ) 1266 { 1267 1268 *taskStatus = kSCSITaskStatus_DeviceNotPresent; 1269 1270 } 1271 1272 CommandCompleted ( request, kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE, *taskStatus ); 1273 1274 } 1275 1276 return true; 1277 1278} 1279 1280 1281//----------------------------------------------------------------------------- 1282// CompleteSCSITask - Completes a command from the controller. [PUBLIC] 1283//----------------------------------------------------------------------------- 1284 1285void 1286IOSCSIParallelInterfaceDevice::CompleteSCSITask ( 1287 SCSIParallelTaskIdentifier completedTask, 1288 SCSIServiceResponse serviceResponse, 1289 SCSITaskStatus completionStatus ) 1290{ 1291 1292 SCSITaskIdentifier clientRequest = NULL; 1293 SCSIParallelTask * task = ( SCSIParallelTask * ) completedTask; 1294 UInt8 retryCount = task->fTaskRetryCount; 1295 1296 if ( completedTask == NULL ) 1297 { 1298 1299 // The driver was asked to complete an invalid task, 1300 // there is nothing it can do so just return. 1301 return; 1302 1303 } 1304 1305 // Check if the device rejected the task because its queue is full. 1306 if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) && 1307 ( completionStatus == kSCSITaskStatus_TASK_SET_FULL ) && 1308 ( fAllowResends == true ) && 1309 ( retryCount < kMaxTaskRetryCount ) ) 1310 { 1311 1312 // The task was not executed because the device reported 1313 // a TASK_SET_FULL, place it on the resend queue and wait for 1314 // a task to complete with a status other than TASK_SET_FULL. 1315 AddToResendTaskList ( completedTask ); 1316 1317 // Done for now. 1318 return; 1319 1320 } 1321 1322 // Make sure that the task is removed from the outstanding task list 1323 // so that the driver no longer sees this task as outstanding. 1324 RemoveFromOutstandingTaskList ( completedTask ); 1325 1326 // Retrieve the original SCSI Task. 1327 clientRequest = GetSCSITaskIdentifier ( completedTask ); 1328 if ( clientRequest == NULL ) 1329 { 1330 panic ( "IOSCSIParallelInterfaceDevice::CompleteSCSITask: clientRequest is NULL, completedTask = %p\n", completedTask ); 1331 } 1332 1333 // Set the appropriate fields in the SCSI Task. 1334 IOSCSIProtocolServices::SetRealizedDataTransferCount ( clientRequest, GetRealizedDataTransferCount ( completedTask ) ); 1335 1336 // Store any negotiations that were done. 1337 for ( UInt32 index = 0; index < kSCSIParallelFeature_TotalFeatureCount; index++ ) 1338 { 1339 1340 // Set each one to false. 1341 if ( IsFeatureNegotiationNecessary ( ( SCSIParallelFeature ) index ) == true ) 1342 { 1343 1344 if ( GetSCSIParallelFeatureNegotiationResult ( completedTask, ( SCSIParallelFeature ) index ) == 1345 kSCSIParallelFeature_NegotitiationSuccess ) 1346 { 1347 fFeatureIsNegotiated[index] = true; 1348 } 1349 1350 } 1351 1352 } 1353 1354 // Release the SCSI Parallel Task object. 1355 FreeSCSIParallelTask ( completedTask ); 1356 1357 IOSimpleLockLock ( fQueueLock ); 1358 1359 // If there are requests on the resend queue, send them first. 1360 // Currently only the element at the head of the queue will be sent. 1361 // If the desire is to allow all elements to be sent, the break 1362 // statement can be removed. 1363 while ( !queue_empty ( &fResendTaskList ) ) 1364 { 1365 1366 SCSIParallelTaskIdentifier parallelTask; 1367 SCSIParallelTask * task = NULL; 1368 1369 parallelTask = ( SCSIParallelTaskIdentifier ) queue_first ( &fResendTaskList ); 1370 1371 task = ( SCSIParallelTask * ) parallelTask ; 1372 1373 queue_remove ( &fResendTaskList, task, SCSIParallelTask *, fResendTaskChain ); 1374 1375 IOSimpleLockUnlock ( fQueueLock ); 1376 1377 1378 if ( ExecuteParallelTask ( parallelTask ) != kSCSIServiceResponse_Request_In_Process ) 1379 { 1380 1381 SCSITaskIdentifier nextRequest = NULL; 1382 1383 // The task has already completed 1384 RemoveFromOutstandingTaskList ( parallelTask ); 1385 1386 nextRequest = GetSCSITaskIdentifier ( parallelTask ); 1387 1388 // Release the SCSI Parallel Task object 1389 FreeSCSIParallelTask ( parallelTask ); 1390 1391 CommandCompleted ( nextRequest, kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE, kSCSITaskStatus_No_Status ); 1392 1393 1394 IOSimpleLockLock ( fQueueLock ); 1395 1396 // Since this command has already completed, start the next 1397 // one on the queue. 1398 continue; 1399 1400 } 1401 1402 else 1403 { 1404 1405 IOSimpleLockLock ( fQueueLock ); 1406 1407 // A command was successfully sent, wait for it to complete 1408 // before sending the next one. 1409 break; 1410 1411 } 1412 1413 } 1414 1415 IOSimpleLockUnlock ( fQueueLock ); 1416 1417 // If the IO completed with TASK_SET_FULL but has exhausted its max retries, 1418 // complete it with taskStatus BUSY. The upper layer will retry it again. 1419 if ( ( serviceResponse == kSCSIServiceResponse_TASK_COMPLETE ) && 1420 ( completionStatus == kSCSITaskStatus_TASK_SET_FULL ) && 1421 ( retryCount >= kMaxTaskRetryCount ) ) 1422 { 1423 1424 CommandCompleted ( clientRequest, kSCSIServiceResponse_TASK_COMPLETE, kSCSITaskStatus_BUSY ); 1425 1426 } 1427 1428 else 1429 { 1430 1431 // Inform the client that the task has been executed. 1432 CommandCompleted ( clientRequest, serviceResponse, completionStatus ); 1433 1434 } 1435 1436} 1437 1438 1439#if 0 1440#pragma mark - 1441#pragma mark SCSI Protocol Service Feature routines 1442#pragma mark - 1443#endif 1444 1445 1446//----------------------------------------------------------------------------- 1447// IsProtocolServiceSupported - Called by SCSI Application Layer to determine 1448// if the protocol layer driver supports a 1449// SCSIProtocolFeature. [PUBLIC] 1450//----------------------------------------------------------------------------- 1451 1452bool 1453IOSCSIParallelInterfaceDevice::IsProtocolServiceSupported ( 1454 SCSIProtocolFeature feature, 1455 void * value ) 1456{ 1457 1458 bool isSupported = false; 1459 1460 require ( ( isInactive ( ) == false ), ErrorExit ); 1461 require_nonzero ( fController, ErrorExit ); 1462 1463 switch ( feature ) 1464 { 1465 1466 case kSCSIProtocolFeature_GetMaximumLogicalUnitNumber: 1467 { 1468 1469 isSupported = true; 1470 *( UInt32 * ) value = fController->ReportHBAHighestLogicalUnitNumber ( ); 1471 1472 } 1473 break; 1474 1475 case kSCSIProtocolFeature_SubmitDefaultInquiryData: 1476 { 1477 isSupported = true; 1478 } 1479 break; 1480 1481 case kSCSIProtocolFeature_ProtocolAlwaysReportsAutosenseData: 1482 { 1483 isSupported = fController->DoesHBAPerformAutoSense ( ); 1484 } 1485 break; 1486 1487 case kSCSIProtocolFeature_HierarchicalLogicalUnits: 1488 { 1489 1490 OSBoolean * obj = NULL; 1491 1492 obj = OSDynamicCast ( OSBoolean, fController->getProperty ( kIOHierarchicalLogicalUnitSupportKey ) ); 1493 1494 if ( ( obj != NULL ) && ( obj->isTrue ( ) ) ) 1495 { 1496 isSupported = true; 1497 } 1498 1499 } 1500 break; 1501 1502 case kSCSIProtocolFeature_MultiPathing: 1503 { 1504 isSupported = fMultiPathSupport; 1505 } 1506 break; 1507 1508 default: 1509 { 1510 // Since isSupported is set to false by default, there is 1511 // nothing that needs to be done for the default case. 1512 } 1513 break; 1514 1515 } 1516 1517 1518ErrorExit: 1519 1520 1521 return isSupported; 1522 1523} 1524 1525 1526//----------------------------------------------------------------------------- 1527// HandleProtocolServiceFeature - Called by SCSI Application Layer to handle 1528// a SCSIProtocolFeature. [PUBLIC] 1529//----------------------------------------------------------------------------- 1530bool 1531IOSCSIParallelInterfaceDevice::HandleProtocolServiceFeature ( 1532 SCSIProtocolFeature feature, 1533 void * serviceValue ) 1534{ 1535 1536 bool wasHandled = false; 1537 1538 switch ( feature ) 1539 { 1540 1541 case kSCSIProtocolFeature_SubmitDefaultInquiryData: 1542 { 1543 1544 DetermineParallelFeatures ( ( UInt8 * ) serviceValue ); 1545 wasHandled = true; 1546 1547 // Put us in the IORegistry so we can be found by utilities like 1548 // System Profiler easily. 1549 registerService ( ); 1550 1551 } 1552 break; 1553 1554 default: 1555 { 1556 break; 1557 } 1558 1559 } 1560 1561 return wasHandled; 1562 1563} 1564 1565 1566#if 0 1567#pragma mark - 1568#pragma mark SCSI Task Management Functions 1569#pragma mark - 1570#endif 1571 1572 1573//----------------------------------------------------------------------------- 1574// AbortSCSICommand - Not used. [OBSOLETE][PUBLIC] 1575//----------------------------------------------------------------------------- 1576 1577SCSIServiceResponse 1578IOSCSIParallelInterfaceDevice::AbortSCSICommand ( 1579 SCSITaskIdentifier request ) 1580{ 1581 return kSCSIServiceResponse_FUNCTION_REJECTED; 1582} 1583 1584 1585//----------------------------------------------------------------------------- 1586// HandleAbortTask - Calls controller to perform abort task. [PROTECTED] 1587//----------------------------------------------------------------------------- 1588 1589SCSIServiceResponse 1590IOSCSIParallelInterfaceDevice::HandleAbortTask ( 1591 UInt8 theLogicalUnit, 1592 SCSITaggedTaskIdentifier theTag ) 1593{ 1594 return fController->AbortTaskRequest ( fTargetIdentifier, theLogicalUnit, theTag ); 1595} 1596 1597 1598//----------------------------------------------------------------------------- 1599// HandleAbortTaskSet - Calls controller to perform abort task set. 1600// [PROTECTED] 1601//----------------------------------------------------------------------------- 1602 1603SCSIServiceResponse 1604IOSCSIParallelInterfaceDevice::HandleAbortTaskSet ( 1605 UInt8 theLogicalUnit ) 1606{ 1607 return fController->AbortTaskSetRequest ( fTargetIdentifier, theLogicalUnit ); 1608} 1609 1610 1611//----------------------------------------------------------------------------- 1612// HandleClearACA - Calls controller to perform Clear ACA. [PROTECTED] 1613//----------------------------------------------------------------------------- 1614 1615SCSIServiceResponse 1616IOSCSIParallelInterfaceDevice::HandleClearACA ( 1617 UInt8 theLogicalUnit ) 1618{ 1619 return fController->ClearACARequest ( fTargetIdentifier, theLogicalUnit ); 1620} 1621 1622 1623//----------------------------------------------------------------------------- 1624// HandleClearTaskSet - Calls controller to perform clear task set. 1625// [PROTECTED] 1626//----------------------------------------------------------------------------- 1627 1628SCSIServiceResponse 1629IOSCSIParallelInterfaceDevice::HandleClearTaskSet ( 1630 UInt8 theLogicalUnit ) 1631{ 1632 return fController->ClearTaskSetRequest ( fTargetIdentifier, theLogicalUnit ); 1633} 1634 1635 1636//----------------------------------------------------------------------------- 1637// HandleLogicalUnitReset - Calls controller to perform LUN reset. [PROTECTED] 1638//----------------------------------------------------------------------------- 1639 1640SCSIServiceResponse 1641IOSCSIParallelInterfaceDevice::HandleLogicalUnitReset ( 1642 UInt8 theLogicalUnit ) 1643{ 1644 return fController->LogicalUnitResetRequest ( fTargetIdentifier, theLogicalUnit ); 1645} 1646 1647 1648//----------------------------------------------------------------------------- 1649// HandleTargetReset - Calls controller to perform Target reset. [PROTECTED] 1650//----------------------------------------------------------------------------- 1651 1652SCSIServiceResponse 1653IOSCSIParallelInterfaceDevice::HandleTargetReset ( void ) 1654{ 1655 return fController->TargetResetRequest ( fTargetIdentifier ); 1656} 1657 1658 1659#if 0 1660#pragma mark - 1661#pragma mark Controller Object Accessors 1662#pragma mark - 1663#endif 1664 1665 1666//----------------------------------------------------------------------------- 1667// ExecuteParallelTask - Called to issue a task to the controller. [PROTECTED] 1668//----------------------------------------------------------------------------- 1669 1670SCSIServiceResponse 1671IOSCSIParallelInterfaceDevice::ExecuteParallelTask ( 1672 SCSIParallelTaskIdentifier parallelRequest ) 1673{ 1674 return fController->ExecuteParallelTask ( parallelRequest ); 1675} 1676 1677 1678//----------------------------------------------------------------------------- 1679// GetSCSIParallelTask - Gets a SCSIParallelTaskIdentifier from the 1680// controller's command pool. [PROTECTED] 1681//----------------------------------------------------------------------------- 1682 1683SCSIParallelTaskIdentifier 1684IOSCSIParallelInterfaceDevice::GetSCSIParallelTask ( bool blockForCommand ) 1685{ 1686 return fController->GetSCSIParallelTask ( blockForCommand ); 1687} 1688 1689 1690//----------------------------------------------------------------------------- 1691// FreeSCSIParallelTask - Returns a SCSIParallelTaskIdentifier to the 1692// controller's command pool. [PROTECTED] 1693//----------------------------------------------------------------------------- 1694 1695void 1696IOSCSIParallelInterfaceDevice::FreeSCSIParallelTask ( 1697 SCSIParallelTaskIdentifier returnTask ) 1698{ 1699 return fController->FreeSCSIParallelTask ( returnTask ); 1700} 1701 1702 1703//----------------------------------------------------------------------------- 1704// DoesHBASupportSCSIParallelFeature - Queries the controller if a 1705// specific SCSIParallelFeature is 1706// supported. [PROTECTED] 1707//----------------------------------------------------------------------------- 1708 1709bool 1710IOSCSIParallelInterfaceDevice::DoesHBASupportSCSIParallelFeature ( 1711 SCSIParallelFeature theFeature ) 1712{ 1713 return fController->DoesHBASupportSCSIParallelFeature ( theFeature ); 1714} 1715 1716 1717#if 0 1718#pragma mark - 1719#pragma mark SCSI Parallel Task Object Accessors 1720#pragma mark - 1721#endif 1722 1723 1724//----------------------------------------------------------------------------- 1725// AddToOutstandingTaskList - Adds a task to the outstanding task list. 1726// [PROTECTED] 1727//----------------------------------------------------------------------------- 1728 1729bool 1730IOSCSIParallelInterfaceDevice::AddToOutstandingTaskList ( 1731 SCSIParallelTaskIdentifier parallelTask ) 1732{ 1733 1734 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 1735 1736 if ( task == NULL ) 1737 { 1738 return false; 1739 } 1740 1741 IOSimpleLockLock ( fQueueLock ); 1742 1743 queue_enter ( &fOutstandingTaskList, task, SCSIParallelTask *, fCommandChain ); 1744 1745 IOSimpleLockUnlock ( fQueueLock ); 1746 1747 return true; 1748 1749} 1750 1751 1752//----------------------------------------------------------------------------- 1753// RemoveFromOutstandingTaskList - Removes a task from the outstanding 1754// task list. [PROTECTED] 1755//----------------------------------------------------------------------------- 1756 1757void 1758IOSCSIParallelInterfaceDevice::RemoveFromOutstandingTaskList ( 1759 SCSIParallelTaskIdentifier parallelTask ) 1760{ 1761 1762 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 1763 1764 require_nonzero ( ( task->fCommandChain.next ), Exit ); 1765 require_nonzero ( ( task->fCommandChain.prev ), Exit ); 1766 1767 IOSimpleLockLock ( fQueueLock ); 1768 1769 require ( ( queue_empty ( &fOutstandingTaskList ) == false ), ExitLocked ); 1770 1771 queue_remove ( &fOutstandingTaskList, task, SCSIParallelTask *, fCommandChain ); 1772 1773 1774ExitLocked: 1775 1776 1777 IOSimpleLockUnlock ( fQueueLock ); 1778 1779 1780Exit: 1781 1782 1783 return; 1784 1785} 1786 1787 1788//----------------------------------------------------------------------------- 1789// AddToResendTaskList - Adds a task to the resend (TASK_SET_FULL) task list. 1790// [PROTECTED] 1791//----------------------------------------------------------------------------- 1792 1793bool 1794IOSCSIParallelInterfaceDevice::AddToResendTaskList ( 1795 SCSIParallelTaskIdentifier parallelTask ) 1796{ 1797 1798 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 1799 thread_t thread = THREAD_NULL; 1800 1801 if ( task == NULL ) 1802 { 1803 return false; 1804 } 1805 1806 IOSimpleLockLock ( fQueueLock ); 1807 1808 task->fTaskRetryCount++; 1809 1810 queue_enter ( &fResendTaskList, task, SCSIParallelTask *, fResendTaskChain ); 1811 1812 // Some targets return TASK SET FULL even if they have no other pending 1813 // IOs from the I-T nexus. In this case we don't want that IO to sit 1814 // in a limbo on the fResendTaskList. So we start a thread that will drive 1815 // the list. 1816 if ( fResendThreadScheduled == false ) 1817 { 1818 1819 fResendThreadScheduled = true; 1820 1821 IOSimpleLockUnlock ( fQueueLock ); 1822 1823 retain ( ); 1824 1825 kernel_thread_start ( 1826 OSMemberFunctionCast ( 1827 thread_continue_t, 1828 this, 1829 &IOSCSIParallelInterfaceDevice::SendFromResendTaskList ), 1830 this, 1831 &thread ); 1832 1833 } 1834 1835 else 1836 { 1837 IOSimpleLockUnlock ( fQueueLock ); 1838 } 1839 1840 return true; 1841 1842} 1843 1844 1845//----------------------------------------------------------------------------- 1846// SendFromResendTaskList - Drives the Resend Task List. 1847// [PROTECTED] 1848//----------------------------------------------------------------------------- 1849 1850void 1851IOSCSIParallelInterfaceDevice::SendFromResendTaskList ( void ) 1852{ 1853 1854 thread_t thread = THREAD_NULL; 1855 SCSIParallelTaskIdentifier parallelTask = NULL; 1856 SCSIParallelTask * task = NULL; 1857 1858 // Sleep for 10 seconds before driving the queue 1859 // only if we are not terminating. 1860 if ( fAllowResends == true ) 1861 { 1862 1863 // Wait 10 seconds before driving the list. 1864 IOSleep ( 10000 ); 1865 1866 } 1867 1868 1869 IOSimpleLockLock ( fQueueLock ); 1870 1871 // If there are requests on the resend queue, send them first. 1872 // Currently only the element at the head of the queue will be sent. 1873 // If the desire is to allow all elements to be sent, the break 1874 // statement can be removed. 1875 1876 while ( !queue_empty ( &fResendTaskList ) ) 1877 { 1878 1879 parallelTask = ( SCSIParallelTaskIdentifier ) queue_first ( &fResendTaskList ); 1880 1881 task = ( SCSIParallelTask * ) parallelTask; 1882 1883 queue_remove ( &fResendTaskList, task, SCSIParallelTask *, fResendTaskChain ); 1884 1885 IOSimpleLockUnlock ( fQueueLock ); 1886 1887 // If Device is not destroyed, send command to device, else 1888 // complete the command with error. 1889 if ( fAllowResends == true ) 1890 { 1891 1892 if ( ExecuteParallelTask ( parallelTask ) == kSCSIServiceResponse_Request_In_Process ) 1893 { 1894 1895 IOSimpleLockLock ( fQueueLock ); 1896 1897 // A command was successfully sent. 1898 // The next IO in the Resend task list will be driven when 1899 // this completes. 1900 break; 1901 1902 } 1903 1904 } 1905 1906 SCSITaskIdentifier nextRequest = NULL; 1907 1908 // The task has already completed 1909 RemoveFromOutstandingTaskList ( parallelTask ); 1910 1911 nextRequest = GetSCSITaskIdentifier ( parallelTask ); 1912 1913 // Release the SCSI Parallel Task object 1914 FreeSCSIParallelTask ( parallelTask ); 1915 1916 // Return taskStatus BUSY so that upper layer will retry the IO. 1917 CommandCompleted ( nextRequest, kSCSIServiceResponse_TASK_COMPLETE, kSCSITaskStatus_BUSY ); 1918 1919 IOSimpleLockLock ( fQueueLock ); 1920 1921 // Since this command has already completed, start the next 1922 // one on the queue. 1923 continue; 1924 1925 } 1926 1927 fResendThreadScheduled = false; 1928 1929 IOSimpleLockUnlock ( fQueueLock ); 1930 1931 // Release our retain held while starting thread. 1932 release ( ); 1933 1934 // Terminate the thread. 1935 thread = current_thread ( ); 1936 thread_deallocate ( thread ); 1937 thread_terminate ( thread ); 1938 1939} 1940 1941 1942//----------------------------------------------------------------------------- 1943// RemoveFromOutstandingTaskList - Removes a task from the resend task 1944// (TASK_SET_FULL) list. [PROTECTED] 1945//----------------------------------------------------------------------------- 1946 1947void 1948IOSCSIParallelInterfaceDevice::RemoveFromResendTaskList ( 1949 SCSIParallelTaskIdentifier parallelTask ) 1950{ 1951 1952 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 1953 1954 require_nonzero ( ( task->fResendTaskChain.next ), Exit ); 1955 require_nonzero ( ( task->fResendTaskChain.prev ), Exit ); 1956 1957 IOSimpleLockLock ( fQueueLock ); 1958 1959 require ( ( queue_empty ( &fResendTaskList ) == false ), ExitLocked ); 1960 1961 queue_remove ( &fResendTaskList, task, SCSIParallelTask *, fResendTaskChain ); 1962 1963 1964ExitLocked: 1965 1966 1967 IOSimpleLockUnlock ( fQueueLock ); 1968 1969 1970Exit: 1971 1972 1973 return; 1974 1975} 1976 1977 1978//----------------------------------------------------------------------------- 1979// SetSCSITaskIdentifier - Sets the SCSITaskIdentifier in the 1980// parallelTask. [PROTECTED] 1981//----------------------------------------------------------------------------- 1982 1983bool 1984IOSCSIParallelInterfaceDevice::SetSCSITaskIdentifier ( 1985 SCSIParallelTaskIdentifier parallelTask, 1986 SCSITaskIdentifier scsiRequest ) 1987{ 1988 1989 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 1990 1991 if ( task == NULL ) 1992 { 1993 return false; 1994 } 1995 1996 return task->SetSCSITaskIdentifier ( scsiRequest ); 1997 1998} 1999 2000 2001//----------------------------------------------------------------------------- 2002// GetSCSITaskIdentifier - Retrieves the SCSITaskIdentifier from the 2003// parallelTask. [PROTECTED] 2004//----------------------------------------------------------------------------- 2005 2006SCSITaskIdentifier 2007IOSCSIParallelInterfaceDevice::GetSCSITaskIdentifier ( 2008 SCSIParallelTaskIdentifier parallelTask ) 2009{ 2010 2011 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2012 2013 if ( task == NULL ) 2014 { 2015 return NULL; 2016 } 2017 2018 return task->GetSCSITaskIdentifier ( ); 2019 2020} 2021 2022 2023//----------------------------------------------------------------------------- 2024// SetDevice - Sets the device in the parallelTask. [PROTECTED] 2025//----------------------------------------------------------------------------- 2026 2027bool 2028IOSCSIParallelInterfaceDevice::SetDevice ( 2029 SCSIParallelTaskIdentifier parallelTask, 2030 IOSCSIParallelInterfaceDevice * device ) 2031{ 2032 2033 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2034 2035 if ( task == NULL ) 2036 { 2037 return false; 2038 } 2039 2040 return task->SetDevice ( device ); 2041 2042} 2043 2044 2045//----------------------------------------------------------------------------- 2046// SetTargetIdentifier - Sets the SCSITargetIdentifier in the 2047// parallelTask. [PROTECTED] 2048//----------------------------------------------------------------------------- 2049 2050bool 2051IOSCSIParallelInterfaceDevice::SetTargetIdentifier ( 2052 SCSIParallelTaskIdentifier parallelTask, 2053 SCSITargetIdentifier theTargetID ) 2054{ 2055 2056 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2057 2058 if ( task == NULL ) 2059 { 2060 return false; 2061 } 2062 2063 return task->SetTargetIdentifier ( theTargetID ); 2064 2065} 2066 2067 2068//----------------------------------------------------------------------------- 2069// GetTargetIdentifier - Retrieves the SCSITargetIdentifier from the 2070// parallelTask. [PROTECTED] 2071//----------------------------------------------------------------------------- 2072 2073SCSITargetIdentifier 2074IOSCSIParallelInterfaceDevice::GetTargetIdentifier ( 2075 SCSIParallelTaskIdentifier parallelTask ) 2076{ 2077 2078 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2079 2080 if ( task == NULL ) 2081 { 2082 return NULL; 2083 } 2084 2085 return task->GetTargetIdentifier ( ); 2086 2087} 2088 2089 2090//----------------------------------------------------------------------------- 2091// SetDMABuffer - Sets the DMA buffer in the task. [PROTECTED] 2092//----------------------------------------------------------------------------- 2093 2094IOReturn 2095IOSCSIParallelInterfaceDevice::SetDMABuffer ( 2096 SCSIParallelTaskIdentifier parallelTask, 2097 IOMemoryDescriptor * buffer ) 2098{ 2099 2100 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2101 2102 if ( task == NULL ) 2103 { 2104 return NULL; 2105 } 2106 2107 return task->SetBuffer ( buffer ); 2108 2109} 2110 2111 2112// ---- Methods for Accessing data in the client's SCSI Task Object ---- 2113// Method to retrieve the LUN that identifies the Logical Unit whose Task 2114// Set to which this task is to be added. 2115// --> Currently this only supports Level 1 Addressing, complete 2116// Hierachal LUN addressing will need to be added to the SCSI Task object 2117// and the Peripheral Device Type objects which will represent Logical Units. 2118// Since that will be completed before this is released, this method will be 2119// changed at that time. 2120 2121//----------------------------------------------------------------------------- 2122// GetLogicalUnitNumber - Retrieves the SCSILogicalUnitNumber from the 2123// parallelTask. [PROTECTED] 2124//----------------------------------------------------------------------------- 2125 2126SCSILogicalUnitNumber 2127IOSCSIParallelInterfaceDevice::GetLogicalUnitNumber ( 2128 SCSIParallelTaskIdentifier parallelTask ) 2129{ 2130 2131 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2132 2133 if ( task == NULL ) 2134 { 2135 return 0; 2136 } 2137 2138 return task->GetLogicalUnitNumber ( ); 2139 2140} 2141 2142 2143//----------------------------------------------------------------------------- 2144// GetTaggedTaskIdentifier - Retrieves the SCSITaggedTaskIdentifier from the 2145// parallelTask. [PROTECTED] 2146//----------------------------------------------------------------------------- 2147 2148SCSITaggedTaskIdentifier 2149IOSCSIParallelInterfaceDevice::GetTaggedTaskIdentifier ( 2150 SCSIParallelTaskIdentifier parallelTask ) 2151{ 2152 2153 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2154 2155 if ( task == NULL ) 2156 { 2157 return kSCSIUntaggedTaskIdentifier; 2158 } 2159 2160 return task->GetTaggedTaskIdentifier ( ); 2161 2162} 2163 2164 2165//----------------------------------------------------------------------------- 2166// GetTaskAttribute - Retrieves the SCSITaskAttribute from the parallelTask. 2167// [PROTECTED] 2168//----------------------------------------------------------------------------- 2169 2170SCSITaskAttribute 2171IOSCSIParallelInterfaceDevice::GetTaskAttribute ( 2172 SCSIParallelTaskIdentifier parallelTask ) 2173{ 2174 2175 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2176 2177 if ( task == NULL ) 2178 { 2179 return kSCSITask_SIMPLE; 2180 } 2181 2182 return task->GetTaskAttribute ( ); 2183 2184} 2185 2186 2187//----------------------------------------------------------------------------- 2188// GetCommandDescriptorBlockSize - Retrieves the CDB size from the 2189// parallelTask. [PROTECTED] 2190//----------------------------------------------------------------------------- 2191 2192UInt8 2193IOSCSIParallelInterfaceDevice::GetCommandDescriptorBlockSize ( 2194 SCSIParallelTaskIdentifier parallelTask ) 2195{ 2196 2197 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2198 2199 if ( task == NULL ) 2200 { 2201 return 0; 2202 } 2203 2204 return task->GetCommandDescriptorBlockSize ( ); 2205 2206} 2207 2208 2209//----------------------------------------------------------------------------- 2210// GetCommandDescriptorBlockSize - Retrieves the CDB from the parallelTask. 2211// [PROTECTED] 2212//----------------------------------------------------------------------------- 2213 2214bool 2215IOSCSIParallelInterfaceDevice::GetCommandDescriptorBlock ( 2216 SCSIParallelTaskIdentifier parallelTask, 2217 SCSICommandDescriptorBlock * cdbData ) 2218{ 2219 2220 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2221 2222 if ( task == NULL ) 2223 { 2224 return false; 2225 } 2226 2227 return task->GetCommandDescriptorBlock ( cdbData ); 2228 2229} 2230 2231 2232//----------------------------------------------------------------------------- 2233// GetDataTransferDirection - Retrieves the data transfer direction from 2234// the parallelTask. [PROTECTED] 2235//----------------------------------------------------------------------------- 2236 2237UInt8 2238IOSCSIParallelInterfaceDevice::GetDataTransferDirection ( 2239 SCSIParallelTaskIdentifier parallelTask ) 2240{ 2241 2242 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2243 2244 if ( task == NULL ) 2245 { 2246 return kSCSIDataTransfer_NoDataTransfer; 2247 } 2248 2249 return task->GetDataTransferDirection ( ); 2250 2251} 2252 2253 2254//----------------------------------------------------------------------------- 2255// GetRequestedDataTransferCount - Retrieves the requested data transfer 2256// count from the parallelTask. [PROTECTED] 2257//----------------------------------------------------------------------------- 2258 2259UInt64 2260IOSCSIParallelInterfaceDevice::GetRequestedDataTransferCount ( 2261 SCSIParallelTaskIdentifier parallelTask ) 2262{ 2263 2264 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2265 2266 if ( task == NULL ) 2267 { 2268 return 0; 2269 } 2270 2271 return task->GetRequestedDataTransferCount ( ); 2272 2273} 2274 2275 2276//----------------------------------------------------------------------------- 2277// GetRequestedDataTransferCount - Retrieves the realized data transfer 2278// count from the parallelTask. [PROTECTED] 2279//----------------------------------------------------------------------------- 2280 2281UInt64 2282IOSCSIParallelInterfaceDevice::GetRealizedDataTransferCount ( 2283 SCSIParallelTaskIdentifier parallelTask ) 2284{ 2285 2286 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2287 2288 if ( task == NULL ) 2289 { 2290 return 0; 2291 } 2292 2293 return task->GetRealizedDataTransferCount ( ); 2294 2295} 2296 2297 2298//----------------------------------------------------------------------------- 2299// GetRequestedDataTransferCount - Sets the realized data transfer 2300// count in the parallelTask. [PROTECTED] 2301//----------------------------------------------------------------------------- 2302 2303bool 2304IOSCSIParallelInterfaceDevice::SetRealizedDataTransferCount ( 2305 SCSIParallelTaskIdentifier parallelTask, 2306 UInt64 realizedTransferCountInBytes ) 2307{ 2308 2309 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2310 2311 if ( task == NULL ) 2312 { 2313 return false; 2314 } 2315 2316 return task->SetRealizedDataTransferCount ( realizedTransferCountInBytes ); 2317 2318} 2319 2320 2321//----------------------------------------------------------------------------- 2322// GetRequestedDataTransferCount - Increments the realized data transfer 2323// count in the parallelTask. [PROTECTED] 2324//----------------------------------------------------------------------------- 2325 2326void 2327IOSCSIParallelInterfaceDevice::IncrementRealizedDataTransferCount ( 2328 SCSIParallelTaskIdentifier parallelTask, 2329 UInt64 realizedTransferCountInBytes ) 2330{ 2331 2332 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2333 2334 if ( task == NULL ) 2335 { 2336 return; 2337 } 2338 2339 return task->IncrementRealizedDataTransferCount ( realizedTransferCountInBytes ); 2340 2341} 2342 2343 2344//----------------------------------------------------------------------------- 2345// GetRequestedDataTransferCount - Retrieves the data buffer in the 2346// parallelTask. [PROTECTED] 2347//----------------------------------------------------------------------------- 2348 2349IOMemoryDescriptor * 2350IOSCSIParallelInterfaceDevice::GetDataBuffer ( 2351 SCSIParallelTaskIdentifier parallelTask ) 2352{ 2353 2354 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2355 2356 if ( task == NULL ) 2357 { 2358 return NULL; 2359 } 2360 2361 return task->GetDataBuffer ( ); 2362 2363} 2364 2365 2366//----------------------------------------------------------------------------- 2367// GetDataBufferOffset - Retrieves the data buffer offset in the parallelTask. 2368// [PROTECTED] 2369//----------------------------------------------------------------------------- 2370 2371UInt64 2372IOSCSIParallelInterfaceDevice::GetDataBufferOffset ( 2373 SCSIParallelTaskIdentifier parallelTask ) 2374{ 2375 2376 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2377 2378 if ( task == NULL ) 2379 { 2380 return 0; 2381 } 2382 2383 return task->GetDataBufferOffset ( ); 2384 2385} 2386 2387 2388//----------------------------------------------------------------------------- 2389// GetTimeoutDuration - Retrieves the timeout duration in the parallelTask. 2390// [PROTECTED] 2391//----------------------------------------------------------------------------- 2392 2393UInt32 2394IOSCSIParallelInterfaceDevice::GetTimeoutDuration ( 2395 SCSIParallelTaskIdentifier parallelTask ) 2396{ 2397 2398 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2399 2400 if ( task == NULL ) 2401 { 2402 return 0; 2403 } 2404 2405 return task->GetTimeoutDuration ( ); 2406 2407} 2408 2409//----------------------------------------------------------------------------- 2410// SetSCSIParallelFeatureNegotiation - Sets a feature negotiation request 2411// in the specified task. 2412// [PROTECTED] 2413//----------------------------------------------------------------------------- 2414 2415void 2416IOSCSIParallelInterfaceDevice::SetSCSIParallelFeatureNegotiation ( 2417 SCSIParallelTaskIdentifier parallelTask, 2418 SCSIParallelFeature requestedFeature, 2419 SCSIParallelFeatureRequest newRequest ) 2420{ 2421 2422 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2423 2424 if ( task == NULL ) 2425 { 2426 return; 2427 } 2428 2429 return task->SetSCSIParallelFeatureNegotiation ( requestedFeature, newRequest ); 2430 2431} 2432 2433 2434//----------------------------------------------------------------------------- 2435// GetSCSIParallelFeatureNegotiation - Gets a feature negotiation request 2436// in the specified task. 2437// [PROTECTED] 2438//----------------------------------------------------------------------------- 2439 2440SCSIParallelFeatureRequest 2441IOSCSIParallelInterfaceDevice::GetSCSIParallelFeatureNegotiation ( 2442 SCSIParallelTaskIdentifier parallelTask, 2443 SCSIParallelFeature requestedFeature ) 2444{ 2445 2446 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2447 2448 if ( task == NULL ) 2449 { 2450 return kSCSIParallelFeature_NoNegotiation; 2451 } 2452 2453 return task->GetSCSIParallelFeatureNegotiation ( requestedFeature ); 2454 2455} 2456 2457 2458//----------------------------------------------------------------------------- 2459// GetSCSIParallelFeatureNegotiationResult - Gets a feature negotiation 2460// result in the specified task. 2461// [PROTECTED] 2462//----------------------------------------------------------------------------- 2463 2464SCSIParallelFeatureResult 2465IOSCSIParallelInterfaceDevice::GetSCSIParallelFeatureNegotiationResult ( 2466 SCSIParallelTaskIdentifier parallelTask, 2467 SCSIParallelFeature requestedFeature ) 2468{ 2469 2470 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2471 2472 if ( task == NULL ) 2473 { 2474 return kSCSIParallelFeature_NegotitiationUnchanged; 2475 } 2476 2477 return task->GetSCSIParallelFeatureNegotiationResult ( requestedFeature ); 2478 2479} 2480 2481 2482//----------------------------------------------------------------------------- 2483// GetControllerTaskIdentifier - Gets the identifier associated with the 2484// task. [PROTECTED] 2485//----------------------------------------------------------------------------- 2486 2487UInt64 2488IOSCSIParallelInterfaceDevice::GetControllerTaskIdentifier ( 2489 SCSIParallelTaskIdentifier parallelTask ) 2490{ 2491 2492 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2493 2494 if ( task == NULL ) 2495 { 2496 return 0; 2497 } 2498 2499 return task->GetControllerTaskIdentifier ( ); 2500 2501} 2502 2503 2504//----------------------------------------------------------------------------- 2505// GetHBADataSize - Gets the size of HBA Data associated with a command. 2506// [PROTECTED] 2507//----------------------------------------------------------------------------- 2508 2509UInt32 2510IOSCSIParallelInterfaceDevice::GetHBADataSize ( 2511 SCSIParallelTaskIdentifier parallelTask ) 2512{ 2513 2514 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2515 2516 if ( task == NULL ) 2517 { 2518 return 0; 2519 } 2520 2521 return task->GetHBADataSize ( ); 2522 2523} 2524 2525 2526//----------------------------------------------------------------------------- 2527// GetHBADataPointer - Gets the HBA Data pointer associated with a command. 2528// [PROTECTED] 2529//----------------------------------------------------------------------------- 2530 2531void * 2532IOSCSIParallelInterfaceDevice::GetHBADataPointer ( 2533 SCSIParallelTaskIdentifier parallelTask ) 2534{ 2535 2536 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2537 2538 if ( task == NULL ) 2539 { 2540 return NULL; 2541 } 2542 2543 return task->GetHBADataPointer ( ); 2544 2545} 2546 2547 2548//----------------------------------------------------------------------------- 2549// GetHBADataDescriptor - Gets the HBA memory descriptor associated with 2550// a command. [PROTECTED] 2551//----------------------------------------------------------------------------- 2552 2553IOMemoryDescriptor * 2554IOSCSIParallelInterfaceDevice::GetHBADataDescriptor ( 2555 SCSIParallelTaskIdentifier parallelTask ) 2556{ 2557 2558 SCSIParallelTask * task = ( SCSIParallelTask * ) parallelTask; 2559 2560 if ( task == NULL ) 2561 { 2562 return NULL; 2563 } 2564 2565 return task->GetHBADataDescriptor ( ); 2566 2567} 2568