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#define FIREWIREPRIVATE 23 24#include <IOKit/firewire/IOFireWireController.h> 25#include <IOKit/firewire/IOFireWireNub.h> 26#include <IOKit/IOSyncer.h> 27 28#include "IOFireWireIPCommand.h" 29#include "IOFWIPBusInterface.h" 30 31#define BCOPY(s, d, l) do { bcopy((void *) s, (void *) d, l); } while(0) 32 33#pragma mark - 34#pragma mark ��� IOFWIPAsyncWriteCommand methods ��� 35 36/************************************************************************************ 37 IOFWIPAsyncWriteCommand - Asynchronous write command class 38 ***********************************************************************************/ 39 40OSDefineMetaClassAndStructors(IOFWIPAsyncWriteCommand, IOFWWriteCommand); 41OSMetaClassDefineReservedUnused(IOFWIPAsyncWriteCommand, 0); 42OSMetaClassDefineReservedUnused(IOFWIPAsyncWriteCommand, 1); 43OSMetaClassDefineReservedUnused(IOFWIPAsyncWriteCommand, 2); 44OSMetaClassDefineReservedUnused(IOFWIPAsyncWriteCommand, 3); 45 46/*! 47 @function initAll 48 Initializes the Asynchronous write command object 49 @result true if successfull. 50*/ 51bool IOFWIPAsyncWriteCommand::initAll(IOFireWireIP *networkObject, IOFWIPBusInterface *fwIPBusIfObject, UInt32 cmdLen, FWAddress devAddress, FWDeviceCallback completion, void *refcon, bool failOnReset) 52{ 53 fIPLocalNode = networkObject; 54 55 if(!fIPLocalNode) 56 return false; 57 58 IOFireWireNub *device = fIPLocalNode->getDevice(); 59 60 if(!IOFWWriteCommand::initWithController(device->getController())) 61 return false; 62 63 // Create a buffer descriptor that will hold something more than MTU 64 fBuffer = IOBufferMemoryDescriptor::inTaskWithOptions( kernel_task, 0, cmdLen, 1 ); 65 if(fBuffer == NULL) 66 return false; 67 68 // Create a Memory descriptor that will hold the buffer descriptor's memory pointer 69 fMem = NULL; 70 71 fCursorBuf = (UInt8*)getBufferFromDescriptor(); 72 73 // Initialize the maxBufLen with current max configuration 74 maxBufLen = cmdLen; 75 76 fMaxRetries = 2; 77 fCurRetries = fMaxRetries; 78 fMemDesc = fMem; 79 fComplete = completion; 80 fSync = completion == NULL; 81 fRefCon = refcon; 82 fTimeout = 1000*125; 83 84 if(fMem) 85 fSize = fMem->getLength(); 86 fBytesTransferred = 0; 87 fLinkFragmentType = UNFRAGMENTED; 88 89 fDevice = device; 90 device->getNodeIDGeneration(fGeneration, fNodeID); 91 fAddressHi = devAddress.addressHi; 92 fAddressLo = devAddress.addressLo; 93 fMaxPack = 1 << device->maxPackLog(fWrite, devAddress); 94 fSpeed = fControl->FWSpeed(fNodeID); 95 fFailOnReset = failOnReset; 96 97 if(fwIPBusIfObject) 98 { 99 fIPBusIf = fwIPBusIfObject; 100 fIPBusIf->retain(); 101 } 102 103 return true; 104} 105 106/*! 107 @function free 108 @abstract releases the buffer and the command object. 109 @param None. 110 @result void. 111*/ 112void IOFWIPAsyncWriteCommand::free() 113{ 114 if(fIPBusIf) 115 { 116 fIPBusIf->release(); 117 fIPBusIf = NULL; 118 } 119 120 // Release the buffer descriptor 121 if(fBuffer){ 122 fBuffer->release(); 123 fBuffer = NULL; 124 } 125 126 // Release the memory descriptor 127 if(fMem){ 128 fMem->release(); 129 fMem = NULL; 130 } 131 132 // Should we free the command 133 IOFWWriteCommand::free(); 134} 135 136void IOFWIPAsyncWriteCommand::wait() 137{ 138 IODelay(fTimeout); 139} 140 141/*! 142 @function reinit 143 @abstract reinit will re-initialize all the variables for this command object, good 144 when we have to reconfigure our outgoing command objects. 145 @result kIOReturnSuccess if successfull. 146*/ 147IOReturn IOFWIPAsyncWriteCommand::reinit(IOFireWireNub *device, UInt32 cmdLen, 148 FWAddress devAddress, FWDeviceCallback completion, void *refcon, 149 bool failOnReset, bool deferNotify) 150{ 151 // Check the cmd len less than the pre-allocated buffer 152 if(cmdLen > maxBufLen) 153 return kIOFireWireIPNoResources; 154 155 fComplete = completion; 156 fRefCon = refcon; 157 158 fSize = cmdLen; 159 fBytesTransferred = 0; 160 161 fDevice = device; 162 device->getNodeIDGeneration(fGeneration, fNodeID); 163 fAddressHi = devAddress.addressHi; 164 fAddressLo = devAddress.addressLo; 165 fMaxPack = 1 << device->maxPackLog(fWrite, devAddress); 166 fSpeed = fControl->FWSpeed(fNodeID); 167 fFailOnReset = failOnReset; 168 fMaxRetries = 2; 169 fCurRetries = fMaxRetries; 170 fTimeout = 1000*125; 171 172 setDeferredNotify(deferNotify); 173 174 IOFWWriteCommand::setFastRetryOnBusy(fIPLocalNode->fIPoFWDiagnostics.fDoFastRetry); 175 176 return kIOReturnSuccess; 177} 178 179IOReturn IOFWIPAsyncWriteCommand::transmit(IOFireWireNub *device, UInt32 cmdLen, 180 FWAddress devAddress, FWDeviceCallback completion, void *refcon, 181 bool failOnReset, bool deferNotify, bool doQueue, FragmentType fragmentType) 182{ 183 fLinkFragmentType = fragmentType; 184 return transmit(device, cmdLen, devAddress, completion, refcon, failOnReset, deferNotify, doQueue); 185} 186 187IOReturn IOFWIPAsyncWriteCommand::transmit(IOFireWireNub *device, UInt32 cmdLen, 188 FWAddress devAddress, FWDeviceCallback completion, void *refcon, 189 bool failOnReset, bool deferNotify, bool doQueue) 190{ 191 fMBufCommand->retain(); // released in resetDescriptor 192 193 IOReturn status = initDescriptor(cmdLen); 194 195 // Initialize the command with new values of device object 196 if(status == kIOReturnSuccess) 197 status = reinit(device, cmdLen+fHeaderSize, devAddress, completion, refcon, failOnReset, deferNotify); 198 199 if(status == kIOReturnSuccess) 200 { 201 reInitCount = 0; 202 resetCount = 0; 203 reInitCount++; 204 submit(doQueue); 205 status = getStatus(); 206 } 207 208 switch (status) 209 { 210 case kIOFireWireOutOfTLabels: 211 fIPLocalNode->fIPoFWDiagnostics.fSubmitErrs++; 212 break; 213 214 case kIOFireWireIPNoResources: 215 resetDescriptor(status); 216 ((IOFWIPBusInterface*)refcon)->returnAsyncCommand(this); 217 fIPLocalNode->fIPoFWDiagnostics.fNoResources++; 218 status = kIOReturnSuccess; 219 break; 220 221 default: // kIOReturnNoResources || kIOReturnBusy || kIOReturnSuccess 222 status = kIOReturnSuccess; 223 break; 224 } 225 226 return status; 227} 228 229/*! 230 @function createFragmentedDescriptors 231 @abstract creates IOVirtual ranges for fragmented Mbuf packets. 232 @param none. 233 @result 0 if copied successfully else non-negative value 234*/ 235IOReturn IOFWIPAsyncWriteCommand::createFragmentedDescriptors() 236{ 237 mbuf_t m = fMBufCommand->getMBuf(); 238 mbuf_t srcm = m; 239 240 SInt32 srcLen = mbuf_len(srcm); 241 vm_address_t src = (vm_offset_t)mbuf_data(srcm); 242 243 // Mbuf manipulated to point at the correct offset 244 SInt32 tempOffset = fOffset; 245 246 ((IOFWIPBusInterface*)fRefCon)->moveMbufWithOffset(tempOffset, &srcm, &src, &srcLen); 247 248 SInt32 dstLen = fLength; 249 SInt32 copylen = dstLen; 250 251 mbuf_t temp = NULL; 252 253 for (;;) 254 { 255 if (fIndex > (MAX_ALLOWED_SEGS-3)) 256 { 257 fTailMbuf = NULL; 258 fCursorBuf = fCursorBuf + fHeaderSize; 259 // Just copy the remaining length 260 fLength = copylen; 261 UInt32 residual = copyToBufferDescriptors(); 262 if(residual != 0) 263 return kIOFireWireIPNoResources; 264 265 fVirtualRange[fIndex].address = (IOVirtualAddress)(fCursorBuf); 266 fVirtualRange[fIndex].length = fLength; 267 fIndex++; 268 return kIOReturnSuccess; 269 } 270 271 if (srcLen < dstLen) 272 { 273 // Set the remainder of src mbuf to current virtual range. 274 fVirtualRange[fIndex].address = (IOVirtualAddress)(src); 275 fVirtualRange[fIndex].length = srcLen; 276 fIndex++; 277 278 dstLen -= srcLen; 279 copylen -= srcLen; 280 // set the offset 281 fOffset = fOffset + srcLen; 282 283 if(copylen == 0) 284 { 285 // set the new mbuf to point to the new chain 286 temp = mbuf_next(srcm); 287 srcm = temp; 288 break; 289 } 290 // Move on to the next source mbuf. 291 temp = mbuf_next(srcm); assert(temp); 292 srcm = temp; 293 srcLen = mbuf_len(srcm); 294 src = (vm_offset_t)mbuf_data(srcm); 295 } 296 else if (srcLen > dstLen) 297 { 298 // set some of src mbuf to the next virtual range. 299 fVirtualRange[fIndex].address = (IOVirtualAddress)(src); 300 fVirtualRange[fIndex].length = dstLen; 301 fIndex++; 302 303 src += dstLen; 304 srcLen -= dstLen; 305 copylen -= dstLen; 306 307 // set the offset 308 fOffset = fOffset + dstLen; 309 310 // Move on to the next destination mbuf. 311 if(copylen == 0) 312 break;// set the new mbuf to point to the new chain 313 } 314 else 315 { 316 // srcLen == dstLen 317 // set remainder of src into the available virtual range 318 fVirtualRange[fIndex].address = (IOVirtualAddress)(src); 319 fVirtualRange[fIndex].length = srcLen; 320 fIndex++; 321 322 copylen -= srcLen; 323 324 if(copylen == 0) 325 { 326 // set the offset 327 fOffset = 0; 328 // set the new mbuf to point to the new chain 329 temp = mbuf_next(srcm); 330 srcm = temp; 331 break; 332 } 333 // Free current mbuf and move the current onto the next 334 srcm = mbuf_next(srcm); 335 336 // Do we have any data left to copy? 337 if (dstLen == 0) 338 break; 339 340 srcLen = mbuf_len(srcm); 341 src = (vm_offset_t)mbuf_data(srcm); 342 } 343 } 344 345 return copylen; 346} 347 348/*! 349 @function createUnFragmentedDescriptors 350 @abstract creates IOVirtual ranges for fragmented Mbuf packets. 351 @param none. 352 @result kIOReturnSuccess if successfull, else kIOFireWireIPNoResources. 353*/ 354IOReturn IOFWIPAsyncWriteCommand::createUnFragmentedDescriptors() 355{ 356 mbuf_t m = fMBufCommand->getMBuf(); 357 mbuf_t n = 0; 358 UInt32 totalLength = 0; 359 UInt32 residual = 0; 360 UInt32 pktLen = 0; 361 UInt32 offset = 0; 362 363 fIndex = 0; 364 365 if (mbuf_flags(m) & MBUF_PKTHDR) 366 { 367 pktLen = mbuf_pkthdr_len(m); 368 offset = fOffset; 369 } 370 371 while (m) 372 { 373 374 if(mbuf_data(m) != NULL) 375 { 376 fVirtualRange[fIndex].address = (IOVirtualAddress)((UInt8*)mbuf_data(m) + offset); 377 fVirtualRange[fIndex].length = mbuf_len(m) - offset; 378 totalLength += fVirtualRange[fIndex].length; 379 fIndex++; 380 } 381 382 offset = 0; 383 384 m = mbuf_next(m); 385 386 // 387 // If Mbuf chain gets to the last segment 388 // it will be copied into the available buffer area 389 // 390 if ((fIndex > MAX_ALLOWED_SEGS-3) && (m != NULL)) 391 { 392 n = mbuf_next(m); 393 // If last mbuf, then use it in segment directly 394 if(n == NULL) 395 { 396 fVirtualRange[fIndex].address = (IOVirtualAddress)(mbuf_data(m)); 397 fVirtualRange[fIndex].length = mbuf_len(m); 398 } 399 // unlucky, so lets copy rest into the pre-allocated buffer 400 else 401 { 402 fTailMbuf = m; 403 // Just copy the remaining length 404 fLength = fLength - totalLength + fHeaderSize; 405 fCursorBuf = (UInt8*)getBufferFromDescriptor(); 406 407 residual = copyToBufferDescriptors(); 408 if(residual != 0) 409 return kIOFireWireIPNoResources; 410 411 fVirtualRange[fIndex].address = (IOVirtualAddress)(fCursorBuf); 412 fVirtualRange[fIndex].length = fLength; 413 } 414 fIndex++; 415 return kIOReturnSuccess; 416 } 417 } 418 419 return kIOReturnSuccess; 420} 421 422/*! 423 @function copyToBufferDescriptors 424 @abstract copies mbuf data into the buffer pointed by IOMemoryDescriptor. 425 @param none. 426 @result 0 if copied successfully else non-negative value 427*/ 428IOReturn IOFWIPAsyncWriteCommand::copyToBufferDescriptors() 429{ 430 // Get the source 431 mbuf_t srcm = fMBufCommand->getMBuf(); 432 SInt32 srcLen = mbuf_len(srcm); 433 vm_address_t src = (vm_offset_t)mbuf_data(srcm); 434 435 // 436 // Mbuf manipulated to point at the correct offset 437 // If its last segment copy, to form the scatter gather list 438 // we don't need to move the cursor to the offset position 439 // 440 SInt32 tempOffset = 0; 441 if(fTailMbuf != NULL) 442 { 443 srcm = fTailMbuf; 444 srcLen = mbuf_len(srcm); 445 src = (vm_offset_t)mbuf_data(srcm); 446 } 447 else 448 { 449 tempOffset = fOffset; 450 ((IOFWIPBusInterface*)fRefCon)->moveMbufWithOffset(tempOffset, &srcm, &src, &srcLen); 451 } 452 453 SInt32 dstLen = fLength; 454 SInt32 copylen = dstLen; 455 vm_address_t dst = (vm_address_t)fCursorBuf; 456 457 mbuf_t temp = NULL; 458 459 UInt32 totalLen = 0; 460 461 for (;;) 462 { 463 464 if (srcLen < dstLen) 465 { 466 // Copy remainder of src mbuf to current dst. 467 BCOPY(src, dst, srcLen); 468 totalLen += srcLen; 469 dst += srcLen; 470 dstLen -= srcLen; 471 copylen -= srcLen; 472 // set the offset 473 fOffset = fOffset + srcLen; 474 475 if(copylen == 0) 476 { 477 // set the new mbuf to point to the new chain 478 temp = mbuf_next(srcm); 479 srcm = temp; 480 break; 481 } 482 // Move on to the next source mbuf. 483 temp = mbuf_next(srcm); 484 if(temp == NULL) 485 break; 486 487 assert(temp); 488 srcm = temp; 489 srcLen = mbuf_len(srcm); 490 src = (vm_offset_t)mbuf_data(srcm); 491 } 492 else if (srcLen > dstLen) 493 { 494 // Copy some of src mbuf to remaining space in dst mbuf. 495 BCOPY(src, dst, dstLen); 496 totalLen += dstLen; 497 src += dstLen; 498 srcLen -= dstLen; 499 copylen -= dstLen; 500 // set the offset 501 fOffset = fOffset + dstLen; 502 503 // Move on to the next destination mbuf. 504 if(copylen == 0) 505 break; 506 } 507 else 508 { 509 /* (srcLen == dstLen) */ 510 // copy remainder of src into remaining space of current dst 511 BCOPY(src, dst, srcLen); 512 totalLen += srcLen; 513 copylen -= srcLen; 514 515 if(copylen == 0) 516 { 517 // set the offset 518 fOffset = 0; 519 // set the new mbuf to point to the new chain 520 temp = mbuf_next(srcm); 521 srcm = temp; 522 break; 523 } 524 // Free current mbuf and move the current onto the next 525 srcm = mbuf_next(srcm); 526 527 // Do we have any data left to copy? 528 if (dstLen == 0) 529 break; 530 531 srcLen = mbuf_len(srcm); 532 src = (vm_offset_t)mbuf_data(srcm); 533 } 534 } 535 536 return copylen; 537} 538 539/*! 540 @function initDescriptor 541 @abstract copies mbuf data into the buffer pointed by IOMemoryDescriptor. 542 @param unfragmented - indicates whether the packet is fragmented or unfragmented. 543 @param length - length to copy. 544 @result kIOReturnSuccess, if successfull. 545*/ 546IOReturn IOFWIPAsyncWriteCommand::initDescriptor(UInt32 length) 547{ 548 fLength = length; 549 550 // if we copy the payload 551 if(fCopy == true) 552 { 553 // Increment the buffer pointer for the unfrag or frag header 554 fVirtualRange[fIndex].address = (IOVirtualAddress)fCursorBuf; 555 fVirtualRange[fIndex].length = fLength + fHeaderSize; 556 fIndex++; 557 558 fCursorBuf = fCursorBuf + fHeaderSize; 559 560 if(copyToBufferDescriptors() != 0) 561 return kIOFireWireIPNoResources; 562 } 563 // if we don't copy the payload 564 else 565 { 566 // if packets are unfragmented 567 if(((fLinkFragmentType == UNFRAGMENTED) ? createUnFragmentedDescriptors() : createFragmentedDescriptors()) != kIOReturnSuccess) 568 return kIOFireWireIPNoResources; 569 } 570 571 fMem = IOMemoryDescriptor::withAddressRanges(fVirtualRange, 572 fIndex, 573 kIODirectionOut, 574 kernel_task); 575 576 if(!fMem) 577 return kIOFireWireIPNoResources; 578 579 fMemDesc = fMem; 580 fMemDesc->prepare(); 581 582 return kIOReturnSuccess; 583} 584 585/*! 586 @function resetDescriptor 587 @abstract resets the IOMemoryDescriptor & reinitializes the cursorbuf. 588 @result void. 589*/ 590void IOFWIPAsyncWriteCommand::resetDescriptor(IOReturn status) 591{ 592 if( fMem ){ 593 fMem->complete(); 594 fMem->release(); 595 fMem = NULL; 596 fMemDesc = fMem; 597 } 598 599 memset(fVirtualRange, 0, sizeof(IOVirtualRange)*MAX_ALLOWED_SEGS); 600 fTailMbuf = NULL; 601 fCursorBuf = (UInt8*)getBufferFromDescriptor(); 602 603 if( status == kIOReturnSuccess || status == kIOReturnBusy ) 604 fIPLocalNode->fIPoFWDiagnostics.fFastRetryBusyAcks += getFastRetryCount(); 605 606 fMBufCommand->releaseWithStatus(status); 607 608 // reset the link fragment type 609 fLinkFragmentType = UNFRAGMENTED; 610 fDevice = NULL; 611 fMBufCommand = NULL; 612 613 resetCount++; 614} 615 616/*! 617 @function initPacketHeader 618 @abstract returns a descriptor header based on fragmentation and copying 619 of payload. 620 @result void. 621*/ 622void* IOFWIPAsyncWriteCommand::initPacketHeader(IOFWIPMBufCommand *mBufCommand, bool doCopy, FragmentType unfragmented, UInt32 headerSize, UInt32 offset) 623{ 624 fMBufCommand = mBufCommand; 625 fCopy = doCopy; 626 fOffset = offset; 627 fHeaderSize = headerSize; 628 fLinkFragmentType = unfragmented; 629 fIndex = 0; 630 631 if(fCopy == false) 632 { 633 // If we don't copy then return the starting point of the Mbuf 634 if(unfragmented == UNFRAGMENTED) 635 { 636 fOffset = fOffset - fHeaderSize; 637 return (void*)((UInt8*)mbuf_data(fMBufCommand->getMBuf()) + fOffset); 638 } 639 else 640 { 641 fVirtualRange[fIndex].address = (IOVirtualAddress)(getCursorBuf()); 642 fVirtualRange[fIndex].length = fHeaderSize; 643 fIndex++; 644 return getCursorBuf(); 645 } 646 } 647 648 // else return the buffer pointer 649 return getBufferFromDescriptor(); 650} 651 652void IOFWIPAsyncWriteCommand::gotAck(int ackCode) 653{ 654 if ( (ackCode == kFWAckBusyX) || (ackCode == kFWAckBusyA) || (ackCode == kFWAckBusyB) ) 655 fIPLocalNode->fIPoFWDiagnostics.fBusyAcks++; 656 657 IOFWWriteCommand::gotAck(ackCode); 658} 659 660/*! 661 @function getCursorBuf 662 @abstract returns the pointer from the current position of fBuffer. 663 @result void* - pre-allocated buffer pointer 664*/ 665void* IOFWIPAsyncWriteCommand::getCursorBuf() 666{ 667 return fCursorBuf; 668} 669 670/*! 671 @function getBufferFromDescriptor 672 @abstract returns the head pointer position of fBuffer. 673 @result void* - pre-allocated buffer pointer 674*/ 675void* IOFWIPAsyncWriteCommand::getBufferFromDescriptor() 676{ 677 return fBuffer->getBytesNoCopy(); 678} 679 680/*! 681 @function getMaxBufLen 682 @abstract Usefull when MTU changes to a greater value and we need to 683 accomodate more data in the buffer without a 1394 fragmentation 684 @result UInt32 - size of the pre-allocated buffer 685*/ 686UInt32 IOFWIPAsyncWriteCommand::getMaxBufLen() 687{ 688 return maxBufLen; 689} 690 691bool IOFWIPAsyncWriteCommand::notDoubleComplete() 692{ 693 return (reInitCount == resetCount); 694} 695 696#pragma mark - 697#pragma mark ��� IOFWIPAsyncStreamTxCommand methods ��� 698 699/************************************************************************************ 700 IOFWIPAsyncStreamTxCommand - AsynStream Trasmit command class 701 ***********************************************************************************/ 702 703OSDefineMetaClassAndStructors(IOFWIPAsyncStreamTxCommand, IOFWAsyncStreamCommand); 704OSMetaClassDefineReservedUnused(IOFWIPAsyncStreamTxCommand, 0); 705OSMetaClassDefineReservedUnused(IOFWIPAsyncStreamTxCommand, 1); 706OSMetaClassDefineReservedUnused(IOFWIPAsyncStreamTxCommand, 2); 707OSMetaClassDefineReservedUnused(IOFWIPAsyncStreamTxCommand, 3); 708 709 710/*! 711 @function initAll 712 Initializes the Asynchronous write command object 713 @result true if successfull. 714*/ 715bool IOFWIPAsyncStreamTxCommand::initAll( 716 IOFireWireIP *networkObject, 717 IOFireWireController *control, 718 IOFWIPBusInterface *fwIPBusIfObject, 719 UInt32 generation, 720 UInt32 channel, 721 UInt32 sync, 722 UInt32 tag, 723 UInt32 cmdLen, 724 int speed, 725 FWAsyncStreamCallback completion, 726 void *refcon) 727 728{ 729 if(!IOFWAsyncStreamCommand::initWithController(control)) 730 return false; 731 732 fIPLocalNode = networkObject; 733 734 if(!fIPLocalNode) 735 return false; 736 737 // Create a buffer descriptor that will hold something more than MTU 738 fBuffer = IOBufferMemoryDescriptor::inTaskWithOptions( kernel_task, 0, cmdLen, 1 ); 739 if(fBuffer == NULL) 740 return false; 741 742 // Create a Memory descriptor that will hold the buffer descriptor's memory pointer 743 fMem = IOMemoryDescriptor::withAddress((void *)fBuffer->getBytesNoCopy(), cmdLen, 744 kIODirectionOut); 745 if(!fMem) { 746 return false; 747 } 748 749 // Initialize the maxBufLen with current max configuration 750 maxBufLen = cmdLen; 751 752 fMaxRetries = 0; 753 fCurRetries = fMaxRetries; 754 fMemDesc = fMem; 755 fComplete = completion; 756 fSync = completion == NULL; 757 fRefCon = refcon; 758 fTimeout = 1000*125; 759 760 if(fMem) 761 fSize = fMem->getLength(); 762 763 fGeneration = generation; 764 fChannel = channel; 765 fSyncBits = sync; 766 fTag = tag; 767 fSpeed = speed; 768 fFailOnReset = true; 769 770 if(fwIPBusIfObject) 771 { 772 fIPBusIf = fwIPBusIfObject; 773 fIPBusIf->retain(); 774 } 775 776 return true; 777} 778 779void IOFWIPAsyncStreamTxCommand::wait() 780{ 781 IODelay(fTimeout); 782} 783 784void IOFWIPAsyncStreamTxCommand::free() 785{ 786 if(fIPBusIf) 787 { 788 fIPBusIf->release(); 789 fIPBusIf = NULL; 790 } 791 792 // Release the buffer descriptor 793 if(fBuffer){ 794 fBuffer->release(); 795 fBuffer = NULL; 796 } 797 798 // Release the memory descriptor 799 if(fMem){ 800 fMem->release(); 801 fMem = NULL; 802 } 803 804 // Should we free the command 805 IOFWAsyncStreamCommand::free(); 806} 807 808/*! 809 @function reinit 810 reinit will re-initialize all the variables for this command object, good 811 when we have to reconfigure our outgoing command objects. 812 @result true if successfull. 813*/ 814IOReturn IOFWIPAsyncStreamTxCommand::reinit( 815 UInt32 generation, 816 UInt32 channel, 817 UInt32 cmdLen, 818 int speed, 819 FWAsyncStreamCallback completion, 820 void *refcon) 821{ 822 if(fStatus == kIOReturnBusy || fStatus == kIOFireWirePending) 823 return fStatus; 824 825 // Check the cmd len less than the pre-allocated buffer 826 if(cmdLen > maxBufLen) 827 return kIOReturnNoResources; 828 829 fComplete = completion; 830 fRefCon = refcon; 831 832 if(fMem) 833 fSize = cmdLen; 834 835 fMaxRetries = 0; 836 fCurRetries = fMaxRetries; 837 fGeneration = generation; 838 fChannel = channel; 839 fSpeed = speed; 840 fTimeout = 1000*125; 841 842 return fStatus = kIOReturnSuccess; 843} 844 845/*! 846 @function getBufferFromDescriptor 847 Usefull for copying data from the mbuf 848 @result void* - pre-allocated buffer pointer 849*/ 850void* IOFWIPAsyncStreamTxCommand::getBufferFromDesc() 851{ 852 return fBuffer->getBytesNoCopy(); 853} 854 855/*! 856 @function getMaxBufLen 857 Usefull when MTU changes to a greater value and we need to 858 accomodate more data in the buffer without a 1394 fragmentation 859 @result UInt32 - size of the pre-allocated buffer 860*/ 861UInt32 IOFWIPAsyncStreamTxCommand::getMaxBufLen() 862{ 863 return maxBufLen; 864} 865