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