1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/IOMessage.h> 24 25#define FIREWIREPRIVATE 26#include <IOKit/firewire/IOFireWireController.h> 27#undef FIREWIREPRIVATE 28 29#include <IOKit/firewire/IOConfigDirectory.h> 30#include <IOKit/firewire/IOFireWireDevice.h> 31#include <IOKit/IODeviceTreeSupport.h> 32 33#include <IOKit/sbp2/IOFireWireSBP2LUN.h> 34#include <IOKit/sbp2/IOFireWireSBP2Target.h> 35#include "FWDebugging.h" 36 37const OSSymbol *gCommand_Set_Spec_ID_Symbol = NULL; 38const OSSymbol *gCommand_Set_Symbol = NULL; 39const OSSymbol *gModule_Vendor_ID_Symbol = NULL; 40const OSSymbol *gCommand_Set_Revision_Symbol = NULL; 41const OSSymbol *gIOUnit_Symbol = NULL; 42const OSSymbol *gFirmware_Revision_Symbol = NULL; 43const OSSymbol *gDevice_Type_Symbol = NULL; 44const OSSymbol *gGUID_Symbol = NULL; 45const OSSymbol *gUnit_Characteristics_Symbol = NULL; 46const OSSymbol *gManagement_Agent_Offset_Symbol = NULL; 47const OSSymbol *gFast_Start_Symbol = NULL; 48 49OSDefineMetaClassAndStructors(IOFireWireSBP2Target, IOService); 50 51OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 0); 52OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 1); 53OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 2); 54OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 3); 55OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 4); 56OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 5); 57OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 6); 58OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 7); 59OSMetaClassDefineReservedUnused(IOFireWireSBP2Target, 8); 60 61// 62// start / stop routines 63// 64 65bool IOFireWireSBP2Target::start( IOService *provider ) 66{ 67 fProviderUnit = OSDynamicCast(IOFireWireUnit, provider); 68 if (fProviderUnit == NULL) 69 return false; 70 71 fProviderUnit->retain(); 72 73 // we want the expansion data member to be zeroed if it's available 74 // so create and zero in a local then assign to the member when were done 75 76 ExpansionData * exp_data = (ExpansionData*) IOMalloc( sizeof(ExpansionData) ); 77 if( !exp_data ) 78 { 79 return false; 80 } 81 82 bzero( exp_data, sizeof(ExpansionData) ); 83 84 fExpansionData = exp_data; 85 86 fControl = fProviderUnit->getController(); 87 88 // assume safe mode 89 fFlags = kIOFWSBP2FailsOnBusResetsDuringIO; 90 91 fOpenFromTarget = false; 92 fOpenFromLUNCount = 0; 93 fIOCriticalSectionCount = 0; 94 95 // 96 // create symbols 97 // 98 99 if( gCommand_Set_Spec_ID_Symbol == NULL ) 100 gCommand_Set_Spec_ID_Symbol = OSSymbol::withCString("Command_Set_Spec_ID"); 101 102 if( gCommand_Set_Symbol == NULL ) 103 gCommand_Set_Symbol = OSSymbol::withCString("Command_Set"); 104 105 if( gModule_Vendor_ID_Symbol == NULL ) 106 gModule_Vendor_ID_Symbol = OSSymbol::withCString("Vendor_ID"); 107 108 if( gCommand_Set_Revision_Symbol == NULL ) 109 gCommand_Set_Revision_Symbol = OSSymbol::withCString("Command_Set_Revision"); 110 111 if( gIOUnit_Symbol == NULL ) 112 gIOUnit_Symbol = OSSymbol::withCString("IOUnit"); 113 114 if( gFirmware_Revision_Symbol == NULL ) 115 gFirmware_Revision_Symbol = OSSymbol::withCString("Firmware_Revision"); 116 117 if( gDevice_Type_Symbol == NULL ) 118 gDevice_Type_Symbol = OSSymbol::withCString("Device_Type"); 119 120 if( gGUID_Symbol == NULL ) 121 gGUID_Symbol = OSSymbol::withCString("GUID"); 122 123 if( gUnit_Characteristics_Symbol == NULL ) 124 gUnit_Characteristics_Symbol = OSSymbol::withCString("Unit_Characteristics"); 125 126 if( gManagement_Agent_Offset_Symbol == NULL ) 127 gManagement_Agent_Offset_Symbol = OSSymbol::withCString("Management_Agent_Offset"); 128 129 if( gFast_Start_Symbol == NULL ) 130 gFast_Start_Symbol = OSSymbol::withCString("Fast_Start"); 131 132 if (IOService::start(provider)) 133 { 134 IOFireWireController * controller = fProviderUnit->getController(); 135 IOService * fwim = (IOService*)controller->getLink(); 136 OSObject * prop = NULL; 137 UInt32 byteCount1, byteCount2; 138 139 // 140 // read receive properties from registry 141 // 142 143 byteCount1 = 0; 144 prop = fwim->getProperty( "FWMaxAsyncReceiveBytes" ); 145 if( prop ) 146 { 147 byteCount1 = ((OSNumber*)prop)->unsigned32BitValue(); 148 if( byteCount1 != 0 ) 149 { 150 // minus 32 bytes for status block 151 byteCount1 -= 32; 152 } 153 } 154 155 byteCount2 = 0; 156 prop = fwim->getProperty( "FWMaxAsyncReceivePackets" ); 157 if( prop ) 158 { 159 UInt32 packetCount = ((OSNumber*)prop)->unsigned32BitValue(); 160 if( packetCount != 0 ) 161 { 162 // minus 1 for the status block 163 byteCount2 = (packetCount - 1) * 512; // 512 bytes is minimum packet size 164 } 165 } 166 167 // publish min byte size 168 UInt32 size = byteCount1 < byteCount2 ? byteCount1 : byteCount2; 169 if( size != 0) 170 setProperty( "SBP2ReceiveBufferByteCount", size, 32 ); 171 172 // start scanning for LUNs 173 scanForLUNs(); 174 } 175 else 176 return false; 177 178 FWKLOG( ( "IOFireWireSBP2Target<%p> : started\n", this ) ); 179 180 fExpansionData->fStarted = true; 181 182 return true; 183} 184 185// stop 186// 187// 188 189void IOFireWireSBP2Target::stop( IOService *provider ) 190{ 191 FWKLOG( ( "IOFireWireSBP2Target<%p>::stop\n", this ) ); 192 193 IOService::stop(provider); 194} 195 196// finalize 197// 198// 199 200bool IOFireWireSBP2Target::finalize( IOOptionBits options ) 201{ 202 // Nuke from device tree 203 detachAll( gIODTPlane ); 204 205 return IOService::finalize( options ); 206} 207 208// free 209// 210// 211 212void IOFireWireSBP2Target::free( void ) 213{ 214 FWKLOG( ( "IOFireWireSBP2Target<%p>::free\n", this ) ); 215 216 if( fIOCriticalSectionCount != 0 ) 217 { 218 IOLog( "IOFireWireSBP2Target<%p>::free - fIOCriticalSectionCount == %d!\n", this, fIOCriticalSectionCount ); 219 } 220 221 while( fIOCriticalSectionCount != 0 ) 222 { 223 fIOCriticalSectionCount--; 224 fControl->endIOCriticalSection(); 225 } 226 227 if( fExpansionData ) 228 { 229 if( fExpansionData->fPendingMgtAgentCommands ) 230 fExpansionData->fPendingMgtAgentCommands->release() ; 231 232 IOFree( fExpansionData, sizeof(ExpansionData) ); 233 fExpansionData = NULL; 234 } 235 236 if( fProviderUnit ) 237 { 238 fProviderUnit->release(); 239 fProviderUnit = NULL; 240 } 241 242 IOService::free(); 243} 244 245//////////////////////////////////////////////////////////////////////// 246 247// 248// message method 249// 250 251IOReturn IOFireWireSBP2Target::message( UInt32 type, IOService *nub, void *arg ) 252{ 253 IOReturn res = kIOReturnUnsupported; 254 255 FWKLOG( ("IOFireWireSBP2Target<%p> : message 0x%x, arg 0x%08lx\n", this, type, arg) ); 256 257 res = IOService::message(type, nub, arg); 258 if( kIOReturnUnsupported == res ) 259 { 260 switch (type) 261 { 262 case kIOMessageServiceIsTerminated: 263 FWKLOG( ( "IOFireWireSBP2Target<%p> : kIOMessageServiceIsTerminated\n", this ) ); 264 res = kIOReturnSuccess; 265 break; 266 267 case kIOMessageServiceIsSuspended: 268 FWKLOG( ( "IOFireWireSBP2Target<%p> : kIOMessageServiceIsSuspended\n", this ) ); 269 clearMgmtAgentAccess(); 270 res = kIOReturnSuccess; 271 break; 272 273 case kIOMessageServiceIsResumed: 274 FWKLOG( ( "IOFireWireSBP2Target<%p> : kIOMessageServiceIsResumed\n", this ) ); 275 configurePhysicalFilter(); 276 res = kIOReturnSuccess; 277 break; 278 279 default: // default the action to return kIOReturnUnsupported 280 break; 281 } 282 } 283 284 if( type != kIOMessageServiceIsTerminated && 285 type != (UInt32)kIOMessageFWSBP2ReconnectFailed && 286 type != (UInt32)kIOMessageFWSBP2ReconnectComplete ) 287 { 288 messageClients( type, arg ); 289 } 290 291 return res; 292} 293 294// getFireWireUnit 295// 296// returns the FireWire unit for doing non-SBP2 work 297 298IOFireWireUnit * IOFireWireSBP2Target::getFireWireUnit( void ) 299{ 300 return (IOFireWireUnit*)getProvider(); 301} 302 303//////////////////////////////////////////////////////////////////////// 304// open / close internals 305 306// 307// handleOpen / handleClose 308// 309// we override these two methods to allow a reference counted open from 310// LUNs only. Exculsive access is enforced for non-LUN clients 311// 312 313bool IOFireWireSBP2Target::handleOpen( IOService * forClient, IOOptionBits options, void * arg ) 314{ 315 bool ok = true; 316 317 FWKLOG(( "IOFireWireSBP2Target<%p::handleOpen entered fOpenFromLUNCount = %d, fOpenFromTarget = %d\n", this, fOpenFromLUNCount, fOpenFromTarget )); 318 319 IOFireWireSBP2LUN * lunClient = OSDynamicCast( IOFireWireSBP2LUN, forClient ); 320 if( lunClient != NULL ) 321 { 322 // bail if we're open from the target 323 if( fOpenFromTarget ) 324 return false; 325 326 // if this is the first open call, actually do an open 327 if( fOpenFromLUNCount == 0 ) 328 { 329 ok = fProviderUnit->open(this, options, arg); 330 if( ok ) 331 { 332 fOpenFromLUNCount++; 333 ok = IOService::handleOpen( this, options, arg ); 334 FWKLOG(( "IOFireWireSBP2Target<%p>::handleOpen called open\n", this )); 335 } 336 } 337 else 338 { 339 // otherwise just increase the reference count 340 fOpenFromLUNCount++; 341 } 342 } 343 else 344 { 345 // bail if we're open as a LUN 346 if( fOpenFromLUNCount != 0 ) 347 return false; 348 349 // try to open 350 if( !fOpenFromTarget ) // extra safe 351 { 352 ok = fProviderUnit->open(this, options, arg); 353 if( ok ) 354 { 355 fOpenFromTarget = true; 356 ok = IOService::handleOpen( forClient, options, arg ); 357 FWKLOG(( "IOFireWireSBP2Target<%p>::handleOpen called open\n", this )); 358 } 359 } 360 else 361 ok = false; // already open 362 } 363 364 FWKLOG(( "IOFireWireSBP2Target<%p>::handleOpen - exit handleOpen fOpenFromLUNCount = %d, fOpenFromTarget = %d\n", this, fOpenFromLUNCount, fOpenFromTarget )); 365 366 return ok; 367} 368 369void IOFireWireSBP2Target::handleClose( IOService * forClient, IOOptionBits options ) 370{ 371 FWKLOG(( "IOFireWireSBP2Target<%p>::handleClose enter handleClose fOpenFromLUNCount = %d, fOpenFromTarget = %d\n", this, fOpenFromLUNCount, fOpenFromTarget )); 372 373 IOFireWireSBP2LUN * lunClient = OSDynamicCast( IOFireWireSBP2LUN, forClient ); 374 if( lunClient != NULL ) 375 { 376 if( fOpenFromLUNCount != 0 ) // extra safe 377 { 378 fOpenFromLUNCount--; 379 380 if( fOpenFromLUNCount == 0 ) // close if we're down to zero 381 { 382 IOService::handleClose( this, options); 383 fProviderUnit->close(this, options); 384 FWKLOG(( "IOFireWireSBP2Target<%p>::handleClose - called close\n", this )); 385 } 386 } 387 } 388 else 389 { 390 if( fOpenFromTarget ) // if we were open from the target 391 { 392 fOpenFromTarget = false; 393 IOService::handleClose(forClient, options); 394 fProviderUnit->close(this, options); 395 FWKLOG(( "IOFireWireSBP2Target<%p::handleClose - called close\n", this )); 396 } 397 } 398 399 FWKLOG(( "IOFireWireSBP2Target<%p>::handleClose - exit handleClose fOpenFromLUNCount = %d, fOpenFromTarget = %d\n", this, fOpenFromLUNCount, fOpenFromTarget )); 400} 401 402// 403// handleIsOpen 404// 405// Default implementation is for single object access. We use this when someone 406// has opened the target, but since multiple LUNs can open this object we override 407// the behavior in this case. 408 409bool IOFireWireSBP2Target::handleIsOpen( const IOService * forClient ) const 410{ 411 // are we open from one or more LUNs? 412 if( fOpenFromLUNCount != 0 ) 413 { 414 // is the client really a LUN? 415 IOFireWireSBP2LUN * lunClient = OSDynamicCast( IOFireWireSBP2LUN, forClient ); 416 return (lunClient != NULL ); 417 } 418 419 // are we open from the target 420 if( fOpenFromTarget ) 421 { 422 // is the client the one who opened us? 423 return IOService::handleIsOpen( forClient ); 424 } 425 426 // we're not open 427 return false; 428} 429 430//////////////////////////////////////////////////////////////////////// 431// LUN discovery and creation 432 433// scanForLUNS 434// 435// look for LUNs, publish the information in the registry and initiate matching. 436 437void IOFireWireSBP2Target::scanForLUNs( void ) 438{ 439 IOReturn status = kIOReturnSuccess; 440 IOReturn tempStatus = kIOReturnSuccess; 441 442 LUNInfo info; 443 444 info.cmdSpecID = 0; 445 info.cmdSet = 0; 446 info.vendorID = 0; 447 info.softwareRev = 0; 448 info.firmwareRev = 0; 449 info.lun = 0; 450 info.devType = 0; 451 info.unitCharacteristics = 0; 452 info.managementOffset = 0; 453 info.revision = 0; 454 info.fastStartSupported = false; 455 info.fastStart = 0; 456 457 // 458 // get root directory 459 // 460 461 IOConfigDirectory * directory; 462 463 IOFireWireDevice * device = NULL; 464 IOService * providerService = fProviderUnit->getProvider(); 465 if( providerService == NULL ) 466 status = kIOReturnError; 467 468 if( status == kIOReturnSuccess ) 469 { 470 device = OSDynamicCast( IOFireWireDevice, providerService ); 471 if( device == NULL ) 472 status = kIOReturnError; 473 FWKLOG( ("IOFireWireSBP2Target<%p> : unit = 0x%08lx, provider = 0x%08lx, device = 0x%08lx\n", this, fProviderUnit, providerService, device) ); 474 } 475 476 if( status == kIOReturnSuccess ) 477 { 478 status = device->getConfigDirectory( directory ); 479 FWKLOG( ( "IOFireWireSBP2Target<%p> : status = %d\n", this, status ) ); 480 } 481 482 // 483 // find vendor id 484 // 485 486 if( status == kIOReturnSuccess ) 487 tempStatus = directory->getKeyValue( kConfigModuleVendorIdKey, info.vendorID ); 488 489 // 490 // get unit directory 491 // 492 493 status = fProviderUnit->getConfigDirectory( directory ); 494 FWKLOG( ( "IOFireWireSBP2Target<%p> : status = %d\n", this, status ) ); 495 496 // 497 // find command spec id 498 // 499 500 if( status == kIOReturnSuccess ) 501 status = directory->getKeyValue( kCmdSpecIDKey, info.cmdSpecID ); 502 503 // 504 // find command set 505 // 506 507 if( status == kIOReturnSuccess ) 508 status = directory->getKeyValue( kCmdSetKey, info.cmdSet ); 509 510 // 511 // find unit characteristics 512 // 513 514 if( status == kIOReturnSuccess ) 515 status = directory->getKeyValue( kUnitCharacteristicsKey, info.unitCharacteristics ); 516 517 // 518 // find management agent offset 519 // and add ourselves to the DeviceTree with that location 520 // for OpenFirmware boot path generation. 521 // 522 523 status = directory->getKeyValue( kManagementAgentOffsetKey, info.managementOffset ); 524 if( status == kIOReturnSuccess ) 525 { 526 IOService *parent = this; 527 while(parent) { 528 if(parent->inPlane(gIODTPlane)) 529 break; 530 parent = parent->getProvider(); 531 } 532 if(parent) { 533 char location[9]; 534 snprintf( location, sizeof(location), "%lx", info.managementOffset ); 535 attachToParent(parent, gIODTPlane); 536 setLocation(location, gIODTPlane); 537 setName("sbp-2", gIODTPlane); 538 } 539 } 540 541 // failure to find one of the following is not fatal, hence the use of tempStatus 542 543 // 544 // find revision 545 // 546 547 if( status == kIOReturnSuccess ) 548 tempStatus = directory->getKeyValue( kRevisionKey, info.revision ); 549 550 // 551 // find fast start info 552 // 553 554 if( status == kIOReturnSuccess && info.revision != 0 ) 555 { 556 tempStatus = directory->getKeyValue( kFastStartKey, info.fastStart ); 557 if( tempStatus == kIOReturnSuccess ) 558 { 559 info.fastStartSupported = true; 560 } 561 } 562 563 // 564 // find software rev 565 // 566 567 if( status == kIOReturnSuccess ) 568 tempStatus = directory->getKeyValue( kSoftwareRevKey, info.softwareRev ); 569 570 // 571 // find firmware rev 572 // 573 574 if( status == kIOReturnSuccess ) 575 tempStatus = directory->getKeyValue( kFirmwareRevKey, info.firmwareRev ); 576 577 FWKLOG( ( "IOFireWireSBP2Target<%p> : status = %d, cmdSpecID = %d, cmdSet = %d, vendorID = %d, softwareRev = %d, firmwareRev = %d\n", 578 this, status, info.cmdSpecID, info.cmdSet, info.vendorID, info.softwareRev, info.firmwareRev ) ); 579 580 // 581 // look for luns implemented as immediate values 582 // 583 584 if( status == kIOReturnSuccess ) 585 { 586 // look at each entry 587 for( int pos = 0; pos < directory->getNumEntries(); pos++ ) 588 { 589 // get index key 590 UInt32 key; 591 tempStatus = directory->getIndexEntry( pos, key ); 592 FWKLOG( ( "IOFireWireSBP2Target<%p> : tempStatus = %d, pos = %d, key = %d\n", 593 this, tempStatus, pos, key ) ); 594 595 // if it was the LUN key 596 if( tempStatus == kIOReturnSuccess && key >> kConfigEntryKeyValuePhase == kLUNKey ) 597 { 598 UInt32 data; 599 tempStatus = directory->getIndexValue( pos, data ); 600 if( tempStatus == kIOReturnSuccess ) 601 { 602 info.lun = data & 0x0000ffff; 603 info.devType = (data & 0x001f0000) >> 16; 604 605 FWKLOG( ( "IOFireWireSBP2Target<%p> : cmdSpecID = %d, cmdSet = %d, vendorID = %d, softwareRev = %d\n", 606 this, info.cmdSpecID, info.cmdSet, info.vendorID, info.softwareRev ) ); 607 FWKLOG( ( "IOFireWireSBP2Target<%p> : firmwareRev = %d, lun = %d, devType = %d\n", 608 this, info.firmwareRev, info.lun, info.devType ) ); 609 FWKLOG( ( "IOFireWireSBP2Target<%p> : unitCharacteristics = %d, managementOffset = %d,\n", 610 this, info.unitCharacteristics, info.managementOffset ) ); 611 FWKLOG( ( "IOFireWireSBP2Target<%p> : revision = %d, fastStartSupported = %d, fastStart = 0x%08lx\n", 612 this, info.revision, info.fastStartSupported, info.fastStart ) ); 613 614 // force vendors to use real values, (0, 0) is not legal 615 if( (info.cmdSpecID & 0x00ffffff) || (info.cmdSet & 0x00ffffff) ) 616 { 617 fExpansionData->fNumLUNs++; 618 createLUN( &info ); 619 } 620 } 621 } 622 } 623 } 624 625 // 626 // look for luns implemented as directories 627 // 628 629 if( status == kIOReturnSuccess ) 630 { 631 OSIterator * directoryIterator; 632 IOConfigDirectory * lunDirectory; 633 UInt32 lunValue; 634 635 status = directory->getKeySubdirectories( kLUNDirectoryKey, directoryIterator ); 636 637 // iterate through directories 638 while( (lunDirectory = OSDynamicCast(IOConfigDirectory,directoryIterator->getNextObject())) != NULL ) 639 { 640 // 641 // find fast start info 642 // 643 644 if( info.revision != 0 ) 645 { 646 tempStatus = directory->getKeyValue( kFastStartKey, info.fastStart ); 647 if( tempStatus == kIOReturnSuccess ) 648 { 649 info.fastStartSupported = true; 650 } 651 } 652 653 // get lun value 654 655 tempStatus = lunDirectory->getKeyValue( kLUNKey, lunValue ); 656 if( tempStatus == kIOReturnSuccess ) 657 { 658 info.lun = lunValue & 0x0000ffff; 659 info.devType = (lunValue & 0x001f0000) >> 16; 660 661 FWKLOG( ( "IOFireWireSBP2Target<%p> : cmdSpecID = %d, cmdSet = %d, vendorID = %d, softwareRev = %d\n", 662 this, info.cmdSpecID, info.cmdSet, info.vendorID, info.softwareRev ) ); 663 FWKLOG( ( "IOFireWireSBP2Target<%p> : firmwareRev = %d, lun = %d, devType = %d\n", 664 this, info.firmwareRev, info.lun, info.devType ) ); 665 FWKLOG( ( "IOFireWireSBP2Target<%p> : revision = %d, fastStartSupported = %d, fastStart = 0x%08lx\n", 666 this, info.revision, info.fastStartSupported, info.fastStart ) ); 667 668 // force vendors to use real values, (0, 0) is not legal 669 if( (info.cmdSpecID & 0x00ffffff) || (info.cmdSet & 0x00ffffff) ) 670 { 671 fExpansionData->fNumLUNs++; 672 createLUN( &info ); 673 } 674 } 675 } 676 677 directoryIterator->release(); 678 } 679 680 fExpansionData->fPendingMgtAgentCommands = OSArray::withCapacity( fExpansionData->fNumLUNs) ; 681 682 // 683 // we found all the luns so lets call registerService on ourselves 684 // for drivers that want to drive all luns 685 // 686 687 OSObject *prop; 688 689 if( status == kIOReturnSuccess ) 690 { 691 // all of these values are 24 bits or less, even though we have specified 32 bits 692 693 prop = OSNumber::withNumber( info.cmdSpecID, 32 ); 694 setProperty( gCommand_Set_Spec_ID_Symbol, prop ); 695 prop->release(); 696 697 prop = OSNumber::withNumber( info.cmdSet, 32 ); 698 setProperty( gCommand_Set_Symbol, prop ); 699 prop->release(); 700 701 prop = OSNumber::withNumber( info.vendorID, 32 ); 702 setProperty( gModule_Vendor_ID_Symbol, prop ); 703 prop->release(); 704 705 prop = OSNumber::withNumber( info.softwareRev, 32 ); 706 setProperty( gCommand_Set_Revision_Symbol, prop ); 707 prop->release(); 708 709 prop = OSNumber::withNumber( info.firmwareRev, 32 ); 710 setProperty( gFirmware_Revision_Symbol, prop ); 711 prop->release(); 712 713 prop = OSNumber::withNumber( info.devType, 32 ); 714 setProperty( gDevice_Type_Symbol, prop ); 715 prop->release(); 716 717 prop = fProviderUnit->getProperty(gGUID_Symbol); 718 if( prop ) 719 setProperty( gGUID_Symbol, prop ); 720 721 prop = fProviderUnit->getProperty(gFireWireModel_ID); 722 if( prop ) 723 setProperty( gFireWireModel_ID, prop ); 724 725 prop = fProviderUnit->getProperty(gFireWireProduct_Name); 726 if( prop ) 727 setProperty( gFireWireProduct_Name, prop ); 728 729 prop = fProviderUnit->getProperty(gFireWireVendor_Name); 730 if( prop ) 731 setProperty( gFireWireVendor_Name, prop ); 732 733 registerService(); 734 } 735} 736 737IOReturn IOFireWireSBP2Target::createLUN( LUNInfo * info ) 738 739{ 740 IOReturn status = kIOReturnSuccess; 741 742 OSDictionary * propTable = OSDictionary::withCapacity(7); 743 744 OSObject *prop; 745 746 if( propTable ) 747 { 748 // all of these values are 24 bits or less, even though we have specified 32 bits 749 750 prop = OSNumber::withNumber( info->cmdSpecID, 32 ); 751 propTable->setObject( gCommand_Set_Spec_ID_Symbol, prop ); 752 prop->release(); 753 754 prop = OSNumber::withNumber( info->cmdSet, 32 ); 755 propTable->setObject( gCommand_Set_Symbol, prop ); 756 prop->release(); 757 758 prop = OSNumber::withNumber( info->vendorID, 32 ); 759 propTable->setObject( gModule_Vendor_ID_Symbol, prop ); 760 prop->release(); 761 762 prop = OSNumber::withNumber( info->softwareRev, 32 ); 763 propTable->setObject( gCommand_Set_Revision_Symbol, prop ); 764 prop->release(); 765 766 prop = OSNumber::withNumber( info->firmwareRev, 32 ); 767 propTable->setObject( gFirmware_Revision_Symbol, prop ); 768 prop->release(); 769 770 prop = OSNumber::withNumber( info->lun, 32 ); 771 propTable->setObject( gIOUnit_Symbol, prop ); 772 prop->release(); 773 774 prop = OSNumber::withNumber( info->devType, 32 ); 775 propTable->setObject( gDevice_Type_Symbol, prop ); 776 prop->release(); 777 778 prop = OSNumber::withNumber( info->unitCharacteristics, 32 ); 779 propTable->setObject( gUnit_Characteristics_Symbol, prop ); 780 prop->release(); 781 782 prop = OSNumber::withNumber(info->managementOffset, 32 ); 783 propTable->setObject( gManagement_Agent_Offset_Symbol, prop ); 784 prop->release(); 785 786 if( info->fastStartSupported ) 787 { 788 prop = OSNumber::withNumber( info->fastStart, 32 ); 789 propTable->setObject( gFast_Start_Symbol, prop ); 790 prop->release(); 791 } 792 793 prop = fProviderUnit->getProperty(gGUID_Symbol); 794 if( prop ) 795 propTable->setObject( gGUID_Symbol, prop ); 796 797 prop = fProviderUnit->getProperty(gFireWireModel_ID); 798 if( prop ) 799 propTable->setObject( gFireWireModel_ID, prop ); 800 801 prop = fProviderUnit->getProperty(gFireWireProduct_Name); 802 if( prop ) 803 propTable->setObject( gFireWireProduct_Name, prop ); 804 805 prop = fProviderUnit->getProperty(gFireWireVendor_Name); 806 if( prop ) 807 propTable->setObject( gFireWireVendor_Name, prop ); 808 809 // 810 // create lun 811 // 812 813 IOFireWireSBP2LUN * newLUN = new IOFireWireSBP2LUN; 814 if( newLUN != NULL ) 815 { 816 bool success = true; 817 818 if( success ) 819 success = newLUN->init(propTable); 820 821 if( success ) 822 success = newLUN->attach(this); 823 824 if( success ) 825 newLUN->registerService(); 826 827 FWKLOG( ( "IOFireWireSBP2Target<%p> : created LUN object - success = %d\n", this, success ) ); 828 829 if( !success ) 830 status = kIOReturnError; 831 832 newLUN->release(); 833 } 834 835 propTable->release(); 836 } 837 838 return status; 839} 840 841// matchPropertyTable 842// 843// 844 845bool IOFireWireSBP2Target::matchPropertyTable(OSDictionary * table) 846{ 847 848 // 849 // If the service object wishes to compare some of its properties in its 850 // property table against the supplied matching dictionary, 851 // it should do so in this method and return truth on success. 852 // 853 854 if( !IOService::matchPropertyTable(table) ) 855 return false; 856 857 // We return success if the following expression is true -- individual 858 // comparisions evaluate to truth if the named property is not present 859 // in the supplied matching dictionary. 860 861 bool res = compareProperty(table, gCommand_Set_Spec_ID_Symbol) && 862 compareProperty(table, gCommand_Set_Symbol) && 863 compareProperty(table, gModule_Vendor_ID_Symbol) && 864 compareProperty(table, gCommand_Set_Revision_Symbol) && 865 compareProperty(table, gFirmware_Revision_Symbol) && 866 compareProperty(table, gDevice_Type_Symbol) && 867 compareProperty(table, gGUID_Symbol) && 868 compareProperty(table, gFireWireModel_ID); 869 870 return res; 871} 872 873void IOFireWireSBP2Target::setTargetFlags( UInt32 flags ) 874{ 875 fFlags |= flags; 876 877 FWKLOG(( "IOFireWireSBP2Target<%p>::setTargetFlags 0x%08lx\n", this, fFlags )); 878 879 configurePhysicalFilter(); 880} 881 882void IOFireWireSBP2Target::clearTargetFlags( UInt32 flags ) 883{ 884 fFlags &= ~flags; 885 886 FWKLOG(( "IOFireWireSBP2Target<%p>::clearTargetFlags 0x%08lx\n", this, fFlags )); 887 888 configurePhysicalFilter(); 889} 890 891UInt32 IOFireWireSBP2Target::getTargetFlags( void ) 892{ 893 return fFlags; 894} 895 896void IOFireWireSBP2Target::configurePhysicalFilter( void ) 897{ 898 bool disablePhysicalAccess = false; 899 900 // sometimes message() gets called before start completes 901 // we shouldn't try to configure anything until start is done 902 903 if( fExpansionData == NULL ) 904 return; 905 906 if( !fExpansionData->fStarted ) 907 return; 908 909 // 910 // determine if we should turn off physical access 911 // 912 913 if( fFlags & kIOFWSBP2FailsOnAckBusy ) 914 { 915 IOFireWireController * controller = fProviderUnit->getController(); 916 IOService * fwim = (IOService*)controller->getLink(); 917 918 UInt32 deviceCount = 0; 919 920 // get self id property 921 OSData * data = (OSData*)controller->getProperty( "FireWire Self IDs" ); 922 923 // get self id data 924 UInt32 numIDs = data->getLength() / sizeof(UInt32); 925 UInt32 *IDs = (UInt32*)data->getBytesNoCopy(); 926 927 // count nodes on bus 928 UInt32 i; 929 for( i = 0; i < numIDs; i++ ) 930 { 931 UInt32 current_id = IDs[i]; 932 // count all type zero selfid with the linkon bit set 933 if( (current_id & kFWSelfIDPacketType) == 0 && 934 (current_id & kFWSelfID0L) ) 935 { 936 deviceCount++; 937 } 938 } 939 940 // if PhysicalUnitBlocksOnReads and more than one device on the bus, 941 // then turn off the physical unit for this node 942 if( (deviceCount > 2) && (fwim->getProperty( "PhysicalUnitBlocksOnReads" ) != NULL) ) 943 { 944 disablePhysicalAccess = true; 945 } 946 } 947 948 // 949 // turn on or off physical access 950 // 951 952 if( disablePhysicalAccess ) 953 { 954 FWKLOG(( "IOFireWireSBP2Target<%p>::configurePhysicalFilter disabling physical access for unit 0x%08lx\n", this, fProviderUnit )); 955 fProviderUnit->setNodeFlags( kIOFWDisableAllPhysicalAccess ); 956 } 957 else 958 { 959 FWKLOG(( "IOFireWireSBP2Target<%p>::configurePhysicalFilter enabling physical access for unit 0x%08lx\n", this, fProviderUnit )); 960 fProviderUnit->clearNodeFlags( kIOFWDisableAllPhysicalAccess ); 961 } 962 963} 964 965// beginIOCriticalSection 966// 967// 968 969IOReturn IOFireWireSBP2Target::beginIOCriticalSection( void ) 970{ 971 IOReturn status = kIOReturnSuccess; 972 973 FWKLOG(( "IOFireWireSBP2Target<%p>::beginIOCriticalSection\n", this )); 974 975 if( fFlags & kIOFWSBP2FailsOnBusResetsDuringIO ) 976 { 977 FWKLOG(( "IOFireWireSBP2Target<%p>::beginIOCriticalSection fControl->disableSoftwareBusResets()\n", this )); 978 status = fControl->beginIOCriticalSection(); 979 if( status == kIOReturnSuccess ) 980 { 981 fIOCriticalSectionCount++; 982 } 983 } 984 985 FWKLOG(( "IOFireWireSBP2Target<%p>::beginIOCriticalSection status = 0x%08lx\n", this, (UInt32)status )); 986 987 return status; 988} 989 990// endIOCriticalSection 991// 992// 993 994void IOFireWireSBP2Target::endIOCriticalSection( void ) 995{ 996 FWKLOG(( "IOFireWireSBP2Target<%p>::endIOCriticalSection\n", this )); 997 998 if( fFlags & kIOFWSBP2FailsOnBusResetsDuringIO ) 999 { 1000 FWKLOG(( "IOFireWireSBP2Target<%p>::endIOCriticalSection fControl->enableSoftwareBusResets()\n", this )); 1001 1002 if( fIOCriticalSectionCount != 0 ) 1003 { 1004 fIOCriticalSectionCount--; 1005 fControl->endIOCriticalSection(); 1006 } 1007 else 1008 { 1009#if __LP64__ 1010 IOLog( "IOFireWireSBP2Target<0x%016llx>::endIOCriticalSection - fIOCriticalSectionCount == 0!\n", (UInt64)this ); 1011#else 1012 IOLog( "IOFireWireSBP2Target<%p>::endIOCriticalSection - fIOCriticalSectionCount == 0!\n", this ); 1013#endif 1014 } 1015 } 1016} 1017 1018// synchMgmtAgentAccess 1019// 1020// 1021 1022IOReturn IOFireWireSBP2Target::synchMgmtAgentAccess( 1023 IOFWCommand * mgmtOrbCommand 1024) 1025{ 1026 if( fExpansionData->fNumLUNs > 1 ) 1027 { 1028 FWKLOG(("IOFireWireSBP2Target::synchMgmtAgentAccess count %x\n",fExpansionData->fNumberPendingMgtAgentOrbs + 1)); 1029 1030 if( fExpansionData->fNumberPendingMgtAgentOrbs++ ) 1031 { 1032 FWKLOG(("IOFireWireSBP2Target::synchMgmtAgentAccess Mgmt Agent Busy, saving submit command %08x\n",mgmtOrbCommand)); 1033 fExpansionData->fPendingMgtAgentCommands->setObject( mgmtOrbCommand ); 1034 } 1035 else 1036 return( mgmtOrbCommand->submit() ); 1037 } 1038 else 1039 return( mgmtOrbCommand->submit() ); 1040 1041 return kIOReturnSuccess; 1042 1043} 1044 1045// completeMgmtAgentAccess 1046// 1047// 1048 1049void IOFireWireSBP2Target::completeMgmtAgentAccess( ) 1050{ 1051 IOFWAsyncCommand * mgmtOrbCommand; 1052 IOReturn status = kIOReturnSuccess; 1053 1054 if( fExpansionData->fNumLUNs > 1 ) 1055 { 1056 1057 FWKLOG(("IOFireWireSBP2Target::completeMgmtAgentAccess >> count %x\n",fExpansionData->fNumberPendingMgtAgentOrbs - 1)); 1058 if( fExpansionData->fNumberPendingMgtAgentOrbs-- ) 1059 { 1060 mgmtOrbCommand = (IOFWAsyncCommand *)fExpansionData->fPendingMgtAgentCommands->getObject( 0 ) ; 1061 1062 if( mgmtOrbCommand ) 1063 { 1064 FWKLOG(("IOFireWireSBP2Target::completeMgmtAgentAccess, calling submit command %08x\n",mgmtOrbCommand)); 1065 fExpansionData->fPendingMgtAgentCommands->removeObject( 0 ) ; 1066 1067 status = mgmtOrbCommand->submit() ; 1068 1069 if( status ) 1070 { 1071 FWKLOG(("IOFireWireSBP2Target::completeMgmtAgentAccess, submit for command %08x failed with %08x\n",mgmtOrbCommand,status)); 1072 mgmtOrbCommand->gotPacket( kFWResponseBusResetError, NULL, 0 ); 1073 } 1074 } 1075 } 1076 FWKLOG(("IOFireWireSBP2Target::completeMgmtAgentAccess << count %x\n",fExpansionData->fNumberPendingMgtAgentOrbs)); 1077 } 1078} 1079 1080// clearMgmtAgentAccess 1081// 1082// 1083 1084void IOFireWireSBP2Target::cancelMgmtAgentAccess( IOFWCommand * mgmtOrbCommand ) 1085{ 1086 // should only have one instance of a given command in this list, but I'll use a loop for good measure. 1087 1088 int index; 1089 while( (index = fExpansionData->fPendingMgtAgentCommands->getNextIndexOfObject( mgmtOrbCommand, 0 )) != -1 ) 1090 { 1091 fExpansionData->fPendingMgtAgentCommands->removeObject( index ); 1092 } 1093} 1094 1095// clearMgmtAgentAccess 1096// 1097// 1098 1099void IOFireWireSBP2Target::clearMgmtAgentAccess( ) 1100{ 1101 if( fExpansionData && fExpansionData->fPendingMgtAgentCommands ) 1102 { 1103 IOFWAsyncCommand * mgmtOrbCommand; 1104 1105 FWKLOG(("IOFireWireSBP2Target::clearMgmtAgentAccess\n",mgmtOrbCommand)); 1106 1107 while( (mgmtOrbCommand = (IOFWAsyncCommand *)fExpansionData->fPendingMgtAgentCommands->getObject( 0 )) ) 1108 { 1109 mgmtOrbCommand->retain(); 1110 1111 fExpansionData->fPendingMgtAgentCommands->removeObject( 0 ) ; 1112 1113 FWKLOG(("IOFireWireSBP2Target::clearMgmtAgentAccess, failing command %08x\n",mgmtOrbCommand)); 1114 mgmtOrbCommand->gotPacket( kFWResponseBusResetError, NULL, 0 ); 1115 1116 mgmtOrbCommand->release(); 1117 } 1118 1119 fExpansionData->fNumberPendingMgtAgentOrbs = 0; 1120 } 1121} 1122