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 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 24 * 25 * HISTORY 26 * 21 May 99 wgulland created. 27 * 28 */ 29 30#define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme 31#define DEBUGLOG kprintf 32#include <IOKit/assert.h> 33 34#include <IOKit/IOMessage.h> 35#include <IOKit/firewire/IOFireWireUnit.h> 36#include <IOKit/firewire/IOFireWireDevice.h> 37#include <IOKit/firewire/IOFireWireController.h> 38#include <IOKit/firewire/IOConfigDirectory.h> 39#import <IOKit/firewire/IOFWSimpleContiguousPhysicalAddressSpace.h> 40 41#include "FWDebugging.h" 42 43OSDefineMetaClassAndStructors(IOFireWireUnitAux, IOFireWireNubAux); 44OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 0); 45OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 1); 46OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 2); 47OSMetaClassDefineReservedUnused(IOFireWireUnitAux, 3); 48 49#pragma mark - 50 51// init 52// 53// 54 55bool IOFireWireUnitAux::init( IOFireWireUnit * primary ) 56{ 57 bool success = true; // assume success 58 59 // init super 60 61 if( !IOFireWireNubAux::init( primary ) ) 62 success = false; 63 64 if( success ) 65 { 66 } 67 68 return success; 69} 70 71// free 72// 73// 74 75void IOFireWireUnitAux::free() 76{ 77 IOFireWireNubAux::free(); 78} 79 80// isPhysicalAccessEnabled 81// 82// 83 84bool IOFireWireUnitAux::isPhysicalAccessEnabled( void ) 85{ 86 IOFireWireUnit * unit = (IOFireWireUnit*)fPrimary; 87 IOFireWireDevice * device = unit->fDevice; 88 return device->isPhysicalAccessEnabled(); 89} 90 91// createSimpleContiguousPhysicalAddressSpace 92// 93// 94 95IOFWSimpleContiguousPhysicalAddressSpace * IOFireWireUnitAux::createSimpleContiguousPhysicalAddressSpace( vm_size_t size, IODirection direction ) 96{ 97 IOFWSimpleContiguousPhysicalAddressSpace * space = IOFireWireNubAux::createSimpleContiguousPhysicalAddressSpace( size, direction ); 98 99 if( space != NULL ) 100 { 101 space->addTrustedNode( ((IOFireWireUnit*)fPrimary)->fDevice ); 102 } 103 104 return space; 105} 106 107// createSimplePhysicalAddressSpace 108// 109// 110 111IOFWSimplePhysicalAddressSpace * IOFireWireUnitAux::createSimplePhysicalAddressSpace( vm_size_t size, IODirection direction ) 112{ 113 IOFWSimplePhysicalAddressSpace * space = IOFireWireNubAux::createSimplePhysicalAddressSpace( size, direction ); 114 115 if( space != NULL ) 116 { 117 space->addTrustedNode( ((IOFireWireUnit*)fPrimary)->fDevice ); 118 } 119 120 return space; 121} 122 123#pragma mark - 124 125/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 126 127OSDefineMetaClassAndStructors(IOFireWireUnit, IOFireWireNub) 128OSMetaClassDefineReservedUnused(IOFireWireUnit, 0); 129OSMetaClassDefineReservedUnused(IOFireWireUnit, 1); 130 131#pragma mark - 132/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 133 134// init 135// 136// 137 138bool IOFireWireUnit::init( OSDictionary *propTable, IOConfigDirectory *directory ) 139{ 140 if(!IOFireWireNub::init(propTable)) 141 return false; 142 143 directory->retain(); 144 fDirectory = directory; 145 return true; 146} 147 148// createAuxiliary 149// 150// virtual method for creating auxiliary object. subclasses needing to subclass 151// the auxiliary object can override this. 152 153IOFireWireNubAux * IOFireWireUnit::createAuxiliary( void ) 154{ 155 IOFireWireUnitAux * auxiliary; 156 157 auxiliary = OSTypeAlloc( IOFireWireUnitAux ); 158 159 if( auxiliary != NULL && !auxiliary->init(this) ) 160 { 161 auxiliary->release(); 162 auxiliary = NULL; 163 } 164 165 return auxiliary; 166} 167 168// attach 169// 170// 171 172bool IOFireWireUnit::attach( IOService *provider ) 173{ 174 fDevice = OSDynamicCast(IOFireWireDevice, provider); 175 if(!fDevice) 176 return false; 177 fDevice->retain(); 178 if( !IOFireWireNub::attach(provider)) 179 return (false); 180 fControl = fDevice->getController(); 181 fControl->retain(); 182 fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID); 183 184 // check if this is a kprintf unit directory 185 OSNumber * spec_id_number = (OSNumber*)getProperty( gFireWireUnit_Spec_ID ); 186 OSNumber * sw_vers_number = (OSNumber*)getProperty( gFireWireUnit_SW_Version ); 187 if( spec_id_number && sw_vers_number ) 188 { 189 if( (spec_id_number->unsigned32BitValue() == kIOFWSpecID_AAPL) && 190 (sw_vers_number->unsigned32BitValue() == kIOFWSWVers_KPF) ) 191 { 192 // tell the controller to enter logging mode 193 fControl->enterLoggingMode(); 194 } 195 } 196 197 return true; 198} 199 200// free 201// 202// 203 204void IOFireWireUnit::free() 205{ 206 if( fDevice != NULL ) 207 { 208 fDevice->release(); 209 fDevice = NULL; 210 } 211 212 IOFireWireNub::free(); 213} 214 215// message 216// 217// 218 219IOReturn IOFireWireUnit::message( UInt32 mess, 220 IOService * provider, 221 void * argument ) 222{ 223 if(provider == fDevice && 224 (kIOMessageServiceIsRequestingClose == mess || 225 kIOFWMessageServiceIsRequestingClose == mess)) 226 { 227 fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID); 228 if( isOpen() ) 229 { 230 messageClients( mess ); 231 } 232 233 return kIOReturnSuccess; 234 } 235 236 // Propagate bus reset start/end messages 237 if(provider == fDevice && 238 (kIOMessageServiceIsResumed == mess || 239 kIOMessageServiceIsSuspended == mess)) 240 { 241 fDevice->getNodeIDGeneration(fGeneration, fNodeID, fLocalNodeID); 242 messageClients( mess ); 243 return kIOReturnSuccess; 244 } 245 246 if( kIOFWMessagePowerStateChanged == mess ) 247 { 248 messageClients( mess ); 249 return kIOReturnSuccess; 250 } 251 252 if( kIOFWMessageTopologyChanged == mess ) 253 { 254 messageClients( mess ); 255 return kIOReturnSuccess; 256 } 257 258 return IOService::message(mess, provider, argument ); 259} 260 261/** 262 ** Matching methods 263 **/ 264 265// matchPropertyTable 266// 267// 268 269bool IOFireWireUnit::matchPropertyTable( OSDictionary * table ) 270{ 271 // 272 // If the service object wishes to compare some of its properties in its 273 // property table against the supplied matching dictionary, 274 // it should do so in this method and return truth on success. 275 // 276 if (!IOFireWireNub::matchPropertyTable(table)) return false; 277 278 // We return success if the following expression is true -- individual 279 // comparisions evaluate to truth if the named property is not present 280 // in the supplied matching dictionary. 281 282 bool res = compareProperty(table, gFireWireUnit_Spec_ID) && 283 compareProperty(table, gFireWireUnit_SW_Version) && 284 compareProperty(table, gFireWireVendor_ID) && 285 compareProperty(table, gFireWire_GUID); 286 return res; 287} 288 289#pragma mark - 290 291///////////////////////////////////////////////////////////////////////////// 292// open / close 293// 294 295// handleOpen 296// 297// 298 299bool IOFireWireUnit::handleOpen( IOService * forClient, 300 IOOptionBits options, 301 void * arg ) 302{ 303 // arbitration lock is held 304 305 bool success = true; 306 307 if( isOpen() ) 308 { 309 success = false; 310 } 311 312 if( success ) 313 { 314 success = fDevice->open( this, options, arg ); 315 } 316 317 if( success ) 318 { 319 success = IOFireWireNub::handleOpen( forClient, options, arg ); 320 } 321 322 return success; 323} 324 325// handleClose 326// 327// 328 329void IOFireWireUnit::handleClose( IOService * forClient, 330 IOOptionBits options ) 331{ 332 // arbitration lock is held 333 334 // retain since device->close() could start a termination thread 335 336 retain(); 337 338 IOFireWireNub::handleClose(forClient, options); 339 fDevice->close( this, options ); 340 341 if( getTerminationState() == kNeedsTermination ) 342 { 343 setTerminationState( kTerminated ); 344 345 retain(); // will be released in thread function 346 347 thread_t thread; 348 if( kernel_thread_start((thread_continue_t)IOFireWireUnit::terminateUnitThreadFunc, this, &thread) == KERN_SUCCESS ) 349 { 350 thread_deallocate(thread); 351 } 352 } 353 354 release(); 355} 356 357// terminateUnit 358// 359// 360 361void IOFireWireUnit::terminateUnit( void ) 362{ 363 // synchronize with the open close routines 364 365 lockForArbitration(); 366 367 // retain since we could start a termination thread 368 retain(); 369 370 if( isOpen() ) 371 { 372 if( getTerminationState() == kNotTerminated ) 373 { 374 setTerminationState( kNeedsTermination ); 375 376 // send our custom requesting close message 377 378 messageClients( kIOFWMessageServiceIsRequestingClose ); 379 } 380 } 381 else 382 { 383 TerminationState state = getTerminationState(); 384 385 // if we're closed, we shouldn't be in the kNeedsTermination state 386 387 FWKLOGASSERT( state != kNeedsTermination ); 388 389 if( state == kNotTerminated ) 390 { 391 setTerminationState( kTerminated ); 392 393 retain(); // will be released in thread function 394 395 thread_t thread; 396 if( kernel_thread_start((thread_continue_t)IOFireWireUnit::terminateUnitThreadFunc, this, &thread) == KERN_SUCCESS ) 397 { 398 thread_deallocate(thread); 399 } 400 } 401 } 402 403 release(); 404 405 unlockForArbitration(); 406} 407 408// terminateUnitThreadFunc 409// 410// 411 412void IOFireWireUnit::terminateUnitThreadFunc( void * refcon ) 413{ 414 IOFireWireUnit *me = (IOFireWireUnit *)refcon; 415 416 FWKLOG(( "IOFireWireUnit::terminateUnitThreadFunc - entered terminate unit = 0x%08lx\n", me )); 417 418 me->fControl->closeGate(); 419 420 // synchronize with open and close routines 421 422 me->lockForArbitration(); 423 424 if( ( me->getTerminationState() == kTerminated) && 425 !me->isInactive() && !me->isOpen() ) 426 { 427 // release arbitration lock before terminating. 428 // this leaves a small hole of someone opening the device right here, 429 // which shouldn't be too bad - the client will just get terminated too. 430 431 me->unlockForArbitration(); 432 433 me->terminate(); 434 435 } 436 else 437 { 438 me->unlockForArbitration(); 439 } 440 441 me->fControl->openGate(); 442 443 me->release(); // retained when thread was spawned 444 445 FWKLOG(( "IOFireWireUnit::terminateUnitThreadFunc - exiting terminate unit = 0x%08lx\n", me )); 446} 447 448// setConfigDirectory 449// 450// 451 452IOReturn IOFireWireUnit::setConfigDirectory( IOConfigDirectory * directory ) 453{ 454 // arbitration lock is held 455 456 IOReturn status = kIOReturnSuccess; 457 458 TerminationState state = getTerminationState(); 459 460 FWKLOGASSERT( state != kTerminated ); 461 462 if( state == kNeedsTermination ) 463 { 464 setTerminationState( kNotTerminated ); 465 } 466 467 status = IOFireWireNub::setConfigDirectory( directory ); 468 469 return status; 470} 471 472#pragma mark - 473 474///////////////////////////////////////////////////////////////////////////// 475// node flags 476// 477 478// setNodeFlags 479// 480// 481 482void IOFireWireUnit::setNodeFlags( UInt32 flags ) 483{ 484 if( fDevice ) 485 fDevice->setNodeFlags( flags ); 486} 487 488// clearNodeFlags 489// 490// 491 492void IOFireWireUnit::clearNodeFlags( UInt32 flags ) 493{ 494 if( fDevice ) 495 fDevice->clearNodeFlags( flags ); 496} 497 498// getNodeFlags 499// 500// 501 502UInt32 IOFireWireUnit::getNodeFlags( void ) 503{ 504 if( fDevice ) 505 return fDevice->getNodeFlags(); 506 else 507 return 0; 508} 509 510// setMaxSpeed 511// 512// 513 514void IOFireWireUnit::setMaxSpeed( IOFWSpeed speed ) 515{ 516 if( fDevice ) 517 fDevice->setMaxSpeed( speed ); 518} 519 520#pragma mark - 521 522///////////////////////////////////////////////////////////////////////////// 523// address spaces 524// 525 526/* 527 * Create local FireWire address spaces for the device to access 528 */ 529 530// createPhysicalAddressSpace 531// 532// 533 534IOFWPhysicalAddressSpace * IOFireWireUnit::createPhysicalAddressSpace( IOMemoryDescriptor *mem ) 535{ 536 IOFWPhysicalAddressSpace * space = fControl->createPhysicalAddressSpace(mem); 537 538 if( space != NULL ) 539 { 540 space->addTrustedNode( fDevice ); 541 } 542 543 return space; 544} 545 546// createPseudoAddressSpace 547// 548// 549 550IOFWPseudoAddressSpace * IOFireWireUnit::createPseudoAddressSpace( FWAddress * addr, 551 UInt32 len, 552 FWReadCallback reader, 553 FWWriteCallback writer, 554 void * refcon ) 555{ 556 IOFWPseudoAddressSpace * space = fControl->createPseudoAddressSpace(addr, len, reader, writer, refcon); 557 558 if( space != NULL ) 559 { 560 space->addTrustedNode( fDevice ); 561 } 562 563 return space; 564 565} 566