1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/IOMessage.h> 24 25#include <IOKit/sbp2/IOFireWireSBP2Login.h> 26#include <IOKit/sbp2/IOFireWireSBP2LUN.h> 27#include <IOKit/sbp2/IOFireWireSBP2Target.h> 28 29#define FIREWIREPRIVATE 30#include <IOKit/firewire/IOFireWireController.h> 31#undef FIREWIREPRIVATE 32 33#include <IOKit/firewire/IOConfigDirectory.h> 34 35#include "FWDebugging.h" 36#include "IOFireWireSBP2Diagnostics.h" 37#include "IOFWSBP2PseudoAddressSpace.h" 38 39#define kFetchAgentSplitTimeout (3*125*1000) // 275 milliseconds 40#define kFetchAgentRetryInterval (125*1000) // 125 milliseconds 41 42extern const OSSymbol *gUnit_Characteristics_Symbol; 43extern const OSSymbol *gManagement_Agent_Offset_Symbol; 44extern const OSSymbol *gFast_Start_Symbol; 45 46OSDefineMetaClassAndStructors( IOFireWireSBP2Login, OSObject ); 47 48OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 0); 49OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 1); 50OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 2); 51OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 3); 52OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 4); 53OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 5); 54OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 6); 55OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 7); 56OSMetaClassDefineReservedUnused(IOFireWireSBP2Login, 8); 57 58#if defined(__BIG_ENDIAN__) 59#define SBP2SwapHostToBigInt32Array(array, bytes) 60#define SBP2SwapBigToHostInt32Array(array, bytes) 61#elif defined(__LITTLE_ENDIAN__) 62static void SBP2SwapInt32Array(void * array, int bytes) 63{ 64 if ( array && bytes ) 65 { 66 UInt32 * quads = (UInt32 *) array; 67 bytes >>= 2; 68 while (bytes--) 69 quads[bytes] = OSSwapInt32(quads[bytes]); 70 } 71} 72static inline void SBP2SwapHostToBigInt32Array(void * array, int bytes) 73{ SBP2SwapInt32Array(array, bytes); } 74static inline void SBP2SwapBigToHostInt32Array(void * array, int bytes) 75{ SBP2SwapInt32Array(array, bytes); } 76#else 77#error Unknown endianess 78#endif 79 80#pragma mark - 81 82// initWithLUN 83// 84// initializer 85 86bool IOFireWireSBP2Login::initWithLUN( IOFireWireSBP2LUN * lun ) 87{ 88 IOReturn status = kIOReturnSuccess; 89 90 // store LUN & Unit 91 fLUN = lun; 92 fTarget = getTarget(); 93 fUnit = fLUN->getFireWireUnit(); 94 fControl = fUnit->getController(); 95 96 fRefCon = NULL; 97 98 fLoginGeneration = 0; 99 fLoginNodeID = 0; 100 fLoginFlags = 0; 101 fMaxPayloadSize = 4; 102 103 // NULL out fields we may allocate 104 fStatusBlockAddressSpace = NULL; 105 fStatusNotifyCallback = NULL; 106 fStatusNotifyRefCon = NULL; 107 fUnsolicitedStatusNotifyCallback = NULL; 108 fUnsolicitedStatusNotifyRefCon = NULL; 109 110 fLoginORBAddressSpace = NULL; 111 fLoginResponseAddressSpace = NULL; 112 fLoginTimeoutTimerSet = false; 113 fLoginWriteCommand = NULL; 114 fLoginWriteCommandMemory = NULL; 115 fLoginWriteInProgress = false; 116 fLoginCompletionCallback = NULL; 117 fLoginCompletionRefCon = NULL; 118 119 fReconnectORBAddressSpace = NULL; 120 fReconnectStatusBlockAddressSpace = NULL; 121 fReconnectTime = 0; 122 fReconnectTimeoutTimerSet = false; 123 fReconnectWriteCommand = NULL; 124 fReconnectWriteCommandMemory = NULL; 125 fReconnectWriteInProgress = false; 126 fReconnectWriteInterrupted = false; 127 128 fLogoutORBAddressSpace = NULL; 129 fLogoutTimeoutTimerSet = false; 130 fLogoutWriteInProgress = false; 131 fLogoutWriteCommand = NULL; 132 fLogoutWriteCommandMemory = NULL; 133 fLogoutCompletionCallback = NULL; 134 fLogoutCompletionRefCon = NULL; 135 136 fLoginRetryMax = 32; 137 fLoginRetryDelay = 1000000; 138 139 fUnsolicitedStatusEnableRequested = false; 140 141 fFetchAgentWriteCommandInUse = false; 142 fFetchAgentWriteCommand = NULL; 143 fFetchAgentWriteCommandMemory = NULL; 144 fFetchAgentWriteCompletion = NULL; 145 146 fFetchAgentResetInProgress = false; 147 fFetchAgentResetCommand = NULL; 148 fFetchAgentResetRefCon = NULL; 149 fFetchAgentResetCompletion = NULL; 150 151 fDoorbellInProgress = false; 152 fDoorbellRingAgain = false; 153 fDoorbellCommand = NULL; 154 155 fUnsolicitedStatusEnableInProgress = false; 156 fUnsolicitedStatusEnableCommand = NULL; 157 158 fSetBusyTimeoutBuffer = OSSwapHostToBigInt32(0x0000000f); 159 fSetBusyTimeoutInProgress = false; 160 fSetBusyTimeoutAddress = FWAddress( 0x0000FFFF, 0xF0000210 ); 161 fSetBusyTimeoutCommand = NULL; 162 163 fPasswordBuf = NULL; 164 fPasswordLen = 0; 165 fPasswordAddressSpace = NULL; 166 fPasswordAddress = NULL; 167 fPasswordDescriptor = NULL; 168 fSuspended = false; 169 170 fARDMAMax = 0; 171 172 fLastORBAddress = FWAddress(0,0); 173 174 // 175 // set up command gate 176 // 177 178 IOWorkLoop * workLoop = NULL; 179 if( status == kIOReturnSuccess ) 180 { 181 workLoop = fLUN->getWorkLoop(); 182 if( !workLoop ) 183 status = kIOReturnNoResources; 184 } 185 186 if( status == kIOReturnSuccess ) 187 { 188 fGate = IOCommandGate::commandGate( this ); 189 if( !fGate ) 190 status = kIOReturnNoMemory; 191 } 192 193 if( status == kIOReturnSuccess ) 194 { 195 workLoop->retain(); 196 workLoop->addEventSource( fGate ); 197 } 198 199 if( status == kIOReturnSuccess ) 200 { 201 // init state machine 202 fLoginState = kLoginStateIdle; 203 204 // scan unit 205 status = getUnitInformation(); 206 FWKLOG( ( "IOFireWireSBP2Login<%p> : fManagementOffset = 0x%lx, fMaxORBSize = %d, fMaxCommandBlockSize = %d\n", this, fManagementOffset, fMaxORBSize, fMaxCommandBlockSize ) ); 207 } 208 209 if( status == kIOReturnSuccess ) 210 { 211 status = allocateResources(); 212 } 213 214 if( status == kIOReturnSuccess ) 215 { 216 fORBSet = OSSet::withCapacity(1); 217 if( fORBSet == NULL ) 218 status = kIOReturnNoMemory; 219 } 220 221 if( status == kIOReturnSuccess ) 222 { 223 fORBSetIterator = OSCollectionIterator::withCollection( fORBSet ); 224 } 225 226 if( status == kIOReturnSuccess ) 227 { 228 OSObject * prop = fLUN->getProperty( "FWARDMAMax", gIOServicePlane ); 229 if( prop != NULL ) 230 { 231 fARDMAMax = ((OSNumber*)prop)->unsigned32BitValue(); 232 } 233 } 234 235 // the LUN that's creating us will call release() on a non-successful init 236 // we'll clean up there from what ever half-allocated state we are in 237 238 return (status == kIOReturnSuccess); 239} 240 241///////////////////////////////////////////////////////////////////// 242// getUnitInformation 243// 244// gathers SBP2 specific information from unit's ROM 245// specifically it reads, the management agent, and unit dependent 246// characteristics 247 248IOReturn IOFireWireSBP2Login::getUnitInformation( void ) 249{ 250 IOReturn status = kIOReturnSuccess; 251 UInt32 unitCharacteristics = 0; 252 OSObject * prop = NULL; 253 254 // 255 // get management agent info 256 // 257 258 prop = fLUN->getProperty( gManagement_Agent_Offset_Symbol ); 259 if( prop == NULL ) 260 status = kIOReturnError; 261 262 if( status == kIOReturnSuccess ) 263 { 264 fManagementOffset = ((OSNumber*)prop)->unsigned32BitValue(); 265 } 266 267 FWKLOG( ("IOFireWireSBP2Login<%p> : status = %d, fManagementOffset = %d\n", this, status, fManagementOffset) ); 268 269 // 270 // get unit characteristics 271 // 272 273 if( status == kIOReturnSuccess ) 274 { 275 prop = fLUN->getProperty( gUnit_Characteristics_Symbol ); 276 if( prop == NULL ) 277 status = kIOReturnError; 278 } 279 280 if( status == kIOReturnSuccess ) 281 { 282 unitCharacteristics = ((OSNumber*)prop)->unsigned32BitValue(); 283 284 // extract management timeout, max ORB size, max command block size 285 286 fManagementTimeout = ((unitCharacteristics >> 8) & 0xff) * 500; // in milliseconds 287 UInt32 orbSize = (unitCharacteristics & 0xff) * 4; 288 if( orbSize < 32 ) 289 orbSize = 32; 290 fMaxORBSize = orbSize; 291 fMaxCommandBlockSize = orbSize - (sizeof(IOFireWireSBP2ORB::FWSBP2ORB) - 4); 292 } 293 294 // 295 // get fast start info 296 // 297 298 if( status == kIOReturnSuccess ) 299 { 300 prop = fLUN->getProperty( gFast_Start_Symbol ); 301 if( prop != NULL ) 302 { 303 UInt32 fastStartInfo = ((OSNumber*)prop)->unsigned32BitValue(); 304 305 fFastStartSupported = true; 306 fFastStartOffset = fastStartInfo & 0x000000ff; 307 fFastStartMaxPayload = (fastStartInfo >> 8) & 0x000000ff; 308 } 309 } 310 311 FWKLOG( ("IOFireWireSBP2Login<%p> : fFastStartSupported = %d, fFastStartOffset = 0x%02lx, fFastStartMaxPayload = %d\n", this, fFastStartSupported, fFastStartOffset, fFastStartMaxPayload ) ); 312 313 return status; 314} 315 316// allocateResources 317// 318// allocate addressSpaces (ORBs, status registers, response registers) 319// and command objects for writing registers, etc. 320 321IOReturn IOFireWireSBP2Login::allocateResources( void ) 322{ 323 IOReturn status = kIOReturnSuccess; 324 325 // 326 // allocate and register an address space for the login ORB 327 // 328 329 FWAddress host_address; 330 if( status == kIOReturnSuccess ) 331 { 332 fLoginORBAddressSpace = IOFWSBP2PseudoAddressSpace::simpleRead( fControl, &host_address, sizeof(FWSBP2LoginORB), &fLoginORB ); 333 if ( fLoginORBAddressSpace == NULL ) 334 status = kIOReturnNoMemory; 335 } 336 337 if( status == kIOReturnSuccess ) 338 { 339 fLoginORBAddress.nodeID = OSSwapHostToBigInt16( host_address.nodeID ); 340 fLoginORBAddress.addressHi = OSSwapHostToBigInt16( host_address.addressHi ); 341 fLoginORBAddress.addressLo = OSSwapHostToBigInt32( host_address.addressLo ); 342 343 status = fLoginORBAddressSpace->activate(); 344 } 345 346 // 347 // allocate and register an address space for the login response 348 // 349 350 if( status == kIOReturnSuccess ) 351 { 352 fLoginResponseAddressSpace = IOFWSBP2PseudoAddressSpace::simpleRW( fControl, &fLoginResponseAddress, 353 sizeof(FWSBP2LoginResponse), 354 &fLoginResponse ); 355 if ( fLoginResponseAddressSpace == NULL ) 356 status = kIOReturnNoMemory; 357 } 358 359 if( status == kIOReturnSuccess ) 360 { 361 status = fLoginResponseAddressSpace->activate(); 362 } 363 364 // 365 // allocate and register an address space for the reconnect ORB 366 // 367 368 if( status == kIOReturnSuccess ) 369 { 370 fReconnectORBAddressSpace = IOFWPseudoAddressSpace::simpleRead( fControl, &host_address, 371 sizeof(FWSBP2ReconnectORB), 372 &fReconnectORB ); 373 if ( fReconnectORBAddressSpace == NULL ) 374 status = kIOReturnNoMemory; 375 } 376 377 if( status == kIOReturnSuccess ) 378 { 379 fReconnectORBAddress.nodeID = OSSwapHostToBigInt16( host_address.nodeID ); 380 fReconnectORBAddress.addressHi = OSSwapHostToBigInt16( host_address.addressHi ); 381 fReconnectORBAddress.addressLo = OSSwapHostToBigInt32( host_address.addressLo ); 382 383 status = fReconnectORBAddressSpace->activate(); 384 } 385 386 // 387 // allocate and register an address space for the status block 388 // 389 390 if( status == kIOReturnSuccess ) 391 { 392 fStatusBlockAddressSpace = fUnit->createPseudoAddressSpace( &fStatusBlockAddress, 393 sizeof(FWSBP2StatusBlock), 394 NULL, 395 IOFireWireSBP2Login::statusBlockWriteStatic, 396 this ); 397 if ( fStatusBlockAddressSpace == NULL ) 398 status = kIOReturnNoMemory; 399 } 400 401 if( status == kIOReturnSuccess ) 402 { 403 status = fStatusBlockAddressSpace->activate(); 404 } 405 406 // 407 // allocate and register an address space for the reconnect status block 408 // 409 410 if( status == kIOReturnSuccess ) 411 { 412 fReconnectStatusBlockAddressSpace = 413 fUnit->createPseudoAddressSpace( &fReconnectStatusBlockAddress, sizeof(FWSBP2StatusBlock), 414 NULL, IOFireWireSBP2Login::reconnectStatusBlockWriteStatic, this ); 415 416 if ( fReconnectStatusBlockAddressSpace == NULL ) 417 status = kIOReturnNoMemory; 418 } 419 420 if( status == kIOReturnSuccess ) 421 { 422 status = fReconnectStatusBlockAddressSpace->activate(); 423 } 424 425 // 426 // allocate and register an address space for the logout ORB 427 // 428 429 if( status == kIOReturnSuccess ) 430 { 431 fLogoutORBAddressSpace = IOFWPseudoAddressSpace::simpleRead( fControl, &host_address, sizeof(FWSBP2LogoutORB), 432 &fLogoutORB ); 433 if ( fLogoutORBAddressSpace == NULL ) 434 status = kIOReturnNoMemory; 435 } 436 437 if( status == kIOReturnSuccess ) 438 { 439 fLogoutORBAddress.nodeID = OSSwapHostToBigInt16( host_address.nodeID ); 440 fLogoutORBAddress.addressHi = OSSwapHostToBigInt16( host_address.addressHi ); 441 fLogoutORBAddress.addressLo = OSSwapHostToBigInt32( host_address.addressLo ); 442 443 status = fLogoutORBAddressSpace->activate(); 444 } 445 446 // 447 // prepare parts of the ORBs 448 // 449 450 fLoginORB.loginResponseAddressHi = OSSwapHostToBigInt32((fLoginResponseAddress.nodeID << 16) | fLoginResponseAddress.addressHi); 451 fLoginORB.loginResponseAddressLo = OSSwapHostToBigInt32(fLoginResponseAddress.addressLo); 452 fLoginORB.loginResponseLength = OSSwapHostToBigInt16(sizeof( FWSBP2LoginResponse )); 453 fLoginORB.lun = OSSwapHostToBigInt16(fLUN->getLUNumber()); 454 FWKLOG( ("IOFireWireSBP2Login<%p>::allocateResources lun number = %d\n", this, OSSwapBigToHostInt16(fLoginORB.lun)) ); 455 fLoginORB.statusFIFOAddressHi = OSSwapHostToBigInt32((fStatusBlockAddress.nodeID << 16) | fStatusBlockAddress.addressHi); 456 fLoginORB.statusFIFOAddressLo = OSSwapHostToBigInt32(fStatusBlockAddress.addressLo); 457 458 fReconnectORB.options = OSSwapHostToBigInt16(3 | 0x8000); // reconnect | notify 459 fReconnectORB.statusFIFOAddressHi = OSSwapHostToBigInt32((fReconnectStatusBlockAddress.nodeID << 16) | fReconnectStatusBlockAddress.addressHi); 460 fReconnectORB.statusFIFOAddressLo = OSSwapHostToBigInt32(fReconnectStatusBlockAddress.addressLo); 461 462 fLogoutORB.options = OSSwapHostToBigInt16(7 | 0x8000); // logout | notify 463 fLogoutORB.statusFIFOAddressHi = OSSwapHostToBigInt32((fStatusBlockAddress.nodeID << 16) | fStatusBlockAddress.addressHi); 464 fLogoutORB.statusFIFOAddressLo = OSSwapHostToBigInt32(fStatusBlockAddress.addressLo); 465 466 // 467 // create command for writing the management agent 468 // 469 470 if( status == kIOReturnSuccess ) 471 { 472 fLoginWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLoginORBAddress, 8, kIODirectionOut); 473 if( fLoginWriteCommandMemory == NULL ) 474 status = kIOReturnNoMemory; 475 } 476 477 if( status == kIOReturnSuccess ) 478 { 479 fLoginWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 480 fLoginWriteCommandMemory, 481 IOFireWireSBP2Login::loginWriteCompleteStatic, this, true ); 482 if( fLoginWriteCommand == NULL ) 483 status = kIOReturnNoMemory; 484 } 485 486 if( status == kIOReturnSuccess ) 487 { 488 fLoginTimeoutCommand = fControl->createDelayedCmd( fManagementTimeout * 1000, 489 IOFireWireSBP2Login::loginTimeoutStatic, this); 490 } 491 492 493 if( status == kIOReturnSuccess ) 494 { 495 fLoginRetryTimeoutCommand = fControl->createDelayedCmd( 1000000, // 1 second 496 IOFireWireSBP2Login::loginRetryTimeoutStatic, this); 497 } 498 499 if( status == kIOReturnSuccess ) 500 { 501 fReconnectRetryTimeoutCommand = fControl->createDelayedCmd( 100000, // 1/10th of a second 502 IOFireWireSBP2Login::reconnectRetryTimeoutStatic, this); 503 } 504 505 // 506 // create command for writing the management agent during reconnect 507 // 508 509 if( status == kIOReturnSuccess ) 510 { 511 fReconnectWriteCommandMemory = IOMemoryDescriptor::withAddress( &fReconnectORBAddress, 8, kIODirectionOut); 512 if( fReconnectWriteCommandMemory == NULL ) 513 status = kIOReturnNoMemory; 514 } 515 516 if( status == kIOReturnSuccess ) 517 { 518 fReconnectWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 519 fReconnectWriteCommandMemory, 520 IOFireWireSBP2Login::reconnectWriteCompleteStatic, this, true ); 521 if( fReconnectWriteCommand == NULL ) 522 status = kIOReturnNoMemory; 523 } 524 525 if( status == kIOReturnSuccess ) 526 { 527 fReconnectTimeoutCommand = (IOFWDelayCommand*)fControl->createDelayedCmd( ((fManagementTimeout + 1000) * 1000), 528 IOFireWireSBP2Login::reconnectTimeoutStatic, this); 529 if( !fReconnectTimeoutCommand ) 530 status = kIOReturnNoMemory; 531 } 532 533 // 534 // create command for writing the management agent during logout 535 // 536 537 if( status == kIOReturnSuccess ) 538 { 539 fLogoutWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLogoutORBAddress, 8, kIODirectionOut); 540 if( fLogoutWriteCommandMemory == NULL ) 541 status = kIOReturnNoMemory; 542 } 543 544 if( status == kIOReturnSuccess ) 545 { 546 fLogoutWriteCommand = fUnit->createWriteCommand( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 547 fLogoutWriteCommandMemory, 548 IOFireWireSBP2Login::logoutWriteCompleteStatic, this, true ); 549 if( fLogoutWriteCommand == NULL ) 550 status = kIOReturnNoMemory; 551 } 552 553 // 554 // create command timeout during logout 555 // 556 557 if( status == kIOReturnSuccess ) 558 { 559 fLogoutTimeoutCommand = fControl->createDelayedCmd( fManagementTimeout * 1000, 560 IOFireWireSBP2Login::logoutTimeoutStatic, this); 561 } 562 563 // 564 // create command for fetch agent write retries 565 // 566 567 if( status == kIOReturnSuccess ) 568 { 569 fFetchAgentRetryTimerCommand = fControl->createDelayedCmd( kFetchAgentRetryInterval, 570 IOFireWireSBP2Login::fetchAgentRetryTimerStatic, this); 571 } 572 573 // 574 // create command for writing the fetch agent 575 // 576 577 // 578 // create command for writing the fast start register 579 // 580 581 if( fFastStartSupported ) 582 { 583 if( status == kIOReturnSuccess ) 584 { 585 UInt32 size = fFastStartMaxPayload * 4; 586 if( size == 0 ) 587 size = 4096; 588 fFetchAgentWriteCommandMemory = IOBufferMemoryDescriptor::withOptions( kIODirectionOutIn | kIOMemoryUnshared, size, PAGE_SIZE ); 589 if( fFetchAgentWriteCommandMemory == NULL ) 590 status = kIOReturnNoMemory; 591 } 592 593 if( status == kIOReturnSuccess ) 594 { 595 fFetchAgentWriteCommand = fUnit->createWriteCommand( FWAddress(0,0), // tbd later 596 fFetchAgentWriteCommandMemory, 597 IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true ); 598 if( fFetchAgentWriteCommand == NULL ) 599 status = kIOReturnNoMemory; 600 } 601 602 if( status == kIOReturnSuccess ) 603 { 604 // extra long timeout to support a slow to respond still camera 605 fFetchAgentWriteCommand->setTimeout( kFetchAgentSplitTimeout ); 606 fFetchAgentWriteCommand->setRetries( 0 ); 607 } 608 } 609 else 610 { 611 if( status == kIOReturnSuccess ) 612 { 613 fFetchAgentWriteCommandMemory = IOMemoryDescriptor::withAddress( &fLastORBAddress, 8, kIODirectionOut ); 614 if( fFetchAgentWriteCommandMemory == NULL ) 615 status = kIOReturnNoMemory; 616 } 617 618 if( status == kIOReturnSuccess ) 619 { 620 fFetchAgentWriteCommand = fUnit->createWriteCommand( FWAddress(0,0), // tbd later 621 fFetchAgentWriteCommandMemory, 622 IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true ); 623 if( fFetchAgentWriteCommand == NULL ) 624 status = kIOReturnNoMemory; 625 } 626 627 if( status == kIOReturnSuccess ) 628 { 629 // extra long timeout to support a slow to respond still camera 630 fFetchAgentWriteCommand->setTimeout( kFetchAgentSplitTimeout ); 631 fFetchAgentWriteCommand->setRetries( 0 ); 632 } 633 } 634 635 // 636 // create command for reseting the fetch agent 637 // 638 639 if( status == kIOReturnSuccess ) 640 { 641 fFetchAgentResetCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), // tbd later 642 &fFetchAgentResetBuffer, 1, 643 IOFireWireSBP2Login::fetchAgentResetCompleteStatic, 644 this, true ); 645 if( fFetchAgentResetCommand == NULL ) 646 status = kIOReturnNoMemory; 647 } 648 649 // 650 // create command for ringing the doorbell 651 // 652 653 if( status == kIOReturnSuccess ) 654 { 655 fDoorbellCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), // tbd later 656 &fDoorbellBuffer, 1, 657 IOFireWireSBP2Login::doorbellCompleteStatic, 658 this, true ); 659 if( fDoorbellCommand == NULL ) 660 status = kIOReturnNoMemory; 661 } 662 663 // 664 // create command for setting busy timeout 665 // 666 667 if( status == kIOReturnSuccess ) 668 { 669 fSetBusyTimeoutCommand = fUnit->createWriteQuadCommand( fSetBusyTimeoutAddress, 670 &fSetBusyTimeoutBuffer, 1, 671 IOFireWireSBP2Login::setBusyTimeoutCompleteStatic, 672 this, true ); 673 if( fSetBusyTimeoutCommand == NULL ) 674 status = kIOReturnNoMemory; 675 } 676 677 // 678 // create command for enabling unsolicited status 679 // 680 681 if( status == kIOReturnSuccess ) 682 { 683 fUnsolicitedStatusEnableCommand = fUnit->createWriteQuadCommand( FWAddress(0,0), // tbd later 684 &fUnsolicitedStatusEnableBuffer, 1, 685 IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic, 686 this, true ); 687 if( fUnsolicitedStatusEnableCommand == NULL ) 688 status = kIOReturnNoMemory; 689 } 690 691 return status; 692} 693 694void IOFireWireSBP2Login::release() const 695{ 696 if( getRetainCount() >= 2 ) 697 OSObject::release(2); 698} 699 700void IOFireWireSBP2Login::free( void ) 701{ 702 IOReturn status = kIOReturnSuccess; 703 704 FWKLOG( ( "IOFireWireSBP2Login<%p> : free called\n", this ) ); 705 706 if( fControl && fTarget ) 707 { 708 fControl->closeGate(); 709 710 if( fReconnectWriteCommand ) 711 { 712 fTarget->cancelMgmtAgentAccess( fReconnectWriteCommand ); 713 } 714 715 if( fLoginWriteCommand ) 716 { 717 fTarget->cancelMgmtAgentAccess( fLoginWriteCommand ); 718 } 719 720 fControl->openGate(); 721 } 722 723 // disconnect from lun 724 removeLogin(); 725 726 /////////////////////////////////////////// 727 728 // 729 // release command for reseting fetch agent 730 // 731 732 if( fFetchAgentResetInProgress ) 733 fFetchAgentResetCommand->cancel( kIOReturnAborted ); 734 735 if( fFetchAgentResetCommand ) 736 fFetchAgentResetCommand->release(); 737 738 // 739 // release command for ringing the doorbell 740 // 741 742 if( fDoorbellInProgress ) 743 fDoorbellCommand->cancel( kIOReturnAborted ); 744 745 if( fDoorbellCommand ) 746 fDoorbellCommand->release(); 747 748 // 749 // release command for enabling unsolicited status 750 // 751 752 if( fUnsolicitedStatusEnableInProgress ) 753 fUnsolicitedStatusEnableCommand->cancel( kIOReturnAborted ); 754 755 if( fUnsolicitedStatusEnableCommand ) 756 fUnsolicitedStatusEnableCommand->release(); 757 758 // 759 // release command for setting busy timeout 760 // 761 762 if( fSetBusyTimeoutInProgress ) 763 fSetBusyTimeoutCommand->cancel( kIOReturnAborted ); 764 765 if( fSetBusyTimeoutCommand ) 766 fSetBusyTimeoutCommand->release(); 767 768 // 769 // release command for writing the management agent 770 // 771 772 if( fLoginWriteInProgress ) 773 fLoginWriteCommand->cancel( kIOReturnAborted ); 774 775 if( fLoginWriteCommand != NULL ) 776 fLoginWriteCommand->release(); 777 778 if( fLoginWriteCommandMemory != NULL ) 779 fLoginWriteCommandMemory->release(); 780 781 // cancel timer 782 if( fLoginTimeoutTimerSet ) 783 fLoginTimeoutCommand->cancel(kIOReturnAborted); 784 785 if( fLoginTimeoutCommand ) 786 fLoginTimeoutCommand->release(); 787 788 // cancel timer 789 stopLoginRetryTimer(); 790 791 if( fLoginRetryTimeoutCommand ) 792 fLoginRetryTimeoutCommand->release(); 793 794 // cancel timer 795 stopReconnectRetryTimer(); 796 797 if( fReconnectRetryTimeoutCommand ) 798 fReconnectRetryTimeoutCommand->release(); 799 800 // 801 // deallocate login orb address space 802 // 803 804 if( fLoginORBAddressSpace != NULL && status == kIOReturnSuccess ) 805 { 806 fLoginORBAddressSpace->deactivate(); 807 fLoginORBAddressSpace->release(); 808 } 809 810 // 811 // deallocate login response address space 812 // 813 814 if( fLoginResponseAddressSpace != NULL && status == kIOReturnSuccess ) 815 { 816 fLoginResponseAddressSpace->deactivate(); 817 fLoginResponseAddressSpace->release(); 818 } 819 820 /////////////////////////////////////////// 821 822 // 823 // release command for writing the management agent during reconnect 824 // 825 826 if( fReconnectWriteInProgress ) 827 fReconnectWriteCommand->cancel(kIOReturnAborted); 828 829 if( fReconnectWriteCommand != NULL ) 830 fReconnectWriteCommand->release(); 831 832 if( fReconnectWriteCommandMemory != NULL ) 833 fReconnectWriteCommandMemory->release(); 834 835 // cancel timer 836 if( fReconnectTimeoutTimerSet ) 837 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 838 839 if( fReconnectTimeoutCommand ) 840 fReconnectTimeoutCommand->release(); 841 842 // 843 // deallocate reconnect orb address space 844 // 845 846 if( fReconnectORBAddressSpace != NULL && status == kIOReturnSuccess ) 847 { 848 fReconnectORBAddressSpace->deactivate(); 849 fReconnectORBAddressSpace->release(); 850 } 851 852 // 853 // deallocate reconnect status block address space 854 // 855 856 if( fReconnectStatusBlockAddressSpace != NULL && status == kIOReturnSuccess ) 857 { 858 fReconnectStatusBlockAddressSpace->deactivate(); 859 fReconnectStatusBlockAddressSpace->release(); 860 } 861 862 /////////////////////////////////////////// 863 864 // 865 // release command for writing the management agent during logout 866 // 867 868 if( fLogoutWriteInProgress ) 869 fLogoutWriteCommand->cancel(kIOReturnAborted); 870 871 if( fLogoutWriteCommand != NULL ) 872 fLogoutWriteCommand->release(); 873 874 if( fLogoutWriteCommandMemory != NULL ) 875 fLogoutWriteCommandMemory->release(); 876 877 // cancel timer 878 if( fLogoutTimeoutTimerSet ) 879 fLogoutTimeoutCommand->cancel(kIOReturnAborted); 880 881 // release logout timer 882 if( fLogoutTimeoutCommand ) 883 fLogoutTimeoutCommand->release(); 884 885 // 886 // deallocate logout orb address space 887 // 888 889 if( fLogoutORBAddressSpace != NULL && status == kIOReturnSuccess ) 890 { 891 fLogoutORBAddressSpace->deactivate(); 892 fLogoutORBAddressSpace->release(); 893 } 894 895 /////////////////////////////////////////// 896 897 // 898 // release command for writing the fetch agent 899 // 900 901 // cancel timer 902 stopFetchAgentRetryTimer(); 903 904 if( fFetchAgentRetryTimerCommand ) 905 { 906 fFetchAgentRetryTimerCommand->release(); 907 fFetchAgentRetryTimerCommand = NULL; 908 } 909 910 if( fFetchAgentWriteCommandInUse ) 911 { 912 fFetchAgentWriteCommand->cancel(kIOReturnAborted); 913 } 914 915 if( fFetchAgentWriteCommand != NULL ) 916 { 917 fFetchAgentWriteCommand->release(); 918 fFetchAgentWriteCommand = NULL; 919 } 920 921 if( fFetchAgentWriteCommandMemory != NULL ) 922 { 923 fFetchAgentWriteCommandMemory->release(); 924 fFetchAgentWriteCommandMemory = NULL; 925 } 926 927 // 928 // deallocate status block address space 929 // 930 931 if( fStatusBlockAddressSpace != NULL && status == kIOReturnSuccess ) 932 { 933 fStatusBlockAddressSpace->deactivate(); 934 fStatusBlockAddressSpace->release(); 935 } 936 937 // 938 // deallocate old password address space 939 // 940 941 if( fPasswordAddressSpace != NULL ) 942 { 943 fPasswordAddressSpace->deactivate(); 944 fPasswordAddressSpace->release(); 945 fPasswordBuf = NULL; 946 fPasswordLen = 0; 947 } 948 949 if( fPasswordDescriptor != NULL ) 950 { 951 fPasswordDescriptor->release(); 952 fPasswordDescriptor = NULL; 953 } 954 955 // 956 // free unreleased orbs 957 // 958 959 if( fORBSetIterator ) 960 { 961 IOFireWireSBP2ORB * item = NULL; 962 do 963 { 964 fORBSetIterator->reset(); 965 item = (IOFireWireSBP2ORB *)fORBSetIterator->getNextObject(); 966 if( item ) 967 item->release(); 968 } while( item ); 969 970 fORBSetIterator->release(); 971 } 972 973 if( fORBSet ) 974 fORBSet->release(); 975 976 // clean up any dangling critical section disables 977 for( int i = 0; i < fCriticalSectionCount; i++ ) 978 { 979 fTarget->endIOCriticalSection(); 980 } 981 982 // 983 // destroy command gate 984 // 985 986 if( fGate != NULL ) 987 { 988 IOWorkLoop * workLoop = NULL; 989 990 workLoop = fGate->getWorkLoop(); 991 workLoop->removeEventSource( fGate ); 992 workLoop->release(); 993 994 fGate->release(); 995 fGate = NULL; 996 } 997 998 OSObject::free(); 999} 1000 1001#pragma mark - 1002///////////////////////////////////////////////////////////////////// 1003// accessors 1004// 1005 1006// get unit 1007 1008IOFireWireUnit * IOFireWireSBP2Login::getFireWireUnit( void ) 1009{ 1010 return fUnit; 1011} 1012 1013// get lun 1014 1015IOFireWireSBP2LUN * IOFireWireSBP2Login::getFireWireLUN( void ) 1016{ 1017 return fLUN; 1018} 1019 1020// get command block size 1021 1022UInt32 IOFireWireSBP2Login::getMaxCommandBlockSize( void ) 1023{ 1024 return fMaxCommandBlockSize; 1025} 1026 1027UInt32 IOFireWireSBP2Login::getLoginID( void ) 1028{ 1029 return fLoginID; 1030} 1031 1032// get / set refCon 1033 1034void IOFireWireSBP2Login::setRefCon( void * refCon ) 1035{ 1036 fRefCon = refCon; 1037} 1038 1039void * IOFireWireSBP2Login::getRefCon( void ) 1040{ 1041 return fRefCon; 1042} 1043 1044// get / set login flags 1045 1046void IOFireWireSBP2Login::setLoginFlags( UInt32 loginFlags ) 1047{ 1048 fLoginFlags = loginFlags; 1049 FWKLOG(( "IOFireWireSBP2Login<%p> : setLoginFlags : 0x%08lx\n", this, fLoginFlags )); 1050} 1051 1052UInt32 IOFireWireSBP2Login::getLoginFlags( void ) 1053{ 1054 return fLoginFlags; 1055} 1056 1057// set login and logout completion routines 1058 1059void IOFireWireSBP2Login::setLoginCompletion( void * refCon, FWSBP2LoginCallback completion ) 1060{ 1061 fLoginCompletionRefCon = refCon; 1062 fLoginCompletionCallback = completion; 1063} 1064 1065void IOFireWireSBP2Login::setLogoutCompletion( void * refCon, FWSBP2LogoutCallback completion ) 1066{ 1067 fLogoutCompletionRefCon = refCon; 1068 fLogoutCompletionCallback = completion; 1069} 1070 1071// get / set reconnect time 1072 1073void IOFireWireSBP2Login::setReconnectTime( UInt32 reconnectTime ) 1074{ 1075 fReconnectTime = reconnectTime & 0x0000000f; 1076} 1077 1078UInt32 IOFireWireSBP2Login::getReconnectTime( void ) 1079{ 1080 return fReconnectTime; 1081} 1082 1083// get / set status notify proc 1084 1085void IOFireWireSBP2Login::setStatusNotifyProc( void * refCon, FWSBP2NotifyCallback callback ) 1086{ 1087 fStatusNotifyCallback = callback; 1088 fStatusNotifyRefCon = refCon; 1089} 1090 1091void IOFireWireSBP2Login::getStatusNotifyProc( void ** refCon, FWSBP2NotifyCallback * callback ) 1092{ 1093 *callback = fStatusNotifyCallback; 1094 *refCon = fStatusNotifyRefCon; 1095} 1096 1097// get / set status notify proc 1098 1099void IOFireWireSBP2Login::setUnsolicitedStatusNotifyProc( void * refCon, FWSBP2NotifyCallback callback ) 1100{ 1101 fUnsolicitedStatusNotifyCallback = callback; 1102 fUnsolicitedStatusNotifyRefCon = refCon; 1103} 1104 1105void IOFireWireSBP2Login::getUnsolicitedStatusNotifyProc( void ** refCon, FWSBP2NotifyCallback * callback ) 1106{ 1107 *callback = fStatusNotifyCallback; 1108 *refCon = fStatusNotifyRefCon; 1109} 1110 1111// get / set max payload size 1112 1113void IOFireWireSBP2Login::setMaxPayloadSize( UInt32 maxPayloadSize ) 1114{ 1115 fMaxPayloadSize = maxPayloadSize; 1116} 1117 1118UInt32 IOFireWireSBP2Login::getMaxPayloadSize( void ) 1119{ 1120 return fMaxPayloadSize; 1121} 1122 1123void IOFireWireSBP2Login::setLoginRetryCountAndDelayTime( UInt32 retryCount, UInt32 uSecs ) 1124{ 1125 fLoginRetryMax = retryCount; 1126 fLoginRetryDelay = uSecs; 1127 1128 if( fLoginRetryTimeoutCommand ) 1129 { 1130 fLoginRetryTimeoutCommand->reinit( fLoginRetryDelay, IOFireWireSBP2Login::loginRetryTimeoutStatic, this ); 1131 } 1132} 1133 1134 1135// set password 1136// 1137// 1138 1139IOReturn IOFireWireSBP2Login::setPassword( IOMemoryDescriptor * memory ) 1140{ 1141 IOReturn status = kIOReturnSuccess; 1142 IOByteCount len = 0; 1143 1144 // 1145 // deallocate old password address space 1146 // 1147 1148 if( fPasswordAddressSpace != NULL ) 1149 { 1150 fPasswordAddressSpace->deactivate(); 1151 fPasswordAddressSpace->release(); 1152 fPasswordBuf = NULL; 1153 fPasswordLen = 0; 1154 } 1155 1156 if( fPasswordDescriptor != NULL ) 1157 { 1158 fPasswordDescriptor->release(); 1159 fPasswordDescriptor = NULL; 1160 } 1161 1162 if( status == kIOReturnSuccess ) 1163 { 1164 fPasswordDescriptor = memory; 1165 if( memory == NULL ) 1166 status = kIOReturnError; 1167 } 1168 1169 if( status == kIOReturnSuccess ) 1170 { 1171 fPasswordDescriptor->retain(); 1172 len = fPasswordDescriptor->getLength(); 1173 status = fPasswordDescriptor->prepare(); // for readBytes 1174 } 1175 1176 if( status == kIOReturnSuccess ) 1177 { 1178 if( len <= 8 ) 1179 { 1180 fLoginORB.password[0] = 0; 1181 fLoginORB.password[1] = 0; 1182 fLoginORB.passwordLength = 0; 1183 status = memory->readBytes( 0, &(fLoginORB.password), len ); 1184 } 1185 else 1186 { 1187 1188 // 1189 // allocate and register an address space for the password 1190 // 1191 1192 if( status == kIOReturnSuccess ) 1193 { 1194 fPasswordAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fPasswordAddress, memory ); 1195 if( fPasswordAddressSpace == NULL ) 1196 status = kIOReturnNoMemory; 1197 } 1198 1199 if( status == kIOReturnSuccess ) 1200 { 1201 status = fPasswordAddressSpace->activate(); 1202 } 1203 1204 if( status == kIOReturnSuccess ) 1205 { 1206 fLoginORB.passwordLength = OSSwapHostToBigInt16(len); 1207 fLoginORB.password[0] = OSSwapHostToBigInt32(0x0000ffff & fPasswordAddress.addressHi); 1208 fLoginORB.password[1] = OSSwapHostToBigInt32(fPasswordAddress.addressLo); 1209 } 1210 1211 } 1212 } 1213 1214 return status; 1215} 1216 1217// set password 1218// 1219// 1220 1221IOReturn IOFireWireSBP2Login::setPassword( void * buf, UInt32 len ) 1222{ 1223 IOReturn status = kIOReturnSuccess; 1224 1225 // 1226 // deallocate old password address space 1227 // 1228 1229 1230 if( fPasswordAddressSpace != NULL ) 1231 { 1232 fPasswordAddressSpace->deactivate(); 1233 fPasswordAddressSpace->release(); 1234 fPasswordBuf = NULL; 1235 fPasswordLen = 0; 1236 } 1237 1238 if( fPasswordDescriptor != NULL ) 1239 { 1240 fPasswordDescriptor->release(); 1241 fPasswordDescriptor = NULL; 1242 } 1243 1244 if( len <= 8 ) 1245 { 1246 fPasswordBuf = buf; 1247 fPasswordLen = len; 1248 1249 fLoginORB.password[0] = 0; 1250 fLoginORB.password[1] = 0; 1251 1252 bcopy( buf, &(fLoginORB.password), len ); 1253 fLoginORB.passwordLength = 0; 1254 } 1255 else 1256 { 1257 1258 // 1259 // allocate and register an address space for the password 1260 // 1261 1262 if( status == kIOReturnSuccess ) 1263 { 1264 fPasswordAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fPasswordAddress, len, buf ); 1265 if( fPasswordAddressSpace == NULL ) 1266 status = kIOReturnNoMemory; 1267 } 1268 1269 if( status == kIOReturnSuccess ) 1270 { 1271 status = fPasswordAddressSpace->activate(); 1272 } 1273 1274 if( status == kIOReturnSuccess ) 1275 { 1276 fPasswordBuf = buf; 1277 fPasswordLen = len; 1278 fLoginORB.passwordLength = OSSwapHostToBigInt16(len); 1279 fLoginORB.password[0] = OSSwapHostToBigInt32(0x0000ffff & fPasswordAddress.addressHi); 1280 fLoginORB.password[1] = OSSwapHostToBigInt32(fPasswordAddress.addressLo); 1281 } 1282 1283 } 1284 1285 return status; 1286} 1287 1288// setLoginGeneration 1289// 1290// 1291 1292void IOFireWireSBP2Login::setLoginGeneration( UInt32 generation ) 1293{ 1294 fUserLoginGeneration = generation; 1295 fUserLoginGenerationSet = true; 1296} 1297 1298// clearLoginGeneration 1299// 1300// 1301 1302void IOFireWireSBP2Login::clearLoginGeneration( void ) 1303{ 1304 fUserLoginGenerationSet = false; 1305} 1306 1307#pragma mark - 1308///////////////////////////////////////////////////////////////////// 1309// 1310// login path 1311// 1312 1313// submitLogin 1314// 1315// 1316 1317IOReturn IOFireWireSBP2Login::submitLogin( void ) 1318{ 1319 IOReturn status = kIOReturnSuccess; 1320 1321 status = fGate->runAction( staticExecuteLogin ); 1322 1323 return status; 1324} 1325 1326IOReturn IOFireWireSBP2Login::staticExecuteLogin( OSObject *self, void *, void *, void *, void * ) 1327{ 1328 return ((IOFireWireSBP2Login *)self)->initialExecuteLogin(); 1329} 1330 1331IOReturn IOFireWireSBP2Login::initialExecuteLogin( void ) 1332{ 1333 IOReturn status = kIOReturnSuccess; 1334 1335 if( fLoginState != kLoginStateIdle || fLoginRetryTimeoutTimerSet ) 1336 { 1337 return kIOReturnExclusiveAccess; 1338 } 1339 1340 fLoginRetryCount = fLoginRetryMax; 1341 1342 status = executeLogin(); 1343 if( status != kIOReturnSuccess && 1344 ((status != kIOFireWireBusReset) || !fUserLoginGenerationSet) && 1345 fLoginRetryCount != 0 ) 1346 { 1347 fLoginRetryCount--; 1348 startLoginRetryTimer(); 1349 status = kIOReturnSuccess; 1350 } 1351 1352 return status; 1353} 1354 1355IOReturn IOFireWireSBP2Login::executeLogin( void ) 1356{ 1357 IOReturn status = kIOReturnSuccess; 1358 1359 FWKLOG( ( "IOFireWireSBP2Login<%p> : executeLogin\n", this ) ); 1360 1361 if( fSuspended ) 1362 { 1363 return kIOFireWireBusReset; 1364 } 1365 1366 if( fLoginState != kLoginStateIdle ) 1367 { 1368 return kIOReturnExclusiveAccess; 1369 } 1370 1371 fLoginState = kLoginStateLoggingIn; // set state 1372 1373 if( fLastORB ) 1374 { 1375 fLastORB->release(); 1376 fLastORB = NULL; 1377 } 1378 1379 fLastORBAddress = FWAddress(0,0); 1380 1381 // to quote sbp-2 : ... truncated login response data 1382 // shall be interpreted as if the omitted fields 1383 // had been stored as zeros. ... 1384 1385 fLoginResponse.reserved = 0; 1386 fLoginResponse.reconnectHold = 0; 1387 1388 // set options 1389 FWKLOG(( "IOFireWireSBP2Login<%p> : fLoginFlags : 0x%08lx\n", this, fLoginFlags )); 1390 1391 fLoginORB.options = OSSwapHostToBigInt16(0x0000 | 0x8000); // login | notify 1392 fLoginORB.options |= OSSwapHostToBigInt16(fReconnectTime << 4); 1393 if( fLoginFlags & kFWSBP2ExclusiveLogin ) 1394 fLoginORB.options |= OSSwapHostToBigInt16(0x1000); 1395 1396 // set to correct generation 1397 fLoginWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 1398 fLoginWriteCommandMemory, IOFireWireSBP2Login::loginWriteCompleteStatic, 1399 this, true ); 1400 1401 // get local node and generation 1402 // note: these two are latched affter command gen is set and before submit is called 1403 // if these are old command will fail 1404 fUnit->getNodeIDGeneration(fLoginGeneration, fLoginNodeID, fLocalNodeID); 1405 1406 if( fUserLoginGenerationSet && fUserLoginGeneration != fLoginGeneration ) 1407 { 1408 status = kIOFireWireBusReset; 1409 } 1410 1411 if( status == kIOReturnSuccess ) 1412 { 1413 fLoginWriteInProgress = true; 1414 fLoginStatusReceived = false; 1415 status = fTarget->beginIOCriticalSection(); 1416 } 1417 1418 if( status == kIOReturnSuccess ) 1419 { 1420 fInCriticalSection = true; 1421 fCriticalSectionCount++; 1422 1423 if( fLoginFlags & kFWSBP2DontSynchronizeMgmtAgent ) 1424 fLoginWriteCommand->submit(); 1425 else 1426 fTarget->synchMgmtAgentAccess( fLoginWriteCommand ); 1427 } 1428 1429 if( status != kIOReturnSuccess ) 1430 { 1431 fLoginWriteInProgress = false; 1432 fLoginState = kLoginStateIdle; 1433 } 1434 1435 return status; 1436} 1437 1438// 1439// login write completion 1440// 1441 1442void IOFireWireSBP2Login::loginWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, 1443 IOFWCommand *fwCmd ) 1444{ 1445 ((IOFireWireSBP2Login*)refcon)->loginWriteComplete( status, device, fwCmd ); 1446} 1447 1448void IOFireWireSBP2Login::loginWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 1449{ 1450 FWKLOG( ("IOFireWireSBP2Login<%p> : login write complete\n", this) ); 1451 1452 fLoginWriteInProgress = false; 1453 1454 if( fLoginStatusReceived ) 1455 { 1456 processLoginWrite(); 1457 } 1458 else 1459 { 1460 if( status == kIOReturnSuccess ) 1461 { 1462 // we wrote the management agent, now set a timer and wait for response & status 1463 fLoginTimeoutTimerSet = true; 1464 if( fLoginTimeoutCommand->submit() != kIOReturnSuccess ) 1465 fLoginTimeoutTimerSet = false; 1466 } 1467 else 1468 { 1469 fLoginState = kLoginStateIdle; 1470 completeLogin( status ); // complete with error 1471 } 1472 } 1473} 1474 1475// 1476// login timeout 1477// 1478 1479void IOFireWireSBP2Login::loginTimeoutStatic( void *refcon, IOReturn status, 1480 IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1481{ 1482 ((IOFireWireSBP2Login*)refcon)->loginTimeout( status, bus, fwCmd ); 1483} 1484 1485void IOFireWireSBP2Login::loginTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1486{ 1487 fLoginTimeoutTimerSet = false; 1488 if( status != kIOReturnSuccess ) 1489 { 1490 FWKLOG( ("IOFireWireSBP2Login<%p> : login timed out\n", this) ); 1491 1492 // init state machine 1493 fLoginState = kLoginStateIdle; 1494 completeLogin( kIOReturnTimeout ); 1495 } 1496} 1497 1498// login retry timeout 1499// 1500// 1501 1502void IOFireWireSBP2Login::startLoginRetryTimer( void ) 1503{ 1504 stopLoginRetryTimer(); 1505 1506 fLoginRetryTimeoutTimerSet = true; 1507 if( fLoginRetryTimeoutCommand->submit() != kIOReturnSuccess ) 1508 fLoginRetryTimeoutTimerSet = false; 1509} 1510 1511void IOFireWireSBP2Login::stopLoginRetryTimer( void ) 1512{ 1513 // cancel timeout 1514 if( fLoginRetryTimeoutTimerSet ) 1515 fLoginRetryTimeoutCommand->cancel( kIOReturnAborted ); 1516} 1517 1518void IOFireWireSBP2Login::loginRetryTimeoutStatic( void *refcon, IOReturn status, 1519 IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1520{ 1521 ((IOFireWireSBP2Login*)refcon)->loginRetryTimeout( status, bus, fwCmd ); 1522} 1523 1524void IOFireWireSBP2Login::loginRetryTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1525{ 1526 fLoginRetryTimeoutTimerSet = false; 1527 if( status == kIOReturnTimeout ) 1528 { 1529 FWKLOG( ("IOFireWireSBP2Login<%p> : login retry timer fired\n", this) ); 1530 1531 IOReturn login_status = executeLogin(); 1532 if( login_status != kIOReturnSuccess ) 1533 { 1534 completeLogin( login_status ); 1535 } 1536 } 1537} 1538 1539void IOFireWireSBP2Login::abortLogin( void ) 1540{ 1541 // if we're in the middle of a login write, we need to cancel it 1542 // before aborting the command 1543 if( fLoginWriteInProgress ) 1544 fLoginWriteCommand->cancel( kIOReturnAborted ); 1545 1546 // cancel timeout 1547 if( fLoginTimeoutTimerSet ) 1548 fLoginTimeoutCommand->cancel( kIOReturnAborted ); 1549 1550 // set state 1551 fLoginState = kLoginStateIdle; 1552 1553 // complete command 1554// completeLogin( kIOReturnTimeout ); //zzz is this a good error?, this is what OS9 returns 1555} 1556 1557void IOFireWireSBP2Login::completeLogin( IOReturn state, const void *buf, UInt32 len, void * buf2 ) 1558{ 1559 FWKLOG( ( "IOFireWireSBP2Login<%p> : completeLogin\n", this ) ); 1560 1561 if( (fLoginFlags & kFWSBP2DontSynchronizeMgmtAgent) == 0 ) 1562 fTarget->completeMgmtAgentAccess( ); 1563 1564 if( fInCriticalSection ) 1565 { 1566 fInCriticalSection = false; 1567 if( fCriticalSectionCount > 0 ) 1568 { 1569 fCriticalSectionCount--; 1570 } 1571 fTarget->endIOCriticalSection(); 1572 } 1573 1574 if( (state != kIOReturnSuccess) && 1575 ((state != kIOFireWireBusReset) || !fUserLoginGenerationSet) && 1576 (state != kIOReturnNotAttached) && 1577 (fLoginRetryCount != 0) ) 1578 { 1579 fLoginRetryCount--; 1580 startLoginRetryTimer(); 1581 } 1582 else if( fLoginCompletionCallback != NULL ) 1583 { 1584 FWSBP2LoginCompleteParams params; 1585 1586 // try enabling unsolicited status now 1587 if( fUnsolicitedStatusEnableRequested ) 1588 { 1589 fUnsolicitedStatusEnableRequested = false; 1590 executeUnsolicitedStatusEnable(); 1591 } 1592 1593 params.login = this; 1594 params.generation = fLoginGeneration; 1595 1596 params.status = state; 1597 params.loginResponse = (FWSBP2LoginResponsePtr)buf2; 1598 params.statusBlock = (FWSBP2StatusBlock*)buf; 1599 params.statusBlockLength = len; 1600 1601 (*fLoginCompletionCallback)(fLoginCompletionRefCon, ¶ms); 1602 } 1603} 1604 1605// 1606// status block handlers 1607// 1608 1609UInt32 IOFireWireSBP2Login::statusBlockWriteStatic(void *refcon, UInt16 nodeID, IOFWSpeed &speed, 1610 FWAddress addr, UInt32 len, const void *buf, IOFWRequestRefCon lockRead) 1611{ 1612 return ((IOFireWireSBP2Login*)refcon)->statusBlockWrite( nodeID, speed, addr, len, buf, lockRead ); 1613} 1614 1615UInt32 IOFireWireSBP2Login::statusBlockWrite( UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len, 1616 const void *buf, IOFWRequestRefCon lockRead ) 1617{ 1618 FWKLOG( ( "IOFireWireSBP2Login<%p> : status block write\n", this ) ); 1619 1620 1621 if( len < 8 ) 1622 { 1623 // IOLog( "IOFireWireSBP2Login<0x%08lx> : illegal status block length = %d\n", this, len ); 1624 return kFWResponseComplete; 1625 } 1626 1627 bzero( &fStatusBlock, sizeof(fStatusBlock) ); 1628 1629 //����������������� 1630 if( len < sizeof(fStatusBlock) ) 1631 bcopy( buf, &fStatusBlock, len); 1632 else 1633 bcopy( buf, &fStatusBlock, sizeof(fStatusBlock)); 1634 1635 const void * client_status_block = &fStatusBlock; 1636 1637#if 0 1638 // compatibility hack for Craig's layer 1639 1640 FWSBP2StatusBlock host_status_block; 1641 1642 bzero( &host_status_block, sizeof(host_status_block) ); 1643 bcopy( &fStatusBlock, &host_status_block, sizeof(host_status_block)); 1644 1645 host_status_block.orbOffsetHi = OSSwapBigToHostInt16(fStatusBlock.orbOffsetHi); 1646 host_status_block.orbOffsetLo = OSSwapBigToHostInt32(fStatusBlock.orbOffsetLo); 1647 1648 SBP2SwapBigToHostInt32Array( &host_status_block.status, sizeof(host_status_block.status) ); 1649 1650 client_status_block = &host_status_block; 1651#endif 1652 1653 switch( fLoginState ) 1654 { 1655 case kLoginStateLoggingIn: 1656 1657 // complete login 1658 1659 // cancel timeout 1660 if( fLoginTimeoutTimerSet ) 1661 { 1662 fLoginTimeoutCommand->cancel(kIOReturnSuccess); 1663 } 1664 1665 if( !fLoginStatusReceived ) 1666 { 1667 bzero( &fLoginStatusBlock, sizeof(fLoginStatusBlock) ); 1668 1669 //����������������� 1670 if( len < sizeof(fLoginStatusBlock) ) 1671 bcopy( buf, &fLoginStatusBlock, len); 1672 else 1673 bcopy( buf, &fLoginStatusBlock, sizeof(fLoginStatusBlock)); 1674 1675 fLoginStatusBlockLen = len; 1676 1677 if( fLoginWriteInProgress ) 1678 { 1679 fLoginStatusReceived = true; 1680 } 1681 else 1682 { 1683 processLoginWrite(); 1684 } 1685 } 1686 1687 break; 1688 1689 case kLoginStateConnected: 1690 // orb related or unsolicited 1691 1692 if( (fStatusBlock.details & 0xc0) == 0x80 ) 1693 { 1694 // send unsolicited status 1695 if( fUnsolicitedStatusNotifyCallback != NULL ) 1696 { 1697 FWSBP2NotifyParams params; 1698 1699 params.message = client_status_block; 1700 params.length = len; 1701 params.notificationEvent = kFWSBP2UnsolicitedStatus; 1702 params.generation = fLoginGeneration; 1703 (*fUnsolicitedStatusNotifyCallback)(fUnsolicitedStatusNotifyRefCon, ¶ms ); 1704 } 1705 1706 } 1707 else 1708 { 1709 // normal command orb 1710 1711 // find ORB 1712 bool found = false; 1713 1714 FWAddress notificationAddress; 1715 notificationAddress.nodeID = 0x0000; 1716 notificationAddress.addressHi = OSSwapBigToHostInt16(fStatusBlock.orbOffsetHi); 1717 notificationAddress.addressLo = OSSwapBigToHostInt32(fStatusBlock.orbOffsetLo); 1718 1719 IOFireWireSBP2ORB * item = NULL; 1720 fORBSetIterator->reset(); 1721 while( (found != true) && (item = (IOFireWireSBP2ORB *) fORBSetIterator->getNextObject()) ) 1722 { 1723 FWAddress address; 1724 item->getORBAddress( &address ); 1725 if( (notificationAddress.addressHi & 0x0000ffff) == (address.addressHi & 0x0000ffff) && 1726 notificationAddress.addressLo == address.addressLo ) 1727 { 1728 found = true; 1729 } 1730 } 1731 1732 FWKLOG( ( "IOFireWireSBP2Login<%p> : solicited found = %d\n", this, found ) ); 1733 1734 bool deadBitIsSet = fStatusBlock.details & 0x08; 1735 1736 if( found ) 1737 { 1738 UInt32 flags = item->getCommandFlags(); 1739 1740 // cancel timer if set 1741 if( isORBTimerSet( item ) ) 1742 { 1743 cancelORBTimer( item); 1744 1745 if( isORBAppended( item ) ) 1746 { 1747 setORBIsAppended( item, false ); 1748 if( fCriticalSectionCount > 0 ) 1749 { 1750 fCriticalSectionCount--; 1751 } 1752 fTarget->endIOCriticalSection(); 1753 } 1754 } 1755 else if( flags & kFWSBP2CommandCompleteNotify ) 1756 { 1757 // if timer went off and then we get status, just ignore status. 1758 // late arriving status will be discarded unless timeout duration is changed to zero 1759 // at which point we can't tell that there ever was a timer running 1760 break; 1761 } 1762 1763 // send solicited status 1764 1765 if( fStatusNotifyCallback != NULL ) 1766 { 1767 FWSBP2NotifyParams params; 1768 1769 params.message = client_status_block; 1770 params.length = len; 1771 params.notificationEvent = kFWSBP2NormalCommandStatus; 1772 params.generation = fLoginGeneration; 1773 params.commandObject = item; 1774 (*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms ); 1775 } 1776 } 1777 1778 if( deadBitIsSet ) 1779 { 1780 // all tasks are aborted 1781 clearAllTasksInSet(); 1782 } 1783 } 1784 1785 break; 1786 1787 case kLoginStateLoggingOut: 1788 1789 // cancel timeout 1790 if( fLogoutTimeoutTimerSet ) 1791 { 1792 fLogoutTimeoutCommand->cancel(kIOReturnSuccess); 1793 } 1794 1795 // success or not 1796 if( ((fStatusBlock.details >> 4) & 3) == kFWSBP2RequestComplete && 1797 fStatusBlock.sbpStatus == kFWSBP2NoSense ) 1798 { 1799 FWKLOG( ( "IOFireWireSBP2Login<%p> : successful logout\n", this ) ); 1800 fLoginState = kLoginStateIdle; 1801 fUnsolicitedStatusEnableRequested = false; 1802 1803 // get login ID and fetch agent address 1804 fLoginID = OSSwapBigToHostInt16(fLoginResponse.loginID); 1805 completeLogout( kIOReturnSuccess, client_status_block, len ); 1806 } 1807 else 1808 { 1809 FWKLOG( ( "IOFireWireSBP2Login<%p> : logout failed!?\n", this ) ); 1810 fLoginState = kLoginStateIdle; 1811 completeLogout( kIOReturnError, client_status_block, len ); 1812 } 1813 1814 // all tasks are aborted 1815 clearAllTasksInSet(); 1816 1817 break; 1818 1819 case kLoginStateReconnect: 1820 case kLoginStateIdle: 1821 default: 1822 FWKLOG( ( "IOFireWireSBP2Login<%p> : status block write on illegal state\n", this ) ); 1823 break; 1824 } 1825 1826 return kFWResponseComplete; 1827} 1828 1829// processLoginWrite 1830// 1831// 1832 1833void IOFireWireSBP2Login::processLoginWrite( void ) 1834{ 1835 // success or not 1836 if( ((fLoginStatusBlock.details >> 4) & 3) == kFWSBP2RequestComplete && 1837 fLoginStatusBlock.sbpStatus == kFWSBP2NoSense ) 1838 { 1839 FWKLOG( ( "IOFireWireSBP2Login<%p> : successful login\n", this ) ); 1840 1841 // get login ID and fetch agent address 1842 fLoginID = OSSwapBigToHostInt16(fLoginResponse.loginID); 1843 fReconnectORB.loginID = OSSwapHostToBigInt16(fLoginID); // set id for reconnect; 1844 1845 // set reconnect_hold, some devices indicate it 1846 if( OSSwapBigToHostInt16(fLoginResponse.length) >= 16 ) 1847 fReconnectHold = (OSSwapBigToHostInt16(fLoginResponse.reconnectHold) & 0x7fff) + 1; 1848 else 1849 fReconnectHold = 1; 1850 1851 UInt32 commandBlockAgentAddressHi = OSSwapBigToHostInt32(fLoginResponse.commandBlockAgentAddressHi); 1852 UInt32 commandBlockAgentAddressLo = OSSwapBigToHostInt32(fLoginResponse.commandBlockAgentAddressLo); 1853 1854 // set fetch agent reset address 1855 fFetchAgentResetAddress = FWAddress( commandBlockAgentAddressHi & 0x0000ffff, 1856 commandBlockAgentAddressLo + 0x00000004 ); 1857 1858 fFetchAgentResetCommand->reinit( fFetchAgentResetAddress, 1859 &fFetchAgentResetBuffer, 1, 1860 IOFireWireSBP2Login::fetchAgentResetCompleteStatic, 1861 this, true ); 1862 fFetchAgentResetCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 1863 1864 // set fetch agent address 1865 if( fFastStartSupported ) 1866 { 1867 fFetchAgentAddress = FWAddress( commandBlockAgentAddressHi & 0x0000ffff, 1868 commandBlockAgentAddressLo + (fFastStartOffset << 2)); 1869 } 1870 else 1871 { 1872 fFetchAgentAddress = FWAddress( commandBlockAgentAddressHi & 0x0000ffff, 1873 commandBlockAgentAddressLo + 0x00000008); 1874 } 1875 1876 fFetchAgentWriteCommand->reinit( fFetchAgentAddress, // tis determined 1877 fFetchAgentWriteCommandMemory, 1878 IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true ); 1879 fFetchAgentWriteCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 1880 fFetchAgentWriteCommand->setRetries( 0 ); 1881 1882 // set doorbell reset address 1883 fDoorbellAddress = FWAddress( commandBlockAgentAddressHi & 0x0000ffff, 1884 commandBlockAgentAddressLo + 0x00000010 ); 1885 1886 fDoorbellCommand->reinit( fDoorbellAddress, 1887 &fDoorbellBuffer, 1, 1888 IOFireWireSBP2Login::doorbellCompleteStatic, 1889 this, true ); 1890 fDoorbellCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 1891 1892 // set unsolicited status enable address 1893 fUnsolicitedStatusEnableAddress = FWAddress( commandBlockAgentAddressHi & 0x0000ffff, 1894 commandBlockAgentAddressLo + 0x00000014 ); 1895 1896 fUnsolicitedStatusEnableCommand->reinit( fUnsolicitedStatusEnableAddress, 1897 &fUnsolicitedStatusEnableBuffer, 1, 1898 IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic, 1899 this, true ); 1900 fUnsolicitedStatusEnableCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 1901 1902 fLoginState = kLoginStateConnected; 1903 1904 completeLogin( kIOReturnSuccess, &fLoginStatusBlock, fLoginStatusBlockLen, &fLoginResponse ); 1905 } 1906 else 1907 { 1908 FWKLOG( ( "IOFireWireSBP2Login<%p> : login failed\n", this ) ); 1909 fLoginState = kLoginStateIdle; 1910 1911 completeLogin( kIOReturnError, &fLoginStatusBlock, fLoginStatusBlockLen, NULL ); 1912 } 1913} 1914 1915#pragma mark - 1916///////////////////////////////////////////////////////////////////// 1917// 1918// reconnect path 1919// 1920 1921// 1922// suspendedNotify method 1923// 1924// called when a suspended message is received 1925 1926void IOFireWireSBP2Login::suspendedNotify( void ) 1927{ 1928 FWKLOG( ( "IOFireWireSBP2Login<%p> : suspendedNotify\n", this ) ); 1929 1930 fSuspended = true; 1931 1932 UInt32 generation = fControl->getGeneration(); 1933 1934 stopFetchAgentRetryTimer(); // better stop fetch agent retry timer on a bus reset 1935 1936 switch( fLoginState ) 1937 { 1938 case kLoginStateConnected: 1939 // start/restart timer 1940 startReconnectTimer(); 1941 break; 1942 1943 case kLoginStateReconnect: 1944 // cancel any pending reconnect retries 1945 stopReconnectRetryTimer(); 1946 1947 // start/restart timer 1948 startReconnectTimer(); 1949 break; 1950 1951 case kLoginStateLoggingIn: 1952 // login is valid until generation changes 1953 if( fLoginGeneration != generation ) 1954 { 1955 abortLogin(); 1956 } 1957 break; 1958 1959 case kLoginStateIdle: 1960 case kLoginStateLoggingOut: 1961 default: 1962 FWKLOG( ("IOFireWireSBP2Login<%p> : suspended notify, nothing to do\n", this) ); 1963 break; 1964 } 1965} 1966 1967// 1968// resumeNotify method 1969// 1970// called when a resume message is received 1971 1972void IOFireWireSBP2Login::resumeNotify( void ) 1973{ 1974 FWKLOG( ( "IOFireWireSBP2Login<%p> : resume notify\n", this ) ); 1975 1976 UInt32 generation = fControl->getGeneration(); 1977 fPhysicalAccessEnabled = fUnit->isPhysicalAccessEnabled(); 1978 1979 fSuspended = false; 1980 1981 executeSetBusyTimeout(); //can handle interruption 1982 1983 if( fLogoutPending ) 1984 { 1985 fLogoutPending = false; 1986 executeLogout(); 1987 } 1988 else 1989 { 1990 switch( fLoginState ) 1991 { 1992 case kLoginStateReconnect: 1993 if( fLoginGeneration != generation ) 1994 { 1995 // start/restart reconnect 1996 restartReconnect(); 1997 } 1998 else 1999 { 2000 // already logged in this generation 2001 fLoginState = kLoginStateConnected; 2002 if( fReconnectTimeoutTimerSet ) 2003 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 2004 } 2005 break; 2006 2007 case kLoginStateLoggingIn: 2008 // login is valid until generation changes 2009 if( fLoginGeneration != generation) 2010 { 2011 abortLogin(); 2012 } 2013 break; 2014 2015 case kLoginStateIdle: 2016 case kLoginStateLoggingOut: 2017 case kLoginStateConnected: 2018 default: 2019 FWKLOG( ("IOFireWireSBP2Login<%p> : resume notify, nothing to do\n", this) ); 2020 break; 2021 } 2022 } 2023} 2024 2025// terminateNotify method 2026// 2027// called when a terminated message is received 2028 2029void IOFireWireSBP2Login::terminateNotify( void ) 2030{ 2031 FWKLOG( ( "IOFireWireSBP2Login<%p> : terminate notify\n", this ) ); 2032 2033 if( fLogoutPending ) 2034 { 2035 fLogoutPending = false; 2036 } 2037 else 2038 { 2039 switch( fLoginState ) 2040 { 2041 case kLoginStateReconnect: 2042 if( fReconnectTimeoutTimerSet ) 2043 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 2044 break; 2045 2046 case kLoginStateLoggingIn: 2047 abortLogin(); 2048 break; 2049 2050 case kLoginStateIdle: 2051 case kLoginStateLoggingOut: 2052 case kLoginStateConnected: 2053 case kLoginStateTerminated: 2054 default: 2055 FWKLOG( ("IOFireWireSBP2Login<%p> : terminate notify, nothing to do\n", this) ); 2056 break; 2057 } 2058 2059 // cancel timeout 2060 if( fLoginRetryTimeoutTimerSet ) 2061 { 2062 fLoginRetryTimeoutCommand->cancel( kIOReturnAborted ); 2063 fLoginState = kLoginStateTerminated; 2064 completeLogin( kIOReturnNotAttached ); 2065 } 2066 } 2067} 2068 2069// startReconnectTimer 2070// 2071// 2072 2073void IOFireWireSBP2Login::startReconnectTimer( void ) 2074{ 2075 IOReturn status = kIOReturnSuccess; 2076 2077 fLoginState = kLoginStateReconnect; 2078 2079 if( fReconnectTimeoutTimerSet ) 2080 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 2081 2082 FWKLOGASSERT( status == kIOReturnSuccess ); 2083 2084 // start a reconnect timer 2085 2086 // even if a device went away 2087 // we want to keep trying for up to the reconnect timeout. maybe we'll get 2088 // another bus reset and the device will be back, and still willing to reconnect 2089 2090 // this assumes that transient errors might cause us to loose sight of the device 2091 // for short periods (shorter than the timeout). if the reconnect timeout is 2092 // really large (several seconds) then maybe we'll wait too long. 2093 2094 // zzz some devices wait until the end of the reconnect interval before they 2095 // acknowledge a reconnect. that seems bad, but for now add one second of fudge 2096 // factor so we can tolerate this. 2097 2098 // reconnect hold is in seconds, createDelayed cmd expects microseconds 2099 2100 fReconnectTimeoutCommand->reinit( ((fManagementTimeout + 1000) * 1000), 2101 IOFireWireSBP2Login::reconnectTimeoutStatic, this); 2102 2103 // we wrote the management agent, now set a timer and wait for response & status 2104 fReconnectTimeoutTimerSet = true; 2105 2106 status = fReconnectTimeoutCommand->submit(); 2107 if( status != kIOReturnSuccess ) 2108 { 2109 fReconnectTimeoutTimerSet = false; 2110 } 2111 2112#if FWLOGGING 2113 if( fReconnectTimeoutTimerSet ) 2114 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect timeout set for %d microseconds \n", this, ((fManagementTimeout + 1000) * 1000)) ); 2115#endif 2116 2117} 2118 2119// doReconnect 2120// 2121// called when we recieve bus reset notification while we're logged in 2122// also called if we get a second reset while reconnecting, but only after 2123// the first reconnect attempt has been cleaned up. 2124// 2125// starts reconnect processs by writing a reconnect ORB to the target 2126// the remainder of the process occurs after the write command complete 2127 2128void IOFireWireSBP2Login::doReconnect( void ) 2129{ 2130 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect\n", this) ); 2131 2132 IOReturn status = fTarget->beginIOCriticalSection(); 2133 if( status != kIOReturnSuccess ) 2134 { 2135 IOLog( "IOFireWireSBP2Login<0x%08lx>::doReconnect fTarget->beginIOCriticalSection() returned 0x%08lx\n", (UInt32)status); 2136 return; 2137 } 2138 2139 fInCriticalSection = true; 2140 fCriticalSectionCount++; 2141 2142 // set to correct generation 2143 fReconnectWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 2144 fReconnectWriteCommandMemory, IOFireWireSBP2Login::reconnectWriteCompleteStatic, 2145 this, true ); 2146 2147 // get local node and generation 2148 // note: these two are latched after command gen is set and before submit is called 2149 // if these are old command will fail 2150 fUnit->getNodeIDGeneration(fLoginGeneration, fLoginNodeID, fLocalNodeID); 2151 2152 fReconnectWriteInProgress = true; 2153 2154 if( fLoginFlags & kFWSBP2DontSynchronizeMgmtAgent ) 2155 status = fReconnectWriteCommand->submit(); 2156 else 2157 status = fTarget->synchMgmtAgentAccess( fReconnectWriteCommand ); 2158 2159 if( status == kIOFireWireBusReset ) 2160 { 2161 fReconnectWriteInProgress = false; 2162 } 2163 else if( status != kIOReturnSuccess ) 2164 { 2165 fLoginState = kLoginStateIdle; 2166 fReconnectWriteInProgress = false; 2167 sendReconnectNotification( kIOMessageFWSBP2ReconnectFailed ); 2168 } 2169 2170} 2171 2172// restartReconnect 2173// 2174// Called if we get a bus reset while we are already trying to reconnect. 2175// Per sbp-2, the entire reconnect process (and timer) starts over again. 2176// So we clean up the in-progress reconnect attempt and try again. 2177 2178void IOFireWireSBP2Login::restartReconnect( void ) 2179{ 2180 // we may be in two possible states 2181 // (1) we are waiting for the reconnect write to complete 2182 // (2) we are waiting for either the timer to go off or a response from the target 2183 2184 // case (1) 2185 2186 if( fReconnectWriteInProgress ) 2187 { 2188 // the write will fail with a bus reset error, unless it is already 2189 // complete and waiting for completion to happen. 2190 // (can that happen? does completion get called immediately, or is it q'd?) 2191 // 2192 // in any case, we know that it has not run yet, so we just make a note about this 2193 // new reset, so that when it does run, it can continue to work. That way, even if 2194 // it thought the write completed, it can immediately start over. 2195 // the reset makes even a completed write pointless. 2196 2197 fReconnectWriteInterrupted = true; 2198 } 2199 else 2200 { 2201 // case (2) 2202 2203 // we already wrote the reconnect ORB to the target and we are waiting for either a 2204 // timeout or a response from the target. 2205 // 2206 2207 // restart reconnect 2208 doReconnect(); 2209 2210 //zzz what if timer has gone off but not run? 2211 } 2212} 2213 2214// 2215// reconnect write completion handler 2216// 2217 2218void IOFireWireSBP2Login::reconnectWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, 2219 IOFWCommand *fwCmd ) 2220{ 2221 ((IOFireWireSBP2Login*)refcon)->reconnectWriteComplete( status, device, fwCmd ); 2222} 2223 2224void IOFireWireSBP2Login::reconnectWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 2225{ 2226 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnectWriteComplete \n", this) ); 2227 2228 fReconnectWriteInProgress = false; 2229 2230 if( fReconnectWriteInterrupted ) 2231 { 2232 fReconnectWriteInterrupted = false; 2233 doReconnect(); 2234 } 2235 else if( status == kIOFireWireResponseBase+kFWResponseConflictError ) 2236 { 2237 // retry reconnect 2238 startReconnectRetryTimer(); 2239 } 2240} 2241 2242// 2243// reconnect timeout handler 2244// 2245 2246void IOFireWireSBP2Login::reconnectTimeoutStatic( void *refcon, IOReturn status, IOFireWireBus *bus, 2247 IOFWBusCommand *fwCmd ) 2248{ 2249 ((IOFireWireSBP2Login*)refcon)->reconnectTimeout( status, bus, fwCmd ); 2250} 2251 2252void IOFireWireSBP2Login::reconnectTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 2253{ 2254 fReconnectTimeoutTimerSet = false; 2255 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect timeout proc, status = 0x%08lx\n", this, status) ); 2256 2257 if( fInCriticalSection ) 2258 { 2259 fInCriticalSection = false; 2260 if( fCriticalSectionCount > 0 ) 2261 { 2262 fCriticalSectionCount--; 2263 } 2264 fTarget->endIOCriticalSection(); 2265 } 2266 2267 if(status == kIOReturnTimeout) 2268 { 2269 FWKLOG( ("IOFireWireSBP2Login<0x%08lx> : reconnect timeout\n") ); 2270 2271 // only send failure notification if we really failed 2272 // zzz is this necessary 2273 if( fLoginState == kLoginStateReconnect ) 2274 { 2275 // reset state machine 2276 fLoginState = kLoginStateIdle; 2277 2278 // stop any retries that might have been in progress 2279 stopReconnectRetryTimer(); 2280 2281 if( fLogoutPending ) 2282 executeLogout(); 2283 else 2284 sendReconnectNotification( kIOMessageFWSBP2ReconnectFailed ); 2285 } 2286 } 2287} 2288 2289// 2290// reconnect status block handler 2291// 2292 2293UInt32 IOFireWireSBP2Login::reconnectStatusBlockWriteStatic(void *refcon, UInt16 nodeID, IOFWSpeed &speed, 2294 FWAddress addr, UInt32 len, const void *buf, 2295 IOFWRequestRefCon lockRead) 2296{ 2297 return ((IOFireWireSBP2Login*)refcon)->reconnectStatusBlockWrite( nodeID, speed, addr, len, buf, lockRead ); 2298} 2299 2300UInt32 IOFireWireSBP2Login::reconnectStatusBlockWrite( UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, 2301 UInt32 len, const void *buf, IOFWRequestRefCon lockRead ) 2302{ 2303 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect status block write\n", this) ); 2304 2305//IOLog("length %ld contents %08lx %08lx\n", len, *((UInt32 *)buf), *(1+(UInt32 *)buf) ); 2306 2307 // this is possibly a belated reconnect acknowledgement. if so ignore it 2308 if( !fReconnectTimeoutTimerSet ) 2309 { 2310 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect status block write after timer went off\n", this) ); 2311 return kFWResponseComplete; 2312 } 2313 2314 // this is possibly a write that came in before the most recent bus reset 2315 // if so ignore it 2316 if( fLoginGeneration != fControl->getGeneration() ) 2317 { 2318 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect status block write for wrong generation\n", this) ); 2319 return kFWResponseComplete; 2320 } 2321 2322 bzero( &fReconnectStatusBlock, sizeof(fReconnectStatusBlock) ); 2323 2324 if( len < sizeof(fReconnectStatusBlock) ) 2325 bcopy( buf, &fReconnectStatusBlock, len); 2326 else 2327 bcopy( buf, &fReconnectStatusBlock, sizeof(fReconnectStatusBlock)); 2328 2329 // erfolgreich �der nicht? 2330 if( ( ( ( fReconnectStatusBlock.details >> 4 ) & 3 ) == kFWSBP2RequestComplete ) && 2331 ( fReconnectStatusBlock.sbpStatus == kFWSBP2NoSense ) ) 2332 { 2333 FWKLOG( ( "IOFireWireSBP2Login<%p> : successful reconnect\n", this ) ); 2334 2335 // cancel timer, won't get here if its not set 2336 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 2337 2338 if( fLastORB ) 2339 { 2340 fLastORB->release(); 2341 fLastORB = NULL; 2342 } 2343 fLastORBAddress = FWAddress(0,0); 2344 fLoginState = kLoginStateConnected; 2345 2346 // set generation 2347 fFetchAgentWriteCommand->reinit( fFetchAgentAddress, 2348 fFetchAgentWriteCommandMemory, 2349 IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true ); 2350 fFetchAgentWriteCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 2351 fFetchAgentWriteCommand->setRetries( 0 ); 2352 2353 // try enabling unsolicited status now 2354 if( fUnsolicitedStatusEnableRequested ) 2355 { 2356 fUnsolicitedStatusEnableRequested = false; 2357 executeUnsolicitedStatusEnable(); 2358 } 2359 2360 if( fLogoutPending ) 2361 { 2362 fLogoutPending = false; 2363 executeLogout(); 2364 } 2365 else 2366 sendReconnectNotificationWithStatusBlock( kIOMessageFWSBP2ReconnectComplete ); 2367 } 2368 else if( ( ( ( fReconnectStatusBlock.details >> 4 ) & 3 ) == kFWSBP2RequestComplete ) && 2369 ( fReconnectStatusBlock.sbpStatus == kFWSBP2UnspecifiedError ) ) 2370 { 2371 // retry reconnect 2372 startReconnectRetryTimer(); 2373 } 2374 else 2375 { 2376 FWKLOG( ( "IOFireWireSBP2Login<%p> : reconnect failed\n", this ) ); 2377 2378 // cancel timer, won't get here if its not set 2379 fReconnectTimeoutCommand->cancel(kIOReturnAborted); 2380 2381 fLoginState = kLoginStateIdle; 2382 if( fLogoutPending ) 2383 { 2384 fLogoutPending = false; 2385 executeLogout(); 2386 } 2387 else 2388 sendReconnectNotificationWithStatusBlock( kIOMessageFWSBP2ReconnectFailed ); 2389 } 2390 2391 return kFWResponseComplete; 2392} 2393 2394// reconnect retry timeout 2395// 2396// 2397 2398void IOFireWireSBP2Login::startReconnectRetryTimer( void ) 2399{ 2400 stopReconnectRetryTimer(); 2401 2402 fReconnectRetryTimeoutTimerSet = true; 2403 if( fReconnectRetryTimeoutCommand->submit() != kIOReturnSuccess ) 2404 fReconnectRetryTimeoutTimerSet = false; 2405} 2406 2407void IOFireWireSBP2Login::stopReconnectRetryTimer( void ) 2408{ 2409 // cancel timeout 2410 if( fReconnectRetryTimeoutTimerSet ) 2411 fReconnectRetryTimeoutCommand->cancel( kIOReturnAborted ); 2412} 2413 2414void IOFireWireSBP2Login::reconnectRetryTimeoutStatic( void *refcon, IOReturn status, 2415 IOFireWireBus *bus, IOFWBusCommand *fwCmd) 2416{ 2417 ((IOFireWireSBP2Login*)refcon)->reconnectRetryTimeout( status, bus, fwCmd ); 2418} 2419 2420void IOFireWireSBP2Login::reconnectRetryTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd) 2421{ 2422 fReconnectRetryTimeoutTimerSet = false; 2423 if( status == kIOReturnTimeout ) 2424 { 2425 FWKLOG( ("IOFireWireSBP2Login<%p> : reconnect retry timer fired\n", this) ); 2426 2427 doReconnect(); 2428 } 2429} 2430 2431// 2432// send reconnect notification 2433// 2434 2435void IOFireWireSBP2Login::sendReconnectNotification( UInt32 event ) 2436{ 2437 FWSBP2ReconnectParams params; 2438 2439 if( (fLoginFlags & kFWSBP2DontSynchronizeMgmtAgent) == 0 ) 2440 fTarget->completeMgmtAgentAccess( ); 2441 2442 params.login = this; 2443 params.generation = fLoginGeneration; 2444 2445 params.reconnectStatusBlock = NULL; 2446 params.reconnectStatusBlockLength = 0; 2447 2448 FWKLOG( ( "IOFireWireSBP2Login<%p> : arg address 0x%08lx\n", this, ¶ms ) ); 2449 2450 FWKLOG( ( "IOFireWireSBP2Login<%p> : reconnectStatusBlock 0x%08lx, reconnectStatusBlockLength 0x%08lx\n", this, params.reconnectStatusBlock, params.reconnectStatusBlockLength ) ); 2451 2452 fTarget->messageClients( event, ¶ms ); 2453 fLUN->messageClients( event, ¶ms ); 2454} 2455 2456void IOFireWireSBP2Login::sendReconnectNotificationWithStatusBlock( UInt32 event ) 2457{ 2458 FWSBP2ReconnectParams params; 2459 2460 if( (fLoginFlags & kFWSBP2DontSynchronizeMgmtAgent) == 0 ) 2461 fTarget->completeMgmtAgentAccess( ); 2462 2463 params.login = this; 2464 params.generation = fLoginGeneration; 2465 2466 params.reconnectStatusBlock = &fReconnectStatusBlock; 2467 params.reconnectStatusBlockLength = sizeof(FWSBP2StatusBlock); 2468 2469 FWKLOG( ( "IOFireWireSBP2Login<%p> : arg address 0x%08lx\n", this, ¶ms ) ); 2470 FWKLOG( ( "IOFireWireSBP2Login<%p> : reconnectStatusBlock 0x%08lx, reconnectStatusBlockLength 0x%08lx\n", this, params.reconnectStatusBlock, params.reconnectStatusBlockLength ) ); 2471 fTarget->messageClients( event, ¶ms ); 2472 fLUN->messageClients( event, ¶ms ); 2473} 2474 2475#pragma mark - 2476///////////////////////////////////////////////////////////////////// 2477// 2478// logout path 2479// 2480 2481// submitLogout 2482// 2483// 2484 2485IOReturn IOFireWireSBP2Login::submitLogout( void ) 2486{ 2487 IOReturn status = kIOReturnSuccess; 2488 2489 status = fGate->runAction( staticExecuteLogout ); 2490 2491 return status; 2492} 2493 2494IOReturn IOFireWireSBP2Login::staticExecuteLogout( OSObject *self, void *, void *, void *, void * ) 2495{ 2496 return ((IOFireWireSBP2Login *)self)->executeLogout(); 2497} 2498 2499IOReturn IOFireWireSBP2Login::executeLogout( void ) 2500{ 2501 FWKLOG( ( "IOFireWireSBP2Login<%p> : executeLogout\n", this ) ); 2502 2503 // are we already processing a logout 2504 if( fLoginState == kLoginStateLoggingOut || fLogoutPending ) 2505 { 2506 return kIOReturnBusy; 2507 } 2508 2509 // logout while suspended 2510 if( fSuspended ) 2511 { 2512 fLogoutPending = true; 2513 } 2514 2515 // logout during login 2516 if( fLoginState == kLoginStateLoggingIn ) 2517 { 2518 return kIOReturnBusy; 2519 } 2520 2521 // logout during reconnect 2522 if( fLoginState == kLoginStateReconnect ) 2523 { 2524 fLogoutPending = true; 2525 } 2526 2527 if( fLoginState == kLoginStateIdle ) 2528 { 2529// completeLogout( kIOReturnSuccess ); 2530// zzz what do I do here? 2531 return kIOReturnSuccess; 2532 } 2533 2534 if( fLoginState == kLoginStateConnected ) 2535 { 2536 fLoginState = kLoginStateLoggingOut; 2537 fLogoutORB.loginID = OSSwapHostToBigInt16(fLoginID); 2538 2539 // set to correct generation 2540 fLogoutWriteCommand->reinit( FWAddress(0x0000ffff, 0xf0000000 + (fManagementOffset << 2)), 2541 fLogoutWriteCommandMemory, IOFireWireSBP2Login::logoutWriteCompleteStatic, 2542 this, true ); 2543 fLogoutWriteCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 2544 2545 IOReturn status = fTarget->beginIOCriticalSection(); 2546 2547 if( status == kIOReturnSuccess ) 2548 { 2549 fInCriticalSection = true; 2550 fCriticalSectionCount++; 2551 fLogoutWriteInProgress = true; 2552 status = fLogoutWriteCommand->submit(); 2553 } 2554 2555 if( status != kIOReturnSuccess ) 2556 { 2557 // fLoginState = kLoginStateIdle; //zzz what do I do here? 2558 fLogoutWriteInProgress = false; 2559 2560 if( fInCriticalSection ) 2561 { 2562 fInCriticalSection = false; 2563 if( fCriticalSectionCount > 0 ) 2564 { 2565 fCriticalSectionCount--; 2566 } 2567 fTarget->endIOCriticalSection(); 2568 } 2569 2570 return status; 2571 } 2572 } 2573 2574 return kIOReturnSuccess; 2575} 2576 2577// 2578// logout write complete handler 2579// 2580 2581void IOFireWireSBP2Login::logoutWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, 2582 IOFWCommand *fwCmd ) 2583{ 2584 ((IOFireWireSBP2Login*)refcon)->logoutWriteComplete( status, device, fwCmd ); 2585} 2586 2587void IOFireWireSBP2Login::logoutWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 2588{ 2589 FWKLOG( ( "IOFireWireSBP2Login<%p> : logoutWriteComplete \n", this ) ); 2590 2591 fLogoutWriteInProgress = false; 2592 2593 if( status == kIOReturnSuccess ) 2594 { 2595 // we wrote the management agent, now set a timer and wait for response & status 2596 fLogoutTimeoutTimerSet = true; 2597 if( fLogoutTimeoutCommand->submit() != kIOReturnSuccess ) 2598 fLogoutTimeoutTimerSet = false; 2599 } 2600 else 2601 { 2602 fLoginState = kLoginStateIdle; 2603 completeLogout( status ); // complete with error 2604 } 2605} 2606 2607// 2608// logout timeout handler 2609// 2610 2611void IOFireWireSBP2Login::logoutTimeoutStatic( void *refcon, IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 2612{ 2613 ((IOFireWireSBP2Login*)refcon)->logoutTimeout( status, bus, fwCmd ); 2614} 2615 2616void IOFireWireSBP2Login::logoutTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 2617{ 2618 FWKLOG( ( "IOFireWireSBP2Login<%p> : logoutTimeout \n", this ) ); 2619 2620 fLogoutTimeoutTimerSet = false; 2621 if( status != kIOReturnSuccess ) 2622 { 2623 FWKLOG( ("IOFireWireSBP2Login<%p> : logout timed out\n", this) ); 2624 2625 // back to idle 2626 fLoginState = kLoginStateIdle; 2627 completeLogout( status ); 2628 } 2629} 2630 2631void IOFireWireSBP2Login::completeLogout( IOReturn state, const void *buf, UInt32 len ) 2632{ 2633 FWKLOG( ( "IOFireWireSBP2Login<%p> : completeLogout\n", this ) ); 2634 2635 if( fInCriticalSection ) 2636 { 2637 fInCriticalSection = false; 2638 if( fCriticalSectionCount > 0 ) 2639 { 2640 fCriticalSectionCount--; 2641 } 2642 fTarget->endIOCriticalSection(); 2643 } 2644 2645 if( fLogoutCompletionCallback != NULL ) 2646 { 2647 FWSBP2LogoutCompleteParams params; 2648 2649 params.login = this; 2650 params.generation = fLoginGeneration; 2651 2652 params.status = state; 2653 params.statusBlock = (FWSBP2StatusBlock*)buf; 2654 params.statusBlockLength = len; 2655 2656 (*fLogoutCompletionCallback)(fLogoutCompletionRefCon, ¶ms); 2657 } 2658} 2659 2660void IOFireWireSBP2Login::clearAllTasksInSet( void ) 2661{ 2662 stopFetchAgentRetryTimer(); 2663 2664 // send reset notification for each orb 2665 // find ORB 2666 IOFireWireSBP2ORB * item; 2667 fORBSetIterator->reset(); 2668 while( (item = (IOFireWireSBP2ORB *) fORBSetIterator->getNextObject()) ) 2669 { 2670 if( isORBTimerSet( item ) ) 2671 { 2672 cancelORBTimer( item ); 2673 2674 if( isORBAppended( item ) ) 2675 { 2676 setORBIsAppended( item, false ); 2677 if( fCriticalSectionCount > 0 ) 2678 { 2679 fCriticalSectionCount--; 2680 } 2681 fTarget->endIOCriticalSection(); 2682 } 2683 2684 // send solicited status 2685 if( fStatusNotifyCallback != NULL ) 2686 { 2687 FWSBP2NotifyParams params; 2688 2689 params.message = 0; 2690 params.length = 0; 2691 params.notificationEvent = kFWSBP2NormalCommandReset; 2692 params.generation = fLoginGeneration; 2693 params.commandObject = item; 2694 (*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms ); 2695 } 2696 } 2697 } 2698 2699 // if we've set aside an orb we have not set its timer yet 2700 if( fORBToWrite ) 2701 { 2702 item = fORBToWrite; 2703 fORBToWrite = 0; 2704 2705 if( item->getCommandTimeout() != 0 ) 2706 { 2707 // send solicited status 2708 if( fStatusNotifyCallback != NULL ) 2709 { 2710 FWSBP2NotifyParams params; 2711 2712 params.message = 0; 2713 params.length = 0; 2714 params.notificationEvent = kFWSBP2NormalCommandReset; 2715 params.generation = fLoginGeneration; 2716 params.commandObject = item; 2717 (*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms ); 2718 } 2719 } 2720 } 2721 2722 if( fLastORB ) 2723 { 2724 fLastORB->release(); 2725 fLastORB = NULL; 2726 } 2727 fLastORBAddress = FWAddress(0,0); 2728} 2729 2730#pragma mark - 2731///////////////////////////////////////////////////////////////////// 2732// 2733// command block ORB routines 2734 2735// createORB 2736// 2737// create an orb object 2738 2739IOFireWireSBP2ORB * IOFireWireSBP2Login::createORB( void ) 2740{ 2741 IOFireWireSBP2ORB * orb = new IOFireWireSBP2ORB; 2742 if( orb != NULL && !initORBWithLogin( orb, this ) ) 2743 { 2744 orb->release(); 2745 orb = NULL; 2746 } 2747 else 2748 { 2749 addORB( orb ); 2750 } 2751 2752 return orb; 2753} 2754 2755// addORB 2756// 2757// 2758 2759IOReturn IOFireWireSBP2Login::addORB( IOFireWireSBP2ORB * orb ) 2760{ 2761 IOReturn status = kIOReturnSuccess; 2762 2763 status = fGate->runAction( staticExecuteAddORB, (void*)orb ); 2764 2765 return status; 2766} 2767 2768IOReturn IOFireWireSBP2Login::staticExecuteAddORB( OSObject *self, void * orb, void *, void *, void * ) 2769{ 2770 return ((IOFireWireSBP2Login *)self)->executeAddORB( (IOFireWireSBP2ORB*)orb ); 2771} 2772 2773IOReturn IOFireWireSBP2Login::executeAddORB( IOFireWireSBP2ORB * orb ) 2774{ 2775 return fORBSet->setObject( orb ); 2776} 2777 2778// removeORB 2779// 2780// 2781 2782IOReturn IOFireWireSBP2Login::removeORB( IOFireWireSBP2ORB * orb ) 2783{ 2784 IOReturn status = kIOReturnSuccess; 2785 2786 status = fGate->runAction( staticExecuteRemoveORB, (void*)orb ); 2787 2788 return status; 2789} 2790 2791IOReturn IOFireWireSBP2Login::staticExecuteRemoveORB( OSObject *self, void * orb, void *, void *, void * ) 2792{ 2793 return ((IOFireWireSBP2Login *)self)->executeRemoveORB( (IOFireWireSBP2ORB*)orb ); 2794} 2795 2796IOReturn IOFireWireSBP2Login::executeRemoveORB( IOFireWireSBP2ORB * orb ) 2797{ 2798 fORBSet->removeObject( orb ); 2799 2800 return kIOReturnSuccess; 2801} 2802 2803// submitORB 2804// 2805// 2806 2807IOReturn IOFireWireSBP2Login::submitORB( IOFireWireSBP2ORB * orb ) 2808{ 2809 IOReturn status = kIOReturnSuccess; 2810 2811 status = fGate->runAction( staticExecuteORB, (void*)orb ); 2812 2813 return status; 2814} 2815 2816IOReturn IOFireWireSBP2Login::staticExecuteORB( OSObject *self, void * orb, void *, void *, void * ) 2817{ 2818 return ((IOFireWireSBP2Login *)self)->executeORB( ( IOFireWireSBP2ORB *)orb ); 2819} 2820 2821IOReturn IOFireWireSBP2Login::executeORB( IOFireWireSBP2ORB * orb ) 2822{ 2823 IOReturn status = kIOReturnSuccess; 2824 UInt32 commandFlags = 0; 2825 2826 if( !isConnected() ) 2827 { 2828 status = kIOFireWireBusReset; //zzz better error 2829 } 2830 2831 if( status == kIOReturnSuccess ) 2832 { 2833 commandFlags = orb->getCommandFlags(); 2834 } 2835 2836 if( status == kIOReturnSuccess ) 2837 { 2838 if( (fFetchAgentWriteCommandInUse || fFetchAgentRetryTimerSet) && // if we're still writing the fetch agent 2839 ( commandFlags & kFWSBP2CommandImmediate ) && // and this is an immediate orb 2840 fORBToWrite ) // and we've already got another orb 2841 { 2842 FWKLOG(("IOFireWireSBP2Login<%p> : fetchAgentWriteCommand still in use\n", this )); 2843 status = kIOReturnNoResources; 2844 } 2845 } 2846 2847 if( status == kIOReturnSuccess ) 2848 { 2849 UInt32 generation = orb->getCommandGeneration(); 2850 2851 // check generation 2852 if( commandFlags & kFWSBP2CommandCheckGeneration && !fControl->checkGeneration(generation) ) 2853 status = kIOFireWireBusReset; 2854 } 2855 2856 if( status == kIOReturnSuccess ) 2857 { 2858 UInt32 targetFlags = fTarget->getTargetFlags(); 2859 if( targetFlags & kIOFWSBP2FailsOnBusResetsDuringIO ) 2860 { 2861 // sorry, no silent orbs if your device 2862 // can't handle bus resets at any time 2863 UInt32 orbFlags = orb->getCommandFlags(); 2864 orb->setCommandFlags( orbFlags | kFWSBP2CommandCompleteNotify ); 2865 } 2866 } 2867 2868 if( status == kIOReturnSuccess ) 2869 { 2870 // retries failed fetch agent writes up to four times 2871 orb->setFetchAgentWriteRetries( 20 ); 2872 orb->setFetchAgentWriteRetryInterval( 1000 ); 2873 prepareORBForExecution(orb); 2874 } 2875 2876 if( status == kIOReturnSuccess && fFastStartSupported ) 2877 { 2878 // setup fast start data 2879 2880 // 2881 // set fast start write length 2882 // 2883 2884 UInt32 maxPacketBytes = 1 << fUnit->maxPackLog(true,fFetchAgentAddress); 2885 UInt32 fastStartPacketBytes = fFastStartMaxPayload << 2; 2886 if( fastStartPacketBytes == 0 ) 2887 { 2888 fastStartPacketBytes = maxPacketBytes; 2889 } 2890 else if( maxPacketBytes < fastStartPacketBytes ) 2891 { 2892 fastStartPacketBytes = maxPacketBytes; 2893 } 2894 2895 IOBufferMemoryDescriptor * descriptor = OSDynamicCast(IOBufferMemoryDescriptor, fFetchAgentWriteCommandMemory); 2896 2897 if( descriptor == NULL ) 2898 { 2899 panic( "IOFireWireSBP2Login<0x%08lx>::executeORB() - fFetchAgentWriteCommandMemory is not an IOBufferMemoryDescriptor!\n", this ); 2900 } 2901 2902 descriptor->setLength( fastStartPacketBytes ); 2903 2904 // 2905 // write previous orb 2906 // 2907 2908 { 2909 FWAddress orbAddress(0,0); 2910 if( commandFlags & kFWSBP2CommandImmediate ) 2911 { 2912 orbAddress = FWAddress(0,0); 2913 } 2914 else 2915 { 2916 orbAddress = fLastORBAddress; 2917 } 2918 2919 if( orbAddress.addressHi == 0 && orbAddress.addressLo == 0 ) 2920 { 2921 orbAddress.nodeID = OSSwapHostToBigInt16(0x8000); 2922 } 2923 else 2924 { 2925 orbAddress.nodeID = OSSwapHostToBigInt16(fLocalNodeID); 2926 } 2927 descriptor->writeBytes( 0, &orbAddress, sizeof(FWAddress) ); 2928 } 2929 2930 // 2931 // write this orb 2932 // 2933 { 2934 FWAddress orbAddress(0,0); 2935 orb->getORBAddress( &orbAddress ); 2936 2937 orbAddress.nodeID = OSSwapHostToBigInt16(fLocalNodeID); 2938 orbAddress.addressHi = OSSwapHostToBigInt16(orbAddress.addressHi); 2939 orbAddress.addressLo = OSSwapHostToBigInt32(orbAddress.addressLo); 2940 2941 descriptor->writeBytes( 8, &orbAddress, sizeof(FWAddress) ); 2942 } 2943 2944 // 2945 // prepare orb and page table 2946 // 2947 2948 orb->prepareFastStartPacket( descriptor ); 2949 2950 fastStartPacketBytes = descriptor->getLength(); 2951 } 2952 2953#if FWDIAGNOSTICS 2954 ((IOFireWireSBP2Diagnostics*)(fLUN->getDiagnostics()))->incrementExecutedORBCount(); 2955#endif 2956 2957 if( status == kIOReturnSuccess ) 2958 { 2959 if( commandFlags & kFWSBP2CommandImmediate ) 2960 { 2961 if( fLastORB ) 2962 { 2963 fLastORB->release(); 2964 fLastORB = NULL; 2965 } 2966 2967 FWAddress orbAddress(0,0); 2968 orb->getORBAddress( &orbAddress ); 2969 2970 fLastORBAddress.nodeID = OSSwapHostToBigInt16(orbAddress.nodeID); 2971 fLastORBAddress.addressHi = OSSwapHostToBigInt16(orbAddress.addressHi); 2972 fLastORBAddress.addressLo = OSSwapHostToBigInt32(orbAddress.addressLo); 2973 orb->retain(); 2974 fLastORB = orb; 2975 2976 if( fFetchAgentWriteCommandInUse ) 2977 { 2978 fORBToWrite = orb; 2979 // IOLog( "IOFireWireSBP2Login : fetch agent write command busy, putting aside orb 0x%08lx\n", orb ); 2980 } 2981 else 2982 { 2983 startORBTimer(orb); 2984 if( fTarget->beginIOCriticalSection() == kIOReturnSuccess ) 2985 { 2986#if PANIC_ON_DOUBLE_APPEND 2987 if( isORBAppended( orb ) ) 2988 { 2989 panic( "IOFireWireSBP2Login::executeORB - double appending orb!\n" ); 2990 } 2991#endif 2992 fCriticalSectionCount++; 2993 setORBIsAppended( orb, true ); 2994 status = appendORBImmediate( orb ); 2995 } 2996 } 2997 } 2998 else 2999 { 3000 startORBTimer(orb); 3001 if( fTarget->beginIOCriticalSection() == kIOReturnSuccess ) 3002 { 3003#if PANIC_ON_DOUBLE_APPEND 3004 if( isORBAppended( orb ) ) 3005 { 3006 panic( "IOFireWireSBP2Login::executeORB - double appending orb!\n" ); 3007 } 3008#endif 3009 3010 fCriticalSectionCount++; 3011 setORBIsAppended( orb, true ); 3012 3013 status = appendORB( orb ); 3014 3015 // clean up if there are no ORBs to chain to or if we 3016 // tried to chain to ourselves 3017 3018 if( status != kIOReturnSuccess ) 3019 { 3020 cancelORBTimer( orb ); 3021 setORBIsAppended( orb, false ); 3022 if( fCriticalSectionCount > 0 ) 3023 { 3024 fCriticalSectionCount--; 3025 } 3026 fTarget->endIOCriticalSection(); 3027 } 3028 } 3029 } 3030 } 3031 3032 return status; 3033} 3034 3035 3036// are we connected? 3037bool IOFireWireSBP2Login::isConnected( void ) 3038{ 3039 return (fLoginState == kLoginStateConnected); 3040} 3041 3042void IOFireWireSBP2Login::setFetchAgentWriteCompletion( void * refCon, FWSBP2FetchAgentWriteCallback completion ) 3043{ 3044 fFetchAgentWriteCompletion = completion; 3045 fFetchAgentWriteRefCon = refCon; 3046} 3047 3048// 3049// fetchAgentWrite completion handler 3050// 3051 3052void IOFireWireSBP2Login::fetchAgentWriteCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3053{ 3054 ((IOFireWireSBP2Login*)refcon)->fetchAgentWriteComplete( status, device, fwCmd ); 3055} 3056 3057void IOFireWireSBP2Login::fetchAgentWriteComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3058{ 3059 IOFireWireSBP2ORB * orb = fORBToWrite; 3060 3061 fFetchAgentWriteCommandInUse = false; 3062 3063 if( fLastORB != NULL ) 3064 { 3065 3066 UInt32 retries = fLastORB->getFetchAgentWriteRetries(); 3067 int ack = fFetchAgentWriteCommand->getAckCode(); 3068 int rcode = fFetchAgentWriteCommand->getResponseCode(); 3069 3070 if( status != kIOReturnSuccess && 3071 status != kIOFireWireBusReset && 3072 retries != 0 ) 3073 { 3074 if( (ack == kFWAckBusyX) || 3075 (ack == kFWAckBusyA) || 3076 (ack == kFWAckBusyB) ) 3077 { 3078 3079 // IOLog( "IOFireWireSBP2Login::fetchAgentWriteComplete fetch agent write failed! retrying\n" ); 3080 3081 #if PANIC_ON_DOUBLE_APPEND 3082 panic( "IOFireWireSBP2Login::fetchAgentWriteComplete fetch agent write failed!\n" ); 3083 #endif 3084 3085 // retry 3086 retries--; 3087 fLastORB->setFetchAgentWriteRetries( retries ); 3088 3089 // on busy family already delays for split timeout 3090 3091 if( kFetchAgentRetryInterval > kFetchAgentSplitTimeout ) 3092 { 3093 // wait a bit logner 3094 startFetchAgentRetryTimer( kFetchAgentRetryInterval - kFetchAgentSplitTimeout ); 3095 } 3096 else 3097 { 3098 // waited long enough, append 3099 appendORBImmediate( fLastORB ); 3100 } 3101 3102 return; 3103 } 3104 else if ( (ack == kFWAckDataError) || 3105 (rcode == kFWResponseConflictError) || 3106 (rcode == kFWResponseDataError) ) 3107 { 3108 3109 // IOLog( "IOFireWireSBP2Login::fetchAgentWriteComplete fetch agent write failed! retrying\n" ); 3110 #if PANIC_ON_DOUBLE_APPEND 3111 panic( "IOFireWireSBP2Login::fetchAgentWriteComplete fetch agent write failed!\n" ); 3112 #endif 3113 3114 // retry 3115 retries--; 3116 fLastORB->setFetchAgentWriteRetries( retries ); 3117 3118 // arithmetic increase in retry time 3119 UInt32 interval = fLastORB->getFetchAgentWriteRetryInterval(); 3120 fLastORB->setFetchAgentWriteRetryInterval( interval + 1000 ); 3121 3122 // family does not delay on these acks and rcodes 3123 startFetchAgentRetryTimer( interval ); 3124 3125 return; 3126 } 3127 } 3128 } 3129 3130 // 3131 // check if we have an orb waiting to be appended 3132 // 3133 3134 fORBToWrite = 0; // no more orb pending a fetch agent write 3135 3136 // theoretically fORBToWrite should already be cleared to zero 3137 // before this fails with kIOFireWireBusReset 3138 3139 if( orb && status != kIOFireWireBusReset ) 3140 { 3141 // IOLog( "IOFireWireSBP2Login : fetch agent write command free, submitting orb 0x%08lx\n", orb ); 3142 3143 // actually do the write if this completed for normal reasons 3144 startORBTimer( orb ); 3145 if( fTarget->beginIOCriticalSection() == kIOReturnSuccess ) 3146 { 3147#if PANIC_ON_DOUBLE_APPEND 3148 if( isORBAppended( orb ) ) 3149 { 3150 panic( "IOFireWireSBP2Login::fetchAgentWriteComplete - double appending orb!\n" ); 3151 } 3152#endif 3153 fCriticalSectionCount++; 3154 setORBIsAppended( orb, true ); 3155 appendORBImmediate( orb ); 3156 } 3157 } 3158 3159 // send complete notification here 3160 if( fFetchAgentWriteCompletion != NULL ) 3161 (*fFetchAgentWriteCompletion)( fFetchAgentWriteRefCon, status, fLastORB ); 3162} 3163 3164// 3165// fetch agent retry timer 3166// 3167 3168// startFetchAgentRetryTimer 3169// 3170// 3171 3172void IOFireWireSBP2Login::startFetchAgentRetryTimer( UInt32 duration ) 3173{ 3174 // shouldn't already be set 3175 FWKLOGASSERT( fFetchAgentRetryTimerSet == false ); 3176 3177 // stop it if it is 3178 stopFetchAgentRetryTimer(); 3179 3180 fFetchAgentRetryTimerCommand->reinit( duration, 3181 IOFireWireSBP2Login::fetchAgentRetryTimerStatic, this ); 3182 3183 // wait a little bit before retrying 3184 fFetchAgentRetryTimerSet = true; 3185 3186 IOReturn status = fFetchAgentRetryTimerCommand->submit(); 3187 if( status != kIOReturnSuccess ) 3188 { 3189 fFetchAgentRetryTimerSet = false; 3190 } 3191} 3192 3193// stopFetchAgentRetryTimer 3194// 3195// 3196 3197void IOFireWireSBP2Login::stopFetchAgentRetryTimer( void ) 3198{ 3199 if( fFetchAgentRetryTimerSet ) 3200 { 3201 fFetchAgentRetryTimerCommand->cancel(kIOReturnAborted); 3202 } 3203} 3204 3205// fetchAgentRetryTimer 3206// 3207// 3208 3209void IOFireWireSBP2Login::fetchAgentRetryTimerStatic( void *refcon, IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 3210{ 3211 ((IOFireWireSBP2Login*)refcon)->fetchAgentRetryTimer( status, bus, fwCmd ); 3212} 3213 3214void IOFireWireSBP2Login::fetchAgentRetryTimer( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 3215{ 3216 FWKLOG( ( "IOFireWireSBP2Login<%p>IOFireWireSBP2Login::fetchAgentRetryTimer\n", this ) ); 3217 3218 fFetchAgentRetryTimerSet = false; 3219 3220 if( status == kIOReturnTimeout ) 3221 { 3222 appendORBImmediate( fLastORB ); 3223 } 3224} 3225 3226// isFetchAgentWriteInProgress 3227// 3228// do we have a fetch agent write in progress 3229 3230bool IOFireWireSBP2Login::isFetchAgentWriteInProgress( void ) 3231{ 3232 return (fFetchAgentWriteCommandInUse || fFetchAgentRetryTimerSet); 3233} 3234 3235// fetch agent reset 3236// 3237// 3238 3239void IOFireWireSBP2Login::setFetchAgentResetCompletion( void * refCon, FWSBP2StatusCallback completion ) 3240{ 3241 fFetchAgentResetCompletion = completion; 3242 fFetchAgentResetRefCon = refCon; 3243} 3244 3245IOReturn IOFireWireSBP2Login::submitFetchAgentReset( void ) 3246{ 3247 IOReturn status = kIOReturnSuccess; 3248 3249 status = fGate->runAction( staticExecuteFetchAgentReset ); 3250 3251 return status; 3252} 3253 3254IOReturn IOFireWireSBP2Login::staticExecuteFetchAgentReset( OSObject *self, void *, void *, void *, void * ) 3255{ 3256 return ((IOFireWireSBP2Login *)self)->executeFetchAgentReset(); 3257} 3258 3259IOReturn IOFireWireSBP2Login::executeFetchAgentReset( void ) 3260{ 3261 IOReturn status = kIOReturnSuccess; 3262 3263 switch( fLoginState ) 3264 { 3265 case kLoginStateConnected: 3266 if( fFetchAgentResetInProgress ) 3267 fFetchAgentResetCommand->cancel( kIOReturnAborted ); 3268 3269 fFetchAgentResetInProgress = true; 3270 fFetchAgentResetCommand->reinit( fFetchAgentResetAddress, 3271 &fFetchAgentResetBuffer, 1, 3272 IOFireWireSBP2Login::fetchAgentResetCompleteStatic, 3273 this, true ); 3274 fFetchAgentResetCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 3275 3276 fFetchAgentResetCommand->submit(); 3277 break; 3278 3279 case kLoginStateLoggingIn: 3280 case kLoginStateReconnect: 3281 case kLoginStateIdle: 3282 case kLoginStateLoggingOut: 3283 default: 3284 status = kIOReturnError; 3285 break; 3286 } 3287 3288 return status; 3289} 3290 3291void IOFireWireSBP2Login::fetchAgentResetCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3292{ 3293 ((IOFireWireSBP2Login*)refcon)->fetchAgentResetComplete( status, device, fwCmd ); 3294} 3295 3296void IOFireWireSBP2Login::fetchAgentResetComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3297{ 3298 FWKLOG( ("IOFireWireSBP2Login<%p> : fetch agent reset complete\n", this) ); 3299 3300 fFetchAgentResetInProgress = false; 3301 3302 if( status == kIOReturnSuccess ) 3303 { 3304 clearAllTasksInSet(); 3305 } 3306 3307 if( status != kIOReturnAborted ) 3308 { 3309 if( fFetchAgentResetCompletion ) 3310 (*fFetchAgentResetCompletion)( fFetchAgentResetRefCon, status ); 3311 } 3312} 3313 3314// ringDoorbell 3315// 3316// 3317 3318IOReturn IOFireWireSBP2Login::ringDoorbell( void ) 3319{ 3320 IOReturn status = kIOReturnSuccess; 3321 3322 status = fGate->runAction( staticExecuteDoorbell ); 3323 3324 return status; 3325} 3326 3327IOReturn IOFireWireSBP2Login::staticExecuteDoorbell( OSObject *self, void *, void *, void *, void * ) 3328{ 3329 return ((IOFireWireSBP2Login *)self)->executeDoorbell(); 3330} 3331 3332IOReturn IOFireWireSBP2Login::executeDoorbell( void ) 3333{ 3334 // must be logged to ring the doorbell 3335 if( isConnected() ) 3336 { 3337 if( fDoorbellInProgress ) 3338 { 3339 fDoorbellRingAgain = true; 3340 return kIOReturnSuccess; 3341 } 3342 3343 fDoorbellInProgress = true; 3344 fDoorbellCommand->reinit( fDoorbellAddress, 3345 &fDoorbellBuffer, 1, 3346 IOFireWireSBP2Login::doorbellCompleteStatic, 3347 this, true ); 3348 fDoorbellCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 3349 3350 fDoorbellCommand->submit(); 3351 } 3352 else 3353 return kIOReturnError; 3354 3355 return kIOReturnSuccess; 3356} 3357 3358void IOFireWireSBP2Login::doorbellCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3359{ 3360 ((IOFireWireSBP2Login*)refcon)->doorbellComplete( status, device, fwCmd ); 3361} 3362 3363void IOFireWireSBP2Login::doorbellComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3364{ 3365 FWKLOG( ("IOFireWireSBP2Login<%p> : doorbell complete\n", this) ); 3366 3367 fDoorbellInProgress = false; 3368 3369 if( fDoorbellRingAgain ) 3370 { 3371 fDoorbellRingAgain = false; 3372 executeDoorbell(); 3373 } 3374} 3375 3376// enableUnsolicitedStatus 3377// 3378// 3379 3380IOReturn IOFireWireSBP2Login::enableUnsolicitedStatus( void ) 3381{ 3382 IOReturn status = kIOReturnSuccess; 3383 3384 status = fGate->runAction( staticExecuteUnsolicitedStatusEnable ); 3385 3386 return status; 3387} 3388 3389IOReturn IOFireWireSBP2Login::staticExecuteUnsolicitedStatusEnable( OSObject *self, void *, void *, void *, void * ) 3390{ 3391 return ((IOFireWireSBP2Login *)self)->executeUnsolicitedStatusEnable(); 3392} 3393 3394IOReturn IOFireWireSBP2Login::executeUnsolicitedStatusEnable( void ) 3395{ 3396 IOReturn status = kIOReturnSuccess; 3397 3398 switch( fLoginState ) 3399 { 3400 case kLoginStateConnected: 3401 if( fUnsolicitedStatusEnableInProgress ) 3402 fUnsolicitedStatusEnableCommand->cancel( kIOReturnAborted ); 3403 3404 fUnsolicitedStatusEnableInProgress = true; 3405 fUnsolicitedStatusEnableCommand->reinit( fUnsolicitedStatusEnableAddress, 3406 &fUnsolicitedStatusEnableBuffer, 1, 3407 IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic, 3408 this, true ); 3409 fUnsolicitedStatusEnableCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 3410 3411 fUnsolicitedStatusEnableCommand->submit(); 3412 break; 3413 3414 case kLoginStateLoggingIn: 3415 case kLoginStateReconnect: 3416 fUnsolicitedStatusEnableRequested = true; // try again after we're logged in 3417 break; 3418 3419 case kLoginStateIdle: 3420 case kLoginStateLoggingOut: 3421 default: 3422 status = kIOReturnError; 3423 break; 3424 } 3425 3426 return status; 3427} 3428 3429void IOFireWireSBP2Login::unsolicitedStatusEnableCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3430{ 3431 ((IOFireWireSBP2Login*)refcon)->unsolicitedStatusEnableComplete( status, device, fwCmd ); 3432} 3433 3434void IOFireWireSBP2Login::unsolicitedStatusEnableComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3435{ 3436 FWKLOG( ("IOFireWireSBP2Login<%p> : unsolicitedStatusEnableComplete complete\n", this) ); 3437 3438 fUnsolicitedStatusEnableInProgress = false; 3439 3440 if( status == kIOFireWireBusReset ) 3441 { 3442 fUnsolicitedStatusEnableRequested = true; // try again after we're logged in 3443 } 3444} 3445 3446// set busy timeout 3447// 3448// 3449 3450void IOFireWireSBP2Login::setBusyTimeoutRegisterValue( UInt32 timeout ) 3451{ 3452 fSetBusyTimeoutBuffer = OSSwapHostToBigInt32(timeout); 3453 executeSetBusyTimeout(); 3454} 3455 3456IOReturn IOFireWireSBP2Login::executeSetBusyTimeout( void ) 3457{ 3458 if( fSetBusyTimeoutInProgress ) 3459 fSetBusyTimeoutCommand->cancel( kIOReturnAborted ); 3460 3461 fSetBusyTimeoutInProgress = true; 3462 fSetBusyTimeoutCommand->reinit( fSetBusyTimeoutAddress, 3463 &fSetBusyTimeoutBuffer, 1, 3464 IOFireWireSBP2Login::setBusyTimeoutCompleteStatic, 3465 this, true ); 3466 3467 fSetBusyTimeoutCommand->submit(); 3468 3469 return kIOReturnSuccess; 3470} 3471 3472void IOFireWireSBP2Login::setBusyTimeoutCompleteStatic( void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3473{ 3474 ((IOFireWireSBP2Login*)refcon)->setBusyTimeoutComplete( status, device, fwCmd ); 3475} 3476 3477void IOFireWireSBP2Login::setBusyTimeoutComplete( IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd ) 3478{ 3479 FWKLOG( ("IOFireWireSBP2Login<%p> : setBusyTimeoutComplete\n", this) ); 3480 3481 fSetBusyTimeoutInProgress = false; 3482} 3483 3484// appendORBImmediate 3485// 3486// 3487 3488IOReturn IOFireWireSBP2Login::appendORBImmediate( IOFireWireSBP2ORB * orb ) 3489{ 3490 if( fFetchAgentWriteCommandInUse ) 3491 fFetchAgentWriteCommand->cancel( kIOReturnAborted ); 3492 3493 fFetchAgentWriteCommandInUse = true; 3494 3495 fFetchAgentWriteCommand->reinit( fFetchAgentAddress, 3496 fFetchAgentWriteCommandMemory, 3497 IOFireWireSBP2Login::fetchAgentWriteCompleteStatic, this, true ); 3498 3499 fFetchAgentWriteCommand->setRetries( 0 ); 3500 fFetchAgentWriteCommand->updateNodeID( fLoginGeneration, fLoginNodeID ); 3501 3502 return fFetchAgentWriteCommand->submit(); 3503} 3504 3505// appendORB 3506// 3507// 3508 3509IOReturn IOFireWireSBP2Login::appendORB( IOFireWireSBP2ORB * orb ) 3510{ 3511 IOReturn status = kIOReturnSuccess; 3512 if( fLastORB != NULL && fLastORB != orb ) 3513 { 3514 FWAddress orb_address(0,0); 3515 orb->getORBAddress( &orb_address ); 3516 setNextORBAddress( fLastORB, orb_address ); 3517 3518 fLastORBAddress.nodeID = OSSwapHostToBigInt16(orb_address.nodeID); 3519 fLastORBAddress.addressHi = OSSwapHostToBigInt16(orb_address.addressHi); 3520 fLastORBAddress.addressLo = OSSwapHostToBigInt32(orb_address.addressLo); 3521 orb->retain(); 3522 3523 if( fLastORB ) 3524 { 3525 fLastORB->release(); 3526 fLastORB = NULL; 3527 } 3528 3529 fLastORB = orb; 3530 } 3531 else 3532 status = kIOReturnError; 3533 3534 return status; 3535} 3536 3537// sendTimeoutNotification 3538// 3539// 3540 3541void IOFireWireSBP2Login::sendTimeoutNotification( IOFireWireSBP2ORB * orb ) 3542{ 3543 if( isORBAppended( orb ) ) 3544 { 3545 setORBIsAppended( orb, false ); 3546 if( fCriticalSectionCount > 0 ) 3547 { 3548 fCriticalSectionCount--; 3549 } 3550 fTarget->endIOCriticalSection(); 3551 } 3552 3553 // send solicited status 3554 if( fStatusNotifyCallback != NULL ) 3555 { 3556 FWSBP2NotifyParams params; 3557 3558 params.message = 0; 3559 params.length = 0; 3560 params.notificationEvent = kFWSBP2NormalCommandTimeout; 3561 params.generation = fLoginGeneration; 3562 params.commandObject = orb; 3563 (*fStatusNotifyCallback)(fStatusNotifyRefCon, ¶ms ); 3564 } 3565} 3566 3567// setAddressLoForLoginORBAndResponse 3568// 3569// 3570 3571void IOFireWireSBP2Login::setAddressLoForLoginORBAndResponse( UInt32 addressLoORB, UInt32 addressLoResponse ) 3572{ 3573 IOFWSBP2PseudoAddressSpace * space; 3574 UInt32 addressLoORBMasked = addressLoORB & 0xfffffff0; 3575 UInt32 addressLoResponseMasked = addressLoResponse & 0xfffffff0; 3576 3577 fControl->closeGate(); 3578 3579 FWKLOG(( "IOFireWireSBP2Login::setAddressLoForLoginORBAndResponse<%p> - set ORB addressLo to 0x%08lx, set Response addressLo to 0x%08lx\n", this, addressLoORBMasked, addressLoResponseMasked )); 3580 3581 space = OSDynamicCast( IOFWSBP2PseudoAddressSpace, fLoginORBAddressSpace ); 3582 if( space != NULL ) 3583 { 3584 fLoginORBAddress.addressLo = OSSwapHostToBigInt32(addressLoORBMasked); 3585 space->setAddressLo( addressLoORBMasked ); 3586 } 3587 3588 space = OSDynamicCast( IOFWSBP2PseudoAddressSpace, fLoginResponseAddressSpace ); 3589 if( space != NULL ) 3590 { 3591 fLoginResponseAddress.addressLo = addressLoResponseMasked; 3592 fLoginORB.loginResponseAddressLo = OSSwapHostToBigInt32(fLoginResponseAddress.addressLo); 3593 space->setAddressLo( addressLoResponseMasked ); 3594 } 3595 3596 fControl->openGate(); 3597} 3598 3599// isPhysicalAccessEnabled 3600// 3601// 3602 3603bool IOFireWireSBP2Login::isPhysicalAccessEnabled( void ) 3604{ 3605 return fPhysicalAccessEnabled; 3606} 3607 3608// getARDMMax 3609// 3610// 3611 3612UInt32 IOFireWireSBP2Login::getARDMMax( void ) 3613{ 3614 return fARDMAMax; 3615} 3616 3617#pragma mark - 3618////////////////////////////////////////////////////////////////////////////////////////// 3619// friend class wrappers 3620 3621// 3622// IOFireWireSBP2ORB friend class wrappers 3623// 3624 3625bool IOFireWireSBP2Login::initORBWithLogin( IOFireWireSBP2ORB * orb, IOFireWireSBP2Login * login ) 3626{ 3627 return orb->initWithLogin( login ); 3628} 3629 3630void IOFireWireSBP2Login::setNextORBAddress( IOFireWireSBP2ORB * orb, FWAddress address ) 3631{ 3632 orb->setNextORBAddress( address ); 3633} 3634 3635void IOFireWireSBP2Login::fetchAgentWriteComplete( IOFireWireSBP2ORB * orb, IOReturn status ) 3636{ 3637 // orb->fetchAgentWriteComplete( status ); 3638} 3639 3640bool IOFireWireSBP2Login::isORBTimerSet( IOFireWireSBP2ORB * orb ) 3641{ 3642 return orb->isTimerSet(); 3643} 3644 3645void IOFireWireSBP2Login::cancelORBTimer( IOFireWireSBP2ORB * orb ) 3646{ 3647 orb->cancelTimer(); 3648} 3649 3650void IOFireWireSBP2Login::startORBTimer( IOFireWireSBP2ORB * orb ) 3651{ 3652 orb->startTimer(); 3653} 3654 3655void IOFireWireSBP2Login::prepareORBForExecution( IOFireWireSBP2ORB * orb ) 3656{ 3657 orb->prepareORBForExecution(); 3658} 3659 3660bool IOFireWireSBP2Login::isORBAppended( IOFireWireSBP2ORB * orb ) 3661{ 3662 return orb->isAppended(); 3663} 3664 3665void IOFireWireSBP2Login::setORBIsAppended( IOFireWireSBP2ORB * orb, bool state ) 3666{ 3667 orb->setIsAppended( state ); 3668} 3669 3670// 3671// IOFireWireSBP2LUN friend class wrappers 3672// 3673 3674void IOFireWireSBP2Login::removeLogin( void ) 3675{ 3676 fLUN->removeLogin( this); 3677} 3678 3679IOFireWireSBP2Target * IOFireWireSBP2Login::getTarget( void ) 3680{ 3681 return fLUN->getTarget(); 3682} 3683