1/* 2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/firewire/IOFireWireBus.h> 24#include <IOKit/firewire/IOFireWireNub.h> 25#include <IOKit/firewire/IOFWUtils.h> 26 27#include "IOFWAsyncStreamReceiver.h" 28#include "IOFWAsyncStreamReceivePort.h" 29#include "IOFWAsyncStreamListener.h" 30#include "FWDebugging.h" 31 32 33OSDefineMetaClassAndStructors(IOFWAsyncStreamReceiver, OSObject); 34OSMetaClassDefineReservedUnused(IOFWAsyncStreamReceiver, 0); 35OSMetaClassDefineReservedUnused(IOFWAsyncStreamReceiver, 1); 36 37//#define DCL_MODE 1 // comment this to turn on multi mode async stream receive 38 39/*! 40 @function initAll 41 Initializes the AsyncStream Recieve command object 42 @result true if successfull. 43*/ 44bool IOFWAsyncStreamReceiver::initAll( IOFireWireController *control, UInt32 channel ) 45{ 46 IOReturn status = kIOReturnSuccess; 47 48 fControl = control; 49 fFWIM = fControl->getLink(); 50 51 fControl->closeGate(); 52 53#ifdef DCL_MODE 54 // Create a DCL program 55 fdclProgram = CreateAsyncStreamRxDCLProgram(receiveAsyncStream, this); 56 if(fdclProgram == NULL){ 57 DebugLog("IOFWAsyncStreamReceiver::initAll -> CreateAsyncStreamRxDCLProgram failed %x\n", status); 58 return false; 59 } 60 61 fChannel = channel; 62 fSpeed = kFWSpeedMaximum; 63 64 fActive = false; 65 fInitialized = true; 66 67 fAsyncStreamClients = OSSet::withCapacity(2); 68 if( fAsyncStreamClients ) 69 fAsyncStreamClientIterator = OSCollectionIterator::withCollection( fAsyncStreamClients ); 70 71 status = activate(control->getBroadcastSpeed()); 72 73 if ( status == kIOReturnSuccess ) 74 { 75 fIODclProgram->setForceStopProc( forceStopNotification, this, fAsyncStreamChan ); 76 } 77 78#else 79 80 UInt64 mask = fControl->getFireWirePhysicalBufferMask(); // get controller mask 81 mask &= ~((UInt64)(PAGE_SIZE-1)); // page align 82 fBufDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( 83 kernel_task, // kernel task 84 0, // options 85 kMaxAsyncStreamReceiveBufferSize*2, // size = 4096 * 2 86 mask ); // mask for physically addressable memory 87 88 if( fBufDesc ) 89 { 90 fListener = control->createMultiIsochReceiveListener(channel,receiveAsyncStream,this); 91 92 if ( fListener ) 93 { 94 fChannel = channel; 95 fSpeed = kFWSpeedMaximum; 96 fActive = false; 97 fInitialized = true; 98 99 fAsyncStreamClients = OSSet::withCapacity(1); 100 if( fAsyncStreamClients ) 101 { 102 fAsyncStreamClientIterator = OSCollectionIterator::withCollection( fAsyncStreamClients ); 103 } 104 else 105 { 106 status = kIOReturnError; 107 } 108 109 status = fListener->Activate(); 110 } 111 else 112 { 113 status = kIOReturnError; 114 } 115 } 116 else 117 { 118 status = kIOReturnError; 119 } 120 121#endif 122 123 fControl->openGate(); 124 125 return ( status == kIOReturnSuccess ); 126} 127 128void IOFWAsyncStreamReceiver::free() 129{ 130 fControl->closeGate(); 131 132#ifdef DCL_MODE 133 134 deactivate(); 135 136 // free dcl program 137 if( fdclProgram ) 138 { 139 FreeAsyncStreamRxDCLProgram(fdclProgram); 140 fdclProgram = NULL; 141 } 142 143 // free the buffer 144 if( fBufDesc ) 145 { 146 fBufDesc->release(); 147 fBufDesc = NULL; 148 } 149 150#else 151 152 if( fListener ) 153 { 154 fListener->Deactivate(); 155 fListener->release(); 156 fListener = NULL; 157 } 158 159 // free the buffer 160 if( fBufDesc ) 161 { 162 fBufDesc->release(); 163 fBufDesc = NULL; 164 } 165 166#endif 167 168 removeAllListeners(); 169 170 if ( fAsyncStreamClients ) 171 { 172 fAsyncStreamClients->release(); 173 fAsyncStreamClients = NULL; 174 } 175 176 if( fAsyncStreamClientIterator ) 177 { 178 fAsyncStreamClientIterator->release(); 179 fAsyncStreamClientIterator = NULL; 180 } 181 182 fControl->openGate(); 183 184 OSObject::free(); 185} 186 187void IOFWAsyncStreamReceiver::FreeAsyncStreamRxDCLProgram(DCLCommandStruct *dclProgram) 188{ 189 UInt32 seg = 0; 190 DCLLabel *startLabel; 191 DCLTransferPacket *receivePacket; 192 DCLUpdateDCLList *update; 193 DCLCommand *dclCommand; 194 DCLCallProc *callProc; 195 FWAsyncStreamReceiveRefCon *rxProcData; 196 DCLJump *jump; 197 198 if ( fReceiveSegmentInfoPtr ) 199 { 200 for (seg=0; seg<kMaxAsyncStreamReceiveBuffers-1; seg++) 201 { 202 // free label 203 startLabel = fReceiveSegmentInfoPtr[seg].pSegmentLabelDCL; 204 if(startLabel == NULL) 205 break; 206 207 receivePacket = (DCLTransferPacket*)startLabel->pNextDCLCommand; 208 if(receivePacket == NULL) 209 break; 210 211 update = (DCLUpdateDCLList*)receivePacket->pNextDCLCommand; 212 if(update == NULL) 213 break; 214 215 dclCommand = (DCLCommand*)update->dclCommandList[0]; 216 if(dclCommand == NULL) 217 break; 218 219 callProc = (DCLCallProc*)update->pNextDCLCommand; 220 if(callProc == NULL) 221 break; 222 223 rxProcData = (FWAsyncStreamReceiveRefCon*)callProc->procData; 224 if(rxProcData == NULL) 225 break; 226 227 jump = (DCLJump *)callProc->pNextDCLCommand; 228 if(jump == NULL) 229 break; 230 231 delete rxProcData; 232 delete dclCommand; 233 delete update->dclCommandList; 234 delete update; 235 delete startLabel; 236 delete jump; 237 delete callProc; 238 } 239 240 delete[] fReceiveSegmentInfoPtr; 241 fReceiveSegmentInfoPtr = NULL; 242 } 243 244 if ( fDCLOverrunLabelPtr ) 245 { 246 receivePacket = (DCLTransferPacket*)fDCLOverrunLabelPtr->pNextDCLCommand; 247 if(receivePacket != NULL) 248 { 249 update = (DCLUpdateDCLList*)receivePacket->pNextDCLCommand; 250 if(update != NULL) 251 { 252 callProc = (DCLCallProc*)update->pNextDCLCommand; 253 if(callProc != NULL) 254 delete callProc; 255 256 delete update->dclCommandList; 257 delete update; 258 } 259 delete receivePacket; 260 } 261 delete fDCLOverrunLabelPtr; 262 fDCLOverrunLabelPtr = NULL; 263 } 264} 265 266DCLCommandStruct *IOFWAsyncStreamReceiver::CreateAsyncStreamRxDCLProgram(DCLCallCommandProc* proc, void *callbackObject) 267{ 268 // Create a DCL program 269 UInt64 mask = fControl->getFireWirePhysicalBufferMask(); // get controller mask 270 UInt16 size = kMaxAsyncStreamReceiveBufferSize; 271 272 mask &= ~((UInt64)(PAGE_SIZE-1)); // page align 273 fBufDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( 274 kernel_task, // kernel task 275 0, // options 276 kMaxAsyncStreamReceiveBuffers*size, // size 277 mask ); // mask for physically addressable memory 278 279 if(fBufDesc == NULL) 280 return NULL; 281 282 UInt8 *currentBuffer = (UInt8*)fBufDesc->getBytesNoCopy() ; 283 284 fReceiveSegmentInfoPtr = new FWAsyncStreamReceiveSegment[kMaxAsyncStreamReceiveBuffers-1]; 285 286 // start of new way 287 for (fSegment=0; fSegment<kMaxAsyncStreamReceiveBuffers-1; fSegment++) 288 { 289 DCLLabel *pLastDCL = new DCLLabel ; 290 { 291 pLastDCL->opcode = kDCLLabelOp ; 292 } 293 294 fReceiveSegmentInfoPtr[fSegment].pSegmentLabelDCL = NULL; 295 fReceiveSegmentInfoPtr[fSegment].pSegmentJumpDCL = NULL; 296 297 // Allocate the label for this segment, and save pointer in seg info 298 fReceiveSegmentInfoPtr[fSegment].pSegmentLabelDCL = (DCLLabelPtr) pLastDCL; 299 300 if (fSegment == 0) 301 { 302 fdclProgram = (DCLCommand*)pLastDCL; 303 } 304 305 DCLTransferPacket *receivePacket = new DCLTransferPacket ; 306 { 307 receivePacket->opcode = kDCLReceivePacketStartOp ; 308 receivePacket->buffer = currentBuffer ; 309 receivePacket->size = size ; 310 } 311 312 DCLUpdateDCLList *update = new DCLUpdateDCLList ; 313 { 314 update->opcode = kDCLUpdateDCLListOp ; 315 update->dclCommandList = new DCLCommand*[1] ; 316 update->dclCommandList[0] = (DCLCommand*)receivePacket ; 317 update->numDCLCommands = 1; // Number of DCL commands in list. 318 } 319 320 DCLCallProc *callProc = new DCLCallProc ; 321 { 322 callProc->opcode = kDCLCallProcOp ; 323 callProc->proc = proc ; 324 callProc->procData = (DCLCallProcDataType)new FWAsyncStreamReceiveRefCon ; 325 326 ((FWAsyncStreamReceiveRefCon*)callProc->procData)->obj = callbackObject; 327 ((FWAsyncStreamReceiveRefCon*)callProc->procData)->thisObj = this; 328 ((FWAsyncStreamReceiveRefCon*)callProc->procData)->buffer = currentBuffer ; 329 ((FWAsyncStreamReceiveRefCon*)callProc->procData)->index = fSegment ; 330 } 331 332 DCLJump *jump = new DCLJump ; 333 { 334 jump->opcode = kDCLJumpOp ; 335 jump->pJumpDCLLabel = pLastDCL ; 336 } 337 338 pLastDCL->pNextDCLCommand = (DCLCommand*)receivePacket ; 339 receivePacket->pNextDCLCommand = (DCLCommand*)update ; 340 update->pNextDCLCommand = (DCLCommand*)callProc ; 341 callProc->pNextDCLCommand = (DCLCommand*)jump ; 342 343 currentBuffer += receivePacket->size ; 344 345 // Store the jump information. 346 fReceiveSegmentInfoPtr[fSegment].pSegmentJumpDCL = jump; 347 } 348 349 // Allocate Overrun label & callback DCL 350 fDCLOverrunLabelPtr = new DCLLabel ; 351 352 fDCLOverrunLabelPtr->opcode = kDCLLabelOp ; 353 354 DCLTransferPacket *receivePacket = new DCLTransferPacket ; 355 { 356 receivePacket->opcode = kDCLReceivePacketStartOp ; 357 receivePacket->buffer = currentBuffer ; 358 receivePacket->size = size ; 359 } 360 361 DCLUpdateDCLList *update = new DCLUpdateDCLList ; 362 { 363 update->opcode = kDCLUpdateDCLListOp ; 364 update->dclCommandList = new DCLCommand*[1] ; 365 update->dclCommandList[0] = (DCLCommand*)receivePacket ; 366 update->numDCLCommands = 1; // Number of DCL commands in list. 367 } 368 369 DCLCallProc *callProc = new DCLCallProc ; 370 { 371 callProc->opcode = kDCLCallProcOp ; 372 callProc->proc = overrunNotification; 373 callProc->procData = (DCLCallProcDataType)this; 374 } 375 376 fDCLOverrunLabelPtr->pNextDCLCommand = (DCLCommand*)receivePacket ; 377 receivePacket->pNextDCLCommand = (DCLCommand*)update ; 378 update->pNextDCLCommand = (DCLCommand*)callProc ; 379 // Set the next pointer in the last DCL to nil 380 callProc->pNextDCLCommand = NULL ; 381 382 fixDCLJumps(false); 383 384 385 return (DCLCommand*)fdclProgram; 386} 387 388IOFWAsyncStreamReceivePort *IOFWAsyncStreamReceiver::CreateAsyncStreamPort(bool talking, DCLCommandStruct *opcodes, void *info, 389 UInt32 startEvent, UInt32 startState, UInt32 startMask, 390 UInt32 channel ) 391{ 392 IOFWAsyncStreamReceivePort *port; 393 394 if(fFWIM == NULL) 395 { 396 DebugLog("IOFWAsyncStreamReceiver::CreateAsyncStreamPort failed -> FWIM is NULL\n"); 397 return NULL; 398 } 399 400 fIODclProgram = fFWIM->createDCLProgram(talking, opcodes, NULL, startEvent, startState, startMask); 401 if(!fIODclProgram) 402 { 403 DebugLog("IOFWAsyncStreamReceiver::CreateAsyncStreamPort failed -> fIODclProgram is NULL\n"); 404 return NULL; 405 } 406 407 port = OSTypeAlloc( IOFWAsyncStreamReceivePort ); 408 if(!port) 409 { 410 DebugLog("IOFWAsyncStreamReceiver::CreateAsyncStreamPort failed -> IOFWAsyncStreamReceivePort is NULL\n"); 411 fIODclProgram->release(); 412 fIODclProgram = NULL; 413 return NULL; 414 } 415 416 if(!port->init(fIODclProgram, fControl, channel)) 417 { 418 DebugLog("IOFWAsyncStreamReceiver::CreateAsyncStreamPort failed -> IOFWAsyncStreamReceivePort::init failed\n"); 419 port->release(); 420 port = NULL; 421 } 422 423 return port; 424} 425 426IOReturn IOFWAsyncStreamReceiver::activate(IOFWSpeed fBroadCastSpeed) 427{ 428 IOReturn status = kIOReturnSuccess; 429 430 if(fInitialized == false) 431 return status; 432 433 if(fActive) 434 return status; 435 436 fSpeed = fBroadCastSpeed; 437 438 // Create IOFWAsyncStreamReceivePort with the required channel and DCL program 439 fAsynStreamPort = CreateAsyncStreamPort(false, fdclProgram, NULL, 0, 0, 0, fChannel); 440 if(fAsynStreamPort == NULL) 441 { 442 FreeAsyncStreamRxDCLProgram(fdclProgram); 443 DebugLog("IOFWAsyncStreamReceiver::activate -> CreateAsyncStreamPort failed %x\n", status); 444 return kIOReturnError; 445 } 446 447 // Create a IOFWIsocChannel with the created port 448 fAsyncStreamChan = fControl->createIsochChannel(false, 0, fSpeed, NULL, NULL); 449 if(fAsyncStreamChan == NULL) 450 { 451 FreeAsyncStreamRxDCLProgram(fdclProgram); 452 fAsynStreamPort->release() ; 453 fAsynStreamPort = NULL; 454 DebugLog("IOFWAsyncStreamReceiver::activate -> createIsochChannel failed %x\n", status); 455 return kIOReturnError; 456 } 457 458 status = fAsyncStreamChan->addListener(fAsynStreamPort); 459 if(status != kIOReturnSuccess) 460 { 461 FreeAsyncStreamRxDCLProgram(fdclProgram); 462 fAsyncStreamChan->stop(); 463 fAsyncStreamChan->releaseChannel(); 464 fAsyncStreamChan->release(); 465 fAsyncStreamChan = NULL; 466 fAsynStreamPort->release() ; 467 fAsynStreamPort = NULL; 468 DebugLog("IOFWAsyncStreamReceiver::activate -> addListener failed %x\n", status); 469 return kIOReturnError; 470 } 471 472 // Allocate channel 473 status = fAsyncStreamChan->allocateChannel(); 474 475 fixDCLJumps(true); 476 477 // Start channel 478 status = fAsyncStreamChan->start(); 479 if(status != kIOReturnSuccess) 480 { 481 FreeAsyncStreamRxDCLProgram(fdclProgram); 482 fAsyncStreamChan->stop(); 483 fAsyncStreamChan->releaseChannel(); 484 fAsyncStreamChan->release(); 485 fAsyncStreamChan = NULL; 486 fAsynStreamPort->release() ; 487 fAsynStreamPort = NULL; 488 DebugLog("IOFWAsyncStreamReceiver::activate -> channel start failed %x\n", status); 489 return kIOReturnError; 490 } 491 492 fActive = true; 493 494 return status; 495} 496 497IOReturn IOFWAsyncStreamReceiver::modifyDCLJumps(DCLCommandStruct *callProc) 498{ 499 DCLCallProc *ptr = (DCLCallProc*)callProc; 500 FWAsyncStreamReceiveRefCon *proc = (FWAsyncStreamReceiveRefCon*)ptr->procData; 501 IOReturn status = kIOReturnError; 502 503 if(fInitialized == false) 504 return status; 505 506 if(!fActive) 507 return status; 508 509 if(proc == NULL) 510 { 511 DebugLog("IOFWAsyncStreamReceiver::modifyDCLJumps callproc data is NULL\n"); 512 return status; 513 } 514 515 // Make the current segment's jump point to OverRun Label 516 UInt16 jumpIndex = (proc->index - 1 + (kMaxAsyncStreamReceiveBuffers-1)) % (kMaxAsyncStreamReceiveBuffers-1); 517 518 fReceiveSegmentInfoPtr[proc->index].pSegmentJumpDCL->pJumpDCLLabel = fDCLOverrunLabelPtr; 519 status = fAsynStreamPort->notify(kFWDCLModifyNotification, 520 (DCLCommand**) & fReceiveSegmentInfoPtr[proc->index].pSegmentJumpDCL, 521 1); 522 if(status != kIOReturnSuccess) 523 DebugLog("IOFWAsyncStreamReceiver::modifyDCLJumps failed %x\n", status); 524 525 fReceiveSegmentInfoPtr[jumpIndex].pSegmentJumpDCL->pJumpDCLLabel = fReceiveSegmentInfoPtr[proc->index].pSegmentLabelDCL; 526 status = fAsynStreamPort->notify(kFWDCLModifyNotification, 527 (DCLCommand**) & fReceiveSegmentInfoPtr[jumpIndex].pSegmentJumpDCL, 528 1); 529 if(status != kIOReturnSuccess) 530 DebugLog("IOFWAsyncStreamReceiver::modifyDCLJumps failed %x\n", status); 531 532 return status; 533} 534 535void IOFWAsyncStreamReceiver::fixDCLJumps(bool restart) 536{ 537 UInt32 i; 538 IOReturn error; 539 540 for (i=0; i<kMaxAsyncStreamReceiveBuffers-1; i++) 541 { 542 if (i != (kMaxAsyncStreamReceiveBuffers-2)) 543 { 544 fReceiveSegmentInfoPtr[i].pSegmentJumpDCL->pJumpDCLLabel = fReceiveSegmentInfoPtr[i+1].pSegmentLabelDCL; 545 fReceiveSegmentInfoPtr[i].pSegmentJumpDCL->pNextDCLCommand = (DCLCommand*)fReceiveSegmentInfoPtr[i+1].pSegmentLabelDCL; 546 } 547 else 548 { 549 fReceiveSegmentInfoPtr[i].pSegmentJumpDCL->pJumpDCLLabel = fDCLOverrunLabelPtr; 550 fReceiveSegmentInfoPtr[i].pSegmentJumpDCL->pNextDCLCommand = (DCLCommand*)fDCLOverrunLabelPtr; 551 } 552 553 // Only if fAsynStreamPort becomes valid, do it !! 554 if(restart == true && fAsynStreamPort != NULL) 555 { 556 error = fAsynStreamPort->notify(kFWDCLModifyNotification, 557 (DCLCommand**) & fReceiveSegmentInfoPtr[i].pSegmentJumpDCL, 558 1); 559 if(error != kIOReturnSuccess) 560 DebugLog("IOFWAsyncStreamReceiver::fixDCLJumps failed %x\n", error); 561 } 562 } 563} 564 565void IOFWAsyncStreamReceiver::overrunNotification(DCLCommandStruct *callProc) 566{ 567 DCLCallProc *ptr = (DCLCallProc*)callProc; 568 569 if( ptr ) 570 { 571 IOFWAsyncStreamReceiver *fwRxAsyncStream = OSDynamicCast( IOFWAsyncStreamReceiver, (OSObject*)ptr->procData ); 572 573 if( fwRxAsyncStream ) 574 { 575 fwRxAsyncStream->fIsoRxOverrun++; 576 fwRxAsyncStream->restart(); 577 } 578 } 579} 580 581IOReturn IOFWAsyncStreamReceiver::forceStopNotification( void* refCon, IOFWIsochChannel* channel, UInt32 stopCondition ) 582{ 583 IOFWAsyncStreamReceiver *fwRxAsyncStream = OSDynamicCast(IOFWAsyncStreamReceiver, (OSObject*)refCon); 584 585 if( fwRxAsyncStream ) 586 fwRxAsyncStream->restart(); 587 588 return kIOReturnSuccess; 589} 590 591void IOFWAsyncStreamReceiver::restart() 592{ 593 // Stop the channel 594 fAsyncStreamChan->stop(); 595 596 fixDCLJumps(true); 597 598 // Start the channel 599 fAsyncStreamChan->start(); 600} 601 602IOReturn IOFWAsyncStreamReceiver::deactivate() 603{ 604 IOReturn status = kIOReturnSuccess; 605 606 if(fInitialized == false) 607 return status; 608 609 if(!fActive) 610 return status; 611 612 // Stop the channel 613 if( fAsyncStreamChan ) 614 fAsyncStreamChan->stop(); 615 616 // Lets release the channel 617 if( fAsyncStreamChan ) 618 fAsyncStreamChan->releaseChannel(); 619 620 // free the channel 621 if( fAsyncStreamChan ) 622 { 623 fAsyncStreamChan->release(); 624 fAsyncStreamChan = NULL; 625 } 626 627 // free the port 628 if( fAsynStreamPort ) 629 { 630 fAsynStreamPort->release(); 631 fAsynStreamPort = NULL; 632 } 633 634 fActive = false; 635 636 return status; 637} 638 639IOReturn IOFWAsyncStreamReceiver::receiveAsyncStream(void *refcon, IOFireWireMultiIsochReceivePacket *pPacket) 640{ 641 IOFWAsyncStreamReceiver *receiver = (IOFWAsyncStreamReceiver*)refcon; 642 643 if( not receiver) 644 return kIOReturnError; 645 646 UInt16 index = 0; 647 IOByteCount offset = 0; 648 649 for(;;) 650 { 651 if(index == pPacket->numRanges) 652 break; 653 654 IOByteCount bytesWritten = receiver->fBufDesc->writeBytes(offset, (void*)pPacket->ranges[index].address, pPacket->ranges[index].length); 655 offset += bytesWritten; 656 657 index++; 658 } 659 660 // Need to make the isoch header native endian 661 UInt32 *pHeader = (UInt32*)receiver->fBufDesc->getBytesNoCopy(); 662 *pHeader = OSSwapLittleToHostInt32(*pHeader); 663 664 receiver->indicateListeners( (UInt8*)receiver->fBufDesc->getBytesNoCopy() ); 665 666 pPacket->clientDone(); 667 668 return kIOReturnSuccess; 669} 670 671 672void IOFWAsyncStreamReceiver::receiveAsyncStream(DCLCommandStruct *callProc) 673{ 674 DCLCallProc *ptr = (DCLCallProc*)callProc; 675 676 if( not ptr ) return; 677 678 FWAsyncStreamReceiveRefCon *proc = (FWAsyncStreamReceiveRefCon*)ptr->procData; 679 680 if( not proc ) return; 681 682 IOFWAsyncStreamReceiver *receiver = (IOFWAsyncStreamReceiver*)proc->thisObj; 683 684 if( not receiver) return; 685 686 UInt8 *buffer = proc->buffer; 687 688 receiver->indicateListeners( buffer ); 689 690 if( receiver->modifyDCLJumps( callProc ) == kIOReturnError ) return; 691} 692 693bool IOFWAsyncStreamReceiver::addListener ( IOFWAsyncStreamListener *listener ) 694{ 695 fControl->closeGate(); 696 697 bool ret = true; 698 699 if( listener ) 700 { 701 if(not fAsyncStreamClients->setObject( listener )) 702 ret = false; 703 } 704 705 fControl->openGate(); 706 707 return ret; 708} 709 710void IOFWAsyncStreamReceiver::removeAllListeners() 711{ 712 IOFWAsyncStreamListener * found; 713 714 fControl->closeGate(); 715 716 fAsyncStreamClientIterator->reset(); 717 718 while( (found = (IOFWAsyncStreamListener *) fAsyncStreamClientIterator->getNextObject())) 719 fAsyncStreamClients->removeObject(found); 720 721 fControl->openGate(); 722 723 return; 724} 725 726void IOFWAsyncStreamReceiver::removeListener ( IOFWAsyncStreamListener *listener ) 727{ 728 fControl->closeGate(); 729 730 if( listener ) 731 fAsyncStreamClients->removeObject(listener); 732 733 fControl->openGate(); 734 735 return; 736} 737 738void IOFWAsyncStreamReceiver::indicateListeners ( UInt8 *buffer ) 739{ 740 IOFWAsyncStreamListener * found; 741 742 fAsyncStreamClientIterator->reset(); 743 744 while( (found = (IOFWAsyncStreamListener *) fAsyncStreamClientIterator->getNextObject() ) ) 745 found->invokeClients(buffer); 746 747} 748 749UInt32 IOFWAsyncStreamReceiver::getClientsCount() 750{ 751 return fAsyncStreamClients->getCount(); 752} 753 754 755OSDefineMetaClassAndStructors(IOFWAsyncStreamListener, OSObject); 756OSMetaClassDefineReservedUnused(IOFWAsyncStreamListener, 0); 757OSMetaClassDefineReservedUnused(IOFWAsyncStreamListener, 1); 758 759bool IOFWAsyncStreamListener::initAll(IOFireWireController *control, UInt32 channel, FWAsyncStreamReceiveCallback proc, void *obj) 760{ 761 fControl = control; 762 763 fControl->closeGate(); 764 765 fReceiver = control->getAsyncStreamReceiver( channel ); 766 767 bool ret = false; 768 769 if( fReceiver == NULL ) 770 fReceiver = control->allocAsyncStreamReceiver( channel, proc, obj ); 771 772 if( fReceiver and fReceiver->addListener( this ) ) 773 { 774 fReceiver->retain(); 775 fClientProc = proc; 776 fRefCon = obj; 777 ret = true; 778 TurnOffNotification(); 779 } 780 781 fControl->openGate(); 782 783 return ret; 784} 785 786const FWAsyncStreamReceiveCallback IOFWAsyncStreamListener::setListenerHandler( FWAsyncStreamReceiveCallback inReceiver ) 787{ 788 FWAsyncStreamReceiveCallback previousCallback = fClientProc; 789 fClientProc = inReceiver; 790 791 return previousCallback; 792} 793 794void IOFWAsyncStreamListener::free() 795{ 796 fControl->closeGate(); 797 798 if( fReceiver ) 799 { 800 if( fReceiver->getClientsCount() == 0 ) 801 fControl->removeAsyncStreamReceiver(fReceiver); 802 803 fReceiver->release(); 804 805 fReceiver = NULL; 806 } 807 808 fControl->openGate(); 809 810 OSObject::free(); 811} 812 813void IOFWAsyncStreamListener::invokeClients(UInt8 *buffer) 814{ 815 if( fNotify ) 816 { 817 fClientProc(fRefCon, buffer); 818 } 819} 820 821UInt32 IOFWAsyncStreamListener::getOverrunCounter() 822{ 823 return fReceiver->getOverrunCounter(); 824} 825 826void IOFWAsyncStreamListener::setFlags( UInt32 flags ) 827{ 828 fFlags = flags; 829} 830 831UInt32 IOFWAsyncStreamListener::getFlags() 832{ 833 return fFlags; 834} 835 836 837