1/* 2 * IOFireWireLocalNode.cpp 3 * IOFireWireFamily 4 * 5 * Created by Niels on Fri Aug 16 2002. 6 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 7 * 8 * @APPLE_LICENSE_HEADER_START@ 9 * 10 * The contents of this file constitute Original Code as defined in and 11 * are subject to the Apple Public Source License Version 1.1 (the 12 * "License"). You may not use this file except in compliance with the 13 * License. Please obtain a copy of the License at 14 * http://www.apple.com/publicsource and read it before using this file. 15 * 16 * This Original Code and all software distributed under the License are 17 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 18 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 19 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 21 * License for the specific language governing rights and limitations 22 * under the License. 23 * 24 * @APPLE_LICENSE_HEADER_END@ 25 */ 26/* 27 $Log: IOFireWireLocalNode.cpp,v $ 28 Revision 1.12 2012/06/07 18:06:02 calderon 29 Fix IOFireWireController leak 30 <rdar://11005341> or <rdar://11411007> 31 32 Revision 1.11 2009/03/26 22:45:17 calderon 33 <rdar://6728033> User client fails to terminate with unexpected consuequences 34 35 Revision 1.10 2008/04/24 00:01:39 collin 36 more K640 37 38 Revision 1.9 2006/11/08 22:33:38 ayanowit 39 Changed the SetProperty(...) function on the IOFireWireLocalNode, which is used to instantiate objects with the IOFireWireMatchingNub, to add a new way 40 of instantiating IOFireWireMatchingNub matched objects, where we ensure that only one of those objects gets instantiated on the LocalNode (SummonNubExclusive). 41 This is part of the changes needed to get AppleFWAudio to start using the IOFireWireMatchingNub instead of directly matching on IOFireWireLocalNode. 42 43 Revision 1.8 2005/02/18 22:56:53 gecko1 44 3958781 Q45C EVT: FireWire ASP reporter says port speed is 800 Mb/sec 45 46 Revision 1.7 2003/10/16 00:57:20 collin 47 *** empty log message *** 48 49 Revision 1.6 2003/02/20 02:00:12 collin 50 *** empty log message *** 51 52 Revision 1.5 2003/02/17 21:47:52 collin 53 *** empty log message *** 54 55 Revision 1.4 2002/10/31 18:53:13 wgulland 56 Fix kernel panic when unloading family while reading ROMs 57 58 Revision 1.3 2002/10/18 23:29:44 collin 59 fix includes, fix cast which fails on new compiler 60 61 Revision 1.2 2002/09/25 00:27:24 niels 62 flip your world upside-down 63 64*/ 65 66// public 67#import <IOKit/firewire/IOFireWireBus.h> 68#import <IOKit/firewire/IOFireWireController.h> 69 70// private 71#import "IOFireWireMagicMatchingNub.h" 72#import "IOFireWireLocalNode.h" 73 74OSDefineMetaClassAndStructors(IOFireWireLocalNodeAux, IOFireWireNubAux); 75OSMetaClassDefineReservedUnused(IOFireWireLocalNodeAux, 0); 76OSMetaClassDefineReservedUnused(IOFireWireLocalNodeAux, 1); 77OSMetaClassDefineReservedUnused(IOFireWireLocalNodeAux, 2); 78OSMetaClassDefineReservedUnused(IOFireWireLocalNodeAux, 3); 79 80#pragma mark - 81 82// init 83// 84// 85 86bool IOFireWireLocalNodeAux::init( IOFireWireLocalNode * primary ) 87{ 88 bool success = true; // assume success 89 90 // init super 91 92 if( !IOFireWireNubAux::init( primary ) ) 93 success = false; 94 95 if( success ) 96 { 97 } 98 99 return success; 100} 101 102// free 103// 104// 105 106void IOFireWireLocalNodeAux::free() 107{ 108 IOFireWireNubAux::free(); 109} 110 111#pragma mark - 112 113OSDefineMetaClassAndStructors(IOFireWireLocalNode, IOFireWireNub) 114 115// init 116// 117// 118 119bool IOFireWireLocalNode::init(OSDictionary * propTable) 120{ 121 if(!IOFireWireNub::init(propTable)) 122 return false; 123 fMaxReadROMPackLog = 11; 124 fMaxReadPackLog = 11; 125 fMaxWritePackLog = 11; 126 127 fOpenClients = OSSet::withCapacity( 2 ); 128 if( fOpenClients == NULL ) 129 return false; 130 131 return true; 132} 133 134// createAuxiliary 135// 136// virtual method for creating auxiliary object. subclasses needing to subclass 137// the auxiliary object can override this. 138 139IOFireWireNubAux * IOFireWireLocalNode::createAuxiliary( void ) 140{ 141 IOFireWireLocalNodeAux * auxiliary; 142 143 auxiliary = OSTypeAlloc( IOFireWireLocalNodeAux ); 144 145 if( auxiliary != NULL && !auxiliary->init(this) ) 146 { 147 auxiliary->release(); 148 auxiliary = NULL; 149 } 150 151 return auxiliary; 152} 153 154// free 155// 156// 157 158void IOFireWireLocalNode::free() 159{ 160 if( fOpenClients != NULL ) 161 { 162 fOpenClients->release(); 163 fOpenClients = NULL; 164 } 165 166 if ( fControl ) 167 { 168 fControl->release(); 169 fControl = NULL; 170 } 171 172 IOFireWireNub::free(); 173} 174 175// attach 176// 177// 178 179bool IOFireWireLocalNode::attach(IOService * provider ) 180{ 181 assert(OSDynamicCast(IOFireWireController, provider)); 182 if( !IOFireWireNub::attach(provider)) 183 return (false); 184 fControl = (IOFireWireController *)provider; 185 fControl->retain(); 186 187 return(true); 188} 189 190// setNodeProperties 191// 192// 193 194void IOFireWireLocalNode::setNodeProperties(UInt32 gen, UInt16 nodeID, 195 UInt32 *selfIDs, int numSelfIDs, IOFWSpeed maxSpeed ) 196{ 197 OSObject *prop; 198 199 fLocalNodeID = fNodeID = nodeID; 200 fGeneration = gen; 201 202 prop = OSNumber::withNumber(nodeID, 16); 203 setProperty(gFireWireNodeID, prop); 204 prop->release(); 205 206 // Store selfIDs 207 prop = OSData::withBytes(selfIDs, numSelfIDs*sizeof(UInt32)); 208 setProperty(gFireWireSelfIDs, prop); 209 prop->release(); 210 211 prop = OSNumber::withNumber(maxSpeed, 32); 212 setProperty(gFireWireSpeed, prop); 213 prop->release(); 214} 215 216// message 217// 218// 219 220IOReturn IOFireWireLocalNode::message( UInt32 mess, IOService * provider, 221 void * argument ) 222{ 223 if( kIOFWMessagePowerStateChanged == mess ) 224 { 225 messageClients( mess ); 226 return kIOReturnSuccess; 227 } 228 229 if( kIOFWMessageTopologyChanged == mess ) 230 { 231 messageClients( mess ); 232 return kIOReturnSuccess; 233 } 234 235 return IOService::message(mess, provider, argument ); 236} 237 238// handleOpen 239// 240// 241 242bool IOFireWireLocalNode::handleOpen( IOService * forClient, 243 IOOptionBits options, 244 void * arg ) 245{ 246 bool ok = true ; 247 248 if ( fOpenClients->getCount() == 0) 249 ok = IOFireWireNub::handleOpen( this, 0, NULL ) ; 250 251 if ( ok ) 252 { 253 fOpenClients->setObject( forClient ); 254 } 255 256 return ok; 257} 258 259// handleClose 260// 261// 262 263void IOFireWireLocalNode::handleClose( IOService * forClient, 264 IOOptionBits options ) 265{ 266 if( fOpenClients->containsObject( forClient ) ) 267 { 268 fOpenClients->removeObject( forClient ); 269 270 if ( fOpenClients->getCount() == 0 ) 271 IOFireWireNub::handleClose( this, 0 ); 272 } 273} 274 275// handleIsOpen 276// 277// 278 279bool IOFireWireLocalNode::handleIsOpen( const IOService * forClient ) const 280{ 281 return fOpenClients->containsObject( forClient ); 282} 283 284// setProperties 285// 286// 287 288IOReturn IOFireWireLocalNode::setProperties( OSObject * properties ) 289{ 290 IOFireWireMagicMatchingNub *nub = NULL; 291 IOReturn ret = kIOReturnBadArgument; 292 bool doSummon = false; 293 OSIterator *localNodeChildIterator; 294 OSIterator *magicMatchingNubChildIterator; 295 OSObject *localNodeChild; 296 OSObject *matchingNubChild; 297 OSObject *desiredChild; 298 OSString *desiredChildString; 299 300 OSDictionary *dict = OSDynamicCast(OSDictionary, properties); 301 OSDictionary *summon; 302 if(!dict) 303 return kIOReturnUnsupported; 304 305 // Take the FireWire workloop lock, to prevent multi-thread issues 306 if (fControl) 307 fControl->closeGate(); 308 else 309 return kIOReturnNoDevice; 310 311 summon = OSDynamicCast(OSDictionary, dict->getObject("SummonNubExclusive")); 312 if(summon) 313 { 314 //IOLog("SummonNubExclusive\n"); 315 316 // For now, assume we'll need to summon the object 317 doSummon = true; 318 319 localNodeChildIterator = getClientIterator(); 320 if( localNodeChildIterator ) 321 { 322 while( (localNodeChild = localNodeChildIterator->getNextObject()) ) 323 { 324 //IOLog("found a localNodeChild\n"); 325 326 IOFireWireMagicMatchingNub * matchingNub = OSDynamicCast(IOFireWireMagicMatchingNub, localNodeChild); 327 if(matchingNub) 328 { 329 //IOLog("found a matchingNub\n"); 330 331 desiredChild = matchingNub->getProperty( "IODesiredChild" ); 332 if (desiredChild) 333 { 334 desiredChildString = OSDynamicCast(OSString,desiredChild); 335 if (desiredChildString) 336 { 337 //IOLog("desiredChildString = %s\n",desiredChildString->getCStringNoCopy()); 338 339 magicMatchingNubChildIterator = matchingNub->getClientIterator(); 340 if( magicMatchingNubChildIterator ) 341 { 342 while( (matchingNubChild = magicMatchingNubChildIterator->getNextObject()) ) 343 { 344 //IOLog("found a matchingNubChild\n"); 345 346 // See if this matching nub's child is of the IODesiredChild class 347 if (matchingNubChild->metaCast(desiredChildString)) 348 { 349 //IOLog("matchingNubChild is IODesiredChild\n"); 350 doSummon = false; 351 } 352 } 353 magicMatchingNubChildIterator->release(); 354 } 355 } 356 } 357 } 358 } 359 localNodeChildIterator->release(); 360 } 361 } 362 else 363 { 364 summon = OSDynamicCast(OSDictionary, dict->getObject("SummonNub")); 365 if(!summon) 366 ret = kIOReturnBadArgument; 367 else 368 doSummon = true; 369 } 370 371 if (doSummon) 372 { 373 do { 374 nub = OSTypeAlloc( IOFireWireMagicMatchingNub ); 375 if(!nub->init(summon)) 376 break; 377 if (!nub->attach(this)) 378 break; 379 nub->registerService(kIOServiceSynchronous); 380 // Kill nub if nothing matched 381 if(!nub->getClient()) { 382 nub->detach(this); 383 } 384 ret = kIOReturnSuccess; 385 } while (0); 386 if(nub) 387 nub->release(); 388 } 389 390 if (fControl) 391 fControl->openGate(); 392 393 return ret; 394} 395