1/* 2 * Copyright (c) 1998-2002 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 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. 24 * 25 * HISTORY 26 * 27 */ 28 29#include <IOKit/firewire/IOFWDCLTranslator.h> 30 31//////////////////////////////////////////////////////////////////////////////// 32// 33// FWDCLReceivePacketStart 34// 35// This routine runs a DCL receive packet start command. 36// 37 38static void DCLReceivePacketStart( 39 DCLCommand** ppCurrentDCLCommand, 40 UInt32 packetHeader, 41 UInt8** pPacketBuffer, 42 UInt32* pPacketSize, 43 bool* pGetNextPacket) 44{ 45 DCLTransferPacket* pDCLTransferPacket; 46 UInt8 * transferBuffer; 47 UInt8 * packetBuffer; 48 SInt32 transferSize, packetSize; 49 50 // Recast DCL command. 51 pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand; 52 53 // Get some parameters. 54 transferBuffer = (UInt8 *)pDCLTransferPacket->buffer; 55 transferSize = pDCLTransferPacket->size - sizeof (UInt32); 56 packetSize = *pPacketSize; 57 if (transferSize > packetSize) 58 transferSize = packetSize; 59 packetBuffer = *pPacketBuffer; 60 61 // Transfer the packet data. 62 *((UInt32 *) transferBuffer) = packetHeader; 63 transferBuffer += sizeof (UInt32); 64 if (transferSize > 0) { 65 bcopy (packetBuffer, transferBuffer, transferSize); 66 packetSize -= transferSize; 67 packetBuffer += transferSize; 68 } 69 70 // Check if we need another packet. 71 *pGetNextPacket = true; 72 if (pDCLTransferPacket->pNextDCLCommand != NULL) 73 { 74 if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) == 75 kDCLReceivePacketOp) 76 { 77 *pGetNextPacket = false; 78 } 79 } 80 81 // Update parameters. 82 *ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand; 83 *pPacketBuffer = packetBuffer; 84 *pPacketSize = packetSize; 85} 86 87 88//////////////////////////////////////////////////////////////////////////////// 89// 90// DCLReceivePacket 91// 92// This routine runs a DCL receive packet command. 93// 94 95static void DCLReceivePacket( 96 DCLCommand** ppCurrentDCLCommand, 97 UInt32 packetHeader, 98 UInt8 * *pPacketBuffer, 99 UInt32 *pPacketSize, 100 bool *pGetNextPacket) 101{ 102 DCLTransferPacket* pDCLTransferPacket; 103 UInt8 * transferBuffer; 104 UInt8 * packetBuffer; 105 UInt32 transferSize, packetSize; 106 107 // Recast DCL command. 108 pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand; 109 110 // Get some parameters. 111 transferBuffer = (UInt8 *)pDCLTransferPacket->buffer; 112 transferSize = pDCLTransferPacket->size; 113 packetSize = *pPacketSize; 114 if (transferSize > packetSize) 115 transferSize = packetSize; 116 packetBuffer = *pPacketBuffer; 117 118 // Transfer the packet data. 119 if (transferSize > 0) 120 { 121 bcopy (packetBuffer, transferBuffer, transferSize); 122 packetSize -= transferSize; 123 packetBuffer += transferSize; 124 } 125 126 // Check if we need another packet. 127 *pGetNextPacket = true; 128 if (pDCLTransferPacket->pNextDCLCommand != NULL) 129 { 130 if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) == 131 kDCLReceivePacketOp) 132 { 133 *pGetNextPacket = false; 134 } 135 } 136 137 // Update parameters. 138 *ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand; 139 *pPacketBuffer = packetBuffer; 140 *pPacketSize = packetSize; 141} 142 143 144//////////////////////////////////////////////////////////////////////////////// 145// 146// FWDCLReceiveBuffer 147// 148// This routine runs a DCL receive buffer command. 149//zzz should we include packet header? 150//zzz should we clip off end of packet when buffer is filled? 151// 152 153static void DCLReceiveBuffer( DCLCommand** ppCurrentDCLCommand, UInt32 packetHeader, 154 UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket ) 155{ 156 DCLTransferBuffer* pDCLTransferBuffer; 157 UInt8 * buffer; 158 UInt32 bufferOffset, bufferSize; 159 UInt32 bufferSizeLeft; 160 UInt8 * packetBuffer; 161 UInt32 packetSize; 162 UInt32 transferSize; 163 164 // Recast current DCL command. 165 pDCLTransferBuffer = (DCLTransferBuffer*) *ppCurrentDCLCommand; 166 167 // Get some parameters. 168 buffer = (UInt8 *)pDCLTransferBuffer->buffer; 169 bufferOffset = pDCLTransferBuffer->bufferOffset; 170 bufferSize = pDCLTransferBuffer->size; 171 packetBuffer = *pPacketBuffer; 172 packetSize = *pPacketSize; 173 174 // Compute size of transfer. 175 bufferSizeLeft = bufferSize - bufferOffset; 176 if (bufferSizeLeft > packetSize) 177 transferSize = packetSize; 178 else 179 transferSize = bufferSizeLeft; 180 181 // Transfer the packet data. 182 if (transferSize > 0) 183 { 184 bcopy (packetBuffer, buffer + bufferOffset, transferSize); 185 186 packetBuffer += transferSize; 187 packetSize -= transferSize; 188 bufferOffset += transferSize; 189 } 190 191 // Check if we're done with this DCL or need another packet. 192 if (bufferOffset == bufferSize) 193 { 194 *ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand; 195 *pGetNextPacket = false; 196 } 197 else 198 { 199 *pGetNextPacket = true; 200 } 201 202 // Update parameters. 203 pDCLTransferBuffer->bufferOffset = bufferOffset; 204 *pPacketBuffer = packetBuffer; 205 *pPacketSize = packetSize; 206} 207 208//////////////////////////////////////////////////////////////////////////////// 209// 210// DCLSendPacket 211// 212// This routine runs a DCL send packet command. 213// 214 215static void DCLSendPacket( 216 DCLCommand** ppCurrentDCLCommand, 217 UInt8 * *pPacketBuffer, 218 UInt32 *pPacketSize, 219 bool *pGetNextPacket) 220{ 221 DCLTransferPacket* pDCLTransferPacket; 222 UInt8 * transferBuffer; 223 UInt8 * packetBuffer; 224 UInt32 transferSize, packetSize; 225 226 // Recast DCL command. 227 pDCLTransferPacket = (DCLTransferPacket*) *ppCurrentDCLCommand; 228 229 // Get some parameters. 230 transferBuffer = (UInt8 *)pDCLTransferPacket->buffer; 231 transferSize = pDCLTransferPacket->size; 232 packetSize = *pPacketSize; 233 packetBuffer = *pPacketBuffer + packetSize; 234 235 // Transfer the packet data. 236 bcopy (transferBuffer, packetBuffer, transferSize); 237 packetSize += transferSize; 238 239 // Check if we need another packet. 240 *pGetNextPacket = true; 241 if (pDCLTransferPacket->pNextDCLCommand != NULL) 242 { 243 if ((pDCLTransferPacket->pNextDCLCommand->opcode & ~kFWDCLOpFlagMask) == 244 kDCLSendPacketOp) 245 { 246 *pGetNextPacket = false; 247 } 248 } 249 250 // Update parameters. 251 *ppCurrentDCLCommand = pDCLTransferPacket->pNextDCLCommand; 252 *pPacketSize = packetSize; 253} 254 255 256//////////////////////////////////////////////////////////////////////////////// 257// 258// DCLSendBuffer 259// 260// This routine runs a DCL send buffer command. 261//zzz should we clip off end of packet when buffer is emptied? 262// 263 264static void DCLSendBuffer( DCLCommand** ppCurrentDCLCommand, UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket) 265{ 266 DCLTransferBuffer* pDCLTransferBuffer; 267 UInt8 * buffer; 268 UInt32 bufferOffset, bufferSize; 269 UInt32 bufferSizeLeft; 270 UInt8 * packetBuffer; 271 UInt32 packetSize; 272 UInt32 transferPacketSize; 273 UInt32 transferSize; 274 275 // Recast current DCL command. 276 pDCLTransferBuffer = (DCLTransferBuffer*) *ppCurrentDCLCommand; 277 278 // Get some parameters. 279 buffer = (UInt8 *)pDCLTransferBuffer->buffer; 280 bufferOffset = pDCLTransferBuffer->bufferOffset; 281 bufferSize = pDCLTransferBuffer->size; 282 packetSize = *pPacketSize; 283 packetBuffer = *pPacketBuffer + packetSize; 284 transferPacketSize = pDCLTransferBuffer->packetSize; 285 286 // Compute size of transfer. 287 bufferSizeLeft = bufferSize - bufferOffset; 288 if (bufferSizeLeft > transferPacketSize) 289 transferSize = transferPacketSize; 290 else 291 transferSize = bufferSizeLeft; 292 293 // Transfer the packet data. 294 if (transferSize > 0) 295 { 296 bcopy (buffer + bufferOffset, packetBuffer, transferSize); 297 298 packetSize += transferSize; 299 bufferOffset += transferSize; 300 } 301 302 // Check if we're done with this DCL or need another packet. 303 //zzz is this the best way to do this? 304 //zzz what if the next transfer command is a transfer packet command? 305 if (bufferOffset == bufferSize) 306 { 307 *ppCurrentDCLCommand = pDCLTransferBuffer->pNextDCLCommand; 308 *pGetNextPacket = false; 309 } 310 else 311 { 312 *pGetNextPacket = true; 313 } 314 315 // Update parameters. 316 pDCLTransferBuffer->bufferOffset = bufferOffset; 317 *pPacketSize = packetSize; 318} 319 320//////////////////////////////////////////////////////////////////////////////// 321// 322// FWRunTranslatedDCLEngine 323// 324// This routine runs the current DCL command using the given packet. It will 325// update the current DCL command, packet buffer pointer, packet size, and will 326// set get next packet to true if it needs another packet. 327//zzz maybe a vector table would be nice 328//zzz implement rest of DCL commands. 329// 330 331static void RunListeningDCLEngine( DCLCommand** ppCurrentDCLCommand, UInt32 packetHeader, UInt8** pPacketBuffer, 332 UInt32* pPacketSize, bool* pGetNextPacket) 333{ 334 DCLCommand* pCurrentDCLCommand; 335 DCLCallProc* pDCLCallProc; 336 DCLJump* pDCLJump; 337 338 // Run the current DCL command. 339 pCurrentDCLCommand = *ppCurrentDCLCommand; 340 switch (pCurrentDCLCommand->opcode & ~kFWDCLOpFlagMask) 341 { 342 case kDCLReceivePacketStartOp : 343 DCLReceivePacketStart ( 344 &pCurrentDCLCommand, 345 packetHeader, 346 pPacketBuffer, 347 pPacketSize, 348 pGetNextPacket); 349 break; 350 351 case kDCLReceivePacketOp : 352 DCLReceivePacket ( 353 &pCurrentDCLCommand, 354 packetHeader, 355 pPacketBuffer, 356 pPacketSize, 357 pGetNextPacket); 358 break; 359 360 case kDCLReceiveBufferOp : 361 DCLReceiveBuffer ( 362 &pCurrentDCLCommand, 363 packetHeader, 364 pPacketBuffer, 365 pPacketSize, 366 pGetNextPacket); 367 break; 368 369 case kDCLCallProcOp : 370 pDCLCallProc = (DCLCallProc*) pCurrentDCLCommand; 371 // Call the handler if there is one. 372 if (pDCLCallProc->proc != NULL) 373 (*(pDCLCallProc->proc)) ((DCLCommand*) pDCLCallProc); 374 375 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 376 *pGetNextPacket = false; 377 break; 378 379 case kDCLJumpOp : 380 pDCLJump = (DCLJump*) pCurrentDCLCommand; 381 pCurrentDCLCommand = (DCLCommand*) pDCLJump->pJumpDCLLabel; 382 *pGetNextPacket = false; 383 break; 384 385 default : 386 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 387 *pGetNextPacket = false; 388 break; 389 } 390 391 // Update current DCL command. 392 *ppCurrentDCLCommand = pCurrentDCLCommand; 393} 394 395//////////////////////////////////////////////////////////////////////////////// 396// 397// FWRunTranslatedTalkingDCLEngine 398// 399// This routine runs the current DCL command using the given packet. It will 400// update the current DCL command, packet buffer pointer, packet size, and will 401// set get next packet to true if it needs another packet. 402//zzz maybe a vector table would be nice 403// 404 405static void RunTalkingDCLEngine( UInt32* packetHeader, DCLCommand** ppCurrentDCLCommand, 406 UInt8** pPacketBuffer, UInt32* pPacketSize, bool* pGetNextPacket) 407{ 408 DCLCommand* pCurrentDCLCommand; 409 DCLCallProc* pDCLCallProc; 410 DCLJump* pDCLJump; 411 DCLSetTagSyncBits* pDCLSetTagSyncBits; 412 UInt32 host_header; 413 414 // Run the current DCL command. 415 pCurrentDCLCommand = *ppCurrentDCLCommand; 416 switch (pCurrentDCLCommand->opcode & ~kFWDCLOpFlagMask) 417 { 418 case kDCLSendPacketStartOp : 419 case kDCLSendPacketOp : 420 DCLSendPacket ( 421 &pCurrentDCLCommand, 422 pPacketBuffer, 423 pPacketSize, 424 pGetNextPacket); 425 break; 426 427 case kDCLSendBufferOp : 428 DCLSendBuffer ( 429 &pCurrentDCLCommand, 430 pPacketBuffer, 431 pPacketSize, 432 pGetNextPacket); 433 break; 434 435 case kDCLCallProcOp : 436 pDCLCallProc = (DCLCallProc*) pCurrentDCLCommand; 437 // Call the handler if there is one. 438 if (pDCLCallProc->proc != NULL) 439 (*(pDCLCallProc->proc)) ((DCLCommand*) pDCLCallProc); 440 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 441 *pGetNextPacket = false; 442 break; 443 444 case kDCLJumpOp : 445 pDCLJump = (DCLJump*) pCurrentDCLCommand; 446 pCurrentDCLCommand = (DCLCommand*) pDCLJump->pJumpDCLLabel; 447 *pGetNextPacket = false; 448 break; 449 450 case kDCLLabelOp : 451 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 452 *pGetNextPacket = false; 453 break; 454 455 case kDCLSetTagSyncBitsOp : 456 pDCLSetTagSyncBits = (DCLSetTagSyncBits*) pCurrentDCLCommand; 457 host_header = OSSwapBigToHostInt32( *packetHeader ); 458 host_header &= ~(kFWIsochTag | kFWIsochSy); 459 host_header |= (pDCLSetTagSyncBits->tagBits << kFWIsochTagPhase); 460 host_header |= (pDCLSetTagSyncBits->syncBits << kFWIsochSyPhase); 461 *packetHeader = OSSwapHostToBigInt32( host_header ); 462 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 463 *pGetNextPacket = false; 464 break; 465 466 default : 467 pCurrentDCLCommand = pCurrentDCLCommand->pNextDCLCommand; 468 *pGetNextPacket = false; 469 break; 470 } 471 472 // Update current DCL command. 473 *ppCurrentDCLCommand = pCurrentDCLCommand; 474} 475 476OSDefineMetaClass( IODCLTranslator, IODCLProgram ) 477OSDefineAbstractStructors(IODCLTranslator, IODCLProgram) 478 479bool IODCLTranslator::init(DCLCommand* toInterpret) 480{ 481 if(!IODCLProgram::init()) 482 return false; 483 484 // Allocate buffers etc. for programs 485 486 fToInterpret = toInterpret; 487 return true; 488} 489 490IOReturn 491IODCLTranslator::notify ( 492 IOFWDCLNotificationType notificationType, 493 DCLCommand ** dclCommandList, 494 UInt32 numDCLCommands ) 495{ 496 return kIOReturnSuccess; // Nothing to do, we're interpreting anyway 497} 498 499IOReturn IODCLTranslator::allocateHW(IOFWSpeed speed, UInt32 chan) 500{ 501 if(!fHWProgram) 502 return kIOReturnInternalError; 503 return fHWProgram->allocateHW(speed, chan); 504} 505IOReturn IODCLTranslator::releaseHW() 506{ 507 if(!fHWProgram) 508 return kIOReturnInternalError; 509 return fHWProgram->releaseHW(); 510} 511 512void IODCLTranslator::stop() 513{ 514 fHWProgram->stop(); 515} 516 517DCLCommand* 518IODCLTranslator::getTranslatorOpcodes() 519{ 520 return (DCLCommand*)&fStartLabel; 521} 522 523void 524IODCLTranslator::setHWProgram(IODCLProgram *program) 525{ 526 fHWProgram = program; 527} 528 529void 530IODCLTranslator::ListeningDCLPingPongProc(DCLCommand* pDCLCommand) 531{ 532 IODCLTranslator * me; 533 DCLCommand* pCurrentDCLCommand; 534 DCLTransferPacket* pDCLTransferPacket; 535 UInt8 * packetBuffer; 536 UInt32 packetHeader; 537 UInt32 packetSize; 538 UInt32 packetNum; 539 bool getNextPacket; 540 541 me = (IODCLTranslator *)((DCLCallProc*)pDCLCommand)->procData; 542 pCurrentDCLCommand = me->fCurrentDCLCommand; 543 pDCLTransferPacket = &me->fTransfers[me->fPingCount * kNumPacketsPerPingPong]; 544 // Run all packets through DCL program. 545 for (packetNum = 0; 546 ((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL)); 547 packetNum++) { 548 // Compute packet size. 549 packetBuffer = (UInt8 *)pDCLTransferPacket->buffer; 550 packetHeader = *((UInt32 *) packetBuffer); 551 packetBuffer += sizeof (UInt32); 552 packetSize = (OSSwapBigToHostInt32(packetHeader) & kFWIsochDataLength) >> kFWIsochDataLengthPhase; 553 554 // Run this packet through DCL program. 555 getNextPacket = false; 556 while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) { 557 RunListeningDCLEngine ( 558 &pCurrentDCLCommand, 559 packetHeader, 560 &packetBuffer, 561 &packetSize, 562 &getNextPacket); 563 } 564 565 // Update for next packet. 566 pDCLTransferPacket++; 567 } 568 569 // Update DCL translation data. 570 me->fCurrentDCLCommand = pCurrentDCLCommand; 571 me->fPingCount++; 572 if(me->fPingCount > kNumPingPongs) 573 me->fPingCount = 0; 574} 575 576void IODCLTranslator::TalkingDCLPingPongProc(DCLCommand* pDCLCommand) 577{ 578 IODCLTranslator * me; 579 DCLCommand* pCurrentDCLCommand; 580 DCLTransferPacket* pDCLTransferPacket; 581 UInt8 * packetBuffer; 582 UInt32 packetHeader; 583 UInt32 packetSize; 584 UInt32 packetNum; 585 bool getNextPacket; 586 587 me = (IODCLTranslator *)((DCLCallProc*)pDCLCommand)->procData; 588 pCurrentDCLCommand = me->fCurrentDCLCommand; 589 pDCLTransferPacket = &me->fTransfers[me->fPingCount * kNumPacketsPerPingPong]; 590 // Run all packets through DCL program. 591 for (packetNum = 0; 592 ((packetNum < kNumPacketsPerPingPong) && (pCurrentDCLCommand != NULL)); 593 packetNum++) { 594 // Compute packet size. 595 packetBuffer = (UInt8 *)pDCLTransferPacket->buffer; 596 packetSize = sizeof (UInt32); 597 598 // Run this packet through DCL program. 599 getNextPacket = false; 600 while ((!getNextPacket) && (pCurrentDCLCommand != NULL)) { 601 RunTalkingDCLEngine (&(me->fPacketHeader), 602 &pCurrentDCLCommand, 603 &packetBuffer, 604 &packetSize, 605 &getNextPacket); 606 } 607 // Update packet header. 608 packetSize -= 4;//zzz not the best way 609 packetHeader = 610 (packetSize << kFWIsochDataLengthPhase) | 611 (OSSwapBigToHostInt32(me->fPacketHeader) & ~(kFWIsochDataLength)); 612 *((UInt32 *) packetBuffer) = OSSwapHostToBigInt32(packetHeader); 613 614 // Update send packet DCL. 615 packetSize += 4;//zzz really, not the best way 616 // Change the transfer packet command. 617 pDCLTransferPacket->size = packetSize; 618 // Send notification to DCL compiler. 619 me->fHWProgram->notify(kFWDCLModifyNotification, 620 (DCLCommand**) pDCLTransferPacket, 1); 621 622 // Update for next packet. 623 pDCLTransferPacket++; 624 } 625 626 // Update DCL translation data. 627 me->fCurrentDCLCommand = pCurrentDCLCommand; 628 me->fPingCount++; 629 if(me->fPingCount > kNumPingPongs) 630 me->fPingCount = 0; 631} 632 633/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 634OSDefineMetaClassAndStructors(IODCLTranslateTalk, IODCLTranslator) 635 636IOReturn IODCLTranslateTalk::compile(IOFWSpeed speed, UInt32 chan) 637{ 638 int pingPongNum; 639 int packetNum; 640 DCLTransferPacket* pDCLTransferPacket = &fTransfers[0]; 641 DCLCallProc* pDCLPingPongProc = &fCalls[0]; 642 UInt8 *pingPongBuffer = fBuffer; 643 644 if(!fHWProgram) 645 return kIOReturnInternalError; 646 647 fPacketHeader = OSSwapHostToBigInt32( chan << kFWIsochChanNumPhase ); 648 649 // Create label for start of loop. 650 fStartLabel.pNextDCLCommand = (DCLCommand*)pDCLTransferPacket; 651 fStartLabel.opcode = kDCLLabelOp; 652 653 // Create kNumPingPongs ping pong buffer lists of kNumPacketsPerPingPong 654 // packets each. 655 for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) { 656 // Create transfer DCL for each packet. 657 for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) { 658 // Receive one packet up to kMaxIsochPacketSize bytes. 659 pDCLTransferPacket->pNextDCLCommand = (DCLCommand*)(pDCLTransferPacket+1); 660 pDCLTransferPacket->opcode = kDCLSendPacketWithHeaderStartOp | kFWDCLOpDynamicFlag; 661 pDCLTransferPacket->buffer = pingPongBuffer; 662 pDCLTransferPacket->size = kMaxIsochPacketSize; 663 pingPongBuffer += kMaxIsochPacketSize; 664 pDCLTransferPacket++; 665 } 666 // Correct next opcode for last transfer op. 667 (pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommand*)pDCLPingPongProc; 668 // Call the ping pong proc. 669 pDCLPingPongProc->pNextDCLCommand = (DCLCommand*) pDCLTransferPacket; 670 pDCLPingPongProc->opcode = kDCLCallProcOp; 671 pDCLPingPongProc->proc = TalkingDCLPingPongProc; 672 pDCLPingPongProc->procData = (UInt32) this; 673 pDCLPingPongProc++; 674 } 675 // Correct next opcode for last call op. 676 (pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommand*)&fJumpToStart; 677 678 // Loop to start of ping pong. 679 fJumpToStart.pNextDCLCommand = NULL; 680 fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag; 681 fJumpToStart.pJumpDCLLabel = &fStartLabel; 682 683 return fHWProgram->compile(speed, chan); 684} 685 686IOReturn IODCLTranslateTalk::start() 687{ 688 int i; 689 fPingCount = 0; 690 // Prime all buffers 691 for(i=0; i<kNumPingPongs; i++) { 692 TalkingDCLPingPongProc((DCLCommand*)&fCalls[i]); 693 } 694 return fHWProgram->start(); 695} 696 697/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 698OSDefineMetaClassAndStructors(IODCLTranslateListen, IODCLTranslator) 699 700IOReturn IODCLTranslateListen::compile(IOFWSpeed speed, UInt32 chan) 701{ 702 int pingPongNum; 703 int packetNum; 704 DCLTransferPacket* pDCLTransferPacket = &fTransfers[0]; 705 DCLCallProc* pDCLPingPongProc = &fCalls[0]; 706 UInt8 *pingPongBuffer = fBuffer; 707 708 if(!fHWProgram) 709 return kIOReturnInternalError; 710 711 fPacketHeader = OSSwapHostToBigInt32( chan << kFWIsochChanNumPhase ); 712 713 // Create label for start of loop. 714 fStartLabel.pNextDCLCommand = (DCLCommand*)pDCLTransferPacket; 715 fStartLabel.opcode = kDCLLabelOp; 716 717 // Create kNumPingPongs ping pong buffer lists of kNumPacketsPerPingPong 718 // packets each. 719 for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) { 720 // Create transfer DCL for each packet. 721 for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) { 722 // Receive one packet up to kMaxIsochPacketSize bytes. 723 pDCLTransferPacket->pNextDCLCommand = (DCLCommand*)(pDCLTransferPacket+1); 724 pDCLTransferPacket->opcode = kDCLReceivePacketStartOp | kFWDCLOpDynamicFlag; 725 pDCLTransferPacket->buffer = pingPongBuffer; 726 pDCLTransferPacket->size = kMaxIsochPacketSize; 727 pingPongBuffer += kMaxIsochPacketSize; 728 pDCLTransferPacket++; 729 } 730 // Correct next opcode for last transfer op. 731 (pDCLTransferPacket-1)->pNextDCLCommand = (DCLCommand*)pDCLPingPongProc; 732 // Call the ping pong proc. 733 pDCLPingPongProc->pNextDCLCommand = (DCLCommand*) pDCLTransferPacket; 734 pDCLPingPongProc->opcode = kDCLCallProcOp; 735 pDCLPingPongProc->proc = ListeningDCLPingPongProc; 736 pDCLPingPongProc->procData = (UInt32) this; 737 pDCLPingPongProc++; 738 } 739 // Correct next opcode for last call op. 740 (pDCLPingPongProc-1)->pNextDCLCommand = (DCLCommand*)&fJumpToStart; 741 742 // Loop to start of ping pong. 743 fJumpToStart.pNextDCLCommand = NULL; 744 fJumpToStart.opcode = kDCLJumpOp | kFWDCLOpDynamicFlag; 745 fJumpToStart.pJumpDCLLabel = &fStartLabel; 746 747 return fHWProgram->compile(speed, chan); 748} 749 750IOReturn IODCLTranslateListen::start() 751{ 752 fPingCount = 0; 753 return fHWProgram->start(); 754} 755