|
|
1.1 ! root 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: * 27 April 99 wgulland created. ! 27: * ! 28: */ ! 29: ! 30: #include <IOKit/assert.h> ! 31: ! 32: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme ! 33: #define DEBUGLOG kprintf ! 34: ! 35: #include <IOKit/IOWorkLoop.h> ! 36: #include <IOKit/IOTimerEventSource.h> ! 37: #include <IOKit/IOKitKeys.h> ! 38: ! 39: #include <IOKit/firewire/IOFireWireController.h> ! 40: #include <IOKit/firewire/IOFWCommand.h> ! 41: #include <IOKit/firewire/IOFireWireDevice.h> ! 42: #include <IOKit/firewire/IOFWDCLProgram.h> ! 43: #include <IOKit/firewire/IOFWLocalIsochPort.h> ! 44: #include <IOKit/firewire/IOFWAddressSpace.h> ! 45: #include <IOKit/IOBufferMemoryDescriptor.h> ! 46: ! 47: #define kDevicePruneDelay 1000 // 1000 milliseconds ! 48: ! 49: #define FWAddressToID(addr) (addr & 63) ! 50: ! 51: const OSSymbol *gFireWireROM; ! 52: const OSSymbol *gFireWireNodeID; ! 53: const OSSymbol *gFireWireSelfIDs; ! 54: const OSSymbol *gFireWireUnit_Spec_ID; ! 55: const OSSymbol *gFireWireUnit_SW_Version; ! 56: const OSSymbol *gFireWireVendor_ID; ! 57: const OSSymbol *gFireWire_GUID; ! 58: const OSSymbol *gFireWireSpeed; ! 59: ! 60: const IORegistryPlane * IOFireWireController::gIOFireWirePlane = NULL; ! 61: ! 62: enum ReadROMState { ! 63: kReadROMSize, ! 64: kReadingROM ! 65: }; ! 66: ! 67: struct NodeScan { ! 68: IOFireWireController * fControl; ! 69: FWAddress fAddr; ! 70: UInt32 * fBuf; ! 71: UInt32 * fSelfIDs; ! 72: int fNumSelfIDs; ! 73: ReadROMState fState; ! 74: IOFWReadQuadCommand * fCmd; ! 75: UInt32 fROMHdr; ! 76: int fROMSize; ! 77: int fRead; ! 78: }; ! 79: ! 80: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 81: //Utility functions ! 82: ! 83: #define super IOFireWireBus ! 84: ! 85: OSDefineMetaClass( IOFireWireController, IOFireWireBus ) ! 86: OSDefineAbstractStructors(IOFireWireController, IOFireWireBus) ! 87: ! 88: static void doneReset(void *refcon, IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd) ! 89: { ! 90: fwCmd->release(); ! 91: } ! 92: ! 93: void IOFireWireController::readROMGlue(void *refcon, IOReturn status, ! 94: IOFireWireNub *device, IOFWCommand *fwCmd) ! 95: { ! 96: NodeScan *scan = (NodeScan *)refcon; ! 97: scan->fControl->readDeviceROM(scan, status); ! 98: } ! 99: ! 100: IOReturn IOFireWireController::execCommand(OSObject * obj, void *field0, ! 101: void *field1, void *field2, void *field3) ! 102: { ! 103: // obj is the IOFireWireController, if we need that ! 104: ! 105: IOFWCommand *cmd = (IOFWCommand *)field0; ! 106: //kprintf("Executing command 0x%x\n", cmd); ! 107: return cmd->execute(); ! 108: } ! 109: ! 110: void IOFireWireController::clockTick(OSObject *obj, IOTimerEventSource *src) ! 111: { ! 112: IOFireWireController *me = (IOFireWireController *)obj; ! 113: ! 114: me->pruneDevices(); ! 115: } ! 116: IOWorkLoop * IOFireWireController::createWorkLoop() ! 117: { ! 118: IOWorkLoop * wrkLoop; ! 119: ! 120: wrkLoop = new IOWorkLoop; ! 121: if ( wrkLoop == NULL ) { ! 122: return NULL; ! 123: } ! 124: ! 125: if ( wrkLoop->init() != true ) { ! 126: return NULL; ! 127: } ! 128: ! 129: return wrkLoop; ! 130: } ! 131: ! 132: bool IOFireWireController::init(OSDictionary * dict) ! 133: { ! 134: if(!super::init(dict)) ! 135: return false; ! 136: ! 137: // Create firewire symbols. ! 138: gFireWireROM = OSSymbol::withCString("FireWire Device ROM"); ! 139: gFireWireNodeID = OSSymbol::withCString("FireWire Node ID"); ! 140: gFireWireSelfIDs = OSSymbol::withCString("FireWire Self IDs"); ! 141: gFireWireUnit_Spec_ID = OSSymbol::withCString("Unit_Spec_ID"); ! 142: gFireWireUnit_SW_Version = OSSymbol::withCString("Unit_SW_Version"); ! 143: gFireWireVendor_ID = OSSymbol::withCString("Vendor_ID"); ! 144: gFireWire_GUID = OSSymbol::withCString("GUID"); ! 145: gFireWireSpeed = OSSymbol::withCString("FireWire Speed"); ! 146: ! 147: if(NULL == gIOFireWirePlane) { ! 148: gIOFireWirePlane = IORegistryEntry::makePlane( kIOFireWirePlane ); ! 149: } ! 150: ! 151: fLocalAddresses = OSSet::withCapacity(3); // Local ROM + CSR registers + SBP-2 ORBs ! 152: if(fLocalAddresses) ! 153: fSpaceIterator = OSCollectionIterator::withCollection(fLocalAddresses); ! 154: ! 155: fAllocatedChannels = OSSet::withCapacity(1); // DV channel. ! 156: if(fAllocatedChannels) ! 157: fAllocChannelIterator = OSCollectionIterator::withCollection(fAllocatedChannels); ! 158: ! 159: fLastTrans = kMaxPendingTransfers-1; ! 160: fTransAllocLock = IOLockAlloc(); ! 161: fChannelLock = IOLockAlloc(); ! 162: ! 163: return (gFireWireROM != NULL && gFireWireNodeID != NULL && ! 164: fChannelLock != NULL && fTransAllocLock != NULL && ! 165: gFireWireUnit_Spec_ID != NULL && gFireWireUnit_SW_Version != NULL && ! 166: fLocalAddresses != NULL && fSpaceIterator != NULL && ! 167: fAllocatedChannels != NULL && fAllocChannelIterator != NULL); ! 168: } ! 169: ! 170: bool IOFireWireController::startWorkLoop() ! 171: { ! 172: OSData *rom; ! 173: UInt16 crc16; ! 174: IOReturn status; ! 175: CSRROMEntryID csrROMRootEntryID = kInvalidCSRROMEntryID; ! 176: CSRROMEntryID csrROMEntryID = kInvalidCSRROMEntryID; ! 177: UInt32 immediateEntry; ! 178: ! 179: ! 180: kprintf("Local GUID = 0x%x:0x%x\n", (UInt32)(fUniqueID >> 32), (UInt32)(fUniqueID & 0xffffffff)); ! 181: ! 182: // Build local device ROM ! 183: rom = OSData::withCapacity(20); // smallest possible real ROM ! 184: if(!rom) ! 185: return false; ! 186: ! 187: // Allocate address space for Configuration ROM and fill in Bus Info ! 188: // block. ! 189: fROMHeader[1] = kFWBIBBusName; ! 190: fROMHeader[2] = ! 191: kFWBIBIrmc | kFWBIBCmc | kFWBIBIsc | (8 << kFWBIBMaxRecPhase); ! 192: fROMHeader[3] = fUniqueID >> 32; ! 193: fROMHeader[4] = fUniqueID & 0xffffffff; ! 194: ! 195: crc16 = FWComputeCRC16 (&fROMHeader[1], 4); ! 196: fROMHeader[0] = 0x04040000 | crc16; ! 197: ! 198: rom->appendBytes(fROMHeader, 20); ! 199: setProperty(gFireWireROM, rom); ! 200: rom->release(); // XXX -- svail: added. ! 201: ! 202: // Create root directory in FWIM data.//zzz should we have one for each FWIM or just one??? ! 203: fCSRROMRootDirectory.csrROMEntryData.pParentCSRROMEntryData = NULL; ! 204: fCSRROMRootDirectory.csrROMEntryData.pPrevCSRROMEntryData = NULL; ! 205: fCSRROMRootDirectory.csrROMEntryData.pNextCSRROMEntryData = NULL; ! 206: fCSRROMRootDirectory.csrROMEntryData.entryType = ! 207: kDirectoryCSRROMEntryType; ! 208: //fCSRROMRootDirectory->csrROMEntryData.fwimID = fwimID; ! 209: //fCSRROMRootDirectory.csrROMEntryData.pEntryLocation = NULL; ! 210: fCSRROMRootDirectory.csrROMBasicEntryData.keyValue = 0; ! 211: fCSRROMRootDirectory.pChildCSRROMEntryData = NULL; ! 212: fCSRROMRootDirectory.numChildren = 0; ! 213: ! 214: status = CSRROMGetRootDirectory (&csrROMRootEntryID); ! 215: ! 216: // Set our CSR ROM generation. ! 217: if (status == kIOReturnSuccess) { ! 218: immediateEntry = 0; ! 219: status = CSRROMCreateEntry (csrROMRootEntryID, ! 220: &csrROMEntryID, ! 221: kImmediateCSRROMEntryType, ! 222: kCSRGenerationKey, ! 223: (UInt8 *) &immediateEntry, ! 224: 3); ! 225: } ! 226: ! 227: // Set our module vendor ID. ! 228: if (status == kIOReturnSuccess) { ! 229: immediateEntry = 0x00A040 << 8; ! 230: status = CSRROMCreateEntry (csrROMRootEntryID, ! 231: &csrROMEntryID, ! 232: kImmediateCSRROMEntryType, ! 233: kCSRModuleVendorIDKey, ! 234: (UInt8 *) &immediateEntry, ! 235: 3); ! 236: } ! 237: ! 238: // Set our capabilities. ! 239: if (status == kIOReturnSuccess) { ! 240: immediateEntry = 0x000083C0 << 8;//zzz need real values. ! 241: status = CSRROMCreateEntry (csrROMRootEntryID, ! 242: &csrROMEntryID, ! 243: kImmediateCSRROMEntryType, ! 244: kCSRNodeCapabilitiesKey, ! 245: (UInt8 *) &immediateEntry, ! 246: 3); ! 247: } ! 248: ! 249: // Set our node unique ID. ! 250: if (status == kIOReturnSuccess) { ! 251: status = CSRROMCreateEntry (csrROMRootEntryID, ! 252: &csrROMEntryID, ! 253: kLeafCSRROMEntryType, ! 254: kCSRNodeUniqueIdKey, ! 255: &fUniqueID, ! 256: 8); ! 257: } ! 258: ! 259: // Will instantiate at end (causes a bus reset). ! 260: // Clean up ROM entry references ! 261: if (csrROMRootEntryID != kInvalidCSRROMEntryID) ! 262: FWCSRROMDisposeEntryID (csrROMRootEntryID); ! 263: ! 264: if (csrROMEntryID != kInvalidCSRROMEntryID) ! 265: FWCSRROMDisposeEntryID (csrROMEntryID); ! 266: ! 267: // Create command gate, start probing etc. ! 268: fGate = IOCommandGate::commandGate(this, execCommand); ! 269: if(!fGate) ! 270: return false; ! 271: ! 272: // Create Timer Event source ! 273: fTimer = IOTimerEventSource::timerEventSource(this, clockTick); ! 274: if(!fTimer) ! 275: return false; ! 276: ! 277: fWorkLoop = createWorkLoop(); ! 278: fWorkLoop->addEventSource(fGate); ! 279: fWorkLoop->addEventSource(fTimer); ! 280: ! 281: ! 282: IOFWUpdateROM *reset = new IOFWUpdateROM; ! 283: if(reset) { ! 284: if(reset->initWithController(this, doneReset, NULL)) ! 285: reset->submit(); ! 286: else { ! 287: reset->release(); ! 288: reset = NULL; ! 289: } ! 290: } ! 291: ! 292: return fWorkLoop != NULL && reset != NULL; ! 293: } ! 294: ! 295: IOWorkLoop *IOFireWireController::getWorkLoop() const ! 296: { ! 297: return fWorkLoop; ! 298: } ! 299: ! 300: AsyncPendingTrans *IOFireWireController::allocTrans(bool sleepOK) ! 301: { ! 302: unsigned int i; ! 303: unsigned int tran; ! 304: ! 305: do { ! 306: IOTakeLock(fTransAllocLock); ! 307: tran = fLastTrans; ! 308: for(i=0; i<kMaxPendingTransfers; i++) { ! 309: AsyncPendingTrans *t; ! 310: tran++; ! 311: if(tran >= kMaxPendingTransfers) ! 312: tran = 0; ! 313: t = &fTrans[tran]; ! 314: if(!t->fInUse) { ! 315: t->fHandler = NULL; ! 316: t->fInUse = true; ! 317: t->fTCode = tran; ! 318: fLastTrans = tran; ! 319: IOUnlock(fTransAllocLock); ! 320: return t; ! 321: } ! 322: } ! 323: IOUnlock(fTransAllocLock); ! 324: IOLog("Out of FireWire read request codes!\n"); ! 325: if(!sleepOK) ! 326: break; ! 327: IOSleep(10); ! 328: } while (true); ! 329: return NULL; ! 330: } ! 331: ! 332: void IOFireWireController::freeTrans(AsyncPendingTrans *trans) ! 333: { ! 334: // No lock needed - can't have two users of a tcode. ! 335: trans->fInUse = false; ! 336: } ! 337: ! 338: ! 339: void IOFireWireController::readDeviceROM(NodeScan *scan, IOReturn status) ! 340: { ! 341: bool done = true; ! 342: if(status != kIOReturnSuccess) { ! 343: // If status isn't bus reset, make a dummy registry entry. ! 344: if(status == kIOFireWireBusReset) ! 345: return; ! 346: ! 347: OSDictionary *propTable; ! 348: UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID); ! 349: OSObject * prop; ! 350: propTable = OSDictionary::withCapacity(3); ! 351: prop = OSNumber::withNumber(scan->fAddr.nodeID, 16); ! 352: propTable->setObject(gFireWireNodeID, prop); ! 353: prop->release(); ! 354: ! 355: prop = OSNumber::withNumber((scan->fSelfIDs[0] & kFWSelfID0SP) >> kFWSelfID0SPPhase, 32); ! 356: propTable->setObject(gFireWireSpeed, prop); ! 357: prop->release(); ! 358: ! 359: prop = OSData::withBytes(scan->fSelfIDs, scan->fNumSelfIDs*sizeof(UInt32)); ! 360: propTable->setObject(gFireWireSelfIDs, prop); ! 361: prop->release(); ! 362: ! 363: IORegistryEntry * newPhy; ! 364: newPhy = new IORegistryEntry; ! 365: if(newPhy) { ! 366: if(!newPhy->init(propTable)) { ! 367: newPhy->release(); ! 368: newPhy = NULL; ! 369: } ! 370: } ! 371: fNodes[nodeID] = newPhy; ! 372: if(propTable) ! 373: propTable->release(); ! 374: fNumROMReads--; ! 375: if(fNumROMReads == 0) { ! 376: fTimer->enable(); ! 377: fTimer->setTimeoutMS(kDevicePruneDelay); // One second ! 378: } ! 379: ! 380: if(scan->fBuf) ! 381: IOFree(scan->fBuf, scan->fROMSize); ! 382: scan->fCmd->release(); ! 383: IOFree(scan, sizeof(*scan)); ! 384: return; ! 385: } ! 386: ! 387: if(scan->fState == kReadROMSize) { ! 388: if( ((scan->fROMHdr & kCSRBusInfoBlockLength) >> kCSRBusInfoBlockLengthPhase) == 1) { ! 389: // Minimal ROM ! 390: scan->fROMSize = 4; ! 391: done = true; ! 392: } ! 393: else { ! 394: scan->fROMSize = 4*((scan->fROMHdr & kCSRROMCRCLength) >> kCSRROMCRCLengthPhase) + 4; ! 395: scan->fBuf = (UInt32 *)IOMalloc(scan->fROMSize); ! 396: *scan->fBuf = scan->fROMHdr; ! 397: scan->fRead = 4; ! 398: if(scan->fROMSize > 4) { ! 399: scan->fState = kReadingROM; ! 400: scan->fAddr.addressLo = kCSRROMBaseAddress+4; ! 401: scan->fCmd->reinit(scan->fAddr, scan->fBuf+1, scan->fROMSize/4-1, ! 402: &readROMGlue, scan, true); ! 403: scan->fCmd->execute(); ! 404: done = false; ! 405: } ! 406: else ! 407: done = true; ! 408: } ! 409: } ! 410: if(done) { ! 411: // Check if node exists, if not create it ! 412: #if (DEBUGGING_LEVEL > 0) ! 413: DEBUGLOG("Finished reading ROM for node 0x%x\n", scan->fNodeID); ! 414: #endif ! 415: OSDictionary * propTable = NULL; ! 416: IOFireWireDevice * newDevice = NULL; ! 417: OSData * rom = NULL; ! 418: do { ! 419: CSRNodeUniqueID guid; ! 420: OSIterator *childIterator; ! 421: if(scan->fROMSize >= 20) ! 422: guid = *(CSRNodeUniqueID *)(scan->fBuf+3); ! 423: else ! 424: guid = scan->fROMHdr; // Best we can do. ! 425: if(scan->fROMSize == 4) ! 426: rom = OSData::withBytes(&scan->fROMHdr, 4); ! 427: else ! 428: rom = OSData::withBytes(scan->fBuf, scan->fROMSize); ! 429: childIterator = getClientIterator(); ! 430: if( childIterator) { ! 431: IOFireWireDevice * found; ! 432: while( (found = (IOFireWireDevice *) childIterator->getNextObject())) { ! 433: if(found->fUniqueID == guid) { ! 434: newDevice = found; ! 435: break; ! 436: } ! 437: } ! 438: childIterator->release(); ! 439: } ! 440: ! 441: if(newDevice) { ! 442: // Just update device properties. ! 443: newDevice->setNodeROM(fBusGeneration, scan->fAddr.nodeID, fLocalNodeID, ! 444: rom, scan->fSelfIDs, scan->fNumSelfIDs); ! 445: newDevice->retain(); // match release, since not newly created. ! 446: } ! 447: else { ! 448: OSObject * prop; ! 449: propTable = OSDictionary::withCapacity(6); ! 450: if (!propTable) ! 451: continue; ! 452: ! 453: prop = OSNumber::withNumber(guid, 64); ! 454: propTable->setObject(gFireWire_GUID, prop); ! 455: prop->release(); ! 456: prop = OSNumber::withNumber((scan->fSelfIDs[0] & kFWSelfID0SP) >> kFWSelfID0SPPhase, 32); ! 457: propTable->setObject(gFireWireSpeed, prop); ! 458: prop->release(); ! 459: newDevice = createDeviceNub(propTable); ! 460: if (!newDevice) ! 461: continue; ! 462: propTable->release(); // done with it after init ! 463: propTable = NULL; ! 464: ! 465: if (!newDevice->attach(this)) ! 466: continue; ! 467: newDevice->setNodeROM(fBusGeneration, scan->fAddr.nodeID, fLocalNodeID, ! 468: rom, scan->fSelfIDs, scan->fNumSelfIDs); ! 469: newDevice->registerService(); ! 470: } ! 471: if(fIRMNodeID == scan->fAddr.nodeID) { ! 472: IOFWIsochChannel *found; ! 473: fIRMDevice = newDevice; ! 474: // Tell all active ioschronous channels to re-allocate bandwidth ! 475: IOTakeLock(fChannelLock); ! 476: fAllocChannelIterator->reset(); ! 477: while( (found = (IOFWIsochChannel *) fAllocChannelIterator->getNextObject())) { ! 478: found->handleBusReset(); ! 479: } ! 480: IOUnlock(fChannelLock); ! 481: } ! 482: UInt32 nodeID = FWAddressToID(scan->fAddr.nodeID); ! 483: fNodes[nodeID] = newDevice; ! 484: fNodes[nodeID]->retain(); ! 485: } while (false); ! 486: if (propTable) ! 487: propTable->release(); ! 488: if (newDevice) ! 489: newDevice->release(); ! 490: if (rom) ! 491: rom->release(); ! 492: if(scan->fBuf) ! 493: IOFree(scan->fBuf, scan->fROMSize); ! 494: scan->fCmd->release(); ! 495: IOFree(scan, sizeof(*scan)); ! 496: fNumROMReads--; ! 497: if(fNumROMReads == 0) { ! 498: fTimer->enable(); ! 499: fTimer->setTimeoutMS(kDevicePruneDelay); // One second ! 500: } ! 501: } ! 502: } ! 503: ! 504: ! 505: // ! 506: // Hardware detected a bus reset. ! 507: // At this point we don't know what the hardware addresses are ! 508: void IOFireWireController::processBusReset() ! 509: { ! 510: clock_get_uptime(&fResetTime); // Update even if we're already processing a reset ! 511: ! 512: if(!fInReset) { ! 513: fInReset = true; ! 514: unsigned int i; ! 515: ! 516: fTimer->cancelTimeout(); ! 517: ! 518: // Set all current device nodeIDs to something invalid ! 519: OSIterator *childIterator; ! 520: childIterator = getClientIterator(); ! 521: if( childIterator) { ! 522: IOFireWireDevice * found; ! 523: while( (found = (IOFireWireDevice *) childIterator->getNextObject())) { ! 524: found->setNodeROM(fBusGeneration, kFWBadNodeID, kFWBadNodeID, NULL, NULL, 0); ! 525: } ! 526: childIterator->release(); ! 527: } ! 528: ! 529: ! 530: // Invalidate current topology and speed map ! 531: fBusGeneration++; ! 532: bzero(fSpeedCodes, sizeof(fSpeedCodes)); ! 533: ! 534: // Zap all outstanding async requests ! 535: for(i=0; i<kMaxPendingTransfers; i++) { ! 536: AsyncPendingTrans *t = &fTrans[i]; ! 537: if(t->fInUse) { ! 538: IOFWAsyncCommand * cmd = t->fHandler; ! 539: if(cmd) { ! 540: cmd->gotPacket(this, kFWResponseBusResetError, NULL, 0); ! 541: } ! 542: } ! 543: } ! 544: ! 545: // Clear out the old firewire plane ! 546: if(fNodes[fRootNodeID]) { ! 547: fNodes[fRootNodeID]->detachAll(gIOFireWirePlane); ! 548: } ! 549: for(i=0; i<=fRootNodeID; i++) { ! 550: if(fNodes[i]) { ! 551: fNodes[i]->release(); ! 552: fNodes[i] = NULL; ! 553: } ! 554: } ! 555: } ! 556: } ! 557: ! 558: // ! 559: // SelfID packets received after reset. ! 560: void IOFireWireController::processSelfIDs(UInt32 *IDs, int numIDs, UInt32 *ownIDs, int numOwnIDs) ! 561: { ! 562: OSObject *prop; ! 563: int i; ! 564: UInt32 id; ! 565: UInt32 nodeID; ! 566: UInt16 irmID, ourID; ! 567: ! 568: #if 0 ! 569: for(i=0; i<numIDs; i++) ! 570: IOLog("ID %d: 0x%x <-> 0x%x\n", i, IDs[2*i], ~IDs[2*i+1]); ! 571: ! 572: for(i=0; i<numOwnIDs; i++) ! 573: IOLog("Own ID %d: 0x%x <-> 0x%x\n", i, ownIDs[2*i], ~ownIDs[2*i+1]); ! 574: #endif ! 575: // If not processing a reset, then we should be ! 576: // This can happen if we get two resets in quick succession ! 577: if(!fInReset) ! 578: processBusReset(); ! 579: fInReset = false; ! 580: fNumROMReads = 0; ! 581: ! 582: // Update the registry entry for our local nodeID, ! 583: // which will have been updated by the device driver. ! 584: prop = OSNumber::withNumber(fLocalNodeID, 16); ! 585: setProperty(gFireWireNodeID, prop); ! 586: prop->release(); ! 587: prop = OSNumber::withNumber((ownIDs[0] & kFWSelfID0SP) >> kFWSelfID0SPPhase, 32); ! 588: setProperty(gFireWireSpeed, prop); ! 589: prop->release(); ! 590: ! 591: // Initialize root node to be our node, we'll update it below to be the highest node ID. ! 592: fRootNodeID = ourID = (*ownIDs & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase; ! 593: ! 594: fNodes[ourID] = this; ! 595: retain(); ! 596: ! 597: // Copy over the selfIDs, checking validity and merging in our selfIDs if they aren't ! 598: // already in the list. ! 599: SInt16 prevID = -1; // Impossible ID. ! 600: UInt32 *idPtr = fSelfIDs; ! 601: for(i=0; i<numIDs; i++) { ! 602: UInt32 id = IDs[2*i]; ! 603: UInt16 currID = (id & kFWPhyPacketPhyID) >> kFWPhyPacketPhyIDPhase; ! 604: ! 605: if(id != ~IDs[2*i+1]) { ! 606: IOLog("Bad SelfID packet %d: 0x%x != 0x%x!\n", i, id, ~IDs[2*i+1]); ! 607: resetBus(); // Could wait a bit in case somebody else spots the bad packet ! 608: return; ! 609: } ! 610: if(currID != prevID) { ! 611: // Check for ownids not in main list ! 612: if(prevID < ourID && currID > ourID) { ! 613: int j; ! 614: fNodeIDs[ourID] = idPtr; ! 615: for(j=0; j<numOwnIDs; j++) ! 616: *idPtr++ = ownIDs[2*j]; ! 617: } ! 618: fNodeIDs[currID] = idPtr; ! 619: prevID = currID; ! 620: if(fRootNodeID < currID) ! 621: fRootNodeID = currID; ! 622: } ! 623: *idPtr++ = id; ! 624: } ! 625: // Check for ownids at end & not in main list ! 626: if(prevID < ourID) { ! 627: int j; ! 628: fNodeIDs[ourID] = idPtr; ! 629: for(j=0; j<numOwnIDs; j++) ! 630: *idPtr++ = ownIDs[2*j]; ! 631: } ! 632: // Stick a known elephant at the end. ! 633: fNodeIDs[fRootNodeID+1] = idPtr; ! 634: ! 635: buildTopology(false); ! 636: ! 637: prop = OSData::withBytes(fNodeIDs[ourID], numOwnIDs*sizeof(UInt32)); ! 638: setProperty(gFireWireSelfIDs, prop); ! 639: prop->release(); ! 640: ! 641: // Ask each device for its GUID. ! 642: // In the completion handler we'll match the new IDs to existing ! 643: // nubs and create new ones. ! 644: #if (DEBUGGING_LEVEL > 0) ! 645: for(i=0; i<numIDs; i++) { ! 646: id = IDs[2*i]; ! 647: if(id != ~IDs[2*i+1]) { ! 648: DEBUGLOG("Bad SelfID: 0x%x <-> 0x%x\n", id, ~IDs[2*i+1]); ! 649: continue; ! 650: } ! 651: DEBUGLOG("SelfID: 0x%x\n", id); ! 652: } ! 653: DEBUGLOG("Our ID: 0x%x\n", *ownIDs); ! 654: #endif ! 655: irmID = 0; ! 656: for(i=0; i<=fRootNodeID; i++) { ! 657: if(i == ourID) ! 658: continue; // Skip ourself! ! 659: id = *fNodeIDs[i]; ! 660: // Get nodeID. ! 661: nodeID = (id & kFWSelfIDPhyID) >> kFWSelfIDPhyIDPhase; ! 662: nodeID |= kFWLocalBusAddress>>kCSRNodeIDPhase; ! 663: ! 664: if((id & (kFWSelfID0C | kFWSelfID0L)) == (kFWSelfID0C | kFWSelfID0L)) { ! 665: kprintf("IRM contender: %x\n", nodeID); ! 666: if(nodeID > irmID) ! 667: irmID = nodeID; ! 668: } ! 669: ! 670: // Read ROM header if link is active (MacOS8 turns link on, why?) ! 671: if(true) { //id & kFWSelfID0L) { ! 672: NodeScan *scan; ! 673: scan = (NodeScan *)IOMalloc(sizeof(*scan)); ! 674: fNumROMReads++; ! 675: ! 676: scan->fControl = this; ! 677: scan->fAddr.nodeID = nodeID; ! 678: scan->fAddr.addressHi = kCSRRegisterSpaceBaseAddressHi; ! 679: scan->fAddr.addressLo = kCSRBIBHeaderAddress; ! 680: scan->fSelfIDs = fNodeIDs[i]; ! 681: scan->fNumSelfIDs = fNodeIDs[i+1] - fNodeIDs[i]; ! 682: scan->fState = kReadROMSize; ! 683: scan->fCmd = new IOFWReadQuadCommand; ! 684: scan->fCmd->initAll(this, NULL, scan->fAddr, &scan->fROMHdr, 1, ! 685: &readROMGlue, scan, true); ! 686: scan->fBuf = NULL; ! 687: scan->fCmd->execute(); ! 688: } ! 689: } ! 690: if(irmID != 0) ! 691: fIRMNodeID = irmID; ! 692: else ! 693: fIRMNodeID = kFWBadNodeID; ! 694: if(fNumROMReads == 0) { ! 695: fTimer->enable(); ! 696: fTimer->setTimeoutMS(kDevicePruneDelay); // One second ! 697: } ! 698: } ! 699: ! 700: void IOFireWireController::buildTopology(bool doFWPlane) ! 701: { ! 702: int i; ! 703: IORegistryEntry *root; ! 704: struct FWNodeScan ! 705: { ! 706: int nodeID; ! 707: int childrenRemaining; ! 708: IORegistryEntry *node; ! 709: }; ! 710: FWNodeScan scanList[kFWMaxNodeHops]; ! 711: FWNodeScan *level; ! 712: root = fNodes[fRootNodeID]; ! 713: level = scanList; ! 714: ! 715: // First build the topology. ! 716: for(i=fRootNodeID; i>=0; i--) { ! 717: UInt32 id0; ! 718: UInt8 speedCode; ! 719: IORegistryEntry *node = fNodes[i]; ! 720: id0 = *fNodeIDs[i]; ! 721: int children = 0; ! 722: UInt32 port; ! 723: port = (id0 & kFWSelfID0P0) >> kFWSelfID0P0Phase; ! 724: if(port == kFWSelfIDPortStatusChild) ! 725: children++; ! 726: port = (id0 & kFWSelfID0P1) >> kFWSelfID0P1Phase; ! 727: if(port == kFWSelfIDPortStatusChild) ! 728: children++; ! 729: port = (id0 & kFWSelfID0P2) >> kFWSelfID0P2Phase; ! 730: if(port == kFWSelfIDPortStatusChild) ! 731: children++; ! 732: ! 733: // Add node to bottom of tree ! 734: level->nodeID = i; ! 735: level->childrenRemaining = children; ! 736: level->node = node; ! 737: ! 738: // Add node's self speed to speedmap ! 739: speedCode = (id0 & kFWSelfID0SP) >> kFWSelfID0SPPhase; ! 740: fSpeedCodes[(kFWMaxNodesPerBus + 1)*i + i] = speedCode; ! 741: ! 742: // Add to parent ! 743: // Compute rest of this node's speed map entries unless it's the root. ! 744: // We only need to compute speeds between this node and all higher node numbers. ! 745: // These speeds will be the minimum of this node's speed and the speed between ! 746: // this node's parent and the other higher numbered nodes. ! 747: if (i != fRootNodeID) { ! 748: int parentNodeNum, scanNodeNum; ! 749: parentNodeNum = (level-1)->nodeID; ! 750: if(doFWPlane) ! 751: node->attachToParent((level-1)->node, gIOFireWirePlane); ! 752: for (scanNodeNum = i + 1; scanNodeNum <= fRootNodeID; scanNodeNum++) { ! 753: UInt8 scanSpeedCode; ! 754: // Get speed code between parent and scan node. ! 755: scanSpeedCode = ! 756: fSpeedCodes[(kFWMaxNodesPerBus + 1)*parentNodeNum + scanNodeNum]; ! 757: ! 758: // Set speed map entry to minimum of scan speed and node's speed. ! 759: if (speedCode < scanSpeedCode) ! 760: scanSpeedCode = speedCode; ! 761: fSpeedCodes[(kFWMaxNodesPerBus + 1)*i + scanNodeNum] = scanSpeedCode; ! 762: fSpeedCodes[(kFWMaxNodesPerBus + 1)*scanNodeNum + i] = scanSpeedCode; ! 763: } ! 764: } ! 765: // Find next child port. ! 766: if (i > 0) { ! 767: while (level->childrenRemaining == 0) { ! 768: // Go up one level in tree. ! 769: level--; ! 770: ! 771: // One less child to scan. ! 772: level->childrenRemaining--; ! 773: } ! 774: // Go down one level in tree. ! 775: level++; ! 776: } ! 777: } ! 778: ! 779: ! 780: if(doFWPlane) { ! 781: IOLog("FireWire Speed map:\n"); ! 782: for(i=0; i <= fRootNodeID; i++) { ! 783: int j; ! 784: for(j=0; j <= fRootNodeID; j++) { ! 785: IOLog("%d ", fSpeedCodes[(kFWMaxNodesPerBus + 1)*i + j]); ! 786: } ! 787: IOLog("\n"); ! 788: } ! 789: } ! 790: // Finally attach the full topology into the IOKit registry ! 791: if(doFWPlane) ! 792: root->attachToParent(IORegistryEntry::getRegistryRoot(), gIOFireWirePlane); ! 793: } ! 794: ! 795: void IOFireWireController::pruneDevices() ! 796: { ! 797: OSIterator *childIterator; ! 798: childIterator = getClientIterator(); ! 799: if( childIterator) { ! 800: IOFireWireDevice * found; ! 801: while( (found = (IOFireWireDevice *) childIterator->getNextObject())) { ! 802: if(found->fNodeID == kFWBadNodeID) { ! 803: found->terminate(); ! 804: } ! 805: } ! 806: childIterator->release(); ! 807: } ! 808: ! 809: buildTopology(true); ! 810: } ! 811: ! 812: //////////////////////////////////////////////////////////////////////////////// ! 813: // ! 814: // processWriteRequest ! 815: // ! 816: // process quad and block writes. ! 817: // ! 818: void IOFireWireController::processWriteRequest(UInt16 sourceID, UInt32 tLabel, ! 819: UInt32 *hdr, void *buf, int len) ! 820: { ! 821: UInt32 ret = kFWResponseAddressError; ! 822: FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]); ! 823: IOFWAddressSpace * found; ! 824: fSpaceIterator->reset(); ! 825: while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { ! 826: ret = found->doWrite(sourceID, addr, len, buf, false); ! 827: if(ret != kFWResponseAddressError) ! 828: break; ! 829: } ! 830: asyncWriteResponse(sourceID, FWSpeed(sourceID), tLabel, ret, addr.addressHi); ! 831: } ! 832: ! 833: //////////////////////////////////////////////////////////////////////////////// ! 834: // ! 835: // processLockRequest ! 836: // ! 837: // process 32 and 64 bit locks. ! 838: // ! 839: void IOFireWireController::processLockRequest(UInt16 sourceID, UInt32 tLabel, ! 840: UInt32 *hdr, void *buf, int len) ! 841: { ! 842: UInt32 oldVal[2]; ! 843: UInt32 ret = kFWResponseAddressError; ! 844: bool ok; ! 845: int size; ! 846: int i; ! 847: int type = (hdr[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase; ! 848: FWAddress addr((hdr[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, hdr[2]); ! 849: IOFWAddressSpace * found; ! 850: IOMemoryDescriptor *desc = NULL; ! 851: IOByteCount offset; ! 852: ! 853: ! 854: size = len/8; // Depends on type, but right for 'compare and swap' ! 855: ! 856: fSpaceIterator->reset(); ! 857: while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { ! 858: ret = found->doRead(sourceID, addr, size*4, &desc, &offset, true); ! 859: if(ret != kFWResponseAddressError) ! 860: break; ! 861: } ! 862: if(NULL != desc) { ! 863: desc->readBytes(offset,oldVal, size*4); ! 864: switch (type) { ! 865: case kFWExtendedTCodeCompareSwap: ! 866: ok = true; ! 867: for(i=0; i<size; i++) ! 868: ok = ok && oldVal[i] == ((UInt32 *)buf)[i]; ! 869: if(ok) ! 870: ret = found->doWrite(sourceID, addr, size*4, (UInt32 *)buf+size, true); ! 871: break; ! 872: ! 873: default: ! 874: ret = kFWResponseTypeError; ! 875: } ! 876: asyncLockResponse(sourceID, FWSpeed(sourceID), tLabel, ret, type, oldVal, size*4); ! 877: } ! 878: else { ! 879: oldVal[0] = 0xdeadbabe; ! 880: asyncLockResponse(sourceID, FWSpeed(sourceID), tLabel, ret, type, oldVal, 4); ! 881: } ! 882: } ! 883: ! 884: //////////////////////////////////////////////////////////////////////////////// ! 885: // ! 886: // processRcvPacket ! 887: // ! 888: // Dispatch received Async packet based on tCode. ! 889: // ! 890: void IOFireWireController::processRcvPacket(UInt32 *data, int size) ! 891: { ! 892: #if 0 ! 893: int i; ! 894: kprintf("Received packet 0x%x size %d\n", data, size); ! 895: for(i=0; i<size; i++) { ! 896: kprintf("0x%x ", data[i]); ! 897: } ! 898: kprintf("\n"); ! 899: #endif ! 900: UInt32 tCode, tLabel; ! 901: UInt32 quad0; ! 902: UInt16 sourceID; ! 903: ! 904: // Get first quad. ! 905: quad0 = *data; ! 906: ! 907: tCode = (quad0 & kFWPacketTCode) >> kFWPacketTCodePhase; ! 908: tLabel = (quad0 & kFWAsynchTLabel) >> kFWAsynchTLabelPhase; ! 909: sourceID = (data[1] & kFWAsynchSourceID) >> kFWAsynchSourceIDPhase; ! 910: ! 911: // Dispatch processing based on tCode. ! 912: switch (tCode) ! 913: { ! 914: case kFWTCodeWriteQuadlet : ! 915: #if (DEBUGGING_LEVEL > 0) ! 916: DEBUGLOG("WriteQuadlet: addr 0x%x:0x%x\n", ! 917: (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); ! 918: #endif ! 919: processWriteRequest(sourceID, tLabel, data, &data[3], 4); ! 920: break; ! 921: ! 922: case kFWTCodeWriteBlock : ! 923: #if (DEBUGGING_LEVEL > 0) ! 924: DEBUGLOG("WriteBlock: addr 0x%x:0x%x\n", ! 925: (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); ! 926: #endif ! 927: processWriteRequest(sourceID, tLabel, data, &data[4], ! 928: (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase); ! 929: break; ! 930: ! 931: case kFWTCodeWriteResponse : ! 932: if(fTrans[tLabel].fInUse) { ! 933: IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; ! 934: cmd->gotPacket(this, ! 935: (data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, 0, 0); ! 936: } ! 937: else { ! 938: #if (DEBUGGING_LEVEL > 0) ! 939: DEBUGLOG("WriteResponse: label %d isn't in use!!\n", tLabel); ! 940: #endif ! 941: } ! 942: break; ! 943: ! 944: case kFWTCodeReadQuadlet : ! 945: #if (DEBUGGING_LEVEL > 0) ! 946: DEBUGLOG("ReadQuadlet: addr 0x%x:0x%x\n", ! 947: (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); ! 948: #endif ! 949: { ! 950: // Rather inefficiently search for a matching address space ! 951: UInt32 ret = kFWResponseAddressError; ! 952: FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2]); ! 953: IOFWAddressSpace * found; ! 954: IOMemoryDescriptor *buf = NULL; ! 955: IOByteCount offset; ! 956: fSpaceIterator->reset(); ! 957: while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { ! 958: ret = found->doRead(sourceID, addr, 4, &buf, &offset, false); ! 959: if(ret != kFWResponseAddressError) ! 960: break; ! 961: } ! 962: if(NULL != buf) { ! 963: IOByteCount lengthOfSegment; ! 964: asyncReadQuadResponse(sourceID, FWSpeed(sourceID), tLabel, ret, ! 965: *(UInt32 *)buf->getVirtualSegment(offset, &lengthOfSegment)); ! 966: } ! 967: else { ! 968: asyncReadQuadResponse(sourceID, FWSpeed(sourceID), ! 969: tLabel, ret, 0xdeadbeef); ! 970: } ! 971: } ! 972: break; ! 973: ! 974: case kFWTCodeReadBlock : ! 975: #if (DEBUGGING_LEVEL > 0) ! 976: DEBUGLOG("ReadBlock: addr 0x%x:0x%x len %d\n", ! 977: (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, data[2], ! 978: (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase); ! 979: #endif ! 980: { ! 981: // Rather inefficiently search for a matching address space ! 982: IOReturn ret = kFWResponseAddressError; ! 983: int length = (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase ; ! 984: FWAddress addr((data[1] & kFWAsynchDestinationOffsetHigh) >> ! 985: kFWAsynchDestinationOffsetHighPhase, data[2]); ! 986: IOFWAddressSpace * found; ! 987: IOMemoryDescriptor *buf = NULL; ! 988: IOByteCount offset; ! 989: fSpaceIterator->reset(); ! 990: while( (found = (IOFWAddressSpace *) fSpaceIterator->getNextObject())) { ! 991: ret = found->doRead(sourceID, addr, length, &buf, &offset, false); ! 992: if(ret != kFWResponseAddressError) ! 993: break; ! 994: } ! 995: if(NULL != buf) { ! 996: asyncReadResponse(sourceID, FWSpeed(sourceID), ! 997: tLabel, ret, buf, offset, length); ! 998: } ! 999: else { ! 1000: UInt32 bad = 0xcafebabe; ! 1001: asyncReadResponse(sourceID, FWSpeed(sourceID), ! 1002: tLabel, ret, &bad, 4); ! 1003: } ! 1004: } ! 1005: break; ! 1006: ! 1007: case kFWTCodeReadQuadletResponse : ! 1008: if(fTrans[tLabel].fInUse) { ! 1009: IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; ! 1010: cmd->gotPacket(this, (data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, ! 1011: (UInt8*)(data+3), 4); ! 1012: } ! 1013: else { ! 1014: #if (DEBUGGING_LEVEL > 0) ! 1015: DEBUGLOG("ReadQuadletResponse: label %d isn't in use!!\n", tLabel); ! 1016: #endif ! 1017: } ! 1018: break; ! 1019: ! 1020: case kFWTCodeReadBlockResponse : ! 1021: case kFWTCodeLockResponse : ! 1022: if(fTrans[tLabel].fInUse) { ! 1023: IOFWAsyncCommand * cmd = fTrans[tLabel].fHandler; ! 1024: cmd->gotPacket(this, (data[1] & kFWAsynchRCode)>>kFWAsynchRCodePhase, ! 1025: (UInt8*)(data+4), (data[3] & kFWAsynchDataLength)>>kFWAsynchDataLengthPhase); ! 1026: } ! 1027: else { ! 1028: #if (DEBUGGING_LEVEL > 0) ! 1029: DEBUGLOG("ReadBlock/LockResponse: label %d isn't in use!!\n", tLabel); ! 1030: #endif ! 1031: } ! 1032: break; ! 1033: ! 1034: case kFWTCodeLock : ! 1035: #if (DEBUGGING_LEVEL > 0) ! 1036: DEBUGLOG("Lock type %d: addr 0x%x:0x%x\n", ! 1037: (data[3] & kFWAsynchExtendedTCode) >> kFWAsynchExtendedTCodePhase, ! 1038: (data[1] & kFWAsynchDestinationOffsetHigh) >> kFWAsynchDestinationOffsetHighPhase, ! 1039: data[2]); ! 1040: #endif ! 1041: processLockRequest(sourceID, tLabel, data, &data[4], ! 1042: (data[3] & kFWAsynchDataLength) >> kFWAsynchDataLengthPhase); ! 1043: ! 1044: break; ! 1045: ! 1046: case kFWTCodeIsochronousBlock : ! 1047: #if (DEBUGGING_LEVEL > 0) ! 1048: DEBUGLOG("Async Stream Packet\n"); ! 1049: #endif ! 1050: break; ! 1051: ! 1052: default : ! 1053: #if (DEBUGGING_LEVEL > 0) ! 1054: DEBUGLOG("Unexpected tcode in Asyncrecv: %d\n", tCode); ! 1055: #endif ! 1056: break; ! 1057: } ! 1058: } ! 1059: ! 1060: IOReturn IOFireWireController::allocAddress(IOFWAddressSpace *space) ! 1061: { ! 1062: /* ! 1063: * Lots of scope for optimizations here, perhaps building a hash table for ! 1064: * addresses etc. ! 1065: * Drivers may want to override this if their hardware can match addresses ! 1066: * without CPU intervention. ! 1067: */ ! 1068: if(!fLocalAddresses->setObject(space)) ! 1069: return kIOReturnNoMemory; ! 1070: else ! 1071: return kIOReturnSuccess; ! 1072: } ! 1073: ! 1074: void IOFireWireController::freeAddress(IOFWAddressSpace *space) ! 1075: { ! 1076: fLocalAddresses->removeObject(space); ! 1077: } ! 1078: ! 1079: void IOFireWireController::addAllocatedChannel(IOFWIsochChannel *channel) ! 1080: { ! 1081: IOTakeLock(fChannelLock); ! 1082: fAllocatedChannels->setObject(channel); ! 1083: IOUnlock(fChannelLock); ! 1084: } ! 1085: ! 1086: void IOFireWireController::removeAllocatedChannel(IOFWIsochChannel *channel) ! 1087: { ! 1088: IOTakeLock(fChannelLock); ! 1089: fAllocatedChannels->removeObject(channel); ! 1090: IOUnlock(fChannelLock); ! 1091: } ! 1092: ! 1093: ! 1094: IOFireWireDevice * IOFireWireController::nodeIDtoDevice(UInt16 nodeID) ! 1095: { ! 1096: OSIterator *childIterator; ! 1097: IOFireWireDevice * found = NULL; ! 1098: ! 1099: childIterator = getClientIterator(); ! 1100: ! 1101: if( childIterator) { ! 1102: while( (found = (IOFireWireDevice *) childIterator->getNextObject())) { ! 1103: if(found->fNodeID == nodeID) ! 1104: break; ! 1105: } ! 1106: childIterator->release(); ! 1107: } ! 1108: return found; ! 1109: } ! 1110: ! 1111: IOFireWireDevice *IOFireWireController::createDeviceNub(OSDictionary *propTable) ! 1112: { ! 1113: IOFireWireDevice *newDevice; ! 1114: newDevice = new IOFireWireDevice; ! 1115: ! 1116: if (!newDevice) ! 1117: return NULL; ! 1118: if(!newDevice->init(propTable)) { ! 1119: newDevice->release(); ! 1120: return NULL; ! 1121: } ! 1122: return newDevice; ! 1123: } ! 1124: ! 1125: IOFWIsochChannel *IOFireWireController::createIsochChannel( ! 1126: bool doIRM, UInt32 bandwidth, IOFWSpeed prefSpeed, ! 1127: FWIsochChannelForceStopNotificationProc stopProc, void *stopRefCon) ! 1128: { ! 1129: IOFWIsochChannel *channel; ! 1130: ! 1131: channel = new IOFWIsochChannel; ! 1132: if(!channel) ! 1133: return NULL; ! 1134: ! 1135: if(!channel->init(this, doIRM, bandwidth, prefSpeed, stopProc, stopRefCon)) { ! 1136: channel->release(); ! 1137: channel = NULL; ! 1138: } ! 1139: return channel; ! 1140: } ! 1141: ! 1142: IOFWIsochPort *IOFireWireController::createLocalIsochPort(bool talking, ! 1143: DCLCommandStruct *opcodes, DCLTaskInfo *info, ! 1144: UInt32 startEvent, UInt32 startState, UInt32 startMask) ! 1145: { ! 1146: IOFWLocalIsochPort *port; ! 1147: IODCLProgram *program; ! 1148: ! 1149: program = createDCLProgram(talking, opcodes, info, startEvent, startState, startMask); ! 1150: if(!program) ! 1151: return NULL; ! 1152: ! 1153: port = new IOFWLocalIsochPort; ! 1154: if(!port) { ! 1155: program->release(); ! 1156: return NULL; ! 1157: } ! 1158: ! 1159: if(!port->init(program, this)) { ! 1160: port->release(); ! 1161: port = NULL; ! 1162: } ! 1163: ! 1164: return port; ! 1165: } ! 1166: ! 1167: // How big (as a power of two) can packets sent to/received from the node be? ! 1168: int IOFireWireController::maxPackLog(bool forSend, UInt16 nodeAddress) const ! 1169: { ! 1170: return 9+FWSpeed(nodeAddress); ! 1171: } ! 1172: ! 1173: // How big (as a power of two) can packets sent from A to B be? ! 1174: int IOFireWireController::maxPackLog(UInt16 nodeA, UInt16 nodeB) const ! 1175: { ! 1176: return 9+FWSpeed(nodeA, nodeB); ! 1177: } ! 1178:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.