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 "IOFireWireSBP2LibLUN.h" 27#include "IOFireWireSBP2LibLogin.h" 28#include "IOFireWireSBP2LibMgmtORB.h" 29#include "IOFireWireSBP2UserClientCommon.h" 30 31#include <System/libkern/OSCrossEndian.h> 32 33__BEGIN_DECLS 34#include <IOKit/iokitmig.h> 35#include <mach/mach.h> 36__END_DECLS 37 38// 39// static interface table for IOCFPlugInInterface 40// 41 42IOCFPlugInInterface IOFireWireSBP2LibLUN::sIOCFPlugInInterface = 43{ 44 0, 45 &IOFireWireSBP2LibLUN::staticQueryInterface, 46 &IOFireWireSBP2LibLUN::staticAddRef, 47 &IOFireWireSBP2LibLUN::staticRelease, 48 1, 0, // version/revision 49 &IOFireWireSBP2LibLUN::staticProbe, 50 &IOFireWireSBP2LibLUN::staticStart, 51 &IOFireWireSBP2LibLUN::staticStop 52}; 53 54// 55// static interface table for IOFireWireSBP2LibLUNInterface 56// 57 58IOFireWireSBP2LibLUNInterface IOFireWireSBP2LibLUN::sIOFireWireSBP2LibLUNInterface = 59{ 60 0, 61 &IOFireWireSBP2LibLUN::staticQueryInterface, 62 &IOFireWireSBP2LibLUN::staticAddRef, 63 &IOFireWireSBP2LibLUN::staticRelease, 64 1, 0, // version/revision 65 &IOFireWireSBP2LibLUN::staticOpen, 66 &IOFireWireSBP2LibLUN::staticOpenWithSessionRef, 67 &IOFireWireSBP2LibLUN::staticGetSessionRef, 68 &IOFireWireSBP2LibLUN::staticClose, 69 &IOFireWireSBP2LibLUN::staticAddIODispatcherToRunLoop, 70 &IOFireWireSBP2LibLUN::staticRemoveIODispatcherFromRunLoop, 71 &IOFireWireSBP2LibLUN::staticSetMessageCallback, 72 &IOFireWireSBP2LibLUN::staticSetRefCon, 73 &IOFireWireSBP2LibLUN::staticGetRefCon, 74 &IOFireWireSBP2LibLUN::staticCreateLogin, 75 &IOFireWireSBP2LibLUN::staticCreateMgmtORB, 76}; 77 78// IOFireWireSBP2LibFactory 79// 80// factory method 81 82void *IOFireWireSBP2LibFactory( CFAllocatorRef allocator, CFUUIDRef typeID ) 83{ 84 FWLOG(( "IOFireWireSBP2LibFactory called\n" )); 85 86 if( CFEqual(typeID, kIOFireWireSBP2LibTypeID) ) 87 return (void *) IOFireWireSBP2LibLUN::alloc(); 88 else 89 return NULL; 90} 91 92// alloc 93// 94// static allocator, called by factory method 95 96IOCFPlugInInterface ** IOFireWireSBP2LibLUN::alloc() 97{ 98 IOFireWireSBP2LibLUN * me; 99 IOCFPlugInInterface ** interface = NULL; 100 101 me = new IOFireWireSBP2LibLUN; 102 if( me ) 103 { 104 // we return an interface here. queryInterface will not be called. call addRef here 105 me->addRef(); 106 interface = (IOCFPlugInInterface **) &me->fIOCFPlugInInterface.pseudoVTable; 107 } 108 109 return interface; 110} 111 112// ctor 113// 114// 115 116IOFireWireSBP2LibLUN::IOFireWireSBP2LibLUN( void ) 117{ 118 // init cf plugin ref counting 119 fRefCount = 0; 120 121 // init user client connection 122 fConnection = MACH_PORT_NULL; 123 fService = MACH_PORT_NULL; 124 125 // init async callbacks 126 fAsyncPort = MACH_PORT_NULL; 127 fCFAsyncPort = NULL; 128 fCFRunLoopSource = NULL; 129 fMessageCallbackRoutine = NULL; 130 fMessageCallbackRefCon = NULL; 131 132 // create plugin interface map 133 fIOCFPlugInInterface.pseudoVTable = (IUnknownVTbl *) &sIOCFPlugInInterface; 134 fIOCFPlugInInterface.obj = this; 135 136 // create test driver interface map 137 fIOFireWireSBP2LibLUNInterface.pseudoVTable 138 = (IUnknownVTbl *) &sIOFireWireSBP2LibLUNInterface; 139 fIOFireWireSBP2LibLUNInterface.obj = this; 140 141 fFactoryId = kIOFireWireSBP2LibFactoryID; 142 CFRetain( fFactoryId ); 143 CFPlugInAddInstanceForFactory( fFactoryId ); 144} 145 146// dtor 147// 148// 149 150IOFireWireSBP2LibLUN::~IOFireWireSBP2LibLUN() 151{ 152 CFPlugInRemoveInstanceForFactory( fFactoryId ); 153 CFRelease( fFactoryId ); 154} 155 156////////////////////////////////////////////////////////////////// 157// IUnknown methods 158// 159 160// queryInterface 161// 162// 163 164HRESULT IOFireWireSBP2LibLUN::staticQueryInterface( void * self, REFIID iid, void **ppv ) 165{ 166 return getThis(self)->queryInterface( iid, ppv ); 167} 168 169HRESULT IOFireWireSBP2LibLUN::queryInterface( REFIID iid, void **ppv ) 170{ 171 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 172 HRESULT result = S_OK; 173 174 if( CFEqual(uuid, IUnknownUUID) || CFEqual(uuid, kIOCFPlugInInterfaceID) ) 175 { 176 *ppv = &fIOCFPlugInInterface; 177 addRef(); 178 } 179 else if( CFEqual(uuid, kIOFireWireSBP2LibLUNInterfaceID) ) 180 { 181 *ppv = &fIOFireWireSBP2LibLUNInterface; 182 addRef(); 183 } 184 else 185 *ppv = 0; 186 187 if( !*ppv ) 188 result = E_NOINTERFACE; 189 190 CFRelease( uuid ); 191 192 return result; 193} 194 195// addRef 196// 197// 198 199UInt32 IOFireWireSBP2LibLUN::staticAddRef( void * self ) 200{ 201 return getThis(self)->addRef(); 202} 203 204UInt32 IOFireWireSBP2LibLUN::addRef() 205{ 206 fRefCount += 1; 207 return fRefCount; 208} 209 210// release 211// 212// 213 214UInt32 IOFireWireSBP2LibLUN::staticRelease( void * self ) 215{ 216 return getThis(self)->release(); 217} 218 219UInt32 IOFireWireSBP2LibLUN::release( void ) 220{ 221 UInt32 retVal = fRefCount; 222 223 if( 1 == fRefCount-- ) 224 { 225 delete this; 226 } 227 228 return retVal; 229} 230 231////////////////////////////////////////////////////////////////// 232// IOCFPlugInInterface methods 233// 234 235// probe 236// 237// 238 239IOReturn IOFireWireSBP2LibLUN::staticProbe( void * self, CFDictionaryRef propertyTable, 240 io_service_t service, SInt32 *order ) 241{ 242 return getThis(self)->probe( propertyTable, service, order ); 243} 244 245IOReturn IOFireWireSBP2LibLUN::probe( CFDictionaryRef propertyTable, 246 io_service_t service, SInt32 *order ) 247{ 248 // only load against LUN's 249 if( !service || !IOObjectConformsTo(service, "IOFireWireSBP2LUN") ) 250 return kIOReturnBadArgument; 251 252 return kIOReturnSuccess; 253} 254 255// start 256// 257// 258 259IOReturn IOFireWireSBP2LibLUN::staticStart( void * self, CFDictionaryRef propertyTable, 260 io_service_t service ) 261{ 262 return getThis(self)->start( propertyTable, service ); 263} 264 265IOReturn IOFireWireSBP2LibLUN::start( CFDictionaryRef propertyTable, io_service_t service ) 266{ 267 IOReturn status = kIOReturnSuccess; 268 269 FWLOG(( "IOFireWireSBP2LibLUN : start\n" )); 270 271 fService = service; 272 status = IOServiceOpen( fService, mach_task_self(), 273 kIOFireWireSBP2LibConnection, &fConnection ); 274 if( !fConnection ) 275 status = kIOReturnNoDevice; 276 277 if( status == kIOReturnSuccess ) 278 { 279 status = IOCreateReceivePort( kOSAsyncCompleteMessageID, &fAsyncPort ); 280 } 281 282 FWLOG(( "IOFireWireSBP2LibLUN : IOServiceOpen status = 0x%08lx, connection = %d\n", (UInt32) status, fConnection )); 283 284 return status; 285} 286 287// stop 288// 289// 290 291IOReturn IOFireWireSBP2LibLUN::staticStop( void * self ) 292{ 293 return getThis(self)->stop(); 294} 295 296IOReturn IOFireWireSBP2LibLUN::stop( void ) 297{ 298 FWLOG(( "IOFireWireSBP2LibLUN : stop\n" )); 299 300 removeIODispatcherFromRunLoop(); 301 302 if( fConnection ) 303 { 304 FWLOG(( "IOFireWireSBP2LibLUN : IOServiceClose connection = %d\n", fConnection )); 305 IOServiceClose( fConnection ); 306 fConnection = MACH_PORT_NULL; 307 } 308 309 if( fAsyncPort != MACH_PORT_NULL ) 310 { 311 FWLOG(( "IOFireWireSBP2LibLUN : release fAsyncPort\n" )); 312 mach_port_destroy( mach_task_self(), fAsyncPort ); 313 fAsyncPort = MACH_PORT_NULL; 314 } 315 316 return kIOReturnSuccess; 317} 318 319////////////////////////////////////////////////////////////////// 320// IOFireWireSBP2LUN methods 321// 322 323// open 324// 325// 326 327IOReturn IOFireWireSBP2LibLUN::staticOpen( void * self ) 328{ 329 return getThis(self)->open(); 330} 331 332IOReturn IOFireWireSBP2LibLUN::open( void ) 333{ 334 IOReturn status = kIOReturnSuccess; 335 336 if( !fConnection ) 337 return kIOReturnNoDevice; 338 339 FWLOG(( "IOFireWireSBP2LUN : open\n" )); 340 341 uint32_t len = 0; 342 status = IOConnectCallScalarMethod( fConnection, 343 kIOFWSBP2UserClientOpen, 344 NULL, 0, NULL, &len ); 345 return status; 346} 347 348// openWithSessionRef 349// 350// 351 352IOReturn IOFireWireSBP2LibLUN::staticOpenWithSessionRef( void * self, IOFireWireSessionRef sessionRef ) 353{ 354 return getThis(self)->openWithSessionRef( sessionRef ); 355} 356 357IOReturn IOFireWireSBP2LibLUN::openWithSessionRef( IOFireWireSessionRef sessionRef ) 358{ 359 IOReturn status = kIOReturnSuccess; 360 361 if( !fConnection ) 362 return kIOReturnNoDevice; 363 364 FWLOG(( "IOFireWireSBP2LUN : openWithSessionRef\n" )); 365 366 uint32_t len = 0; 367 uint64_t session_ref_64 = (uint64_t)sessionRef; 368 status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientOpenWithSessionRef, 369 &session_ref_64, 1, NULL, &len ); 370 371 return status; 372} 373 374// getSessionRef 375// 376// 377 378IOFireWireSessionRef IOFireWireSBP2LibLUN::staticGetSessionRef( void * self ) 379{ 380 return getThis(self)->getSessionRef(); 381} 382 383IOFireWireSessionRef IOFireWireSBP2LibLUN::getSessionRef( void ) 384{ 385 IOReturn status = kIOReturnSuccess; 386 uint64_t sessionRef = 0; 387 388 if( !fConnection ) 389 return (IOFireWireSessionRef)sessionRef; 390 391 FWLOG(( "IOFireWireSBP2LUN : getSessionRef\n" )); 392 393 uint32_t len = 1; 394 status = IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientGetSessionRef, 395 NULL, 0, &sessionRef, &len ); 396 397 if( status != kIOReturnSuccess ) 398 sessionRef = 0; // just to make sure 399 400 return (IOFireWireSessionRef)sessionRef; 401} 402 403// close 404// 405// 406 407void IOFireWireSBP2LibLUN::staticClose( void * self ) 408{ 409 getThis(self)->close(); 410} 411 412void IOFireWireSBP2LibLUN::close( void ) 413{ 414 if( !fConnection ) 415 return; 416 417 FWLOG(( "IOFireWireSBP2LUN : close\n" )); 418 419 uint32_t len = 0; 420 IOConnectCallScalarMethod( fConnection, kIOFWSBP2UserClientClose, 421 NULL, 0, NULL, &len ); 422 423} 424 425// addIODispatcherToRunLoop 426// 427// 428 429IOReturn IOFireWireSBP2LibLUN::staticAddIODispatcherToRunLoop( void *self, 430 CFRunLoopRef cfRunLoopRef ) 431{ 432 return getThis(self)->addIODispatcherToRunLoop( cfRunLoopRef ); 433} 434 435IOReturn IOFireWireSBP2LibLUN::addIODispatcherToRunLoop( CFRunLoopRef cfRunLoopRef ) 436{ 437 IOReturn status = kIOReturnSuccess; 438 439 FWLOG(( "IOFireWireSBP2LibLUN : addIODispatcherToRunLoop\n" )); 440 441 if( !fConnection ) 442 return kIOReturnNoDevice; 443 444 if( status == kIOReturnSuccess ) 445 { 446 CFMachPortContext context; 447 Boolean shouldFreeInfo; // zzz what's this for? 448 449 context.version = 1; 450 context.info = this; 451 context.retain = NULL; 452 context.release = NULL; 453 context.copyDescription = NULL; 454 455 fCFAsyncPort = CFMachPortCreateWithPort( kCFAllocatorDefault, fAsyncPort, 456 (CFMachPortCallBack) IODispatchCalloutFromMessage, 457 &context, &shouldFreeInfo ); 458 if( !fCFAsyncPort ) 459 status = kIOReturnNoMemory; 460 } 461 462 if( status == kIOReturnSuccess ) 463 { 464 fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, fCFAsyncPort, 0 ); 465 if( !fCFRunLoopSource ) 466 status = kIOReturnNoMemory; 467 } 468 469 if( status == kIOReturnSuccess ) 470 { 471 fCFRunLoop = cfRunLoopRef; 472 CFRunLoopAddSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopCommonModes ); 473 } 474 475 if( status == kIOReturnSuccess ) 476 { 477 io_async_ref64_t asyncRef; 478 mach_msg_type_number_t size = 0; 479 480 asyncRef[kIOAsyncCalloutFuncIndex] = (uint64_t)&IOFireWireSBP2LibLUN::staticMessageCallback; 481 asyncRef[kIOAsyncCalloutRefconIndex] = (uint64_t)this; 482 483 status = IOConnectCallAsyncScalarMethod( fConnection, kIOFWSBP2UserClientSetMessageCallback, fAsyncPort, asyncRef, kOSAsyncRef64Count, NULL, 0, NULL, &size ); 484 } 485 486 return status; 487} 488 489// removeIODispatcherFromRunLoop 490// 491// 492 493void IOFireWireSBP2LibLUN::staticRemoveIODispatcherFromRunLoop( void * self ) 494{ 495 return getThis(self)->removeIODispatcherFromRunLoop(); 496} 497 498void IOFireWireSBP2LibLUN::removeIODispatcherFromRunLoop( void ) 499{ 500 if( fCFRunLoopSource != NULL ) 501 { 502 CFRunLoopRemoveSource( fCFRunLoop, fCFRunLoopSource, kCFRunLoopCommonModes ); 503 CFRelease( fCFRunLoopSource ); 504 fCFRunLoopSource = NULL; 505 } 506 507 if( fCFAsyncPort != NULL ) 508 { 509 FWLOG(( "IOFireWireSBP2LibLUN : release fCFAsyncPort\n" )); 510 CFMachPortInvalidate( fCFAsyncPort ); 511 CFRelease( fCFAsyncPort ); 512 fCFAsyncPort = NULL; 513 } 514} 515 516// setMessageCallback 517// 518// 519 520void IOFireWireSBP2LibLUN::staticSetMessageCallback( void * self, void * refCon, 521 IOFWSBP2MessageCallback callback ) 522{ 523 getThis(self)->setMessageCallback( refCon, callback ); 524} 525 526void IOFireWireSBP2LibLUN::setMessageCallback( void * refCon, 527 IOFWSBP2MessageCallback callback ) 528{ 529 fMessageCallbackRoutine = callback; 530 fMessageCallbackRefCon = refCon; 531} 532 533// createLogin 534// 535// create a login object 536 537IUnknownVTbl ** IOFireWireSBP2LibLUN::staticCreateLogin( void * self, REFIID iid ) 538{ 539 return getThis(self)->createLogin( iid ); 540} 541 542IUnknownVTbl ** IOFireWireSBP2LibLUN::createLogin( REFIID iid ) 543{ 544 IOReturn status = kIOReturnSuccess; 545 IUnknownVTbl ** iunknown = NULL; 546 547 if( !fConnection ) 548 status = kIOReturnError; 549 550 if( fAsyncPort == MACH_PORT_NULL ) 551 status = kIOReturnError; 552 553 if( status == kIOReturnSuccess ) 554 { 555 iunknown = IOFireWireSBP2LibLogin::alloc( fConnection, fAsyncPort ); 556 if( iunknown == NULL ) 557 status = kIOReturnNoMemory; 558 } 559 560 if( status == kIOReturnSuccess ) 561 { 562 HRESULT res; 563 res = (*iunknown)->QueryInterface( iunknown, iid, 564 (void **) &fLoginInterface ); 565 566 if( res != S_OK ) 567 status = kIOReturnError; 568 } 569 570 if( iunknown != NULL ) 571 { 572 (*iunknown)->Release(iunknown); 573 } 574 575 if( status == kIOReturnSuccess ) 576 return fLoginInterface; 577 else 578 return NULL; 579} 580 581// setRefCon 582// 583// 584 585void IOFireWireSBP2LibLUN::staticSetRefCon( void * self, void * refCon ) 586{ 587 getThis(self)->setRefCon( refCon ); 588} 589 590void IOFireWireSBP2LibLUN::setRefCon( void * refCon ) 591{ 592 fRefCon = refCon; 593} 594 595// getRefCon 596// 597// 598 599void * IOFireWireSBP2LibLUN::staticGetRefCon( void * self ) 600{ 601 return getThis(self)->getRefCon(); 602} 603 604void * IOFireWireSBP2LibLUN::getRefCon( void ) 605{ 606 return fRefCon; 607} 608 609// createMgmtORB 610// 611// 612 613IUnknownVTbl ** IOFireWireSBP2LibLUN::staticCreateMgmtORB( void * self, REFIID iid ) 614{ 615 return getThis(self)->createMgmtORB( iid ); 616} 617 618IUnknownVTbl ** IOFireWireSBP2LibLUN::createMgmtORB( REFIID iid ) 619{ 620 IOReturn status = kIOReturnSuccess; 621 IUnknownVTbl ** iunknown = NULL; 622 IUnknownVTbl ** mgmtORB = NULL; 623 624 if( !fConnection ) 625 status = kIOReturnError; 626 627 if( fAsyncPort == MACH_PORT_NULL ) 628 status = kIOReturnError; 629 630 if( status == kIOReturnSuccess ) 631 { 632 iunknown = IOFireWireSBP2LibMgmtORB::alloc( fConnection, fAsyncPort ); 633 if( iunknown == NULL ) 634 status = kIOReturnNoMemory; 635 } 636 637 if( status == kIOReturnSuccess ) 638 { 639 HRESULT res; 640 res = (*iunknown)->QueryInterface( iunknown, iid, 641 (void **) &mgmtORB ); 642 643 if( res != S_OK ) 644 status = kIOReturnError; 645 } 646 647 if( iunknown != NULL ) 648 { 649 (*iunknown)->Release(iunknown); 650 } 651 652 if( status == kIOReturnSuccess ) 653 return mgmtORB; 654 else 655 return NULL; 656} 657 658 659////////////////////////////////////////////////////////////////// 660// callback static methods 661// 662 663// messageCallback 664// 665// 666 667void IOFireWireSBP2LibLUN::staticMessageCallback( void *refcon, IOReturn result, 668 io_user_reference_t *args, int numArgs ) 669{ 670 ((IOFireWireSBP2LibLUN*)refcon)->messageCallback( result, args, numArgs ); 671} 672 673void IOFireWireSBP2LibLUN::messageCallback( IOReturn result, io_user_reference_t *args, int numArgs ) 674{ 675 FWLOG(( "IOFireWireSBP2LibLUN : messageCallback numArgs = %d\n", numArgs )); 676 677 FWSBP2ReconnectParams params; 678 void * outArgs = NULL; 679 680 UInt32 type = (UInt32)args[11]; 681 if( type == kIOMessageFWSBP2ReconnectComplete || 682 type == kIOMessageFWSBP2ReconnectFailed ) 683 { 684 UInt32 statusBlock[8]; 685 686 { 687 int i; 688 689 for( i = 0; i < 8; i++ ) 690 { 691 IF_ROSETTA() 692 { 693 statusBlock[i] = OSSwapInt32( (UInt32)args[3+i] ); 694 } 695 else 696 { 697 statusBlock[i] = (UInt32)args[3+i]; 698 } 699 } 700 } 701 702 params.refCon = (void*)fRefCon; 703 params.generation = (UInt32)args[0]; 704 params.status = (IOReturn)args[1]; 705 params.reconnectStatusBlock = (FWSBP2StatusBlock*)&statusBlock; 706 params.reconnectStatusBlockLength = (UInt32)args[2]; 707 708 outArgs = ¶ms; 709 } 710 711 if( fMessageCallbackRoutine != NULL ) 712 (fMessageCallbackRoutine)( fMessageCallbackRefCon, type, outArgs ); 713 714} 715