/* * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef _IOKIT_IOFWIPBUSINTERFACE_H #define _IOKIT_IOFWIPBUSINTERFACE_H #include <IOKit/IOService.h> #include <IOKit/IOMessage.h> #include <IOKit/IOLib.h> #include "IOFireWireIP.h" class IOFWIPAsyncWriteCommand; const int kWaitSecs = 5; const int kUnicastArbs = 128; const int kMulticastArbs = 64; const int kActiveDrbs = 128; const int kActiveRcbs = 128; const int kMaxChannels = 64; const int kMaxAsyncCommands = 127; const int kMaxAsyncStreamCommands = 5; // BusyX Ack workaround to maximize IPoFW performance const UInt32 kMaxBusyXAcksPerSecond = 10; const UInt32 kMaxSecondsToTurnOffFastRetry = 60; class IOFWIPMBufCommand : public IOCommand { OSDeclareDefaultStructors(IOFWIPMBufCommand); private: mbuf_t fMbuf; IOFireWireIP *fIPLocalNode; bool fInited; IOReturn fStatus; IOCommandPool *fPool; protected: void free(); public: bool init(); void reinit(mbuf_t pkt, IOFireWireIP *ipNode, IOCommandPool *pool); void releaseWithStatus(IOReturn status = kIOReturnSuccess); mbuf_t getMBuf(); }; /*! @class IOFWIPBusInterface @abstract Object to seperate IP over FireWire's firewire services. */ class IOFWIPBusInterface : public IOService { OSDeclareDefaultStructors(IOFWIPBusInterface) private: IOFireWireIP *fIPLocalNode; IOFireWireController *fControl; LCB *fLcb; IOFWPseudoAddressSpace *fIP1394AddressSpace; FWAddress fIP1394Address; bool fStarted; IOCommandPool *fAsyncCmdPool; IOCommandPool *fMbufCmdPool; OSSet *fAsyncTransitSet; IOCommandPool *fAsyncStreamTxCmdPool; OSSet *fAsyncStreamTransitSet; UInt32 fMaxRxIsocPacketSize; UInt32 fMaxTxAsyncDoubleBuffer; IORecursiveLock *fIPLock; IOWorkLoop *workLoop; OSSet *unicastArb; // Address information from ARP OSSet *multicastArb; // Address information from MCAP OSSet *activeDrb; // Devices with valid device IDs OSSet *activeRcb; // Linked list of datagrams in reassembly OSDictionary *mcapState; // Per channel MCAP descriptors IOTimerEventSource *timerSource; volatile SInt16 fUnitCount; UInt32 fLowWaterMark; UInt32 fPrevTransmitCount; UInt32 fPrevBusyAcks; UInt32 fPrevFastRetryBusyAcks; UInt8 fFastRetryUnsetTimer; int fCurrentAsyncIPCommands; int fCurrentMBufCommands; protected: IOFWAsyncStreamRxCommand *fBroadcastReceiveClient; // Instance methods: /*! @struct ExpansionData @discussion This structure will be used to expand the capablilties of the class in the future. */ struct ExpansionData { }; /*! @var reserved Reserved for future use. (Internal use only) */ ExpansionData *reserved; public: // IOService overrides bool init(IOFireWireIP *provider); bool finalize(IOOptionBits options); void free(); IOReturn message(UInt32 type, IOService *provider, void *argument); void processWatchDogTimeout(); bool attachIOFireWireIP(IOFireWireIP *provider); void detachIOFireWireIP(); /*! @function calculateMaxTransferUnit @abstract checks whether the FWIM is for builtin H/W. @param none. @result Returns void. */ void calculateMaxTransferUnit(); /*! @function createIPFifoAddress @abstract creates the pseudo address space for IP over Firewire. @param UInt32 fifosize - size of the pseudo address space @result IOReturn - kIOReturnSuccess or error if failure. */ IOReturn createIPFifoAddress(UInt32 fifosize); IOReturn stopReceivingBroadcast(); IOReturn startReceivingBroadcast(IOFWSpeed speed); /*! @function initAsyncStreamCmdPool @abstract constructs Asyncstream Send command objects and queues them in the pool @param none. @result Returns kIOReturnSuccess if it was successful, else kIOReturnNoMemory. */ UInt32 initAsyncStreamCmdPool(); /*! @function initAsyncCmdPool @abstract constructs Asynchronous Send command objects and queues them in the pool @param none. @result Returns kIOReturnSuccess if it was successful, else kIOReturnNoMemory. */ UInt32 initAsyncCmdPool(); IOFWIPMBufCommand *getMBufCommand(); IOFWIPAsyncWriteCommand *getAsyncCommand(bool block, bool *deferNotify); void returnAsyncCommand(IOFWIPAsyncWriteCommand *cmd); /*! @function freeIPCmdPool @abstract frees the command objects from the pool @param none. @result void. */ void freeAsyncCmdPool(); /*! @function freeAsyncStreamCmdPool @abstract frees the command objects from the pool @param none. @result void. */ void freeAsyncStreamCmdPool(); ARB *updateARBwithDevice(IOFireWireNub *device, UWIDE eui64); DRB *initDRBwithDevice(UWIDE eui64, IOFireWireNub *fDevObj, bool itsMac); static DRB *staticInitDRBwithDevice(void *refcon, UWIDE eui64, IOFireWireNub *fDevObj, bool itsMac); /*! @function incrementUnitCount @abstract Increments the unit count */ void incrementUnitCount(); /*! @function decrementUnitCount @abstract Decrements the unit count */ void decrementUnitCount(); SInt16 getUnitCount(); /*! @function fwIPUnitAttach @abstract Callback for a Unit Attach of type IPv4 or IPv6 @result void. */ void fwIPUnitAttach(); /*! @function fwIPUnitTerminate @abstract Callback for a Unit detach of type IPv4 or IPv6 @result void. */ void fwIPUnitTerminate(); /*! @function updateBroadcastValues @abstract Updates the max broadcast payload and speed @param reset - useful to know whether to start from beginning. @result void. */ void updateBroadcastValues(bool reset); /*! @function updateLinkStatus @abstract Updates the link status based on maxbroadcast speed & payload. @param None. @result void. */ void updateLinkStatus(); UInt32 getMTU(); /*! @function txCompleteBlockWrite @abstract Callback for the Async write complete @param refcon - callback data. @param status - status of the command. @param device - device. @param fwCmd - command object which generated the transaction. @result void. */ static void txCompleteBlockWrite(void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd); /*! @function txAsyncStreamComplete @abstract Callback for the Async stream transmit complete @param refcon - callback data. @param status - status of the command. @param bus information. @param fwCmd - command object which generated the transaction. @result void. */ static void txCompleteAsyncStream(void *refcon, IOReturn status, IOFireWireBus *bus, IOFWAsyncStreamCommand *fwCmd); /*! @function txARP @abstract Transmit ARP request or response. @param ifp - ifnet pointer. @param m - mbuf containing the ARP packet. @param nodeID - our node id. @result void. */ SInt32 txARP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, IOFWSpeed speed); SInt32 txBroadcastIP(const mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, UInt16 maxBroadcastPayload, IOFWSpeed speed, const UInt16 type); SInt32 txUnicastUnFragmented(IOFireWireNub *device, const FWAddress addr, const mbuf_t m, const UInt16 pktSize, const UInt16 type); SInt32 txUnicastFragmented(IOFireWireNub *device, const FWAddress addr, const mbuf_t m, const UInt16 pktSize, const UInt16 type, UInt16 maxPayload, UInt16 dgl); SInt32 txUnicastIP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, IOFWSpeed speed,const UInt16 type); UInt32 outputPacket(mbuf_t pkt, void * param); static UInt32 staticOutputPacket(mbuf_t pkt, void * param); IOTransmitPacket getOutputHandler() const; IOUpdateARPCache getARPCacheHandler() const; /*! @function txIP @abstract Transmit IP packet. @param m - mbuf containing the IP packet. @result SInt32 - can be EHOSTUNREACH or 0; */ SInt32 txIP(mbuf_t m, UInt16 nodeID, UInt32 busGeneration, UInt16 ownMaxPayload, UInt16 maxBroadcastPayload, IOFWSpeed speed, UInt16 type); /*! @function txMCAP @abstract multicast solicitation and advertisement messages. @param LCB* - link control block @param MCB* - mcb - multicast channel control block @param ipAddress - address of the multicast group. @result void. */ void txMCAP(LCB *lcb, MCB *mcb, UInt32 ipAddress); /*! @function rxUnicastFlush @abstract Starts the batch processing of the packets, its already on its own workloop. */ void rxUnicastFlush(); /*! @function rxUnicastComplete @abstract triggers the indication workloop to do batch processing of incoming packets. */ static void rxUnicastComplete(void *refcon); /*! @function rxUnicast @abstract block write handler */ static UInt32 rxUnicast(void *refcon, UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len, const void *buf, IOFWRequestRefCon requestRefcon); IOReturn rxFragmentedUnicast(UInt16 nodeID, IP1394_FRAG_HDR *pkt, UInt32 len); /*! @function rxAsyncStream @abstract callback for an Asyncstream packet, can be both IP or ARP packet. This procedure receives an indication when an asynchronous stream packet arrives on the default broadcast channel. The packet "should" be GASP, but we perform a few checks to make sure. Once we know these are OK, we check the etherType field in the unfragmented encapsulation header. This is necessary to dispatch the three types of packet that RFC 2734 permits on the default broadcast channel: an IPv4 datagram, and ARP request or response or a multi- channel allocation protocol (MCAP) message. The only remaining check, for each of these three cases, is to make sure that the packet is large enough to hold meaningful data. If so, send the packet to another procedure for further processing. @param DCLCommandStruct *callProc. @result void. */ static void rxAsyncStream(DCLCommandStruct *dclProgram); /*! @function rxMCAP @abstract called from rxAsyncstream for processing MCAP advertisement. When an MCAP advertisement is received, parse all of its descriptors looking for any that match group addreses in our MCAP cache. For those that match, update the channel number (it may have changed from the default broadcast channel or since the last advertisement), update the speed (the MCAP owner may have changed the speed requirements as nodes joined or left the group) and refresh the expiration timer so that the MCAP channel is valid for another number of seconds into the future. Th-th-th-that's all, folks! @param lcb - the firewire link control block for this interface. @param mcapSourceID - source nodeid which generated the multicast advertisement packet. @param mcap - mulitcast advertisment packet without the GASP header. @param dataSize - size of the packet. @result void. */ void rxMCAP(LCB *lcb, UInt16 mcapSourceID, IP1394_MCAP *mcap, UInt32 dataSize); /*! @function rxIP @abstract Receive IP packet. @param fwIPObj - IOFireWireIP object. @param pkt - points to the IP packet without the header. @param len - length of the packet. @params flags - indicates broadcast or unicast @params type - indicates type of the packet IPv4 or IPv6 @result IOReturn. */ IOReturn rxIP(void *pkt, UInt32 len, UInt32 flags, UInt16 type); /*! @function rxARP @abstract ARP processing routine called from both Asynstream path and Async path. @param fwIPObj - IOFireWireIP object. @param arp - 1394 arp packet without the GASP or Async header. @params flags - indicates broadcast or unicast @result IOReturn. */ IOReturn rxARP(IP1394_ARP *arp, UInt32 flags); static bool staticUpdateARPCache(void *refcon, IP1394_ARP *fwa); bool updateARPCache(IP1394_ARP *fwa); /*! @function getRcb @abstract Locates a reassembly control block. @param lcb - the firewire link control block for this interface. @param sourceID - source nodeid which generated the fragmented packet. @param dgl - datagram label for the fragmented packet. @result Returns RCB if successfull else NULL. */ RCB *getRcb(UInt16 sourceID, UInt16 dgl); /*! @function getMulticastArb @abstract Locates the corresponding multicast ARB (Address resolution block) for ipaddress @param lcb - the firewire link control block for this interface. @param ipAddress - destination ipaddress to send the multicast packet. @result Returns ARB if successfull else NULL. */ MARB *getMulticastArb(UInt32 ipAddress); /*! @function getDrbFromDeviceID @abstract Locates the corresponding DRB (Address resolution block) for IOFireWireNub @param lcb - the firewire link control block for this interface. @param deviceID - IOFireWireNub to look for. @result Returns DRB if successfull else NULL. */ DRB *getDrbFromDeviceID(void *deviceID); bool addNDPOptions(mbuf_t m); void updateNDPCache(mbuf_t m); void updateNDPCache(void *buf, UInt16 *len); /*! @function getARBFromEui64 @abstract Locates the corresponding Unicast ARB (Address resolution block) for GUID @param eui64 - global unique id of a device on the bus. @result Returns ARB if successfull else NULL. */ ARB *getARBFromEui64(UWIDE eui64); static ARB *staticGetARBFromEui64(void *refcon, UWIDE eui64); /*! @function getDeviceID @abstract returns a fireWire device object for the GUID @param lcb - the firewire link control block for this interface. @param eui64 - global unique id of a device on the bus. @param itsMac - destination is Mac or not. @result Returns IOFireWireNub if successfull else 0. */ UInt32 getDeviceID(UWIDE eui64, BOOLEAN *itsMac); /*! @function getDrbFromEui64 @abstract Locates the corresponding DRB (device reference block) for GUID @param lcb - the firewire link control block for this interface. @param eui64 - global unique id of a device on the bus. @result Returns DRB if successfull else NULL. */ DRB *getDrbFromEui64(UWIDE eui64); /*! @function getDrbFromFwAddr @abstract Locates the corresponding DRB (device reference block) for GUID @param lcb - the firewire link control block for this interface. @param fwaddr - global unique id of a device on the bus. @result Returns DRB if successfull else NULL. */ DRB *getDrbFromFwAddr(u_char *fwaddr); /*! @function getArbFromFwAddr @abstract Locates the corresponding Unicast ARB (Address resolution block) for GUID @param FwAddr - global unique id of a device on the bus. @result Returns ARB if successfull else NULL. */ ARB *getArbFromFwAddr(u_char *fwaddr); static ARB *staticGetArbFromFwAddr(void *refcon, u_char *fwaddr); /*! @function getUnicastArb @abstract Locates the corresponding unicast ARB (Address resolution block) for ipaddress @param ipAddress - destination ipaddress to send the unicast packet. @result Returns ARB if successfull else NULL. */ ARB *getUnicastArb(UInt32 ipAddress); /*! @function cleanRCBCache @abstract cleans the Link control block's stale rcb's. UnAssembled RCB's are returned to the free CBLKs @param none. @result void. */ void cleanRCBCache(); void releaseRCB(RCB *rcb, bool freeMbuf = true); void resetARBCache(); void resetRCBCache(); void resetMcapState(); void releaseDRB(u_char *fwaddr); void releaseDRB(ULONG deviceID); void releaseARB(u_char *fwaddr); void updateMcapState(); void releaseMulticastARB(MCB *mcb); mbuf_t allocateMbuf(UInt32 size); /*! @function bufferToMbuf @abstract Copies buffer to Mbuf. @param m - destination mbuf. @param offset - offset into the mbuf data pointer. @param srcbuf - source buf. @param srcbufLen - source buffer length. @result bool - true if success else false. */ bool bufferToMbuf(mbuf_t m, UInt32 offset, UInt8 *srcbuf, UInt32 srcbufLen); /*! @function mbufTobuffer @abstract Copies mbuf data into the buffer pointed by IOMemoryDescriptor. @param src - source mbuf. @param offset - offset into the mbuf data pointer. @param dstbuf - destination buf. @param dstbufLen - destination buffer length. @param length - length to copy. @result NULL if copied else should be invoked again till the residual is copied into the buffer. */ mbuf_t mbufTobuffer(const mbuf_t src, UInt32 *offset, UInt8 *dstbuf, UInt32 dstbufLen, UInt32 length); void moveMbufWithOffset(SInt32 tempOffset, mbuf_t *srcm, vm_address_t *src, SInt32 *srcLen); #ifdef DEBUG void showRcb(RCB *rcb); void showArb(ARB *arb); void showHandle(TNF_HANDLE *handle); void showDrb(DRB *drb); void showLcb(); #endif }; class recursiveScopeLock { private: IORecursiveLock *fLock; public: recursiveScopeLock(IORecursiveLock *lock){fLock = lock; IORecursiveLockLock(fLock);}; ~recursiveScopeLock(){IORecursiveLockUnlock(fLock);}; }; #endif