1/* 2 * IOFWUserCommand.cpp 3 * IOFireWireFamily 4 * 5 * Created by noggin on Tue May 08 2001. 6 * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. 7 * 8 */ 9 10// public 11#import <IOKit/firewire/IOFireWireDevice.h> 12#import <IOKit/firewire/IOFireWireFamilyCommon.h> 13#import <IOKit/firewire/IOFireWireController.h> 14 15// private 16#import "IOFWUserCommand.h" 17#import "IOFireWireLib.h" 18#import "IOFWUserVectorCommand.h" 19 20OSDefineMetaClassAndAbstractStructors(IOFWUserCommand, OSObject) 21OSDefineMetaClassAndStructors(IOFWUserReadCommand, IOFWUserCommand) 22OSDefineMetaClassAndStructors(IOFWUserWriteCommand, IOFWUserCommand) 23OSDefineMetaClassAndStructors(IOFWUserPHYCommand, IOFWUserCommand) 24OSDefineMetaClassAndStructors(IOFWUserCompareSwapCommand, IOFWUserCommand) 25OSDefineMetaClassAndStructors(IOFWUserAsyncStreamCommand, IOFWUserCommand) 26 27// ============================================================ 28// IOFWUserCommand 29// ============================================================ 30void 31IOFWUserCommand::free() 32{ 33 if ( fCommand ) 34 { 35 IOReturn cmdStatus = fCommand->getStatus() ; 36 if ( cmdStatus == kIOReturnBusy || cmdStatus == kIOFireWirePending ) 37 { 38 DebugLog("cancelling cmd %p\n", fCommand) ; 39 fCommand->cancel( kIOReturnAborted ) ; 40 } 41 42 fCommand->release() ; 43 fCommand = NULL; 44 } 45 46 if( fOutputArgs ) 47 { 48 IOFree( fOutputArgs, fOutputArgsSize ); 49 fOutputArgs = NULL; 50 fQuads = NULL ; 51 fNumQuads = 0 ; 52 } 53 54 if (fMem) 55 { 56 fMem->complete() ; 57 fMem->release() ; 58 fMem = NULL; 59 } 60 61 OSObject::free() ; 62} 63 64void 65IOFWUserCommand::setAsyncReference64( 66 OSAsyncReference64 inAsyncRef) 67{ 68 bcopy(inAsyncRef, fAsyncRef, sizeof(OSAsyncReference64)) ; 69} 70 71IOFWUserCommand* 72IOFWUserCommand::withSubmitParams( 73 const CommandSubmitParams* params, 74 const IOFireWireUserClient* inUserClient) 75{ 76 IOFWUserCommand* result = NULL ; 77 78 switch ( params->type ) 79 { 80 case kFireWireCommandType_Read: 81 // fallthru 82 case kFireWireCommandType_ReadQuadlet: 83 result = OSTypeAlloc( IOFWUserReadCommand ); 84 break ; 85 86 case kFireWireCommandType_Write: 87 // fallthru 88 case kFireWireCommandType_WriteQuadlet: 89 result = OSTypeAlloc( IOFWUserWriteCommand ); 90 break ; 91 92 case kFireWireCommandType_CompareSwap: 93 result = OSTypeAlloc( IOFWUserCompareSwapCommand ); 94 break ; 95 96 case kFireWireCommandType_PHY: 97 result = OSTypeAlloc( IOFWUserPHYCommand ); 98 break ; 99 100 case kFireWireCommandType_AsyncStream: 101 result = OSTypeAlloc( IOFWUserAsyncStreamCommand ); 102 break; 103 104 default: 105 DebugLog( "bad command type!\n" ) ; 106 break ; 107 } 108 109 if (result && !result->initWithSubmitParams( params, inUserClient )) 110 { 111 result->release() ; 112 result = NULL ; 113 } 114 115 return result ; 116} 117 118bool 119IOFWUserCommand::initWithSubmitParams( 120 const CommandSubmitParams* params, 121 const IOFireWireUserClient* inUserClient) 122{ 123 fFlush = true; 124 fUserClient = inUserClient ; 125 return true ; 126} 127 128 129void 130IOFWUserCommand::asyncReadWriteCommandCompletion( 131 void * refcon, 132 IOReturn status, 133 IOFireWireNub * device, 134 IOFWCommand * fwCmd) 135{ 136 IOFWUserCommand* cmd = (IOFWUserCommand*) refcon ; 137 138 // tell the vector 139 if( cmd->fVectorCommand ) 140 { 141 cmd->fVectorCommand->asyncCompletion( refcon, status, device, fwCmd ); 142 } 143 else if ( refcon && cmd->fAsyncRef[0] ) 144 { 145 io_user_reference_t args[3]; 146 args[0] = cmd->fCommand->getBytesTransferred(); 147 args[1] = cmd->fCommand->getAckCode(); 148 args[2] = cmd->fCommand->getResponseCode(); 149#if IOFIREWIREDEBUG > 0 150 IOReturn error = 151#endif 152 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, args, 3 ); 153 154 DebugLogCond ( error, "IOFWUserCommand::asyncReadWriteCommandCompletion: sendAsyncResult64 returned error %x\n", error ) ; 155 } 156} 157 158void 159IOFWUserCommand::asyncReadQuadletCommandCompletion( 160 void * refcon, 161 IOReturn status, 162 IOFireWireNub * device, 163 IOFWCommand * fwCmd) 164{ 165 IOFWUserCommand* cmd = (IOFWUserCommand*)refcon ; 166 167 if (refcon && cmd->fAsyncRef[0] ) 168 { 169 cmd->fOutputArgs[0] = cmd->fCommand->getAckCode(); 170 cmd->fOutputArgs[1] = cmd->fCommand->getResponseCode(); 171 // quad data is already in fOutputArgs[3] and later 172 173#if IOFIREWIREDEBUG > 0 174 IOReturn result = 175#endif 176 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, (io_user_reference_t *)cmd->fOutputArgs, ( cmd->fCommand->getBytesTransferred() >> 2) + 2 ) ; 177 DebugLogCond ( result, "IOFireWireUserClient::asyncReadQuadletCommandCompletion: sendAsyncResult64 returned error 0x%08x\n", result) ; 178 } 179} 180 181#pragma mark - 182// ============================================================ 183// IOFWUserReadCommand 184// ============================================================ 185 186bool 187IOFWUserReadCommand::initWithSubmitParams( 188 const CommandSubmitParams* params, 189 const IOFireWireUserClient* inUserClient) 190{ 191 bool result = true ; 192 193 result = (NULL != IOFWUserCommand::initWithSubmitParams(params, inUserClient)) ; 194 195 if (result) 196 { 197 fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, params->newBufferSize, kIODirectionIn, fUserClient->getOwningTask() ) ; 198 result = (NULL != fMem) ; 199 } 200 201 if (result) 202 { 203 IOReturn error = fMem->prepare() ; 204 result = ( kIOReturnSuccess == error ) ; 205 } 206 207 if (!result) 208 { 209 if (fMem) 210 { 211 fMem->release() ; 212 fMem = NULL; 213 } 214 } 215 216 return result ; 217} 218 219IOReturn 220IOFWUserReadCommand::submit( 221 CommandSubmitParams* params, 222 CommandSubmitResult* outResult) 223{ 224 IOReturn error = kIOReturnSuccess ; 225 Boolean syncFlag = ( params->flags & kFWCommandInterfaceSyncExecute ) != 0 ; 226 Boolean copyFlag = ( params->flags & kFireWireCommandUseCopy ) != 0; 227 Boolean absFlag = ( params->flags & kFireWireCommandAbsolute ) != 0 ; 228 bool forceBlockFlag = (params->flags & kFWCommandInterfaceForceBlockRequest) != 0; 229 230 FWAddress target_address; 231 target_address.addressLo = (UInt32)(params->newTarget & 0xffffffff); 232 target_address.addressHi = (UInt16)((params->newTarget >> 32) & 0x0000ffff); 233 target_address.nodeID = (UInt16)(params->newTarget >> 48); 234 235 if ( params->staleFlags & kFireWireCommandStale_Buffer ) // do we need reevaluate our buffers? 236 { 237 if ( fMem ) // whatever happens, we're going to need a new memory descriptor 238 { 239 fMem->complete() ; 240 fMem->release() ; 241 fMem = NULL; 242 } 243 244 if ( copyFlag ) // is this command using in-line data? 245 { 246 if( fQuads && (fNumQuads != params->newBufferSize) || syncFlag) // if we're executing synchronously, 247 // don't need quadlet buffer 248 { 249 IOFree( fOutputArgs, fOutputArgsSize ); 250 fOutputArgs = NULL; 251 fQuads = NULL ; 252 fNumQuads = 0 ; 253 } 254 255 if (!syncFlag) 256 { 257 fNumQuads = params->newBufferSize ; 258 fOutputArgsSize = (params->newBufferSize + 2) * sizeof(UInt32); 259 fOutputArgs = (UInt32*)IOMalloc( fOutputArgsSize ); 260 fQuads = fOutputArgs + 2; 261 } 262 263 fMem = NULL ; 264 } 265 else 266 { 267 if (fQuads) 268 { 269 IOFree( fOutputArgs, fOutputArgsSize ); 270 fOutputArgs = NULL; 271 fQuads = NULL ; 272 fNumQuads = 0 ; 273 } 274 275 if (NULL == (fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, 276 params->newBufferSize, 277 kIODirectionIn, 278 fUserClient->getOwningTask())) ) 279 { 280 error = kIOReturnNoMemory ; 281 } 282 else 283 { 284 error = fMem->prepare() ; 285 286 if ( error ) 287 { 288 fMem->release() ; 289 fMem = NULL ; 290 } 291 } 292 } 293 } 294 295 if ( not error ) 296 { 297 if (fCopyFlag != copyFlag) 298 if (fCommand) 299 { 300 fCommand->release() ; // we had a normal command and need a quadlet command or vice-versa 301 fCommand = NULL ; 302 } 303 304 if (fCommand) 305 { 306 if ( copyFlag ) 307 if (syncFlag) 308 { 309 if ( absFlag ) 310 { 311 error = ((IOFWReadQuadCommand*)fCommand)->reinit( params->newGeneration, target_address, (UInt32*) params+1, params->newBufferSize, NULL, this ) ; 312 } 313 else 314 error = ((IOFWReadQuadCommand*)fCommand)->reinit( target_address, (UInt32*) params+1, params->newBufferSize, NULL, this, params->newFailOnReset) ; 315 } 316 else 317 { 318 error = ((IOFWReadQuadCommand*)fCommand)->reinit( target_address, 319 fQuads, 320 fNumQuads, 321 & IOFWUserCommand::asyncReadWriteCommandCompletion, 322 this, 323 params->newFailOnReset) ; 324 } 325 else 326 error = ((IOFWReadCommand*)fCommand)->reinit( target_address, 327 fMem, 328 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 329 this, 330 params->newFailOnReset ) ; 331 332 fCommand->setGeneration(params->newGeneration) ; 333 DebugLogCond ( error, "IOFWUserReadCommand::submit: fCommand->reinit error=%08x\n", error) ; 334 } 335 else// if (params->staleFlags ) 336 { 337 if ( copyFlag ) 338 { 339 if (syncFlag) 340 { 341 if ( absFlag ) 342 { 343 fCommand = fUserClient->createReadQuadCommand( params->newGeneration, target_address, (UInt32*) params+1, params->newBufferSize, NULL, this ) ; 344 } 345 else 346 fCommand = fUserClient->getOwner()->createReadQuadCommand( target_address, (UInt32*) params+1, params->newBufferSize, NULL, this, params->newFailOnReset ) ; 347 } 348 else 349 { 350 // create a quadlet command and copy in-line quads into it. 351 if ( absFlag ) 352 { 353 fCommand = fUserClient->createReadQuadCommand( params->newGeneration, target_address, fQuads, fNumQuads, & IOFWUserCommand::asyncReadQuadletCommandCompletion, this ) ; 354 } 355 else 356 { 357 fCommand = fUserClient->getOwner()->createReadQuadCommand( target_address, 358 fQuads, 359 fNumQuads, 360 & IOFWUserCommand::asyncReadQuadletCommandCompletion, 361 this, 362 params->newFailOnReset) ; 363 if ( fCommand ) 364 fCommand->setGeneration( params->newGeneration ) ; 365 } 366 } 367 } 368 else 369 { 370 // create a read command -- memory descriptor based 371 if ( absFlag ) 372 { 373 fCommand = fUserClient->createReadCommand( params->newGeneration, target_address, fMem, syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, this ) ; 374 } 375 else 376 { 377 fCommand = fUserClient->getOwner()->createReadCommand( target_address, 378 fMem, 379 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 380 this, 381 params->newFailOnReset ) ; 382 if ( fCommand ) 383 fCommand->setGeneration( params->newGeneration ) ; 384 } 385 } 386 387 if (!fCommand) 388 error = kIOReturnNoMemory ; 389 } 390 } 391 392 if ( not error ) 393 { 394 if (params->staleFlags & kFireWireCommandStale_MaxPacket) 395 { 396 fCommand->setMaxPacket(params->newMaxPacket) ; 397 } 398 399 if( params->staleFlags & kFireWireCommandStale_Timeout ) 400 { 401 fCommand->setTimeout( params->timeoutDuration ); 402 } 403 404 if( params->staleFlags & kFireWireCommandStale_Retries ) 405 { 406 fCommand->setRetries( params->retryCount ); 407 } 408 409 if( params->staleFlags & kFireWireCommandStale_Speed ) 410 { 411 fCommand->setMaxSpeed( params->maxPacketSpeed ); 412 } 413 414 // block or not 415 fCommand->setForceBlockRequests( forceBlockFlag ); 416 417 // turn off flushing if requested 418 if( !fFlush ) 419 { 420 fCommand->setFlush( fFlush ); 421 } 422 423 error = fCommand->submit() ; 424 425 if( !fFlush ) 426 { 427 fCommand->setFlush( true ); 428 } 429 430 DebugLogCond ( error, "IOFWUserReadCommand::submit: fCommand->submit error=%08x\n", error ) ; 431 } 432 433 if( syncFlag && (outResult != NULL) ) 434 { 435 outResult->result = fCommand->getStatus() ; 436 outResult->bytesTransferred = fCommand->getBytesTransferred() ; 437 outResult->ackCode = fCommand->getAckCode(); 438 outResult->responseCode = fCommand->getResponseCode(); 439 440 // mach won't copy any of our result info out on an error, pretend everything is fine 441 error = kIOReturnSuccess; 442 } 443 444 return error ; 445} 446 447#pragma mark - 448// ============================================================ 449// IOFWUserWriteCommand 450// ============================================================ 451bool 452IOFWUserWriteCommand::initWithSubmitParams( 453 const CommandSubmitParams* params, 454 const IOFireWireUserClient* inUserClient) 455{ 456 bool result = true ; 457 458 result = (NULL != IOFWUserCommand::initWithSubmitParams(params, inUserClient)) ; 459 460 if (result) 461 { 462 fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, params->newBufferSize, kIODirectionOut, fUserClient->getOwningTask() ) ; 463 result = (NULL != fMem) ; 464 } 465 466 if (result) 467 { 468 IOReturn error = fMem->prepare() ; 469 result = (error == kIOReturnSuccess) ; 470 } 471 472 if (!result) 473 { 474 if (fMem) 475 { 476 fMem->release() ; 477 fMem = NULL; 478 } 479 } 480 481 return result ; 482} 483 484IOReturn 485IOFWUserWriteCommand::submit( 486 CommandSubmitParams* params, 487 CommandSubmitResult* outResult) 488{ 489 IOReturn result = kIOReturnSuccess; 490 Boolean syncFlag = (params->flags & kFWCommandInterfaceSyncExecute) != 0; 491 Boolean copyFlag = (params->flags & kFireWireCommandUseCopy) != 0; 492 Boolean absFlag = (params->flags & kFireWireCommandAbsolute) != 0; 493 bool forceBlockFlag = (params->flags & kFWCommandInterfaceForceBlockRequest) != 0; 494 495 FWAddress target_address; 496 target_address.addressLo = (UInt32)(params->newTarget & 0xffffffff); 497 target_address.addressHi = (UInt16)((params->newTarget >> 32) & 0x0000ffff); 498 target_address.nodeID = (UInt16)(params->newTarget >> 48); 499 500 if ( params->staleFlags & kFireWireCommandStale_Buffer ) // do we need reevaluate our buffers? 501 { 502 if ( fMem ) // whatever happens, we're going to need a new memory descriptor 503 { 504 fMem->complete() ; 505 fMem->release() ; 506 } 507 508 if ( copyFlag ) // is this command using in-line data? 509 fMem = NULL ; 510 else 511 { 512 if (NULL == (fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, 513 params->newBufferSize, 514 kIODirectionOut, 515 fUserClient->getOwningTask())) ) 516 { 517 result = kIOReturnNoMemory ; 518 } 519 else 520 { 521 result = fMem->prepare() ; 522 523 if ( kIOReturnSuccess != result ) 524 { 525 fMem->release() ; 526 fMem = NULL ; 527 } 528 } 529 } 530 } 531 532 if ( kIOReturnSuccess == result) 533 { 534 if (fCopyFlag != copyFlag) 535 if (fCommand) 536 { 537 fCommand->release() ; // we had a normal command and need a quadlet command or vice-versa 538 fCommand = NULL ; 539 } 540 541 if (fCommand) 542 { 543 if ( copyFlag ) 544 { 545 result = ((IOFWWriteQuadCommand*)fCommand)->reinit( target_address, 546 (UInt32*) params+1, 547 params->newBufferSize, 548 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 549 this, 550 params->newFailOnReset) ; 551 } 552 else 553 { 554 result = ((IOFWWriteCommand*)fCommand)->reinit( target_address, 555 fMem, 556 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 557 this, 558 params->newFailOnReset ) ; 559 } 560 561 DebugLogCond ( result, "IOFWUserWriteCommand::submit: fCommand->reinit result=%08x\n", result) ; 562 } 563 else 564 { 565 if ( copyFlag ) 566 { 567 if ( absFlag ) 568 fCommand = fUserClient->createWriteQuadCommand( params->newGeneration, target_address, (UInt32*) params+1, params->newBufferSize, syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, this ) ; 569 else 570 { 571 fCommand = fUserClient->getOwner()->createWriteQuadCommand( target_address, 572 (UInt32*) params+1, 573 params->newBufferSize, 574 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 575 this, 576 params->newFailOnReset ) ; 577 if ( fCommand ) 578 fCommand->setGeneration( params->newGeneration ) ; 579 } 580 } 581 else 582 { 583 // create a read command -- memory descriptor based 584 if ( absFlag ) 585 fCommand = fUserClient->createWriteCommand( params->newGeneration, 586 target_address, 587 fMem, 588 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 589 this ) ; 590 else 591 { 592 fCommand = fUserClient->getOwner()->createWriteCommand( target_address, 593 fMem, 594 syncFlag ? NULL : & IOFWUserCommand::asyncReadWriteCommandCompletion, 595 this, 596 params->newFailOnReset ) ; 597 if ( fCommand ) 598 fCommand->setGeneration( params->newGeneration ) ; 599 } 600 } 601 602 if (!fCommand) 603 result = kIOReturnNoMemory ; 604 } 605 } 606 607 if ( kIOReturnSuccess == result) 608 { 609 if (params->staleFlags & kFireWireCommandStale_MaxPacket) 610 { 611 fCommand->setMaxPacket(params->newMaxPacket) ;// zzz is there any reason for us to pay 612 } 613 614 if( params->staleFlags & kFireWireCommandStale_Timeout ) 615 { 616 fCommand->setTimeout( params->timeoutDuration ); 617 } 618 619 if( params->staleFlags & kFireWireCommandStale_Retries ) 620 { 621 fCommand->setRetries( params->retryCount ); 622 } 623 624 if( params->staleFlags & kFireWireCommandStale_Speed ) 625 { 626 fCommand->setMaxSpeed( params->maxPacketSpeed ); 627 } 628 629 // block or not 630 fCommand->setForceBlockRequests( forceBlockFlag ); 631 632 // turn off flushing if requested 633 if( !fFlush ) 634 { 635 fCommand->setFlush( fFlush ); 636 } 637 638 result = fCommand->submit() ; 639 640 if( !fFlush ) 641 { 642 fCommand->setFlush( true ); 643 } 644 645 DebugLogCond ( result, "IOFWUserReadCommand::submit: fCommand->submit result=%08x\n", result); 646 } 647 648 if( syncFlag && (outResult != NULL) ) 649 { 650 outResult->result = fCommand->getStatus(); 651 outResult->bytesTransferred = fCommand->getBytesTransferred(); 652 outResult->ackCode = fCommand->getAckCode(); 653 outResult->responseCode = fCommand->getResponseCode(); 654 655 // mach won't copy any of our result info out on an error, pretend everything is fine 656 result = kIOReturnSuccess; 657 } 658 659 return result; 660} 661 662#pragma mark - 663// ============================================================ 664// IOFWUserPHYCommand 665// ============================================================ 666bool 667IOFWUserPHYCommand::initWithSubmitParams( 668 const CommandSubmitParams* params, 669 const IOFireWireUserClient* inUserClient) 670{ 671 bool result = true ; 672 673 result = (NULL != IOFWUserCommand::initWithSubmitParams(params, inUserClient)); 674 675 return result; 676} 677 678IOReturn 679IOFWUserPHYCommand::submit( 680 CommandSubmitParams* params, 681 CommandSubmitResult* outResult) 682{ 683 IOReturn result = kIOReturnSuccess; 684 Boolean syncFlag = (params->flags & kFWCommandInterfaceSyncExecute) != 0; 685 686 if( kIOReturnSuccess == result) 687 { 688 if( fPHYCommand ) 689 { 690 result = fPHYCommand->reinit( params->newGeneration, 691 params->data1, 692 params->data2, 693 syncFlag ? NULL : & IOFWUserPHYCommand::asyncPHYCommandCompletion, 694 this, 695 params->newFailOnReset ); 696 697 DebugLogCond ( result, "IOFWUserPHYCommand::submit: fCommand->reinit result=%08x\n", result) ; 698 } 699 else 700 { 701 IOFireWireController * control = fUserClient->getOwner()->getController(); 702 703 fPHYCommand = control->createAsyncPHYCommand( params->newGeneration, 704 params->data1, 705 params->data2, 706 syncFlag ? NULL : &IOFWUserPHYCommand::asyncPHYCommandCompletion, 707 this, 708 params->newFailOnReset ); 709 710 if( !fPHYCommand ) 711 { 712 result = kIOReturnNoMemory; 713 } 714 } 715 } 716 717 if( kIOReturnSuccess == result ) 718 { 719 if( params->staleFlags & kFireWireCommandStale_Timeout ) 720 { 721 fPHYCommand->setTimeout( params->timeoutDuration ); 722 } 723 724 if( params->staleFlags & kFireWireCommandStale_Retries ) 725 { 726 fPHYCommand->setRetries( params->retryCount ); 727 } 728 729 // turn off flushing if requested 730 if( !fFlush ) 731 { 732 fPHYCommand->setFlush( fFlush ); 733 } 734 735 result = fPHYCommand->submit() ; 736 737 if( !fFlush ) 738 { 739 fPHYCommand->setFlush( true ); 740 } 741 742 DebugLogCond ( result, "IOFWUserPHYCommand::submit: fCommand->submit result=%08x\n", result); 743 } 744 745 if( syncFlag && (outResult != NULL) ) 746 { 747 outResult->result = fPHYCommand->getStatus(); 748 outResult->bytesTransferred = 8; 749 outResult->ackCode = fPHYCommand->getAckCode(); 750 outResult->responseCode = fPHYCommand->getResponseCode(); 751 752 // mach won't copy any of our result info out on an error, pretend everything is fine 753 result = kIOReturnSuccess; 754 755 } 756 757 return result; 758} 759 760void 761IOFWUserPHYCommand::free() 762{ 763 if( fPHYCommand ) 764 { 765 IOReturn cmdStatus = fPHYCommand->getStatus(); 766 if ( cmdStatus == kIOReturnBusy || cmdStatus == kIOFireWirePending ) 767 { 768 DebugLog("cancelling cmd %p\n", fCommand); 769 fPHYCommand->cancel( kIOReturnAborted ); 770 } 771 772 fPHYCommand->release() ; 773 fCommand = NULL; 774 } 775 776 IOFWUserCommand::free(); 777} 778 779void 780IOFWUserPHYCommand::asyncPHYCommandCompletion( 781 void * refcon, 782 IOReturn status, 783 IOFireWireBus * bus, 784 IOFWAsyncPHYCommand * fwCmd ) 785{ 786 IOFWUserPHYCommand* cmd = (IOFWUserPHYCommand*) refcon ; 787 788 // tell the vector 789 if( cmd->fVectorCommand ) 790 { 791 cmd->fVectorCommand->asyncPHYCompletion( refcon, status, bus, fwCmd ); 792 } 793 else if ( refcon && cmd->fAsyncRef[0] ) 794 { 795 io_user_reference_t args[3]; 796 args[0] = 8; 797 args[1] = cmd->fPHYCommand->getAckCode(); 798 args[2] = cmd->fPHYCommand->getResponseCode(); 799#if IOFIREWIREDEBUG > 0 800 IOReturn error = 801#endif 802 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, args, 3 ); 803 804 DebugLogCond ( error, "IOFWUserCommand::asyncReadWriteCommandCompletion: sendAsyncResult64 returned error %x\n", error ) ; 805 } 806} 807 808#pragma mark - 809// ============================================================ 810// IOFWUserCompareSwapCommand 811// ============================================================ 812bool 813IOFWUserCompareSwapCommand::initWithSubmitParams( 814 const CommandSubmitParams* params, 815 const IOFireWireUserClient* inUserClient) 816{ 817 bool result = true ; 818 819 result = (NULL != IOFWUserCommand::initWithSubmitParams(params, inUserClient)) ; 820 821 return result ; 822} 823 824IOReturn 825IOFWUserCompareSwapCommand::submit ( CommandSubmitParams * params, CommandSubmitResult * outResult ) 826{ 827 // cast to the right type: 828 // for compare swap commands we are really dealing with a 'CompareSwapSubmitResult' 829 // but we have to override submit() with a prototype matching our superclass submit() 830 CompareSwapSubmitResult* result = (CompareSwapSubmitResult*)outResult ; 831 832 IOReturn error = kIOReturnSuccess ; 833 834 if ( params->staleFlags & kFireWireCommandStale_Buffer ) 835 fSize = params->newBufferSize ; 836 837 Boolean syncFlag = ( params->flags & kFWCommandInterfaceSyncExecute ) != 0 ; 838 Boolean absFlag = ( params->flags & kFireWireCommandAbsolute ) != 0 ; 839 840 FWAddress target_address; 841 target_address.addressLo = (UInt32)(params->newTarget & 0xffffffff); 842 target_address.addressHi = (UInt16)((params->newTarget >> 32) & 0x0000ffff); 843 target_address.nodeID = (UInt16)(params->newTarget >> 48); 844 845 if ( params->staleFlags & kFireWireCommandStale ) 846 { 847 if ( fCommand ) 848 { 849 fCommand->release() ; 850 fCommand = NULL ; 851 } 852 853 if ( absFlag ) 854 fCommand = fUserClient->createCompareAndSwapCommand( params->newGeneration, 855 target_address, 856 (UInt32*)(params+1),// cmpVal past end of param struct 857 (UInt32*)(params+1) + 2,// newVal past end of cmpVal 858 fSize >> 2, 859 syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, 860 this ) ; 861 else 862 { 863 fCommand = fUserClient->getOwner()->createCompareAndSwapCommand( target_address, 864 (UInt32*)(params+1),// cmpVal past end of param struct 865 (UInt32*)(params+1) + 2,// newVal past end of cmpVal 866 fSize >> 2, 867 syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, 868 this, 869 params->newFailOnReset ) ; 870 if ( fCommand ) 871 fCommand->setGeneration( params->newGeneration ) ; 872 } 873 874 if ( !fCommand ) 875 error = kIOReturnNoMemory ; 876 877 } 878 else //if ( params->staleFlags ) 879 { 880 if ( absFlag ) 881 error =((IOFWCompareAndSwapCommand*)fCommand)->reinit( params->newGeneration, 882 target_address, (UInt32*)(params+1),// cmpVal past end of param struct 883 (UInt32*)(params+1) + 2,// newVal past end of cmpVal 884 fSize >> 2, syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, this ) ; 885 else 886 { 887 error = ((IOFWCompareAndSwapCommand*)fCommand)->reinit( target_address, 888 (UInt32*)(params+1),// cmpVal past end of param struct 889 (UInt32*)(params+1) + 2,// newVal past end of cmpVal 890 fSize >> 2, syncFlag ? NULL : & IOFWUserCompareSwapCommand::asyncCompletion, this, 891 params->newFailOnReset ) ; 892 fCommand->setGeneration( params->newGeneration ) ; 893 } 894 } 895 896 if ( !error ) 897 { 898 if( params->staleFlags & kFireWireCommandStale_Timeout ) 899 { 900 fCommand->setTimeout( params->timeoutDuration ); 901 } 902 903 if( params->staleFlags & kFireWireCommandStale_Retries ) 904 { 905 fCommand->setRetries( params->retryCount ); 906 } 907 908 if( params->staleFlags & kFireWireCommandStale_Speed ) 909 { 910 fCommand->setMaxSpeed( params->maxPacketSpeed ); 911 } 912 913 // turn off flushing if requested 914 if( !fFlush ) 915 { 916 fCommand->setFlush( fFlush ); 917 } 918 919 error = fCommand->submit() ; 920 921 if( !fFlush ) 922 { 923 fCommand->setFlush( true ); // always restore command to true 924 } 925 926 if( syncFlag && (result != NULL) ) 927 { 928 result->result = fCommand->getStatus() ; 929 result->bytesTransferred = fCommand->getBytesTransferred() ; 930 result->lockInfo.didLock = ((IOFWCompareAndSwapCommand*)fCommand)->locked( (UInt32*) & result->lockInfo.value ) ; 931 result->ackCode = fCommand->getAckCode(); 932 result->responseCode = fCommand->getResponseCode(); 933 934 // mach won't copy any of our result info out on an error, pretend everything is fine 935 error = kIOReturnSuccess; 936 } 937 } 938 939 return error ; 940} 941 942void 943IOFWUserCompareSwapCommand::asyncCompletion( 944 void * refcon, 945 IOReturn status, 946 IOFireWireNub * device, 947 IOFWCommand * fwCmd) 948{ 949 IOFWUserCompareSwapCommand* cmd = (IOFWUserCompareSwapCommand*)refcon ; 950 951 if (refcon && cmd->fAsyncRef[0] ) 952 { 953 UInt32 lock_value[2]; 954 lock_value[0] = 0; 955 lock_value[1] = 0; 956 bool locked = ((IOFWCompareAndSwapCommand*)cmd->fCommand)->locked( lock_value ); 957 958 UInt64 args[7]; 959 args[0] = (UInt64)status; 960 args[1] = (UInt64)cmd->fCommand->getBytesTransferred(); 961 args[2] = (UInt64)cmd->fCommand->getAckCode(); 962 args[3] = (UInt64)cmd->fCommand->getResponseCode(); 963 args[4] = (UInt64)locked; 964 args[5] = (UInt64)lock_value[0]; 965 args[6] = (UInt64)lock_value[1]; 966#if 0 967 int i = 0; 968 for( i = 0; i < 7; i++ ) 969 { 970#ifdef __LP64__ 971 IOLog( "IOFWUserCompareSwapCommand::asyncCompletion - args[%d] - %llx\n", i, args[i] ); 972#else 973 IOLog( "IOFWUserCompareSwapCommand::asyncCompletion- args[%d] - %llx\n", i, args[i] ); 974#endif 975 } 976#endif 977 978#if IOFIREWIREDEBUG > 0 979 IOReturn error = 980#endif 981 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, args, 7 ); 982 DebugLogCond ( error, "IOFireWireUserClient::asyncCompareSwapCommandCompletion: sendAsyncResult64 returned error 0x%08x\n", error ) ; 983 984 985#if 0 986 CompareSwapSubmitResult sendResult ; 987 988 sendResult.result = status ; 989 sendResult.bytesTransferred = cmd->fCommand->getBytesTransferred() ; 990 sendResult.lockInfo.didLock = (Boolean)((IOFWCompareAndSwapCommand*)cmd->fCommand)->locked( (UInt32*) & sendResult.lockInfo.value ) ; 991 sendResult.ackCode = cmd->fCommand->getAckCode(); 992 sendResult.responseCode = cmd->fCommand->getResponseCode(); 993 994#if IOFIREWIREDEBUG > 0 995 IOReturn error = 996#endif 997 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, (io_user_reference_t *)& sendResult, sizeof(sendResult)/sizeof(UInt32) ) ; // +1 to round up 998 DebugLogCond ( error, "IOFireWireUserClient::asyncCompareSwapCommandCompletion: sendAsyncResult64 returned error 0x%08x\n", error ) ; 999#endif 1000 1001 } 1002} 1003 1004#pragma mark - 1005// ============================================================ 1006// IOFWUserAsyncStreamCommand 1007// ============================================================ 1008bool 1009IOFWUserAsyncStreamCommand::initWithSubmitParams( 1010 const CommandSubmitParams* params, 1011 const IOFireWireUserClient* inUserClient) 1012{ 1013 bool result = true ; 1014 1015 result = (NULL != IOFWUserCommand::initWithSubmitParams(params, inUserClient)); 1016 1017 if (result) 1018 { 1019 fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, params->newBufferSize, kIODirectionOut, fUserClient->getOwningTask() ) ; 1020 result = (NULL != fMem) ; 1021 } 1022 1023 if (result) 1024 { 1025 IOReturn error = fMem->prepare() ; 1026 result = (error == kIOReturnSuccess) ; 1027 } 1028 1029 if (!result) 1030 { 1031 if (fMem) 1032 { 1033 fMem->release() ; 1034 fMem = NULL; 1035 } 1036 } 1037 1038 return result; 1039} 1040 1041IOReturn 1042IOFWUserAsyncStreamCommand::submit( 1043 CommandSubmitParams* params, 1044 CommandSubmitResult* outResult) 1045{ 1046 IOReturn result = kIOReturnSuccess; 1047 Boolean syncFlag = (params->flags & kFWCommandInterfaceSyncExecute) != 0; 1048 1049 if ( params->staleFlags & kFireWireCommandStale_Buffer ) // IOFWUserAsyncStreamCommand 1050 { 1051 if ( fMem ) // whatever happens, we're going to need a new memory descriptor 1052 { 1053 fMem->complete() ; 1054 fMem->release() ; 1055 } 1056 1057 if (NULL == (fMem = IOMemoryDescriptor::withAddressRange( params->newBuffer, 1058 params->newBufferSize, 1059 kIODirectionOut, 1060 fUserClient->getOwningTask())) ) 1061 { 1062 result = kIOReturnNoMemory ; 1063 } 1064 else 1065 { 1066 result = fMem->prepare() ; 1067 1068 if ( kIOReturnSuccess != result ) 1069 { 1070 fMem->release() ; 1071 fMem = NULL ; 1072 } 1073 } 1074 } 1075 1076 if ( kIOReturnSuccess == result) 1077 { 1078 if (fAsyncStreamCommand) 1079 { 1080 fAsyncStreamCommand->release() ; 1081 fAsyncStreamCommand = NULL ; 1082 } 1083 1084 if (fAsyncStreamCommand) 1085 { 1086 result = ((IOFWAsyncStreamCommand*)fAsyncStreamCommand)->reinit( params->newGeneration, 1087 params->data1, // channel 1088 params->sync, 1089 params->tag, 1090 fMem, 1091 params->newBufferSize, 1092 params->maxPacketSpeed, 1093 syncFlag ? NULL : & IOFWUserAsyncStreamCommand::asyncStreamCommandCompletion, 1094 this, 1095 params->newFailOnReset) ; 1096 DebugLogCond ( result, "IOFWUserAsyncStreamCommand::submit: fCommand->reinit result=%08x\n", result) ; 1097 } 1098 else 1099 { 1100 IOFireWireController * control = fUserClient->getOwner()->getController(); 1101 1102 fAsyncStreamCommand = control->createAsyncStreamCommand( params->newGeneration, 1103 params->data1, // channel 1104 params->sync, 1105 params->tag, 1106 fMem, 1107 params->newBufferSize, 1108 params->maxPacketSpeed, 1109 syncFlag ? NULL : & IOFWUserAsyncStreamCommand::asyncStreamCommandCompletion, 1110 this, 1111 params->newFailOnReset); 1112 1113 if (!fAsyncStreamCommand) 1114 result = kIOReturnNoMemory ; 1115 } 1116 } 1117 1118 1119 if ( kIOReturnSuccess == result) 1120 { 1121 if( params->staleFlags & kFireWireCommandStale_Timeout ) 1122 { 1123 fAsyncStreamCommand->setTimeout( params->timeoutDuration ); 1124 } 1125 1126 result = fAsyncStreamCommand->submit() ; 1127 1128 DebugLogCond ( result, "IOFWUserAsyncStreamCommand::submit: fCommand->submit result=%08x\n", result); 1129 } 1130 1131 if( syncFlag && (outResult != NULL) ) 1132 { 1133 outResult->result = fAsyncStreamCommand->getStatus(); 1134 outResult->responseCode = 0; 1135 1136 // mach won't copy any of our result info out on an error, pretend everything is fine 1137 result = kIOReturnSuccess; 1138 } 1139 1140 return result; 1141} 1142 1143void 1144IOFWUserAsyncStreamCommand::free() 1145{ 1146 if( fAsyncStreamCommand ) 1147 { 1148 IOReturn cmdStatus = fAsyncStreamCommand->getStatus(); 1149 if ( cmdStatus == kIOReturnBusy || cmdStatus == kIOFireWirePending ) 1150 { 1151 DebugLog("cancelling cmd %p\n", fAsyncStreamCommand); 1152 fAsyncStreamCommand->cancel( kIOReturnAborted ); 1153 } 1154 1155 fAsyncStreamCommand->release() ; 1156 fAsyncStreamCommand = NULL; 1157 } 1158 1159 IOFWUserCommand::free(); 1160} 1161 1162void 1163IOFWUserAsyncStreamCommand::asyncStreamCommandCompletion(void *refcon, 1164 IOReturn status, 1165 IOFireWireBus *bus, 1166 IOFWAsyncStreamCommand *fwCmd ) 1167{ 1168 IOFWUserAsyncStreamCommand* cmd = (IOFWUserAsyncStreamCommand*) refcon ; 1169 1170 if ( refcon && cmd->fAsyncRef[0] ) 1171 { 1172 io_user_reference_t args[3]; 1173 args[0] = 8; 1174#if IOFIREWIREDEBUG > 0 1175 IOReturn error = 1176#endif 1177 IOFireWireUserClient::sendAsyncResult64( cmd->fAsyncRef, status, args, 3 ); 1178 1179 DebugLogCond ( error, "IOFWUserCommand::asyncStreamCommandCompletion: sendAsyncResult64 returned error %x\n", error ) ; 1180 } 1181} 1182