Annotation of XNU/iokit/Families/IOFireWire/IOFireWireUserClient.cpp, revision 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.