Annotation of XNU/iokit/Families/IOFireWire/IOFireWireController.cpp, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.