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#include <CoreFoundation/CoreFoundation.h> 24 25#include "FWDebugging.h" 26#include "IOFireWireSBP2LibORB.h" 27 28#include <System/libkern/OSCrossEndian.h> 29 30__BEGIN_DECLS 31#include <IOKit/iokitmig.h> 32#include <mach/mach.h> 33__END_DECLS 34 35// 36// static interface table for IOFireWireSBP2LibORBInterface 37// 38 39IOFireWireSBP2LibORBInterface IOFireWireSBP2LibORB::sIOFireWireSBP2LibORBInterface = 40{ 41 0, 42 &IOFireWireSBP2LibORB::staticQueryInterface, 43 &IOFireWireSBP2LibORB::staticAddRef, 44 &IOFireWireSBP2LibORB::staticRelease, 45 1, 0, // version/revision 46 &IOFireWireSBP2LibORB::staticSetRefCon, 47 &IOFireWireSBP2LibORB::staticGetRefCon, 48 &IOFireWireSBP2LibORB::staticSetCommandFlags, 49 &IOFireWireSBP2LibORB::staticSetMaxORBPayloadSize, 50 &IOFireWireSBP2LibORB::staticSetCommandTimeout, 51 &IOFireWireSBP2LibORB::staticSetCommandGeneration, 52 &IOFireWireSBP2LibORB::staticSetCommandBuffersAsRanges, 53 &IOFireWireSBP2LibORB::staticReleaseCommandBuffers, 54 &IOFireWireSBP2LibORB::staticSetCommandBlock, 55 &IOFireWireSBP2LibORB::staticLSIWorkaroundSetCommandBuffersAsRanges, 56 &IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForOutput, 57 &IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForInput 58}; 59 60// alloc 61// 62// static allocator, called by factory method 63 64IUnknownVTbl ** IOFireWireSBP2LibORB::alloc( io_connect_t connection, 65 mach_port_t asyncPort ) 66{ 67 IOReturn status = kIOReturnSuccess; 68 IOFireWireSBP2LibORB * me; 69 IUnknownVTbl ** interface = NULL; 70 71 if( status == kIOReturnSuccess ) 72 { 73 me = new IOFireWireSBP2LibORB(); 74 if( me == NULL ) 75 status = kIOReturnError; 76 } 77 78 if( status == kIOReturnSuccess ) 79 { 80 status = me->init( connection, asyncPort ); 81 } 82 83 if( status != kIOReturnSuccess ) 84 delete me; 85 86 if( status == kIOReturnSuccess ) 87 { 88 // we return an interface here. queryInterface will not be called. call addRef here 89 me->addRef(); 90 interface = (IUnknownVTbl **) &me->fIOFireWireSBP2LibORBInterface.pseudoVTable; 91 } 92 93 return interface; 94} 95 96// ctor 97// 98// 99 100IOFireWireSBP2LibORB::IOFireWireSBP2LibORB( void ) 101{ 102 // init cf plugin ref counting 103 fRefCount = 0; 104 fConnection = 0; 105 fORBRef = 0; 106 fRefCon = 0; 107 fRangeScratch = NULL; 108 fRangeScratchLength = 0; 109 110 // create test driver interface map 111 fIOFireWireSBP2LibORBInterface.pseudoVTable 112 = (IUnknownVTbl *) &sIOFireWireSBP2LibORBInterface; 113 fIOFireWireSBP2LibORBInterface.obj = this; 114 115} 116 117// init 118// 119// 120 121IOReturn IOFireWireSBP2LibORB::init( io_connect_t connection, mach_port_t asyncPort ) 122{ 123 IOReturn status = kIOReturnSuccess; 124 125 fConnection = connection; 126 fAsyncPort = asyncPort; 127 128 FWLOG(( "IOFireWireSBP2LibORB : fConnection %d, fAsyncPort %d\n", 129 fConnection, fAsyncPort )); 130 131 if( !fConnection || !fAsyncPort ) 132 status = kIOReturnError; 133 134 if( status == kIOReturnSuccess ) 135 { 136 uint32_t len = 1; 137 status = IOConnectCallScalarMethod( connection, kIOFWSBP2UserClientCreateORB, 138 NULL, 0, &fORBRef, &len ); 139 if( status != kIOReturnSuccess ) 140 fORBRef = 0; // just to make sure 141 142 FWLOG(( "IOFireWireSBP2LibORB : status = 0x%08x = fORBRef 0x%08lx\n", 143 status, fORBRef )); 144 } 145 146 return status; 147} 148 149// dtor 150// 151// 152 153IOFireWireSBP2LibORB::~IOFireWireSBP2LibORB() 154{ 155 if( fORBRef ) 156 { 157 IOReturn status = kIOReturnSuccess; 158 159 uint32_t len = 0; 160 status = IOConnectCallScalarMethod( fConnection, 161 kIOFWSBP2UserClientReleaseORB, 162 &fORBRef, 1, NULL, &len ); 163 FWLOG(( "IOFireWireSBP2LibORB : release orb status = 0x%08x\n", status )); 164 } 165} 166 167 168////////////////////////////////////////////////////////////////// 169// IUnknown methods 170// 171 172// queryInterface 173// 174// 175 176HRESULT IOFireWireSBP2LibORB::staticQueryInterface( void * self, REFIID iid, void **ppv ) 177{ 178 return getThis(self)->queryInterface( iid, ppv ); 179} 180 181HRESULT IOFireWireSBP2LibORB::queryInterface( REFIID iid, void **ppv ) 182{ 183 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 184 HRESULT result = S_OK; 185 186 if( CFEqual(uuid, IUnknownUUID) || CFEqual(uuid, kIOFireWireSBP2LibORBInterfaceID) ) 187 { 188 *ppv = &fIOFireWireSBP2LibORBInterface; 189 addRef(); 190 } 191 else 192 *ppv = 0; 193 194 if( !*ppv ) 195 result = E_NOINTERFACE; 196 197 CFRelease( uuid ); 198 199 return result; 200} 201 202// addRef 203// 204// 205 206UInt32 IOFireWireSBP2LibORB::staticAddRef( void * self ) 207{ 208 return getThis(self)->addRef(); 209} 210 211UInt32 IOFireWireSBP2LibORB::addRef() 212{ 213 fRefCount += 1; 214 return fRefCount; 215} 216 217// Release 218// 219// 220 221UInt32 IOFireWireSBP2LibORB::staticRelease( void * self ) 222{ 223 return getThis(self)->release(); 224} 225 226UInt32 IOFireWireSBP2LibORB::release( void ) 227{ 228 UInt32 retVal = fRefCount; 229 230 if( 1 == fRefCount-- ) 231 { 232 if( fRangeScratch != NULL ) 233 { 234 // delete it 235 vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength ); 236 fRangeScratch = NULL; 237 fRangeScratchLength = 0; 238 } 239 240 delete this; 241 } 242 243 return retVal; 244} 245 246////////////////////////////////////////////////////////////////// 247// IOFireWireSBP2LibORB methods 248 249// setRefCon 250// 251// 252 253void IOFireWireSBP2LibORB::staticSetRefCon( void * self, void * refCon ) 254{ 255 getThis(self)->setRefCon( refCon ); 256} 257 258void IOFireWireSBP2LibORB::setRefCon( void * refCon ) 259{ 260 FWLOG(( "IOFireWireSBP2LibORB : setRefCon\n")); 261 262 fRefCon = refCon; 263 264 uint32_t len = 0; 265 uint64_t params[2]; 266 267 params[0] = fORBRef; 268 params[1] = (uint64_t)refCon; 269 270 IOConnectCallScalarMethod( fConnection, 271 kIOFWSBP2UserClientSetORBRefCon, 272 params, 2, NULL, &len ); 273} 274 275// getRefCon 276// 277// 278 279void * IOFireWireSBP2LibORB::staticGetRefCon( void * self ) 280{ 281 return getThis(self)->getRefCon(); 282} 283 284void * IOFireWireSBP2LibORB::getRefCon( void ) 285{ 286 return fRefCon; 287} 288 289// setCommandFlags 290// 291// 292 293void IOFireWireSBP2LibORB::staticSetCommandFlags( void * self, UInt32 flags ) 294{ 295 getThis(self)->setCommandFlags( flags ); 296} 297 298void IOFireWireSBP2LibORB::setCommandFlags( UInt32 flags ) 299{ 300 FWLOG(( "IOFireWireSBP2LibORB : setCommandFlags = %ld\n", flags )); 301 302 uint32_t len = 0; 303 uint64_t params[2]; 304 305 params[0] = fORBRef; 306 params[1] = flags; 307 308 IOConnectCallScalarMethod( fConnection, 309 kIOFWSBP2UserClientSetCommandFlags, 310 params, 2, NULL, &len ); 311} 312 313 314// setMaxORBPayloadSize 315// 316// 317 318void IOFireWireSBP2LibORB::staticSetMaxORBPayloadSize( void * self, UInt32 size ) 319{ 320 getThis(self)->setMaxORBPayloadSize( size ); 321} 322 323void IOFireWireSBP2LibORB::setMaxORBPayloadSize( UInt32 size ) 324{ 325 FWLOG(( "IOFireWireSBP2LibORB : setMaxORBPayloadSize = %ld\n", size )); 326 327 uint32_t len = 0; 328 uint64_t params[2]; 329 330 params[0] = fORBRef; 331 params[1] = size; 332 333 IOConnectCallScalarMethod( fConnection, 334 kIOFWSBP2UserClientSetMaxORBPayloadSize, 335 params, 2, NULL, &len ); 336} 337 338// setCommandTimeout 339// 340// 341 342void IOFireWireSBP2LibORB::staticSetCommandTimeout( void * self, UInt32 timeout ) 343{ 344 getThis(self)->setCommandTimeout( timeout ); 345} 346 347void IOFireWireSBP2LibORB::setCommandTimeout( UInt32 timeout ) 348{ 349 FWLOG(( "IOFireWireSBP2LibORB : setCommandTimeout = %ld\n", timeout )); 350 351 uint32_t len = 0; 352 uint64_t params[2]; 353 354 params[0] = fORBRef; 355 params[1] = timeout; 356 357 IOConnectCallScalarMethod( fConnection, 358 kIOFWSBP2UserClientSetCommandTimeout, 359 params, 2, NULL, &len ); 360} 361 362// setCommandGeneration 363// 364// 365 366void IOFireWireSBP2LibORB::staticSetCommandGeneration( void * self, UInt32 generation ) 367{ 368 getThis(self)->setCommandGeneration( generation ); 369} 370 371void IOFireWireSBP2LibORB::setCommandGeneration( UInt32 generation ) 372{ 373 FWLOG(( "IOFireWireSBP2LibORB : setCommandGeneration = %ld\n", generation )); 374 375 uint32_t len = 0; 376 uint64_t params[2]; 377 378 params[0] = fORBRef; 379 params[1] = generation; 380 381 IOConnectCallScalarMethod( fConnection, 382 kIOFWSBP2UserClientSetCommandGeneration, 383 params, 2, NULL, &len ); 384} 385 386// setToDummy 387// 388// 389 390void IOFireWireSBP2LibORB::staticSetToDummy( void * self ) 391{ 392 getThis(self)->setToDummy(); 393} 394 395void IOFireWireSBP2LibORB::setToDummy( void ) 396{ 397 IOReturn status = kIOReturnSuccess; 398 399 FWLOG(( "IOFireWireSBP2LibORB : setToDummy\n" )); 400 401 uint32_t len = 0; 402 status = IOConnectCallScalarMethod( fConnection, 403 kIOFWSBP2UserClientSetToDummy, 404 &fORBRef, 1, NULL, &len ); 405} 406 407// setCommandBuffersAsRanges 408// 409// 410 411IOReturn IOFireWireSBP2LibORB::staticSetCommandBuffersAsRanges( void * self, 412 FWSBP2VirtualRange * ranges, UInt32 withCount, 413 UInt32 withDirection, 414 UInt32 offset, UInt32 length ) 415{ 416 return getThis(self)->setCommandBuffersAsRanges( ranges, withCount, withDirection, 417 offset, length); 418} 419 420IOReturn IOFireWireSBP2LibORB::setCommandBuffersAsRanges( FWSBP2VirtualRange * ranges, 421 UInt32 withCount, UInt32 withDirection, 422 UInt32 offset, 423 UInt32 length ) 424{ 425 IOReturn status = kIOReturnSuccess; 426 427 uint32_t len = 0; 428 uint64_t params[6]; 429 430 FWLOG(( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" )); 431// printf( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" ); 432 433 // 434 // create or grow range scratch 435 // 436 437 UInt32 range_length = withCount * sizeof(FWSBP2PrivateVirtualRange); 438 439 if( fRangeScratchLength < range_length ) 440 { 441 if( fRangeScratch != NULL ) 442 { 443 // delete it 444 vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength ); 445 fRangeScratch = NULL; 446 fRangeScratchLength = 0; 447 } 448 449 // alloc a bigger one 450 vm_allocate( mach_task_self(), (vm_address_t*)&fRangeScratch, range_length, true /*anywhere*/ ); 451 if( fRangeScratch != NULL ) 452 { 453 fRangeScratchLength = range_length; 454 } 455 } 456 457 // 458 // fill range scratch 459 // 460 461 if( fRangeScratch != NULL ) 462 { 463 for( UInt32 i = 0; i < withCount; i++ ) 464 { 465 fRangeScratch[i].address = (uint64_t)ranges[i].address; 466 fRangeScratch[i].length = ranges[i].length; 467 468 ROSETTA_ONLY( 469 fRangeScratch[i].address = OSSwapInt64( fRangeScratch[i].address ); 470 fRangeScratch[i].length = OSSwapInt64( fRangeScratch[i].length ); 471 ); 472 } 473 } 474 475 params[0] = fORBRef; 476 params[1] = (uint64_t)fRangeScratch; 477 params[2] = withCount; 478 params[3] = withDirection; 479 params[4] = offset; 480 params[5] = length; 481 482 status = IOConnectCallScalarMethod( fConnection, 483 kIOFWSBP2UserClientSetCommandBuffersAsRanges, 484 params, 6, NULL, &len ); 485 486 return status; 487} 488 489// releaseCommandBuffers 490// 491// 492 493IOReturn IOFireWireSBP2LibORB::staticReleaseCommandBuffers( void * self ) 494{ 495 return getThis(self)->releaseCommandBuffers(); 496} 497 498IOReturn IOFireWireSBP2LibORB::releaseCommandBuffers( void ) 499{ 500 IOReturn status = kIOReturnSuccess; 501 502 FWLOG(( "IOFireWireSBP2LibORB : releaseCommandBuffers\n" )); 503 504 uint32_t len = 0; 505 status = IOConnectCallScalarMethod( fConnection, 506 kIOFWSBP2UserClientReleaseCommandBuffers, 507 &fORBRef, 1, NULL, &len ); 508 return status; 509} 510 511// setCommandBlock 512// 513// 514 515IOReturn IOFireWireSBP2LibORB::staticSetCommandBlock( void * self, void * buffer, 516 UInt32 length ) 517{ 518 return getThis(self)->setCommandBlock( buffer, length ); 519} 520 521IOReturn IOFireWireSBP2LibORB::setCommandBlock( void * buffer, UInt32 length ) 522{ 523 IOReturn status = kIOReturnSuccess; 524 525 FWLOG(( "IOFireWireSBP2LibORB : setCommandBlock\n" )); 526 527 uint32_t len = 0; 528 uint64_t params[3]; 529 530 vm_address_t address = 0; 531 532 status = vm_allocate( mach_task_self(), &address, length, true /*anywhere*/ ); 533 if( address == 0 ) 534 { 535 status = kIOReturnNoMemory; 536 } 537 538 if( status == kIOReturnSuccess ) 539 { 540 bcopy( buffer, (void*)address, length ); 541 542 params[0] = fORBRef; 543 params[1] = address; 544 params[2] = length; 545 546 status = IOConnectCallScalarMethod( fConnection, 547 kIOFWSBP2UserClientSetCommandBlock, 548 params, 3, NULL, &len ); 549 } 550 551 if( address ) 552 { 553 vm_deallocate( mach_task_self(), address, length ); 554 } 555 556 return status; 557} 558 559// LSIWorkaroundSetCommandBuffersAsRanges 560// 561// 562 563IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSetCommandBuffersAsRanges 564 ( void * self, FWSBP2VirtualRange * ranges, UInt32 withCount, 565 UInt32 withDirection, UInt32 offset, UInt32 length ) 566{ 567 return getThis( self )->LSIWorkaroundSetCommandBuffersAsRanges( ranges, withCount, withDirection, 568 offset, length ); 569} 570 571IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSetCommandBuffersAsRanges 572 ( FWSBP2VirtualRange * ranges, UInt32 withCount, 573 UInt32 withDirection, UInt32 offset, UInt32 length ) 574{ 575 IOReturn status = kIOReturnSuccess; 576 577 uint32_t len = 0; 578 uint64_t params[6]; 579 580 FWLOG(( "IOFireWireSBP2LibORB : setCommandBuffersAsRanges\n" )); 581 582 // 583 // create or grow range scratch 584 // 585 586 UInt32 range_length = withCount * sizeof(FWSBP2PrivateVirtualRange); 587 588 if( fRangeScratchLength < range_length ) 589 { 590 if( fRangeScratch != NULL ) 591 { 592 // delete it 593 vm_deallocate( mach_task_self(), (vm_address_t)fRangeScratch, fRangeScratchLength ); 594 fRangeScratch = NULL; 595 fRangeScratchLength = 0; 596 } 597 598 // alloc a bigger one 599 vm_allocate( mach_task_self(), (vm_address_t*)&fRangeScratch, range_length, true /*anywhere*/ ); 600 if( fRangeScratch != NULL ) 601 { 602 fRangeScratchLength = range_length; 603 } 604 } 605 606 // 607 // fill range scratch 608 // 609 610 if( fRangeScratch != NULL ) 611 { 612 for( UInt32 i = 0; i < withCount; i++ ) 613 { 614 fRangeScratch[i].address = (uint64_t)ranges[i].address; 615 fRangeScratch[i].length = ranges[i].length; 616 617 ROSETTA_ONLY( 618 fRangeScratch[i].address = OSSwapInt64( fRangeScratch[i].address ); 619 fRangeScratch[i].length = OSSwapInt64( fRangeScratch[i].length ); 620 ); 621 } 622 } 623 624 params[0] = fORBRef; 625 params[1] = (uint64_t)fRangeScratch; 626 params[2] = withCount; 627 params[3] = withDirection; 628 params[4] = offset; 629 params[5] = length; 630 631 status = IOConnectCallScalarMethod( fConnection, 632 kIOFWSBP2UserClientLSIWorkaroundSetCommandBuffersAsRanges, 633 params, 6, NULL, &len ); 634 635 return status; 636} 637 638// LSIWorkaroundSyncBuffersForOutput 639// 640// 641 642IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForOutput( void * self ) 643{ 644 return getThis( self )->LSIWorkaroundSyncBuffersForOutput(); 645} 646 647IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSyncBuffersForOutput( void ) 648{ 649 IOReturn status = kIOReturnSuccess; 650 651 FWLOG(( "IOFireWireSBP2LibORB : LSIWorkaroundSyncBuffersForOutput\n" )); 652 653 uint32_t len = 0; 654 status = IOConnectCallScalarMethod( fConnection, 655 kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForOutput, 656 &fORBRef, 1, NULL, &len ); 657 return status; 658} 659 660// LSIWorkaroundSyncBuffersForInput 661// 662// 663 664IOReturn IOFireWireSBP2LibORB::staticLSIWorkaroundSyncBuffersForInput( void * self ) 665{ 666 return getThis( self )->LSIWorkaroundSyncBuffersForInput(); 667} 668 669IOReturn IOFireWireSBP2LibORB::LSIWorkaroundSyncBuffersForInput( void ) 670{ 671 IOReturn status = kIOReturnSuccess; 672 673 FWLOG(( "IOFireWireSBP2LibORB : LSIWorkaroundSyncBuffersForInput\n" )); 674 675 uint32_t len = 0; 676 status = IOConnectCallScalarMethod( fConnection, 677 kIOFWSBP2UserClientMgmtORBLSIWorkaroundSyncBuffersForInput, 678 &fORBRef, 1, NULL, &len ); 679 return status; 680} 681 682// getORBRef 683// 684// 685 686UInt32 IOFireWireSBP2LibORB::getORBRef( void ) 687{ 688 return fORBRef; 689} 690