1/* 2* Copyright (c) 1998-2000 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* IOFireWireLibCommand.cpp 24* IOFireWireLib 25* 26* Created on Fri Dec 15 2000. 27* Copyright (c) 2000-2002 Apple, Inc. All rights reserved. 28* 29*/ 30 31// public 32#import <IOKit/firewire/IOFireWireLib.h> 33 34// private 35#import "IOFireWireLibCommand.h" 36#import "IOFireWireLibDevice.h" 37#import "IOFireWireLibPriv.h" 38 39// system 40#import <assert.h> 41#import <IOKit/IOKitLib.h> 42#import <IOKit/iokitmig.h> 43#import <System/libkern/OSCrossEndian.h> 44 45#define IOFIREWIRELIBCOMMANDIMP_INTERFACE \ 46 &Cmd::SGetStatus, \ 47 &Cmd::SGetTransferredBytes, \ 48 &Cmd::SGetTargetAddress, \ 49 &Cmd::SSetTarget, \ 50 &Cmd::SSetGeneration, \ 51 &Cmd::SSetCallback, \ 52 &Cmd::SSetRefCon, \ 53 &Cmd::SIsExecuting, \ 54 &Cmd::SSubmit, \ 55 &Cmd::SSubmitWithRefconAndCallback, \ 56 &Cmd::SCancel 57 58#define IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2 \ 59 &Cmd::SSetBuffer, \ 60 &Cmd::SGetBuffer, \ 61 &Cmd::SSetMaxPacket, \ 62 &Cmd::SSetFlags 63 64#define IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3 \ 65 &Cmd::SSetTimeoutDuration, \ 66 &Cmd::SSetMaxRetryCount, \ 67 &Cmd::SGetAckCode, \ 68 &Cmd::SGetResponseCode, \ 69 &Cmd::SSetMaxPacketSpeed, \ 70 &Cmd::SGetRefCon 71 72namespace IOFireWireLib { 73 74 ReadCmd::Interface ReadCmd::sInterface = 75 { 76 INTERFACEIMP_INTERFACE, 77 1, 1, // version/revision 78 79 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 80 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2, 81 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3 82 } ; 83 84 ReadQuadCmd::Interface ReadQuadCmd::sInterface = 85 { 86 INTERFACEIMP_INTERFACE, 87 1, 0, // version/revision 88 89 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 90 91 & ReadQuadCmd::SSetQuads 92 } ; 93 94 WriteCmd::Interface WriteCmd::sInterface = 95 { 96 INTERFACEIMP_INTERFACE, 97 1, 1, // version/revision 98 99 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 100 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2, 101 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3 102 } ; 103 104 WriteQuadCmd::Interface WriteQuadCmd::sInterface = 105 { 106 INTERFACEIMP_INTERFACE, 107 1, 0, // version/revision 108 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 109 110 & WriteQuadCmd::SSetQuads 111 } ; 112 113 CompareSwapCmd::Interface CompareSwapCmd::sInterface = 114 { 115 INTERFACEIMP_INTERFACE, 116 2, 0, // version/revision 117 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 118 119 // --- v1 120 & CompareSwapCmd::SSetValues, 121 122 // --- v2 123 & CompareSwapCmd::SSetValues64, 124 & CompareSwapCmd::SDidLock, 125 & CompareSwapCmd::SLocked, 126 & CompareSwapCmd::SLocked64, 127 & CompareSwapCmd::SSetFlags 128 129 } ; 130 131 CompareSwapCmd::Interface_v3 CompareSwapCmd::sInterface_v3 = 132 { 133 INTERFACEIMP_INTERFACE, 134 2, 0, // version/revision 135 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 136 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2, 137 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3, 138 139 // --- v1 140 (void (*)(IOFireWireLibCompareSwapCommandV3Ref, UInt32, UInt32)) &CompareSwapCmd::SSetValues, 141 142 // --- v2 143 (void (*)(IOFireWireLibCompareSwapCommandV3Ref, UInt64, UInt64)) &CompareSwapCmd::SSetValues64, 144 (Boolean (*)(IOFireWireLibCompareSwapCommandV3Ref)) &CompareSwapCmd::SDidLock, 145 (IOReturn (*)(IOFireWireLibCompareSwapCommandV3Ref, UInt32 *)) &CompareSwapCmd::SLocked, 146 (IOReturn (*)(IOFireWireLibCompareSwapCommandV3Ref, UInt64 *)) &CompareSwapCmd::SLocked64 147 } ; 148 149 PHYCmd::Interface PHYCmd::sInterface = 150 { 151 INTERFACEIMP_INTERFACE, 152 1, 0, // version/revision 153 154 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 155 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2, 156 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3, 157 &PHYCmd::S_SetDataQuads 158 }; 159 160 AsyncStreamCmd::Interface AsyncStreamCmd::sInterface = 161 { 162 INTERFACEIMP_INTERFACE, 163 1, 0, // version/revision 164 165 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 166 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v2, 167 IOFIREWIRELIBCOMMANDIMP_INTERFACE_v3, 168 &AsyncStreamCmd::S_SetChannel, 169 &AsyncStreamCmd::S_SetSyncBits, 170 &AsyncStreamCmd::S_SetTagBits 171 }; 172 173 // ================================== 174 // virtual members 175 // ================================== 176#pragma mark - 177 IOFireWireCommandInterface Cmd::sInterface = 178 { 179 INTERFACEIMP_INTERFACE, 180 1, 0, // version/revision 181 IOFIREWIRELIBCOMMANDIMP_INTERFACE, 182 0, 0, 0, 0, 183 0, 0, 0, 0, 0, 0 184 } ; 185 186 Cmd::Cmd( const IUnknownVTbl & vtable, Device& userClient, io_object_t device, 187 const FWAddress& inAddr, CommandCallback inCallback, 188 const bool inFailOnReset, const UInt32 inGeneration, void* inRefCon, 189 CommandSubmitParams* params ) 190 : IOFireWireIUnknown( vtable ), 191 mUserClient( userClient ), 192 mDevice( device ), 193 mBytesTransferred( 0 ), 194 mIsExecuting( false ), 195 mStatus( kIOReturnSuccess ), 196 mRefCon( inRefCon ), 197 mCallback( 0 ), 198 mParams(params) 199 { 200 mUserClient.AddRef() ; 201 bzero(mParams, sizeof(*mParams)) ; 202 203 mParams->callback = (mach_vm_address_t)&CommandCompletionHandler; 204 mParams->refCon = (mach_vm_address_t)this; 205 SetTarget(inAddr) ; 206 SetGeneration(inGeneration) ; 207 mParams->staleFlags = kFireWireCommandStale + kFireWireCommandStale_Buffer ; 208 if (0==device) 209 mParams->flags |= kFireWireCommandAbsolute ; 210 mParams->newFailOnReset = inFailOnReset ; 211 SetCallback(inCallback) ; 212 } 213 214 Cmd::~Cmd() 215 { 216 if (mParams) 217 { 218 if (mParams->kernCommandRef) 219 { 220 IOReturn result = kIOReturnSuccess; 221 222 uint32_t outputCnt = 0; 223 const uint64_t inputs[1]={(const uint64_t)mParams->kernCommandRef}; 224 result = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 225 kReleaseUserObject, 226 inputs,1, 227 NULL,&outputCnt); 228 229 DebugLogCond( result, "Cmd::~Cmd: command release returned 0x%08x\n", result) ; 230 } 231 232 delete mParams ; 233 } 234 235 mUserClient.Release() ; 236 } 237 238 HRESULT 239 Cmd::QueryInterface(REFIID iid, LPVOID* ppv) 240 { 241 HRESULT result = S_OK ; 242 *ppv = nil ; 243 244 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 245 246 if (CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) ) 247 { 248 *ppv = & GetInterface() ; 249 AddRef() ; 250 } 251 else 252 { 253 *ppv = nil ; 254 result = E_NOINTERFACE ; 255 } 256 257 CFRelease(interfaceID) ; 258 return result ; 259 } 260 261 // --- setters ----------------------- 262 void 263 Cmd::SetTarget( 264 const FWAddress& addr) 265 { 266 mParams->newTarget = addr.addressLo; 267 mParams->newTarget |= (((UInt64)addr.addressHi) << 32); 268 mParams->newTarget |= (((UInt64)addr.nodeID) << 48); 269 270// mParams->staleFlags |= kFireWireCommandStale ; 271 } 272 273 void 274 Cmd::SetGeneration( 275 UInt32 inGeneration) 276 { 277 mParams->newGeneration = inGeneration ; 278// mParams->staleFlags |= kFireWireCommandStale ; 279 } 280 281 void 282 Cmd::SetCallback( 283 CommandCallback inCallback) 284 { 285 mCallback = inCallback ; 286 287 if (!mCallback) 288 mParams->flags |= kFWCommandInterfaceSyncExecute ; 289 else 290 mParams->flags &= ~kFWCommandInterfaceSyncExecute ; 291 } 292 293 IOReturn 294 Cmd::PrepareForVectorSubmit( CommandSubmitParams * submit_params ) 295 { 296 IOReturn status = kIOReturnSuccess; 297 298 // can't prep the vector if a command is still inflight 299 if( mIsExecuting ) 300 { 301 status = kIOReturnBusy; 302 } 303 304 // we're not supporting synchronous operations 305 // or inline data when using vectors 306 307 if( status == kIOReturnSuccess ) 308 { 309 if( (mParams->flags & kFWCommandInterfaceSyncExecute) || 310 (mParams->flags & kFireWireCommandUseCopy) ) 311 { 312 status = kIOReturnBadArgument; 313 } 314 } 315 316 // we're only supportting read and write operations on vectors 317 318 if( status == kIOReturnSuccess ) 319 { 320 if( (mParams->type != kFireWireCommandType_Read) && 321 (mParams->type != kFireWireCommandType_Write) && 322 (mParams->type != kFireWireCommandType_PHY) ) 323 { 324 status = kIOReturnBadArgument; 325 } 326 } 327 328 if( status == kIOReturnSuccess ) 329 { 330 // if we don't yet have kernel command for this command, make it now 331 if( !mParams->kernCommandRef ) 332 { 333 // async ref data 334 uint64_t async_ref[kOSAsyncRef64Count]; 335 async_ref[kIOAsyncCalloutFuncIndex] = (uint64_t)0; 336 async_ref[kIOAsyncCalloutRefconIndex] = (unsigned long)0; 337 338 // input data 339 CommandSubmitParams create_params; 340 bcopy( mParams, &create_params, sizeof(CommandSubmitParams) ); 341 342 // swap for Rosetta 343 #ifndef __LP64__ 344 ROSETTA_ONLY( 345 { 346 //create_params.kernCommandRef = create_params.kernCommandRef; // no swap 347 create_params.type = (IOFireWireCommandType)OSSwapInt32(create_params.type); 348 create_params.callback = (mach_vm_address_t)OSSwapInt64( (UInt64)create_params.callback ); 349 create_params.refCon = (mach_vm_address_t)OSSwapInt64( (UInt64)create_params.refCon ); 350 create_params.flags = OSSwapInt32( create_params.flags ); 351 create_params.staleFlags = OSSwapInt32( create_params.staleFlags ); 352 create_params.newTarget = OSSwapInt64( create_params.newTarget ); 353 create_params.newBuffer = (mach_vm_address_t)OSSwapInt64( (UInt64)create_params.newBuffer); 354 create_params.newBufferSize = OSSwapInt32( create_params.newBufferSize ); 355 //create_params.newFailOnReset = create_params.newFailOnReset; 356 create_params.newGeneration = OSSwapInt32( create_params.newGeneration ); 357 create_params.newMaxPacket = OSSwapInt32( create_params.newMaxPacket ); 358 359 create_params.timeoutDuration = OSSwapInt32( create_params.timeoutDuration ); 360 create_params.retryCount = OSSwapInt32( create_params.retryCount ); 361 create_params.maxPacketSpeed = OSSwapInt32( create_params.maxPacketSpeed ); 362 } 363 ); 364 #endif 365 366 // output data 367 UInt32 kernel_ref = 0; 368 size_t outputStructCnt = sizeof(kernel_ref); 369 370 // send it down 371 status = IOConnectCallAsyncStructMethod( mUserClient.GetUserClientConnection(), 372 kCommandCreateAsync, 373 mUserClient.GetAsyncPort(), 374 async_ref, kOSAsyncRef64Count, 375 &create_params, sizeof(CommandSubmitParams), 376 &kernel_ref, &outputStructCnt ); 377 if( status == kIOReturnSuccess ) 378 { 379 mParams->kernCommandRef = kernel_ref; 380 } 381 } 382 } 383 384 if( status == kIOReturnSuccess ) 385 { 386 // staleFlags will be reset to 0 on each Submit() call, 387 // so we set kFireWireCommandStale_MaxPacket before we submit 388 if (mParams->newMaxPacket > 0) 389 mParams->staleFlags |= kFireWireCommandStale_MaxPacket; 390 391 // copy params into vector 392 bcopy( mParams, submit_params, sizeof(CommandSubmitParams) ); 393 394 // swap for Rosetta 395 #ifndef __LP64__ 396 ROSETTA_ONLY( 397 { 398 //submit_params->kernCommandRef = submit_params->kernCommandRef; // no swap 399 submit_params->type = (IOFireWireCommandType)OSSwapInt32(submit_params->type); 400 submit_params->callback = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->callback ); 401 submit_params->refCon = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->refCon ); 402 submit_params->flags = OSSwapInt32( submit_params->flags ); 403 submit_params->staleFlags = OSSwapInt32( submit_params->staleFlags ); 404 submit_params->newTarget = OSSwapInt64( submit_params->newTarget ); 405 submit_params->newBuffer = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->newBuffer); 406 submit_params->newBufferSize = OSSwapInt32( submit_params->newBufferSize ); 407 //submit_params->newFailOnReset = submit_params->newFailOnReset; 408 submit_params->newGeneration = OSSwapInt32( submit_params->newGeneration ); 409 submit_params->newMaxPacket = OSSwapInt32( submit_params->newMaxPacket ); 410 411 submit_params->timeoutDuration = OSSwapInt32( submit_params->timeoutDuration ); 412 submit_params->retryCount = OSSwapInt32( submit_params->retryCount ); 413 submit_params->maxPacketSpeed = OSSwapInt32( submit_params->maxPacketSpeed ); 414 } 415 ); 416 #endif 417 418 } 419 420 // printf( "Cmd::PrepareForVectorSubmit - status = 0x%08lx\n", status ); 421 422 return status; 423 } 424 425 void 426 Cmd::VectorIsExecuting( void ) 427 { 428 mIsExecuting = true ; 429 mParams->staleFlags = 0; 430 } 431 432 IOReturn 433 Cmd::Submit( 434 CommandSubmitParams* params, 435 mach_msg_type_number_t paramsSize, 436 CommandSubmitResult* submitResult, 437 mach_msg_type_number_t* submitResultSize) 438 { 439 // staleFlags will be reset to 0 on each Submit() call, 440 // so we set kFireWireCommandStale_MaxPacket before we submit 441 if (mParams->newMaxPacket > 0) 442 mParams->staleFlags |= kFireWireCommandStale_MaxPacket; 443 444 CommandSubmitParams * submit_params = params; 445 446 IOReturn err = 0; 447 vm_address_t vm_address = 0; 448#ifndef __LP64__ 449 ROSETTA_ONLY( 450 { 451 err = vm_allocate( mach_task_self(), &vm_address, paramsSize, true /*anywhere*/ ); 452 if( vm_address == 0 ) 453 { 454 err = kIOReturnNoMemory; 455 } 456 457 if( !err ) 458 { 459 submit_params = (CommandSubmitParams*)vm_address; 460 bcopy( params, submit_params, paramsSize ); 461 462 //submit_params->kernCommandRef = submit_params->kernCommandRef; // no swap 463 submit_params->type = (IOFireWireCommandType)OSSwapInt32(submit_params->type); 464 submit_params->callback = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->callback ); 465 submit_params->refCon = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->refCon ); 466 submit_params->flags = OSSwapInt32( submit_params->flags ); 467 submit_params->staleFlags = OSSwapInt32( submit_params->staleFlags ); 468 submit_params->newTarget = OSSwapInt64( submit_params->newTarget ); 469 submit_params->newBuffer = (mach_vm_address_t)OSSwapInt64( (UInt64)submit_params->newBuffer); 470 submit_params->newBufferSize = OSSwapInt32( submit_params->newBufferSize ); 471 //submit_params->newFailOnReset = submit_params->newFailOnReset; 472 submit_params->newGeneration = OSSwapInt32( submit_params->newGeneration ); 473 submit_params->newMaxPacket = OSSwapInt32( submit_params->newMaxPacket ); 474 475 submit_params->timeoutDuration = OSSwapInt32( submit_params->timeoutDuration ); 476 submit_params->retryCount = OSSwapInt32( submit_params->retryCount ); 477 submit_params->maxPacketSpeed = OSSwapInt32( submit_params->maxPacketSpeed ); 478 479 } 480 } 481 ); 482#endif 483 484 if( !err ) 485 { 486 uint64_t refrncData[kOSAsyncRef64Count]; 487 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 488 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 489 size_t outputStructCnt = *submitResultSize; 490 491 err = IOConnectCallAsyncStructMethod(mUserClient.GetUserClientConnection(), 492 kCommand_Submit, 493 mUserClient.GetAsyncPort(), 494 refrncData,kOSAsyncRef64Count, 495 submit_params,paramsSize, 496 submitResult,&outputStructCnt); 497 *submitResultSize = outputStructCnt; 498 } 499 500 501 if ( !err ) 502 { 503#ifndef __LP64__ 504 ROSETTA_ONLY( 505 { 506 // submitResult->kernCommandRef = submitResult->kernCommandRef; 507 submitResult->result = OSSwapInt32( submitResult->result ); 508 submitResult->bytesTransferred = OSSwapInt32( submitResult->bytesTransferred ); 509 submitResult->ackCode = OSSwapInt32( submitResult->ackCode ); 510 submitResult->responseCode = OSSwapInt32( submitResult->responseCode ); 511 } 512 ); 513#endif 514 if (mParams->flags & kFWCommandInterfaceSyncExecute) 515 { 516 mStatus = submitResult->result ; 517 mBytesTransferred = submitResult->bytesTransferred ; 518 mAckCode = submitResult->ackCode; 519 mResponseCode = submitResult->responseCode; 520 521 // the kernel has to pass success to get submit results, set err to the proper err here 522 err = mStatus; 523 } 524 else 525 mIsExecuting = true ; 526 527 mParams->staleFlags = 0 ; 528 if (!mParams->kernCommandRef) 529 mParams->kernCommandRef = submitResult->kernCommandRef ; 530 } 531 532 if( vm_address ) 533 { 534 vm_deallocate( mach_task_self(), vm_address, paramsSize ); 535 } 536 537 return err ; 538 } 539 540 IOReturn 541 Cmd::SubmitWithRefconAndCallback( 542 void* inRefCon, 543 CommandCallback inCallback) 544 { 545 if (mIsExecuting) 546 return kIOReturnBusy ; 547 548 mRefCon = inRefCon ; 549 SetCallback(inCallback) ; 550 551 return Submit() ; 552 } 553 554 IOReturn 555 Cmd::Cancel( 556 IOReturn reason) 557 { 558 if (!mIsExecuting) 559 return kIOReturnSuccess ; 560 561 uint32_t outputCnt = 0; 562 return IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 563 mUserClient.MakeSelectorWithObject( kCommand_Cancel_d, mParams->kernCommandRef ), 564 NULL,0, 565 NULL,&outputCnt); 566 } 567 568 void 569 Cmd::SetBuffer( 570 UInt32 inSize, 571 void* inBuffer) 572 { 573 mParams->newBufferSize = inSize ; 574 mParams->newBuffer = (mach_vm_address_t)inBuffer ; 575 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 576 } 577 578 void 579 Cmd::GetBuffer( 580 UInt32* outSize, 581 void** outBuf) 582 { 583 *outSize = mParams->newBufferSize ; 584 *outBuf = (void*)mParams->newBuffer ; 585 } 586 587 IOReturn 588 Cmd::SetMaxPacket( 589 IOByteCount inMaxBytes) 590 { 591 mParams->newMaxPacket = inMaxBytes ; 592 // staleFlags will be reset to 0 on each Submit() call, 593 // so we set kFireWireCommandStale_MaxPacket before we submit 594 595// mParams->staleFlags |= kFireWireCommandStale_MaxPacket; 596 return kIOReturnSuccess ; 597 } 598 599 void 600 Cmd::SetFlags( 601 UInt32 inFlags) 602 { 603 if (mParams->flags & ~kFireWireCommandUserFlagsMask) 604 { 605#ifdef __LP64__ 606 DebugLog("Invalid flags %x passed to SetFlags!\n", inFlags) ; 607#else 608 DebugLog("Invalid flags %lx passed to SetFlags!\n", inFlags) ; 609#endif 610 } 611 612 mParams->flags &= ~kFireWireCommandUserFlagsMask ; 613 mParams->flags |= (inFlags & kFireWireCommandUserFlagsMask) ; 614 615 if (mParams->flags & kFWCommandInterfaceForceCopyAlways) 616 mParams->flags |= kFireWireCommandUseCopy ; 617 if (mParams->flags & kFWCommandInterfaceForceNoCopy) 618 mParams->flags &= ~kFireWireCommandUseCopy ; 619 if (mParams->flags & kFWCommandInterfaceAbsolute ) 620 mParams->flags |= kFireWireCommandAbsolute ; 621 } 622 623 void Cmd::SetTimeoutDuration( 624 UInt32 duration ) 625 { 626 mParams->timeoutDuration = duration; 627 mParams->staleFlags |= kFireWireCommandStale_Timeout; 628 } 629 630 void 631 Cmd::SetMaxRetryCount( 632 UInt32 count ) 633 { 634 mParams->retryCount = count; 635 mParams->staleFlags |= kFireWireCommandStale_Retries; 636 } 637 638 UInt32 639 Cmd::GetAckCode() 640 { 641 return mAckCode; 642 } 643 644 UInt32 645 Cmd::GetResponseCode() 646 { 647 return mResponseCode; 648 } 649 650 void 651 Cmd::SetMaxPacketSpeed( IOFWSpeed speed ) 652 { 653 mParams->maxPacketSpeed = speed; 654 mParams->staleFlags |= kFireWireCommandStale_Speed; 655 } 656 657 void 658 Cmd::CommandCompletionHandler( 659 void* refcon, 660 IOReturn result, 661 void* quads[], 662 UInt32 numQuads ) 663 { 664 Cmd* me = (Cmd*)refcon ; 665 666 me->mStatus = result ; 667 me->mBytesTransferred = (unsigned long)quads[0] ; 668 me->mAckCode = (unsigned long)quads[1]; 669 me->mResponseCode = (unsigned long)quads[2]; 670 me->mIsExecuting = false ; 671 672 if (me->mCallback) 673 (*(me->mCallback))(me->mRefCon, me->mStatus) ; 674 } 675 676 // --- getters ----------------------- 677 IOReturn 678 Cmd::SGetStatus( 679 IOFireWireLibCommandRef self) 680 { 681 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mStatus ; 682 } 683 684 UInt32 685 Cmd::SGetTransferredBytes( 686 IOFireWireLibCommandRef self) 687 { 688 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mBytesTransferred ; 689 } 690 691 void 692 Cmd::SGetTargetAddress( 693 IOFireWireLibCommandRef self, 694 FWAddress* outAddr) 695 { 696 *outAddr = IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mParams->newTarget ; 697 } 698 699 // --- setters ----------------------- 700 void 701 Cmd::SSetTarget( 702 IOFireWireLibCommandRef self, 703 const FWAddress* inAddr) 704 { 705 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetTarget(*inAddr) ; 706 } 707 708 void 709 Cmd::SSetGeneration( 710 IOFireWireLibCommandRef self, 711 UInt32 inGeneration) 712 { 713 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetGeneration(inGeneration) ; 714 } 715 716 void 717 Cmd::SSetCallback( 718 IOFireWireLibCommandRef self, 719 CommandCallback inCallback) 720 { 721 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetCallback(inCallback) ; 722 } 723 724 void 725 Cmd::SSetRefCon( 726 IOFireWireLibCommandRef self, 727 void* refCon) 728 { 729 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mRefCon = refCon ; 730 } 731 732 void * 733 Cmd::SGetRefCon( 734 IOFireWireLibCommandRef self ) 735 { 736 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mRefCon; 737 } 738 739 const Boolean 740 Cmd::SIsExecuting( 741 IOFireWireLibCommandRef self) 742 { 743 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->mIsExecuting; 744 } 745 746 IOReturn 747 Cmd::SSubmit( 748 IOFireWireLibCommandRef self) 749 { 750 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->Submit() ; 751 } 752 753 IOReturn 754 Cmd::SSubmitWithRefconAndCallback( 755 IOFireWireLibCommandRef self, 756 void* inRefCon, 757 CommandCallback inCallback) 758 { 759 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SubmitWithRefconAndCallback(inRefCon, inCallback) ; 760 } 761 762 IOReturn 763 Cmd::SCancel( 764 IOFireWireLibCommandRef self, 765 IOReturn reason) 766 { 767 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->Cancel(reason) ; 768 } 769 770 void 771 Cmd::SSetBuffer( 772 IOFireWireLibCommandRef self, 773 UInt32 inSize, 774 void* inBuf) 775 { 776 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetBuffer(inSize, inBuf) ; 777 } 778 779 void 780 Cmd::SGetBuffer( 781 IOFireWireLibCommandRef self, 782 UInt32* outSize, 783 void** outBuf) 784 { 785 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->GetBuffer(outSize, outBuf) ; 786 } 787 788 IOReturn 789 Cmd::SSetMaxPacket( 790 IOFireWireLibCommandRef self, 791 IOByteCount inMaxBytes) 792 { 793 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetMaxPacket(inMaxBytes) ; 794 } 795 796 void 797 Cmd::SSetFlags( 798 IOFireWireLibCommandRef self, 799 UInt32 inFlags) 800 { 801 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetFlags(inFlags) ; 802 } 803 804 void 805 Cmd::SSetTimeoutDuration( 806 IOFireWireLibCommandRef self, 807 UInt32 duration ) 808 { 809 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetTimeoutDuration( duration ); 810 } 811 812 void 813 Cmd::SSetMaxRetryCount( 814 IOFireWireLibCommandRef self, 815 UInt32 count ) 816 { 817 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetMaxRetryCount( count ); 818 } 819 820 UInt32 821 Cmd::SGetAckCode( IOFireWireLibCommandRef self ) 822 { 823 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->GetAckCode(); 824 } 825 826 UInt32 827 Cmd::SGetResponseCode( IOFireWireLibCommandRef self ) 828 { 829 return IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->GetResponseCode(); 830 } 831 832 void 833 Cmd::SSetMaxPacketSpeed( IOFireWireLibCommandRef self, IOFWSpeed speed ) 834 { 835 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetMaxPacketSpeed( speed ); 836 } 837 838 // ============================================================ 839 // 840 // ReadCmd methods 841 // 842 // ============================================================ 843#pragma mark - 844 ReadCmd::ReadCmd( Device& userclient, io_object_t device, const FWAddress& addr, void* buf, 845 UInt32 size, CommandCallback callback, bool failOnReset, 846 UInt32 generation, void* refcon ) 847 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, device, addr, callback, 848 failOnReset, generation, refcon, 849 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams)]) ) 850 { 851 mParams->type = kFireWireCommandType_Read ; 852 mParams->newBuffer = (mach_vm_address_t)buf ; 853 mParams->newBufferSize = size ; 854 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 855 } 856 857 HRESULT 858 ReadCmd::QueryInterface(REFIID iid, LPVOID* ppv) 859 { 860 HRESULT result = S_OK ; 861 *ppv = nil ; 862 863 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 864 865 if ( CFEqual( interfaceID, IUnknownUUID ) 866 || CFEqual( interfaceID, kIOFireWireCommandInterfaceID) 867 || CFEqual( interfaceID, kIOFireWireReadCommandInterfaceID) 868 || CFEqual( interfaceID, kIOFireWireReadCommandInterfaceID_v2) 869 || CFEqual( interfaceID, kIOFireWireReadCommandInterfaceID_v3) ) 870 { 871 *ppv = & GetInterface() ; 872 AddRef() ; 873 } 874 else 875 { 876 *ppv = nil ; 877 result = E_NOINTERFACE ; 878 } 879 880 CFRelease(interfaceID) ; 881 return result ; 882 } 883 884 IUnknownVTbl** 885 ReadCmd::Alloc( 886 Device& userclient, 887 io_object_t device, 888 const FWAddress& addr, 889 void* buf, 890 UInt32 size, 891 CommandCallback callback, 892 bool failOnReset, 893 UInt32 generation, 894 void* inRefCon) 895 { 896 ReadCmd* me = new ReadCmd( userclient, device, addr, buf, size, callback, failOnReset, generation, inRefCon ) ; 897 if (!me) 898 return nil ; 899 900 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 901 } 902 903 IOReturn 904 ReadCmd::Submit() 905 { 906 if ( mIsExecuting ) 907 return kIOReturnBusy ; 908 909 IOReturn result = kIOReturnSuccess ; 910 UInt8 submitResultExtra[ sizeof(CommandSubmitResult) + kFWUserCommandSubmitWithCopyMaxBufferBytes ] ; 911 CommandSubmitResult* submitResult = (CommandSubmitResult*) submitResultExtra ; 912 mach_msg_type_number_t submitResultSize ; 913 914 if (mParams->flags & kFireWireCommandUseCopy) 915 submitResultSize = sizeof(*submitResult) + mParams->newBufferSize ; 916 else 917 submitResultSize = sizeof(*submitResult) ; 918 919 result = Cmd::Submit(mParams, sizeof(*mParams), submitResult, & submitResultSize) ; 920 921 if ((mParams->flags & kFWCommandInterfaceSyncExecute) && 922 (mParams->flags & kFireWireCommandUseCopy) && 923 (kIOReturnSuccess == result)) 924 { 925 bcopy(submitResult + 1, (void*)mParams->newBuffer, mBytesTransferred) ; 926 } 927 928 return result ; 929 } 930 931 // ============================================================ 932 // 933 // ReadQuadCmd methods 934 // 935 // ============================================================ 936#pragma mark - 937 ReadQuadCmd::ReadQuadCmd( Device& userclient, 938 io_object_t device, 939 const FWAddress & addr, 940 UInt32 quads[], 941 UInt32 numQuads, 942 CommandCallback callback, 943 Boolean failOnReset, 944 UInt32 generation, 945 void* refcon) 946 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, device, addr, callback, 947 failOnReset, generation, refcon, 948 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams)]) ) 949 { 950 mParams->callback = (mach_vm_address_t)&CommandCompletionHandler; 951 mParams->type = kFireWireCommandType_ReadQuadlet ; 952 mParams->newBuffer = (mach_vm_address_t)quads ; 953 mParams->newBufferSize = numQuads << 2 ; // x * 4 954 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 955 mParams->flags |= kFireWireCommandUseCopy ; 956 } 957 958 IUnknownVTbl** 959 ReadQuadCmd::Alloc( Device& inUserClient, io_object_t device, const FWAddress& addr, UInt32 quads[], UInt32 numQuads, 960 CommandCallback callback, Boolean failOnReset, UInt32 generation, void* refcon) 961 { 962 ReadQuadCmd* me = new ReadQuadCmd(inUserClient, device, addr, quads, numQuads, callback, failOnReset, generation, refcon) ; 963 if (!me) 964 return nil ; 965 966 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 967 } 968 969 HRESULT 970 ReadQuadCmd::QueryInterface(REFIID iid, LPVOID* ppv) 971 { 972 HRESULT result = S_OK ; 973 *ppv = nil ; 974 975 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 976 977 if (CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) || CFEqual(interfaceID, kIOFireWireReadQuadletCommandInterfaceID) ) 978 { 979 *ppv = & GetInterface() ; 980 AddRef() ; 981 } 982 else 983 { 984 *ppv = nil ; 985 result = E_NOINTERFACE ; 986 } 987 988 CFRelease(interfaceID) ; 989 return result ; 990 } 991 992 void 993 ReadQuadCmd::SetFlags( 994 UInt32 inFlags) 995 { 996 Cmd::SetFlags(inFlags) ; 997 998 // force always copy: 999 mParams->flags |= kFireWireCommandUseCopy ; 1000 } 1001 1002 void 1003 ReadQuadCmd::SetQuads( 1004 UInt32 inQuads[], 1005 UInt32 inNumQuads) 1006 { 1007 mParams->newBufferSize = inNumQuads << 2; // * 4 1008 mParams->newBuffer = (mach_vm_address_t) inQuads ; 1009 mNumQuads = inNumQuads ; 1010 1011 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1012 } 1013 1014 IOReturn 1015 ReadQuadCmd::Submit() 1016 { 1017 if (mIsExecuting) 1018 return kIOReturnBusy ; 1019 1020 IOReturn result = kIOReturnSuccess ; 1021 Boolean syncFlag = mParams->flags & kFWCommandInterfaceSyncExecute ; 1022 UInt8 submitResultExtra[sizeof(CommandSubmitResult) + (syncFlag ? mParams->newBufferSize : 0)] ; 1023 mach_msg_type_number_t submitResultSize = sizeof(submitResultExtra) ; 1024 CommandSubmitResult* submitResult = reinterpret_cast<CommandSubmitResult*>(submitResultExtra) ; 1025 1026 result = Cmd::Submit(mParams, sizeof(*mParams), submitResult, & submitResultSize) ; 1027 1028 if (kIOReturnSuccess == result && syncFlag) 1029 { 1030 1031 bcopy(submitResult + 1, (void*)mParams->newBuffer, mBytesTransferred) ; 1032 } 1033 1034 return result ; 1035 } 1036 1037 void 1038 ReadQuadCmd::CommandCompletionHandler( 1039 void* refcon, 1040 IOReturn result, 1041 void* quads[], 1042 UInt32 numQuads) 1043 { 1044 numQuads -= 2 ; // number increased by 2 to make 1045 // sendAsyncResult64 always send args as a pointer 1046 // instead of inline... 1047 1048 ReadQuadCmd* me = (ReadQuadCmd*)refcon ; 1049 1050 me->mStatus = result ; 1051 me->mBytesTransferred = (numQuads *4) + 2; 1052 me->mAckCode = (unsigned long)quads[2]; 1053 me->mResponseCode = (unsigned long)quads[1]; 1054 me->mIsExecuting = false; 1055 1056 //zzz this copy is going to have to change for 64 bit 1057 bcopy( quads + 2, (void*)me->mParams->newBuffer, me->mBytesTransferred ); 1058 1059#ifndef __LP64__ 1060 ROSETTA_ONLY( 1061 { 1062 // async results get auto swapped on 32 bit boundaries 1063 // unswap what shouldn't have been swapped 1064 1065 UInt32 * buffer_quads = (UInt32*)me->mParams->newBuffer; 1066 1067 for( unsigned i = 0; i < numQuads; i++ ) 1068 { 1069 buffer_quads[i] = OSSwapInt32( buffer_quads[i] ); 1070 } 1071 } 1072 ); 1073#endif 1074 1075 if (me->mCallback) 1076 (*(me->mCallback))(me->mRefCon, me->mStatus) ; 1077 } 1078 1079 void 1080 ReadQuadCmd::SSetQuads( 1081 IOFireWireLibReadQuadletCommandRef self, 1082 UInt32 inQuads[], 1083 UInt32 inNumQuads) 1084 { 1085 IOFireWireIUnknown::InterfaceMap<ReadQuadCmd>::GetThis(self)->SetQuads(inQuads, inNumQuads) ; 1086 } 1087 1088 // ============================================================ 1089 // 1090 // WriteCmd methods 1091 // 1092 // ============================================================ 1093#pragma mark - 1094 WriteCmd::WriteCmd( Device& userclient, io_object_t device, const FWAddress& addr, void* buf, UInt32 size, 1095 CommandCallback callback, bool failOnReset, UInt32 generation, void* refcon ) 1096 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface), userclient, device, addr, callback, 1097 failOnReset, generation, refcon, 1098 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams)]) ) 1099 { 1100 mParams->type = kFireWireCommandType_Write ; 1101 mParams->newBuffer = (mach_vm_address_t)buf ; 1102 mParams->newBufferSize = size ; 1103 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1104 } 1105 1106 IUnknownVTbl** 1107 WriteCmd::Alloc( Device& userclient, io_object_t device, const FWAddress& addr, void* buf, UInt32 size, 1108 CommandCallback callback, bool failOnReset, UInt32 generation, void* refcon) 1109 { 1110 WriteCmd* me = new WriteCmd( userclient, device, addr, buf, size, callback, failOnReset, generation, refcon ) ; 1111 1112 if (!me) 1113 return nil ; 1114 1115 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 1116 } 1117 1118 HRESULT 1119 WriteCmd::QueryInterface(REFIID iid, LPVOID* ppv) 1120 { 1121 HRESULT result = S_OK ; 1122 *ppv = nil ; 1123 1124 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 1125 1126 if ( CFEqual(interfaceID, IUnknownUUID) 1127 || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) 1128 || CFEqual(interfaceID, kIOFireWireWriteCommandInterfaceID) 1129 || CFEqual(interfaceID, kIOFireWireWriteCommandInterfaceID_v2) 1130 || CFEqual(interfaceID, kIOFireWireWriteCommandInterfaceID_v3) ) 1131 { 1132 *ppv = & GetInterface() ; 1133 AddRef() ; 1134 } 1135 else 1136 { 1137 *ppv = nil ; 1138 result = E_NOINTERFACE ; 1139 } 1140 1141 CFRelease(interfaceID) ; 1142 return result ; 1143 } 1144 1145 IOReturn 1146 WriteCmd::Submit() 1147 { 1148 if (mIsExecuting) 1149 return kIOReturnBusy ; 1150 1151 CommandSubmitResult submitResult ; 1152 mach_msg_type_number_t submitResultSize = sizeof(submitResult) ; 1153 UInt32 paramsSize ; 1154 1155 if (mParams->flags & kFireWireCommandUseCopy) 1156 paramsSize = sizeof(*mParams) + mParams->newBufferSize ; 1157 else 1158 paramsSize = sizeof(*mParams) ; 1159 1160 return Cmd::Submit(mParams, paramsSize, & submitResult, & submitResultSize) ; 1161 } 1162 1163 // ============================================================ 1164 // 1165 // PHYCmd methods 1166 // 1167 // ============================================================ 1168#pragma mark - 1169 PHYCmd::PHYCmd( Device& userclient, UInt32 data1, UInt32 data2, 1170 CommandCallback callback, bool failOnReset, UInt32 generation, void* refcon ) 1171 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface), userclient, NULL, FWAddress(), callback, 1172 failOnReset, generation, refcon, 1173 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams)]) ) 1174 { 1175 mParams->type = kFireWireCommandType_PHY ; 1176 mParams->newBuffer = 0; 1177 mParams->newBufferSize = 0; 1178 // mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1179 mParams->data1 = data1; 1180 mParams->data2 = data2; 1181 } 1182 1183 IUnknownVTbl** 1184 PHYCmd::Alloc( Device& userclient, UInt32 data1, UInt32 data2, 1185 CommandCallback callback, bool failOnReset, UInt32 generation, void* refcon) 1186 { 1187 PHYCmd* me = new PHYCmd( userclient, data1, data2, callback, failOnReset, generation, refcon ); 1188 1189 if (!me) 1190 return nil; 1191 1192 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()); 1193 } 1194 1195 HRESULT 1196 PHYCmd::QueryInterface( REFIID iid, LPVOID* ppv ) 1197 { 1198 HRESULT result = S_OK ; 1199 *ppv = nil ; 1200 1201 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes( kCFAllocatorDefault, iid ); 1202 1203 if ( CFEqual(interfaceID, IUnknownUUID) 1204 || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) 1205 || CFEqual(interfaceID, kIOFireWirePHYCommandInterfaceID) 1206 ) 1207 { 1208 *ppv = & GetInterface() ; 1209 AddRef() ; 1210 } 1211 else 1212 { 1213 *ppv = nil ; 1214 result = E_NOINTERFACE ; 1215 } 1216 1217 CFRelease(interfaceID) ; 1218 return result ; 1219 } 1220 1221 IOReturn 1222 PHYCmd::Submit() 1223 { 1224 if (mIsExecuting) 1225 return kIOReturnBusy ; 1226 1227 CommandSubmitResult submitResult ; 1228 mach_msg_type_number_t submitResultSize = sizeof(submitResult) ; 1229 UInt32 paramsSize ; 1230 1231 paramsSize = sizeof(*mParams) ; 1232 1233 return Cmd::Submit(mParams, paramsSize, & submitResult, & submitResultSize) ; 1234 } 1235 1236 void PHYCmd::S_SetDataQuads( IOFireWireLibPHYCommandRef self, 1237 UInt32 data1, 1238 UInt32 data2 ) 1239 { 1240 PHYCmd * phy_cmd = IOFireWireIUnknown::InterfaceMap<PHYCmd>::GetThis(self); 1241 1242 phy_cmd->mParams->data1 = data1; 1243 phy_cmd->mParams->data2 = data2; 1244 } 1245 1246 // ============================================================ 1247 // 1248 // WriteQuadCmd methods 1249 // 1250 // ============================================================ 1251#pragma mark - 1252 WriteQuadCmd::WriteQuadCmd( Device& userclient, io_object_t device, const FWAddress& addr, UInt32 quads[], UInt32 numQuads, 1253 CommandCallback callback, bool failOnReset, UInt32 generation, void* refcon ) 1254 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, device, addr, callback, failOnReset, generation, refcon, 1255 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams) + numQuads << 2]) ), 1256 mParamsExtra( reinterpret_cast<UInt8*>(mParams) ) 1257 { 1258 mParams->type = kFireWireCommandType_WriteQuadlet ; 1259 mParams->newBuffer = (mach_vm_address_t)(mParams+1);//(void*) quads ; 1260 mParams->newBufferSize = numQuads << 2 ; // * 4 1261 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1262 mParams->flags |= kFireWireCommandUseCopy ; 1263 1264 bcopy(quads, mParams+1, mParams->newBufferSize) ; 1265 } 1266 1267 WriteQuadCmd::~WriteQuadCmd() 1268 { 1269 delete[] mParamsExtra ; 1270 mParamsExtra = nil ; 1271 mParams = nil ; 1272 } 1273 1274 HRESULT 1275 WriteQuadCmd::QueryInterface(REFIID iid, LPVOID* ppv) 1276 { 1277 HRESULT result = S_OK ; 1278 *ppv = nil ; 1279 1280 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 1281 1282 if (CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) || CFEqual(interfaceID, kIOFireWireWriteQuadletCommandInterfaceID) ) 1283 { 1284 *ppv = & GetInterface() ; 1285 AddRef() ; 1286 } 1287 else 1288 { 1289 *ppv = nil ; 1290 result = E_NOINTERFACE ; 1291 } 1292 1293 CFRelease(interfaceID) ; 1294 return result ; 1295 } 1296 1297 IUnknownVTbl** 1298 WriteQuadCmd::Alloc( 1299 Device& userclient, 1300 io_object_t device, 1301 const FWAddress & addr, 1302 UInt32 quads[], 1303 UInt32 numQuads, 1304 CommandCallback callback, 1305 bool failOnReset, 1306 UInt32 generation, 1307 void* refcon) 1308 { 1309 WriteQuadCmd* me = new WriteQuadCmd( userclient, device, addr, quads, numQuads, callback, failOnReset, generation, refcon ) ; 1310 if (!me) 1311 return nil ; 1312 1313 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 1314 } 1315 1316 void 1317 WriteQuadCmd::SetFlags( 1318 UInt32 inFlags) 1319 { 1320 Cmd::SetFlags(inFlags) ; 1321 1322 // force always copy: 1323 mParams->flags |= kFireWireCommandUseCopy ; 1324 } 1325 1326 void 1327 WriteQuadCmd::SetQuads( 1328 UInt32 inQuads[], 1329 UInt32 inNumQuads) 1330 { 1331 UInt32 newSize = inNumQuads << 2 ; 1332 if (newSize > mParams->newBufferSize) 1333 { 1334 // we're going to need more room to hold user's quads: 1335 // set our size to the new size 1336 mParams->newBufferSize = newSize ; 1337 1338 // allocate a new submit params + quad storage area: 1339 UInt8* newParamsExtra = new UInt8[sizeof(CommandSubmitParams) + newSize] ; 1340 1341 DebugLogCond( !newParamsExtra, "warning: WriteQuadCmd::SetQuads: out of memory!\n" ) ; 1342 1343 // copy the old params to the new param block (which is at the beginning of ParamsExtra): 1344 bcopy(mParams, newParamsExtra+0, sizeof(*mParams)) ; 1345 1346 // delete the old storage 1347 delete[] mParamsExtra ; 1348 1349 // assign the new storage to the command object: 1350 mParams = (CommandSubmitParams*) newParamsExtra ; 1351 mParamsExtra = newParamsExtra ; 1352 } 1353 1354 // copy users quads to storage area (just past end of params...) 1355 // this allows us to submit the params and quads to the kernel in one 1356 // operation 1357 bcopy(inQuads, mParams + 1, mParams->newBufferSize) ; 1358 1359 // let kernel know that buffer has changed. (but may not be strictly 1360 // necessary for write quad commands...) 1361 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1362 } 1363 1364 IOReturn 1365 WriteQuadCmd::Submit() 1366 { 1367 if (mIsExecuting) 1368 return kIOReturnBusy ; 1369 1370 CommandSubmitResult submitResult ; 1371 mach_msg_type_number_t submitResultSize = sizeof(submitResult) ; 1372 1373 return Cmd::Submit(mParams, sizeof(*mParams)+mParams->newBufferSize, & submitResult, & submitResultSize) ; 1374 } 1375 1376 void 1377 WriteQuadCmd::SSetQuads( 1378 CmdRef self, 1379 UInt32 inQuads[], 1380 UInt32 inNumQuads) 1381 { 1382 IOFireWireIUnknown::InterfaceMap<WriteQuadCmd>::GetThis(self)->SetQuads(inQuads, inNumQuads) ; 1383 } 1384 1385 // ============================================================ 1386 // 1387 // CompareSwapCmd methods 1388 // 1389 // ============================================================ 1390#pragma mark - 1391 CompareSwapCmd::CompareSwapCmd( Device& userclient, io_object_t device, const FWAddress& addr, UInt64 cmpVal, UInt64 newVal, 1392 unsigned int quads, CommandCallback callback, bool failOnReset, 1393 UInt32 generation, void* refcon ) 1394 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, device, addr, callback, 1395 failOnReset, generation, refcon, 1396 reinterpret_cast<CommandSubmitParams*>( new UInt8[sizeof(CommandSubmitParams) + sizeof(UInt64) * 2] ) ), // 8 bytes/UInt16 * 2 values/cmd 1397 mParamsExtra( reinterpret_cast<UInt8*>(mParams) ), 1398 mInterface_v3( reinterpret_cast<const IUnknownVTbl &>( sInterface_v3 ), this ) 1399 { 1400 mParams->callback = (mach_vm_address_t)&CommandCompletionHandler; 1401 mParams->type = kFireWireCommandType_CompareSwap ; 1402 mParams->newBufferSize = quads * sizeof(UInt32) ; 1403 mParams->flags |= kFireWireCommandUseCopy ; // compare swap always does in-line submits 1404 1405 if (quads == 1) 1406 { 1407 ((UInt32*)(mParams+1))[0] = cmpVal ; 1408 ((UInt32*)(mParams+1))[2] = newVal ; 1409 } 1410 else 1411 { 1412 ((UInt64*)(mParams+1))[0] = cmpVal ; 1413 ((UInt64*)(mParams+1))[1] = newVal ; 1414 } 1415 } 1416 1417 CompareSwapCmd::~CompareSwapCmd() 1418 { 1419 delete[] mParamsExtra ; 1420 mParamsExtra = nil ; 1421 mParams = nil ; 1422 } 1423 1424 IUnknownVTbl** 1425 CompareSwapCmd::Alloc( 1426 Device& userclient, 1427 io_object_t device, 1428 const FWAddress & addr, 1429 UInt64 cmpVal, 1430 UInt64 newVal, 1431 unsigned int quads, 1432 CommandCallback callback, 1433 bool failOnReset, 1434 UInt32 generation, 1435 void* refcon) 1436 { 1437 CompareSwapCmd* me = new CompareSwapCmd( userclient, device, addr, cmpVal, newVal, quads, 1438 callback, failOnReset, generation, refcon ) ; 1439 if (!me) 1440 return nil ; 1441 1442 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 1443 } 1444 1445 HRESULT 1446 CompareSwapCmd::QueryInterface(REFIID iid, LPVOID* ppv) 1447 { 1448 HRESULT result = S_OK ; 1449 *ppv = nil ; 1450 1451 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 1452 1453 if ( CFEqual(interfaceID, IUnknownUUID) 1454 || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) 1455 || CFEqual(interfaceID, kIOFireWireCompareSwapCommandInterfaceID) 1456 // v2 1457 || CFEqual(interfaceID, kIOFireWireCompareSwapCommandInterfaceID_v2 ) ) 1458 { 1459 *ppv = & GetInterface() ; 1460 AddRef() ; 1461 } 1462 else if ( CFEqual(interfaceID, kIOFireWireCompareSwapCommandInterfaceID_v3) ) 1463 { 1464 *ppv = &mInterface_v3; 1465 AddRef() ; 1466 } 1467 else 1468 { 1469 *ppv = nil ; 1470 result = E_NOINTERFACE ; 1471 } 1472 1473 CFRelease(interfaceID) ; 1474 return result ; 1475 } 1476 1477 void 1478 CompareSwapCmd::SetFlags( 1479 UInt32 inFlags) 1480 { 1481 Cmd::SetFlags(inFlags) ; 1482 1483 // force always copy: 1484 mParams->flags |= kFireWireCommandUseCopy ; 1485 } 1486 1487 IOReturn 1488 CompareSwapCmd::SetMaxPacket( 1489 IOByteCount inMaxBytes) 1490 { 1491 return kIOReturnUnsupported ; 1492 } 1493 1494 void 1495 CompareSwapCmd::SetValues( 1496 UInt32 cmpVal, 1497 UInt32 newVal) 1498 { 1499 mParams->newBufferSize = sizeof(UInt32) ; // 1 quadlet 1500 ((UInt32*)(mParams+1))[0] = cmpVal ; 1501 ((UInt32*)(mParams+1))[2] = newVal ; 1502 mParams->staleFlags |= kFireWireCommandStale ; 1503 } 1504 1505 void 1506 CompareSwapCmd::SetValues( 1507 UInt64 cmpVal, 1508 UInt64 newVal) 1509 { 1510 mParams->newBufferSize = sizeof(UInt64) ; // 1 quadlet 1511 ((UInt64*)(mParams+1))[0] = cmpVal ; 1512 ((UInt64*)(mParams+1))[1] = newVal ; 1513 mParams->staleFlags |= kFireWireCommandStale ; 1514 } 1515 1516 IOReturn 1517 CompareSwapCmd::Submit() 1518 { 1519 if (mIsExecuting) 1520 return kIOReturnBusy ; 1521 1522 IOReturn error = kIOReturnSuccess ; 1523 1524 CompareSwapSubmitResult submitResult ; 1525 mach_msg_type_number_t submitResultSize = sizeof(submitResult) ; 1526 1527 error = Cmd::Submit(mParams, (mach_msg_type_number_t)(sizeof(*mParams)+2*sizeof(UInt64)), 1528 reinterpret_cast<CommandSubmitResult*>(& submitResult), & submitResultSize) ; 1529 1530 if ( not error ) 1531 { 1532 if( mParams->flags & kFWCommandInterfaceSyncExecute ) 1533 { 1534 mStatus = submitResult.result ; 1535 mBytesTransferred = submitResult.bytesTransferred ; 1536 bcopy( & submitResult, & mSubmitResult, sizeof(mSubmitResult)) ; 1537 } 1538 else 1539 mIsExecuting = true ; 1540 1541 mParams->staleFlags = 0 ; 1542 if (!mParams->kernCommandRef) 1543 mParams->kernCommandRef = submitResult.kernCommandRef ; 1544 } 1545 1546 return error ; 1547 } 1548 1549 Boolean 1550 CompareSwapCmd::DidLock() 1551 { 1552 return mSubmitResult.lockInfo.didLock ; 1553 } 1554 1555 IOReturn 1556 CompareSwapCmd::Locked( 1557 UInt32* oldValue) 1558 { 1559 if (mIsExecuting) 1560 return kIOReturnBusy ; 1561 if (!mParams->kernCommandRef) 1562 return kIOReturnError ; 1563 if (mParams->newBufferSize != sizeof(UInt32)) 1564 return kIOReturnBadArgument ; 1565 1566 *oldValue = mSubmitResult.lockInfo.value[0]; 1567 return kIOReturnSuccess ; 1568 } 1569 1570 IOReturn 1571 CompareSwapCmd::Locked64( 1572 UInt64* oldValue) 1573 { 1574 if (mIsExecuting) 1575 return kIOReturnBusy ; 1576 if (!mParams->kernCommandRef) 1577 return kIOReturnError ; 1578 if (mParams->newBufferSize != sizeof(UInt64)) 1579 return kIOReturnBadArgument ; 1580 1581 *oldValue = *(UInt64*)mSubmitResult.lockInfo.value; 1582 return kIOReturnSuccess ; 1583 } 1584 1585 void 1586 CompareSwapCmd::SSetValues( 1587 CmdRef self, 1588 UInt32 cmpVal, 1589 UInt32 newVal) 1590 { 1591 IOFireWireIUnknown::InterfaceMap<CompareSwapCmd>::GetThis(self)->SetValues(cmpVal, newVal ) ; 1592 } 1593 1594 void 1595 CompareSwapCmd::SSetValues64( 1596 CmdRef self, 1597 UInt64 cmpVal, 1598 UInt64 newVal) 1599 { 1600 IOFireWireIUnknown::InterfaceMap<CompareSwapCmd>::GetThis(self)->SetValues( cmpVal, newVal ) ; 1601 } 1602 1603 Boolean 1604 CompareSwapCmd::SDidLock( 1605 CmdRef self) 1606 { 1607 return GetThis(self)->DidLock() ; 1608 } 1609 1610 IOReturn 1611 CompareSwapCmd::SLocked( 1612 CmdRef self, 1613 UInt32* oldValue) 1614 { 1615 return GetThis(self)->Locked(oldValue) ; 1616 } 1617 1618 IOReturn 1619 CompareSwapCmd::SLocked64( 1620 CmdRef self, 1621 UInt64* oldValue) 1622 { 1623 return GetThis(self)->Locked64(oldValue) ; 1624 } 1625 1626 void 1627 CompareSwapCmd::SSetFlags( CmdRef self, UInt32 inFlags ) 1628 { 1629 IOFireWireIUnknown::InterfaceMap<Cmd>::GetThis(self)->SetFlags(inFlags) ; 1630 } 1631 1632 void 1633 CompareSwapCmd::CommandCompletionHandler( 1634 void* refcon, 1635 IOReturn result, 1636 io_user_reference_t quads[], 1637 UInt32 numQuads) 1638 { 1639 CompareSwapCmd * me = reinterpret_cast<CompareSwapCmd*>(refcon) ; 1640 1641 #if 0 1642 int i = 0; 1643 for( i = 0; i < 7; i++ ) 1644 { 1645 #ifdef __LP64__ 1646 printf( "CompareSwapCmd::CommandCompletionHandler - quads[%d] - %llx\n", i, quads[i] ); 1647 #else 1648 printf( "CompareSwapCmd::CommandCompletionHandler - quads[%d] - %x\n", i, quads[i] ); 1649 #endif 1650 } 1651 #endif 1652 1653 IF_ROSETTA() 1654 { 1655 #ifndef __LP64__ 1656 me->mSubmitResult.result = (UserObjectHandle)OSSwapInt32((UInt32)quads[0]); 1657 me->mSubmitResult.bytesTransferred = (IOByteCount)OSSwapInt32((UInt32)quads[1]); 1658 me->mSubmitResult.ackCode = (UInt32)OSSwapInt32((UInt32)quads[2]); 1659 me->mSubmitResult.responseCode = (UserObjectHandle)OSSwapInt32((UInt32)quads[3]); 1660 me->mSubmitResult.lockInfo.didLock = (UserObjectHandle)OSSwapInt32((UInt32)quads[4]); 1661 me->mSubmitResult.lockInfo.value[0] = OSSwapInt32((UInt32)quads[5]); 1662 me->mSubmitResult.lockInfo.value[1] = OSSwapInt32((UInt32)quads[6]); 1663 #endif 1664 } 1665 else 1666 { 1667 me->mSubmitResult.result = (UserObjectHandle)quads[0]; 1668 me->mSubmitResult.bytesTransferred = (IOByteCount)quads[1]; 1669 me->mSubmitResult.ackCode = (UInt32)quads[2]; 1670 me->mSubmitResult.responseCode = (UserObjectHandle)quads[3]; 1671 me->mSubmitResult.lockInfo.didLock = (UserObjectHandle)quads[4]; 1672 me->mSubmitResult.lockInfo.value[0] = (UInt32)quads[5]; 1673 me->mSubmitResult.lockInfo.value[1] = (UInt32)quads[6]; 1674 } 1675 1676#if 0 1677 bcopy((CompareSwapSubmitResult*)quads, & me->mSubmitResult, sizeof(me->mSubmitResult)) ; 1678 1679#ifndef __LP64__ 1680 ROSETTA_ONLY( 1681 { 1682 // async results get auto swapped on 32 bit boundaries 1683 // unswap what shouldn't have been swapped 1684 1685 // no one uses kernCommandRef currently 1686 me->mSubmitResult.kernCommandRef = (UserObjectHandle)OSSwapInt32( (UInt32)me->mSubmitResult.kernCommandRef ); 1687 me->mSubmitResult.lockInfo.didLock = OSSwapInt32( me->mSubmitResult.lockInfo.didLock ); 1688 1689 UInt32 * value_quads = (UInt32*)&me->mSubmitResult.lockInfo.value; 1690 value_quads[0] = OSSwapInt32( value_quads[0] ); 1691 value_quads[1] = OSSwapInt32( value_quads[1] ); 1692 } 1693 ); 1694#endif 1695#endif 1696 1697 me->mStatus = result ; 1698 me->mBytesTransferred = me->mSubmitResult.bytesTransferred ; 1699 me->mAckCode = me->mSubmitResult.ackCode; 1700 me->mResponseCode = me->mSubmitResult.responseCode; 1701 me->mIsExecuting = false ; 1702 1703 if (me->mCallback) 1704 (*(me->mCallback))(me->mRefCon, me->mStatus) ; 1705 1706 } 1707 1708 // ============================================================ 1709 // 1710 // AsyncStreamCmd methods 1711 // 1712 // ============================================================ 1713#pragma mark - 1714 AsyncStreamCmd::AsyncStreamCmd(Device& userclient, UInt32 channel, UInt32 sync, UInt32 tag, void* buf, UInt32 size, CommandCallback callback, Boolean failOnReset, UInt32 generation, void* inRefCon ) 1715 : Cmd( reinterpret_cast<const IUnknownVTbl &>( sInterface), userclient, NULL, FWAddress(), callback, failOnReset, generation, inRefCon, 1716 reinterpret_cast<CommandSubmitParams*>(new UInt8[sizeof(CommandSubmitParams)]) ) 1717 { 1718 mParams->type = kFireWireCommandType_AsyncStream ; 1719 mParams->newBuffer = (mach_vm_address_t)buf ; 1720 mParams->newBufferSize = size ; 1721 mParams->staleFlags |= kFireWireCommandStale_Buffer ; 1722 mParams->data1 = channel; 1723 mParams->tag = tag; 1724 mParams->sync = sync; 1725 mParams->newFailOnReset = failOnReset; 1726 } 1727 1728 IUnknownVTbl** 1729 AsyncStreamCmd::Alloc( Device& userclient, UInt32 channel, UInt32 sync, UInt32 tag, void* buf, UInt32 size, CommandCallback callback, Boolean failOnReset, UInt32 generation, void* inRefCon) 1730 { 1731 AsyncStreamCmd* me = new AsyncStreamCmd( userclient, channel, sync, tag, buf, size, callback, failOnReset, generation, inRefCon ) ; 1732 1733 if (!me) 1734 return nil ; 1735 1736 return reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 1737 } 1738 1739 HRESULT 1740 AsyncStreamCmd::QueryInterface(REFIID iid, LPVOID* ppv) 1741 { 1742 HRESULT result = S_OK ; 1743 *ppv = nil ; 1744 1745 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 1746 1747 if ( CFEqual(interfaceID, IUnknownUUID) 1748 || CFEqual(interfaceID, kIOFireWireCommandInterfaceID) 1749 || CFEqual(interfaceID, kIOFireWireAsyncStreamCommandInterfaceID) ) 1750 { 1751 *ppv = & GetInterface() ; 1752 AddRef() ; 1753 } 1754 else 1755 { 1756 *ppv = nil ; 1757 result = E_NOINTERFACE ; 1758 } 1759 1760 CFRelease(interfaceID) ; 1761 return result ; 1762 } 1763 1764 IOReturn 1765 AsyncStreamCmd::Submit() 1766 { 1767 if (mIsExecuting) 1768 return kIOReturnBusy ; 1769 1770 CommandSubmitResult submitResult ; 1771 mach_msg_type_number_t submitResultSize = sizeof(submitResult) ; 1772 UInt32 paramsSize ; 1773 1774 if (mParams->flags & kFireWireCommandUseCopy) 1775 paramsSize = sizeof(*mParams) + mParams->newBufferSize ; 1776 else 1777 paramsSize = sizeof(*mParams) ; 1778 1779 return Cmd::Submit(mParams, paramsSize, & submitResult, & submitResultSize) ; 1780 } 1781 1782 void 1783 AsyncStreamCmd::S_SetChannel( IOFireWireLibAsyncStreamCommandRef self, UInt32 channel ) 1784 { 1785 AsyncStreamCmd * asyncStream_cmd = IOFireWireIUnknown::InterfaceMap<AsyncStreamCmd>::GetThis(self); 1786 1787 asyncStream_cmd->mParams->data1 = channel; 1788 } 1789 1790 void 1791 AsyncStreamCmd::S_SetSyncBits( IOFireWireLibAsyncStreamCommandRef self, UInt16 sync ) 1792 { 1793 AsyncStreamCmd * asyncStream_cmd = IOFireWireIUnknown::InterfaceMap<AsyncStreamCmd>::GetThis(self); 1794 1795 asyncStream_cmd->mParams->sync = sync; 1796 } 1797 1798 void 1799 AsyncStreamCmd::S_SetTagBits( IOFireWireLibAsyncStreamCommandRef self, UInt16 tag ) 1800 { 1801 AsyncStreamCmd * asyncStream_cmd = IOFireWireIUnknown::InterfaceMap<AsyncStreamCmd>::GetThis(self); 1802 1803 asyncStream_cmd->mParams->tag = tag; 1804 } 1805 1806} // namespace IOFireWireLib 1807 1808