/* * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include // Turn on logging of when events happen, and log dump when something takes too long //#define TIMING 1 #define kDVMaxDevicesActive 64 // max devices on firewire bus #define kDVMaxStreamsActive 64 // max isoc channels on fw bus #define kLogSize 20 typedef struct _Log { UInt32 tag; CFAbsoluteTime start; CFAbsoluteTime end; } Log; // pthread stuff typedef struct _syncStruct { pthread_mutex_t fMutex; // lock this before updating globals pthread_cond_t fSyncCond; // To synchronize threads. } ThreadSyncer; typedef struct _DVThread DVThread; struct DVGlobalOutStruct; typedef struct DVGlobalOutStruct DVGlobalOut, *DVGlobalOutPtr; struct DVGlobalInStruct; typedef struct DVGlobalInStruct DVGlobalIn, *DVGlobalInPtr; // device structure typedef struct _DVDevice { DVThread *fThread; io_object_t fObject; IOFireWireLibDeviceRef fDevInterface; IOFireWireAVCLibUnitInterface **fAVCInterface; IOFireWireAVCLibProtocolInterface **fAVCProtoInterface; UInt64 fGUID; char fName[256]; UInt32 fOutPlug; UInt32 fDVFormats; // DV formats supported by device UInt8 standard; // device standard - NTSC/PAL UInt8 fWriteChan; // Channel the Mac writes to the device on UInt8 fReadChan; // Channel the Mac reads from the device on UInt8 fMaxSpeed; // Max bus speed for isoc channel bool fSupportsFCP; // Does device support AVC commands using the FCP protocol? bool p2pConnected; UInt32 p2pPlug; UInt32 p2pChan; UInt32 deviceIndex; // 1-based device index for message callback refcon } DVDevice; // callback functions typedef void (*DVDeviceArrivedFunc)(void *refcon, DVDevice *device, UInt32 index, UInt32 refound); struct _DVThread { pthread_t fRTThread; // Real Time thread, avoid CF. pthread_t fRLThread; // Run-loop thread for device messages IONotificationPortRef fNotifyPort; // Our IOKit notification port CFRunLoopSourceRef fNotifySource; // notify port as a runloop source #if 0 CFRunLoopSourceRef fRequestSource; // runloop source to ask workthread to do stuff CFRunLoopTimerRef fTimerSource; #else mach_port_t fRequestMachPort; // for requests to real time thread CFRunLoopTimerCallBack fTimerFunc; // Fake CR timer callbacks on RT thread void * fTimerRefCon; #endif CFRunLoopRef fWorkLoop; io_iterator_t fMatchEnumer; // Iterator over matching devices io_iterator_t fTermEnumer; // Iterator over terminated devices DVDeviceArrivedFunc fAddedFunc; void * fAddedRefCon; IOServiceMatchingCallback fRemovedFunc; void * fRemovedRefCon; IOFWAVCMessageCallback fDeviceMessage; pthread_mutex_t fRequestMutex; ThreadSyncer fRequestSyncer; UInt32 fSyncRequest; // Flag to indicate completion of synchronous operation IOReturn (*fRequestFunc)(void *arg, UInt32 param); void * fRequestArg; UInt32 fRequestParam; IOReturn fRequestResult; UInt32 fNumDevices; DVDevice fDevices[kDVMaxDevicesActive]; CFAbsoluteTime setTimeoutTime; CFAbsoluteTime requestTimeoutTime; DVGlobalOut * fOutStreams[kDVMaxStreamsActive]; DVGlobalIn * fInStreams[kDVMaxStreamsActive]; UInt32 fLogPos; Log fLog[kLogSize]; }; enum { kNumPlayBufferGroups = 6, // Blocks of packet send ops in output program kDVMaxFrames = 20 // Max number of DV frames in ring buffer }; enum { kEmpty = 0, kReading = 1, kWriting = 2, kReady = 3, }; typedef struct _DVSharedVars { UInt32 fNumGroups; // Number of blocks in DCL program UInt32 fGroupSize; // Number of data packets in DCL group UInt32 fAlignedPacketSize; // Total packet size (offset from one to next) UInt32 fPacketDataSize; // Size of DV data in packet UInt32 fDMAPos; // Which block DMA has just done volatile UInt32 * fTimeStampPtrs; // Pointer to array of timestamps, taken at end of block transmit UInt32 fDataOffset[kNumPlayBufferGroups]; // into DCL data buffer } DVSharedVars; typedef struct _DVFrameVars { volatile UInt32 fReader; volatile UInt32 fWriter; volatile UInt32 fDroppedFrames; volatile UInt32 fStatus; volatile UInt32 fFrameSize[kDVMaxFrames]; volatile UInt8 fFrameStandard[kDVMaxFrames]; volatile UInt32 fFrameTime[kDVMaxFrames]; volatile UInt8 fFrameStatus[kDVMaxFrames]; UInt32 fNumFrames; UInt8 * fFrames; } DVFrameVars; extern DVThread * DVCreateThread(DVDeviceArrivedFunc deviceAdded, void * addedRefCon, CFRunLoopTimerCallBack timerTick, void *timerRefCon, IOFWAVCMessageCallback deviceMessage); extern void DVRunThread(DVThread *thread); extern void DVFreeThread(DVThread *thread); extern void DVSetTimeoutTime(DVThread * dvThread, CFAbsoluteTime fireDate); extern void DVSignalSync(ThreadSyncer *sync, UInt32 *var, UInt32 val); extern void DVWaitSync(ThreadSyncer *sync, UInt32 *var); extern void DVLock(ThreadSyncer *sync); extern void DVUnlock(ThreadSyncer *sync); extern IOReturn DVRequest(DVThread *thread, IOReturn (*func)(void *arg, UInt32 param), void *arg, UInt32 param); extern IOReturn openFireWireUnit(IOFireWireAVCLibUnitInterface **avcInterface, IOFireWireSessionRef session, IOFireWireLibDeviceRef *retInterface, DVThread *thread); extern IOReturn openAVCUnit(io_object_t obj, IOFireWireAVCLibUnitInterface ***retInterface, DVThread *thread); extern IOReturn openAVCProto(IOFireWireAVCLibUnitInterface **avcInterface, IOFireWireAVCLibProtocolInterface ***retInterface, DVThread *thread); extern IOReturn DVDeviceInit(DVThread *thread, DVDevice *device, io_object_t obj, IOServiceInterestCallback deviceMessage, void * refCon); extern void DVDeviceTerminate(DVDevice *device); extern IOReturn DVDeviceOpen(DVThread *thread, DVDevice *device); extern void DVDeviceClose(DVDevice *device); extern DVGlobalOutPtr DVAllocWrite(DVDevice *device, DVThread *thread); extern IOReturn DVWriteSetSignalMode(DVGlobalOutPtr globs, UInt8 mode); extern IOReturn DVWriteAllocFrames(DVGlobalOutPtr globs, UInt32 numFrames, DVFrameVars **frameVars, UInt8 **frames); extern UInt8 * DVWriteGetDCLBuffer(DVGlobalOutPtr globs, DVSharedVars **varPtr); extern IOReturn DVWriteStart(DVGlobalOutPtr globs); extern void DVWriteStop(DVGlobalOutPtr globs); extern void DVWriteFreeFrames(DVGlobalOutPtr globs); extern void DVWriteFree(DVGlobalOutPtr globs); extern DVGlobalInPtr DVAllocRead(DVDevice *device, DVThread *thread); extern IOReturn DVReadAllocFrames(DVGlobalInPtr globs, UInt32 numFrames, DVFrameVars **frameVars, UInt8 **frames); extern IOReturn DVReadStart(DVGlobalInPtr globs); extern void DVReadStop(DVGlobalInPtr globs); extern void DVReadFreeFrames(DVGlobalInPtr globs); extern void DVReadFree(DVGlobalInPtr globs); extern void DVSilenceFrame(UInt8 mode, UInt8* frame); extern void DVLog(DVThread *thread, UInt32 tag, CFAbsoluteTime start, CFAbsoluteTime end); extern void DVDumpLog(DVThread *thread);