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