Annotation of XNU/iokit/Families/IOFireWire/IOFireWireUserClient.cpp, revision 1.1.1.1

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        */ &regionSize,
                    841:               /* flavor      */ VM_REGION_BASIC_INFO,
                    842:               /* info        */ (vm_region_info_t) &regionInfo,
                    843:               /* info size   */ &regionInfoSize,
                    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        */ &regionSize,
                    857:               /* flavor      */ VM_REGION_BASIC_INFO,
                    858:               /* info        */ (vm_region_info_t) &regionInfo,
                    859:               /* info size   */ &regionInfoSize,
                    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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.