|
|
1.1 ! root 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: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * HISTORY ! 26: * 8 June 1999 wgulland created. ! 27: * ! 28: */ ! 29: #include <IOKit/assert.h> ! 30: #include <IOKit/IOLib.h> ! 31: #include <IOKit/firewire/IOFireWireDevice.h> ! 32: #include <IOKit/firewire/IOFireWireController.h> ! 33: #include <IOKit/firewire/IOFWIsochChannel.h> ! 34: #include <IOKit/firewire/IOFWIsochPort.h> ! 35: #include <IOKit/firewire/IOFWIsoch.h> ! 36: ! 37: #include <IOKit/IOBufferMemoryDescriptor.h> ! 38: ! 39: #include "IOFireWireUserClient.h" ! 40: ! 41: #define super IOUserClient ! 42: #define DEBUGGING_LEVEL 0 ! 43: ! 44: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 45: ! 46: OSDefineMetaClassAndStructors(IOFireWireUserClient, IOUserClient) ! 47: ! 48: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 49: ! 50: class DVPort : public IOFWIsochPort ! 51: { ! 52: OSDeclareDefaultStructors(DVPort) ! 53: ! 54: public: ! 55: virtual bool init(IOFireWireDevice *device); ! 56: // Return maximum speed and channels supported ! 57: // (bit n set = chan n supported) ! 58: virtual IOReturn getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported); ! 59: ! 60: // Allocate hardware resources for port ! 61: virtual IOReturn allocatePort(IOFWSpeed speed, UInt32 chan); ! 62: virtual IOReturn releasePort(); // Free hardware resources ! 63: virtual IOReturn start(); // Start port processing packets ! 64: virtual IOReturn stop(); // Stop processing packets ! 65: }; ! 66: ! 67: OSDefineMetaClassAndStructors(DVPort, IOFWIsochPort) ! 68: ! 69: bool DVPort::init(IOFireWireDevice *device) ! 70: { ! 71: return IOFWIsochPort::init(); ! 72: } ! 73: ! 74: IOReturn DVPort::getSupported(IOFWSpeed &maxSpeed, UInt64 &chanSupported) ! 75: { ! 76: //kprintf("DVPort::getSupported\n"); ! 77: maxSpeed = kFWSpeed100MBit; ! 78: chanSupported = (UInt64)1; ! 79: return kIOReturnSuccess; ! 80: } ! 81: ! 82: IOReturn DVPort::allocatePort(IOFWSpeed speed, UInt32 chan) ! 83: { ! 84: //kprintf("DVPort::allocatePort(%d, %d)\n", speed, chan); ! 85: return kIOReturnSuccess; ! 86: } ! 87: ! 88: IOReturn DVPort::releasePort() ! 89: { ! 90: //kprintf("DVPort::releasePort()\n"); ! 91: return kIOReturnSuccess; ! 92: } ! 93: ! 94: IOReturn DVPort::start() ! 95: { ! 96: //kprintf("DVPort::start()\n"); ! 97: return kIOReturnSuccess; ! 98: } ! 99: ! 100: IOReturn DVPort::stop() ! 101: { ! 102: //kprintf("DVPort::stop()\n"); ! 103: return kIOReturnSuccess; ! 104: } ! 105: ! 106: ! 107: struct dclStuff { ! 108: int fState; ! 109: IOFWIsochChannel *chan; ! 110: IOFWIsochPort *port; ! 111: DVPort * dvPort; ! 112: OSAsyncReference asyncRef; ! 113: }; ! 114: ! 115: static dclStuff theProg; ! 116: /*static*/ int donePings; ! 117: ! 118: IOFireWireUserClient *IOFireWireUserClient::withTask(task_t owningTask) ! 119: { ! 120: IOFireWireUserClient *me; ! 121: ! 122: me = new IOFireWireUserClient; ! 123: if(me) { ! 124: if(!me->init()) { ! 125: me->release(); ! 126: return NULL; ! 127: } ! 128: me->fTask = owningTask; ! 129: } ! 130: return me; ! 131: } ! 132: ! 133: bool IOFireWireUserClient::start( IOService * provider ) ! 134: { ! 135: assert(OSDynamicCast(IOFireWireDevice, provider)); ! 136: if(!super::start(provider)) ! 137: return false; ! 138: fOwner = (IOFireWireDevice *)provider; ! 139: ! 140: // Got the owner, so initialize the call structures ! 141: fMethods[kFireWireRead].object = this; ! 142: fMethods[kFireWireRead].func = ! 143: (IOMethod)&IOFireWireUserClient::Read; ! 144: fMethods[kFireWireRead].count0 = 2; ! 145: fMethods[kFireWireRead].count1 = 0xffffffff; // variable ! 146: fMethods[kFireWireRead].flags = kIOUCScalarIStructO; ! 147: ! 148: fMethods[kFireWireWrite].object = this; ! 149: fMethods[kFireWireWrite].func = ! 150: (IOMethod)&IOFireWireUserClient::Write; ! 151: fMethods[kFireWireWrite].count0 = 2; ! 152: fMethods[kFireWireWrite].count1 = 0xffffffff; // variable ! 153: fMethods[kFireWireWrite].flags = kIOUCScalarIStructI; ! 154: ! 155: fMethods[kFireWireCompareSwap].object = this; ! 156: fMethods[kFireWireCompareSwap].func = ! 157: (IOMethod)&IOFireWireUserClient::CompareSwap; ! 158: fMethods[kFireWireCompareSwap].count0 = 4; ! 159: fMethods[kFireWireCompareSwap].count1 = 0; ! 160: fMethods[kFireWireCompareSwap].flags = kIOUCScalarIScalarO; ! 161: ! 162: fMethods[kFireWireBusReset].object = this; ! 163: fMethods[kFireWireBusReset].func = ! 164: (IOMethod)&IOFireWireUserClient::BusReset; ! 165: fMethods[kFireWireBusReset].count0 = 0; ! 166: fMethods[kFireWireBusReset].count1 = 0; ! 167: fMethods[kFireWireBusReset].flags = kIOUCScalarIScalarO; ! 168: ! 169: fMethods[kFireWireTest].object = this; ! 170: fMethods[kFireWireTest].func = ! 171: (IOMethod)&IOFireWireUserClient::Test; ! 172: fMethods[kFireWireTest].count0 = 0; ! 173: fMethods[kFireWireTest].count1 = 0; ! 174: fMethods[kFireWireTest].flags = kIOUCScalarIScalarO; ! 175: ! 176: fMethods[kFireWireCycleTime].object = fOwner->fControl; ! 177: fMethods[kFireWireCycleTime].func = ! 178: (IOMethod)&IOFireWireController::getCycleTime; ! 179: fMethods[kFireWireCycleTime].count0 = 0; ! 180: fMethods[kFireWireCycleTime].count1 = 1; ! 181: fMethods[kFireWireCycleTime].flags = kIOUCScalarIScalarO; ! 182: ! 183: fMethods[kFireWireCompileDCL].object = this; ! 184: fMethods[kFireWireCompileDCL].func = ! 185: (IOMethod)&CompileDCL; ! 186: fMethods[kFireWireCompileDCL].count0 = 5; ! 187: fMethods[kFireWireCompileDCL].count1 = 1; ! 188: fMethods[kFireWireCompileDCL].flags = kIOUCScalarIScalarO; ! 189: ! 190: fMethods[kFireWireStopDCL].object = this; ! 191: fMethods[kFireWireStopDCL].func = ! 192: (IOMethod)&StopDCL; ! 193: fMethods[kFireWireStopDCL].count0 = 1; ! 194: fMethods[kFireWireStopDCL].count1 = 0; ! 195: fMethods[kFireWireStopDCL].flags = kIOUCScalarIScalarO; ! 196: ! 197: fAsyncMethods[kFireWireRunDCL].object = this; ! 198: fAsyncMethods[kFireWireRunDCL].func = ! 199: (IOAsyncMethod)&RunDCL; ! 200: fAsyncMethods[kFireWireRunDCL].count0 = 1; ! 201: fAsyncMethods[kFireWireRunDCL].count1 = 0; ! 202: fAsyncMethods[kFireWireRunDCL].flags = kIOUCScalarIScalarO; ! 203: ! 204: ! 205: ! 206: return true; ! 207: } ! 208: ! 209: IOReturn IOFireWireUserClient::clientClose( void ) ! 210: { ! 211: if(theProg.fState != 0) ! 212: IOLog("Client close, DCL state = %d\n", theProg.fState); ! 213: ! 214: if(theProg.fState == 2) { ! 215: StopDCL((UInt32)&theProg); ! 216: } ! 217: if(theProg.fState == 1) { ! 218: StopDCL((UInt32)&theProg); ! 219: } ! 220: detach( fOwner); ! 221: ! 222: return kIOReturnSuccess; ! 223: } ! 224: ! 225: IOReturn IOFireWireUserClient::clientDied( void ) ! 226: { ! 227: return( clientClose()); ! 228: } ! 229: ! 230: IOExternalMethod * ! 231: IOFireWireUserClient::getExternalMethodForIndex( UInt32 index ) ! 232: { ! 233: if(index >= kNumFireWireMethods) ! 234: return NULL; ! 235: else ! 236: return &fMethods[index]; ! 237: } ! 238: ! 239: IOExternalAsyncMethod * ! 240: IOFireWireUserClient::getExternalAsyncMethodForIndex( UInt32 index ) ! 241: { ! 242: if(index >= kNumFireWireMethods || fAsyncMethods[index].object == NULL) ! 243: return NULL; ! 244: else ! 245: return &fAsyncMethods[index]; ! 246: } ! 247: ! 248: ! 249: ! 250: IOReturn ! 251: IOFireWireUserClient::Read(UInt32 addrHi, UInt32 addrLo, void *buf, UInt32 *size) ! 252: { ! 253: IOReturn res; ! 254: IOMemoryDescriptor * mem = NULL; ! 255: IOFWCommand * cmd = NULL; ! 256: UInt32 req = *size; ! 257: ! 258: do { ! 259: *size = 0; ! 260: if(req == 4 || req == 8) { ! 261: cmd = fOwner->createReadQuadCommand(FWAddress(addrHi, addrLo), (UInt32 *)buf, req/4); ! 262: if(!cmd) { ! 263: res = kIOReturnNoMemory; ! 264: break; ! 265: } ! 266: } ! 267: else { ! 268: mem = IOMemoryDescriptor::withAddress(buf, req, kIODirectionIn); ! 269: if(!mem) { ! 270: res = kIOReturnNoMemory; ! 271: break; ! 272: } ! 273: ! 274: cmd = fOwner->createReadCommand(FWAddress(addrHi, addrLo), mem); ! 275: if(!cmd) { ! 276: res = kIOReturnNoMemory; ! 277: break; ! 278: } ! 279: } ! 280: res = cmd->submit(); ! 281: // We block here until the command finishes ! 282: if(kIOReturnSuccess == res) ! 283: res = cmd->fStatus; ! 284: if(kIOReturnSuccess == res) { ! 285: if(mem) ! 286: *size = cmd->fBytesTransferred; ! 287: else ! 288: *size = req; ! 289: } ! 290: ! 291: } while(false); ! 292: ! 293: if(cmd) ! 294: cmd->release(); ! 295: if(mem) ! 296: mem->release(); ! 297: ! 298: return res; ! 299: } ! 300: ! 301: IOReturn ! 302: IOFireWireUserClient::Write(UInt32 addrHi, UInt32 addrLo, void *buf, UInt32 size) ! 303: { ! 304: IOReturn res; ! 305: IOMemoryDescriptor * mem = NULL; ! 306: IOFWCommand * cmd = NULL; ! 307: ! 308: do { ! 309: if(size == 4 || size == 8) { ! 310: cmd = fOwner->createWriteQuadCommand(FWAddress(addrHi, addrLo), (UInt32 *)buf, size/4); ! 311: if(!cmd) { ! 312: res = kIOReturnNoMemory; ! 313: break; ! 314: } ! 315: } ! 316: else { ! 317: mem = IOMemoryDescriptor::withAddress(buf, size, kIODirectionOut); ! 318: if(!mem) { ! 319: res = kIOReturnNoMemory; ! 320: break; ! 321: } ! 322: ! 323: cmd = fOwner->createWriteCommand(FWAddress(addrHi, addrLo), mem); ! 324: if(!cmd) { ! 325: res = kIOReturnNoMemory; ! 326: break; ! 327: } ! 328: } ! 329: res = cmd->submit(); ! 330: // We block here until the command finishes ! 331: if(kIOReturnSuccess == res) ! 332: res = cmd->fStatus; ! 333: ! 334: } while(false); ! 335: ! 336: if(cmd) ! 337: cmd->release(); ! 338: if(mem) ! 339: mem->release(); ! 340: ! 341: return res; ! 342: } ! 343: ! 344: IOReturn ! 345: IOFireWireUserClient::CompareSwap(UInt32 addrHi, UInt32 addrLo, UInt32 cmpVal, UInt32 newVal) ! 346: { ! 347: IOReturn res; ! 348: IOFWCompareAndSwapCommand * cmd = NULL; ! 349: ! 350: cmd = fOwner->createCompareAndSwapCommand(FWAddress(addrHi, addrLo), &cmpVal, &newVal, 1); ! 351: if(!cmd) { ! 352: return kIOReturnNoMemory; ! 353: } ! 354: ! 355: res = cmd->submit(); ! 356: // We block here until the command finishes ! 357: if(kIOReturnSuccess == res) { ! 358: UInt32 oldVal; ! 359: res = cmd->fStatus; ! 360: if(kIOReturnSuccess == res && !cmd->locked(&oldVal)) ! 361: res = kIOReturnCannotLock; ! 362: } ! 363: ! 364: if(cmd) ! 365: cmd->release(); ! 366: ! 367: return res; ! 368: } ! 369: ! 370: ! 371: IOReturn ! 372: IOFireWireUserClient::clientMemoryForType( UInt32 type, ! 373: UInt32 * flags, IOMemoryDescriptor ** memory ) ! 374: { ! 375: // This is a wonderful hack. ! 376: // Create some memory, map it out to the user and off we go!! ! 377: // We abuse the type as the low part of a fire wire address. ! 378: // The high part is 0xf1d0. Woof Woof!! ! 379: // The size is one page. ! 380: IOBufferMemoryDescriptor * desc; ! 381: IOFWAddressSpace * space; ! 382: IOFWAllocAddressCommand * cmd = NULL; ! 383: void * buf; ! 384: IOReturn res; ! 385: ! 386: desc = IOBufferMemoryDescriptor::withCapacity(PAGE_SIZE, ! 387: kIODirectionOutIn, true); ! 388: if(!desc) ! 389: return kIOReturnNoMemory; ! 390: desc->setLength(PAGE_SIZE); ! 391: buf = desc->getBytesNoCopy(); ! 392: desc->retain(); ! 393: *memory = desc; ! 394: ! 395: space = IOFWPseudoAddressSpace::simpleRW(FWAddress(0xf1d0, type), PAGE_SIZE, buf); ! 396: if(!space) ! 397: return kIOReturnNoMemory; ! 398: cmd = fOwner->createAllocAddrCommand(space); ! 399: if(!cmd) ! 400: return kIOReturnNoMemory; ! 401: res = cmd->submit(); ! 402: // We block here until the command finishes ! 403: if(kIOReturnSuccess == res) ! 404: res = cmd->fStatus; ! 405: if(cmd) ! 406: cmd->release(); ! 407: ! 408: if(kIOReturnSuccess == res) { ! 409: space = fOwner->createPhysicalAddressSpace(desc); ! 410: if(space) { ! 411: cmd = fOwner->createAllocAddrCommand(space); ! 412: if(!cmd) ! 413: return kIOReturnNoMemory; ! 414: res = cmd->submit(); ! 415: // We block here until the command finishes ! 416: if(kIOReturnSuccess == res) ! 417: res = cmd->fStatus; ! 418: if(cmd) ! 419: cmd->release(); ! 420: } ! 421: } ! 422: return res; ! 423: } ! 424: ! 425: IOReturn IOFireWireUserClient::BusReset() ! 426: { ! 427: IOFWUpdateROM *reset; ! 428: IOReturn res = kIOReturnNoMemory; ! 429: kprintf("Bus Reset!!!\n"); ! 430: reset = new IOFWUpdateROM; ! 431: if(reset) { ! 432: if(reset->initWithController(fOwner->fControl)) { ! 433: res = reset->submit(); ! 434: // We block here until the command finishes ! 435: if(kIOReturnSuccess == res) ! 436: res = reset->fStatus; ! 437: } ! 438: } ! 439: if(reset) ! 440: reset->release(); ! 441: ! 442: return kIOReturnSuccess; ! 443: } ! 444: ! 445: static int state; ! 446: IOReturn IOFireWireUserClient::message( UInt32 type, IOService * provider, void * arg ) ! 447: { ! 448: kprintf("IOFireWireUserClient(0x%x)::message(0x%x, 0x%x, 0x%x)\n", ! 449: this, type, provider, arg); ! 450: kprintf("state = 0x%x\n", state); ! 451: return kIOReturnSuccess; ! 452: } ! 453: ! 454: #if 1 ! 455: static void PingPongProc(DCLCommandPtr pDCLCommand) ! 456: { ! 457: if(donePings++ < 2) ! 458: IOLog("Ping! (or Pong!) %0x\n", pDCLCommand); ! 459: } ! 460: ! 461: #if 0 ! 462: IOReturn IOFireWireUserClient::Test() ! 463: { ! 464: IOFWIsochChannel *chan; ! 465: IOFWIsochPort *port; ! 466: DVPort * dvPort; ! 467: DCLCommandStruct *opcodes; ! 468: ! 469: enum ! 470: { ! 471: kNumPingPongs = 2, ! 472: kNumPacketsPerPingPong = 10, ! 473: kNumDCLsPerPingPongPacket = 1, ! 474: kRecordNumDCLs = ! 475: kNumPingPongs * kNumPacketsPerPingPong * kNumDCLsPerPingPongPacket, ! 476: kMaxDCLSize = 32, ! 477: kRecordDCLProgramSize = kMaxDCLSize * kRecordNumDCLs, ! 478: kReceiveDVPacketSize = 492, ! 479: kPingPongBufferSize = ! 480: kNumPingPongs * kNumPacketsPerPingPong * kReceiveDVPacketSize ! 481: }; ! 482: ! 483: const UInt32 blockSize = kRecordDCLProgramSize; ! 484: ! 485: UInt8 * pingPongBuffer = NULL; ! 486: UInt8 * pingPongPtr; ! 487: UInt8 * pDCLCommand; ! 488: DCLLabelPtr pStartDCLLabel; ! 489: DCLTransferPacketPtr pDCLTransferPacket; ! 490: DCLCallProcPtr pDCLPingPongProc; ! 491: DCLJumpPtr pDCLPingPongLoop; ! 492: int pingPongNum, packetNum; ! 493: ! 494: kprintf("IOFireWireUserClient::Test()!!\n"); ! 495: ! 496: opcodes = (DCLCommandStruct *)IOMalloc(blockSize); ! 497: ! 498: // Create ping pong buffer. ! 499: //zzz should allocate in initialization routine. ! 500: pingPongBuffer = (UInt8 *)IOMalloc(kPingPongBufferSize); ! 501: ! 502: // Get pointer to start of DCL commands and update list. ! 503: pDCLCommand = (UInt8 *)opcodes; ! 504: ! 505: // Create label for start of loop. ! 506: pStartDCLLabel = (DCLLabelPtr) pDCLCommand; ! 507: pDCLCommand += sizeof (DCLLabel); ! 508: pStartDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 509: pStartDCLLabel->opcode = kDCLLabelOp; ! 510: pingPongPtr = pingPongBuffer; ! 511: ! 512: // Create 2 ping pong buffer lists of 10 packets each. ! 513: for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) ! 514: { ! 515: ! 516: // Create transfer DCL for each packet. ! 517: for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) ! 518: { ! 519: // Receive one packet up to kReceiveDVPacketSize bytes. ! 520: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand; ! 521: pDCLCommand += sizeof (DCLTransferPacket); ! 522: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 523: pDCLTransferPacket->opcode = kDCLReceivePacketStartOp; ! 524: pDCLTransferPacket->buffer = pingPongPtr; ! 525: pDCLTransferPacket->size = kReceiveDVPacketSize; ! 526: ! 527: pingPongPtr += kReceiveDVPacketSize; ! 528: } ! 529: ! 530: // Call the ping pong proc. ! 531: pDCLPingPongProc = (DCLCallProcPtr) pDCLCommand; ! 532: pDCLCommand += sizeof (DCLCallProc); ! 533: pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 534: pDCLPingPongProc->opcode = kDCLCallProcOp; ! 535: pDCLPingPongProc->proc = PingPongProc; ! 536: pDCLPingPongProc->procData = (UInt32) this; ! 537: } ! 538: ! 539: // Loop to start of ping pong. ! 540: pDCLPingPongLoop = (DCLJumpPtr) pDCLCommand; ! 541: pDCLPingPongLoop->pNextDCLCommand = NULL; ! 542: pDCLPingPongLoop->opcode = kDCLJumpOp; ! 543: pDCLPingPongLoop->pJumpDCLLabel = pStartDCLLabel; ! 544: ! 545: donePings = 0; ! 546: ! 547: chan = fOwner->fControl->createIsochChannel(false, 488*8*8000, kFWSpeed100MBit); ! 548: port = fOwner->fControl->createLocalIsochPort(false, opcodes); ! 549: dvPort = new DVPort; ! 550: dvPort->init(fOwner); ! 551: chan->addListener(port); ! 552: chan->setTalker(dvPort); ! 553: chan->allocateChannel(); ! 554: chan->start(); ! 555: ! 556: IOSleep(10000); ! 557: ! 558: chan->stop(); ! 559: chan->releaseChannel(); ! 560: dvPort->release(); ! 561: port->release(); ! 562: chan->release(); ! 563: ! 564: /* ! 565: for (packetNum = 0; packetNum < kNumPacketsPerPingPong*kNumPingPongs; packetNum++) { ! 566: kprintf("Pack Header: 0x%x 0x%x 0x%x 0x%x\n", ! 567: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize), ! 568: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+4), ! 569: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+8), ! 570: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+12) ! 571: ); ! 572: } ! 573: */ ! 574: ! 575: IOFree(pingPongBuffer, kPingPongBufferSize); ! 576: IOFree(opcodes, blockSize); ! 577: ! 578: return kIOReturnSuccess; ! 579: } ! 580: ! 581: #else ! 582: ! 583: IOReturn IOFireWireUserClient::Test() ! 584: { ! 585: IOFWIsochChannel *chan; ! 586: IOFWIsochPort *port; ! 587: DVPort * dvPort; ! 588: DCLCommandStruct *opcodes; ! 589: ! 590: enum ! 591: { ! 592: kNumPingPongs = 2, ! 593: kNumPacketsPerPingPong = 10, ! 594: kNumDCLsPerPingPongPacket = 2, ! 595: kPlayNumDCLs = ! 596: kNumPingPongs * kNumPacketsPerPingPong * kNumDCLsPerPingPongPacket, ! 597: kMaxDCLSize = 32, ! 598: kPlayDCLProgramSize = kMaxDCLSize * kPlayNumDCLs, ! 599: kSendDVPacketSize = 492, ! 600: kDVPacketHdrSize = 8, ! 601: kDVPacketDataSize = 480, ! 602: kPingPongBufferSize = ! 603: kNumPingPongs * kNumPacketsPerPingPong * kSendDVPacketSize ! 604: }; ! 605: ! 606: const UInt32 blockSize = kPlayDCLProgramSize; ! 607: ! 608: UInt8 * pingPongBuffer = NULL; ! 609: UInt8 * pingPongPtr; ! 610: UInt8 * pDCLCommand; ! 611: DCLLabelPtr pStartDCLLabel; ! 612: DCLTransferPacketPtr pDCLTransferPacket; ! 613: DCLCallProcPtr pDCLPingPongProc; ! 614: DCLJumpPtr pDCLPingPongLoop; ! 615: int pingPongNum, packetNum; ! 616: ! 617: kprintf("IOFireWireUserClient::Test()!!\n"); ! 618: ! 619: opcodes = (DCLCommandStruct *)IOMalloc(blockSize); ! 620: ! 621: // Create ping pong buffer. ! 622: //zzz should allocate in initialization routine. ! 623: pingPongBuffer = (UInt8 *)IOMalloc(kPingPongBufferSize); ! 624: ! 625: // Get pointer to start of DCL commands and update list. ! 626: pDCLCommand = (UInt8 *)opcodes; ! 627: ! 628: // Create label for start of loop. ! 629: pStartDCLLabel = (DCLLabelPtr) pDCLCommand; ! 630: pDCLCommand += sizeof (DCLLabel); ! 631: pStartDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 632: pStartDCLLabel->opcode = kDCLLabelOp; ! 633: pingPongPtr = pingPongBuffer; ! 634: ! 635: // Create 2 ping pong buffer lists of 10 packets each. ! 636: for (pingPongNum = 0; pingPongNum < kNumPingPongs; pingPongNum++) ! 637: { ! 638: ! 639: // Create transfer DCL for each packet. ! 640: for (packetNum = 0; packetNum < kNumPacketsPerPingPong; packetNum++) ! 641: { ! 642: // Send a packet with a header (CIP) and Mystery D/V Data ! 643: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand; ! 644: pDCLCommand += sizeof (DCLTransferPacket); ! 645: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 646: pDCLTransferPacket->opcode = kDCLSendPacketStartOp; ! 647: pDCLTransferPacket->buffer = pingPongPtr; ! 648: pDCLTransferPacket->size = kDVPacketHdrSize; ! 649: pingPongPtr += kDVPacketHdrSize; ! 650: ! 651: pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand; ! 652: pDCLCommand += sizeof (DCLTransferPacket); ! 653: pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 654: pDCLTransferPacket->opcode = kDCLSendPacketOp; ! 655: pDCLTransferPacket->buffer = pingPongPtr; ! 656: pDCLTransferPacket->size = kDVPacketDataSize; ! 657: pingPongPtr += kDVPacketDataSize; ! 658: ! 659: } ! 660: ! 661: // Call the ping pong proc. ! 662: pDCLPingPongProc = (DCLCallProcPtr) pDCLCommand; ! 663: pDCLCommand += sizeof (DCLCallProc); ! 664: pDCLPingPongProc->pNextDCLCommand = (DCLCommandPtr) pDCLCommand; ! 665: pDCLPingPongProc->opcode = kDCLCallProcOp; ! 666: pDCLPingPongProc->proc = PingPongProc; ! 667: pDCLPingPongProc->procData = (UInt32) this; ! 668: } ! 669: ! 670: // Loop to start of ping pong. ! 671: pDCLPingPongLoop = (DCLJumpPtr) pDCLCommand; ! 672: pDCLPingPongLoop->pNextDCLCommand = NULL; ! 673: pDCLPingPongLoop->opcode = kDCLJumpOp; ! 674: pDCLPingPongLoop->pJumpDCLLabel = pStartDCLLabel; ! 675: ! 676: donePings = 0; ! 677: ! 678: chan = fOwner->fControl->createIsochChannel(true, 488*8*8000, kFWSpeed100MBit); ! 679: port = fOwner->fControl->createLocalIsochPort(true, opcodes); ! 680: dvPort = new DVPort; ! 681: dvPort->init(fOwner); ! 682: chan->addListener(dvPort); ! 683: chan->setTalker(port); ! 684: chan->allocateChannel(); ! 685: chan->start(); ! 686: ! 687: IOSleep(10); ! 688: ! 689: chan->stop(); ! 690: chan->releaseChannel(); ! 691: dvPort->release(); ! 692: port->release(); ! 693: chan->release(); ! 694: ! 695: /* ! 696: for (packetNum = 0; packetNum < kNumPacketsPerPingPong*kNumPingPongs; packetNum++) { ! 697: kprintf("Pack Header: 0x%x 0x%x 0x%x 0x%x\n", ! 698: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize), ! 699: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+4), ! 700: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+8), ! 701: *(UInt32 *)(pingPongBuffer+packetNum*kReceiveDVPacketSize+12) ! 702: ); ! 703: } ! 704: */ ! 705: ! 706: IOFree(pingPongBuffer, kPingPongBufferSize); ! 707: IOFree(opcodes, blockSize); ! 708: ! 709: return kIOReturnSuccess; ! 710: } ! 711: #endif ! 712: ! 713: #endif ! 714: #if 0 ! 715: ! 716: static IOFWCommand *cmd1 = 0; ! 717: static IOFWCommand *cmd2 = 0; ! 718: static IOFWCommand *cmd3 = 0; ! 719: ! 720: static void Complete(void *refcon, IOReturn status, IOFireWireDevice *device, IOFWCommand *fwCmd) ! 721: { ! 722: // if(status != kIOReturnSuccess) ! 723: // kprintf("%x Completed with error %x\n", refcon, status); ! 724: if(fwCmd == cmd1) { ! 725: state |= 2; ! 726: cmd1->release(); ! 727: cmd1 = 0; ! 728: cmd2->execute(); ! 729: } ! 730: else if(fwCmd == cmd2) { ! 731: cmd2->release(); ! 732: cmd2 = 0; ! 733: state |= 4; ! 734: } ! 735: else ! 736: kprintf("Complete(): Bad refcon: 0x%x\n", refcon); ! 737: } ! 738: ! 739: IOReturn IOFireWireUserClient::Test() ! 740: { ! 741: FWAddress testAddr(0xf1d0, 0); ! 742: UInt32 quad = 0x12345677; ! 743: UInt32 quad1 = 0x12345678; ! 744: UInt32 quad2 = 0x12345679; ! 745: IOReturn status; ! 746: ! 747: if(cmd1 != 0 || cmd2 != 0) ! 748: return state; // Still busy. ! 749: ! 750: cmd1 = fOwner->createWriteQuadCommand(testAddr, &quad, 1, Complete, (void *)quad); ! 751: cmd2 = fOwner->createWriteQuadCommand(testAddr, &quad1, 1, Complete, (void *)(quad+1)); ! 752: cmd3 = fOwner->createWriteQuadCommand(testAddr, &quad2, 1); ! 753: state = 0; ! 754: cmd1->submit(); ! 755: state |= 1; ! 756: //cmd2->submit(); ! 757: cmd3->submit(); ! 758: state |= 8; ! 759: status = cmd3->fStatus; ! 760: ! 761: cmd3->release(); ! 762: return status; ! 763: } ! 764: #endif ! 765: ! 766: #if 0 ! 767: IOReturn IOFireWireUserClient::Test() ! 768: { ! 769: IOBufferMemoryDescriptor * desc; ! 770: IOFWAddressSpace * space; ! 771: IOFWBusCommand * cmd = NULL; ! 772: ! 773: desc = IOBufferMemoryDescriptor::withCapacity(PAGE_SIZE, ! 774: kIODirectionOutIn, true); ! 775: if(!desc) ! 776: return kIOReturnNoMemory; ! 777: desc->setLength(PAGE_SIZE); ! 778: space = fOwner->createPhysicalAddressSpace(desc); ! 779: if(!space) ! 780: return kIOReturnNoMemory; ! 781: cmd = fOwner->createAllocAddrCommand(space); ! 782: if(!cmd) ! 783: return kIOReturnNoMemory; ! 784: cmd->submit(); ! 785: cmd->release(); ! 786: cmd = fOwner->createDeallocAddrCommand(space); ! 787: if(!cmd) ! 788: return kIOReturnNoMemory; ! 789: cmd->submit(); ! 790: cmd->release(); ! 791: space->release(); ! 792: desc->release(); ! 793: ! 794: return kIOReturnSuccess; ! 795: } ! 796: #endif ! 797: ! 798: // from IOKitLibPrivate.h! ! 799: enum { ! 800: kIOAsyncReservedIndex = 0, ! 801: ! 802: kIOAsyncCalloutFuncIndex = 1, ! 803: kIOAsyncCalloutRefconIndex, ! 804: kIOAsyncCalloutCount, ! 805: }; ! 806: ! 807: void IOFireWireUserClient::kernPongProc(void *refcon, void * userProc, void * dclCommand) ! 808: { ! 809: IOReturn kr; ! 810: IOFireWireUserClient * me; ! 811: #if 0 ! 812: if(donePings++ < 2) ! 813: IOLog("Ping! (or Pong!) %0x ->0x%x\n", dclCommand, ! 814: userProc); ! 815: #endif ! 816: me = (IOFireWireUserClient *)refcon; ! 817: theProg.asyncRef[kIOAsyncCalloutFuncIndex] = (natural_t) userProc; ! 818: theProg.asyncRef[kIOAsyncCalloutRefconIndex] = (natural_t) dclCommand; ! 819: kr = me->sendAsyncResult(theProg.asyncRef, kIOReturnSuccess, NULL, 0); ! 820: } ! 821: ! 822: ! 823: IOReturn IOFireWireUserClient::CompileDCL(UInt32 dclStart, UInt32 dclBase, ! 824: UInt32 dclSize, UInt32 dataBase, UInt32 dataSize, UInt32 *program) ! 825: { ! 826: IOReturn res; ! 827: // IOLog("DCL start:0x%x base:0x%x size:%d, Data base:0x%x, size:%d\n", ! 828: // dclStart, dclBase, dclSize, dataBase, dataSize); ! 829: ! 830: // Check that DCL program and data buffers are in single regions ! 831: vm_region_basic_info_data_t regionInfo; ! 832: mach_msg_type_number_t regionInfoSize = sizeof(regionInfo); ! 833: vm_size_t regionSize; ! 834: vm_offset_t checkBase = trunc_page(dclBase); ! 835: vm_size_t checkSize = round_page(dclSize); ! 836: ! 837: res = vm_region( ! 838: /* map */ get_task_map(fTask), ! 839: /* address */ &checkBase, ! 840: /* size */ ®ionSize, ! 841: /* flavor */ VM_REGION_BASIC_INFO, ! 842: /* info */ (vm_region_info_t) ®ionInfo, ! 843: /* info size */ ®ionInfoSize, ! 844: /* object name */ 0 ); ! 845: if(res != kIOReturnSuccess) ! 846: return res; ! 847: ! 848: if(checkBase + regionSize < dclBase + dclSize) ! 849: return kIOReturnVMError; ! 850: ! 851: checkBase = trunc_page(dataBase); ! 852: checkSize = round_page(dataSize); ! 853: res = vm_region( ! 854: /* map */ get_task_map(fTask), ! 855: /* address */ &checkBase, ! 856: /* size */ ®ionSize, ! 857: /* flavor */ VM_REGION_BASIC_INFO, ! 858: /* info */ (vm_region_info_t) ®ionInfo, ! 859: /* info size */ ®ionInfoSize, ! 860: /* object name */ 0 ); ! 861: if(res != kIOReturnSuccess) ! 862: return res; ! 863: ! 864: if(checkBase + regionSize < dataBase + dataSize) ! 865: return kIOReturnVMError; ! 866: ! 867: *program = &theProg; ! 868: IOFireWireBus::DCLTaskInfo info; ! 869: info.fTask = fTask; ! 870: info.fDCLBaseAddr = dclBase; ! 871: info.fDCLSize = dclSize; ! 872: info.fDataBaseAddr = dataBase; ! 873: info.fDataSize = dataSize; ! 874: info.fCallUser = kernPongProc; ! 875: info.fCallRefCon = this; ! 876: theProg.port = fOwner->fControl->createLocalIsochPort(false, (DCLCommand *)dclStart, &info); ! 877: ! 878: theProg.chan = fOwner->fControl->createIsochChannel(false, 488*8*8000, kFWSpeed100MBit); ! 879: theProg.dvPort = new DVPort; ! 880: theProg.dvPort->init(fOwner); ! 881: theProg.chan->addListener(theProg.port); ! 882: theProg.chan->setTalker(theProg.dvPort); ! 883: theProg.fState = 1; ! 884: ! 885: return kIOReturnSuccess; ! 886: } ! 887: ! 888: IOReturn IOFireWireUserClient::RunDCL(OSAsyncReference asyncRef, UInt32 program) ! 889: { ! 890: donePings = 0; ! 891: if(theProg.fState == 1) { ! 892: bcopy(asyncRef, theProg.asyncRef, sizeof(OSAsyncReference)); ! 893: theProg.chan->allocateChannel(); ! 894: theProg.chan->start(); ! 895: theProg.fState = 2; ! 896: return kIOReturnSuccess; ! 897: } ! 898: else { ! 899: IOLog("RunDCL, state is %d not 1!\n", theProg.fState); ! 900: return kIOReturnNotReady; ! 901: } ! 902: ! 903: } ! 904: ! 905: IOReturn IOFireWireUserClient::StopDCL(UInt32 program) ! 906: { ! 907: if(theProg.fState == 2) { ! 908: theProg.chan->stop(); ! 909: theProg.chan->releaseChannel(); ! 910: } ! 911: theProg.chan->release(); ! 912: theProg.dvPort->release(); ! 913: theProg.port->release(); ! 914: ! 915: theProg.fState = 0; ! 916: return kIOReturnSuccess; ! 917: } ! 918: ! 919:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.