1/*
2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22#include "IOFireWireIP.h"
23#include "IOFireWireIPCommand.h"
24#include <IOKit/firewire/IOFireWireController.h>
25
26extern "C"
27{
28void _logMbuf(struct mbuf * m);
29void _logPkt(void *pkt, UInt16 len);
30}
31
32#define super IOFWController
33
34OSDefineMetaClassAndStructors(IOFireWireIP, IOFWController);
35
36#pragma mark -
37#pragma mark ��� IOService methods ���
38
39bool IOFireWireIP::start(IOService *provider)
40{
41    IOReturn	ioStat = kIOReturnSuccess;
42
43	if(fStarted)
44		return fStarted;
45
46	// Create the lock
47	if(ioStat == kIOReturnSuccess)
48	{
49		// Allocate lock
50		ipLock = IORecursiveLockAlloc();
51
52		if(ipLock == NULL)
53			ioStat = kIOReturnNoMemory;
54	}
55
56	if(ioStat == kIOReturnSuccess)
57	{
58		recursiveScopeLock lock(ipLock);
59
60		fIPoFWDiagnostics.fMaxPktSize = 0;
61		netifEnabled = false;
62		busifEnabled = false;
63		fClientStarting = false;
64		fIPoFWDiagnostics.fDoFastRetry = false;
65
66		fDevice = OSDynamicCast(IOFireWireNub, provider);
67
68		if(!fDevice)
69			return false;
70
71		fControl = fDevice->getController();
72
73		if(!fControl)
74			return false;
75
76		fControl->retain();
77
78		OSObject * prop = fDevice->getProperty(gFireWire_GUID);
79		if( prop )
80		{
81			setProperty( gFireWire_GUID, prop );
82		}
83
84		// Initialize the LCB
85		fLcb = (LCB*)IOMalloc(sizeof(LCB));
86		if(fLcb == NULL)
87			return false;
88
89		memset(fLcb, 0, sizeof(LCB));
90
91		fDiagnostics_Symbol = OSSymbol::withCStringNoCopy("Diagnostics");
92
93		fDiagnostics = IOFireWireIPDiagnostics::createDiagnostics(this);
94		if( fDiagnostics )
95		{
96			if(fDiagnostics_Symbol)
97				setProperty( fDiagnostics_Symbol, fDiagnostics );
98			fDiagnostics->release();
99		}
100
101		if(ioStat == kIOReturnSuccess) {
102
103			CSRNodeUniqueID	fwuid = fDevice->getUniqueID();
104
105			// Construct the ethernet address
106			makeEthernetAddress(&fwuid, macAddr, GUID_TYPE);
107		}
108
109		// IONetworkingFamily attachments
110		if (!super::start(provider))
111			return false;
112
113		if (getHardwareAddress(&myAddress) != kIOReturnSuccess)
114		{
115			return false;
116		}
117
118		if(!createMediumState())
119		{
120			IOLog( "IOFireWireIP::start - Couldn't allocate IONetworkMedium\n" );
121			return false;
122		}
123
124
125		if(ioStat == kIOReturnSuccess)
126		{
127			// Add unit notification for units disappearing
128			fIPUnitNotifier = IOService::addMatchingNotification(gIOPublishNotification,
129														serviceMatching("IOFireWireIPUnit"),
130														&fwIPUnitAttach, this, (void*)IP1394_VERSION, 0);
131		}
132
133		if(ioStat == kIOReturnSuccess)
134		{
135			// Add unit notification for units disappearing
136			fIPv6UnitNotifier = IOService::addMatchingNotification(gIOPublishNotification,
137														serviceMatching("IOFireWireIPUnit"),
138														&fwIPUnitAttach, this, (void*)IP1394v6_VERSION, 0);
139		}
140
141		// Create config rom entry
142		if(ioStat == kIOReturnSuccess)
143			ioStat = createIPConfigRomEntry();
144
145		if(ioStat == kIOReturnSuccess)
146		{
147			fDevice->getNodeIDGeneration(fLcb->busGeneration, fLcb->ownNodeID);
148			fLcb->ownMaxSpeed = fDevice->FWSpeed();
149			fLcb->maxBroadcastPayload = fDevice->maxPackLog(true);
150			fLcb->maxBroadcastSpeed = fDevice->FWSpeed();
151			fLcb->ownMaxPayload = fDevice->maxPackLog(true);
152
153			IP1394_HDW_ADDR	hwAddr;
154
155			CSRNodeUniqueID	fwuid = fDevice->getUniqueID();
156
157			memset(&hwAddr, 0, sizeof(IP1394_HDW_ADDR));
158			hwAddr.eui64.hi = OSSwapHostToBigInt32((UInt32)(fwuid >> 32));
159			hwAddr.eui64.lo = OSSwapHostToBigInt32((UInt32)(fwuid & 0xffffffff));
160
161			hwAddr.maxRec	= fControl->getMaxRec();
162			hwAddr.spd		= fDevice->FWSpeed();
163
164			hwAddr.unicastFifoHi = kUnicastHi;
165			hwAddr.unicastFifoLo = kUnicastLo;
166
167			memcpy(&fLcb->ownHardwareAddress, &hwAddr, sizeof(IP1394_HDW_ADDR));
168
169			UInt32 size = getMaxARDMAPacketSize();
170
171			if(size > 0)
172				fLcb->ownHardwareAddress.maxRec = getMaxARDMARec(size);
173
174			setProperty(kIOFWHWAddr,  (void *)&fLcb->ownHardwareAddress, sizeof(IP1394_HDW_ADDR));
175		}
176
177		if(ioStat != kIOReturnSuccess)
178		{
179			IOLog( "IOFireWireIP::start - failed\n" );
180			return false;
181		}
182
183		if (!attachInterface((IONetworkInterface**)&networkInterface, false ))
184		{
185			return false;
186		}
187
188		fPrivateInterface	= NULL;
189
190		networkInterface->setIfnetMTU( 1 << fDevice->maxPackLog(true) );
191
192		transmitQueue = (IOGatedOutputQueue*)getOutputQueue();
193		if ( !transmitQueue )
194		{
195			IOLog( "IOFireWireIP::start - Output queue initialization failed\n" );
196			return false;
197		}
198		transmitQueue->retain();
199
200		// Publish interface name if tunnelled Thunderbolt device
201		OSBoolean * tunnelled = OSDynamicCast( OSBoolean, getProperty("IOPCITunnelled", gIOServicePlane, kIORegistryIterateParents | kIORegistryIterateRecursively) );
202		if ( (tunnelled != NULL) )
203		{
204			if ( (tunnelled->isTrue()) )
205			{
206				OSData * tbtVendorID = (OSData *)getProperty("Tunnel Endpoint Device Vendor ID", gIOServicePlane, kIORegistryIterateParents | kIORegistryIterateRecursively);
207				OSData * tbtModelID = (OSData *)getProperty("Tunnel Endpoint Device Model ID", gIOServicePlane, kIORegistryIterateParents | kIORegistryIterateRecursively);
208
209				if ( tbtVendorID && tbtModelID )
210				{
211					uint32_t j59VendorID = 0x00000001;
212					uint32_t j59ModelID = 0x00008002;
213					uint32_t * tbtVendorIDPtr = (uint32_t *)(tbtVendorID->getBytesNoCopy(0, 4));
214					uint32_t * tbtModelIDPtr = (uint32_t *)(tbtModelID->getBytesNoCopy(0, 4));
215
216					//IOLog( "IOFireWireIP: VID: 0x%x MID: 0x%x\n", *tbtVendorIDPtr, *tbtModelIDPtr );
217
218					if ( j59VendorID == *tbtVendorIDPtr && j59ModelID == *tbtModelIDPtr )
219					{
220						setProperty("Product Name", "Display FireWire");
221					}
222					else
223					{
224						OSData * tbtUID = (OSData *)getProperty("Tunnel Endpoint GUID", gIOServicePlane, kIORegistryIterateParents | kIORegistryIterateRecursively);
225
226						if ( tbtUID )
227						{
228							OSDictionary * matchDict = serviceMatching( "IOThunderboltSwitch" );
229							const OSSymbol * uidSym = OSSymbol::withCString( "UID" );
230							OSNumber * tbtUIDNumber = OSNumber::withNumber( *((uint64_t *)(tbtUID->getBytesNoCopy(0, 8))), 64 );
231
232							if ( matchDict && uidSym && tbtUIDNumber )
233							{
234								matchDict = propertyMatching( uidSym, tbtUIDNumber, matchDict );
235
236								mach_timespec_t timeout = { 10, 0 };
237								IOService * tbtSwitch = waitForService( matchDict, &timeout );
238
239								if ( tbtSwitch )
240								{
241									/*
242									OSString * modelName = (OSString *)(tbtSwitch->getProperty("Device Model Name", gIOServicePlane, 0));
243
244									if ( modelName )
245									{
246										char propertyName[256];
247										bzero(propertyName, sizeof(propertyName));
248
249										// could be ugly with devices with "FireWire" in the name
250										snprintf(propertyName, sizeof(propertyName)-1, "%s (FireWire)", modelName->getCStringNoCopy());
251
252										setProperty("Product Name", propertyName);
253									}
254									 */
255
256									setProperty("Product Name", "Thunderbolt FireWire");
257								}
258							}
259						}
260					}
261				}
262			}
263		}
264
265		networkInterface->registerService();
266
267		registerService();
268
269		fStarted = true;
270	}
271
272    return fStarted;
273} // end start
274
275bool IOFireWireIP::matchPropertyTable(OSDictionary * table)
276{
277    //
278    // If the service object wishes to compare some of its properties in its
279    // property table against the supplied matching dictionary,
280    // it should do so in this method and return truth on success.
281    //
282    if (!IOService::matchPropertyTable(table))  return false;
283
284    // We return success if the following expression is true -- individual
285    // comparisions evaluate to truth if the named property is not present
286    // in the supplied matching dictionary.
287    return  compareProperty(table, gFireWire_GUID);
288}
289
290bool IOFireWireIP::finalize(IOOptionBits options)
291{
292	return super::finalize(options);
293}
294
295void IOFireWireIP::stop(IOService *provider)
296{
297	recursiveScopeLock lock(ipLock);
298
299	if(fDiagnostics_Symbol != NULL)
300		fDiagnostics_Symbol->release();
301
302	fDiagnostics_Symbol = 0;
303
304    // Free the firewire stuff
305    if (fLocalIP1394v6ConfigDirectory != NULL)
306	{
307        // clear the unit directory in config rom
308        fDevice->getBus()->RemoveUnitDirectory(fLocalIP1394v6ConfigDirectory) ;
309		fLocalIP1394v6ConfigDirectory->release();
310	}
311	fLocalIP1394v6ConfigDirectory = NULL;
312
313    // Free the firewire stuff
314    if (fLocalIP1394ConfigDirectory != NULL)
315	{
316        // clear the unit directory in config rom
317        fDevice->getBus()->RemoveUnitDirectory(fLocalIP1394ConfigDirectory) ;
318		fLocalIP1394ConfigDirectory->release();
319	}
320
321	fLocalIP1394ConfigDirectory = NULL;
322
323	if(fwOwnAddr != NULL)
324		fwOwnAddr->release();
325
326	fwOwnAddr = NULL;
327
328	if (transmitQueue != NULL)
329		transmitQueue->release();
330
331	transmitQueue = NULL;
332
333	if(fIPv6UnitNotifier != NULL)
334		fIPv6UnitNotifier->remove();
335
336	fIPv6UnitNotifier = NULL;
337
338	// Remove IOFireWireIPUnit notification
339	if(fIPUnitNotifier != NULL)
340		fIPUnitNotifier->remove();
341
342	fIPUnitNotifier = NULL;
343
344    if(fLcb != NULL)
345        IOFree(fLcb, sizeof(LCB));
346
347	fLcb = NULL;
348
349	if (networkInterface != NULL)
350    {
351        detachInterface(networkInterface);
352        networkInterface->release();
353	}
354
355	networkInterface = NULL;
356
357	if(fControl != NULL)
358		fControl->release();
359
360	fControl = NULL;
361
362	super::stop(provider);
363}
364
365void IOFireWireIP::free(void)
366{
367    if (ipLock != NULL)
368        IORecursiveLockFree(ipLock);
369
370	ipLock = NULL;
371
372	return super::free();
373}
374
375IOReturn IOFireWireIP::message(UInt32 type, IOService *provider, void *argument)
376{
377    IOReturn res = kIOReturnUnsupported;
378
379    switch (type)
380    {
381        case kIOMessageServiceIsTerminated:
382        case kIOMessageServiceIsSuspended:
383        case kIOMessageServiceIsResumed:
384        case kIOMessageServiceIsRequestingClose:
385			if(busifEnabled)
386				messageClients(type, this);
387            res = kIOReturnSuccess;
388            break;
389
390        default:
391            break;
392    }
393
394    return res;
395}
396
397#pragma mark -
398#pragma mark ��� IOFWController methods ���
399
400IOReturn IOFireWireIP::setMaxPacketSize(UInt32 maxSize)
401{
402	if (maxSize > kIOFWMaxPacketSize)
403		return kIOReturnError;
404
405    return kIOReturnSuccess;
406}
407
408IOReturn IOFireWireIP::getMaxPacketSize(UInt32 * maxSize) const
409{
410	*maxSize = kIOFWMaxPacketSize;
411
412	return kIOReturnSuccess;
413}
414
415IOReturn IOFireWireIP::getHardwareAddress(IOFWAddress *ea)
416{
417	memcpy(ea->bytes, macAddr, kIOFWAddressSize);
418
419    return kIOReturnSuccess;
420} // end getHardwareAddress
421
422
423bool IOFireWireIP::configureInterface( IONetworkInterface *netif )
424{
425    IONetworkData	 *nd;
426
427    if ( super::configureInterface( netif ) == false )
428        return false;
429
430	// Grab a pointer to the statistics structure in the interface:
431	nd = netif->getNetworkData( kIONetworkStatsKey );
432    if (!nd || !(fpNetStats = (IONetworkStats *) nd->getBuffer()))
433    {
434        IOLog("IOFireWireIP: invalid network statistics\n");
435        return false;
436    }
437
438	// Get the Ethernet statistics structure:
439	nd = netif->getParameter( kIOFWStatsKey );
440	if ( !nd || !(fpEtherStats = (IOFWStats*)nd->getBuffer()) )
441	{
442		IOLog( "IOFireWireIP::configureInterface - invalid ethernet statistics\n" );
443        return false;
444	}
445
446    /*
447     * Set the driver/stack reentrancy flag. This is meant to reduce
448     * context switches. May become irrelevant in the future.
449     */
450    return true;
451
452} // end configureInterface
453
454void IOFireWireIP::receivePackets(mbuf_t pkt, UInt32 pkt_len, UInt32 options)
455{
456	if(options == true)
457		fPacketsQueued = true;
458
459    IORecursiveLockLock(ipLock);
460
461	networkInterface->inputPacket(pkt, pkt_len, options);
462	networkStatAdd(&fpNetStats->inputPackets);
463
464    IORecursiveLockUnlock(ipLock);
465}
466
467IOOutputQueue* IOFireWireIP::createOutputQueue()
468{
469	return IOGatedOutputQueue::withTarget(this, getWorkLoop(), TRANSMIT_QUEUE_SIZE);
470}
471
472/*-------------------------------------------------------------------------
473 * Override IONetworkController::createWorkLoop() method and create
474 * a workloop.
475 *-------------------------------------------------------------------------*/
476bool IOFireWireIP::createWorkLoop()
477{
478	workLoop = fDevice->getController()->getWorkLoop();
479
480    return ( workLoop != 0 );
481} // end createWorkLoop
482
483
484// Override IOService::getWorkLoop() method to return our workloop.
485IOWorkLoop* IOFireWireIP::getWorkLoop() const
486{
487    return workLoop;
488} // end getWorkLoop
489
490IOOutputAction IOFireWireIP::getOutputHandler() const
491{
492    return (IOOutputAction) &IOFireWireIP::transmitPacket;
493}
494
495bool IOFireWireIP::multicastCacheHandler(IOFWAddress *addrs, UInt32 count)
496{
497	bool ret = false;
498
499	if( busifEnabled )
500	{
501		IORecursiveLockLock(ipLock);
502
503		if( fUpdateMulticastCache )
504			ret = (*fUpdateMulticastCache)(fPrivateInterface, addrs, count);
505
506		IORecursiveLockUnlock(ipLock);
507	}
508
509	return ret;
510}
511
512bool IOFireWireIP::arpCacheHandler(IP1394_ARP *fwa)
513{
514	bool ret = false;
515
516	if( busifEnabled )
517	{
518		IORecursiveLockLock(ipLock);
519
520		if( fUpdateARPCache )
521			ret = (*fUpdateARPCache)(fPrivateInterface, fwa);
522
523		IORecursiveLockUnlock(ipLock);
524	}
525
526	return ret;
527}
528
529UInt32 IOFireWireIP::transmitPacket(mbuf_t m, void * param)
530{
531	IOReturn status = kIOReturnOutputDropped;
532
533	if( busifEnabled )
534	{
535		IORecursiveLockLock(ipLock);
536
537		if( fOutAction )
538			status = (*fOutAction)(m, (void*)fPrivateInterface);
539
540		IORecursiveLockUnlock(ipLock);
541	}
542	else
543		freePacket(m);
544
545	return status;
546}
547
548UInt32 IOFireWireIP::outputPacket(mbuf_t pkt, void * param)
549{
550	IOReturn status = kIOReturnOutputDropped;
551
552	// Its just a sink, until we get a valid unit on the bus.
553	((IOFireWireIP*)param)->freePacket(pkt);
554
555	return status;
556}
557
558/*-------------------------------------------------------------------------
559 * Called by IOEthernetInterface client to enable the controller.
560 * This method is always called while running on the default workloop
561 * thread.
562 *-------------------------------------------------------------------------*/
563IOReturn IOFireWireIP::enable(IONetworkInterface * netif)
564{
565    /*
566     * If an interface client has previously enabled us,
567     * and we know there can only be one interface client
568     * for this driver, then simply return true.
569     */
570    if (netifEnabled)
571    {
572        IOLog("IOFireWireIP: already enabled\n");
573        return kIOReturnSuccess;
574    }
575
576    /*
577     * Mark the controller as enabled by the interface.
578     */
579    netifEnabled = true;
580
581	/*
582     * Start our IOOutputQueue object.
583     */
584    transmitQueue->setCapacity( TRANSMIT_QUEUE_SIZE );
585    transmitQueue->start();
586
587    return kIOReturnSuccess;
588
589}// end enable netif
590
591
592/*-------------------------------------------------------------------------
593 * Called by IOEthernetInterface client to disable the controller.
594 * This method is always called while running on the default workloop
595 * thread.
596 *-------------------------------------------------------------------------*/
597IOReturn IOFireWireIP::disable(IONetworkInterface * /*netif*/)
598{
599    netifEnabled = false;
600
601	/*
602     * Disable our IOOutputQueue object. This will prevent the
603     * outputPacket() method from being called.
604     */
605    transmitQueue->stop();
606
607    /*
608     * Flush all packets currently in the output queue.
609     */
610    transmitQueue->setCapacity( 0 );
611    transmitQueue->flush();
612
613    return kIOReturnSuccess;
614
615}// end disable netif
616
617
618IOReturn IOFireWireIP::getPacketFilters( const OSSymbol	*group, UInt32 *filters ) const
619{
620	return super::getPacketFilters( group, filters );
621}// end getPacketFilters
622
623
624IOReturn IOFireWireIP::setWakeOnMagicPacket( bool active )
625{
626	return kIOReturnSuccess;
627}// end setWakeOnMagicPacket
628
629const OSString * IOFireWireIP::newVendorString() const
630{
631    return OSString::withCString("Apple");
632}
633
634const OSString * IOFireWireIP::newModelString() const
635{
636    return OSString::withCString("fw+");
637}
638
639const OSString * IOFireWireIP::newRevisionString() const
640{
641    return OSString::withCString("");
642}
643
644IOReturn IOFireWireIP::setPromiscuousMode( bool active )
645{
646	isPromiscuous	= active;
647
648	return kIOReturnSuccess;
649} // end setPromiscuousMode
650
651IOReturn IOFireWireIP::setMulticastMode( bool active )
652{
653	multicastEnabled = active;
654
655	return kIOReturnSuccess;
656}// end setMulticastMode
657
658IOReturn IOFireWireIP::setMulticastList(IOFWAddress *addrs, UInt32 count)
659{
660	multicastCacheHandler(addrs, count);
661
662    return kIOReturnSuccess;
663}
664
665/*!
666	@function createMediumState
667	@abstract
668	@param none.
669	@result create a supported medium information and
670			attach to the IONetworkingFamily.
671*/
672bool IOFireWireIP::createMediumState()
673{
674	OSDictionary * mediumDict = OSDictionary::withCapacity(5);
675	if (!mediumDict)
676	{
677		return false;
678	}
679
680	IONetworkMedium * medium = IONetworkMedium::medium(
681								(IOMediumType)kIOMediumEthernetAuto |
682								kIOMediumOptionFullDuplex, fLcb->maxBroadcastSpeed);
683	if (medium)
684	{
685		mediumDict->setObject(medium->getKey(), medium);
686		setCurrentMedium(medium);
687		medium->release();
688	}
689
690	if (!publishMediumDictionary(mediumDict))
691	{
692		return false;
693	}
694
695	if( mediumDict )
696	{
697		mediumDict->release();
698	}
699
700	// Link status is Valid and inactive
701	return setLinkStatus( kIONetworkLinkValid, getCurrentMedium(), 0 );
702}
703
704/*!
705	@function getFeatures
706	@abstract
707	@param none.
708	@result Tell family we can handle multipage mbufs. kIONetworkFeatureMultiPages
709*/
710UInt32 IOFireWireIP::getFeatures() const
711{
712    UInt32 result = 0;
713
714#if VERSION_MAJOR >= 9
715    result |= kIONetworkFeatureMultiPages;
716#endif
717
718    return result;
719}
720
721#pragma mark -
722#pragma mark ��� IOFirewireIP methods ���
723
724
725/*!
726	@function getBytesFromGUID
727	@abstract constructs byte array from the GUID.
728	@param fwuid - GUID of the node.
729	@param bufAddr - pointer to the buffer.
730	@result void.
731*/
732void IOFireWireIP::getBytesFromGUID(void *guid, UInt8 *bufAddr, UInt8 type)
733{
734	u_long lo=0, hi=0;
735
736	if(type == GUID_TYPE)
737	{
738		CSRNodeUniqueID	*fwuid = (CSRNodeUniqueID*)guid;
739	    hi	=	(u_long)(*fwuid >> 32);
740		lo	=	(u_long)(*fwuid & 0xffffffff);
741	}
742	else
743	{
744		UWIDE *eui64 = (UWIDE*)guid;
745		hi	=	eui64->hi;
746		lo	=	eui64->lo;
747	}
748
749	bufAddr[0] = (unsigned char)((hi >> 24) & 0x000000ff);
750	bufAddr[1] = (unsigned char)((hi >> 16) & 0x000000ff);
751    bufAddr[2] = (unsigned char)((hi >> 8) & 0x000000ff);
752    bufAddr[3] = (unsigned char)((hi) & 0x000000ff);
753
754	bufAddr[4] = (unsigned char)((lo >> 24) & 0x000000ff);
755	bufAddr[5] = (unsigned char)((lo >> 16) & 0x000000ff);
756	bufAddr[6] = (unsigned char)((lo >> 8) & 0x000000ff);
757    bufAddr[7] = (unsigned char)((lo) & 0x000000ff);
758}
759
760/*!
761	@function makeEthernetAddress
762	@abstract constructs mac address from the GUID.
763	@param fwuid - GUID of the node.
764	@param bufAddr - pointer to the buffer.
765	@param vendorID - vendorID.
766	@result void.
767*/
768void IOFireWireIP::makeEthernetAddress(CSRNodeUniqueID	*fwuid, UInt8 *bufAddr, UInt32 vendorID)
769{
770	getBytesFromGUID(fwuid, bufAddr, GUID_TYPE);
771}
772
773void IOFireWireIP::updateMTU(UInt32 mtu)
774{
775	networkInterface->setIfnetMTU( mtu );
776}
777
778UInt32	IOFireWireIP::getMaxARDMAPacketSize()
779{
780	UInt32	maxARDMASize = 0;
781
782	OSObject *regProperty = fControl->getProperty("FWARDMAMax", gIOServicePlane);
783
784	if(regProperty != NULL)
785	{
786		maxARDMASize = ((OSNumber*)regProperty)->unsigned32BitValue();
787		maxARDMASize -= sizeof(IP1394_UNFRAG_HDR);
788	}
789
790	return maxARDMASize;
791}
792
793UInt8	IOFireWireIP::getMaxARDMARec(UInt32 size)
794{
795    UInt8 maxRecLog	 = 1;
796
797    while( (size >= 8) && (maxRecLog < 15) )
798    {
799        size >>= 1;
800        maxRecLog++;
801    }
802
803	return maxRecLog;
804}
805
806bool IOFireWireIP::clientStarting()
807{
808    IORecursiveLockLock(ipLock);
809
810	bool status = fClientStarting;
811
812	if ( fClientStarting == false )
813	{
814		fClientStarting = true;
815	}
816
817    IORecursiveLockUnlock(ipLock);
818
819	return status;
820}
821
822void IOFireWireIP::registerFWIPPrivateHandlers(IOFireWireIPPrivateHandlers *privateSelf)
823{
824	if(busifEnabled)
825		return;
826
827    IORecursiveLockLock(ipLock);
828
829	fPrivateInterface		= privateSelf->newService;
830	fOutAction				= privateSelf->transmitPacket;
831	fUpdateARPCache			= privateSelf->updateARPCache;
832	fUpdateMulticastCache	= privateSelf->updateMulticastCache;
833
834	busifEnabled		= true;
835
836    IORecursiveLockUnlock(ipLock);
837}
838
839void IOFireWireIP::deRegisterFWIPPrivateHandlers()
840{
841	if ( not busifEnabled)
842		return;
843
844    IORecursiveLockLock(ipLock);
845
846	// Last unit is going away
847	busifEnabled		= false;
848	fPrivateInterface	= NULL;
849	fOutAction			= NULL;
850	fUpdateARPCache		= NULL;
851	fClientStarting		= false;
852
853    IORecursiveLockUnlock(ipLock);
854}
855
856/*!
857	@function fwIPUnitAttach
858	@abstract Callback for a Unit attached of type IP1394
859	@param target - callback data.
860	@param refcon - callback data.
861	@param newService - handle to the new IP1394 unit created.
862	@result bool.
863*/
864bool IOFireWireIP::fwIPUnitAttach(void * target, void * refCon, IOService * newService, IONotifier * notifier)
865{
866	if(target == NULL || newService == NULL)
867		return false;
868
869    IOFireWireIP	*fwIPObject = OSDynamicCast(IOFireWireIP, (IOService *)target);
870    if ( not fwIPObject )
871        return false;
872
873    // Create the device reference block for this IP device
874    IOFireWireNub	*fDevice = OSDynamicCast(IOFireWireNub, newService->getProvider());
875    if ( not fDevice )
876        return false;
877
878	// mismatch of new controller and localnode controller results in false
879	if(fwIPObject->fControl != fDevice->getController())
880		return false;
881
882    return true;
883}
884
885/*!
886	@function createIPConfigRomEntry
887	@abstract creates the config rom entry for IP over Firewire.
888	@param 	none
889	@result IOReturn - kIOReturnSuccess or error if failure.
890*/
891IOReturn IOFireWireIP::createIPConfigRomEntry()
892{
893	IOReturn ioStat = kIOReturnSuccess;
894    // Create entries for UnitSpecID and UnitSwVersion
895    fLocalIP1394ConfigDirectory = IOLocalConfigDirectory::create();
896
897    if (!fLocalIP1394ConfigDirectory){
898        ioStat =  kIOReturnError;
899    }
900
901    if(ioStat == kIOReturnSuccess)
902        ioStat = fLocalIP1394ConfigDirectory->addEntry(kConfigUnitSpecIdKey, IP1394_SPEC_ID) ;
903
904    if(ioStat == kIOReturnSuccess)
905        ioStat = fLocalIP1394ConfigDirectory->addEntry(kConfigUnitSwVersionKey, IP1394_VERSION) ;
906
907    // lets publish it
908    if(ioStat == kIOReturnSuccess)
909        ioStat = fControl->AddUnitDirectory(fLocalIP1394ConfigDirectory) ;
910
911    // Create entries for IPv6 UnitSpecID and UnitSwVersion
912    fLocalIP1394v6ConfigDirectory = IOLocalConfigDirectory::create();
913
914    if (!fLocalIP1394v6ConfigDirectory){
915        ioStat =  kIOReturnError;
916    }
917
918	if(ioStat == kIOReturnSuccess)
919		ioStat = fLocalIP1394v6ConfigDirectory->addEntry(kConfigUnitSpecIdKey, IP1394_SPEC_ID) ;
920
921	if(ioStat == kIOReturnSuccess)
922		ioStat = fLocalIP1394v6ConfigDirectory->addEntry(kConfigUnitSwVersionKey, IP1394v6_VERSION) ;
923
924    if(ioStat == kIOReturnSuccess)
925        ioStat = fControl->AddUnitDirectory(fLocalIP1394v6ConfigDirectory) ;
926
927	return ioStat;
928}
929
930#ifdef DEBUG
931void _logMbuf(mbuf_t m)
932{
933	UInt8	*bytePtr;
934
935    if (!m) {
936        IOLog("logMbuf: NULL mbuf\n");
937        return;
938    }
939
940    while (m) {
941        IOLog("m_next   : %p\n", (void*) mbuf_next(m));
942        IOLog("m_nextpkt: %p\n", (void*) mbuf_nextpkt(m));
943        IOLog("m_len    : %d\n",   (UInt) mbuf_len(m));
944        IOLog("m_data   : %p\n", (void*) mbuf_data(m));
945        IOLog("m_type   : %08x\n", (UInt) mbuf_type(m));
946        IOLog("m_flags  : %08x\n", (UInt) mbuf_flags(m));
947
948        if (mbuf_flags(m) & MBUF_PKTHDR)
949            IOLog("mbuf_pkthdr.len  : %d\n", (UInt) mbuf_pkthdr_len(m));
950
951        if (mbuf_flags(m) & M_EXT) {
952           // IOLog("m_ext.ext_buf : %08x\n", (UInt) mbuf_ext(m));
953           // IOLog("m_ext.ext_size: %d\n", (UInt) m->m_ext.ext_size);
954        }
955
956		IOLog("m_data -> \t\t") ;
957
958		if( mbuf_data(m) != NULL){
959
960			bytePtr = (UInt8*)mbuf_data(m);
961
962			for(SInt32 index=0; index < min(mbuf_len(m), 12); index++)
963			{
964				if ((index & 0x3) == 0)
965				{
966					IOLog(" ") ;
967					if ((index & 0x7) == 0)
968					{
969						IOLog("   ") ;
970						if ((index & 0xF) == 0)
971							IOLog("\n\t\t") ;
972					}
973				}
974				IOLog("%02X", (unsigned char)bytePtr[index]) ;
975			}
976			IOLog("\n\n") ;
977		}
978
979        m = mbuf_next(m);
980    }
981    IOLog("\n");
982}
983
984void _logPkt(void *pkt, UInt16 len)
985{
986	UInt8 	*bytePtr;
987
988	bytePtr = (UInt8*)pkt;
989
990	IOLog("pkt {\n") ;
991
992	for(SInt32 index=0; index<len; index++)
993	{
994		if ((index & 0x3) == 0)
995		{
996			IOLog(" ") ;
997			if ((index & 0x7) == 0)
998			{
999				IOLog("   ") ;
1000				if ((index & 0xF) == 0)
1001					IOLog("\n\t\t") ;
1002			}
1003		}
1004		IOLog("%02X", (unsigned char)bytePtr[index]) ;
1005	}
1006	IOLog("}\n\n") ;
1007}
1008#endif
1009