|
|
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.