1/* 2 * Copyright (c) 1998-2001 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#include "IOFireWireIPUnit.h" 23#include "IOFireWireIP.h" 24#include <IOKit/IOMessage.h> 25#include <IOKit/firewire/IOFireWireBus.h> 26#include <IOKit/firewire/IOFWAddressSpace.h> 27#include <IOKit/firewire/IOConfigDirectory.h> 28#include "IOFWIPDefinitions.h" 29 30OSDefineMetaClassAndStructors(IOFireWireIPUnit, IOService) 31OSMetaClassDefineReservedUnused(IOFireWireIPUnit, 0); 32OSMetaClassDefineReservedUnused(IOFireWireIPUnit, 1); 33OSMetaClassDefineReservedUnused(IOFireWireIPUnit, 2); 34OSMetaClassDefineReservedUnused(IOFireWireIPUnit, 3); 35 36 37bool IOFireWireIPUnit::start(IOService *provider) 38{ 39 fIPLocalNode = NULL; 40 fFWBusInterface = NULL; 41 fStarted = false; 42 43 fDevice = OSDynamicCast(IOFireWireNub, provider); 44 45 if ( not fDevice ) 46 return false; 47 48 fDrb = NULL; 49 50 if ( not IOService::start(provider)) 51 return (false); 52 53 IOFireWireController *control = fDevice->getController(); 54 if ( not control ) 55 return (false); 56 57 if ( not configureFWBusInterface(control) ) 58 { 59 IOLog("IOFireWireIPUnit - configureFWBusInterface failed \n"); 60 return (false); 61 } 62 63 UWIDE eui64; 64 65 CSRNodeUniqueID fwuid = fDevice->getUniqueID(); 66 67 eui64.hi = (UInt32)(fwuid >> 32); 68 eui64.lo = (UInt32)(fwuid & 0xffffffff); 69 70 fDrb = fFWBusInterface->initDRBwithDevice(eui64, fDevice, false); 71 72 if ( not fDrb ) 73 { 74 IOLog("IOFireWireIPUnit - initDRBwithDevice failed \n"); 75 return (false); 76 } 77 78 fDrb->retain(); 79 80 if ( fFWBusInterface->updateARBwithDevice(fDevice, eui64) == NULL ) 81 { 82 IOLog("IOFireWireIPUnit - updateARBwithDevice failed \n"); 83 return (false); 84 } 85 86 fFWBusInterface->fwIPUnitAttach(); 87 88 fTerminateNotifier = IOService::addMatchingNotification(gIOTerminatedNotification, 89 serviceMatching("IOFWIPBusInterface"), 90 &busInterfaceTerminate, this, (void*)fFWBusInterface, 0); 91 92 fStarted = true; 93 94 registerService(); 95 96 return true; 97} 98 99bool IOFireWireIPUnit::busInterfaceTerminate(void *target, void *refCon, IOService *newService, IONotifier * notifier) 100{ 101 if(target == NULL || newService == NULL) 102 return false; 103 104 IOFireWireIPUnit *unit = OSDynamicCast(IOFireWireIPUnit, (IOService *)target); 105 106 if ( not unit ) 107 return false; 108 109 if ( unit->fStarted ) 110 { 111 if ( unit->fFWBusInterface != refCon) 112 return false; 113 114 unit->terminate(); 115 } 116 117 return true; 118} 119 120bool IOFireWireIPUnit::finalize(IOOptionBits options) 121{ 122 if ( fStarted ) 123 { 124 if ( fTerminateNotifier != NULL ) 125 fTerminateNotifier->remove(); 126 127 fTerminateNotifier = NULL; 128 129 if ( fFWBusInterface ) 130 fFWBusInterface->fwIPUnitTerminate(); 131 132 if ( fDrb ) 133 { 134 fFWBusInterface->releaseARB(fDrb->fwaddr); 135 136 fFWBusInterface->releaseDRB(fDrb->fwaddr); 137 138 fDrb->release(); 139 } 140 141 fDrb = NULL; 142 143 if ( fFWBusInterface ) 144 { 145 fFWBusInterface->release(); 146 147 if ( fFWBusInterface->getUnitCount() == 0 ) 148 fFWBusInterface->terminate(); 149 } 150 151 fFWBusInterface = NULL; 152 153 fDevice = NULL; 154 } 155 fStarted = false; 156 157 return IOService::finalize(options); 158} 159 160void IOFireWireIPUnit::free(void) 161{ 162 IOService::free(); 163} 164 165IOReturn IOFireWireIPUnit::message(UInt32 type, IOService *provider, void *argument) 166{ 167 IOReturn res = kIOReturnSuccess; 168 169 switch (type) 170 { 171 case kIOMessageServiceIsTerminated: 172 case kIOMessageServiceIsRequestingClose: 173 case kIOMessageServiceIsSuspended: 174 break; 175 176 case kIOMessageServiceIsResumed: 177 if( fStarted ) 178 { 179 fIPLocalNode->closeIPoFWGate(); 180 181 updateDrb(); 182 183 fIPLocalNode->openIPoFWGate(); 184 } 185 break; 186 187 default: // default the action to return kIOReturnUnsupported 188 res = kIOReturnUnsupported; 189 break; 190 } 191 192 return res; 193} 194 195/*! 196 @function updateDrb 197 @abstract Updates the device reference block in the FireWire IP unit 198*/ 199void IOFireWireIPUnit::updateDrb() 200{ 201 if(fDrb) 202 { 203 fDrb->maxSpeed = fDevice->FWSpeed(); 204 fDrb->maxPayload = fDevice->maxPackLog(true); 205 fFWBusInterface->updateBroadcastValues(true); 206 } 207} 208 209bool IOFireWireIPUnit::configureFWBusInterface(IOFireWireController *controller) 210{ 211 bool status = false; 212 213 fIPLocalNode = getIPNode(controller); 214 215 if( fIPLocalNode ) 216 { 217 fIPLocalNode->retain(); 218 219 if ( fIPLocalNode->clientStarting() == true ) 220 { 221 OSDictionary *matchingTable; 222 223 matchingTable = serviceMatching("IOFWIPBusInterface"); 224 225 if ( matchingTable ) 226 { 227 OSObject *prop = fIPLocalNode->getProperty(gFireWire_GUID); 228 if( prop ) 229 matchingTable->setObject(gFireWire_GUID, prop); 230 } 231 232 waitForService( matchingTable ); 233 } 234 235 fFWBusInterface = getIPTransmitInterface(fIPLocalNode) ; 236 237 status = true; 238 if( fFWBusInterface == NULL ) 239 fFWBusInterface = new IOFWIPBusInterface; 240 241 status = fFWBusInterface->init(fIPLocalNode); 242 if( status ) 243 { 244 fFWBusInterface->retain(); 245 } 246 else 247 { 248 fFWBusInterface->release(); 249 fFWBusInterface = 0; 250 } 251 252 fIPLocalNode->release(); 253 } 254 255 return status; 256} 257 258IOFWIPBusInterface *IOFireWireIPUnit::getIPTransmitInterface(IOFireWireIP *fIPLocalNode) 259{ 260 OSIterator *childIterator = fIPLocalNode->getChildIterator(gIOServicePlane); 261 262 263 IORegistryEntry *child = NULL; 264 if(childIterator) 265 { 266 while((child = (IORegistryEntry*)childIterator->getNextObject())) 267 { 268 if(strncmp(child->getName(gIOServicePlane), "IOFWIPBusInterface", strlen("IOFWIPBusInterface")) == 0) 269 break; 270 } 271 childIterator->release(); 272 childIterator = NULL; 273 } 274 275 IOFWIPBusInterface *fwBusInterface = NULL; 276 277 if(child) 278 fwBusInterface = OSDynamicCast(IOFWIPBusInterface, child); 279 280 return fwBusInterface; 281} 282 283IOFireWireIP *IOFireWireIPUnit::getIPNode(IOFireWireController *control) 284{ 285 OSIterator *iterator = getMatchingServices( serviceMatching("IOFireWireLocalNode") ); 286 287 IOFireWireNub *localNode = NULL; 288 289 if( iterator ) 290 { 291 IOService * obj = NULL; 292 while((obj = (IOService*)iterator->getNextObject())) 293 { 294 localNode = OSDynamicCast(IOFireWireNub, obj); 295 if(localNode) 296 { 297 if(localNode->getController() == control) 298 break; 299 else 300 localNode = NULL; 301 } 302 } 303 iterator->release(); 304 iterator = NULL; 305 } 306 307 IOFireWireIP *fwIP = NULL; 308 309 if( localNode ) 310 { 311 OSDictionary *matchingTable; 312 313 matchingTable = serviceMatching("IOFireWireIP"); 314 315 if ( matchingTable ) 316 { 317 OSObject *prop = localNode->getProperty(gFireWire_GUID); 318 if( prop ) 319 matchingTable->setObject(gFireWire_GUID, prop); 320 } 321 322 fwIP = OSDynamicCast(IOFireWireIP, waitForService( matchingTable )); 323 } 324 325 return fwIP; 326} 327 328