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
23#ifndef _IOKIT_IOFWIPBUSINTERFACE_H
24#define _IOKIT_IOFWIPBUSINTERFACE_H
25
26#include <IOKit/IOService.h>
27#include <IOKit/IOMessage.h>
28#include <IOKit/IOLib.h>
29#include "IOFireWireIP.h"
30
31#define FIREWIREPRIVATE
32
33#include <IOKit/firewire/IOFireWireController.h>
34#include <IOKit/firewire/IOFWAsyncStreamListener.h>
35
36
37class IOFireWireController;
38class IOFWAsyncStreamListener;
39class IOFWIPAsyncWriteCommand;
40
41const int		kWaitSecs				= 5;
42const int		kUnicastArbs			= 128;
43const int		kMulticastArbs			= 64;
44const int		kActiveDrbs				= 128;
45const int		kActiveRcbs				= 128;
46const int		kMaxChannels			= 64;
47const int		kMaxAsyncCommands		= 127;
48const int		kMaxAsyncStreamCommands = 5;
49const int		kRCBExpirationtime		= 2; // 2 seconds active time for reassembly control blocks, decremented by watchdog
50
51const bool		kCopyBuffers			= false; // Set to true if need to copy the payload
52const bool		kQueueCommands			= false; // Set to true if need to queue the block write packets
53
54const UInt32	kLowWaterMark			= 48;	 // Low water mark for commands in the pre-allocated pool
55const UInt32	kWatchDogTimerMS		= 1000;  // Watch dog timeout set to 1 sec = 1000 milli second
56const UInt32	kMaxPseudoAddressSize	= 4096;
57
58// BusyX Ack workaround to maximize IPoFW performance
59const UInt32 kMaxBusyXAcksPerSecond				= 10;
60const UInt32 kMaxSecondsToTurnOffFastRetry		= 60;
61
62class IOFWIPMBufCommand : public IOCommand
63{
64	OSDeclareDefaultStructors(IOFWIPMBufCommand);
65
66private:
67    mbuf_t			fMbuf;
68    IOFireWireIP	*fIPLocalNode;
69	bool			fInited;
70	IOReturn		fStatus;
71	IOCommandPool	*fPool;
72
73protected:
74	void free();
75
76public:
77	bool init();
78	void reinit(mbuf_t pkt, IOFireWireIP *ipNode, IOCommandPool *pool);
79	void releaseWithStatus(IOReturn status = kIOReturnSuccess);
80	mbuf_t getMBuf();
81};
82
83/*!
84@class IOFWIPBusInterface
85@abstract Object to seperate IP over FireWire's firewire services.
86*/
87class IOFWIPBusInterface : public IOService
88{
89    OSDeclareDefaultStructors(IOFWIPBusInterface)
90
91private:
92	IOFireWireIP			*fIPLocalNode;
93	IOFireWireController	*fControl;
94	LCB						*fLcb;
95
96    IOFWPseudoAddressSpace	*fIP1394AddressSpace;
97    FWAddress				fIP1394Address;
98	bool					fStarted;
99
100    IOCommandPool			*fAsyncCmdPool;
101    IOCommandPool			*fMbufCmdPool;
102	IOCommandPool			*fRCBCmdPool;
103	OSSet					*fAsyncTransitSet;
104    IOCommandPool			*fAsyncStreamTxCmdPool;
105	OSSet					*fAsyncStreamTransitSet;
106	UInt32					fMaxTxAsyncDoubleBuffer;
107	IORecursiveLock			*fIPLock;
108    IOWorkLoop				*workLoop;
109
110	OSSet					*unicastArb;        // Address information from ARP
111	OSSet					*multicastArb;      // Address information from MCAP
112    OSSet					*activeDrb;         // Devices with valid device IDs
113    OSSet					*activeRcb;         // Linked list of datagrams in reassembly
114    OSArray					*mcapState;			// Per channel MCAP descriptors
115	IOTimerEventSource		*timerSource;
116	SInt16					fUnitCount;
117	UInt32					fLowWaterMark;
118	UInt32					fPrevTransmitCount;
119	UInt32					fPrevBusyAcks;
120	UInt32					fPrevFastRetryBusyAcks;
121	UInt8					fFastRetryUnsetTimer;
122	int						fCurrentAsyncIPCommands;
123	int						fCurrentMBufCommands;
124	int						fCurrentRCBCommands;
125	UInt32					fOptimalMTU;
126
127protected:
128	IOFWAsyncStreamListener	*fBroadcastReceiveClient;
129
130	// Instance methods:
131	/*!
132		@struct ExpansionData
133        @discussion This structure will be used to expand the capablilties of the class in the future.
134	*/
135    struct ExpansionData { };
136
137    /*!
138		@var reserved
139        Reserved for future use.  (Internal use only)
140	*/
141    ExpansionData *reserved;
142
143
144
145public:
146	// IOService overrides
147	bool		init(IOFireWireIP *provider);
148
149	bool		finalize(IOOptionBits options);
150
151	void		stop(IOService *provider);
152
153	void		free();
154
155	IOReturn	message(UInt32 type, IOService *provider, void *argument);
156
157	void		processWatchDogTimeout();
158
159	bool		attachIOFireWireIP(IOFireWireIP *provider);
160
161	void		detachIOFireWireIP();
162
163	/*!
164		@function calculateMaxTransferUnit
165		@abstract checks whether the FWIM is for builtin H/W.
166		@param none.
167		@result Returns void.
168	*/
169	void	calculateMaxTransferUnit();
170
171	/*!
172		@function createIPFifoAddress
173		@abstract creates the pseudo address space for IP over Firewire.
174		@param 	UInt32 fifosize - size of the pseudo address space
175		@result IOReturn - kIOReturnSuccess or error if failure.
176	*/
177	IOReturn createIPFifoAddress(UInt32 fifosize);
178
179	/*!
180		@function initAsyncStreamCmdPool
181		@abstract constructs Asyncstream Send command objects and queues them in the pool
182		@param none.
183        @result Returns kIOReturnSuccess if it was successful, else kIOReturnNoMemory.
184	*/
185	UInt32 initAsyncStreamCmdPool();
186
187	/*!
188		@function initAsyncCmdPool
189		@abstract constructs Asynchronous Send command objects and queues them in the pool
190		@param none.
191        @result Returns kIOReturnSuccess if it was successful, else kIOReturnNoMemory.
192	*/
193	UInt32 initAsyncCmdPool();
194
195	IOFWIPMBufCommand *getMBufCommand();
196
197	IOFWIPAsyncWriteCommand	*getAsyncCommand(bool block, bool *deferNotify);
198
199	void	returnAsyncCommand(IOFWIPAsyncWriteCommand *cmd);
200
201	/*!
202		@function freeIPCmdPool
203		@abstract frees the command objects from the pool
204		@param none.
205        @result void.
206	*/
207	void	freeAsyncCmdPool();
208
209	/*!
210		@function freeAsyncStreamCmdPool
211		@abstract frees the command objects from the pool
212		@param none.
213        @result void.
214	*/
215	void	freeAsyncStreamCmdPool();
216
217	ARB		*updateARBwithDevice(IOFireWireNub *device, UWIDE eui64);
218
219	DRB		*initDRBwithDevice(UWIDE eui64, IOFireWireNub *fDevObj, bool itsMac);
220
221	static	DRB	*staticInitDRBwithDevice(void *refcon, UWIDE eui64, IOFireWireNub *fDevObj, bool itsMac);
222
223    /*!
224		@function incrementUnitCount
225		@abstract Increments the unit count
226    */
227	void incrementUnitCount();
228
229    /*!
230		@function decrementUnitCount
231		@abstract Decrements the unit count
232    */
233	void decrementUnitCount();
234
235	SInt16 getUnitCount();
236
237	/*!
238		@function fwIPUnitAttach
239		@abstract Callback for a Unit Attach of type IPv4 or IPv6
240        @result void.
241	*/
242	void fwIPUnitAttach();
243
244	/*!
245		@function fwIPUnitTerminate
246		@abstract Callback for a Unit detach of type IPv4 or IPv6
247        @result void.
248	*/
249	void fwIPUnitTerminate();
250
251	/*!
252		@function updateBroadcastValues
253		@abstract Updates the max broadcast payload and speed
254		@param reset - useful to know whether to start from beginning.
255		@result void.
256	*/
257	void updateBroadcastValues(bool reset);
258
259	/*!
260		@function updateLinkStatus
261		@abstract Updates the link status based on maxbroadcast speed & payload.
262		@param None.
263		@result void.
264	*/
265	void updateLinkStatus();
266
267	UInt32	getMTU();
268
269	/*!
270		@function txCompleteBlockWrite
271		@abstract Callback for the Async write complete
272		@param refcon - callback data.
273        @param status - status of the command.
274        @param device - device.
275        @param fwCmd - command object which generated the transaction.
276        @result void.
277	*/
278	static void txCompleteBlockWrite(void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd);
279
280	/*!
281		@function txAsyncStreamComplete
282		@abstract Callback for the Async stream transmit complete
283		@param refcon - callback data.
284        @param status - status of the command.
285        @param bus information.
286        @param fwCmd - command object which generated the transaction.
287        @result void.
288	*/
289	static void txCompleteAsyncStream(void *refcon, IOReturn status, IOFireWireBus *bus, IOFWAsyncStreamCommand *fwCmd);
290
291	/*!
292		@function txARP
293		@abstract Transmit ARP request or response.
294		@param ifp - ifnet pointer.
295		@param m - mbuf containing the ARP packet.
296		@param nodeID - our node id.
297        @result void.
298	*/
299	SInt32  txARP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, IOFWSpeed speed);
300
301	SInt32	txBroadcastIP(const mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, UInt16 maxBroadcastPayload, IOFWSpeed speed, const UInt16 type, UInt32 channel);
302
303	SInt32	txUnicastUnFragmented(IOFireWireNub *device, const FWAddress addr, const mbuf_t m, const UInt16 pktSize, const UInt16 type);
304
305	SInt32	txUnicastFragmented(IOFireWireNub *device, const FWAddress addr, const mbuf_t m,
306												const UInt16 pktSize, const UInt16 type, UInt16 maxPayload, UInt16 dgl);
307
308	SInt32	txUnicastIP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, IOFWSpeed speed,const UInt16 type);
309
310	UInt32	outputPacket(mbuf_t pkt, void * param);
311
312	static  UInt32	staticOutputPacket(mbuf_t pkt, void * param);
313
314	IOTransmitPacket		getOutputHandler() const;
315
316	IOUpdateARPCache		getARPCacheHandler() const;
317
318	IOUpdateMulticastCache	getMulticastCacheHandler() const;
319
320	/*!
321		@function txIP
322		@abstract Transmit IP packet.
323		@param m - mbuf containing the IP packet.
324        @result SInt32 - can be EHOSTUNREACH or 0;
325	*/
326	SInt32 txIP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, UInt16 maxBroadcastPayload, IOFWSpeed speed, UInt16 type);
327
328	IOReturn createAsyncStreamRxClient(UInt8 speed, UInt32 channel, MCB *mcb);
329
330	/*!
331		@function txMCAP
332		@abstract multicast solicitation and advertisement messages.
333		@param MCB*			- mcb - multicast channel control block
334		@param ipAddress	- address of the multicast group.
335        @result void.
336	*/
337	void txMCAP(MCB *mcb, UInt32 groupAddress);
338
339	/*!
340		@function rxUnicastFlush
341		@abstract Starts the batch processing of the packets, its
342				already on its own workloop.
343	*/
344	void rxUnicastFlush();
345
346	/*!
347		@function rxUnicastComplete
348		@abstract triggers the indication workloop to do batch processing
349					of incoming packets.
350	*/
351	static void rxUnicastComplete(void *refcon);
352
353	/*!
354		@function rxUnicast
355		@abstract block write handler
356	*/
357	static UInt32	rxUnicast(void *refcon, UInt16 nodeID, IOFWSpeed	&speed, FWAddress addr, UInt32	len, const void *buf, IOFWRequestRefCon requestRefcon);
358
359	IOReturn rxFragmentedUnicast(UInt16 nodeID, IP1394_FRAG_HDR *pkt, UInt32 len);
360
361	/*!
362		@function rxAsyncStream
363		@abstract callback for an Asyncstream packet, can be both IP or ARP packet.
364				This procedure receives an indication when an asynchronous stream
365				packet arrives on the default broadcast channel. The packet "should" be GASP,
366				but we perform a few checks to make sure. Once we know these are OK, we check
367				the etherType field in the unfragmented encapsulation header. This is necessary
368				to dispatch the three types of packet that RFC 2734 permits on the default
369				broadcast channel: an IPv4 datagram, and ARP request or response or a multi-
370				channel allocation protocol (MCAP) message. The only remaining check, for each
371				of these three cases, is to make sure that the packet is large enough to hold
372				meaningful data. If so, send the packet to another procedure for further
373				processing.
374		@param DCLCommandStruct *callProc.
375		@result void.
376	*/
377	static void rxAsyncStream(void *refcon, const void *buf);
378
379	/*!
380		@function rxMCAP
381		@abstract called from rxAsyncstream for processing MCAP advertisement.
382				When an MCAP advertisement is received, parse all of its descriptors
383				looking for any that match group addreses in our MCAP cache. For those that
384				match, update  the channel number (it may have changed from the default
385				broadcast channel or since the last advertisement), update the speed
386				(the MCAP owner may have changed the speed requirements as nodes joined or
387				left the group) and refresh the expiration timer so that the MCAP
388				channel is valid for another number of seconds into the future.
389				Th-th-th-that's all, folks!
390		@param lcb - the firewire link control block for this interface.
391		@param mcapSourceID - source nodeid which generated the multicast advertisement packet.
392		@param mcap - mulitcast advertisment packet without the GASP header.
393		@param dataSize - size of the packet.
394		@result void.
395	*/
396	void rxMCAP(LCB *lcb, UInt16 mcapSourceID, IP1394_MCAP *mcap, UInt32 dataSize);
397
398	/*!
399		@function rxIP
400		@abstract Receive IP packet.
401		@param fwIPObj - IOFireWireIP object.
402		@param pkt - points to the IP packet without the header.
403		@param len - length of the packet.
404		@params flags - indicates broadcast or unicast
405		@params type - indicates type of the packet IPv4 or IPv6
406		@result IOReturn.
407	*/
408	IOReturn rxIP(void *pkt, UInt32 len, UInt32 flags, UInt16 type);
409
410	/*!
411		@function rxARP
412		@abstract ARP processing routine called from both Asynstream path and Async path.
413		@param fwIPObj - IOFireWireIP object.
414		@param arp - 1394 arp packet without the GASP or Async header.
415		@params flags - indicates broadcast or unicast
416        @result IOReturn.
417	*/
418	IOReturn rxARP(IP1394_ARP *arp, UInt32 flags);
419
420	static bool staticUpdateARPCache(void *refcon, IP1394_ARP *fwa);
421
422	static bool staticUpdateMulticastCache(void *refcon, IOFWAddress *addrs, UInt32 count);
423
424	bool updateARPCache(IP1394_ARP *fwa);
425
426	bool wellKnownMulticastAddress(IOFWAddress *addr);
427
428	bool updateMulticastCache(IOFWAddress *addrs, UInt32 count);
429
430	/*!
431		@function getRcb
432		@abstract Locates a reassembly control block.
433		@param lcb - the firewire link control block for this interface.
434        @param sourceID - source nodeid which generated the fragmented packet.
435        @param dgl - datagram label for the fragmented packet.
436        @result Returns RCB if successfull else NULL.
437	*/
438	RCB *getRcb(UInt16 sourceID, UInt16 dgl);
439
440	RCB *getRCBCommand( UInt16 sourceID, UInt16 dgl, UInt16 etherType, UInt16 datagramSize, mbuf_t m );
441
442	/*!
443		@function getMulticastArb
444		@abstract Locates the corresponding multicast ARB (Address resolution block) for ipaddress
445		@param lcb			- the firewire link control block for this interface.
446        @param groupAddress - destination ipaddress to send the multicast packet.
447        @result Returns ARB if successfull else NULL.
448	*/
449	MARB *getMulticastArb(UInt32 groupAddress);
450
451	/*!
452		@function getDrbFromDeviceID
453		@abstract Locates the corresponding DRB (Address resolution block) for IOFireWireNub
454		@param lcb - the firewire link control block for this interface.
455        @param deviceID - IOFireWireNub to look for.
456        @result Returns DRB if successfull else NULL.
457	*/
458	DRB *getDrbFromDeviceID(void *deviceID);
459
460	bool addNDPOptions(mbuf_t m);
461
462    bool updateNDPCache(mbuf_t m);
463
464	void updateNDPCache(void *buf, UInt16 *len);
465
466	/*!
467		@function getARBFromEui64
468		@abstract Locates the corresponding Unicast ARB (Address resolution block) for GUID
469        @param eui64 - global unique id of a device on the bus.
470        @result Returns ARB if successfull else NULL.
471	*/
472	ARB *getARBFromEui64(UWIDE eui64);
473
474	static ARB *staticGetARBFromEui64(void *refcon, UWIDE eui64);
475
476	/*!
477		@function getDeviceID
478		@abstract returns a fireWire device object for the GUID
479		@param lcb - the firewire link control block for this interface.
480		@param eui64 - global unique id of a device on the bus.
481		@param itsMac - destination is Mac or not.
482		@result Returns IOFireWireNub if successfull else 0.
483	*/
484	void* getDeviceID(UWIDE eui64, bool *itsMac);
485
486	/*!
487		@function getDrbFromEui64
488		@abstract Locates the corresponding DRB (device reference block) for GUID
489		@param lcb - the firewire link control block for this interface.
490        @param eui64 - global unique id of a device on the bus.
491        @result Returns DRB if successfull else NULL.
492	*/
493	DRB *getDrbFromEui64(UWIDE eui64);
494
495
496	/*!
497		@function getDrbFromFwAddr
498		@abstract Locates the corresponding DRB (device reference block) for GUID
499		@param lcb - the firewire link control block for this interface.
500		@param fwaddr - global unique id of a device on the bus.
501		@result Returns DRB if successfull else NULL.
502	*/
503	DRB *getDrbFromFwAddr(UInt8 *fwaddr);
504
505	/*!
506		@function getArbFromFwAddr
507		@abstract Locates the corresponding Unicast ARB (Address resolution block) for GUID
508		@param FwAddr - global unique id of a device on the bus.
509		@result Returns ARB if successfull else NULL.
510	*/
511	ARB *getArbFromFwAddr(UInt8 *fwaddr);
512
513	static ARB *staticGetArbFromFwAddr(void *refcon, UInt8 *fwaddr);
514
515	/*!
516		@function getUnicastArb
517		@abstract Locates the corresponding unicast ARB (Address resolution block) for ipaddress
518        @param ipAddress - destination ipaddress to send the unicast packet.
519        @result Returns ARB if successfull else NULL.
520	*/
521	ARB *getUnicastArb(UInt32 ipAddress);
522
523	/*!
524		@function cleanRCBCache
525		@abstract cleans the Link control block's stale rcb's. UnAssembled RCB's
526					are returned to the free CBLKs
527		@param none.
528		@result void.
529	*/
530	void cleanRCBCache();
531
532	void releaseRCB(RCB	*rcb, bool freeMbuf = true);
533
534	void resetMARBCache();
535
536	void resetRCBCache();
537
538	void resetMcapState();
539
540	void releaseDRB(UInt8 *fwaddr);
541
542	void releaseDRB(UInt32 deviceID);
543
544	void releaseARB(UInt8 *fwaddr);
545
546	void updateMcapState();
547
548	void releaseMulticastARB(MCB *mcb);
549
550    mbuf_t allocateMbuf(UInt32 size);
551
552	/*!
553		@function bufferToMbuf
554		@abstract Copies buffer to Mbuf.
555		@param m - destination mbuf.
556		@param offset - offset into the mbuf data pointer.
557		@param srcbuf - source buf.
558		@param srcbufLen - source buffer length.
559		@result bool - true if success else false.
560	*/
561	bool bufferToMbuf(mbuf_t		m,
562					  UInt32		offset,
563					  vm_address_t	*srcbuf,
564					  UInt32		srcbufLen);
565
566	/*!
567		@function mbufTobuffer
568		@abstract Copies mbuf data into the buffer pointed by IOMemoryDescriptor.
569		@param src - source mbuf.
570		@param offset - offset into the mbuf data pointer.
571		@param dstbuf - destination buf.
572		@param dstbufLen - destination buffer length.
573		@param length - length to copy.
574        @result NULL if copied else should be invoked again till
575					the residual is copied into the buffer.
576	*/
577	mbuf_t mbufTobuffer(const mbuf_t	src,
578						UInt32			*offset,
579						vm_address_t	*dstbuf,
580						UInt32			dstbufLen,
581						UInt32			length);
582
583	void moveMbufWithOffset(SInt32 tempOffset, mbuf_t *srcm, vm_address_t *src, SInt32 *srcLen);
584
585#ifdef DEBUG
586	void showRcb(RCB *rcb);
587	void showMinRcb(RCB *rcb);
588	void showArb(ARB *arb);
589	void showHandle(TNF_HANDLE *handle);
590	void showDrb(DRB *drb);
591	void showLcb();
592#endif
593};
594
595#endif
596