1/* 2 * Copyright (c) 1998-2002 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 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. 24 * 25 * HISTORY 26 * 27 April 99 wgulland created. 27 * 28 */ 29 30// public 31#import <IOKit/firewire/IOFWUtils.h> 32#import <IOKit/firewire/IOFireWireController.h> 33#import <IOKit/firewire/IOLocalConfigDirectory.h> 34#import <IOKit/firewire/IOFireWireNub.h> 35#import <IOKit/firewire/IOFireWireDevice.h> 36#import <IOKit/firewire/IOFWLocalIsochPort.h> 37#import <IOKit/firewire/IOFWDCLProgram.h> 38#import <IOKit/firewire/IOFireWirePowerManager.h> 39#import <IOKit/firewire/IOFWSimpleContiguousPhysicalAddressSpace.h> 40#import <IOKit/pwr_mgt/RootDomain.h> 41#import <IOKit/firewire/IOFWAsyncStreamListener.h> 42#import <IOKit/firewire/IOFWPHYPacketListener.h> 43#import <IOKit/firewire/IOFWUserObjectExporter.h> 44#import <IOKit/firewire/IOFireWireMultiIsochReceive.h> 45 46#import "IOFWAsyncStreamReceiver.h" 47 48// protected 49#import <IOKit/firewire/IOFWWorkLoop.h> 50#import <IOKit/firewire/IOFireWireLink.h> 51 52// private 53#import "FWDebugging.h" 54#import "IOFireWireLocalNode.h" 55#import "IOFWQEventSource.h" 56#import "IOFireWireIRM.h" 57#include <IOKit/firewire/IOFWUtils.h> 58 59// system 60#import <IOKit/IOKitKeys.h> 61#import <IOKit/IOBufferMemoryDescriptor.h> 62#import <IOKit/IODeviceTreeSupport.h> 63#import <IOKit/IOMessage.h> 64#import <IOKit/IOTimerEventSource.h> 65#import <IOKit/IOKitKeysPrivate.h> 66 67// bsd 68#include <sys/sysctl.h> 69 70/////////////////////////////////////////////////////////////////////////////////// 71// Start Tracepooint Setup 72// 73class FireWireGlobals 74{ 75public: 76 FireWireGlobals ( void ); // Constructor 77 virtual ~FireWireGlobals ( void ); // Destructor 78}; 79 80static int FireWireSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req ); 81static FireWireGlobals gFireWireGlobals; // needs to be declared early to register tracepoints via sysctl 82UInt32 gFireWireDebugFlags = 0; // extern-ed in FWTracepoints.h 83SYSCTL_PROC ( _debug, OID_AUTO, FireWire, CTLFLAG_RW, 0, 0, FireWireSysctl, "FireWire", "FireWire debug interface" ); 84 85static int FireWireSysctl ( struct sysctl_oid * oidp, void * arg1, int arg2, struct sysctl_req * req ) 86{ 87 int error = 0; 88 FireWireSysctlArgs fwArgs; 89 90 DEBUG_UNUSED ( oidp ); 91 DEBUG_UNUSED ( arg1 ); 92 DEBUG_UNUSED ( arg2 ); 93 94 //IOLog( "FireWireSysctl: gFireWireDebugFlags = 0x%08X\n", ( unsigned int ) gFireWireDebugFlags ); 95 96 error = SYSCTL_IN ( req, &fwArgs, sizeof ( fwArgs ) ); 97 if ( ( error == 0 ) && ( fwArgs.type == kFireWireTypeDebug ) ) 98 { 99 if ( fwArgs.operation == kFireWireOperationGetFlags ) 100 { 101 fwArgs.debugFlags = gFireWireDebugFlags; 102 error = SYSCTL_OUT ( req, &fwArgs, sizeof ( fwArgs ) ); 103 } 104 105 else if ( fwArgs.operation == kFireWireOperationSetFlags ) 106 { 107 gFireWireDebugFlags = fwArgs.debugFlags; 108 } 109 } 110 111 //IOLog( "FireWireSysctl: gFireWireDebugFlags = 0x%08X error=0x%x\n", ( unsigned int ) gFireWireDebugFlags, error ); 112 113 return error; 114} 115 116FireWireGlobals::FireWireGlobals ( void ) 117{ 118 int debugFlags; 119 120 if ( PE_parse_boot_argn ( "firewire", &debugFlags, sizeof ( debugFlags ) ) ) 121 { 122 gFireWireDebugFlags = debugFlags; 123 } 124 125 // Register our sysctl interface 126 sysctl_register_oid ( &sysctl__debug_FireWire ); 127} 128 129FireWireGlobals::~FireWireGlobals ( void ) 130{ 131 // Unregister our sysctl interface 132 sysctl_unregister_oid ( &sysctl__debug_FireWire ); 133} 134 135/////////////////////////////////////////////////////////////////////////////////// 136 137/////////////////////////////////////////////////////////////////////////////////// 138// timing constants 139// 140 141// 100 mSec delay after bus reset before scanning bus 142// to make first generation Sony cameras happy 143#define kScanBusDelay 100 144 145// 35000 mSec delay for a bus reset to become allowed after one was requested 146#define kBusResetStartTimeout 35000 147 148// 1000 mSec delay for a bus reset to occur after one was requested 149#define kBusResetTimeout 1000 150 151// 100 mSec delay for self ids to arrive after a bus reset 152#define kSelfIDTimeout 1000 153 154// 1000 mSec delay before pruning devices 155// this will end up being kNormalDevicePruneDelay + kRepeatResetDelay because of gap count optimization 156#define kNormalDevicePruneDelay 1000 157 158// 2000 mSec delay between bus resets 159// from the 1394a spec 160#define kRepeatResetDelay 2000 161 162// 3000 mSec delay before pruning last device 163// should generally equal kNormalDevicePruneDelay + kRepeatResetDelay 164#define kOnlyNodeDevicePruneDelay 3000 165 166// 15000 mSec delay before pruning devices after wake 167// needs to be at least long enough for the iPod to reboot into disk mode 168#define kWakeDevicePruneDelay 15000 169 170// 30000 mSec delay before pruning devices after wake if any ack busies are seen 171// needs to be at least long enough for the iPod to reboot into disk mode 172// allows some slow HDs to reappear after wake if the Mac's node went away 173#define kWakeDevicePruneDelayBusy 30000 174 175// the maximum amount of time we will allow a device to exist undiscovered 176#define kDeviceMaximuPruneTime 45000 177 178/////////////////////////////////////////////////////////////////////////////////// 179 180#define kFireWireGenerationID "FireWire Generation ID" 181#define kFireWireLoggingMode "Logging Mode Enabled" 182#define kFWBusScanInProgress "-1" 183 184#define FWAddressToID(addr) (addr & 63) 185 186enum requestRefConBits 187{ 188 kRequestLabel = kFWAsynchTTotal-1, // 6 bits 189 kRequestExtTCodeShift = 6, 190 kRequestExtTCodeMask = 0x3fffc0, // 16 bits 191 kRequestIsComplete = 0x20000000, // Was write request already ack-complete? 192 kRequestIsLock = 0x40000000, 193 kRequestIsQuad = 0x80000000 194}; 195 196enum 197{ 198 kFWInvalidPort = 0xffffffff 199}; 200 201const OSSymbol *gFireWireROM; 202const OSSymbol *gFireWireNodeID; 203const OSSymbol *gFireWireSelfIDs; 204const OSSymbol *gFireWireUnit_Spec_ID; 205const OSSymbol *gFireWireUnit_SW_Version; 206const OSSymbol *gFireWireVendor_ID; 207const OSSymbol *gFireWire_GUID; 208const OSSymbol *gFireWireSpeed; 209const OSSymbol *gFireWireVendor_Name; 210const OSSymbol *gFireWireProduct_Name; 211const OSSymbol *gFireWireModel_ID; 212const OSSymbol *gFireWireTDM; 213 214const IORegistryPlane * IOFireWireBus::gIOFireWirePlane = NULL; 215 216#if __ppc__ 217 218enum 219{ 220 kFWPMSleepState = 0, 221 kFWPMWakeState = 1 222}; 223 224#else 225 226enum 227{ 228 kFWPMSleepState = 0, 229 kFWPMWakeState = 2 230}; 231 232#endif 233 234OSDefineMetaClassAndStructors(IOFireWireDuplicateGUIDList, OSObject); 235 236IOFireWireDuplicateGUIDList * IOFireWireDuplicateGUIDList::create( void ) 237{ 238 IOFireWireDuplicateGUIDList * me; 239 240 me = OSTypeAlloc( IOFireWireDuplicateGUIDList ); 241 242 return me; 243} 244 245void IOFireWireDuplicateGUIDList::free() 246{ 247 IOFWDuplicateGUIDRec * GUIDRec; 248 IOFWDuplicateGUIDRec * GUIDtoFree; 249 250 GUIDRec = fFirstGUID; 251 252 while( GUIDRec ) 253 { 254 GUIDtoFree = GUIDRec; 255 256 GUIDRec = GUIDRec->fNextGUID; 257 258 IOFree( GUIDtoFree, sizeof( IOFWDuplicateGUIDRec ) ); 259 } 260 261 OSObject::free(); 262} 263 264void IOFireWireDuplicateGUIDList::addDuplicateGUID( CSRNodeUniqueID guid, UInt32 gen ) 265{ 266 IOFWDuplicateGUIDRec * newGUID; 267 268 if( !guid || findDuplicateGUID( guid, gen ) ) 269 return; // Already found this one. 270 271 newGUID = (IOFWDuplicateGUIDRec *) IOMalloc( sizeof(IOFWDuplicateGUIDRec)); 272 273 FWKLOG(("addDuplicateGUID adding GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff))); 274 275 IOLog("FireWire Error: Devices with identical unique ID: %08x %08x cannot be used.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff)); 276 277 newGUID->fGUID = guid; 278 newGUID->fLastGenSeen = gen; 279 newGUID->fNextGUID = fFirstGUID; 280 fFirstGUID = newGUID; 281} 282 283void IOFireWireDuplicateGUIDList::removeDuplicateGUID( CSRNodeUniqueID guid ) 284{ 285 IOFWDuplicateGUIDRec * GUIDRec; 286 IOFWDuplicateGUIDRec * prevGUID; 287 288 GUIDRec = fFirstGUID; 289 prevGUID = NULL; 290 291 while( GUIDRec ) 292 { 293 if( GUIDRec->fGUID == guid ) 294 { 295 if( prevGUID ) 296 prevGUID->fNextGUID = GUIDRec->fNextGUID; 297 else 298 fFirstGUID = GUIDRec->fNextGUID; 299 300 FWKLOG(("removeDuplicateGUID removing GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff))); 301 302 IOFree( GUIDRec, sizeof( IOFWDuplicateGUIDRec ) ); 303 304 break; 305 } 306 prevGUID = GUIDRec; 307 GUIDRec = GUIDRec->fNextGUID; 308 } 309} 310 311bool IOFireWireDuplicateGUIDList::findDuplicateGUID( CSRNodeUniqueID guid, UInt32 gen ) 312{ 313 IOFWDuplicateGUIDRec * GUIDRec; 314 315 //FWKLOG(("findDuplicateGUID looking for GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff))); 316 317 GUIDRec = fFirstGUID; 318 while( GUIDRec ) 319 { 320 if( GUIDRec->fGUID == guid ) 321 { 322 323 FWKLOG(("findDuplicateGUID found GUID %08x %08x.\n",(unsigned int )(guid >> 32),(unsigned int )(guid & 0xffffffff))); 324 325 326 GUIDRec->fLastGenSeen = gen; 327 328 return( true ); 329 } 330 GUIDRec = GUIDRec->fNextGUID; 331 } 332 333 return( false ); 334} 335 336OSDefineMetaClassAndStructors(IOFireWireControllerAux, IOFireWireBusAux); 337OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 0); 338OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 1); 339OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 2); 340OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 3); 341OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 4); 342OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 5); 343OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 6); 344OSMetaClassDefineReservedUnused(IOFireWireControllerAux, 7); 345 346#pragma mark - 347 348// init 349// 350// 351 352bool IOFireWireControllerAux::init( IOFireWireController * primary ) 353{ 354 bool success = true; // assume success 355 356 success = IOFireWireBusAux::init(); 357 358 fPrimary = primary; 359 360 fSessionRefExporter = IOFWUserObjectExporter::createWithOwner( this ); 361 if( !fSessionRefExporter ) 362 success = false ; 363 364 return success; 365} 366 367// free 368// 369// 370 371void IOFireWireControllerAux::free() 372{ 373 if( fSessionRefExporter ) 374 { 375 fSessionRefExporter->release(); 376 fSessionRefExporter = NULL; 377 } 378 379 IOFireWireBusAux::free(); 380} 381 382IOFWDCLPool * 383IOFireWireControllerAux::createDCLPool ( unsigned capacity ) const 384{ 385 return fPrimary->getLink()->createDCLPool( capacity ) ; 386} 387 388// getMaxRec 389// 390// 391 392UInt8 IOFireWireControllerAux::getMaxRec( void ) 393{ 394 return fMaxRec; 395} 396 397// getFireWirePhysicalAddressMask 398// 399// 400 401UInt64 IOFireWireControllerAux::getFireWirePhysicalAddressMask( void ) 402{ 403 // all current FW hardware is 32 bit 404 return 0x00000000FFFFFFFFULL; 405} 406 407// getFireWirePhysicalAddressBits 408// 409// 410 411UInt32 IOFireWireControllerAux::getFireWirePhysicalAddressBits( void ) 412{ 413 // all current FW hardware is 32 bit 414 return 32; 415} 416 417// getFireWirePhysicalBufferMask 418// 419// 420 421UInt64 IOFireWireControllerAux::getFireWirePhysicalBufferMask( void ) 422{ 423 // all current FW hardware is 32 bit 424 return 0x00000000FFFFFFFFULL; 425} 426 427// getFireWirePhysicalBufferBits 428// 429// 430 431UInt32 IOFireWireControllerAux::getFireWirePhysicalBufferBits( void ) 432{ 433 // all current FW hardware is 32 bit 434 return 32; 435} 436 437// createSimpleContiguousPhysicalAddressSpace 438// 439// 440 441IOFWSimpleContiguousPhysicalAddressSpace * 442IOFireWireControllerAux::createSimpleContiguousPhysicalAddressSpace( vm_size_t size, IODirection direction ) 443{ 444 IOFWSimpleContiguousPhysicalAddressSpace * space; 445 space = OSTypeAlloc( IOFWSimpleContiguousPhysicalAddressSpace ); 446 if( !space ) 447 return NULL; 448 449 if( !space->init( fPrimary, size, direction ) ) 450 { 451 space->release(); 452 space = NULL; 453 } 454 455 return space; 456} 457 458// createSimplePhysicalAddressSpace 459// 460// 461 462IOFWSimplePhysicalAddressSpace * 463IOFireWireControllerAux::createSimplePhysicalAddressSpace( vm_size_t size, IODirection direction ) 464{ 465 IOFWSimplePhysicalAddressSpace * space; 466 space = OSTypeAlloc( IOFWSimplePhysicalAddressSpace ); 467 if( !space ) 468 return NULL; 469 470 if( !space->init( fPrimary, size, direction ) ) 471 { 472 space->release(); 473 space = NULL; 474 } 475 476 return space; 477} 478 479// getSessionRefExporter 480// 481// 482 483IOFWUserObjectExporter * IOFireWireControllerAux::getSessionRefExporter( void ) 484{ 485 return fSessionRefExporter; 486} 487 488#pragma mark - 489 490OSDefineMetaClassAndStructors( IOFireWireController, IOFireWireBus ) 491OSMetaClassDefineReservedUnused(IOFireWireController, 0); 492OSMetaClassDefineReservedUnused(IOFireWireController, 1); 493OSMetaClassDefineReservedUnused(IOFireWireController, 2); 494OSMetaClassDefineReservedUnused(IOFireWireController, 3); 495OSMetaClassDefineReservedUnused(IOFireWireController, 4); 496OSMetaClassDefineReservedUnused(IOFireWireController, 5); 497OSMetaClassDefineReservedUnused(IOFireWireController, 6); 498OSMetaClassDefineReservedUnused(IOFireWireController, 7); 499OSMetaClassDefineReservedUnused(IOFireWireController, 8); 500 501#pragma mark - 502 503///////////////////////////////////////////////////////////////////////////// 504 505// init 506// 507// 508 509bool IOFireWireController::init( IOFireWireLink *fwim ) 510{ 511 bool success = true; 512 513 if( !IOFireWireBus::init() ) 514 { 515 success = false; 516 } 517 518 if( success ) 519 { 520 fAuxiliary = createAuxiliary(); 521 if( fAuxiliary == NULL ) 522 { 523 success = false; 524 } 525 } 526 527 if( success ) 528 { 529 530 fwim->retain() ; 531 fFWIM = fwim; 532 fHubPort = kFWInvalidPort; // assume no hub 533 534 fOutOfTLabels = 0; 535 fOutOfTLabels10S = 0; 536 fOutOfTLabelsThreshold = 0; 537 fWaitingForSelfID = 0; 538 } 539 540 // 541 // Create firewire symbols. 542 // 543 544 if( success ) 545 { 546 gFireWireROM = OSSymbol::withCString("FireWire Device ROM"); 547 if( gFireWireROM == NULL ) 548 success = false; 549 } 550 551 if( success ) 552 { 553 gFireWireNodeID = OSSymbol::withCString("FireWire Node ID"); 554 if( gFireWireNodeID == NULL ) 555 success = false; 556 } 557 558 if( success ) 559 { 560 gFireWireSelfIDs = OSSymbol::withCString("FireWire Self IDs"); 561 if( gFireWireSelfIDs == NULL ) 562 success = false; 563 } 564 565 if( success ) 566 { 567 gFireWireUnit_Spec_ID = OSSymbol::withCString("Unit_Spec_ID"); 568 if( gFireWireUnit_Spec_ID == NULL ) 569 success = false; 570 } 571 572 if( success ) 573 { 574 gFireWireUnit_SW_Version = OSSymbol::withCString("Unit_SW_Version"); 575 if( gFireWireUnit_SW_Version == NULL ) 576 success = false; 577 } 578 579 if( success ) 580 { 581 gFireWireVendor_ID = OSSymbol::withCString("Vendor_ID"); 582 if( gFireWireVendor_ID == NULL ) 583 success = false; 584 } 585 586 if( success ) 587 { 588 gFireWire_GUID = OSSymbol::withCString("GUID"); 589 if( gFireWire_GUID == NULL ) 590 success = false; 591 } 592 593 if( success ) 594 { 595 gFireWireSpeed = OSSymbol::withCString("FireWire Speed"); 596 if( gFireWireSpeed == NULL ) 597 success = false; 598 } 599 600 if( success ) 601 { 602 gFireWireVendor_Name = OSSymbol::withCString("FireWire Vendor Name"); 603 if( gFireWireVendor_Name == NULL ) 604 success = false; 605 } 606 607 if( success ) 608 { 609 gFireWireProduct_Name = OSSymbol::withCString("FireWire Product Name"); 610 if( gFireWireProduct_Name == NULL ) 611 success = false; 612 } 613 614 if( success ) 615 { 616 gFireWireModel_ID = OSSymbol::withCString("Model_ID"); 617 if( gFireWireModel_ID == NULL ) 618 success = false; 619 } 620 621 if( success ) 622 { 623 gFireWireTDM = OSSymbol::withCString("TDM"); 624 if( gFireWireTDM == NULL ) 625 success = false; 626 } 627 628 if( success ) 629 { 630 if( gIOFireWirePlane == NULL ) 631 { 632 gIOFireWirePlane = IORegistryEntry::makePlane( kIOFireWirePlane ); 633 } 634 635 if( gIOFireWirePlane == NULL ) 636 success = false; 637 } 638 639 // 640 // create sets 641 // 642 643 if( success ) 644 { 645 fLocalAddresses = OSSet::withCapacity( 5 ); // Local ROM + CSR registers + SBP-2 ORBs + FCP + PCR 646 if( fLocalAddresses == NULL ) 647 success = false; 648 } 649 650 if( success ) 651 { 652 fSpaceIterator = OSCollectionIterator::withCollection( fLocalAddresses ); 653 if( fSpaceIterator == NULL ) 654 success = false; 655 } 656 657 if( success ) 658 { 659 fPHYPacketListeners = OSSet::withCapacity( 2 ); 660 if( fPHYPacketListeners == NULL ) 661 success = false; 662 } 663 664 if( success ) 665 { 666 fPHYPacketListenersIterator = OSCollectionIterator::withCollection( fPHYPacketListeners ); 667 if( fPHYPacketListenersIterator == NULL ) 668 success = false; 669 } 670 671 if( success ) 672 { 673 fLocalAsyncStreamReceivers = OSSet::withCapacity(2); 674 if( fLocalAsyncStreamReceivers == NULL ) 675 success = false; 676 } 677 678 if( success ) 679 { 680 fAllocatedChannels = OSSet::withCapacity(1); // DV channel. 681 if( fAllocatedChannels == NULL ) 682 success = false; 683 } 684 685 if( success ) 686 { 687 fAllocChannelIterator = OSCollectionIterator::withCollection(fAllocatedChannels); 688 if( fAllocChannelIterator == NULL ) 689 success = false; 690 } 691 692 if( success ) 693 { 694 fIRMAllocations = OSSet::withCapacity(1); 695 if( fIRMAllocations == NULL ) 696 success = false; 697 } 698 699 if( success ) 700 { 701 fIRMAllocationsIterator = OSCollectionIterator::withCollection(fIRMAllocations); 702 if( fIRMAllocationsIterator == NULL ) 703 success = false; 704 } 705 706 if( success ) 707 { 708 fIRMAllocationsAllocated = OSSet::withCapacity(1); 709 if( fIRMAllocationsAllocated == NULL ) 710 success = false; 711 } 712 713 if( success ) 714 { 715 fLastTrans = kMaxPendingTransfers-1; 716 fDevicePruneDelay = kNormalDevicePruneDelay; 717 718 UInt32 bad = OSSwapHostToBigInt32(0xdeadbabe); 719 fBadReadResponse = IOBufferMemoryDescriptor::withBytes(&bad, sizeof(bad), kIODirectionOutIn); 720 if( fBadReadResponse == NULL ) 721 success = false; 722 } 723 724 if( success ) 725 { 726 fDelayedStateChangeCmdNeedAbort = false; 727 fDelayedStateChangeCmd = createDelayedCmd(1000 * kScanBusDelay, delayedStateChange, NULL); 728 if( fDelayedStateChangeCmd == NULL ) 729 success = false; 730 } 731 732 if( success ) 733 { 734 fBusResetStateChangeCmd = createDelayedCmd(1000 * kRepeatResetDelay, resetStateChange, NULL); 735 if( fBusResetStateChangeCmd == NULL ) 736 success = false; 737 } 738 739 if( success ) 740 { 741 fGUIDDups = IOFireWireDuplicateGUIDList::create(); 742 if( fGUIDDups == NULL ) 743 success = false; 744 } 745 746 // 747 // create the bus power manager 748 // 749 750 if( success ) 751 { 752 fBusPowerManager = IOFireWirePowerManager::createWithController( this ); 753 if( fBusPowerManager == NULL ) 754 { 755 IOLog( "IOFireWireController::start - failed to create bus power manager!\n" ); 756 success = false; 757 } 758 } 759 760 if( success ) 761 { 762 fNodeMustBeRootFlag = false; 763 fNodeMustNotBeRootFlag = false; 764 fForcedGapFlag = false; 765 } 766 767 return success; 768} 769 770// createAuxiliary 771// 772// virtual method for creating auxiliary object. subclasses needing to subclass 773// the auxiliary object can override this. 774 775IOFireWireBusAux * IOFireWireController::createAuxiliary( void ) 776{ 777 IOFireWireControllerAux * auxiliary; 778 779 auxiliary = OSTypeAlloc( IOFireWireControllerAux ); 780 781 if( auxiliary != NULL && !auxiliary->init(this) ) 782 { 783 auxiliary->release(); 784 auxiliary = NULL; 785 } 786 787 return auxiliary; 788} 789 790// free 791// 792// 793 794void IOFireWireController::free() 795{ 796 closeGate() ; 797 798 fInstantiated = false; 799 800 // Release everything I can think of. 801 fNodeMustBeRootFlag = false; 802 fNodeMustNotBeRootFlag = false; 803 fForcedGapFlag = false; 804 805 if( fIRM != NULL ) 806 { 807 fIRM->release(); 808 fIRM = NULL; 809 } 810 811 if( fBusPowerManager != NULL ) 812 { 813 fBusPowerManager->release(); 814 fBusPowerManager = NULL; 815 } 816 817 if( fROMAddrSpace != NULL ) 818 { 819 fROMAddrSpace->release(); 820 fROMAddrSpace = NULL; 821 } 822 823 if( fRootDir != NULL ) 824 { 825 fRootDir->release(); 826 fRootDir = NULL; 827 } 828 829 if( fBadReadResponse != NULL ) 830 { 831 fBadReadResponse->release(); 832 fBadReadResponse = NULL; 833 } 834 835 if( fDelayedStateChangeCmd != NULL ) 836 { 837 fDelayedStateChangeCmd->release(); 838 fDelayedStateChangeCmd = NULL; 839 } 840 841 if( fBusResetStateChangeCmd != NULL ) 842 { 843 fBusResetStateChangeCmd->release(); 844 fBusResetStateChangeCmd = NULL; 845 } 846 847 if( fSpaceIterator != NULL ) 848 { 849 fSpaceIterator->release(); 850 fSpaceIterator = NULL; 851 } 852 853 if( fLocalAddresses != NULL ) 854 { 855 fLocalAddresses->release(); 856 fLocalAddresses = NULL; 857 } 858 859 if( fPHYPacketListenersIterator != NULL ) 860 { 861 fPHYPacketListenersIterator->release(); 862 fPHYPacketListenersIterator = NULL; 863 } 864 865 if( fPHYPacketListeners != NULL ) 866 { 867 fPHYPacketListeners->release(); 868 fPHYPacketListeners = NULL; 869 } 870 871 872 if( fLocalAsyncStreamReceivers != NULL ) 873 { 874 fLocalAsyncStreamReceivers->release(); 875 fLocalAsyncStreamReceivers = NULL; 876 } 877 878 if( fAllocChannelIterator != NULL ) 879 { 880 fAllocChannelIterator->release(); 881 fAllocChannelIterator = NULL; 882 } 883 884 if( fAllocatedChannels != NULL ) 885 { 886 fAllocatedChannels->release(); 887 fAllocatedChannels = NULL; 888 } 889 890 if( fIRMAllocationsIterator != NULL ) 891 { 892 fIRMAllocationsIterator->release(); 893 fIRMAllocationsIterator = NULL; 894 } 895 896 if( fIRMAllocations != NULL ) 897 { 898 fIRMAllocations->release(); 899 fIRMAllocations = NULL; 900 } 901 902 if( fIRMAllocationsAllocated != NULL ) 903 { 904 fIRMAllocationsAllocated->release(); 905 fIRMAllocationsAllocated = NULL; 906 } 907 908 { 909 IOFireWireLink * fwim = fFWIM ; 910 fFWIM = NULL ; 911 fwim->release() ; 912 } 913 914 openGate() ; 915 916 destroyTimeoutQ(); 917 destroyPendingQ(); 918 919 if( fWorkLoop != NULL ) 920 { 921 fWorkLoop->release(); 922 fWorkLoop = NULL; 923 } 924 925 if( fAuxiliary != NULL ) 926 { 927 fAuxiliary->release(); 928 fAuxiliary = NULL; 929 } 930 931 if( fGUIDDups != NULL ) 932 { 933 fGUIDDups->release(); 934 fGUIDDups = NULL; 935 } 936 937 938 939 IOFireWireBus::free(); 940} 941 942// start 943// 944// 945 946bool IOFireWireController::start( IOService * provider ) 947{ 948 FWTrace_Start( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, 0, 0, 0 ); 949 950 fStarted = false; 951 952 if (!IOService::start(provider)) 953 { 954 return false; 955 } 956 957#ifdef __ppc__ 958 // x86 device tree is different 959 // blow away device tree children from where we've taken over 960 // Note we don't add ourself to the device tree. 961 IOService *parent = this; 962 while(parent) { 963 if(parent->inPlane(gIODTPlane)) 964 break; 965 parent = parent->getProvider(); 966 } 967 if(parent) { 968 IORegistryEntry * child; 969 IORegistryIterator * children; 970 971 children = IORegistryIterator::iterateOver(parent, gIODTPlane); 972 if ( children != 0 ) { 973 // Get all children before we start altering the plane! 974 OSOrderedSet * set = children->iterateAll(); 975 if(set != 0) { 976 OSIterator *iter = OSCollectionIterator::withCollection(set); 977 if(iter != 0) { 978 while ( (child = (IORegistryEntry *)iter->getNextObject()) ) { 979 child->detachAll(gIODTPlane); 980 } 981 iter->release(); 982 } 983 set->release(); 984 } 985 children->release(); 986 } 987 } 988#endif /* __ppc__ */ 989 990 fWorkLoop = fFWIM->getFireWireWorkLoop(); 991 fWorkLoop->retain(); // make sure workloop lives at least as long as we do. 992 993 // workloop must be set up before creating queues 994 // pending queue creates the command gate used by setPowerState() 995 createPendingQ(); 996 createTimeoutQ(); 997 998 // process boot-args - we may want to make this a seperate function... 999 if ( !PE_parse_boot_argn("fwdebug_ignorenode", &fDebugIgnoreNode, sizeof(fDebugIgnoreNode)) ) { 1000 // fDebugIgnoreNode can be in 0xFFCx or regular form 1001 fDebugIgnoreNode = kFWDebugIgnoreNodeNone; 1002 } else { 1003 // IOLog might not make it to sys.log, but seen in verbose mode 1004 IOLog("FireWire: Will ignore node 0x%x per boot-args.\n", (uint32_t)fDebugIgnoreNode); 1005 } 1006 // we should define "fwdebug" for debug purposes... 1007 1008 fInstantiated = true; 1009 fStartStatus = kIOReturnSuccess; 1010 1011 // register ourselves with superclass policy-maker 1012 PMinit(); 1013 provider->joinPMtree(this); 1014 1015 // get power state table from FWIM 1016 unsigned long num_power_states = 0; 1017 IOPMPowerState * power_state_table = fFWIM->getPowerStateTable( &num_power_states ); 1018 1019 registerPowerDriver( this, power_state_table, num_power_states ); 1020 1021 FWTrace( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, kFWPMWakeState, 0, 0 ); 1022 1023 // No idle sleep 1024 changePowerStateTo( kFWPMWakeState ); 1025 1026 // poweredStart will be called once the wake transition occurs 1027 1028 FWTrace_End( kFWTController, kTPControllerStart, (uintptr_t)fFWIM, fStartStatus, 0, 0 ); 1029 return (fStartStatus == kIOReturnSuccess); 1030} 1031 1032// poweredStart 1033// 1034// 1035 1036IOReturn IOFireWireController::poweredStart( void ) 1037{ 1038 FWTrace_Start( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, 0, 0, 0 ); 1039 1040 IOReturn status = kIOReturnSuccess; 1041 1042 fStarted = true; 1043 1044 CSRNodeUniqueID guid = fFWIM->getGUID(); 1045 1046 IOService * provider = getProvider(); 1047 if( provider->getProperty("DelegateCycleMaster") ) 1048 fDelegateCycleMaster = true; 1049 1050 // look up the hub property 1051 OSData * hub_port_property = (OSData*)fFWIM->getProvider()->getProperty( "fwhub" ); 1052 if( hub_port_property ) 1053 { 1054 fHubPort = *((UInt32 *)hub_port_property->getBytesNoCopy()); 1055 } 1056 1057// IOLog( "IOFireWireController::poweredStart = hub_port_property = 0x%08lx fHubPort = %d\n", hub_port_property, fHubPort ); 1058 1059 // 1060 // setup initial security mode and state change notification 1061 // 1062 1063 initSecurity(); 1064 1065 // Build local device ROM 1066 // Allocate address space for Configuration ROM and fill in Bus Info 1067 // block. 1068 fROMHeader[1] = OSSwapHostToBigInt32( kFWBIBBusName ); 1069 1070 UInt32 characteristics = fFWIM->getBusCharacteristics(); 1071 1072 //IOLog( "IOFireWireController:start - characteristics = 0x%08lx\n", characteristics ); 1073 1074 // zero out generation and store in local rom header 1075 fROMHeader[2] = OSSwapHostToBigInt32( characteristics & ~kFWBIBGeneration ); 1076 1077 // Get max speed 1078 ((IOFireWireControllerAux*)fAuxiliary)->fMaxRec = ((characteristics & kFWBIBMaxRec) >> kFWBIBMaxRecPhase); 1079 fMaxRecvLog = ((characteristics & kFWBIBMaxRec) >> kFWBIBMaxRecPhase)+1; 1080 fMaxSendLog = fFWIM->getMaxSendLog(); 1081 fROMHeader[3] = OSSwapHostToBigInt32( guid >> 32 ); 1082 fROMHeader[4] = OSSwapHostToBigInt32( guid & 0xffffffff ); 1083 1084 // Create root directory in FWIM data.//zzz should we have one for each FWIM or just one??? 1085 fRootDir = IOLocalConfigDirectory::create(); 1086 if(!fRootDir) 1087 { 1088 FWTrace_End( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, kIOReturnError, 1, 0 ); 1089 return kIOReturnError; 1090 } 1091 1092 // Set our Config ROM generation. 1093 fRootDir->addEntry(kConfigGenerationKey, (UInt32)1); 1094 // Set our module vendor ID. 1095 fRootDir->addEntry(kConfigModuleVendorIdKey, kConfigUnitSpecAppleA27, OSString::withCString("Apple Computer, Inc.")); 1096 fRootDir->addEntry(kConfigModelIdKey, kConfigUnitSWVersMacintosh10, OSString::withCString("Macintosh")); 1097 // Set our capabilities. 1098 fRootDir->addEntry(kConfigNodeCapabilitiesKey, 0x000083C0); 1099 1100 // Set our node unique ID. 1101 UInt64 guid_big = OSSwapHostToBigInt64( guid ); 1102 OSData *t = OSData::withBytes(&guid_big, sizeof(guid_big)); 1103 fRootDir->addEntry(kConfigNodeUniqueIdKey, t); 1104 1105 fTimer->enable(); 1106 1107 // Create local node 1108 IOFireWireLocalNode *localNode = OSTypeAlloc( IOFireWireLocalNode ); 1109 fLocalNode = localNode; 1110 1111 localNode->setConfigDirectory( fRootDir ); 1112 1113 OSDictionary *propTable; 1114 do { 1115 OSObject * prop; 1116 propTable = OSDictionary::withCapacity(8); 1117 if (!propTable) 1118 continue; 1119 1120 prop = OSNumber::withNumber(guid, 8*sizeof(guid)); 1121 if(prop) { 1122 propTable->setObject(gFireWire_GUID, prop); 1123 prop->release(); 1124 } 1125 1126 localNode->init(propTable); 1127 localNode->attach(this); 1128 localNode->registerService(); 1129 } while (false); 1130 if(propTable) 1131 propTable->release(); // done with it after init 1132 1133#ifdef LEGACY_SHUTDOWN 1134 // install power change handler 1135 fPowerEventNotifier = registerPrioritySleepWakeInterest( systemShutDownHandler, this ); 1136 FWKLOGASSERT( fPowerEventNotifier != NULL ); 1137#endif 1138 1139 fIRM = IOFireWireIRM::create(this); 1140 FWPANICASSERT( fIRM != NULL ); 1141 1142 fFWIM->enableAllInterrupts(); // Enable the interrupt delivery. 1143 1144 registerService(); // Enable matching with this object 1145 1146 FWTrace_End( kFWTController, kTPControllerPoweredStart, (uintptr_t)fFWIM, status, 0, 0 ); 1147 return status; 1148} 1149 1150// stop 1151// 1152// 1153 1154void IOFireWireController::stop( IOService * provider ) 1155{ 1156 closeGate() ; 1157 1158 // Fake up disappearance of entire bus 1159 processBusReset(); 1160 suspendBus(); 1161 1162 // tear down security state change notification 1163 freeSecurity(); 1164 1165 PMstop(); 1166 1167#ifdef LEGACY_SHUTDOWN 1168 if( fPowerEventNotifier ) 1169 { 1170 fPowerEventNotifier->remove(); 1171 fPowerEventNotifier = NULL; 1172 } 1173#endif 1174 1175 if(fBusState == kAsleep) { 1176 IOReturn sleepRes; 1177 sleepRes = fWorkLoop->wake(&fBusState); 1178 if(sleepRes != kIOReturnSuccess) { 1179 IOLog("IOFireWireController::stop - Can't wake FireWire workloop, error 0x%x\n", sleepRes); 1180 } 1181 1182 openGate(); 1183 } 1184 1185 freeAllAsyncStreamReceiver(); 1186 1187 IOService::stop(provider); 1188 1189 openGate() ; 1190} 1191 1192// finalize 1193// 1194// 1195 1196bool IOFireWireController::finalize( IOOptionBits options ) 1197{ 1198 bool res; 1199 1200 closeGate() ; 1201 1202 res = IOService::finalize(options); 1203 1204 openGate() ; 1205 1206 return res; 1207} 1208 1209// requestTerminate 1210// 1211// send our custom kIOFWMessageServiceIsRequestingClose to clients 1212 1213bool IOFireWireController::requestTerminate( IOService * provider, IOOptionBits options ) 1214{ 1215 OSIterator *childIterator; 1216 1217 childIterator = getClientIterator(); 1218 if( childIterator ) 1219 { 1220 OSObject *child; 1221 while( (child = childIterator->getNextObject()) ) 1222 { 1223 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 1224 1225 // don't need to sync with open/close routines when checking for kNotTerminated 1226 if(found && (found->getTerminationState() == kNotTerminated) && found->isOpen()) 1227 { 1228 // send our custom requesting close message 1229 messageClient( kIOFWMessageServiceIsRequestingClose, found ); 1230 } 1231 } 1232 1233 childIterator->release(); 1234 } 1235 1236 // delete local node 1237 if(fLocalNode) { 1238 fLocalNode->release(); 1239 fLocalNode = NULL; 1240 } 1241 1242 return IOService::requestTerminate(provider, options); 1243} 1244 1245// setPowerState 1246// 1247// 1248 1249IOReturn IOFireWireController::setPowerState( unsigned long powerStateOrdinal, 1250 IOService* whatDevice ) 1251{ 1252 FWTrace( kFWTController, kTPControllerSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 0, 0 ); 1253 1254 IOReturn res; 1255 IOReturn sleepRes; 1256 1257 if( !fStarted && (powerStateOrdinal != kFWPMWakeState) ) 1258 { 1259 // if we're not started yet wait for a wake state 1260 return IOPMAckImplied; 1261 } 1262 1263 if( !fInstantiated ) 1264 { 1265 // we're being torn down, bail 1266 return IOPMAckImplied; 1267 } 1268 1269 // use gate to keep other threads off the hardware, 1270 // Either close gate or wake workloop. 1271 // First time through, we aren't really asleep. 1272 if( fBusState != kAsleep ) 1273 { 1274 closeGate(); 1275 } 1276 else 1277 { 1278 sleepRes = fWorkLoop->wake(&fBusState); 1279 if(sleepRes != kIOReturnSuccess) 1280 { 1281 IOLog("Can't wake FireWire workloop, error 0x%x\n", sleepRes); 1282 } 1283 } 1284 // Either way, we have the gate closed against invaders/lost sheep 1285 1286 // <rdar://problem/4435647> Yellow: iChat freezes after hot unplug a FireWire iSight during system asleep. 1287 // Change condition from 'powerStateOrdinal != kFWPMSleepState' to 'powerStateOrdinal == kFWPMWakeState' 1288 // -ng 1289 1290 if( powerStateOrdinal == kFWPMWakeState ) 1291 { 1292 fDevicePruneDelay = kWakeDevicePruneDelay; 1293 fBusState = kRunning; // Will transition to a bus reset state. 1294 if( fDelayedStateChangeCmdNeedAbort ) 1295 { 1296 fDelayedStateChangeCmdNeedAbort = false; 1297 fDelayedStateChangeCmd->cancel(kIOReturnAborted); 1298 } 1299 } 1300 1301 // Reset bus if we're sleeping, before turning hw off. 1302 if(powerStateOrdinal == kFWPMSleepState ) 1303 { 1304 fFWIM->setContender(false); 1305 fFWIM->setRootHoldOff(false); 1306 1307 FWTrace(kFWTResetBusAction, kTPResetSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 1, 0); 1308 1309 fFWIM->resetBus(); 1310 IOSleep(10); // Reset bus may not be instantaneous anymore. Wait a bit to be sure 1311 // it happened before turning off hardware. 1312 // zzz how long to wait? 1313 } 1314 1315 res = fFWIM->setLinkPowerState(powerStateOrdinal); 1316 1317 if( (powerStateOrdinal == kFWPMWakeState) && !fStarted ) 1318 { 1319 // fStartStatus will be returned from IOFireWireController::start 1320 if( res != IOPMAckImplied ) 1321 { 1322 fStartStatus = kIOReturnError; 1323 res = IOPMAckImplied; 1324 } 1325 else 1326 { 1327 fStartStatus = poweredStart(); 1328 } 1329 } 1330 1331 // reset bus 1332 if( (powerStateOrdinal == kFWPMWakeState) && 1333 (res == IOPMAckImplied) && 1334 (fStartStatus == kIOReturnSuccess) ) 1335 { 1336 if ( kIOReturnSuccess != UpdateROM() ) 1337 IOLog(" %s %u: UpdateROM() got error\n", __FILE__, __LINE__ ) ; 1338 1339 FWTrace(kFWTResetBusAction, kTPResetSetPowerState, (uintptr_t)fFWIM, powerStateOrdinal, 2, 0); 1340 1341 fFWIM->resetBus(); // Don't do this on startup until Config ROM built. 1342 } 1343 1344 // Update power state, keep gate closed while we sleep. 1345 if( powerStateOrdinal == kFWPMSleepState ) 1346 { 1347 // Pretend we had a bus reset - we'll have a real one when we wake up. 1348 if( delayedStateCommandInUse() ) 1349 { 1350 fDelayedStateChangeCmdNeedAbort = true; 1351 } 1352 1353 if( fBusResetState == kResetStateDisabled ) 1354 { 1355 // we'll cause a reset when we wake up and reset the state machine anyway 1356 fBusResetStateChangeCmd->cancel( kIOReturnAborted ); 1357 fBusResetState = kResetStateResetting; 1358 } 1359 1360 fBusResetScheduled = false; 1361 1362 fBusState = kAsleep; 1363 } 1364 1365 if( (fBusState == kAsleep) && (OSSwapBigToHostInt32(fROMHeader[1]) == kFWBIBBusName) ) 1366 { 1367 sleepRes = fWorkLoop->sleep(&fBusState); 1368 if(sleepRes != kIOReturnSuccess) 1369 { 1370 IOLog("Can't sleep FireWire workloop, error 0x%x\n", sleepRes); 1371 } 1372 } 1373 else 1374 { 1375 openGate(); 1376 } 1377 1378 return res; 1379} 1380 1381#ifdef LEGACY_SHUTDOWN 1382 1383// systemShutDownHandler 1384// 1385// 1386 1387IOReturn IOFireWireController::systemShutDownHandler( void * target, void * refCon, 1388 UInt32 messageType, IOService * service, 1389 void * messageArgument, vm_size_t argSize ) 1390{ 1391 1392 IOReturn status = kIOReturnSuccess; 1393 1394 IOFireWireController * me = (IOFireWireController*)target; 1395 1396 me->closeGate(); 1397 1398 switch( messageType ) 1399 { 1400 case kIOMessageSystemWillPowerOff: 1401// IOLog( "IOFireWireController::systemShutDownHandler - kIOMessageSystemWillPowerOff\n" ); 1402 1403 me->fFWIM->handleSystemShutDown( messageType ); 1404 status = kIOReturnSuccess; 1405 break; 1406 1407 case kIOMessageSystemWillRestart: 1408// IOLog( "IOFireWireController::systemShutDownHandler - kIOMessageSystemWillRestart\n" ); 1409 1410 me->fFWIM->handleSystemShutDown( messageType ); 1411 status = kIOReturnSuccess; 1412 break; 1413 1414 default: 1415 status = kIOReturnUnsupported; 1416 break; 1417 } 1418 1419 me->openGate(); 1420 1421 // 30 second delay for debugging 1422 // this will allow you to see IOLogs at shutdown when verbose booted 1423 1424// IOSleep( 30000 ); 1425 1426 return status; 1427} 1428 1429#else 1430 1431// systemWillShutdown 1432// 1433// 1434 1435void IOFireWireController::systemWillShutdown( IOOptionBits specifier ) 1436{ 1437 closeGate(); 1438 1439 switch( specifier ) 1440 { 1441 case kIOMessageSystemWillPowerOff: 1442// IOLog( "IOFireWireController::systemWillShutdown - kIOMessageSystemWillPowerOff\n" ); 1443 1444 fFWIM->handleSystemShutDown( specifier ); 1445 break; 1446 1447 case kIOMessageSystemWillRestart: 1448// IOLog( "IOFireWireController::systemWillShutdown - kIOMessageSystemWillRestart\n" ); 1449 1450 fFWIM->handleSystemShutDown( specifier ); 1451 break; 1452 1453 default: 1454 break; 1455 } 1456 1457 openGate(); 1458 1459 // 30 second delay for debugging 1460 // this will allow you to see IOLogs at shutdown when verbose booted 1461 1462// IOSleep( 30000 ); 1463 1464 IOService::systemWillShutdown( specifier ); 1465} 1466 1467#endif 1468 1469// resetBus 1470// 1471// 1472 1473IOReturn IOFireWireController::resetBus() 1474{ 1475 IOReturn res = kIOReturnSuccess; 1476 1477 closeGate(); 1478 1479 switch( fBusResetState ) 1480 { 1481 case kResetStateDisabled: 1482 FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1483 1484 // always schedule resets during the first 2 seconds 1485 fBusResetScheduled = true; 1486 break; 1487 1488 case kResetStateArbitrated: 1489 if( fBusResetDisabledCount == 0 ) 1490 { 1491 FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1492 1493 // cause a reset if no one has disabled resets 1494 doBusReset(); 1495 } 1496 else if( !fBusResetScheduled ) 1497 { 1498 // schedule the reset if resets are disabled 1499 fBusResetScheduled = true; 1500 1501 // 1502 // start bus reset timer 1503 // 1504 1505 if( delayedStateCommandInUse() ) 1506 { 1507 fDelayedStateChangeCmd->cancel( kIOReturnAborted ); 1508 } 1509 1510 fBusState = kWaitingBusResetStart; 1511 fDelayedStateChangeCmd->reinit( 1000 * kBusResetStartTimeout, delayedStateChange, NULL ); 1512 1513 FWTrace(kFWTStateChangeAction, kTPStateChangeResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1514 fDelayedStateChangeCmd->submit(); 1515 } 1516 break; 1517 1518 case kResetStateResetting: 1519 FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1520 // we're in the middle of a reset now, no sense in doing another 1521 // fBusResetScheduled would be cleared on the transition out of this state anyway 1522 default: 1523 FWTrace(kFWTController, kTPControllerResetBus, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1524 break; 1525 } 1526 1527 openGate(); 1528 1529 return res; 1530} 1531 1532 1533// resetStateChange 1534// 1535// called 2 seconds after a bus reset to transition from the disabled state 1536// to the arbitrated state 1537 1538void IOFireWireController::resetStateChange(void *refcon, IOReturn status, 1539 IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1540{ 1541 IOFireWireController *me = (IOFireWireController *)bus; 1542 1543 if( status == kIOReturnTimeout ) 1544 { 1545 // we should only transition here from the disabled state 1546#ifdef FWKLOGASSERT 1547 FWKLOGASSERT( me->fBusResetState == kResetStateDisabled ); 1548#endif 1549 // transition to the arbitrated reset state 1550 me->fBusResetState = kResetStateArbitrated; 1551 1552 // reset now if we need to and no one has disabled resets 1553 if( me->fBusResetScheduled ) 1554 { 1555 if( me->fBusResetDisabledCount == 0 ) 1556 { 1557 FWTrace(kFWTResetBusAction, kTPResetResetStateChangeResetScheduled, (uintptr_t)(me->fFWIM), me->fBusResetState, 0, 0); 1558 me->doBusReset(); 1559 } 1560 else 1561 { 1562 // 1563 // start bus reset timer 1564 // 1565 1566 if( me->delayedStateCommandInUse() ) 1567 { 1568 me->fDelayedStateChangeCmd->cancel( kIOReturnAborted ); 1569 } 1570 1571 me->fBusState = kWaitingBusResetStart; 1572 me->fDelayedStateChangeCmd->reinit( 1000 * kBusResetStartTimeout, delayedStateChange, NULL ); 1573 1574 FWTrace(kFWTStateChangeAction, kTPStateChangeResetStateChange, (uintptr_t)(me->fFWIM), me->fBusResetState, 0, 0); 1575 me->fDelayedStateChangeCmd->submit(); 1576 } 1577 } 1578 } 1579} 1580 1581// doBusReset 1582// 1583// 1584 1585void IOFireWireController::doBusReset( void ) 1586{ 1587 IOReturn status = kIOReturnSuccess; 1588 bool useIBR = false; 1589 1590 if( fDelayedPhyPacket ) 1591 { 1592 fFWIM->sendPHYPacket( fDelayedPhyPacket ); 1593 fDelayedPhyPacket = 0x00000000; 1594 1595 // If the gap counts were mismatched and we're optimizing the 1596 // gap count, use in IBR instead of an ISBR 1597 1598 // This works around a problem with certain devices when they 1599 // see an ISBR followed by an IBR due to ISBR promotion. 1600 1601 // When this occurs the device is supposed to throw out the IBR. 1602 // Devices that don't do this latch the gap count with the ISBR 1603 // and then reset it with the subsequent IBR. 1604 1605 // This gets us into a loop where we keep trying to optimize the 1606 // gap count only to find it reset on the next bus generation 1607 1608 // Using an IBR avoids the problem. 1609 1610 if( fGapCountMismatch ) 1611 { 1612 useIBR = true; 1613 } 1614 } 1615 1616 FWKLOG(( "IOFireWireController::doBusReset\n" )); 1617 1618 fBusResetState = kResetStateResetting; 1619 1620 // 1621 // start bus reset timer 1622 // 1623 1624 if( delayedStateCommandInUse() ) 1625 { 1626 fDelayedStateChangeCmd->cancel(kIOReturnAborted); 1627 } 1628 1629 fBusState = kWaitingBusReset; 1630 fDelayedStateChangeCmd->reinit(1000 * kBusResetTimeout, delayedStateChange, NULL); 1631 1632 FWTrace(kFWTStateChangeAction, kTPStateChangeDoBusReset, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1633 fDelayedStateChangeCmd->submit(); 1634 1635 status = fFWIM->resetBus( useIBR ); 1636 1637 if( status == kIOReturnSuccess ) 1638 { 1639 if( fWaitingForSelfID > kMaxWaitForValidSelfID ) 1640 { 1641 fFWIM->notifyInvalidSelfIDs(); 1642 fWaitingForSelfID = 0; 1643 } 1644 } 1645 else 1646 { 1647 fDelayedStateChangeCmd->cancel( kIOReturnAborted ); 1648 fBusState = kRunning; 1649 } 1650} 1651 1652// enterBusResetDisabledState 1653// 1654// 1655 1656void IOFireWireController::enterBusResetDisabledState( ) 1657{ 1658 if( fBusResetState == kResetStateDisabled ) 1659 fBusResetStateChangeCmd->cancel( kIOReturnAborted ); 1660 1661 // start the reset disabled state 1662 fBusResetState = kResetStateDisabled; 1663 fBusResetStateChangeCmd->reinit( 1000 * kRepeatResetDelay, resetStateChange, NULL ); 1664 fBusResetStateChangeCmd->submit(); 1665} 1666 1667// disableSoftwareBusResets 1668// 1669// 1670 1671IOReturn IOFireWireController::disableSoftwareBusResets( void ) 1672{ 1673 IOReturn status = kIOReturnSuccess; 1674 1675 closeGate(); 1676 1677 switch( fBusResetState ) 1678 { 1679 case kResetStateDisabled: 1680 // bus resets have no priority in this state 1681 // we will always allow this call to succeed in these states 1682 fBusResetDisabledCount++; 1683 break; 1684 1685 case kResetStateResetting: 1686 // we're in the process of bus resetting, but processBusReset has 1687 // not yet been called 1688 1689 // if we allowed this call to succeed the client would receive a 1690 // bus reset notification after the disable call which is 1691 // probably not what the caller expects 1692 status = kIOFireWireBusReset; 1693 break; 1694 1695 case kResetStateArbitrated: 1696 // bus resets have an equal priority in this state 1697 // this call will fail if we need to cause a reset in this state 1698 if( !fBusResetScheduled ) 1699 { 1700 fBusResetDisabledCount++; 1701 } 1702 else 1703 { 1704 // we're trying to get a bus reset out, we're not allowing 1705 // any more disable calls 1706 status = kIOFireWireBusReset; 1707 } 1708 break; 1709 1710 default: 1711 break; 1712 } 1713 1714// IOLog( "IOFireWireController::disableSoftwareBusResets = 0x%08lx\n", (UInt32)status ); 1715 1716 openGate(); 1717 1718 return status; 1719} 1720 1721// enableSoftwareBusResets 1722// 1723// 1724 1725void IOFireWireController::enableSoftwareBusResets( void ) 1726{ 1727 closeGate(); 1728 1729#ifdef FWKLOGASSERT 1730 FWKLOGASSERT( fBusResetDisabledCount != 0 ); 1731#endif 1732 1733 // do this in any state 1734 if( fBusResetDisabledCount > 0 ) 1735 { 1736 fBusResetDisabledCount--; 1737// IOLog( "IOFireWireController::enableSoftwareBusResets\n" ); 1738 } 1739 1740 switch( fBusResetState ) 1741 { 1742 case kResetStateArbitrated: 1743 // this is the only state we're allowed to cause resets in 1744 if( fBusResetDisabledCount == 0 && fBusResetScheduled ) 1745 { 1746 // reset the bus if the disabled count is down 1747 // to zero and a bus reset is scheduled 1748 doBusReset(); 1749 } 1750 break; 1751 1752 case kResetStateResetting: 1753 case kResetStateDisabled: 1754 default: 1755 break; 1756 } 1757 1758 openGate(); 1759} 1760 1761// beginIOCriticalSection 1762// 1763// 1764 1765IOReturn IOFireWireController::beginIOCriticalSection( void ) 1766{ 1767 IOReturn status = kIOReturnSuccess; 1768 1769 // disable software initiated bus resets 1770 status = disableSoftwareBusResets(); 1771 1772 // check success of bus reset disabling 1773 // critical section can be denied if someone has already requested a bus reset 1774 1775 if( status == kIOReturnSuccess ) 1776 { 1777 if( fIOCriticalSectionCount == 0 ) 1778 { 1779 fFWIM->configureAsyncRobustness( true ); 1780 } 1781 1782 fIOCriticalSectionCount++; 1783 } 1784 1785 return status; 1786} 1787 1788// endIOCriticalSection 1789// 1790// 1791 1792void IOFireWireController::endIOCriticalSection( void ) 1793{ 1794 if( fIOCriticalSectionCount != 0 ) 1795 { 1796 enableSoftwareBusResets(); 1797 1798 fIOCriticalSectionCount--; 1799 1800 if( fIOCriticalSectionCount == 0 ) 1801 { 1802 fFWIM->configureAsyncRobustness( false ); 1803 } 1804 } 1805} 1806 1807// delayedStateChange 1808// 1809// 1810 1811void IOFireWireController::delayedStateChange(void *refcon, IOReturn status, 1812 IOFireWireBus *bus, IOFWBusCommand *fwCmd) 1813{ 1814 IOFireWireController *me = (IOFireWireController *)bus; 1815 1816 if(status == kIOReturnTimeout) { 1817 switch (me->fBusState) { 1818 case kWaitingBusResetStart: 1819 // timed out waiting for a bus reset to be alllowed 1820 // IOLog( "IOFireWireController::delayedStateChange - timed out waiting for a bus reset to be allowed - resetting bus\n" ); 1821 FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 1, 0); 1822 me->doBusReset(); 1823 break; 1824 case kWaitingBusReset: 1825 FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0); 1826 1827 // timed out waiting for a bus reset 1828// IOLog( "IOFireWireController::delayedStateChange - timed out waiting for a bus reset - resetting bus\n" ); 1829 me->checkProgress(); 1830 me->enterBusResetDisabledState(); 1831 me->fBusState = kRunning; 1832 1833 FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 2, 0); 1834 me->resetBus(); 1835 break; 1836 case kWaitingSelfIDs: 1837 FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0); 1838 1839 // timed out waiting for self ids 1840// IOLog( "IOFireWireController::delayedStateChange - timed out waiting for self ids - resetting bus\n" ); 1841 me->fBusState = kRunning; 1842 me->fWaitingForSelfID++; 1843 1844 FWTrace(kFWTResetBusAction, kTPResetDelayedStateChangeWaitingBusReset, (uintptr_t)me->fFWIM, me->fBusState, 3, 0); 1845 me->resetBus(); 1846 break; 1847 case kWaitingScan: 1848 FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0); 1849 1850 me->fWaitingForSelfID = 0; 1851 me->fBusState = kScanning; 1852 me->startBusScan(); 1853 break; 1854 case kWaitingPrune: 1855 FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)me->fFWIM, me->fBusState, 0, 0); 1856 1857 me->fBusState = kRunning; 1858 me->updatePlane(); 1859 break; 1860 default: 1861 FWTrace(kFWTController, kTPControllerDelayedStateChange, (uintptr_t)(me->fFWIM), me->fBusState, 0, 0); 1862 1863 IOLog("State change timeout, state is %d\n", me->fBusState); 1864 break; 1865 } 1866 } 1867} 1868 1869// scanningBus 1870// 1871// Are we currently scanning the bus? 1872 1873bool IOFireWireController::scanningBus() const 1874{ 1875 return fBusState == kWaitingSelfIDs || fBusState == kWaitingScan || fBusState == kScanning; 1876} 1877 1878// delayedStateCommandInUse 1879// 1880// 1881 1882bool IOFireWireController::delayedStateCommandInUse() const 1883{ 1884 return (fBusState == kWaitingBusReset) || (fBusState == kWaitingSelfIDs) || (fBusState == kWaitingScan) || (fBusState == kWaitingPrune); 1885} 1886 1887// getResetTime 1888// 1889// 1890 1891const AbsoluteTime * IOFireWireController::getResetTime() const 1892{ 1893 return &fResetTime; 1894} 1895 1896// checkProgress 1897// 1898// 1899 1900void IOFireWireController::checkProgress( void ) 1901{ 1902 // check progress on reset queue 1903 fAfterResetHandledQ.checkProgress(); 1904 1905 // check progress on disconnected devices 1906 OSIterator * childIterator = getClientIterator(); 1907 if( childIterator ) 1908 { 1909 OSObject *child; 1910 while( (child = childIterator->getNextObject())) 1911 { 1912 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 1913 1914 if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == kFWBadNodeID ) 1915 { 1916 AbsoluteTime now; 1917 UInt32 milliDelta; 1918 UInt64 nanoDelta; 1919 1920 AbsoluteTime resume_time = found->getResumeTime(); 1921 IOFWGetAbsoluteTime( &now ); 1922 SUB_ABSOLUTETIME( &now, &resume_time ); 1923 absolutetime_to_nanoseconds( now, &nanoDelta ); 1924 milliDelta = nanoDelta / 1000000; 1925 1926 if( milliDelta > kDeviceMaximuPruneTime ) 1927 { 1928 // it's been too long, kill him 1929 terminateDevice( found ); 1930 } 1931 } 1932 1933 } 1934 childIterator->release(); 1935 } 1936 1937} 1938 1939// processBusReset 1940// 1941// Hardware detected a bus reset. 1942// At this point we don't know what the hardware addresses are 1943 1944void IOFireWireController::processBusReset( void ) 1945{ 1946 FWKLOG(( "IOFireWireController::processBusReset\n" )); 1947 1948 IOFWGetAbsoluteTime(&fResetTime); // Update even if we're already processing a reset 1949 1950 // we got our bus reset, cancel any reset work in progress 1951 fBusResetScheduled = false; 1952 1953 enterBusResetDisabledState(); 1954 1955 if( delayedStateCommandInUse() ) 1956 { 1957 fDelayedStateChangeCmd->cancel( kIOReturnAborted ); 1958 } 1959 1960 fBusState = kWaitingSelfIDs; 1961 1962 checkProgress(); 1963 1964 // set a timer 1965 fDelayedStateChangeCmd->reinit( 1000 * kSelfIDTimeout, delayedStateChange, NULL ); 1966 1967 FWTrace(kFWTStateChangeAction, kTPStateChangeProcessBusReset, (uintptr_t)fFWIM, fBusResetState, 0, 0); 1968 fDelayedStateChangeCmd->submit(); 1969} 1970 1971// suspendBus 1972// 1973// 1974 1975void IOFireWireController::suspendBus( void ) 1976{ 1977 FWKLOG(( "IOFireWireController::suspendBus\n" )); 1978 1979 // set generation property to kFWBusScanInProgress ("-1") 1980 FWKLOG(("IOFireWireController::suspendBus set generation to '%s' realGen=0x%lx\n", kFWBusScanInProgress, fBusGeneration)); 1981 setProperty( kFireWireGenerationID, kFWBusScanInProgress ); 1982 1983 fRequestedHalfSizePackets = false; 1984 fNodeMustNotBeRootFlag = false; 1985 fNodeMustBeRootFlag = false; 1986 fForcedGapFlag = false; 1987 1988 unsigned int i; 1989 UInt32 oldgen = fBusGeneration; 1990 1991 // Set all current device nodeIDs to something invalid 1992 fBusGeneration++; 1993 1994 // Reset all these information only variables 1995 fOutOfTLabels = 0; 1996 fOutOfTLabels10S = 0; 1997 fOutOfTLabelsThreshold = 0; 1998 1999 OSIterator * childIterator = getClientIterator(); 2000 if( childIterator ) 2001 { 2002 OSObject * child; 2003 while( (child = childIterator->getNextObject()) ) 2004 { 2005 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 2006 2007 // don't need to sync with open/close routines when checking for kNotTerminated 2008 if( found && (found->getTerminationState() == kNotTerminated) ) 2009 { 2010 found->setNodeROM( oldgen, kFWBadNodeID, NULL ); 2011 } 2012 else if( OSDynamicCast(IOFireWireLocalNode, child) ) 2013 { 2014 // forceStop should take care of this deactivateAsyncStreamReceivers(); 2015 ((IOFireWireLocalNode *)child)->messageClients(kIOMessageServiceIsSuspended); 2016 } 2017 } 2018 2019 childIterator->release(); 2020 } 2021 2022 // reset physical filters if necessary 2023 physicalAccessProcessBusReset(); 2024 2025 // IOLog("FireWire Bus Generation now %d\n", fBusGeneration); 2026 2027 // Invalidate current topology and speed map 2028 bzero( fSpeedVector, sizeof(fSpeedVector) ); 2029 2030 // Zap all outstanding async requests 2031 for( i=0; i<kMaxPendingTransfers; i++ ) 2032 { 2033 AsyncPendingTrans *t = &fTrans[i]; 2034 if( t->fHandler ) 2035 { 2036 IOFWAsyncCommand * cmd = t->fHandler; 2037 cmd->gotPacket(kFWResponseBusResetError, NULL, 0); 2038 } 2039 else if( t->fAltHandler ) 2040 { 2041 IOFWAsyncPHYCommand * cmd = OSDynamicCast( IOFWAsyncPHYCommand, t->fAltHandler ); 2042 if( cmd ) 2043 { 2044 cmd->gotPacket( kFWResponseBusResetError ); 2045 } 2046 } 2047 } 2048 2049 // Clear out the old firewire plane 2050 if( fNodes[fRootNodeID] ) 2051 { 2052 fNodes[fRootNodeID]->detachAll(gIOFireWirePlane); 2053 } 2054 2055 for( i=0; i<=fRootNodeID; i++ ) 2056 { 2057 if( fScans[i] ) 2058 { 2059 fScans[i]->fCmd->release(); 2060 fScans[i]->fLockCmd->release(); 2061 IOFree(fScans[i], sizeof(*fScans[i])); 2062 fScans[i] = NULL; 2063 } 2064 2065 if(fNodes[i]) 2066 { 2067 fNodes[i]->release(); 2068 fNodes[i] = NULL; 2069 } 2070 } 2071 2072 // Cancel all commands in timeout queue that want to complete on bus reset 2073 fTimeoutQ.busReset(); 2074} 2075 2076// processSelfIDs 2077// 2078// 2079 2080void IOFireWireController::processSelfIDs(UInt32 *IDs, int numIDs, UInt32 *ownIDs, int numOwnIDs) 2081{ 2082 int i; 2083 UInt32 id; 2084 UInt32 nodeID; 2085 UInt16 irmID; 2086 UInt16 ourID; 2087 IOFireWireLocalNode * localNode; 2088 2089 FWKLOG(( "IOFireWireController::processSelfIDs entered\n" )); 2090 FWTrace_Start(kFWTController, kTPControllerProcessSelfIDs, (uintptr_t)fFWIM, 0, 0, 0); 2091 2092#if (DEBUGGING_LEVEL > 0) 2093for(i=0; i<numIDs; i++) 2094 IOLog("ID %d: 0x%x <-> 0x%x\n", i, IDs[2*i], ~IDs[2*i+1]); 2095 2096for(i=0; i<numOwnIDs; i++) 2097 IOLog("Own ID %d: 0x%x <-> 0x%x\n", i, ownIDs[2*i], ~ownIDs[2*i+1]); 2098#endif 2099 2100 if( fBusState != kWaitingSelfIDs ) 2101 { 2102 // If not processing a reset, then we should be 2103 // This can happen if we get two resets in quick successio 2104 processBusReset(); 2105 } 2106 2107 suspendBus(); 2108 2109 // we should now be in the kWaitingSelfIDs state 2110 2111 if( fBusState != kWaitingSelfIDs ) 2112 { 2113 IOLog( "IOFireWireController::processSelfIDs - fBusState != kWaitingSelfIDs\n" ); 2114 } 2115 2116 if( fBusState == kWaitingSelfIDs ) 2117 { 2118 // cancel self id timeout 2119 fDelayedStateChangeCmd->cancel( kIOReturnAborted ); 2120 } 2121 2122 fBusState = kWaitingScan; 2123 2124 // Initialize root node to be our node, we'll update it below to be the highest node ID. 2125 fRootNodeID = ourID = (OSSwapBigToHostInt32(*ownIDs) & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase; 2126 if( fRootNodeID > 0x3e ) 2127 fRootNodeID = 0x3e; 2128 fLocalNodeID = ourID | (kFWLocalBusAddress>>kCSRNodeIDPhase); 2129 2130 fGapCountMismatch = false; 2131 2132 // check for mismatched gap counts 2133 UInt32 gap_count = (OSSwapBigToHostInt32(*ownIDs) & kFWSelfID0GapCnt) >> kFWSelfID0GapCntPhase; 2134 for( i = 0; i < numIDs; i++ ) 2135 { 2136 UInt32 current_id = OSSwapBigToHostInt32(IDs[2*i]); 2137 if( (current_id & kFWSelfIDPacketType) == 0 && 2138 ((current_id & kFWSelfID0GapCnt) >> kFWSelfID0GapCntPhase) != gap_count ) 2139 { 2140 // set the gap counts to 0x3F, if any gap counts are mismatched 2141 fFWIM->sendPHYPacket( (kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 2142 (0x3f << kFWPhyConfigurationGapCntPhase) | kFWPhyConfigurationT ); 2143 2144 fGapCountMismatch = true; 2145 FWKLOG(( "IOFireWireController::processSelfIDs Found Gap Count Mismatch!\n" )); 2146 break; 2147 } 2148 } 2149 2150 // Update the registry entry for our local nodeID, 2151 // which will have been updated by the device driver. 2152 // Find the local node (just avoiding adding a member variable) 2153 localNode = getLocalNode(this); 2154 if(localNode) 2155 { 2156 localNode->setNodeProperties(fBusGeneration, fLocalNodeID, ownIDs, numOwnIDs,fFWIM->getPhySpeed() ); 2157 fNodes[ourID] = localNode; 2158 localNode->retain(); 2159 } 2160 2161 // Copy over the selfIDs, checking validity and merging in our selfIDs if they aren't 2162 // already in the list. 2163 SInt16 prevID = -1; // Impossible ID. 2164 UInt32 *idPtr = fSelfIDs; 2165 2166 // zero out fNodeIDs so any gaps in the received self IDs will be 2167 // apparent later... 2168 bzero( fNodeIDs, sizeof(fNodeIDs) ) ; 2169 2170 fNumSelfIDs = numIDs; 2171 for(i=0; i<numIDs; i++) 2172 { 2173 UInt32 id = OSSwapBigToHostInt32(IDs[2*i]); 2174 UInt16 currID = (id & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase; 2175 2176 UInt32 id_inverse = ~OSSwapBigToHostInt32( IDs[2*i+1] ); 2177 if(id != id_inverse) 2178 { 2179 IOLog("Bad SelfID packet %d: 0x%x != 0x%x!\n", i, (uint32_t)id, (uint32_t)id_inverse); 2180 2181 FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 1, id, 0 ); 2182 resetBus(); // Could wait a bit in case somebody else spots the bad packet 2183 FWKLOG(( "IOFireWireController::processSelfIDs exited\n" )); 2184 return; 2185 } 2186 2187 if(currID != prevID) 2188 { 2189 // Check for ownids not in main list 2190 if( prevID < ourID && currID > ourID ) 2191 { 2192 int j; 2193 fNodeIDs[ourID] = idPtr; 2194 for(j=0; j<numOwnIDs; j++) 2195 { 2196 *idPtr++ = ownIDs[2*j]; 2197 } 2198 fNumSelfIDs += numOwnIDs; 2199 } 2200 fNodeIDs[currID] = idPtr; 2201 prevID = currID; 2202 if((fRootNodeID < currID) && (currID <= 0x3e)) 2203 fRootNodeID = currID; 2204 } 2205 *idPtr++ = IDs[2*i]; 2206 } 2207 2208 // Check for ownids at end & not in main list 2209 if(prevID < ourID) 2210 { 2211 int j; 2212 fNodeIDs[ourID] = idPtr; 2213 for(j=0; j<numOwnIDs; j++) 2214 { 2215 *idPtr++ = ownIDs[2*j]; 2216 } 2217 fNumSelfIDs += numOwnIDs; 2218 } 2219 // Stick a known elephant at the end. 2220 fNodeIDs[fRootNodeID+1] = idPtr; 2221 2222 // Check nodeIDs are monotonically increasing from 0. 2223 for(i = 0; i<=fRootNodeID; i++) 2224 { 2225 if ( NULL == fNodeIDs[i] ) 2226 { 2227 IOLog("Missing self ID for node %d!\n", i ) ; 2228 FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 2, i, 0 ); 2229 resetBus(); // Could wait a bit in case somebody else spots the bad packet 2230 2231 return; // done. 2232 } 2233 2234 UInt32 host_id = OSSwapBigToHostInt32(*fNodeIDs[i]); 2235 if( ((host_id & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase) != (UInt32)i) 2236 { 2237 IOLog("No FireWire node %d (got ID packet 0x%x)!\n", i, (uint32_t)host_id); 2238 FWTrace(kFWTResetBusAction, kTPResetProcessSelfIDs, (uintptr_t)fFWIM, 3, i, 0 ); 2239 resetBus(); // Could wait a bit in case somebody else spots the bad packet 2240 2241 return; // done. 2242 } 2243 } 2244 2245 // Store selfIDs 2246 OSObject * prop = OSData::withBytes( fSelfIDs, fNumSelfIDs * sizeof(UInt32)); 2247 setProperty(gFireWireSelfIDs, prop); 2248 prop->release(); 2249 2250 buildTopology(false); 2251 2252#if (DEBUGGING_LEVEL > 0) 2253 for(i=0; i<numIDs; i++) { 2254 id = IDs[2*i]; 2255 if(id != ~IDs[2*i+1]) { 2256 DEBUGLOG("Bad SelfID: 0x%x <-> 0x%x\n", id, ~IDs[2*i+1]); 2257 continue; 2258 } 2259 DEBUGLOG("SelfID: 0x%x\n", id); 2260 } 2261 DEBUGLOG("Our ID: 0x%x\n", *ownIDs); 2262#endif 2263 // Find isochronous resource manager, if there is one 2264 irmID = 0; 2265 for(i=0; i<=fRootNodeID; i++) { 2266 id = OSSwapBigToHostInt32(*fNodeIDs[i]); 2267 // Get nodeID. 2268 nodeID = (id & kFWSelfIDPhyID) >> kFWSelfIDPhyIDPhase; 2269 nodeID |= kFWLocalBusAddress>>kCSRNodeIDPhase; 2270 2271 if((id & (kFWSelfID0C | kFWSelfID0L)) == (kFWSelfID0C | kFWSelfID0L)) { 2272#if (DEBUGGING_LEVEL > 0) 2273 IOLog("IRM contender: %lx\n", nodeID); 2274#endif 2275 if(nodeID > irmID) 2276 irmID = nodeID; 2277 } 2278 } 2279 if(irmID != 0) 2280 fIRMNodeID = irmID; 2281 else 2282 fIRMNodeID = kFWBadNodeID; 2283 2284 fBusMgr = false; // Update if we find one. 2285 2286 // inform IRM of updated bus generation and node ids 2287 fIRM->processBusReset( fLocalNodeID, fIRMNodeID, fBusGeneration ); 2288 2289 // OK for stuff that only needs our ID and the irmID to continue. 2290 if(localNode) { 2291 localNode->messageClients(kIOMessageServiceIsResumed); 2292 // force stop should take care of this activateAsyncStreamReceivers(); 2293 } 2294 2295 FWTrace(kFWTStateChangeAction, kTPStateChangeProcessSelfIDs, (uintptr_t)fFWIM, fBusState, 0, 0); 2296 2297 fDelayedStateChangeCmd->reinit(1000 * kScanBusDelay, delayedStateChange, NULL); 2298 fDelayedStateChangeCmd->submit(); 2299 2300 FWTrace_End(kFWTController, kTPControllerProcessSelfIDs, (uintptr_t)fFWIM, 0, 0, 0); 2301 FWKLOG(( "IOFireWireController::processSelfIDs exited\n" )); 2302} 2303 2304void IOFireWireController::processCycle64Int() 2305{ 2306 if( fOutOfTLabels10S++ > 1 ) 2307 { 2308 fOutOfTLabels10S = 0; 2309 2310 if( fOutOfTLabels > fOutOfTLabelsThreshold ) 2311 { 2312 IOLog("IOFireWireController:: %d Out of Transaction Labels in last 3 minutes.\n",(int) fOutOfTLabels); 2313 fOutOfTLabelsThreshold = fOutOfTLabels; 2314 } 2315 else 2316 fOutOfTLabelsThreshold = fOutOfTLabelsThreshold >> 1; // back off by half 2317 2318 fOutOfTLabels = 0; 2319 } 2320} 2321 2322//////////////////////////////////////////////////////////////////////////////// 2323// 2324// AssignCycleMaster 2325// 2326// 2327// 2328 2329bool IOFireWireController::AssignCycleMaster( ) 2330{ 2331 IOReturn status = kIOReturnSuccess; 2332 int i; 2333 UInt32 contender, linkOn, otherContenderID = 0, newRoot = 0, data1; 2334 Boolean otherContender = false, localContender = false, needReset = false, badIRM = false; 2335 2336 if( ((fRootNodeID & 63) == (fLocalNodeID & 63)) && fNodeMustBeRootFlag ) 2337 { 2338 status = fFWIM->setContender( false ); 2339 2340 if(status == kIOReturnSuccess) 2341 { 2342 2343 data1 = (kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 2344 ((fForcedRootNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR; 2345 2346 // Send phy packet to set root hold off bit for node 2347 status = fFWIM->sendPHYPacket(data1); 2348 2349 if(kIOReturnSuccess == status) 2350 needReset = true; 2351 } 2352 } 2353 else if( fDelegateCycleMaster || fBadIRMsKnown || fNodeMustNotBeRootFlag ) 2354 { 2355 for( i = 0; i <= fRootNodeID; i++ ) 2356 { 2357 contender = (OSSwapBigToHostInt32(*fNodeIDs[i]) >> 11) & 0x1; 2358 linkOn = (OSSwapBigToHostInt32(*fNodeIDs[i]) >> 22) & 0x1; 2359 2360 if (contender && linkOn ) 2361 { 2362 if ( i == (fLocalNodeID & 63) ) 2363 { 2364 if (contender) 2365 localContender = true; 2366 } 2367 else 2368 { 2369 if( fScans[i] ) 2370 { 2371 if( (not fScans[i]->fMustNotBeRoot) && (not fScans[i]->fIRMisBad) ) // if designated as root 2372 { 2373 otherContender = true; 2374 otherContenderID = i; // any one will do (use highest) 2375 } 2376 } 2377 } 2378 } 2379 } 2380 2381 if (otherContender) 2382 { 2383 if( (fRootNodeID & 63) == (fLocalNodeID & 63) && fDelegateCycleMaster ) 2384 { 2385 // We are root, but we don't really want to be and somebody else can do the job. 2386 // We're doing this in response to self-IDs, so we have not scanned 2387 // the bus yet - presumably it is safe to use the asynch transmitter 2388 // because nobody else could be using it. 2389 2390 //zzz might want to wait for it to settle down in case it was running 2391 // when the bus reset happened 2392 2393 status = fFWIM->setContender( false ); 2394 2395 if( status == kIOReturnSuccess ) 2396 { 2397 // force root 2398 fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 2399 ((otherContenderID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR ); 2400 2401 needReset = true; 2402 } 2403 } 2404 } 2405 else if( ((fRootNodeID & 63) != (fLocalNodeID & 63)) && (localContender) && (not fDelegateCycleMaster)) 2406 { 2407 status = fFWIM->setContender( true ); 2408 2409 // Set RHB for our soon to be root node and clear everyone else 2410 fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 2411 ((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR ); 2412 2413 needReset = true; 2414 } 2415 2416 if( status == kIOReturnSuccess && fBadIRMsKnown ) 2417 { 2418 // Check for unresponsive IRM 2419 badIRM = (!fScans[fIRMNodeID & 63]) && ((fLocalNodeID & 63) != (fIRMNodeID & 63)); 2420 2421 if( fScans[fIRMNodeID & 63] && fScans[fIRMNodeID & 63]->fIRMisBad ) 2422 badIRM = true; 2423 2424 // If Bad IRM or no IRM then find somebody to do the job 2425 if( badIRM || (!localContender) && (!otherContender) ) 2426 { 2427 2428 if( !fDelegateCycleMaster ) 2429 { 2430 // Mac which wants to be cyclemaster gets priority 2431 newRoot = fLocalNodeID & 63; 2432 fFWIM->setContender( true ); 2433 fFWIM->setRootHoldOff(true); 2434 } 2435 else if( otherContender ) 2436 newRoot = otherContenderID; 2437 else 2438 { 2439 // Oh well, nobody else can do it. Make Mac root. Make sure C is set and set our RHB 2440 newRoot = fLocalNodeID & 63; 2441 fFWIM->setContender( true ); 2442 fFWIM->setRootHoldOff(true); 2443 } 2444 2445 if( badIRM ) 2446 IOLog("IOFireWireController unresponsive IRM at node %x, forcing root to node %x\n", (uint32_t) fIRMNodeID & 63, (uint32_t)newRoot ); 2447 2448 // Set RHB for our soon to be root node and clear everyone else 2449 fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 2450 ((newRoot & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR ); 2451 2452 needReset = true; 2453 } 2454 } 2455 } 2456 2457 if( status == kIOReturnSuccess ) 2458 { 2459 if( needReset ) 2460 { 2461 //FWLogEvent ("HackAvoidBeingRoot Reset Bus\n"); 2462 /* zzzzzzzzz edit comment after checking where this gets called from */ 2463 // It is important to re-enable bus reset interrupts when we issue a bus reset. 2464 // Otherwise if the PHY->Link interface is really confused about self-ID 2465 // streams we might never see the self ID interrupts. (LSI/Lucent problem). 2466 // By re-enabling bus reset interrupts we see the next interrupt and 2467 // FWProcessBusReset will queue its selfID timer. If we don't get self 2468 // ids then FSL will reset the bus until we get real ones which should 2469 // happen eventually. 2470 // 2471 // Since this function is always called from the SelfIDDeferredTask we know 2472 // that bus reset interrupts are enabled and thus don't have to do anything. 2473 2474 // Cause bus reset 2475 FWTrace(kFWTResetBusAction, kTPResetAssignCycleMaster, (uintptr_t)fFWIM, 0, 0, 0 ); 2476 fFWIM->resetBus(); 2477 2478 IOSleep( 10 ); // sleep for 10 ms 2479 } 2480 } 2481 2482 return( needReset ); 2483} 2484 2485 2486// startBusScan 2487// 2488// 2489 2490void IOFireWireController::startBusScan() 2491{ 2492 int i; 2493 2494 FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, 0, 0, 0 ); 2495 FWKLOG(( "IOFireWireController::startBusScan entered\n" )); 2496 2497 OSObject * existProp = fFWIM->getProperty( "FWDSLimit" ); 2498 2499 if( existProp ) 2500 { 2501 fDSLimited = true; 2502 } 2503 else 2504 { 2505 fDSLimited = false; 2506 } 2507 2508 // Send global resume packet 2509 fFWIM->sendPHYPacket(((fLocalNodeID & 0x3f) << kFWPhyPacketPhyIDPhase) | 0x003c0000); 2510 2511 // Tell all active isochronous channels to re-allocate bandwidth 2512 IOFWIsochChannel *found; 2513 fAllocChannelIterator->reset(); 2514 while( (found = (IOFWIsochChannel *)fAllocChannelIterator->getNextObject()) ) 2515 { 2516 found->handleBusReset(); 2517 } 2518 2519 IOFireWireIRMAllocation *irmAllocationfound; 2520 fIRMAllocationsIterator->reset(); 2521 while( (irmAllocationfound = (IOFireWireIRMAllocation *)fIRMAllocationsIterator->getNextObject()) ) 2522 { 2523 irmAllocationfound->handleBusReset(fBusGeneration); 2524 } 2525 2526 fNumROMReads = fRootNodeID+1; 2527 for(i=0; i<=fRootNodeID; i++) { 2528 UInt16 nodeID; 2529 UInt32 id; 2530 id = OSSwapBigToHostInt32(*fNodeIDs[i]); 2531 // Get nodeID. 2532 nodeID = (id & kFWSelfIDPhyID) >> kFWSelfIDPhyIDPhase; 2533 nodeID |= kFWLocalBusAddress>>kCSRNodeIDPhase; 2534 if(nodeID == fLocalNodeID) 2535 { 2536 fNumROMReads--; 2537 continue; // Skip ourself! 2538 } 2539 2540 // ??? maybe we should add an fwdebug bit to be strict on scanning only nodes with link bit? 2541 2542 // Read ROM header if link is active (MacOS8 turns link on, why?) 2543 if(true) { //id & kFWSelfID0L) { 2544 IOFWNodeScan *scan; 2545 scan = (IOFWNodeScan *)IOMalloc(sizeof(*scan)); 2546 2547 scan->fControl = this; 2548 scan->fAddr.nodeID = nodeID; 2549 scan->fAddr.addressHi = kCSRRegisterSpaceBaseAddressHi; 2550 scan->fAddr.addressLo = kConfigBIBHeaderAddress; 2551 scan->fSelfIDs = fNodeIDs[i]; 2552 scan->fNumSelfIDs = fNodeIDs[i+1] - fNodeIDs[i]; 2553 scan->fRead = 0; 2554 scan->generation = fBusGeneration; 2555 scan->fRetriesBumped = 0; 2556 scan->fCmd = OSTypeAlloc( IOFWReadQuadCommand ); 2557 scan->fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand ); 2558 2559 // Read an IRM Register if node is a contender 2560 if( (id & (kFWSelfID0C | kFWSelfID0L)) == (kFWSelfID0C | kFWSelfID0L) ) 2561 { 2562 // IOLog("Node 0x%x is Contender\n",nodeID); 2563 scan->fContenderNeedsChecking = true; 2564 } 2565 else 2566 scan->fContenderNeedsChecking = false; 2567 scan->fIRMisBad = false; 2568 scan->fIRMCheckingRead = false; 2569 scan->fIRMCheckingLock = false; 2570 2571 FWKLOG(( "IOFireWireController::startBusScan node %lx speed was %lx\n",(UInt32)nodeID,(UInt32)FWSpeed( nodeID ) )); 2572 2573 if ( fDebugIgnoreNode != kFWDebugIgnoreNodeNone && ((fDebugIgnoreNode & kFWMaxNodesPerBus ) == (nodeID & kFWMaxNodesPerBus )) ) 2574 { 2575 // we do not want to speedcheck an ignored node. 2576 scan->speedChecking = false; 2577 2578 // If current speed to node is masked (ie speedchecking necessary), set to s100. 2579 // This is because we treat an "ignored" node as a unresponsive node (eg hub) 2580 // and if we were to speedcheck it, we would step-down to s100, unmasked. 2581 if( FWSpeed( nodeID ) & kFWSpeedUnknownMask ) 2582 setNodeSpeed(scan->fAddr.nodeID, kFWSpeed100MBit); 2583 // else, do not change current speed to node, which is concurrent with 2584 // the non-ignore, non-speedchecking code below. 2585 2586 // using kIOReturnNotPermitted because, simply, it's different than 2587 // success, timeout, or bus reset. 2588 scan->fControl->readDeviceROM(scan, kIOReturnNotPermitted); 2589 } 2590 else 2591 { 2592 if( FWSpeed( nodeID ) & kFWSpeedUnknownMask ) 2593 { 2594 setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, (FWSpeed(scan->fAddr.nodeID, fLocalNodeID) & ~kFWSpeedUnknownMask)); 2595 2596 scan->fCmd->initAll(this, fBusGeneration, scan->fAddr, scan->fBuf, 1, 2597 &readROMGlue, scan); 2598 2599 FWKLOG(( "IOFireWireController::startBusScan speedchecking\n" )); 2600 scan->speedChecking = true; // May need to try speeds slower than s800 if this fails 2601 // zzz What about s1600? 2602 } 2603 else 2604 { 2605 scan->fCmd->initAll(this, fBusGeneration, scan->fAddr, scan->fBuf, 1, 2606 &readROMGlue, scan); 2607 2608 scan->fCmd->setMaxSpeed( kFWSpeed100MBit ); 2609 scan->speedChecking = false; 2610 FWKLOG(( "IOFireWireController::startBusScan not speedchecking\n" )); 2611 } 2612 2613 scan->fIRMBitBucketNew = 0xffffffff; 2614 scan->fIRMBitBucketOld = 0xffffffff; 2615 2616 scan->fLockCmd->initAll(this, fBusGeneration, scan->fAddr, &scan->fIRMBitBucketOld, &scan->fIRMBitBucketNew, 1, &readROMGlue, scan); 2617 2618 FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 1 ); 2619 2620 scan->fCmd->setRetries(kFWCmdZeroRetries); // don't need to bump kRetriesBumped here 2621 scan->fCmd->submit(); 2622 2623 } 2624 } 2625 } 2626 2627 if(fNumROMReads == 0) { 2628 FWTrace( kFWTController, kTPControllerStartBusScan, (uintptr_t)fFWIM, 0, 0, 2 ); 2629 finishedBusScan(); 2630 } 2631 2632 FWKLOG(( "IOFireWireController::startBusScan exited\n" )); 2633} 2634 2635// readROMGlue 2636// 2637// 2638 2639void IOFireWireController::readROMGlue(void *refcon, IOReturn status, 2640 IOFireWireNub *device, IOFWCommand *fwCmd) 2641{ 2642 IOFWNodeScan *scan = (IOFWNodeScan *)refcon; 2643 scan->fControl->readDeviceROM(scan, status); 2644} 2645 2646// readDeviceROM 2647// 2648// 2649 2650void IOFireWireController::readDeviceROM(IOFWNodeScan *scan, IOReturn status) 2651{ 2652 bool done = true; 2653 2654 FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 0 ); 2655 FWKLOG(( "IOFireWireController::readDeviceROM entered\n" )); 2656 2657 if(status != kIOReturnSuccess) 2658 { 2659 // If status isn't bus reset, make a dummy registry entry. 2660 2661 if(status == kIOFireWireBusReset) 2662 { 2663 scan->fCmd->release(); 2664 scan->fLockCmd->release(); 2665 IOFree(scan, sizeof(*scan)); 2666 FWKLOG(( "IOFireWireController::readDeviceROM exited\n" )); 2667 return; 2668 } 2669 2670 if( scan->fCmd->getAckCode() == kFWAckBusyX || scan->fCmd->getAckCode() == kFWAckBusyA || scan->fCmd->getAckCode() == kFWAckBusyB ) 2671 { 2672 // Newer Macs with only one FW port will turn off the PHY on sleep. Some hard disks go into a low-power sleep mode if they are the only 2673 // node on the bus. Some of these are larger devices which take a long time to spin up once the Mac wakes again. These drives seem to return 2674 // AckBusyX when spinning up. If we see this from any device on the bus and we've just woken up then we need to wait some additional time for 2675 // the drives to spin up or else the user will get an unplug notice. 2676 // 2677 // rdar://problem/6190408 2678 // rdar://problem/6237407 2679 2680 if( fDevicePruneDelay >= kWakeDevicePruneDelay && fDevicePruneDelay < kWakeDevicePruneDelayBusy ) 2681 fDevicePruneDelay = kWakeDevicePruneDelayBusy; 2682 } 2683 2684 if( scan->fIRMCheckingRead || scan->fIRMCheckingLock ) 2685 { 2686 // IOLog("Bad IRM for Node 0x%x Rd %d Lk %d\n",scan->fAddr.nodeID,scan->fIRMCheckingRead,scan->fIRMCheckingLock); 2687 if( (scan->fAddr.nodeID & 63) == (fIRMNodeID & 63) ) 2688 fBadIRMsKnown = true; 2689 2690 scan->fIRMisBad = true; 2691 scan->fContenderNeedsChecking = false; 2692 } 2693 else 2694 { 2695 2696 // "Naughty Camera Workaround" 2697 // If a "slow" device responds AckPending to the first attempt of the first BIB ReadQuad during 2698 // BusScan AND TIMES OUT (no ReadResp), we increase the number of times that ReadQuad may retry it's command 2699 // because we know the device is there, but not ready to respond to ConfigROM reads. 2700 2701 // This "if" should run after trying the command once, but before it retries. 2702 // Check if command timed out and we haven't increased the retries for this speed 2703 if( status == kIOReturnTimeout && scan->fRetriesBumped == 0 ) 2704 { 2705 // Limit workaround to BIBHeaderAddress to avoid long delay caused by a really slow device 2706 // (e.g. hung node) ackPending any attempt to read any address. This will make sure we don't wait 2707 // "too" long while trying to collect all GUIDs, like lose our time to reconnect to an SBP2 device. 2708 if ( scan->fCmd->getAckCode() == kFWAckPending && scan->fAddr.addressLo == kConfigBIBHeaderAddress ) 2709 { 2710 FWKLOG(( "IOFireWireController::readDeviceROM Node 0x%x timed out on ack %d, setting setMaxRetries = %d\n", scan->fAddr.nodeID, scan->fCmd->getAckCode(), kFWCmdIncreasedRetries)); 2711 2712 // increase retries and set RetriesBumped flag 2713 scan->fCmd->setRetries(kFWCmdIncreasedRetries); 2714 scan->fRetriesBumped++; 2715 2716 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 1 ); 2717 2718 // re-submit command for increased number of retries 2719 scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true); 2720 scan->fCmd->submit(); 2721 return; 2722 } 2723 else 2724 { 2725 // increase retries to normal-1 and set RetriesBumped flag 2726 scan->fCmd->setRetries(kFWCmdReducedRetries); 2727 scan->fRetriesBumped++; 2728 2729 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 2 ); 2730 2731 // re-submit command for the rest of the retries 2732 scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true); 2733 scan->fCmd->submit(); 2734 return; 2735 } 2736 } 2737 2738 2739 // Speed checking for 1394b compatibility 2740 FWKLOG(( "IOFireWireController::readDeviceROM speedcheck %lx ; speed %lx\n", (UInt32)scan->speedChecking, (UInt32)FWSpeed( scan->fAddr.nodeID ) )); 2741 if( scan->speedChecking && FWSpeed( scan->fAddr.nodeID ) > kFWSpeed100MBit ) 2742 { 2743 if( scan->generation == fBusGeneration ) 2744 { 2745 FWKLOG(( "IOFireWireController::readDeviceROM reseting speed for node %lx from local %lx\n", (UInt32)scan->fAddr.nodeID, (UInt32)fLocalNodeID)); 2746 if( fDSLimited ) 2747 { 2748 setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, kFWSpeed100MBit); 2749 } 2750 else 2751 { 2752 setNodeSpeed(scan->fAddr.nodeID, fLocalNodeID, (FWSpeed(scan->fAddr.nodeID, fLocalNodeID) - 1)); 2753 } 2754 2755 // Retry command at slower speed 2756 scan->fCmd->reinit(scan->fAddr, scan->fBuf, 1, &readROMGlue, scan, true); 2757 2758 if ( scan->fAddr.addressLo == kConfigBIBHeaderAddress ) 2759 { 2760 // Reset to run Naughty Camera check on first try of QRead at next speed 2761 scan->fCmd->setRetries(kFWCmdZeroRetries); 2762 scan->fRetriesBumped = 0; 2763 } 2764 else 2765 { 2766 scan->fCmd->setRetries(kFWCmdDefaultRetries); 2767 scan->fRetriesBumped = 0; 2768 } 2769 2770 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 3 ); 2771 2772 scan->fCmd->submit(); 2773 return; 2774 } 2775 } 2776 2777 if( (scan->fAddr.nodeID & 63) == (fIRMNodeID & 63) ) 2778 fBadIRMsKnown = true; 2779 2780 UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID); 2781 fNodes[nodeID] = createDummyRegistryEntry( scan ); 2782 2783 fNumROMReads--; 2784 if(fNumROMReads == 0) 2785 { 2786 FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 1 ); 2787 finishedBusScan(); 2788 } 2789 2790 scan->fCmd->release(); 2791 scan->fLockCmd->release(); 2792 IOFree(scan, sizeof(*scan)); 2793 FWKLOG(( "IOFireWireController::readDeviceROM exited\n" )); 2794 return; 2795 } 2796 } 2797 2798 if( scan->fRead == 0 ) 2799 { 2800 UInt32 bib_quad = OSSwapBigToHostInt32( scan->fBuf[0] ); 2801 if( ((bib_quad & kConfigBusInfoBlockLength) >> kConfigBusInfoBlockLengthPhase) == 1) 2802 { 2803 // Minimal ROM 2804 scan->fROMSize = 4; 2805 done = true; 2806 } 2807 else 2808 { 2809 scan->fROMSize = 20; // Just read bus info block 2810 scan->fRead = 8; 2811 scan->fBuf[1] = OSSwapHostToBigInt32( kFWBIBBusName ); // no point reading this! 2812 scan->fAddr.addressLo = kConfigROMBaseAddress+8; 2813 scan->fCmd->reinit(scan->fAddr, scan->fBuf+2, 1, 2814 &readROMGlue, scan, true); 2815 scan->fCmd->setMaxSpeed( kFWSpeed100MBit ); 2816 scan->fCmd->setRetries( kFWCmdDefaultRetries ); 2817 scan->fCmd->setPingTime( true ); // ping time second quad 2818 2819 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 4 ); 2820 2821 scan->fCmd->submit(); 2822 done = false; 2823 } 2824 } 2825 else if( scan->fRead < 16 ) 2826 { 2827 if(scan->fROMSize > scan->fRead) 2828 { 2829 scan->fRead += 4; 2830 scan->fAddr.addressLo = kConfigROMBaseAddress+scan->fRead; 2831 scan->fCmd->reinit(scan->fAddr, scan->fBuf+scan->fRead/4, 1, 2832 &readROMGlue, scan, true); 2833 scan->fCmd->setMaxSpeed( kFWSpeed100MBit ); 2834 scan->fCmd->setRetries(kFWCmdDefaultRetries); 2835 scan->fCmd->setPingTime( false ); // only ping time on the second quad 2836 2837 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 5 ); 2838 2839 scan->fCmd->submit(); 2840 done = false; 2841 } 2842 else 2843 { 2844 done = true; 2845 } 2846 } 2847 else if( scan->fContenderNeedsChecking && (FWSpeed( scan->fAddr.nodeID ) > kFWSpeed100MBit) ) 2848 { 2849 // Only do this check if node is > 100 MBit. s100 devices are nearly always camcorders and not likely to have 2850 // non-functional IRMs. 2851 2852 // Need to know if this is a capable IRM if this node is already IRM or if Mac doesn't 2853 // want to be IRM and this is a candidate. 2854 2855 if( ((scan->fAddr.nodeID & 63) == (fIRMNodeID & 63)) || fDelegateCycleMaster ) 2856 { 2857 if( !scan->fIRMCheckingRead ) 2858 { 2859 scan->fIRMCheckingRead = true; // Doing the Read check this go-around 2860 2861 scan->fAddr.addressLo = kCSRChannelsAvailable63_32; 2862 scan->fCmd->reinit(scan->fAddr, &scan->fIRMBitBucketOld, 1, 2863 &readROMGlue, scan, true); 2864 scan->fCmd->setMaxSpeed( kFWSpeed100MBit ); 2865 scan->fCmd->setRetries(kFWCmdDefaultRetries); 2866 2867 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 6 ); 2868 scan->fCmd->submit(); 2869 done = false; 2870 } 2871 else 2872 { 2873 2874 // IOLog("Checking IRM for Node 0x%x\n",scan->fAddr.nodeID); 2875 scan->fIRMCheckingLock = true; // Doing the Lock check this go-around 2876 scan->fContenderNeedsChecking = false; // Don't check again 2877 scan->fAddr.addressLo = kCSRChannelsAvailable63_32; 2878 2879 scan->fLockCmd->reinit( scan->generation, scan->fAddr, &scan->fIRMBitBucketOld, &scan->fIRMBitBucketNew, 1, &readROMGlue, scan); 2880 2881 scan->fLockCmd->setMaxSpeed( kFWSpeed100MBit ); 2882 scan->fLockCmd->setRetries(kFWCmdDefaultRetries); 2883 2884 FWTrace( kFWTController, kTPControllerReadDeviceROMSubmitCmd, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 7 ); 2885 scan->fLockCmd->submit(); 2886 done = false; 2887 } 2888 } 2889 } 2890 2891 2892 2893 if( done ) 2894 { 2895 UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID); 2896 2897 FWKLOG(( "IOFireWireController::readDeviceROM scan for ID %lx is %lx\n",nodeID,(long) scan )); 2898 fScans[nodeID] = scan; 2899 2900 updateDevice( scan ); 2901 2902 fNumROMReads--; 2903 if(fNumROMReads == 0) 2904 { 2905 FWTrace( kFWTController, kTPControllerReadDeviceROM, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), status, 2 ); 2906 finishedBusScan(); 2907 } 2908 2909 } 2910 2911 FWKLOG(( "IOFireWireController::readDeviceROM exited\n" )); 2912} 2913 2914// checkForDuplicateGUID 2915// 2916// 2917bool IOFireWireController::checkForDuplicateGUID(IOFWNodeScan *scan, CSRNodeUniqueID *currentGUIDs ) 2918{ 2919 CSRNodeUniqueID guid; 2920 UInt32 nodeID; 2921 UInt32 i; 2922 2923 nodeID = FWAddressToID(scan->fAddr.nodeID); 2924 2925 if(scan->fROMSize >= 20) 2926 { 2927 UInt32 guid_hi = OSSwapBigToHostInt32( scan->fBuf[3] ); 2928 UInt32 guid_lo = OSSwapBigToHostInt32( scan->fBuf[4] ); 2929 2930 guid = ((CSRNodeUniqueID)guid_hi << 32) | guid_lo; 2931 } 2932 else 2933 { 2934 currentGUIDs[nodeID] = 0; 2935 return false; // not a real ROM, don't care. 2936 } 2937 2938 currentGUIDs[nodeID] = guid; 2939 2940 if( !guid || fGUIDDups->findDuplicateGUID( guid, fBusGeneration ) ) 2941 return false; // Already found or zero, don't add it. Return false so caller doesn't reset the bus again 2942 2943 for( i = 0; i< nodeID; i++ ) 2944 { 2945 if( currentGUIDs[i] == guid ) 2946 { 2947 fGUIDDups->addDuplicateGUID( guid, fBusGeneration ); 2948 return true; 2949 } 2950 } 2951 2952 return false; 2953} 2954 2955// updateDevice 2956// 2957// 2958 2959void IOFireWireController::updateDevice(IOFWNodeScan *scan ) 2960{ 2961 FWTrace( kFWTController, kTPControllerUpdateDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, 0 ); 2962 2963 // See if this is a bus manager 2964 UInt32 bib_quad = OSSwapBigToHostInt32( scan->fBuf[2] ); 2965 if( !fBusMgr ) 2966 { 2967 fBusMgr = bib_quad & kFWBIBBmc; 2968 } 2969 2970// Check if node exists, if not create it 2971#if (DEBUGGING_LEVEL > 0) 2972 IOLog("Update Device Finished reading ROM for node 0x%x\n", scan->fAddr.nodeID); 2973#endif 2974 IOFireWireDevice * newDevice = NULL; 2975 do 2976 { 2977 CSRNodeUniqueID guid; 2978 OSIterator *childIterator; 2979 UInt32 nodeID; 2980 bool duplicate; 2981 bool minimal = false; 2982 2983 nodeID = FWAddressToID(scan->fAddr.nodeID); 2984 2985 if(scan->fROMSize >= 20) 2986 { 2987 UInt32 guid_hi = OSSwapBigToHostInt32( scan->fBuf[3] ); 2988 UInt32 guid_lo = OSSwapBigToHostInt32( scan->fBuf[4] ); 2989 2990 guid = ((CSRNodeUniqueID)guid_hi << 32) | guid_lo; 2991 } 2992 else 2993 { 2994 minimal = true; 2995 guid = 0; 2996 } 2997 2998 // 2999 // GUID zero is not a valid GUID. Unfortunately some devices return this as 3000 // their GUID until they're fully powered up. 3001 // 3002 // 3003 3004 // Also check nodes for known bad GUIDs and don't bother with them 3005 // 3006 3007 duplicate = fGUIDDups->findDuplicateGUID( guid, fBusGeneration ); 3008 3009 if( (guid == 0) || duplicate ) 3010 { 3011 fNodes[nodeID] = createDummyRegistryEntry( scan ); 3012 if( minimal ) 3013 { 3014 OSObject * prop = OSData::withBytes( &scan->fBuf[0], scan->fROMSize ); 3015 if( prop != NULL ) 3016 { 3017 fNodes[nodeID]->setProperty( gFireWireROM, prop ); 3018 prop->release(); 3019 } 3020 } 3021 else 3022 { 3023 OSObject * prop = OSNumber::withNumber( guid, 64 ); 3024 if( prop != NULL ) 3025 { 3026 fNodes[nodeID]->setProperty( gFireWire_GUID, prop ); 3027 prop->release(); 3028 3029 } 3030 } 3031// if( duplicate ) 3032// { 3033// 3034// OSString * prop = OSString::withCString("Device with illegal duplicate GUID"); 3035// if( prop2 != NULL ) 3036// { 3037// fNodes[nodeID]->setProperty( gFireWireProduct_Name, prop ); 3038// prop->release(); 3039// } 3040// } 3041 continue; 3042 } 3043 3044 childIterator = getClientIterator(); 3045 if( childIterator) 3046 { 3047 OSObject *child; 3048 while( (child = childIterator->getNextObject())) 3049 { 3050 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 3051 if( found ) 3052 { 3053 // sync with open / close routines on device 3054 found->lockForArbitration(); 3055 3056 if( found->fUniqueID == guid && (found->getTerminationState() != kTerminated) ) 3057 { 3058 newDevice = found; 3059 3060 // arbitration lock still held 3061 3062 break; 3063 } 3064 3065 found->unlockForArbitration(); 3066 } 3067 } 3068 childIterator->release(); 3069 } 3070 3071 if(newDevice) 3072 { 3073 FWTrace( kFWTController, kTPControllerUpdateDeviceNewDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, (uintptr_t)newDevice ); 3074 3075 // Just update device properties. 3076 #if IOFIREWIREDEBUG > 0 3077 IOLog("UpdateDevice Found old device 0x%p\n", newDevice); 3078 #endif 3079 3080 // arbitration lock still held 3081 3082 if( newDevice->getTerminationState() == kNeedsTermination ) 3083 { 3084 newDevice->setTerminationState( kNotTerminated ); 3085 } 3086 3087 newDevice->unlockForArbitration(); 3088 3089 newDevice->setNodeROM(fBusGeneration, fLocalNodeID, scan); 3090 newDevice->retain(); // match release, since not newly created. 3091 } 3092 else 3093 { 3094 newDevice = fFWIM->createDeviceNub(guid, scan); 3095 if (!newDevice) 3096 continue; 3097 3098 FWTrace( kFWTController, kTPControllerUpdateDeviceCreateDevice, (uintptr_t)fFWIM, (uintptr_t)(scan->fCmd), scan->fAddr.nodeID, (uintptr_t)newDevice ); 3099 3100 #if IOFIREWIREDEBUG > 0 3101 IOLog("Update Device Creating new device 0x%p\n", newDevice); 3102 #endif 3103 3104 // In response to <rdar://7116134>. Logging here to see if we can find a reproducible case of this panic. 3105 ErrorLogCond( !newDevice, "IOFireWireController@%p::updateDevice Error creating device nub! (%p, %p)\n", this, fFWIM, newDevice ); 3106 3107 // we must stay busy until we've called registerService on the device 3108 // and all of its units 3109 3110 newDevice->adjustBusy( 1 ); // device 3111 adjustBusy( 1 ); // controller 3112 3113 FWKLOG(( "IOFireWireController@%p::updateDevice adjustBusy(1)\n", this )); 3114 3115 // hook this device into the device tree now 3116 3117 // we won't rediscover this device after a bus reset if the device is 3118 // not in the registry. if we attached later and got a bus reset before 3119 // we had attached the device we would leak the device object 3120 3121 if( !newDevice->attach(this) ) 3122 { 3123 // if we failed to attach, I guess we're not busy anymore 3124 newDevice->adjustBusy( -1 ); // device 3125 adjustBusy( -1 ); // controller 3126 FWKLOG(( "IOFireWireController@%p::updateDevice adjustBusy(-1)\n", this )); 3127 continue; 3128 } 3129 3130 // we will register this service once we finish reading the config rom 3131 newDevice->setRegistrationState( IOFireWireDevice::kDeviceNeedsRegisterService ); 3132 3133 // this will start the config ROM read 3134 newDevice->setNodeROM( fBusGeneration, fLocalNodeID, scan ); 3135 3136 } 3137 3138 fNodes[nodeID] = newDevice; 3139 fNodes[nodeID]->retain(); 3140 3141 } while (false); 3142 3143 if (newDevice) 3144 newDevice->release(); 3145 3146} 3147 3148 3149 3150// createDummyRegistryEntry 3151// 3152// if we are unable to successfully read the BIB of a a device, we create 3153// a dummy registry entry by calling this routine 3154 3155IORegistryEntry * IOFireWireController::createDummyRegistryEntry( IOFWNodeScan *scan ) 3156{ 3157 OSDictionary *propTable; 3158 OSObject * prop; 3159 propTable = OSDictionary::withCapacity(3); 3160 prop = OSNumber::withNumber(scan->fAddr.nodeID, 16); 3161 propTable->setObject(gFireWireNodeID, prop); 3162 prop->release(); 3163 3164 prop = OSNumber::withNumber((OSSwapBigToHostInt32(scan->fSelfIDs[0]) & kFWSelfID0SP) >> kFWSelfID0SPPhase, 32); 3165 propTable->setObject(gFireWireSpeed, prop); 3166 prop->release(); 3167 3168 prop = OSData::withBytes(scan->fSelfIDs, scan->fNumSelfIDs*sizeof(UInt32)); 3169 propTable->setObject(gFireWireSelfIDs, prop); 3170 prop->release(); 3171 3172 IORegistryEntry * newPhy; 3173 newPhy = OSTypeAlloc( IORegistryEntry ); 3174 if(newPhy) 3175 { 3176 if(!newPhy->init(propTable)) 3177 { 3178 newPhy->release(); 3179 newPhy = NULL; 3180 } 3181 if(getSecurityMode() == kIOFWSecurityModeNormal) { 3182 // enable physical access for FireBug and other debug tools without a ROM 3183 setNodeIDPhysicalFilter( scan->fAddr.nodeID & 0x3f, true ); 3184 } 3185 if(propTable) 3186 propTable->release(); 3187 } 3188 3189 return newPhy; 3190} 3191 3192// finishedBusScan 3193// 3194// 3195 3196void IOFireWireController::finishedBusScan() 3197{ 3198 FWTrace_Start( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 0 ); 3199 3200 // These magic numbers come from P1394a, draft 4, table C-2. 3201 // This works for cables up to 4.5 meters and PHYs with 3202 // PHY delay up to 144 nanoseconds. Note that P1394a PHYs 3203 // are allowed to have delay >144nS; we don't cope yet. 3204 static UInt32 gaps[26] = {63, 5, 7, 8, 10, 13, 16, 18, 21, 3205 24, 26, 29, 32, 35, 37, 40, 43, 3206 46, 48, 51, 54, 57, 59, 62, 63}; 3207 int i; 3208 3209 if( AssignCycleMaster() ) 3210 { 3211 FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 1 ); 3212 return; 3213 } 3214 3215 fBadIRMsKnown = false; // If we got here we're happy with the IRM/CycleMaster. No need to read the IRM registers for all nodes 3216 3217 // Go update all the devices now that we've read their ROMs. 3218 { 3219 CSRNodeUniqueID currentGUIDs[kFWMaxNodesPerBus]; 3220 3221 // First check for duplicate GUIDs 3222 for( i=0; i<=fRootNodeID; i++ ) 3223 { 3224 if( fScans[i] ) 3225 { 3226 if( checkForDuplicateGUID( fScans[i], currentGUIDs ) ) 3227 { 3228 // Whoops, duplicate GUID! Reset Bus and bail. 3229 // From now on if UpdateDevice is called with this GUID we won't 3230 // reconnect to it. 3231 3232 FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, fScans[i]->fAddr.nodeID, 1, 0 ); 3233 resetBus(); 3234 3235 FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 2 ); 3236 return; // We'll be right back after these messages from our sponsor 3237 } 3238 3239 fScans[i]->fCmd->release(); 3240 fScans[i]->fLockCmd->release(); 3241 IOFree(fScans[i], sizeof(*fScans[i])); 3242 fScans[i] = NULL; 3243 3244 } 3245 else 3246 { 3247 currentGUIDs[i] = 0; 3248 } 3249 } 3250 } 3251 3252 // Now do simple bus manager stuff, if there isn't a better candidate. 3253 // This might cause us to issue a bus reset... 3254 // Skip if we're about to reset anyway, since we might be in the process of setting 3255 // another node to root. 3256 if( !fBusResetScheduled && !fBusMgr && fLocalNodeID == fIRMNodeID) 3257 { 3258 UInt32 * pingTimes; 3259 int maxHops; 3260 UInt32 maxPing = 0; 3261 UInt32 pingGap=0, hopGap=0, newGap=0; 3262 bool retoolGap = false; 3263 3264 if ( not fForcedGapFlag ) 3265 { 3266 // Set the gap count based on maximum ping time. This assumes the Mac is not in the middle 3267 // of a star with long haul's going out in two different directions from the Mac. To obtain 3268 // the gap cound we use the following algorithm: 3269 // 3270 // Gap = GapTable[ (MaxPing - 20) / 9 ] 3271 3272 // This result is then compared to the value arrived at with the standard hop count based 3273 // table lookup. The higher value is used for the new gap. 3274 3275 // If we don't have ping time information (such as with a Lynx FWIM that doesn't support 3276 // ping timimg) then we use the maximum hop count to index into the table. 3277 3278 // Do lazy gap count optimization. Assume the bus is a daisy-chain (worst 3279 // case) so hop count == root ID. 3280 3281 // a little note on the gap count optimization - all I do is set an internal field to our optimal 3282 // gap count and then reset the bus. my new soft bus reset code sets the gap count before resetting 3283 // the bus (for another reason) and I just rely on that fact. 3284 3285 pingTimes = fFWIM->getPingTimes(); 3286 3287 for( i=0; i<=fRootNodeID; i++ ) 3288 { 3289 //IOLog("IOFireWireController node 0x%lx ping 0x%lx\n",i,pingTimes[i]); 3290 3291 if( pingTimes[i] > maxPing ) 3292 maxPing = pingTimes[i]; 3293 } 3294 3295 maxHops = fRootNodeID; 3296 if (maxHops > 25) 3297 maxHops = 25; 3298 3299 if( maxPing > 245 ) 3300 maxPing = 245; 3301 3302 if( maxPing >= 29 ) 3303 pingGap = gaps [(maxPing - 20) / 9]; // Assumes Mac is NOT in the middle of 2 long haul subnets 3304 else 3305 pingGap = 5; 3306 3307 hopGap = gaps[maxHops]; 3308 3309 if( hopGap > pingGap ) 3310 newGap = hopGap; 3311 else 3312 newGap = pingGap; 3313 3314 // IOLog("IOFireWireController MaxPingTime: 0x%lx PingGap: 0x%lx HopGap: 0x%lx Setting Gap to 0x%lx\n",maxPing, pingGap, hopGap, newGap); 3315 fGapCount = newGap << kFWPhyConfigurationGapCntPhase; 3316 } 3317 else 3318 { 3319 if( fPreviousGap != (fForcedGapCount << kFWPhyConfigurationGapCntPhase) ) 3320 { 3321 fGapCount = fForcedGapCount << kFWPhyConfigurationGapCntPhase; 3322 retoolGap = true; 3323 IOLog( "IOFireWireController::finishedBusScan retoold GAP %d\n", __LINE__ ); 3324 } 3325 } 3326 3327 FWKLOG(("IOFireWireController MaxPingTime: 0x%lx PingGap: 0x%lx HopGap: 0x%lx Setting Gap to 0x%lx\n",maxPing, pingGap, hopGap, newGap)); 3328 FWTrace( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, pingGap, hopGap, newGap ); 3329 3330 fGapCount = ( fForcedGapFlag ) ? fForcedGapCount << kFWPhyConfigurationGapCntPhase : newGap << kFWPhyConfigurationGapCntPhase; 3331 3332 3333 if(fRootNodeID == 0) 3334 { 3335 // If we're the only node, clear root hold off. 3336 fFWIM->setRootHoldOff(false); 3337 } 3338 else 3339 { 3340 // Send phy packet to get rid of other root hold off nodes 3341 // Set gap count too. 3342 fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 3343 ((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR ); 3344 fFWIM->setRootHoldOff(true); 3345 3346 // If we aren't root, issue a bus reset so that we will be. 3347 if(fRootNodeID != (fLocalNodeID & 63)) 3348 { 3349 // IOLog( "IOFireWireController::finishedBusScan - make us root\n" ); 3350 FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, 0, 2, 0 ); 3351 3352 resetBus(); 3353 3354 FWKLOG(( "IOFireWireController::finishedBusScan exited\n" )); 3355 FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 3 ); 3356 return; // We'll be back... 3357 } 3358 } 3359 3360 // If we got here we're root, so turn on cycle master 3361 fFWIM->setCycleMaster(true); 3362 3363 // Finally set gap count if any nodes don't have the right gap. 3364 // Only bother if we aren't the only node on the bus. 3365 // To avoid changing the gap due to ping time jitter we check to see that the gaps 3366 // are both consistent and either the same as we last set it or the same as the new gap. 3367 3368 3369 if(fRootNodeID != 0) 3370 { 3371 // is the gap count consistent? 3372 for( i = 1; i <= fRootNodeID; i++ ) 3373 { 3374 if( (OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != (OSSwapBigToHostInt32(*fNodeIDs[i - 1]) & kFWSelfID0GapCnt) ) 3375 { 3376 //IOLog( "IOFireWireController::finishedBusScan inconsistent gaps!\n"); 3377 retoolGap = true; 3378 break; 3379 } 3380 } 3381 3382 if( !retoolGap && !fDSLimited ) 3383 { 3384 // is the gap something we set? 3385 for( i = 0; i <= fRootNodeID; i++ ) 3386 { 3387 if( ((OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != fPreviousGap 3388 && (OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) != fGapCount) 3389 || ((OSSwapBigToHostInt32(*fNodeIDs[i]) & kFWSelfID0GapCnt) == 0) ) 3390 { 3391 //IOLog( "IOFireWireController::finishedBusScan need new gap count\n"); 3392 retoolGap = true; 3393 break; 3394 } 3395 } 3396 } 3397 3398 if( retoolGap ) 3399 { 3400 3401 //IOLog( "IOFireWireController::finishedBusScan prev: %08lx new: %08lx node: %08lx\n",fPreviousGap, fGapCount, (*fNodeIDs[i] & kFWSelfID0GapCnt) ); 3402 3403 fPreviousGap = fGapCount; 3404 3405 // send phy config packet and do bus reset. 3406 fDelayedPhyPacket = (kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 3407 ((fLocalNodeID & 63) << kFWPhyPacketPhyIDPhase) | 3408 kFWPhyConfigurationR | fGapCount | kFWPhyConfigurationT; 3409 // IOLog( "IOFireWireController::finishedBusScan - set gap count\n" ); 3410 3411 FWTrace(kFWTResetBusAction, kTPResetFinishedBusScan, (uintptr_t)fFWIM, fGapCount, 3, 0 ); 3412 3413 resetBus(); 3414 3415 FWKLOG(( "IOFireWireController::finishedBusScan exited\n" )); 3416 FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 4 ); 3417 return; // We'll be back... 3418 } 3419 } 3420 } 3421 3422 3423 // 3424 // Don't change to the waiting prune state if we're about to bus reset again anyway. 3425 // 3426 3427 if(fBusState == kScanning) 3428 { 3429 bool wouldTerminateDevice = false; 3430 OSIterator * childIterator; 3431 3432 // 3433 // check if we would terminate a device if the prune timer ran right now 3434 // 3435 3436 childIterator = getClientIterator(); 3437 if( childIterator ) 3438 { 3439 OSObject *child; 3440 while( (child = childIterator->getNextObject())) 3441 { 3442 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 3443 3444 // don't need to sync with open/close routines when checking for kNotTerminated 3445 if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == kFWBadNodeID ) 3446 { 3447 wouldTerminateDevice = true; 3448 } 3449 } 3450 childIterator->release(); 3451 } 3452 3453 // 3454 // if we found all of our devices, set the prune delay to normal 3455 // 3456 3457 if( (fRootNodeID == 0) && (fDevicePruneDelay < kOnlyNodeDevicePruneDelay) ) 3458 { 3459 // if we're the only node increase the prune delay 3460 // because we won't be causing a bus reset for gap 3461 // count optimization. 3462 3463 fDevicePruneDelay = kOnlyNodeDevicePruneDelay; 3464 } 3465 3466 if( !wouldTerminateDevice ) 3467 { 3468 fDevicePruneDelay = kNormalDevicePruneDelay; 3469 } 3470 3471 fBusState = kWaitingPrune; // Indicate end of bus scan 3472 fDelayedStateChangeCmd->reinit(1000 * fDevicePruneDelay, delayedStateChange, NULL); // One second 3473 FWTrace(kFWTStateChangeAction, kTPStateChangeFinishedBusScan, (uintptr_t)fFWIM, fBusState, 0, 0 ); 3474 fDelayedStateChangeCmd->submit(); 3475 } 3476 3477 // Run all the commands that are waiting for reset processing to end 3478 IOFWCmdQ &resetQ(getAfterResetHandledQ()); 3479 resetQ.executeQueue(true); 3480 3481 // Anything on queue now is associated with a device not on the bus, I think... 3482 IOFWCommand *cmd; 3483 while( (cmd = resetQ.fHead) ) 3484 { 3485 cmd->cancel(kIOReturnTimeout); 3486 } 3487 3488 FWKLOG(( "IOFireWireController::finishedBusScan exited\n" )); 3489 FWTrace_End( kFWTController, kTPControllerFinishedBusScan, (uintptr_t)fFWIM, 0, 0, 0 ); 3490} 3491 3492// countNodeIDChildren 3493// 3494// 3495 3496UInt32 IOFireWireController::countNodeIDChildren( UInt16 nodeID, int hub_port, int * hubChildRemainder, bool * hubParentFlag ) 3497{ 3498 UInt32 id0, idn; 3499 UInt32 *idPtr; 3500 int i; 3501 int children = 0; 3502 int ports; 3503 UInt32 port; 3504 int mask, shift; 3505 3506 if( hub_port > 2 ) 3507 { 3508 // we currently only look at self id type 0 since we don't currently ship >3 port phys 3509 IOLog( "IOFireWireController::countNodeIDChildren - hub_port = %d out of range.\n", hub_port ); 3510 } 3511 3512 // get type 0 self id 3513 i = nodeID & 63; 3514 idPtr = fNodeIDs[i]; 3515 id0 = OSSwapBigToHostInt32(*idPtr++); 3516 mask = kFWSelfID0P0; 3517 shift = kFWSelfID0P0Phase; 3518 3519 // count children 3520 // 3 ports in type 0 self id 3521 for(ports=0; ports<3; ports++) 3522 { 3523 port = (id0 & mask) >> shift; 3524 if(port == kFWSelfIDPortStatusChild) 3525 { 3526 children++; 3527 } 3528 3529 if( ports == hub_port ) 3530 { 3531 if( port == kFWSelfIDPortStatusChild ) 3532 { 3533 // when the topology builder gets down to the current child count 3534 // then we are at our hub 3535 if( hubChildRemainder != NULL ) 3536 *hubChildRemainder = children; 3537 } 3538 else if( port == kFWSelfIDPortStatusParent ) 3539 { 3540 // the hub us our parent 3541 if( hubParentFlag != NULL ) 3542 *hubParentFlag = true; 3543 } 3544 } 3545 3546 mask >>= 2; 3547 shift -= 2; 3548 } 3549 3550 // any more self ids for this node? 3551 if(fNodeIDs[i+1] > idPtr) 3552 { 3553 // get type 1 self id 3554 idn = OSSwapBigToHostInt32(*idPtr++); 3555 mask = kFWSelfIDNPa; 3556 shift = kFWSelfIDNPaPhase; 3557 3558 // count children 3559 // 8 ports in type 1 self id 3560 for(ports=0; ports<8; ports++) 3561 { 3562 port = (idn & mask) >> shift; 3563 if(port == kFWSelfIDPortStatusChild) 3564 children++; 3565 mask >>= 2; 3566 shift -= 2; 3567 } 3568 3569 // any more self ids for this node? 3570 if(fNodeIDs[i+1] > idPtr) 3571 { 3572 // get type 2 self id 3573 idn = OSSwapBigToHostInt32(*idPtr++); 3574 mask = kFWSelfIDNPa; 3575 shift = kFWSelfIDNPaPhase; 3576 3577 // count children 3578 // 5 ports in type 2 self id 3579 for(ports=0; ports<5; ports++) 3580 { 3581 port = (idn & mask) >> shift; 3582 if(port == kFWSelfIDPortStatusChild) 3583 children++; 3584 mask >>= 2; 3585 shift -= 2; 3586 } 3587 } 3588 } 3589 3590 return children; 3591} 3592 3593// getPortNumberFromIndex 3594// 3595// 3596 3597UInt32 IOFireWireController::getPortNumberFromIndex( UInt16 index ) 3598{ 3599 UInt32 id0, idn; 3600 UInt32 *idPtr; 3601 int i; 3602 int children = 0; 3603 int ports; 3604 UInt32 port; 3605 int mask, shift; 3606 3607 // get type 0 self id 3608 i = fLocalNodeID & 63; 3609 idPtr = fNodeIDs[i]; 3610 id0 = OSSwapBigToHostInt32(*idPtr++); 3611 mask = kFWSelfID0P0; 3612 shift = kFWSelfID0P0Phase; 3613 3614 // count children 3615 // 3 ports in type 0 self id 3616 for(ports=0; ports<3; ports++) 3617 { 3618 port = (id0 & mask) >> shift; 3619 if(port == kFWSelfIDPortStatusChild) 3620 { 3621 if( index == children ) 3622 return ports; 3623 children++; 3624 } 3625 mask >>= 2; 3626 shift -= 2; 3627 } 3628 3629 // any more self ids for this node? 3630 if(fNodeIDs[i+1] > idPtr) 3631 { 3632 // get type 1 self id 3633 idn = OSSwapBigToHostInt32(*idPtr++); 3634 mask = kFWSelfIDNPa; 3635 shift = kFWSelfIDNPaPhase; 3636 3637 // count children 3638 // 8 ports in type 1 self id 3639 for(ports=0; ports<8; ports++) 3640 { 3641 if(port == kFWSelfIDPortStatusChild) 3642 { 3643 //zzz shouldn't ports be returned + 3? 3644 if( index == children ) 3645 return ports; 3646 children++; 3647 } 3648 mask >>= 2; 3649 shift -= 2; 3650 } 3651 } 3652 3653 return 0xFFFFFFFF; 3654} 3655 3656// buildTopology 3657// 3658// 3659 3660void IOFireWireController::buildTopology(bool doFWPlane) 3661{ 3662 FWTrace_Start( kFWTController, kTPControllerBuildTopology, (uintptr_t)fFWIM, (uintptr_t)doFWPlane, 0, 0 ); 3663 3664 int i, maxDepth; 3665 IORegistryEntry *root; 3666 struct FWNodeScan 3667 { 3668 int nodeID; 3669 int childrenRemaining; 3670 int hubChildRemainder; 3671 bool hubParentFlag; 3672 IORegistryEntry *node; 3673 }; 3674 FWNodeScan scanList[kFWMaxNodesPerBus]; 3675 FWNodeScan *level; 3676 maxDepth = 0; 3677 root = fNodes[fRootNodeID]; 3678 level = scanList; 3679 3680 // First build the topology. 3681 3682 // iterate over all self ids starting with root id 3683 for(i=fRootNodeID; i>=0; i--) 3684 { 3685 UInt32 id0; 3686 UInt8 speedCode; 3687 IORegistryEntry *node = fNodes[i]; 3688 int children = 0; 3689 3690 // count the children for this self id 3691 if( (i == (fLocalNodeID & 63)) && (fHubPort != kFWInvalidPort) ) 3692 { 3693 // we use hubChildRemainder here to find the port connected to the builtin hub. 3694 // eg. if childrenRemaining is 3 and the hub is the 3rd child, hubChildRemainder will be 1. 3695 // obvious, no? it's weird like this because at this point in the project I don't want 3696 // to disturb the underlying enumeration algorithm which uses childrenRemaining for iteration. 3697 3698 bool hubParent = false; 3699 int hubChildRemainder = 0; 3700 3701 children = countNodeIDChildren( i, fHubPort, &hubChildRemainder, &hubParent ); 3702 3703// IOLog( "FireWire - buildtopology - node = %d, children = %d, hubPort = %d, hubChildRem = %d, hubParent = %d\n", i, children, fHubPort, hubChildRemainder, hubParent ); 3704 3705 // Add node to bottom of tree 3706 level->nodeID = i; 3707 level->childrenRemaining = children; 3708 level->hubChildRemainder = hubChildRemainder; 3709 level->hubParentFlag = hubParent; 3710 level->node = node; 3711 } 3712 else 3713 { 3714 children = countNodeIDChildren( i ); 3715 3716 // Add node to bottom of tree 3717 level->nodeID = i; 3718 level->childrenRemaining = children; 3719 level->hubChildRemainder = 0; 3720 level->hubParentFlag = false; 3721 level->node = node; 3722 } 3723 3724 // Add node's self speed to speedmap 3725 id0 = OSSwapBigToHostInt32(*fNodeIDs[i]); 3726 speedCode = (id0 & kFWSelfID0SP) >> kFWSelfID0SPPhase; 3727 3728 if( !doFWPlane ) 3729 { 3730 if( speedCode == kFWSpeedReserved ) 3731 speedCode = kFWSpeed800MBit | kFWSpeedUnknownMask; // Remember that we don't know how fast it is 3732 } 3733 3734 if( fDSLimited && !(speedCode & kFWSpeedUnknownMask) ) 3735 { 3736 speedCode = kFWSpeed100MBit; 3737 } 3738 3739 setNodeSpeed(i, i, speedCode); 3740 3741 // Add to parent 3742 // Compute rest of this node's speed map entries unless it's the root. 3743 // We only need to compute speeds between this node and all higher node numbers. 3744 // These speeds will be the minimum of this node's speed and the speed between 3745 // this node's parent and the other higher numbered nodes. 3746 if (i != fRootNodeID) 3747 { 3748 int parentNodeNum, scanNodeNum; 3749 parentNodeNum = (level-1)->nodeID; 3750 if(doFWPlane) 3751 { 3752 FWNodeScan * parent_level = (level-1); 3753 3754 if( parent_level->hubChildRemainder == parent_level->childrenRemaining ) 3755 { 3756 if( parent_level->childrenRemaining == 0 ) 3757 { 3758 // this should be impossible 3759 IOLog( "IOFireWireController::buildTopology - parent child count is 0!\n" ); 3760 } 3761 else 3762 { 3763 // we are the hub 3764 node->setProperty( "Built-in Hub", true ); 3765 } 3766 } 3767 else if( level->hubParentFlag ) 3768 { 3769 // our parent is the hub 3770 parent_level->node->setProperty( "Built-in Hub", true ); 3771 } 3772 3773 if( (node != NULL) && (parent_level->node != NULL) ) 3774 { 3775 node->attachToParent( parent_level->node, gIOFireWirePlane ); 3776 } 3777 3778 } 3779 else 3780 { 3781 for (scanNodeNum = i + 1; scanNodeNum <= fRootNodeID; scanNodeNum++) 3782 { 3783 // Get speed code between parent and scan node. 3784 IOFWSpeed fwspeed = FWSpeed(parentNodeNum, scanNodeNum); 3785 if ( fwspeed > 0xFF ) 3786 ErrorLog("Found oversized speed map entry during speed checking\n"); 3787 3788 UInt8 scanSpeedCode = (UInt8)fwspeed; 3789 3790 UInt8 calcSpeedCode = scanSpeedCode; 3791 // Set speed map entry to minimum of scan speed and node's speed. 3792 if ( (speedCode & ~kFWSpeedUnknownMask) < (scanSpeedCode & ~kFWSpeedUnknownMask) ) 3793 { 3794 calcSpeedCode = speedCode; 3795 } 3796 3797 if( (speedCode & kFWSpeedUnknownMask) || (scanSpeedCode & kFWSpeedUnknownMask) ) 3798 { 3799 calcSpeedCode |= kFWSpeedUnknownMask; 3800 } 3801 3802 setNodeSpeed(i, scanNodeNum, calcSpeedCode); 3803 } 3804 } 3805 } 3806 3807 // Find next child port. 3808 if (i > 0) 3809 { 3810 while (level->childrenRemaining == 0) 3811 { 3812 // Go up one level in tree. 3813 level--; 3814 if(level < scanList) 3815 { 3816 IOLog("SelfIDs don't build a proper tree (missing selfIDS?)!!\n"); 3817 return; 3818 } 3819 // One less child to scan. 3820 level->childrenRemaining--; 3821 } 3822 // Go down one level in tree. 3823 level++; 3824 if(level - scanList > maxDepth) 3825 { 3826 maxDepth = level - scanList; 3827 } 3828 } 3829 } 3830 3831 // Clear out the unknown speed mask for the local node. Not needed once we get here. 3832 // Other nodes with this flag will get cleared once we've decided to speed scan them. 3833 // We never speed scan the local node which means we'll never clear it otherwise. 3834 setNodeSpeed(fLocalNodeID, fLocalNodeID, (FWSpeed(fLocalNodeID, fLocalNodeID) & ~kFWSpeedUnknownMask)); 3835 3836#if (DEBUGGING_LEVEL > 0) 3837 IOLog("MaxDepth:%d LocalNodeID:%x\n", maxDepth, fLocalNodeID); 3838 IOLog("FireWire Speed map:\n"); 3839 for(i=0; i <= fRootNodeID; i++) { 3840 int j; 3841 for(j=0; j <= fRootNodeID; j++) { 3842 IOLog("%-2x ", (unsigned int)FWSpeed(i, j) ); 3843 } 3844 IOLog("\n"); 3845 } 3846#endif 3847#if 0 3848 if( doFWPlane ) 3849 { 3850 IOLog( "FireWire Hop Counts:\n" ); 3851 for( i=0; i <= fRootNodeID; i++ ) 3852 { 3853 int j; 3854 for( j=0; j <= fRootNodeID; j++ ) 3855 { 3856 if ( j < i ) 3857 IOLog("_ "); 3858 else 3859 IOLog("%-2lu ", hopCount(i,j)); 3860 } 3861 IOLog( "\n" ); 3862 } 3863 } 3864#endif 3865 3866 // Finally attach the full topology into the IOKit registry 3867 if(doFWPlane && (root != NULL)) 3868 root->attachToParent(IORegistryEntry::getRegistryRoot(), gIOFireWirePlane); 3869 3870 FWTrace_End( kFWTController, kTPControllerBuildTopology, (uintptr_t)fFWIM, (uintptr_t)doFWPlane, 0, 0 ); 3871} 3872 3873// updatePlane 3874// 3875// 3876 3877void IOFireWireController::updatePlane() 3878{ 3879 FWTrace( kFWTController, kTPControllerUpdatePlane, (uintptr_t)fFWIM, 0, 0, 0 ); 3880 3881 OSIterator *childIterator; 3882 bool foundTDM = false; 3883 3884 fDevicePruneDelay = kNormalDevicePruneDelay; 3885 3886 childIterator = getClientIterator(); 3887 if( childIterator ) 3888 { 3889 OSObject *child; 3890 while( (child = childIterator->getNextObject())) 3891 { 3892 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 3893 3894 // don't need to sync with open/close routines when checking for kNotTerminated 3895 if( found && (found->getTerminationState() == kNotTerminated) ) 3896 { 3897 if( found->fNodeID == kFWBadNodeID ) 3898 { 3899 FWTrace( kFWTController, kTPControllerUpdatePlane, (uintptr_t)fFWIM, (uintptr_t)found, 1, 0 ); 3900 terminateDevice( found ); 3901 } 3902 else 3903 { 3904 OSString * tdm_string = OSDynamicCast( OSString, found->getProperty( gFireWireTDM ) ); 3905 3906 if( (tdm_string != NULL) && 3907 (strncmp( "PPC", tdm_string->getCStringNoCopy(), 4 ) == 0) ) 3908 { 3909 foundTDM = true; 3910 } 3911 } 3912 } 3913 } 3914 childIterator->release(); 3915 } 3916 3917 OSObject * existProp = fFWIM->getProperty( "FWDSLimit" ); 3918 3919 if( existProp && !foundTDM ) 3920 { 3921 fFWIM->setLinkMode( kIOFWSetDSLimit, 0 ); 3922 3923 // Make sure medicine takes effect 3924 FWTrace(kFWTResetBusAction, kTPResetUpdatePlane, (uintptr_t)fFWIM, 0, 0, 0 ); 3925 resetBus(); 3926 } 3927 3928 buildTopology(true); 3929 3930 messageClients( kIOFWMessageTopologyChanged ); 3931 3932 // reset generation property to current FireWire Generation 3933 char busGenerationStr[32]; 3934 snprintf(busGenerationStr, sizeof(busGenerationStr), "%x", (uint32_t)fBusGeneration); 3935 setProperty( kFireWireGenerationID, busGenerationStr); 3936 FWKLOG(("IOFireWireController::updatePlane reset generation to '%s'\n", busGenerationStr)); 3937 3938 fUseHalfSizePackets = fRequestedHalfSizePackets; 3939} 3940 3941// terminateDevice 3942// 3943// 3944 3945void IOFireWireController::terminateDevice( IOFireWireDevice * device ) 3946{ 3947 if( device->isOpen() ) 3948 { 3949 //IOLog( "IOFireWireController : message request close device object %p\n", found); 3950 // send our custom requesting close message 3951 device->lockForArbitration(); 3952 device->setTerminationState( kNeedsTermination ); 3953 device->unlockForArbitration(); 3954 messageClient( kIOFWMessageServiceIsRequestingClose, device ); 3955 } 3956 else 3957 { 3958 device->lockForArbitration(); 3959 device->setTerminationState( kTerminated ); 3960 device->unlockForArbitration(); 3961 IOFireWireDevice::terminateDevice( device ); 3962 } 3963} 3964 3965#pragma mark - 3966///////////////////////////////////////////////////////////////////////////// 3967// physical access 3968// 3969 3970// setPhysicalAccessMode 3971// 3972// 3973 3974void IOFireWireController::setPhysicalAccessMode( IOFWPhysicalAccessMode mode ) 3975{ 3976 closeGate(); 3977 3978 // 3979 // enable physical access in normal security mode 3980 // 3981 3982 if( mode == kIOFWPhysicalAccessEnabled && 3983 getSecurityMode() == kIOFWSecurityModeNormal ) 3984 { 3985 fPhysicalAccessMode = kIOFWPhysicalAccessEnabled; 3986 3987 FWKLOG(( "IOFireWireController::setPhysicalAccessMode - enable physical access\n" )); 3988 3989 // 3990 // disabling physical accesses will have cleared all previous filter state 3991 // 3992 // when physical access is enabled we mimic the filter configuration process 3993 // after a bus reset. we let each node enable its physical filter if desired 3994 // 3995 3996 OSIterator * iterator = getClientIterator(); 3997 OSObject * child = NULL; 3998 while( (child = iterator->getNextObject()) ) 3999 { 4000 IOFireWireDevice * found = OSDynamicCast(IOFireWireDevice, child); 4001 4002 // don't need to sync with open/close routines when checking for kNotTerminated 4003 if( found && (found->getTerminationState() == kNotTerminated) ) 4004 { 4005 // if we found an active device, ask it to reconfigure it's 4006 // physical filter settings 4007 found->configurePhysicalFilter(); 4008 } 4009 } 4010 4011 iterator->release(); 4012 } 4013 4014 // 4015 // disable physical access 4016 // 4017 4018 if( mode == kIOFWPhysicalAccessDisabled ) 4019 { 4020 fPhysicalAccessMode = kIOFWPhysicalAccessDisabled; 4021 4022 FWKLOG(( "IOFireWireController::setPhysicalAccessMode - disable physical access\n" )); 4023 4024 // shut them all down! 4025 fFWIM->setNodeIDPhysicalFilter( kIOFWAllPhysicalFilters, false ); 4026 } 4027 4028 // 4029 // disable physical access for this bus generation if physical access 4030 // is not already permanently disabled 4031 // 4032 4033 if( mode == kIOFWPhysicalAccessDisabledForGeneration && 4034 fPhysicalAccessMode != kIOFWPhysicalAccessDisabled ) 4035 { 4036 fPhysicalAccessMode = kIOFWPhysicalAccessDisabledForGeneration; 4037 4038 FWKLOG(( "IOFireWireController::setPhysicalAccessMode - disable physical access for this bus generation\n" )); 4039 4040 // shut them all down! 4041 fFWIM->setNodeIDPhysicalFilter( kIOFWAllPhysicalFilters, false ); 4042 } 4043 4044 openGate(); 4045} 4046 4047// getPhysicalAccessMode 4048// 4049// 4050 4051IOFWPhysicalAccessMode IOFireWireController::getPhysicalAccessMode( void ) 4052{ 4053 return fPhysicalAccessMode; 4054} 4055 4056// physicalAccessProcessBusReset 4057// 4058// 4059 4060void IOFireWireController::physicalAccessProcessBusReset( void ) 4061{ 4062 // 4063 // reenable physical access if it was only disabled for a generation 4064 // and we're in normal security mode 4065 // 4066 4067 if( fPhysicalAccessMode == kIOFWPhysicalAccessDisabledForGeneration && 4068 getSecurityMode() == kIOFWSecurityModeNormal ) 4069 { 4070 fPhysicalAccessMode = kIOFWPhysicalAccessEnabled; 4071 4072 FWKLOG(( "IOFireWireController::physicalAccessProcessBusReset - re-enable physical access because of bus reset\n" )); 4073 4074 // we don't reconfigure the physical filters here because : 4075 // 1. a bus reset has just occured and all node ids are set to kFWBadNodeID 4076 // 2. reconfiguring filters is done automatically after receiving self-ids 4077 } 4078} 4079 4080// setNodeIDPhysicalFilter 4081// 4082// 4083 4084void IOFireWireController::setNodeIDPhysicalFilter( UInt16 nodeID, bool state ) 4085{ 4086 // only configure node filters if the family is allowing physical access 4087 if( fPhysicalAccessMode == kIOFWPhysicalAccessEnabled ) 4088 { 4089 FWKLOG(( "IOFireWireController::setNodeIDPhysicalFilter - set physical access for node 0x%x to %d\n", nodeID, state )); 4090 4091 fFWIM->setNodeIDPhysicalFilter( nodeID, state ); 4092 } 4093} 4094 4095// isPhysicalAccessEnabledForNodeID 4096// 4097// 4098 4099bool IOFireWireController::isPhysicalAccessEnabledForNodeID( UInt16 nodeID ) 4100{ 4101 return fFWIM->isPhysicalAccessEnabledForNodeID( nodeID ); 4102} 4103 4104#pragma mark - 4105///////////////////////////////////////////////////////////////////////////// 4106// security 4107// 4108 4109// findKeyswitchDevice 4110// 4111// 4112 4113IOService *IOFireWireController::findKeyswitchDevice( void ) 4114{ 4115 IORegistryIterator * iter; 4116 IORegistryEntry * entry = 0; 4117 4118 iter = IORegistryIterator::iterateOver( gIODTPlane, 4119 kIORegistryIterateRecursively ); 4120 4121 if ( iter ) 4122 { 4123 while (( entry = iter->getNextObject() )) 4124 { 4125 if (( strncmp( entry->getName(), "keySwitch-gpio", 16 ) == 0 ) or 4126 ( strncmp( entry->getName(), "keySwitch", 11 ) == 0 ) or 4127 ( strncmp( entry->getName(), "KYLK", 5 ) == 0 ) ) 4128 break; 4129 } 4130 iter->release(); 4131 } 4132 4133 return OSDynamicCast( IOService, entry ); 4134} 4135 4136// initSecurity 4137// 4138// 4139void IOFireWireController::initSecurity( void ) 4140{ 4141 #ifdef kIOConsoleSecurityInterest 4142 { 4143 const OSSymbol * console_security_interest = OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest ); 4144 fConsoleLockNotifier = IOService::getServiceRoot()->registerInterest( console_security_interest, &IOFireWireController::consoleLockInterestHandler, this, NULL ); 4145 if( fConsoleLockNotifier == NULL ) 4146 { 4147 fConsoleLockNotifier->enable(true); 4148 } 4149 } 4150 #endif 4151 4152 bool waitForKeyswitch = false; 4153 4154 if( findKeyswitchDevice() ) 4155 waitForKeyswitch = true; 4156 4157 // 4158 // assume security mode is normal 4159 // 4160 4161 IOFWSecurityMode mode = kIOFWSecurityModeNormal; 4162 4163 #ifdef kIOConsoleSecurityInterest 4164 { 4165 IORegistryEntry * root = IORegistryEntry::getRegistryRoot(); 4166 OSObject * console_lock_property = NULL; 4167 if( root ) 4168 { 4169 console_lock_property = root->getProperty( kIOConsoleLockedKey ); 4170 } 4171 4172 OSBoolean * console_locked = NULL; 4173 if( console_lock_property ) 4174 { 4175 console_locked = OSDynamicCast( OSBoolean, console_lock_property ); 4176 } 4177 4178 if( console_locked && console_locked->isTrue() ) 4179 { 4180 mode = kIOFWSecurityModeSecure; 4181 } 4182 } 4183 #endif 4184 4185 // 4186 // check OpenFirmware security mode 4187 // 4188 4189 { 4190 char matchPath[32]; // IODeviceTree:/:options 4191 OSDictionary * optionsMatchDictionary = IOOFPathMatching( "/options", matchPath, 32 ); // need to release 4192 4193 mach_timespec_t t = { 10, 0 }; //wait 10 secs 4194 IOService * options = IOService::waitForService( optionsMatchDictionary, &t ); // consumes dict ref, don't release options 4195 4196 if( options != NULL ) 4197 { 4198 OSString * securityModeProperty = OSDynamicCast( OSString, options->getProperty("security-mode") ); 4199 4200 if( securityModeProperty != NULL && strncmp( "none", securityModeProperty->getCStringNoCopy(), 5 ) != 0 ) 4201 { 4202 // set security mode to secure/permanent 4203 mode = kIOFWSecurityModeSecurePermanent; 4204 } 4205 } 4206 else 4207 { 4208 ErrorLog("FireWire unable to determine security-mode; defaulting to full-secure.\n"); 4209 // turn security on because we can't determine security-mode 4210 mode = kIOFWSecurityModeSecurePermanent; 4211 } 4212 } 4213 4214 // 4215 // handle security keyswitch 4216 // 4217 4218 if( mode != kIOFWSecurityModeSecurePermanent ) 4219 { 4220 4221 // 4222 // check state of secruity keyswitch 4223 // 4224 UInt8 retryCount = 5; 4225 4226 do 4227 { 4228 OSIterator * iterator = NULL; 4229 OSBoolean * keyswitchState = NULL; 4230 4231 iterator = getMatchingServices( nameMatching("AppleKeyswitch") ); 4232 if( iterator != NULL ) 4233 { 4234 OSObject * obj = NULL; 4235 waitForKeyswitch = false; 4236 4237 if( (obj = iterator->getNextObject()) ) 4238 { 4239 IOService * service = (IOService*)obj; 4240 keyswitchState = OSDynamicCast( OSBoolean, service->getProperty( "Keyswitch" ) ); 4241 4242 if( keyswitchState->isTrue() ) 4243 { 4244 // set security mode to secure 4245 mode = kIOFWSecurityModeSecure; 4246 } 4247 } 4248 4249 iterator->release(); 4250 iterator = NULL; 4251 } 4252 4253 if( retryCount == 0 ) 4254 waitForKeyswitch = false; 4255 4256 retryCount--; 4257 4258 if( waitForKeyswitch ) 4259 { 4260 IOLog("Waiting for AppleKeyswitch ...\n"); 4261 IOSleep(1000); 4262 } 4263 4264 }while( waitForKeyswitch ); 4265 4266 // 4267 // add notification for changes to secruity keyswitch 4268 // 4269 4270 4271 fKeyswitchNotifier = addMatchingNotification( gIOMatchedNotification, nameMatching( "AppleKeyswitch" ), 4272 (IOServiceMatchingNotificationHandler)&IOFireWireController::serverKeyswitchCallback, 4273 this, 0 ); 4274 4275 } 4276 4277 // 4278 // now that we've determined our security mode, set it 4279 // 4280 4281 setSecurityMode( mode ); 4282 4283} 4284 4285// freeSecurity 4286// 4287// 4288 4289void IOFireWireController::freeSecurity( void ) 4290{ 4291 // remove notification 4292 4293 if( fConsoleLockNotifier ) 4294 { 4295 fConsoleLockNotifier->remove(); 4296 fConsoleLockNotifier = NULL; 4297 } 4298 4299 if( fKeyswitchNotifier != NULL ) 4300 { 4301 fKeyswitchNotifier->remove(); 4302 fKeyswitchNotifier = NULL; 4303 } 4304} 4305 4306IOReturn IOFireWireController::consoleLockInterestHandler( void * target, void * refCon, 4307 UInt32 messageType, IOService * provider, 4308 void * messageArgument, vm_size_t argSize ) 4309{ 4310 IOFireWireController * me = OSDynamicCast( IOFireWireController, (OSObject *)target ); 4311 4312 if ( me != NULL ) 4313 { 4314 if( me->getSecurityMode() != kIOFWSecurityModeSecurePermanent ) 4315 { 4316 IORegistryEntry * root = IORegistryEntry::getRegistryRoot(); 4317 OSObject * console_lock_property = NULL; 4318 if( root ) 4319 { 4320 console_lock_property = root->getProperty( kIOConsoleLockedKey ); 4321 } 4322 4323 OSBoolean * console_locked = NULL; 4324 if( console_lock_property ) 4325 { 4326 console_locked = OSDynamicCast( OSBoolean, console_lock_property ); 4327 } 4328 4329 if( console_locked && console_locked->isTrue() ) 4330 { 4331 // Key is locked, set security mode to secure 4332 // IOLog( "IOFireWireController::consoleLockInterestHandler lock: value true\n" ); 4333 me->setSecurityMode( kIOFWSecurityModeSecure ); 4334 } 4335 else 4336 { 4337 // Key is unlocked, set security mode to normal 4338 // IOLog( "IOFireWireController::consoleLockInterestHandler lock: value false\n" ); 4339 me->setSecurityMode( kIOFWSecurityModeNormal ); 4340 } 4341 } 4342 } 4343 4344 return kIOReturnSuccess; 4345} 4346 4347// serverKeyswitchCallback 4348// 4349// 4350 4351bool IOFireWireController::serverKeyswitchCallback( void * target, void * refCon, IOService * service, IONotifier * notifier ) 4352{ 4353 OSBoolean * keyswitchState = NULL; 4354 IOFireWireController * me = NULL; 4355 4356 if( me != NULL ) 4357 { 4358 me = OSDynamicCast( IOFireWireController, (OSObject *)target ); 4359 4360 if ( me->getSecurityMode() != kIOFWSecurityModeSecurePermanent ) 4361 { 4362 keyswitchState = OSDynamicCast( OSBoolean, service->getProperty( "Keyswitch" ) ); 4363 if( keyswitchState != NULL ) 4364 { 4365 // Is the key unlocked? 4366 4367 if( keyswitchState->isFalse() ) 4368 { 4369 // Key is unlocked, set security mode to normal 4370 4371 me->setSecurityMode( kIOFWSecurityModeNormal ); 4372 } 4373 else if( keyswitchState->isTrue() ) 4374 { 4375 // Key is locked, set security mode to secure 4376 4377 me->setSecurityMode( kIOFWSecurityModeSecure ); 4378 } 4379 } 4380 } 4381 } 4382 4383 return true; 4384} 4385 4386// setSecurityMode 4387// 4388// 4389 4390void IOFireWireController::setSecurityMode( IOFWSecurityMode mode ) 4391{ 4392 closeGate(); 4393 4394 fSecurityMode = mode; 4395 4396 switch( fSecurityMode ) 4397 { 4398 case kIOFWSecurityModeNormal: 4399 4400 FWKLOG(( "IOFireWireController::setSecurityMode - set mode to normal\n" )); 4401 4402 // enable physical access 4403 fFWIM->setSecurityMode( mode ); 4404 setPhysicalAccessMode( kIOFWPhysicalAccessEnabled ); 4405 break; 4406 4407 case kIOFWSecurityModeSecure: 4408 case kIOFWSecurityModeSecurePermanent: 4409 4410 FWKLOG(( "IOFireWireController::setSecurityMode - set mode to secure\n" )); 4411 4412 // disable physical access 4413 fFWIM->setSecurityMode( mode ); 4414 setPhysicalAccessMode( kIOFWPhysicalAccessDisabled ); 4415 break; 4416 4417 default: 4418 IOLog( "IOFireWireController::setSecurityMode - illegal security mode = 0x%x\n", fSecurityMode ); 4419 break; 4420 } 4421 4422 openGate(); 4423} 4424 4425// getSecurityMode 4426// 4427// 4428 4429IOFWSecurityMode IOFireWireController::getSecurityMode( void ) 4430{ 4431 return fSecurityMode; 4432} 4433 4434#pragma mark - 4435 4436///////////////////////////////////////////////////////////////////////////// 4437// local config rom 4438// 4439 4440// getRootDir 4441// 4442// 4443 4444IOLocalConfigDirectory * IOFireWireController::getRootDir() const 4445{ 4446 return fRootDir; 4447} 4448 4449// AddUnitDirectory 4450// 4451// 4452 4453IOReturn IOFireWireController::AddUnitDirectory(IOLocalConfigDirectory *unitDir) 4454{ 4455 IOReturn res; 4456 4457 closeGate(); 4458 4459 if ( isInactive() ) 4460 { 4461 openGate() ; 4462 return kIOReturnOffline ; 4463 } 4464 4465 getRootDir()->addEntry(kConfigUnitDirectoryKey, unitDir); 4466 4467 res = UpdateROM(); 4468 if(res == kIOReturnSuccess) 4469 { 4470 FWTrace(kFWTResetBusAction, kTPResetAddUnitDirectory, (uintptr_t)fFWIM, 0, 0, 0 ); 4471 res = resetBus(); 4472 } 4473 openGate(); 4474 4475 return res; 4476} 4477 4478// RemoveUnitDirectory 4479// 4480// 4481 4482IOReturn IOFireWireController::RemoveUnitDirectory(IOLocalConfigDirectory *unitDir) 4483{ 4484 IOReturn res; 4485 4486 closeGate(); 4487 4488 getRootDir()->removeSubDir(unitDir); 4489 4490 res = UpdateROM(); 4491 if(res == kIOReturnSuccess) 4492 { 4493 FWTrace(kFWTResetBusAction, kTPResetRemoveUnitDirectory, (uintptr_t)fFWIM, 0, 0, 0 ); 4494 res = resetBus(); 4495 } 4496 4497 openGate(); 4498 4499 return res; 4500} 4501 4502// UpdateROM() 4503// 4504// Instantiate the local Config ROM. 4505// Always causes at least one bus reset. 4506 4507IOReturn IOFireWireController::UpdateROM() 4508{ 4509 UInt32 * hack; 4510 UInt32 crc; 4511 unsigned int numQuads; 4512 OSData * rom; 4513 IOReturn ret; 4514 UInt32 generation; 4515 IOFireWireLocalNode * localNode; 4516 4517 // Increment the 4 bit generation field, make sure it is at least two. 4518 UInt32 bib_quad = OSSwapBigToHostInt32( fROMHeader[2] ); 4519 generation = bib_quad & kFWBIBGeneration; 4520 generation += (1 << kFWBIBGenerationPhase); 4521 generation &= kFWBIBGeneration; 4522 if(generation < (2 << kFWBIBGenerationPhase)) 4523 generation = (2 << kFWBIBGenerationPhase); 4524 4525 fROMHeader[2] = OSSwapHostToBigInt32((bib_quad & ~kFWBIBGeneration) | generation); 4526 4527 rom = OSData::withBytes(&fROMHeader, sizeof(fROMHeader)); 4528 fRootDir->incrementGeneration(); 4529 fRootDir->compile(rom); 4530 4531 // Now hack in correct CRC and length. 4532 hack = (UInt32 *)rom->getBytesNoCopy(); 4533 UInt32 bibQuads = sizeof(fROMHeader)/sizeof(UInt32) - 1; 4534 crc = FWComputeCRC16 (hack + 1, bibQuads); 4535 *hack = OSSwapHostToBigInt32( 4536 (((sizeof(fROMHeader)/sizeof(UInt32)-1) << kConfigBusInfoBlockLengthPhase) & kConfigBusInfoBlockLength) | 4537 ((bibQuads << kConfigROMCRCLengthPhase) & kConfigROMCRCLength) | 4538 ((crc << kConfigROMCRCValuePhase) & kConfigROMCRCValue) ); 4539 4540 localNode = getLocalNode(this); 4541 if(localNode) 4542 localNode->setProperty(gFireWireROM, rom); 4543 4544 numQuads = rom->getLength()/sizeof(UInt32) - 1; 4545 4546#if 0 4547 { 4548 unsigned int i; 4549 IOLog("--------- FW Local ROM: --------\n"); 4550 for(i=0; i<numQuads+1; i++) 4551 IOLog("ROM[%d] = 0x%x\n", i, OSSwapBigToHostInt32(hack[i])); 4552 } 4553#endif 4554 4555 if(fROMAddrSpace) 4556 { 4557 freeAddress( fROMAddrSpace ); 4558 fROMAddrSpace->release(); 4559 fROMAddrSpace = NULL; 4560 } 4561 4562 fROMAddrSpace = IOFWPseudoAddressSpace::simpleReadFixed( this, 4563 FWAddress(kCSRRegisterSpaceBaseAddressHi, kConfigROMBaseAddress), 4564 (numQuads+1)*sizeof(UInt32), rom->getBytesNoCopy()); 4565 ret = allocAddress(fROMAddrSpace); 4566 if(kIOReturnSuccess == ret) 4567 { 4568 ret = fFWIM->updateROM(rom); 4569 } 4570 rom->release(); 4571 return ret ; 4572} 4573 4574#pragma mark - 4575///////////////////////////////////////////////////////////////////////////// 4576// async request transmit 4577// 4578 4579// allocTrans 4580// 4581// 4582 4583AsyncPendingTrans *IOFireWireController::allocTrans(IOFWAsyncCommand *cmd) 4584{ 4585 return allocTrans( cmd, NULL ); 4586} 4587 4588// allocTrans 4589// 4590// 4591 4592AsyncPendingTrans *IOFireWireController::allocTrans( IOFWAsyncCommand * cmd, IOFWCommand * altcmd ) 4593{ 4594 unsigned int i; 4595 unsigned int tran; 4596 4597 tran = fLastTrans; 4598 for(i=0; i<kMaxPendingTransfers; i++) { 4599 AsyncPendingTrans *t; 4600 tran++; 4601 if(tran >= kMaxPendingTransfers) 4602 tran = 0; 4603 t = &fTrans[tran]; 4604 if(!t->fInUse) { 4605 t->fHandler = cmd; 4606 t->fAltHandler = altcmd; 4607 t->fInUse = true; 4608 t->fTCode = tran; 4609 fLastTrans = tran; 4610 return t; 4611 } 4612 } 4613 4614 // Print only if its a first time 4615 if ( fOutOfTLabels == 0 && fOutOfTLabelsThreshold == 0 ) 4616 IOLog("IOFireWireController:: Out of Transaction Labels\n"); 4617 4618 // Out of TLabels counter (Information Only) 4619 fOutOfTLabels++; 4620 4621 return NULL; 4622} 4623 4624// freeTrans 4625// 4626// 4627 4628void IOFireWireController::freeTrans(AsyncPendingTrans *trans) 4629{ 4630 // No lock needed - can't have two users of a tcode. 4631 trans->fHandler = NULL; 4632 trans->fAltHandler = NULL; 4633 trans->fInUse = false; 4634} 4635 4636// asyncRead 4637// 4638// 4639 4640IOReturn IOFireWireController::asyncRead( UInt32 generation, 4641 UInt16 nodeID, 4642 UInt16 addrHi, 4643 UInt32 addrLo, 4644 int speed, 4645 int label, 4646 int size, 4647 IOFWAsyncCommand * cmd) 4648{ 4649 return asyncRead( generation, 4650 nodeID, 4651 addrHi, 4652 addrLo, 4653 speed, 4654 label, 4655 size, 4656 cmd, 4657 kIOFWReadFlagsNone ); 4658} 4659 4660// asyncRead 4661// 4662// 4663 4664// Route packet sending to FWIM if checks out OK 4665IOReturn IOFireWireController::asyncRead( UInt32 generation, 4666 UInt16 nodeID, 4667 UInt16 addrHi, 4668 UInt32 addrLo, 4669 int speed, 4670 int label, 4671 int size, 4672 IOFWAsyncCommand * cmd, 4673 IOFWReadFlags flags ) 4674{ 4675 FWTrace_Start(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo ); 4676 4677 if( !checkGeneration(generation) ) 4678 { 4679 FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 ); 4680 return kIOFireWireBusReset; 4681 } 4682 4683 // Check if local node 4684 4685 if( nodeID == fLocalNodeID ) 4686 { 4687 UInt32 rcode; 4688 IOMemoryDescriptor *buf; 4689 IOByteCount offset; 4690 IOFWSpeed temp = (IOFWSpeed)speed; 4691 4692 rcode = doReadSpace( nodeID, 4693 temp, 4694 FWAddress(addrHi, addrLo), 4695 size, 4696 &buf, 4697 &offset, 4698 NULL, 4699 (IOFWRequestRefCon)label ); 4700 4701 if(rcode == kFWResponseComplete) 4702 { 4703 void * bytes = IOMalloc( size ); 4704 4705 buf->readBytes( offset, bytes, size ); 4706 4707 cmd->gotPacket( rcode, bytes, size ); 4708 4709 IOFree( bytes, size ); 4710 } 4711 else 4712 { 4713 cmd->gotPacket( rcode, NULL, 0 ); 4714 } 4715 4716 FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 ); 4717 return kIOReturnSuccess; 4718 } 4719 else 4720 { 4721 // reliabilty is more important than speed for IRM access 4722 // perform IRM access at s100 4723 4724 int actual_speed = speed; 4725 if( addrHi == kCSRRegisterSpaceBaseAddressHi ) 4726 { 4727 if( (addrLo == kCSRBandwidthAvailable) || 4728 (addrLo == kCSRChannelsAvailable31_0) || 4729 (addrLo == kCSRChannelsAvailable63_32) || 4730 (addrLo == kCSRBusManagerID) ) 4731 { 4732 actual_speed = kFWSpeed100MBit; 4733 } 4734 } 4735 4736 IOReturn status = fFWIM->asyncRead( nodeID, addrHi, addrLo, actual_speed, label, size, cmd, flags ); 4737 4738 FWTrace_End(kFWTController, kTPControllerAsyncRead, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 ); 4739 return status; 4740 } 4741} 4742 4743// asyncWrite 4744// 4745// DEPRECATED 4746 4747IOReturn IOFireWireController::asyncWrite( UInt32 generation, 4748 UInt16 nodeID, 4749 UInt16 addrHi, 4750 UInt32 addrLo, 4751 int speed, 4752 int label, 4753 void * data, 4754 int size, 4755 IOFWAsyncCommand * cmd) 4756{ 4757 IOLog( "IOFireWireController::asyncWrite : DEPRECATED API\n" ); 4758 return kIOReturnUnsupported; 4759} 4760 4761// asyncWrite 4762// 4763// 4764 4765IOReturn IOFireWireController::asyncWrite( UInt32 generation, 4766 UInt16 nodeID, 4767 UInt16 addrHi, 4768 UInt32 addrLo, 4769 int speed, 4770 int label, 4771 IOMemoryDescriptor * buf, 4772 IOByteCount offset, 4773 int size, 4774 IOFWAsyncCommand * cmd ) 4775{ 4776 return asyncWrite( generation, 4777 nodeID, 4778 addrHi, 4779 addrLo, 4780 speed, 4781 label, 4782 buf, 4783 offset, 4784 size, 4785 cmd, 4786 kIOFWWriteFlagsNone ); 4787} 4788 4789// asyncWrite 4790// 4791// 4792 4793IOReturn IOFireWireController::asyncWrite( UInt32 generation, 4794 UInt16 nodeID, 4795 UInt16 addrHi, 4796 UInt32 addrLo, 4797 int speed, 4798 int label, 4799 IOMemoryDescriptor * buf, 4800 IOByteCount offset, 4801 int size, 4802 IOFWAsyncCommand * cmd, 4803 IOFWWriteFlags flags ) 4804{ 4805 FWTrace_Start(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo ); 4806 4807// IOLog( "IOFireWireController::asyncWrite\n" ); 4808 4809 if( !checkGeneration(generation) ) 4810 { 4811 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 ); 4812 return kIOFireWireBusReset; 4813 } 4814 4815 // Check if local node 4816 if( nodeID == fLocalNodeID ) 4817 { 4818 UInt32 rcode; 4819 IOFWSpeed temp = (IOFWSpeed)speed; 4820 4821 void * bytes = IOMalloc( size ); 4822 4823 buf->readBytes( offset, bytes, size ); 4824 4825 rcode = doWriteSpace( nodeID, 4826 temp, 4827 FWAddress( addrHi, addrLo ), 4828 size, 4829 bytes, 4830 (IOFWRequestRefCon)label ); 4831 4832 IOFree( bytes, size ); 4833 4834 cmd->gotPacket(rcode, NULL, 0); 4835 4836 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 ); 4837 return kIOReturnSuccess; 4838 } 4839 else 4840 { 4841 // reliabilty is more important than speed for IRM access 4842 // perform IRM access at s100 4843 4844 // actually writes to the IRM are not allowed, so we are doing 4845 // this more for consistency than necessity 4846 4847 int actual_speed = speed; 4848 if( addrHi == kCSRRegisterSpaceBaseAddressHi ) 4849 { 4850 if( (addrLo == kCSRBandwidthAvailable) || 4851 (addrLo == kCSRChannelsAvailable31_0) || 4852 (addrLo == kCSRChannelsAvailable63_32) || 4853 (addrLo == kCSRBusManagerID) ) 4854 { 4855 actual_speed = kFWSpeed100MBit; 4856 } 4857 } 4858 4859 IOReturn status = fFWIM->asyncWrite( nodeID, 4860 addrHi, 4861 addrLo, 4862 actual_speed, 4863 label, 4864 buf, 4865 offset, 4866 size, 4867 cmd, 4868 flags ); 4869 4870 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 ); 4871 return status; 4872 } 4873} 4874 4875// asyncPHYPacket 4876// 4877// 4878 4879IOReturn IOFireWireController::asyncPHYPacket( UInt32 generation, UInt32 data, UInt32 data2, IOFWAsyncPHYCommand * cmd ) 4880{ 4881 IOReturn status = kIOReturnSuccess; 4882 4883 if( !checkGeneration(generation) ) 4884 { 4885 status = kIOFireWireBusReset; 4886 } 4887 4888 if( status == kIOReturnSuccess ) 4889 { 4890 if( !(data & 0x40000000) ) 4891 { 4892 // not VersaPHY 4893 status = kIOReturnBadArgument; 4894 } 4895 } 4896 4897 if( status == kIOReturnSuccess ) 4898 { 4899 status = fFWIM->asyncPHYPacket( data, data2, cmd ); 4900 } 4901 4902 return status; 4903} 4904 4905// asyncLock 4906// 4907// DEPRECATED 4908 4909IOReturn IOFireWireController::asyncLock( UInt32 generation, 4910 UInt16 nodeID, 4911 UInt16 addrHi, 4912 UInt32 addrLo, 4913 int speed, 4914 int label, 4915 int type, 4916 void * data, 4917 int size, 4918 IOFWAsyncCommand * cmd ) 4919{ 4920 IOLog( "IOFireWireController::asyncLock : DEPRECATED API\n" ); 4921 return kIOReturnUnsupported; 4922} 4923 4924// asyncLock 4925// 4926// 4927 4928IOReturn IOFireWireController::asyncLock( UInt32 generation, 4929 UInt16 nodeID, 4930 UInt16 addrHi, 4931 UInt32 addrLo, 4932 int speed, 4933 int label, 4934 int type, 4935 IOMemoryDescriptor * buf, 4936 IOByteCount offset, 4937 int size, 4938 IOFWAsyncCommand * cmd ) 4939 4940{ 4941 FWTrace_Start(kFWTController, kTPControllerAsyncLock, (uintptr_t)fFWIM, (uintptr_t)cmd, (uintptr_t)((nodeID << 16) | addrHi), addrLo ); 4942 4943 if( !checkGeneration(generation) ) 4944 { 4945 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOFireWireBusReset, 1 ); 4946 return kIOFireWireBusReset; 4947 } 4948 4949 // Check if local node 4950 if( nodeID == fLocalNodeID ) 4951 { 4952 UInt32 rcode; 4953 UInt32 retVals[2]; 4954 UInt32 retSize = size / 2; 4955 4956 IOFWSpeed temp = (IOFWSpeed)speed; 4957 IOFWRequestRefCon refcon = (IOFWRequestRefCon)(label | kRequestIsLock | (type << kRequestExtTCodeShift)); 4958 4959 void * bytes = IOMalloc( size ); 4960 4961 buf->readBytes( offset, bytes, size ); 4962 4963 rcode = doLockSpace( nodeID, 4964 temp, 4965 FWAddress(addrHi, addrLo), 4966 size, 4967 (const UInt32*)bytes, 4968 retSize, 4969 retVals, 4970 type, 4971 refcon ); 4972 4973 IOFree( bytes, size ); 4974 4975 cmd->gotPacket( rcode, retVals, retSize ); 4976 4977 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, kIOReturnSuccess, 2 ); 4978 return kIOReturnSuccess; 4979 } 4980 else 4981 { 4982 // reliabilty is more important than speed for IRM access 4983 // perform IRM access at s100 4984 4985 int actual_speed = speed; 4986 if( addrHi == kCSRRegisterSpaceBaseAddressHi ) 4987 { 4988 if( (addrLo == kCSRBandwidthAvailable) || 4989 (addrLo == kCSRChannelsAvailable31_0) || 4990 (addrLo == kCSRChannelsAvailable63_32) || 4991 (addrLo == kCSRBusManagerID) ) 4992 { 4993 actual_speed = kFWSpeed100MBit; 4994 } 4995 } 4996 4997 IOReturn status = fFWIM->asyncLock( nodeID, 4998 addrHi, 4999 addrLo, 5000 actual_speed, 5001 label, 5002 type, 5003 buf, 5004 offset, 5005 size, 5006 cmd ); 5007 5008 FWTrace_End(kFWTController, kTPControllerAsyncWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, status, 3 ); 5009 return status; 5010 } 5011} 5012 5013// handleAsyncTimeout 5014// 5015// 5016 5017IOReturn IOFireWireController::handleAsyncTimeout(IOFWAsyncCommand *cmd) 5018{ 5019 return fFWIM->handleAsyncTimeout(cmd); 5020} 5021 5022 5023// handleAsyncCompletion 5024// 5025// 5026 5027IOReturn IOFireWireController::handleAsyncCompletion( IOFWCommand *cmd, IOReturn status ) 5028{ 5029 return fFWIM->handleAsyncCompletion( cmd, status ); 5030} 5031 5032// asyncStreamWrite 5033// 5034// 5035 5036IOReturn IOFireWireController::asyncStreamWrite(UInt32 generation, 5037 int speed, int tag, int sync, int channel, 5038 IOMemoryDescriptor *buf, IOByteCount offset, 5039 int size, IOFWAsyncStreamCommand *cmd) 5040{ 5041 FWTrace_Start(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, 0); 5042 5043 if(!checkGeneration(generation)) 5044 { 5045 FWTrace_End(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, kIOFireWireBusReset); 5046 return (kIOFireWireBusReset); 5047 } 5048 5049 IOReturn status = fFWIM->asyncStreamTransmit((UInt32)channel, speed, (UInt32) sync, (UInt32) tag, buf, offset, size, cmd); 5050 5051 FWTrace_End(kFWTController, kTPControllerAsyncStreamWrite, (uintptr_t)fFWIM, (uintptr_t)cmd, channel, status); 5052 return status; 5053} 5054 5055// createAsyncStreamCommand 5056// 5057// 5058 5059IOFWAsyncStreamCommand * IOFireWireController::createAsyncStreamCommand( UInt32 generation, 5060 UInt32 channel, UInt32 sync, UInt32 tag, IOMemoryDescriptor *hostMem, 5061 UInt32 size, int speed, FWAsyncStreamCallback completion, void *refcon) 5062{ 5063 return createAsyncStreamCommand(generation, channel, sync, tag, hostMem, size, speed, completion, refcon, true); 5064} 5065 5066IOFWAsyncStreamCommand * IOFireWireController::createAsyncStreamCommand( UInt32 generation, 5067 UInt32 channel, UInt32 sync, UInt32 tag, IOMemoryDescriptor *hostMem, 5068 UInt32 size, int speed,FWAsyncStreamCallback completion, void *refcon, bool failOnReset) 5069{ 5070 IOFWAsyncStreamCommand * cmd; 5071 5072 cmd = OSTypeAlloc( IOFWAsyncStreamCommand ); 5073 if(cmd) { 5074 if(!cmd->initAll(this, generation, channel, sync, tag, hostMem,size,speed, completion, refcon, failOnReset)) { 5075 cmd->release(); 5076 cmd = NULL; 5077 } 5078 } 5079 return cmd; 5080} 5081 5082// createAsyncPHYCommand 5083// 5084// 5085 5086IOFWAsyncPHYCommand * IOFireWireController::createAsyncPHYCommand( UInt32 generation, 5087 UInt32 data1, 5088 UInt32 data2, 5089 FWAsyncPHYCallback completion, 5090 void * refcon, 5091 bool failOnReset ) 5092 5093{ 5094 IOFWAsyncPHYCommand * cmd; 5095 5096 cmd = OSTypeAlloc( IOFWAsyncPHYCommand ); 5097 if( cmd ) 5098 { 5099 if( !cmd->initAll( this, generation, data1, data2, completion, refcon, failOnReset ) ) 5100 { 5101 cmd->release(); 5102 cmd = NULL; 5103 } 5104 } 5105 5106 return cmd; 5107} 5108 5109///////////////////////////////////////////////////////////////////////////// 5110// async receive 5111// 5112 5113// processRcvPacket 5114// 5115// dispatch received Async packet based on tCode. 5116 5117void IOFireWireController::processRcvPacket(UInt32 *data, int size, IOFWSpeed speed ) 5118{ 5119#if 0 5120 int i; 5121kprintf("Received packet 0x%x size %d\n", data, size); 5122 for(i=0; i<size; i++) { 5123 kprintf("0x%x ", OSSwapBigToHostInt32(data[i])); 5124 } 5125 kprintf("\n"); 5126#endif 5127 UInt32 tCode, tLabel; 5128 UInt32 quad0; 5129 UInt16 sourceID; 5130 UInt16 destID; 5131 5132 // Get first quad. 5133 quad0 = *data; 5134 5135 tCode = (quad0 & kFWPacketTCode) >> kFWPacketTCodePhase; 5136 tLabel = (quad0 & kFWAsynchTLabel) >> kFWAsynchTLabelPhase; 5137 sourceID = (data[1] & kFWAsynchSourceID) >> kFWAsynchSourceIDPhase; 5138 destID = (data[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase; 5139 5140 FWTrace(kFWTController, kTPControllerProcessRcvPacket, (uintptr_t)fFWIM, sourceID, tCode, 0); 5141 5142 // Dispatch processing based on tCode. 5143 switch (tCode) 5144 { 5145 case kFWTCodeWriteQuadlet : 5146#if (DEBUGGING_LEVEL > 0) 5147 DEBUGLOG("WriteQuadlet: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID, 5148 (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); 5149#endif 5150 processWriteRequest(sourceID, tLabel, data, &data[3], 4, speed); 5151 break; 5152 5153 case kFWTCodePHYPacket: 5154#if (DEBUGGING_LEVEL > 0) 5155 DEBUGLOG( "PHY Packet: 0x%08lx %08lx\n", data[1], data[2] ); 5156#endif 5157 processPHYPacket( data[1], data[2] ); 5158 break; 5159 5160 case kFWTCodeWriteBlock : 5161#if (DEBUGGING_LEVEL > 0) 5162 DEBUGLOG("WriteBlock: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID, 5163 (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); 5164#endif 5165 processWriteRequest(sourceID, tLabel, data, &data[4], 5166 (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase, speed); 5167 break; 5168 5169 case kFWTCodeWriteResponse : 5170 if(fTrans[tLabel].fHandler) { 5171 IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; 5172 FWAddress commandAddress = cmd->getAddress(); 5173 5174 if( sourceID == commandAddress.nodeID ){ 5175 cmd->setResponseSpeed( speed ); 5176 5177 FWTrace(kFWTController, kTPControllerProcessRcvPacketWR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo); 5178 cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, 0, 0); 5179 } 5180 else{ 5181#if (DEBUGGING_LEVEL > 0) 5182 DEBUGLOG( "Response from wrong node ID!\n" ); 5183#endif 5184 } 5185 } 5186 else { 5187#if (DEBUGGING_LEVEL > 0) 5188 DEBUGLOG("WriteResponse: label %d isn't in use!!, data1 = 0x%x\n", 5189 tLabel, data[1]); 5190#endif 5191 } 5192 break; 5193 5194 case kFWTCodeReadQuadlet : 5195#if (DEBUGGING_LEVEL > 0) 5196 DEBUGLOG("ReadQuadlet: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID, 5197 (data[1] & kFWAsynchDestinationOffsetHigh) >> 5198 kFWAsynchDestinationOffsetHighPhase, data[2]); 5199#endif 5200 { 5201 UInt32 ret; 5202 FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); 5203 IOMemoryDescriptor *buf = NULL; 5204 IOByteCount offset; 5205 5206 ret = doReadSpace(sourceID, speed, addr, 4, 5207 &buf, &offset, NULL, (IOFWRequestRefCon)(tLabel | kRequestIsQuad)); 5208 5209 FWTrace(kFWTController, kTPControllerProcessRcvPacketRQ, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) | addr.addressHi), addr.addressLo); 5210 5211 if(ret == kFWResponsePending) 5212 break; 5213 5214 if( NULL != buf ) 5215 { 5216 UInt32 quad = OSSwapHostToBigInt32(0xdeadbeef); 5217 5218 buf->readBytes( offset, &quad, 4 ); 5219 5220 if ( destID != 0xffff ) // we should not respond to broadcast reads 5221 fFWIM->asyncReadQuadResponse(sourceID, speed, tLabel, ret, quad ); 5222 else 5223 DebugLog("Skipped asyncReadQuadResponse because destID=0x%x\n", destID); 5224 } 5225 else 5226 { 5227 if ( destID != 0xffff ) // we should not respond to broadcast reads 5228 fFWIM->asyncReadQuadResponse(sourceID, speed, tLabel, ret, OSSwapHostToBigInt32(0xdeadbeef)); 5229 else 5230 DebugLog("Skipped asyncReadQuadResponse because destID=0x%x\n", destID); 5231 } 5232 } 5233 break; 5234 5235 case kFWTCodeReadBlock : 5236#if (DEBUGGING_LEVEL > 0) 5237 DEBUGLOG("ReadBlock: addr 0x%x -> 0x%x:0x%x:0x%x\n", sourceID, destID, 5238 (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2], 5239 (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase); 5240#endif 5241 { 5242 IOReturn ret; 5243 int length = (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase ; 5244 FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); 5245 IOMemoryDescriptor * buf = NULL; 5246 IODMACommand * dma_command = NULL; 5247 IOByteCount offset; 5248 5249 ret = doReadSpace(sourceID, speed, addr, length, &buf, &offset, &dma_command, (IOFWRequestRefCon)(tLabel)); 5250 5251 FWTrace(kFWTController, kTPControllerProcessRcvPacketRB, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) | addr.addressHi), addr.addressLo); 5252 5253 if(ret == kFWResponsePending) 5254 break; 5255 5256 if(NULL != buf) { 5257 if ( destID != 0xffff ) // we should not respond to broadcast reads 5258 fFWIM->asyncReadResponse(sourceID, speed, tLabel, ret, buf, offset, length, dma_command ); 5259 else 5260 DebugLog("Skipped asyncReadResponse because destID=0x%x\n", destID); 5261 } 5262 else { 5263 if ( destID != 0xffff ) // we should not respond to broadcast reads 5264 fFWIM->asyncReadResponse(sourceID, speed, tLabel, ret, fBadReadResponse, 0, 4, NULL); 5265 else 5266 DebugLog("Skipped asyncReadResponse because destID=0x%x\n", destID); 5267 } 5268 } 5269 break; 5270 5271 case kFWTCodeReadQuadletResponse : 5272 if(fTrans[tLabel].fHandler) { 5273 IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; 5274 FWAddress commandAddress = cmd->getAddress(); 5275 5276 if( sourceID == commandAddress.nodeID ) 5277 { 5278 cmd->setResponseSpeed( speed ); 5279 5280 FWTrace(kFWTController, kTPControllerProcessRcvPacketRQR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo); 5281 5282 cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, 5283 (const void*)(data+3), 4); 5284 } 5285 else 5286 { 5287#if (DEBUGGING_LEVEL > 0) 5288 DEBUGLOG( "Response from wrong node ID!\n" ); 5289#endif 5290 } 5291 5292 } 5293 else { 5294#if (DEBUGGING_LEVEL > 0) 5295 DEBUGLOG("ReadQuadletResponse: label %d isn't in use!!\n", tLabel); 5296#endif 5297 } 5298 break; 5299 5300 case kFWTCodeReadBlockResponse : 5301 case kFWTCodeLockResponse : 5302 if(fTrans[tLabel].fHandler) { 5303 5304 IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; 5305 FWAddress commandAddress = cmd->getAddress(); 5306 5307 if( sourceID == commandAddress.nodeID ) 5308 { 5309 cmd->setResponseSpeed( speed ); 5310 5311 FWTrace(kFWTController, kTPControllerProcessRcvPacketRBR, (uintptr_t)fFWIM, (uintptr_t)cmd, ((commandAddress.nodeID << 16) | commandAddress.addressHi), commandAddress.addressLo); 5312 5313 cmd->gotPacket((data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, 5314 (const void*)(data+4), (data[3] & kFWAsynchDataLength)>>kFWAsynchDataLengthPhase); 5315 } 5316 else 5317 { 5318#if (DEBUGGING_LEVEL > 0) 5319 DEBUGLOG( "Response from wrong node ID!\n" ); 5320#endif 5321 } 5322 } 5323 else { 5324#if (DEBUGGING_LEVEL > 0) 5325 DEBUGLOG("ReadBlock/LockResponse: label %d isn't in use!!\n", tLabel); 5326#endif 5327 } 5328 break; 5329 5330 case kFWTCodeLock : 5331#if (DEBUGGING_LEVEL > 0) 5332 DEBUGLOG("Lock type %d: addr 0x%x -> 0x%x:0x%x:0x%x\n", 5333 (data[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase, sourceID, destID, 5334 (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, 5335 data[2]); 5336#endif 5337 processLockRequest(sourceID, tLabel, data, &data[4], 5338 (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase, speed); 5339 5340 break; 5341 5342 case kFWTCodeIsochronousBlock : 5343#if (DEBUGGING_LEVEL > 0) 5344 DEBUGLOG("Async Stream Packet\n"); 5345#endif 5346 break; 5347 5348 default : 5349#if (DEBUGGING_LEVEL > 0) 5350 DEBUGLOG("Unexpected tcode in Asyncrecv: %d\n", tCode); 5351#endif 5352 break; 5353 } 5354} 5355 5356///////////////////////////////////////////////////////////////////////////// 5357// async request receive 5358// 5359 5360// createPhysicalAddressSpace 5361// 5362// 5363 5364IOFWPhysicalAddressSpace * 5365IOFireWireController::createPhysicalAddressSpace(IOMemoryDescriptor *mem) 5366{ 5367 IOFWPhysicalAddressSpace *space; 5368 space = OSTypeAlloc( IOFWPhysicalAddressSpace ); 5369 if(!space) 5370 return NULL; 5371 if(!space->initWithDesc(this, mem)) { 5372 space->release(); 5373 space = NULL; 5374 } 5375 return space; 5376} 5377 5378// createAsyncStreamListener 5379// 5380// 5381 5382IOFWAsyncStreamListener * 5383IOFireWireController::createAsyncStreamListener( UInt32 channel, FWAsyncStreamReceiveCallback proc, void *refcon ) 5384{ 5385 IOFWAsyncStreamListener * listener = OSTypeAlloc( IOFWAsyncStreamListener ); 5386 5387 if( listener ) 5388 { 5389 if(not listener->initAll( this, channel, proc, refcon )) 5390 { 5391 listener->release(); 5392 listener = NULL; 5393 } 5394 } 5395 5396 return listener; 5397} 5398 5399void 5400IOFireWireController::removeAsyncStreamListener(IOFWAsyncStreamListener *listener) 5401{ 5402 IOFWAsyncStreamReceiver *receiver = listener->getReceiver(); 5403 5404 receiver->removeListener(listener); 5405} 5406 5407// createPseudoAddressSpace 5408// 5409// 5410 5411IOFWPseudoAddressSpace * 5412IOFireWireController::createPseudoAddressSpace(FWAddress *addr, UInt32 len, 5413 FWReadCallback reader, FWWriteCallback writer, void *refcon) 5414{ 5415 IOFWPseudoAddressSpace *space; 5416 space = OSTypeAlloc( IOFWPseudoAddressSpace ); 5417 if(!space) 5418 return NULL; 5419 if(!space->initAll(this, addr, len, reader, writer, refcon)) { 5420 space->release(); 5421 space = NULL; 5422 } 5423 return space; 5424} 5425 5426// createInitialAddressSpace 5427// 5428// 5429 5430IOFWPseudoAddressSpace * 5431IOFireWireController::createInitialAddressSpace(UInt32 addressLo, UInt32 len, 5432 FWReadCallback reader, FWWriteCallback writer, void *refcon) 5433{ 5434 IOFWPseudoAddressSpace *space; 5435 space = OSTypeAlloc( IOFWPseudoAddressSpace ); 5436 if(!space) 5437 return NULL; 5438 if(!space->initFixed(this, FWAddress(kCSRRegisterSpaceBaseAddressHi, addressLo), 5439 len, reader, writer, refcon)) { 5440 space->release(); 5441 space = NULL; 5442 } 5443 return space; 5444} 5445 5446// getAddressSpace 5447// 5448// 5449 5450IOFWAddressSpace * 5451IOFireWireController::getAddressSpace(FWAddress address) 5452{ 5453 closeGate(); 5454 5455 IOFWAddressSpace * found; 5456 fSpaceIterator->reset(); 5457 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { 5458 if(found->contains(address)) 5459 break; 5460 } 5461 5462 openGate(); 5463 5464 return found; 5465} 5466 5467 5468// allocAsyncStreamReceiver 5469// 5470// 5471IOFWAsyncStreamReceiver * 5472IOFireWireController::allocAsyncStreamReceiver(UInt32 channel, FWAsyncStreamReceiveCallback clientProc, void *refcon) 5473{ 5474 closeGate(); 5475 5476 IOFWAsyncStreamReceiver * receiver = OSTypeAlloc( IOFWAsyncStreamReceiver ); 5477 5478 if( receiver ) 5479 { 5480 if( receiver->initAll( this, channel ) ) 5481 { 5482 if( fLocalAsyncStreamReceivers->setObject( receiver )) 5483 receiver->release(); 5484 } 5485 else 5486 { 5487 receiver->release(); 5488 receiver = NULL; 5489 } 5490 } 5491 5492 openGate(); 5493 5494 return receiver; 5495} 5496 5497// getAsyncStreamReceiver 5498// 5499// 5500IOFWAsyncStreamReceiver * 5501IOFireWireController::getAsyncStreamReceiver( UInt32 channel ) 5502{ 5503 closeGate(); 5504 5505 IOFWAsyncStreamReceiver * found = NULL; 5506 OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers); 5507 if( iterator != NULL ) 5508 { 5509 found = NULL; 5510 while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) ) 5511 { 5512 if( found and found->listens(channel) ) 5513 break; 5514 } 5515 iterator->release(); 5516 } 5517 5518 openGate(); 5519 5520 return found; 5521} 5522 5523// removeAsyncStreamReceiver 5524// 5525// 5526void 5527IOFireWireController::removeAsyncStreamReceiver( IOFWAsyncStreamReceiver *receiver ) 5528{ 5529 closeGate(); 5530 5531 fLocalAsyncStreamReceivers->removeObject(receiver); 5532 5533 openGate(); 5534} 5535 5536// activateAsyncStreamReceivers 5537// 5538// 5539void 5540IOFireWireController::activateAsyncStreamReceivers( ) 5541{ 5542 closeGate(); 5543 5544 OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers); 5545 if( iterator != NULL ) 5546 { 5547 IOFWAsyncStreamReceiver * found = NULL; 5548 while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) ) 5549 { 5550 if( found ) 5551 found->activate( getBroadcastSpeed() ); 5552 } 5553 iterator->release(); 5554 } 5555 5556 openGate(); 5557} 5558 5559// deactivateAsyncStreamReceivers 5560// 5561// 5562void 5563IOFireWireController::deactivateAsyncStreamReceivers( ) 5564{ 5565 closeGate(); 5566 5567 OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers); 5568 if( iterator != NULL ) 5569 { 5570 IOFWAsyncStreamReceiver * found = NULL; 5571 while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) ) 5572 { 5573 if( found ) 5574 found->deactivate(); 5575 } 5576 iterator->release(); 5577 } 5578 5579 openGate(); 5580} 5581 5582// freeAllAsyncStreamReceiver 5583// 5584// 5585void 5586IOFireWireController::freeAllAsyncStreamReceiver() 5587{ 5588 closeGate(); 5589 5590 OSIterator *iterator = OSCollectionIterator::withCollection(fLocalAsyncStreamReceivers); 5591 if( iterator != NULL ) 5592 { 5593 IOFWAsyncStreamReceiver * found = NULL; 5594 while( (found = OSDynamicCast(IOFWAsyncStreamReceiver, iterator->getNextObject())) ) 5595 { 5596 if( found ) 5597 removeAsyncStreamReceiver( found ); 5598 } 5599 iterator->release(); 5600 } 5601 5602 openGate(); 5603} 5604 5605// allocAddress 5606// 5607// 5608 5609IOReturn IOFireWireController::allocAddress(IOFWAddressSpace *space) 5610{ 5611 /* 5612 * Lots of scope for optimizations here, perhaps building a hash table for 5613 * addresses etc. 5614 * Drivers may want to override this if their hardware can match addresses 5615 * without CPU intervention. 5616 */ 5617 IOReturn result = kIOReturnSuccess; 5618 5619 closeGate(); 5620 5621 // enforce exclusivity 5622 IOFWAddressSpace * found; 5623 fSpaceIterator->reset(); 5624 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) 5625 { 5626 // if either of the conflicting address spaces wants to be exclusive 5627 if( space->isExclusive() || found->isExclusive() ) 5628 { 5629 // check if they intersect 5630 if( found->intersects( space ) ) 5631 { 5632 // we have a problem 5633 result = kIOReturnExclusiveAccess; 5634 } 5635 } 5636 } 5637 5638 if( result == kIOReturnSuccess ) 5639 { 5640 if(!fLocalAddresses->setObject(space)) 5641 result = kIOReturnNoMemory; 5642 else 5643 result = kIOReturnSuccess; 5644 } 5645 5646 openGate(); 5647 5648 return result; 5649} 5650 5651// freeAddress 5652// 5653// 5654 5655void IOFireWireController::freeAddress(IOFWAddressSpace *space) 5656{ 5657 closeGate(); 5658 5659 fLocalAddresses->removeObject(space); 5660 5661 openGate(); 5662} 5663 5664// allocatePseudoAddress 5665// 5666// 5667 5668IOReturn IOFireWireController::allocatePseudoAddress(FWAddress *addr, UInt32 lenDummy) 5669{ 5670 unsigned int i, len; 5671 UInt8 * data; 5672 UInt8 used = 1; 5673 5674 closeGate(); 5675 5676 if( fAllocatedAddresses == NULL ) 5677 { 5678 fAllocatedAddresses = OSData::withCapacity(4); // SBP2 + some spare 5679 fAllocatedAddresses->appendBytes(&used, 1); // Physical always allocated 5680 } 5681 5682 if( !fAllocatedAddresses ) 5683 { 5684 openGate(); 5685 return kIOReturnNoMemory; 5686 } 5687 5688 len = fAllocatedAddresses->getLength(); 5689 data = (UInt8*)fAllocatedAddresses->getBytesNoCopy(); 5690 for( i=0; i<len; i++ ) 5691 { 5692 if( data[i] == 0 ) 5693 { 5694 data[i] = 1; 5695 addr->addressHi = i; 5696 addr->addressLo = 0; 5697 5698 openGate(); 5699 return kIOReturnSuccess; 5700 } 5701 } 5702 5703 if( len >= 0xfffe ) 5704 { 5705 openGate(); 5706 return kIOReturnNoMemory; 5707 } 5708 5709 if( fAllocatedAddresses->appendBytes(&used, 1)) 5710 { 5711 addr->addressHi = len; 5712 addr->addressLo = 0; 5713 5714 openGate(); 5715 return kIOReturnSuccess; 5716 } 5717 5718 openGate(); 5719 return kIOReturnNoMemory; 5720} 5721 5722// freePseudoAddress 5723// 5724// 5725 5726void IOFireWireController::freePseudoAddress(FWAddress addr, UInt32 lenDummy) 5727{ 5728 unsigned int len; 5729 UInt8 * data; 5730 5731 closeGate(); 5732 5733 assert( fAllocatedAddresses != NULL); 5734 5735 len = fAllocatedAddresses->getLength(); 5736 assert(addr.addressHi < len); 5737 data = (UInt8*)fAllocatedAddresses->getBytesNoCopy(); 5738 assert(data[addr.addressHi]); 5739 data[addr.addressHi] = 0; 5740 5741 openGate(); 5742} 5743 5744#if 0 5745IOReturn MyTestingFWMultiIsochReceiveListenerCallback(void *refcon, IOFireWireMultiIsochReceivePacket *pPacket) 5746{ 5747 DebugLog("AY_DEBUG: MyTestingFWMultiIsochReceiveListenerCallback\n"); 5748 5749 pPacket->clientDone(); 5750 5751 return kIOReturnSuccess; 5752} 5753#endif 5754 5755// processWriteRequest 5756// 5757// process quad and block writes. 5758 5759void IOFireWireController::processWriteRequest(UInt16 sourceID, UInt32 tLabel, 5760 UInt32 *hdr, void *buf, int len, IOFWSpeed speed) 5761{ 5762 UInt32 ret = kFWResponseAddressError; 5763 FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]); 5764 IOFWAddressSpace * found; 5765 5766#if 0 5767 // Special Andy Debug code to set/clear MultiIsochReceiver channels remotely via FireBug qwrite! 5768 if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A00) && (len == 4)) 5769 { 5770 UInt32 add_chan = OSSwapBigToHostInt32(*((UInt32*) buf)); 5771 DebugLog("Got quadlet-write to special MultiIsochReceiver channel-add address: add_chan=%d\n",add_chan); 5772 if (fFWIM) 5773 { 5774 IOReturn result; 5775 IOFireWireMultiIsochReceiveListener *pListener = createMultiIsochReceiveListener(add_chan,MyTestingFWMultiIsochReceiveListenerCallback,this); 5776 if (pListener) 5777 { 5778 result = pListener->Activate(); 5779 if (result != kIOReturnSuccess) 5780 DebugLog("AY_DEBUG: pListener->Activate failed!\n"); 5781 5782 } 5783 else 5784 { 5785 DebugLog("AY_DEBUG: createMultiIsochReceiveListener failed!\n"); 5786 } 5787 } 5788 } 5789 else if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A04) && (len == 4)) 5790 { 5791 //UInt32 remove_chan = OSSwapBigToHostInt32(*((UInt32*) buf)); 5792 //InfoLog("Got quadlet-write to special MultiIsochReceiver channel-remove address: remove_chan=%d\n",remove_chan); 5793 //if (fFWIM) 5794 // fFWIM->setLinkMode(kIOFWSetMultIsochReceiverChanRemove,remove_chan); 5795 } 5796 else if ((addr.addressHi == 0xFFFF) && (addr.addressLo == 0xF0000A08) && (len == 4)) 5797 { 5798 DebugLog("Got quadlet-write to special link-reset address\n"); 5799 if (fFWIM) 5800 fFWIM->setLinkMode(kIOFWSetForceLinkReset,0); 5801 } 5802#endif 5803 5804 fSpaceIterator->reset(); 5805 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { 5806 ret = found->doWrite(sourceID, speed, addr, len, buf, (IOFWRequestRefCon)tLabel); 5807 if(ret != kFWResponseAddressError) 5808 break; 5809 } 5810 5811 FWTrace(kFWTController, kTPControllerProcessWriteRequest, (uintptr_t)fFWIM, sourceID, ret, tLabel); 5812 5813 if ( ((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase) != 0xffff ) // we should not respond to broadcast writes 5814 fFWIM->asyncWriteResponse(sourceID, speed, tLabel, ret, addr.addressHi); 5815 else 5816 DebugLog("Skipped asyncWriteResponse because destID=0x%x\n", (uint32_t)((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase)); 5817} 5818 5819// processLockRequest 5820// 5821// process 32 and 64 bit locks. 5822 5823void IOFireWireController::processLockRequest(UInt16 sourceID, UInt32 tLabel, 5824 UInt32 *hdr, void *buf, int len, IOFWSpeed speed) 5825{ 5826 UInt32 oldVal[2]; 5827 UInt32 ret; 5828 UInt32 outLen =sizeof(oldVal); 5829 int type = (hdr[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase; 5830 5831 FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]); 5832 5833 IOFWRequestRefCon refcon = (IOFWRequestRefCon)(tLabel | kRequestIsLock | (type << kRequestExtTCodeShift)); 5834 5835 ret = doLockSpace(sourceID, speed, addr, len, (const UInt32 *)buf, outLen, oldVal, type, refcon); 5836 5837 FWTrace(kFWTController, kTPControllerProcessLockRequest, (uintptr_t)fFWIM, ret, ((addr.nodeID << 16) & addr.addressHi), addr.addressLo); 5838 5839 if(ret != kFWResponsePending) 5840 { 5841 if ( ((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase) != 0xffff ) // we should not respond to broadcast locks 5842 fFWIM->asyncLockResponse(sourceID, speed, tLabel, ret, type, oldVal, outLen); 5843 else 5844 DebugLog("Skipped asyncLockResponse because destID=0x%x\n", (uint32_t)((hdr[0] & kFWAsynchDestinationID) >> kFWAsynchDestinationIDPhase)); 5845 } 5846} 5847 5848// doReadSpace 5849// 5850// 5851 5852UInt32 IOFireWireController::doReadSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len, 5853 IOMemoryDescriptor **buf, IOByteCount * offset, IODMACommand **dma_command, 5854 IOFWRequestRefCon refcon) 5855{ 5856 IOFWAddressSpace * found; 5857 UInt32 ret = kFWResponseAddressError; 5858 fSpaceIterator->reset(); 5859 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { 5860 ret = found->doRead(nodeID, speed, addr, len, buf, offset, 5861 refcon); 5862 if(ret != kFWResponseAddressError) 5863 break; 5864 } 5865 5866 // hack to pass the IODMACommand for the phys address space to the FWIM 5867 5868 if( (dma_command != NULL) && (ret != kFWResponseAddressError) ) 5869 { 5870 IOFWPhysicalAddressSpace * phys_space = OSDynamicCast( IOFWPhysicalAddressSpace, found ); 5871 5872 if( phys_space ) 5873 { 5874 *dma_command = phys_space->getDMACommand(); 5875 } 5876 } 5877 5878 return ret; 5879} 5880 5881// doWriteSpace 5882// 5883// 5884 5885UInt32 IOFireWireController::doWriteSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len, 5886 const void *buf, IOFWRequestRefCon refcon) 5887{ 5888 IOFWAddressSpace * found; 5889 UInt32 ret = kFWResponseAddressError; 5890 fSpaceIterator->reset(); 5891 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { 5892 ret = found->doWrite(nodeID, speed, addr, len, buf, refcon); 5893 if(ret != kFWResponseAddressError) 5894 break; 5895 } 5896 return ret; 5897} 5898 5899// doLockSpace 5900// 5901// 5902 5903UInt32 IOFireWireController::doLockSpace(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 inLen, 5904 const UInt32 *newVal, UInt32 &outLen, UInt32 *oldVal, UInt32 type, 5905 IOFWRequestRefCon refcon) 5906{ 5907 IOFWAddressSpace * found; 5908 UInt32 ret = kFWResponseAddressError; 5909 fSpaceIterator->reset(); 5910 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { 5911 ret = found->doLock(nodeID, speed, addr, inLen, newVal, outLen, oldVal, type, refcon); 5912 if(ret != kFWResponseAddressError) 5913 break; 5914 } 5915 5916 if(ret != kFWResponseComplete) { 5917 oldVal[0] = OSSwapHostToBigInt32(0xdeadbabe); 5918 outLen = 4; 5919 } 5920 return ret; 5921} 5922 5923// handleARxReqIntComplete 5924// 5925// 5926 5927void IOFireWireController::handleARxReqIntComplete( void ) 5928{ 5929 IOFWAddressSpace * found; 5930 5931 fSpaceIterator->reset(); 5932 while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject()) ) 5933 { 5934 IOFWPseudoAddressSpace * space = OSDynamicCast( IOFWPseudoAddressSpace, found ); 5935 if( space != NULL ) 5936 { 5937 space->handleARxReqIntComplete(); 5938 } 5939 } 5940} 5941 5942// isLockRequest 5943// 5944// 5945 5946bool IOFireWireController::isLockRequest(IOFWRequestRefCon refcon) 5947{ 5948 return ((UInt64)refcon) & kRequestIsLock; 5949} 5950 5951// isQuadRequest 5952// 5953// 5954 5955bool IOFireWireController::isQuadRequest(IOFWRequestRefCon refcon) 5956{ 5957 return ((UInt64)refcon) & kRequestIsQuad; 5958} 5959 5960// isCompleteRequest 5961// 5962// 5963 5964bool IOFireWireController::isCompleteRequest(IOFWRequestRefCon refcon) 5965{ 5966 return ((UInt64)refcon) & kRequestIsComplete; 5967} 5968 5969// getExtendedTCode 5970// 5971// 5972 5973UInt32 IOFireWireController::getExtendedTCode(IOFWRequestRefCon refcon) 5974{ 5975 return((UInt64)refcon & kRequestExtTCodeMask) >> kRequestExtTCodeShift; 5976} 5977 5978///////////////////////////////////////////////////////////////////////////// 5979// async response transmit 5980// 5981 5982// asyncReadResponse 5983// 5984// Send async read response packets 5985// useful for pseudo address spaces that require servicing outside the FireWire work loop. 5986 5987IOReturn IOFireWireController::asyncReadResponse( UInt32 generation, 5988 UInt16 nodeID, 5989 int speed, 5990 IOMemoryDescriptor * buf, 5991 IOByteCount offset, 5992 int size, 5993 IOFWRequestRefCon refcon ) 5994{ 5995 IOReturn result; 5996 UInt64 params = (UInt64)refcon; 5997 UInt32 label = params & kRequestLabel; 5998 5999 closeGate(); 6000 6001 if( !checkGeneration(generation) ) 6002 { 6003 result = kIOFireWireBusReset; 6004 } 6005 else if( params & kRequestIsQuad ) 6006 { 6007 UInt32 quad = OSSwapHostToBigInt32(0xdeadbeef); 6008 6009 buf->readBytes( offset, &quad, 4 ); 6010 6011 result = fFWIM->asyncReadQuadResponse( nodeID, 6012 speed, 6013 label, 6014 kFWResponseComplete, 6015 quad ); 6016 } 6017 else 6018 { 6019 result = fFWIM->asyncReadResponse( nodeID, 6020 speed, 6021 label, 6022 kFWResponseComplete, 6023 buf, 6024 offset, 6025 size, 6026 NULL ); 6027 } 6028 6029 openGate(); 6030 6031 return result; 6032} 6033 6034// asyncLockResponse 6035// 6036// Send async lock response packets 6037// useful for pseudo address spaces that require servicing outside the FireWire work loop. 6038 6039IOReturn IOFireWireController::asyncLockResponse( UInt32 generation, 6040 UInt16 nodeID, 6041 int speed, 6042 IOMemoryDescriptor * buf, 6043 IOByteCount offset, 6044 int size, 6045 IOFWRequestRefCon refcon ) 6046{ 6047 FWTrace(kFWTController, kTPControllerAsyncLockResponse, (uintptr_t)fFWIM, nodeID, 0, 0); 6048 6049 IOReturn result; 6050 UInt64 params = (UInt64)refcon; 6051 UInt32 label = params & kRequestLabel; 6052 6053 closeGate(); 6054 6055 if( !checkGeneration(generation) ) 6056 { 6057 result = kIOFireWireBusReset; 6058 } 6059 else 6060 { 6061 void * bytes = IOMalloc( size ); 6062 6063 buf->readBytes( offset, bytes, size ); 6064 6065 result = fFWIM->asyncLockResponse( nodeID, 6066 speed, 6067 label, 6068 kFWResponseComplete, 6069 getExtendedTCode(refcon), 6070 bytes, 6071 size ); 6072 6073 IOFree( bytes, size ); 6074 6075 } 6076 6077 openGate(); 6078 6079 return result; 6080} 6081 6082///////////////////////////////////////////////////////////////////////////// 6083// timer command 6084// 6085 6086// createDelayedCmd 6087// 6088// 6089 6090IOFWDelayCommand * IOFireWireController::createDelayedCmd(UInt32 uSecDelay, FWBusCallback func, void *refcon) 6091{ 6092 IOFWDelayCommand *delay; 6093 //IOLog("Creating delay of %d\n", uSecDelay); 6094 delay = OSTypeAlloc( IOFWDelayCommand ); 6095 if(!delay) 6096 return NULL; 6097 6098 if(!delay->initWithDelay(this, uSecDelay, func, refcon)) 6099 { 6100 delay->release(); 6101 return NULL; 6102 } 6103 6104 return delay; 6105} 6106 6107#pragma mark - 6108///////////////////////////////////////////////////////////////////////////// 6109// isoch 6110// 6111 6112// createIsochChannel 6113// 6114// 6115 6116IOFWIsochChannel *IOFireWireController::createIsochChannel( bool doIRM, 6117 UInt32 bandwidth, 6118 IOFWSpeed prefSpeed, 6119 FWIsochChannelForceStopNotificationProc stopProc, 6120 void * stopRefCon ) 6121{ 6122 // NOTE: if changing this code, must also change IOFireWireUserClient::isochChannelAllocate() 6123 6124 IOFWIsochChannel *channel; 6125 6126 channel = OSTypeAlloc( IOFWIsochChannel ); 6127 if(!channel) 6128 { 6129 return NULL; 6130 } 6131 6132 if( !channel->init(this, doIRM, bandwidth, prefSpeed, stopProc, stopRefCon) ) 6133 { 6134 channel->release(); 6135 channel = NULL; 6136 } 6137 6138 return channel; 6139} 6140 6141// createLocalIsochPort 6142// 6143// 6144 6145IOFWLocalIsochPort *IOFireWireController::createLocalIsochPort( bool talking, 6146 DCLCommand * opcodes, 6147 DCLTaskInfo * info, 6148 UInt32 startEvent, 6149 UInt32 startState, 6150 UInt32 startMask ) 6151{ 6152 IOFWLocalIsochPort *port; 6153 IODCLProgram *program; 6154 6155 program = fFWIM->createDCLProgram( talking, opcodes, info, startEvent, startState, startMask ); 6156 if(!program) 6157 return NULL; 6158 6159 port = OSTypeAlloc( IOFWLocalIsochPort ); 6160 if( !port ) 6161 { 6162 program->release(); 6163 return NULL; 6164 } 6165 6166 if(!port->init(program, this)) 6167 { 6168 port->release(); 6169 port = NULL; 6170 } 6171 6172 return port; 6173} 6174 6175// addAllocatedChannel 6176// 6177// 6178 6179void IOFireWireController::addAllocatedChannel(IOFWIsochChannel *channel) 6180{ 6181 closeGate(); 6182 6183 fAllocatedChannels->setObject(channel); 6184 6185 openGate(); 6186} 6187 6188// removeAllocatedChannel 6189// 6190// 6191 6192void IOFireWireController::removeAllocatedChannel(IOFWIsochChannel *channel) 6193{ 6194 closeGate(); 6195 6196 fAllocatedChannels->removeObject(channel); 6197 6198 openGate(); 6199} 6200 6201 6202void IOFireWireController::addToIRMAllocationSet(IOFireWireIRMAllocation *anObject) 6203{ 6204 closeGate(); 6205 6206 fIRMAllocationsAllocated->setObject(anObject); 6207 6208 openGate(); 6209} 6210 6211void IOFireWireController::removeFromIRMAllocationSet(IOFireWireIRMAllocation *anObject) 6212{ 6213 closeGate(); 6214 6215 fIRMAllocationsAllocated->removeObject(anObject); 6216 6217 openGate(); 6218} 6219 6220// addIRMAllocation 6221// 6222// 6223 6224void IOFireWireController::addIRMAllocation(IOFireWireIRMAllocation *irmAllocation) 6225{ 6226 closeGate(); 6227 6228 if( fIRMAllocationsAllocated->containsObject(irmAllocation) ) 6229 { 6230 fIRMAllocations->setObject(irmAllocation); 6231 } 6232 6233 openGate(); 6234} 6235 6236// removeIRMAllocation 6237// 6238// 6239 6240void IOFireWireController::removeIRMAllocation(IOFireWireIRMAllocation *irmAllocation) 6241{ 6242 closeGate(); 6243 6244 fIRMAllocations->removeObject(irmAllocation); 6245 6246 openGate(); 6247} 6248 6249// allocateIRMBandwidthInGeneration 6250// 6251// 6252IOReturn IOFireWireController::allocateIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation) 6253{ 6254 IOReturn res; 6255 UInt32 irmGeneration; 6256 UInt16 irmNodeID; 6257 IOFWCompareAndSwapCommand * fLockCmd; 6258 FWAddress addr; 6259 UInt32 expectedOldVal, newVal; 6260 UInt32 actualOldVal; 6261 bool lockSuccessful; 6262 UInt32 retries = 2; 6263 6264 // Get the current IRM and Generation 6265 getIRMNodeID(irmGeneration, irmNodeID); 6266 6267 // Check the current generation 6268 if (irmGeneration != generation) 6269 return kIOFireWireBusReset; 6270 6271 // Initialize the address for the current IRM's bandwidth available register 6272 addr.nodeID = irmNodeID; 6273 addr.addressHi = 0xFFFF; 6274 addr.addressLo = 0xF0000220; 6275 6276 // Start with the default, no-bandwidth allocated value for the old val! 6277 expectedOldVal = OSSwapHostToBigInt32(0x00001333); 6278 6279 // Create a compare/swap command 6280 fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand ); 6281 if (!fLockCmd) 6282 return kIOReturnNoMemory; 6283 6284 // Pre-initialize the compare/swap command. Reinit will take place before use! 6285 if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL)) 6286 { 6287 fLockCmd->release(); 6288 return kIOReturnError; 6289 } 6290 6291 while (retries > 0) 6292 { 6293 // Make sure, in the request, we don't set the newVal to a negative number 6294 if (bandwidthUnits > OSSwapBigToHostInt32(expectedOldVal)) 6295 { 6296 res = kIOFireWireIsochBandwidthNotAvailable; 6297 break; 6298 } 6299 6300 // Calculate the new val for the compare/swap command 6301 newVal = OSSwapHostToBigInt32(OSSwapBigToHostInt32(expectedOldVal) - bandwidthUnits); 6302 6303 // Reinitialize the compare/swap command. If this fails, bail out of the retry loop! 6304 res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL); 6305 if (res != kIOReturnSuccess) 6306 break; 6307 6308 // Submit the compare/swap command. Will not return until complete 6309 res = fLockCmd->submit(); 6310 6311 // Check results, including actualOldVal 6312 if (res == kIOReturnSuccess) 6313 lockSuccessful = fLockCmd->locked(&actualOldVal); 6314 else 6315 lockSuccessful = false; 6316 6317 DebugLog("allocateIRMBandwidthInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n", 6318 res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal)); 6319 6320 // If we got a bus reset (i.e. wrong generation), no point on retrying 6321 if (res == kIOFireWireBusReset) 6322 break; 6323 6324 // If we succeeded, we don't need to retry 6325 else if (lockSuccessful) 6326 break; 6327 6328 else 6329 { 6330 // Decrement the retry count 6331 retries -= 1; 6332 6333 // If we don't have an error, but we're here, it's because 6334 // the compare-swap didn't succeed. Set an error code, in case we're 6335 // out of retries. 6336 if (res == kIOReturnSuccess) 6337 res = kIOFireWireIsochBandwidthNotAvailable; 6338 6339 // Change our expected old value for the retry. 6340 expectedOldVal = actualOldVal; 6341 } 6342 } 6343 6344 // Release the lock command 6345 fLockCmd->release(); 6346 6347 return res; 6348} 6349 6350// releaseIRMBandwidthInGeneration 6351// 6352// 6353IOReturn IOFireWireController::releaseIRMBandwidthInGeneration(UInt32 bandwidthUnits, UInt32 generation) 6354{ 6355 IOReturn res; 6356 UInt32 irmGeneration; 6357 UInt16 irmNodeID; 6358 IOFWCompareAndSwapCommand * fLockCmd; 6359 FWAddress addr; 6360 UInt32 expectedOldVal, newVal; 6361 UInt32 actualOldVal; 6362 bool lockSuccessful; 6363 UInt32 retries = 2; 6364 6365 // Get the current IRM and Generation 6366 getIRMNodeID(irmGeneration, irmNodeID); 6367 6368 // Check the current generation 6369 if (irmGeneration != generation) 6370 return kIOFireWireBusReset; 6371 6372 // Initialize the address for the current IRM's bandwidth available register 6373 addr.nodeID = irmNodeID; 6374 addr.addressHi = 0xFFFF; 6375 addr.addressLo = kCSRBandwidthAvailable; 6376 6377 // Start with the default, no-bandwidth available value for the old val! 6378 expectedOldVal = OSSwapHostToBigInt32(0); 6379 6380 // Create a compare/swap command 6381 fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand ); 6382 if (!fLockCmd) 6383 return kIOReturnNoMemory; 6384 6385 // Pre-initialize the compare/swap command. Reinit will take place before use! 6386 if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL)) 6387 { 6388 fLockCmd->release(); 6389 return kIOReturnError; 6390 } 6391 6392 while (retries > 0) 6393 { 6394 6395#if 0 6396 // Make sure, in the request, we don't set an illegally large value 6397 if ((bandwidthUnits + OSSwapBigToHostInt32(expectedOldVal)) > 0x00001333 ) 6398 { 6399 res = kIOReturnNoResources; 6400 break; 6401 } 6402#endif 6403 6404 // Calculate the new val for the compare/swap command 6405 newVal = OSSwapHostToBigInt32(OSSwapBigToHostInt32(expectedOldVal) + bandwidthUnits); 6406 6407 // Reinitialize the compare/swap command. If this fails, bail out of the retry loop! 6408 res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL); 6409 if (res != kIOReturnSuccess) 6410 break; 6411 6412 // Submit the compare/swap command. Will not return until complete 6413 res = fLockCmd->submit(); 6414 6415 // Check results, including actualOldVal 6416 if (res == kIOReturnSuccess) 6417 lockSuccessful = fLockCmd->locked(&actualOldVal); 6418 else 6419 lockSuccessful = false; 6420 6421 DebugLog("releaseIRMBandwidthInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n", 6422 res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal)); 6423 6424 // If we got a bus reset (i.e. wrong generation), no point on retrying 6425 if (res == kIOFireWireBusReset) 6426 break; 6427 6428 // If we succeeded, we don't need to retry 6429 else if (lockSuccessful) 6430 break; 6431 6432 else 6433 { 6434 // Decrement the retry count 6435 retries -= 1; 6436 6437 // If we don't have an error, but we're here, it's because 6438 // the compare-swap didn't succeed. Set an error code, in case we're 6439 // out of retries. 6440 if (res == kIOReturnSuccess) 6441 res = kIOReturnNoResources; 6442 6443 // Change our expected old value for the retry. 6444 expectedOldVal = actualOldVal; 6445 } 6446 } 6447 6448 // Release the lock command 6449 fLockCmd->release(); 6450 6451 return res; 6452} 6453 6454// allocateIRMChannelInGeneration 6455// 6456// 6457IOReturn IOFireWireController::allocateIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation) 6458{ 6459 IOReturn res; 6460 UInt32 irmGeneration; 6461 UInt16 irmNodeID; 6462 IOFWCompareAndSwapCommand * fLockCmd; 6463 FWAddress addr; 6464 UInt32 newValMask; 6465 UInt32 expectedOldVal, newVal; 6466 UInt32 actualOldVal; 6467 bool lockSuccessful; 6468 UInt32 retries = 2; 6469 6470 // Get the current IRM and Generation 6471 getIRMNodeID(irmGeneration, irmNodeID); 6472 6473 // Check the current generation 6474 if (irmGeneration != generation) 6475 return kIOFireWireBusReset; 6476 6477 // Initialize the address for the current IRM's bandwidth available register 6478 addr.nodeID = irmNodeID; 6479 addr.addressHi = 0xFFFF; 6480 6481 if( isochChannel < 32 ) 6482 { 6483 addr.addressLo = kCSRChannelsAvailable31_0; 6484 newValMask = OSSwapHostToBigInt32(~(1<<(31 - isochChannel))); 6485 } 6486 else if( isochChannel < 64 ) 6487 { 6488 addr.addressLo = kCSRChannelsAvailable63_32; 6489 newValMask = OSSwapHostToBigInt32(~(1 << (63 - isochChannel))); 6490 } 6491 else 6492 return kIOReturnBadArgument; 6493 6494 // Start with the default, no channels allocated value for the old val! 6495 expectedOldVal = OSSwapHostToBigInt32(0xFFFFFFFF); 6496 6497 // Create a compare/swap command 6498 fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand ); 6499 if (!fLockCmd) 6500 return kIOReturnNoMemory; 6501 6502 // Pre-initialize the compare/swap command. Reinit will take place before use! 6503 if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL)) 6504 { 6505 fLockCmd->release(); 6506 return kIOReturnError; 6507 } 6508 6509 while (retries > 0) 6510 { 6511 // Make sure the channel is not already allocated 6512 if ((expectedOldVal & ~newValMask) == 0) 6513 { 6514 res = kIOFireWireChannelNotAvailable; 6515 break; 6516 } 6517 6518 // Calculate the new val for the compare/swap command 6519 newVal = expectedOldVal & newValMask; 6520 6521 // Reinitialize the compare/swap command. If this fails, bail out of the retry loop! 6522 res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL); 6523 if (res != kIOReturnSuccess) 6524 break; 6525 6526 // Submit the compare/swap command. Will not return until complete 6527 res = fLockCmd->submit(); 6528 6529 // Check results, including actualOldVal 6530 if (res == kIOReturnSuccess) 6531 lockSuccessful = fLockCmd->locked(&actualOldVal); 6532 else 6533 lockSuccessful = false; 6534 6535 DebugLog("allocateIRMChannelInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n", 6536 res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal)); 6537 6538 // If we got a bus reset (i.e. wrong generation), no point on retrying 6539 if (res == kIOFireWireBusReset) 6540 break; 6541 6542 // If we succeeded, we don't need to retry 6543 else if (lockSuccessful) 6544 break; 6545 6546 else 6547 { 6548 // Decrement the retry count 6549 retries -= 1; 6550 6551 // If we don't have an error, but we're here, it's because 6552 // the compare-swap didn't succeed. Set an error code, in case we're 6553 // out of retries. 6554 if (res == kIOReturnSuccess) 6555 res = kIOFireWireChannelNotAvailable; 6556 6557 // Change our expected old value for the retry. 6558 expectedOldVal = actualOldVal; 6559 } 6560 } 6561 6562 // Release the lock command 6563 fLockCmd->release(); 6564 6565 return res; 6566} 6567 6568// releaseIRMChannelInGeneration 6569// 6570// 6571IOReturn IOFireWireController::releaseIRMChannelInGeneration(UInt8 isochChannel, UInt32 generation) 6572{ 6573 IOReturn res; 6574 UInt32 irmGeneration; 6575 UInt16 irmNodeID; 6576 IOFWCompareAndSwapCommand * fLockCmd; 6577 FWAddress addr; 6578 UInt32 newValMask; 6579 UInt32 expectedOldVal, newVal; 6580 UInt32 actualOldVal; 6581 bool lockSuccessful; 6582 UInt32 retries = 2; 6583 6584 // Get the current IRM and Generation 6585 getIRMNodeID(irmGeneration, irmNodeID); 6586 6587 // Check the current generation 6588 if (irmGeneration != generation) 6589 return kIOFireWireBusReset; 6590 6591 // Initialize the address for the current IRM's bandwidth available register 6592 addr.nodeID = irmNodeID; 6593 addr.addressHi = 0xFFFF; 6594 6595 if( isochChannel < 32 ) 6596 { 6597 addr.addressLo = kCSRChannelsAvailable31_0; 6598 newValMask = OSSwapHostToBigInt32(1<<(31 - isochChannel)); 6599 } 6600 else if( isochChannel < 64 ) 6601 { 6602 addr.addressLo = kCSRChannelsAvailable63_32; 6603 newValMask = OSSwapHostToBigInt32(1 << (63 - isochChannel)); 6604 } 6605 else 6606 return kIOReturnBadArgument; 6607 6608 // Start with the default, all channels allocated value for the old val! 6609 expectedOldVal = OSSwapHostToBigInt32(0x00000000); 6610 6611 // Create a compare/swap command 6612 fLockCmd = OSTypeAlloc( IOFWCompareAndSwapCommand ); 6613 if (!fLockCmd) 6614 return kIOReturnNoMemory; 6615 6616 // Pre-initialize the compare/swap command. Reinit will take place before use! 6617 if (!fLockCmd->initAll(this,generation,addr, NULL, NULL,0,NULL,NULL)) 6618 { 6619 fLockCmd->release(); 6620 return kIOReturnError; 6621 } 6622 6623 while (retries > 0) 6624 { 6625 // Make sure the channel is not already free 6626 if ((expectedOldVal & newValMask) == newValMask) 6627 { 6628 res = kIOReturnNoResources; 6629 break; 6630 } 6631 6632 // Calculate the new val for the compare/swap command 6633 newVal = expectedOldVal | newValMask; 6634 6635 // Reinitialize the compare/swap command. If this fails, bail out of the retry loop! 6636 res = fLockCmd->reinit(generation,addr, &expectedOldVal, &newVal,1,NULL,NULL); 6637 if (res != kIOReturnSuccess) 6638 break; 6639 6640 // Submit the compare/swap command. Will not return until complete 6641 res = fLockCmd->submit(); 6642 6643 // Check results, including actualOldVal 6644 if (res == kIOReturnSuccess) 6645 lockSuccessful = fLockCmd->locked(&actualOldVal); 6646 else 6647 lockSuccessful = false; 6648 6649 DebugLog("releaseIRMChannelInGeneration: res = 0x%08X, expectedOldVal = 0x%08X, newVal = 0x%08X, lockSuccessful = %d, actualOldVal = 0x%08X\n", 6650 res, OSSwapBigToHostInt32(expectedOldVal),OSSwapBigToHostInt32(newVal),lockSuccessful,OSSwapBigToHostInt32(actualOldVal)); 6651 6652 // If we got a bus reset (i.e. wrong generation), no point on retrying 6653 if (res == kIOFireWireBusReset) 6654 break; 6655 6656 // If we succeeded, we don't need to retry 6657 else if (lockSuccessful) 6658 break; 6659 6660 else 6661 { 6662 // Decrement the retry count 6663 retries -= 1; 6664 6665 // If we don't have an error, but we're here, it's because 6666 // the compare-swap didn't succeed. Set an error code, in case we're 6667 // out of retries. 6668 if (res == kIOReturnSuccess) 6669 res = kIOReturnNoResources; 6670 6671 // Change our expected old value for the retry. 6672 expectedOldVal = actualOldVal; 6673 } 6674 } 6675 6676 // Release the lock command 6677 fLockCmd->release(); 6678 6679 return res; 6680} 6681 6682// createIRMAllocation 6683// 6684// 6685IOFireWireIRMAllocation * IOFireWireController::createIRMAllocation(Boolean releaseIRMResourcesOnFree, 6686 IOFireWireIRMAllocation::AllocationLostNotificationProc allocationLostProc, 6687 void *pLostNotificationProcRefCon) 6688{ 6689 IOFireWireIRMAllocation * pIRMAllocation; 6690 pIRMAllocation = OSTypeAlloc( IOFireWireIRMAllocation ); 6691 if( !pIRMAllocation ) 6692 return NULL; 6693 6694 if( !pIRMAllocation->init(this,releaseIRMResourcesOnFree,allocationLostProc,pLostNotificationProcRefCon)) 6695 { 6696 pIRMAllocation->release(); 6697 pIRMAllocation = NULL; 6698 } 6699 6700 return pIRMAllocation; 6701} 6702 6703#pragma mark - 6704//////////////////////////////////////////////////////////////////////////// 6705 6706// activatePHYPacketListener 6707// 6708// 6709 6710IOReturn IOFireWireController::activatePHYPacketListener( IOFWPHYPacketListener * listener ) 6711{ 6712 IOReturn status = kIOReturnSuccess; 6713 6714 closeGate(); 6715 6716 if( status == kIOReturnSuccess ) 6717 { 6718 OSObject * prop = fFWIM->getProperty( "RcvPhyPkt" ); 6719 if( prop ) 6720 { 6721 UInt32 value = ((OSNumber*)prop)->unsigned32BitValue(); 6722 if( value == 0 ) 6723 { 6724 status = kIOReturnUnsupported; 6725 } 6726 } 6727 } 6728 6729 if( status == kIOReturnSuccess ) 6730 { 6731 if( !fPHYPacketListeners->setObject( listener ) ) 6732 { 6733 status = kIOReturnNoMemory; 6734 } 6735 } 6736 6737 openGate(); 6738 6739 return status; 6740} 6741 6742// deactivatePHYPacketListener 6743// 6744// 6745 6746void IOFireWireController::deactivatePHYPacketListener( IOFWPHYPacketListener * listener ) 6747{ 6748 closeGate(); 6749 6750 fPHYPacketListeners->removeObject( listener ); 6751 6752 openGate(); 6753} 6754 6755// processPHYPacket 6756// 6757// route incoming phy packets to all listeners 6758 6759void IOFireWireController::processPHYPacket( UInt32 data1, UInt32 data2 ) 6760{ 6761 // only process versaphy packets 6762 if( data1 & 0x40000000 ) 6763 { 6764 IOFWPHYPacketListener * listener; 6765 fPHYPacketListenersIterator->reset(); 6766 while( (listener = (IOFWPHYPacketListener *)fPHYPacketListenersIterator->getNextObject()) ) 6767 { 6768 listener->processPHYPacket( data1, data2 ); 6769 } 6770 } 6771} 6772 6773// createPHYPacketListener 6774// 6775// 6776 6777IOFWPHYPacketListener * 6778IOFireWireController::createPHYPacketListener( FWPHYPacketCallback proc, void * refcon ) 6779{ 6780 IOFWPHYPacketListener * listener = IOFWPHYPacketListener::createWithController( this ); 6781 if( listener ) 6782 { 6783 listener->setCallback( proc ); 6784 listener->setRefCon( refcon ); 6785 } 6786 6787 return listener; 6788} 6789 6790#pragma mark - 6791//////////////////////////////////////////////////////////////////////////// 6792 6793// getLocalNode 6794// 6795// static method to fetch the local node for a controller 6796 6797IOFireWireLocalNode * IOFireWireController::getLocalNode(IOFireWireController *control) 6798{ 6799 OSIterator *childIterator; 6800 IOFireWireLocalNode *localNode = NULL; 6801 childIterator = control->getClientIterator(); 6802 if( childIterator) { 6803 OSObject * child; 6804 while( (child = childIterator->getNextObject())) { 6805 localNode = OSDynamicCast(IOFireWireLocalNode, child); 6806 if(localNode) { 6807 break; 6808 } 6809 } 6810 childIterator->release(); 6811 } 6812 return localNode; 6813} 6814 6815// getBusPowerManager 6816// 6817// 6818 6819IOFireWirePowerManager * IOFireWireController::getBusPowerManager( void ) 6820{ 6821 return fBusPowerManager; 6822} 6823 6824// getWorkLoop 6825// 6826// 6827 6828IOWorkLoop * IOFireWireController::getWorkLoop() const 6829{ 6830 return fWorkLoop; 6831} 6832 6833// getLink 6834// 6835// 6836 6837IOFireWireLink * IOFireWireController::getLink() const 6838{ 6839 return fFWIM; 6840} 6841 6842// getCycleTime 6843// 6844// 6845 6846IOReturn IOFireWireController::getCycleTime(UInt32 &cycleTime) 6847{ 6848 IOReturn res; 6849 6850 res = fFWIM->getCycleTime(cycleTime); 6851 6852 return res; 6853} 6854 6855// getCycleTimeAndUpTime 6856// 6857// 6858 6859IOReturn IOFireWireController::getCycleTimeAndUpTime( UInt32 &cycleTime, UInt64 &uptime ) 6860{ 6861 IOReturn res; 6862 6863 res = fFWIM->getCycleTimeAndUpTime( cycleTime, uptime ); 6864 6865 return res; 6866} 6867 6868// getBusCycleTime 6869// 6870// 6871 6872IOReturn IOFireWireController::getBusCycleTime(UInt32 &busTime, UInt32 &cycleTime) 6873{ 6874 // Have to take workloop lock, in case the hardware is sleeping. 6875 IOReturn res; 6876 UInt32 cycleSecs; 6877 6878 closeGate(); 6879 6880 res = fFWIM->getBusCycleTime(busTime, cycleTime); 6881 6882 openGate(); 6883 6884 if(res == kIOReturnSuccess) { 6885 // Bottom 7 bits of busTime should be same as top 7 bits of cycle time. 6886 // However, link only updates bus time every few seconds, 6887 // so use cycletime for overlapping bits and check for cycletime wrap 6888 cycleSecs = cycleTime >> 25; 6889 // Update bus time. 6890 if((busTime & 0x7F) > cycleSecs) { 6891 // Must have wrapped, increment top part of busTime. 6892 cycleSecs += 0x80; 6893 } 6894 busTime = (busTime & ~0x7F) + cycleSecs; 6895 } 6896 return res; 6897} 6898 6899// hopCount 6900// 6901// 6902 6903UInt32 IOFireWireController::hopCount(UInt16 nodeAAddress, UInt16 nodeBAddress ) 6904{ 6905 nodeAAddress &= kFWMaxNodesPerBus; 6906 nodeBAddress &= kFWMaxNodesPerBus; 6907 6908 UInt16 lowNode = nodeAAddress > nodeBAddress ? nodeBAddress : nodeAAddress; 6909 6910 struct FWNodeScan 6911 { 6912 int nodeID; 6913 int childrenRemaining; 6914 }; 6915 6916 FWNodeScan scanList[fRootNodeID]; 6917 FWNodeScan *level; 6918 level = scanList; 6919 6920 const unsigned int maxNodes = fRootNodeID+1; 6921 UInt8 hopArray[maxNodes*(maxNodes+1)]; 6922 bzero(hopArray, sizeof(hopArray)); 6923 6924 closeGate(); 6925 6926 // this is the same basic algorithm used in buildTopology 6927 int i; 6928 // stop once we've found the lower node because there's enough info in the hop count table at that point 6929 for( i = fRootNodeID; i >= lowNode; i-- ) 6930 { 6931 // Add node to bottom of tree 6932 level->nodeID = i; 6933 level->childrenRemaining = countNodeIDChildren( i ); 6934 6935 if (i != fRootNodeID) 6936 { 6937 int parentNodeNum, scanNodeNum; 6938 parentNodeNum = (level-1)->nodeID; 6939 for (scanNodeNum = i + 1; scanNodeNum <= fRootNodeID; scanNodeNum++) 6940 { 6941 UInt8 hops = hopArray[(maxNodes + 1)*parentNodeNum + scanNodeNum]; 6942 6943 // fill out entire table so we don't have to use extra math to use a triangular matrix 6944 hopArray[(maxNodes + 1)*i + scanNodeNum] = hops + 1; 6945 hopArray[(maxNodes + 1)*scanNodeNum + i] = hops + 1; 6946 //IOLog("Calc Hops %d-%d: %d dervied from %d-%d:%d\n", i, scanNodeNum, hops+1, parentNodeNum, scanNodeNum, hops); 6947 } 6948 } 6949 6950 // Find next child port. 6951 if (i > 0) 6952 { 6953 while (level->childrenRemaining == 0) 6954 { 6955 // Go up one level in tree. 6956 level--; 6957 if(level < scanList) 6958 { 6959 ErrorLog("FireWire: SelfIDs don't build a proper tree for hop counts (missing selfIDS?)!!\n"); 6960 return 0xFFFFFFFF; // this seems like the best thing to return here, impossibly large 6961 } 6962 // One less child to scan. 6963 level->childrenRemaining--; 6964 } 6965 // Go down one level in tree. 6966 level++; 6967 } 6968 } 6969 6970 openGate(); 6971 6972 // since both sides of matrix are filled in, no special math is necessary 6973 return hopArray[(maxNodes + 1)*nodeAAddress + nodeBAddress]; 6974} 6975 6976// hopCount 6977// 6978// 6979 6980UInt32 IOFireWireController::hopCount( UInt16 nodeAAddress ) 6981{ 6982 //closeGate(); 6983 6984 UInt32 hops = hopCount( nodeAAddress, fLocalNodeID ); 6985 6986 //openGate(); 6987 6988 return hops; 6989} 6990 6991// FWSpeed 6992// Returns pre-determined speed between nodeAddress and localNode 6993// 6994 6995IOFWSpeed IOFireWireController::FWSpeed(UInt16 nodeAddress) const 6996{ 6997 return FWSpeed(nodeAddress, fLocalNodeID); 6998} 6999 7000// FWSpeed 7001// Returns pre-determined speed between nodeA and nodeB 7002// 7003 7004IOFWSpeed IOFireWireController::FWSpeed(UInt16 nodeA, UInt16 nodeB) const 7005{ 7006 unsigned int txSpeed = kFWSpeedInvalid; 7007 nodeA &= kFWMaxNodesPerBus; 7008 nodeB &= kFWMaxNodesPerBus; 7009 7010 if ( nodeA < kFWMaxNodesPerBus && nodeB < kFWMaxNodesPerBus ) 7011 { 7012 if ( nodeA < nodeB ) 7013 txSpeed = fSpeedVector[nodeA + ((nodeB * (nodeB + 1))/2)]; 7014 else 7015 txSpeed = fSpeedVector[nodeB + ((nodeA * (nodeA + 1))/2)]; 7016 } 7017 else 7018 { 7019 // Get the broadcast speed. 7020 // there's only one "broadcast speed", so looking for the slowest speed between 7021 // the localNode and all others is sufficient for the speed between any node 7022 // and the "broadcast node" 7023 unsigned int remoteNodeSpeed = kFWSpeedInvalid; 7024 int i; 7025 7026 for ( i=0; i <= fRootNodeID; i++ ) 7027 { 7028 remoteNodeSpeed = (unsigned int)FWSpeed(fLocalNodeID, i); 7029 //IOLog("IOFireWireController::FWSpeed(%x,%x) getting broadcast speed %x-%x=0x%x\n", nodeA, nodeB, fLocalNodeID, i, remoteNodeSpeed); 7030 txSpeed = txSpeed > remoteNodeSpeed ? remoteNodeSpeed : txSpeed; 7031 } 7032 } 7033 //DebugLog("IOFireWireController::FWSpeed( %d, %d ) = %d\n", nodeA, nodeB, txSpeed); 7034 7035 return (IOFWSpeed)txSpeed; 7036} 7037 7038// setNodeSpeed 7039// 7040// 7041 7042void IOFireWireController::setNodeSpeed( UInt16 nodeA, UInt16 nodeB, UInt8 speed ) 7043{ 7044 nodeA &= kFWMaxNodesPerBus; 7045 nodeB &= kFWMaxNodesPerBus; 7046 7047 if ( nodeA < kFWMaxNodesPerBus && nodeB < kFWMaxNodesPerBus ) 7048 { 7049 if ( nodeA < nodeB ) 7050 fSpeedVector[nodeA + ((nodeB * (nodeB + 1))/2)] = speed; 7051 else 7052 fSpeedVector[nodeB + ((nodeA * (nodeA + 1))/2)] = speed; 7053 } 7054 //IOLog("setNodeSpeed( A:%d, B:%d, Speed:0x%x)\n", nodeA, nodeB, speed); 7055} 7056 7057void IOFireWireController::setNodeSpeed( UInt16 nodeAddress, UInt8 speed ) 7058{ 7059 setNodeSpeed(nodeAddress, fLocalNodeID, speed); 7060} 7061 7062void IOFireWireController::setNodeSpeed( UInt16 nodeAddress, IOFWSpeed speed ) 7063{ 7064 if ( speed > 0xFF ) 7065 ErrorLog("FireWire: Trying to set speed map entry larger than 8 bits.\n"); 7066 7067 setNodeSpeed(nodeAddress, fLocalNodeID, (UInt8)speed); 7068} 7069 7070// maxPackLog 7071// 7072// How big (as a power of two) can packets sent to/received from the node be? 7073 7074int IOFireWireController::maxPackLog(bool forSend, UInt16 nodeAddress) const 7075{ 7076 int log; 7077 7078 log = 9+FWSpeed(nodeAddress); 7079 if( forSend ) 7080 { 7081 if( log > fMaxSendLog ) 7082 { 7083 log = fMaxSendLog; 7084 } 7085 } 7086 else 7087 { 7088 if( log > fMaxSendLog ) 7089 { 7090 log = fMaxRecvLog; 7091 } 7092 } 7093 7094 if( fUseHalfSizePackets ) 7095 { 7096 if( log > 1 ) 7097 { 7098 log--; 7099 } 7100 } 7101 7102 return log; 7103} 7104 7105// maxPackLog 7106// 7107// How big (as a power of two) can packets sent from A to B be? 7108 7109int IOFireWireController::maxPackLog(UInt16 nodeA, UInt16 nodeB) const 7110{ 7111 return 9+FWSpeed(nodeA, nodeB); 7112} 7113 7114// nodeIDtoDevice 7115// 7116// 7117 7118IOFireWireDevice * IOFireWireController::nodeIDtoDevice(UInt32 generation, UInt16 nodeID) 7119{ 7120 OSIterator *childIterator; 7121 IOFireWireDevice * found = NULL; 7122 7123 if(!checkGeneration(generation)) 7124 { 7125 return NULL; 7126 } 7127 7128 childIterator = getClientIterator(); 7129 7130 if( childIterator) 7131 { 7132 OSObject *child; 7133 while( (child = childIterator->getNextObject())) 7134 { 7135 found = OSDynamicCast(IOFireWireDevice, child); 7136 7137 // don't need to sync with open/close routines when checking for kNotTerminated 7138 if( found && (found->getTerminationState() == kNotTerminated) && found->fNodeID == nodeID ) 7139 { 7140 break; 7141 } 7142 } 7143 childIterator->release(); 7144 } 7145 return found; 7146} 7147 7148// getGeneration 7149// 7150// 7151 7152UInt32 IOFireWireController::getGeneration() const 7153{ 7154 return fBusGeneration; 7155} 7156 7157// checkGeneration 7158// 7159// 7160 7161bool IOFireWireController::checkGeneration(UInt32 gen) const 7162{ 7163 return gen == fBusGeneration; 7164} 7165 7166 7167// getLocalNodeID 7168// 7169// 7170 7171UInt16 IOFireWireController::getLocalNodeID() const 7172{ 7173 return fLocalNodeID; 7174} 7175 7176// getIRMNodeID 7177// 7178// 7179 7180IOReturn IOFireWireController::getIRMNodeID(UInt32 &generation, UInt16 &id) 7181{ 7182 closeGate(); 7183 7184 generation = fBusGeneration; 7185 id = fIRMNodeID; 7186 7187 openGate(); 7188 7189 return kIOReturnSuccess; 7190} 7191 7192// clipMaxRec2K 7193// 7194// 7195 7196IOReturn IOFireWireController::clipMaxRec2K( Boolean clipMaxRec ) 7197{ 7198 IOReturn res; 7199 7200 closeGate(); 7201 7202 //IOLog("IOFireWireController::clipMaxRec2K\n"); 7203 7204 res = fFWIM->clipMaxRec2K(clipMaxRec); 7205 7206 openGate(); 7207 7208 return res; 7209} 7210 7211// makeRoot 7212// 7213// 7214 7215IOReturn IOFireWireController::makeRoot(UInt32 generation, UInt16 nodeID) 7216{ 7217 IOReturn res = kIOReturnSuccess; 7218 nodeID &= 63; 7219 7220 closeGate(); 7221 7222 if(!checkGeneration(generation)) 7223 res = kIOFireWireBusReset; 7224 else if( fRootNodeID != nodeID ) { 7225 // Send phy packet to set root hold off bit for node 7226 res = fFWIM->sendPHYPacket((kFWConfigurationPacketID << kFWPhyPacketIDPhase) | 7227 (nodeID << kFWPhyPacketPhyIDPhase) | kFWPhyConfigurationR); 7228 if(kIOReturnSuccess == res) 7229 { 7230 FWTrace(kFWTResetBusAction, kTPResetMakeRoot, (uintptr_t)fFWIM, 0, 0, 0 ); 7231 // IOLog( "IOFireWireController::makeRoot resetBus\n" ); 7232 res = resetBus(); 7233 } 7234 } 7235 7236 openGate(); 7237 7238 return res; 7239} 7240 7241// nodeMustBeRoot 7242// 7243// 7244void IOFireWireController::nodeMustBeRoot( UInt32 nodeID ) 7245{ 7246 fForcedRootNodeID = nodeID; 7247 fNodeMustBeRootFlag = true; 7248} 7249 7250// nodeMustNotBeRoot 7251// 7252// 7253void IOFireWireController::nodeMustNotBeRoot( UInt32 nodeID ) 7254{ 7255 nodeID &= nodeID & 0x3f; 7256 7257 if( not fDelegateCycleMaster ) 7258 { 7259 if( fScans[nodeID] ) 7260 { 7261 fScans[nodeID]->fMustNotBeRoot = true; 7262 fNodeMustNotBeRootFlag = true; 7263 } 7264 } 7265} 7266 7267// setGapCount 7268// 7269// 7270void IOFireWireController::setGapCount( UInt32 gapCount ) 7271{ 7272 fForcedGapCount = gapCount; 7273 fForcedGapFlag = true; 7274} 7275 7276// useHalfSizePackets 7277// 7278// 7279 7280void IOFireWireController::useHalfSizePackets( void ) 7281{ 7282 fUseHalfSizePackets = true; 7283 fRequestedHalfSizePackets = true; 7284} 7285 7286// disablePhyPortForNodeIDOnSleep 7287// 7288// 7289 7290void IOFireWireController::disablePhyPortOnSleepForNodeID( UInt32 nodeID ) 7291{ 7292 UInt32 childNodeID; 7293 UInt32 childNumber = 0; 7294 UInt32 childPort; 7295 7296 for( childNodeID = 0; childNodeID < (UInt32)(fLocalNodeID & 63); childNodeID++ ) 7297 { 7298 if( childNodeID == nodeID ) 7299 { 7300 // Found it. Now, which port is it connected to? 7301 childPort = getPortNumberFromIndex( childNumber ); 7302 7303 if( childPort != 0xFFFFFFFF ) { 7304 fFWIM->disablePHYPortOnSleep( 1 << childPort ); 7305 break; 7306 } 7307 } 7308 if( hopCount( childNodeID, fLocalNodeID ) == 1 ) 7309 { 7310 childNumber++; 7311 } 7312 } 7313} 7314 7315#pragma mark - 7316///////////////////////////////////////////////////////////////////////////// 7317// workloop lock 7318// 7319 7320// openGate 7321// 7322// 7323 7324void IOFireWireController::openGate() 7325{ 7326 fPendingQ.fSource->openGate(); 7327} 7328 7329// closeGate 7330// 7331// 7332 7333void IOFireWireController::closeGate() 7334{ 7335 fPendingQ.fSource->closeGate(); 7336} 7337 7338// inGate 7339// 7340// 7341 7342bool IOFireWireController::inGate() 7343{ 7344 return fPendingQ.fSource->inGate(); 7345} 7346 7347#pragma mark - 7348///////////////////////////////////////////////////////////////////////////// 7349// queues 7350// 7351 7352// getTimeoutQ 7353// 7354// 7355 7356IOFWCmdQ& IOFireWireController::getTimeoutQ() 7357{ 7358 return fTimeoutQ; 7359} 7360 7361// getPendingQ 7362// 7363// 7364 7365IOFWCmdQ& IOFireWireController::getPendingQ() 7366{ 7367 return fPendingQ; 7368} 7369 7370// getAfterResetHandledQ 7371// 7372// 7373 7374IOFWCmdQ &IOFireWireController::getAfterResetHandledQ() 7375{ 7376 return fAfterResetHandledQ; 7377} 7378 7379// IOFireWireController 7380// 7381// 7382 7383void IOFireWireController::enterLoggingMode( void ) 7384{ 7385 // set controller IOReg property to signify we're in logging mode 7386 if ( fFWIM->enterLoggingMode() ) 7387 { 7388 setProperty(kFireWireLoggingMode, true); 7389 setProperty( kFireWireGenerationID, "Suspended" ); //zzz set GenID so SysProf does timeout 7390 } 7391} 7392 7393// MultiIsochReceiveListener Methods 7394// 7395// 7396IOFireWireMultiIsochReceiveListener * 7397IOFireWireController::createMultiIsochReceiveListener(UInt32 channel, 7398 FWMultiIsochReceiveListenerCallback callback, 7399 void *pCallbackRefCon, 7400 FWMultiIsochReceiveListenerParams *pListenerParams) 7401{ 7402 return IOFireWireMultiIsochReceiveListener::create(this,channel,callback,pCallbackRefCon,pListenerParams); 7403} 7404 7405IOReturn IOFireWireController::activateMultiIsochReceiveListener(IOFireWireMultiIsochReceiveListener *pListener) 7406{ 7407 return fFWIM->activateMultiIsochReceiveListener(pListener); 7408} 7409 7410IOReturn IOFireWireController::deactivateMultiIsochReceiveListener(IOFireWireMultiIsochReceiveListener *pListener) 7411{ 7412 return fFWIM->deactivateMultiIsochReceiveListener(pListener); 7413} 7414 7415void IOFireWireController::clientDoneWithMultiIsochReceivePacket(IOFireWireMultiIsochReceivePacket *pPacket) 7416{ 7417 fFWIM->clientDoneWithMultiIsochReceivePacket(pPacket); 7418} 7419 7420