1/*
2 * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <IOKit/IOKitLib.h>
25#include <IOKit/firewire/IOFireWireLib.h>
26#include <IOKit/avc/IOFireWireAVCLib.h>
27
28// Turn on logging of when events happen, and log dump when something takes too long
29//#define TIMING 1
30
31//#define kIDH_Verbose_Debug_Logging 1
32
33#define kDVMaxDevicesActive		64	// max devices on firewire bus
34#define kDVMaxStreamsActive		64	// max isoc channels on fw bus
35
36#define kLogSize 20
37typedef struct _Log  {
38    UInt32 tag;
39    CFAbsoluteTime start;
40    CFAbsoluteTime end;
41} Log;
42
43
44// pthread stuff
45typedef struct _syncStruct
46{
47    pthread_mutex_t		fMutex;			// lock this before updating globals
48    pthread_cond_t		fSyncCond;		// To synchronize threads.
49} ThreadSyncer;
50
51typedef struct _DVThread DVThread;
52struct DVGlobalOutStruct;
53typedef struct DVGlobalOutStruct DVGlobalOut, *DVGlobalOutPtr;
54
55struct DVGlobalInStruct;
56typedef struct DVGlobalInStruct DVGlobalIn, *DVGlobalInPtr;
57
58// device structure
59typedef struct _DVDevice
60{
61    DVThread *fThread;
62    io_object_t fObject;
63	IOFireWireLibDeviceRef	fDevInterface;
64    IOFireWireAVCLibUnitInterface **fAVCInterface;
65    IOFireWireAVCLibProtocolInterface **fAVCProtoInterface;
66    UInt64 		fGUID;
67    char 		fName[256];
68    UInt32 		fOutPlug;
69    UInt32 		fDVFormats; 		// DV formats supported by device
70    UInt8 		standard; 			// device standard - NTSC/PAL
71    UInt8		fWriteChan;			// Channel the Mac writes to the device on
72    UInt8		fReadChan;			// Channel the Mac reads from the device on
73    UInt8		fMaxSpeed;			// Max bus speed for isoc channel
74    bool		fSupportsFCP;		// Does device support AVC commands using the FCP protocol?
75    UInt8		p2pConnected;
76    UInt32		p2pPlug;
77    UInt32		p2pChan;
78    UInt32		deviceIndex;		// 1-based device index for message callback refcon
79} DVDevice;
80
81// callback functions
82
83typedef void (*DVDeviceArrivedFunc)(void *refcon, DVDevice *device, UInt32 index, UInt32 refound);
84
85struct _DVThread
86{
87    pthread_t				fRTThread;			// Real Time thread, avoid CF.
88    pthread_t				fRLThread;			// Run-loop thread for device messages
89	IONotificationPortRef	fNotifyPort;		// Our IOKit notification port
90	CFRunLoopSourceRef		fNotifySource;		// notify port as a runloop source
91#if 0
92	CFRunLoopSourceRef		fRequestSource;		// runloop source to ask workthread to do stuff
93	CFRunLoopTimerRef		fTimerSource;
94#else
95    mach_port_t				fRequestMachPort;		// for requests to real time thread
96    CFRunLoopTimerCallBack	fTimerFunc;				// Fake CR timer callbacks on RT thread
97    void *					fTimerRefCon;
98#endif
99	CFRunLoopRef			fWorkLoop;
100	io_iterator_t			fMatchEnumer;			// Iterator over matching devices
101	io_iterator_t			fTermEnumer;			// Iterator over terminated devices
102    DVDeviceArrivedFunc		fAddedFunc;
103    void * 					fAddedRefCon;
104    IOServiceMatchingCallback	fRemovedFunc;
105    void * 					fRemovedRefCon;
106    IOFWAVCMessageCallback	fDeviceMessage;
107    pthread_mutex_t			fRequestMutex;
108	ThreadSyncer			fRequestSyncer;
109    UInt32					fSyncRequest;		// Flag to indicate completion of synchronous operation
110    IOReturn 				(*fRequestFunc)(void *arg, UInt32 param);
111    void *					fRequestArg;
112    UInt32					fRequestParam;
113    IOReturn				fRequestResult;
114    UInt32					fNumDevices;
115    DVDevice				fDevices[kDVMaxDevicesActive];
116    CFAbsoluteTime			setTimeoutTime;
117    CFAbsoluteTime			requestTimeoutTime;
118    DVGlobalOut	*			fOutStreams[kDVMaxStreamsActive];
119    DVGlobalIn	*			fInStreams[kDVMaxStreamsActive];
120
121    UInt32					fLogPos;
122    Log						fLog[kLogSize];
123
124	io_object_t             fPowerManagementNotifier;
125	IONotificationPortRef	fPowerNotifyPort;
126	CFRunLoopSourceRef		fPowerNotifySource;
127	io_connect_t			fPowerNotifyConnect;
128	bool					fRunLoopIsRunning;
129};
130
131
132enum {
133    kNumPlayBufferGroups	= 6,	// Blocks of packet send ops in output program
134    kDVMaxFrames			= 20	// Max number of DV frames in ring buffer
135};
136
137enum {
138    kEmpty = 0,
139    kReading = 1,
140    kWriting = 2,
141    kReady = 3,
142
143};
144
145typedef struct _DVSharedVars {
146    UInt32 					fNumGroups;		// Number of blocks in DCL program
147    UInt32 					fGroupSize;		// Number of data packets in DCL group
148    UInt32					fAlignedPacketSize;	// Total packet size (offset from one to next)
149    UInt32					fPacketDataSize;	// Size of DV data in packet
150    UInt32					fDMAPos;			// Which block DMA has just done
151    volatile UInt32	*		fTimeStampPtrs;		// Pointer to array of timestamps, taken at end of block transmit
152    UInt32					fDataOffset[kNumPlayBufferGroups];	// into DCL data buffer
153} DVSharedVars;
154
155typedef struct _DVFrameVars {
156    volatile UInt32 fReader;
157    volatile UInt32 fWriter;
158    volatile UInt32 fDroppedFrames;
159    volatile UInt32 fStatus;
160    volatile UInt32 fFrameSize[kDVMaxFrames];
161    volatile UInt8 fFrameStandard[kDVMaxFrames];
162    volatile UInt32 fFrameTime[kDVMaxFrames];
163    volatile UInt8 fFrameStatus[kDVMaxFrames];
164    UInt32			  fNumFrames;
165    UInt8 *			  fFrames;
166} DVFrameVars;
167
168
169extern DVThread * DVCreateThread(DVDeviceArrivedFunc deviceAdded, void * addedRefCon,
170    CFRunLoopTimerCallBack timerTick, void *timerRefCon, IOFWAVCMessageCallback deviceMessage);
171extern void DVRunThread(DVThread *thread);
172extern void DVFreeThread(DVThread *thread);
173extern void DVSetTimeoutTime(DVThread * dvThread, CFAbsoluteTime fireDate);
174
175extern void DVSignalSync(ThreadSyncer *sync, UInt32 *var, UInt32 val);
176extern void DVWaitSync(ThreadSyncer *sync, UInt32 *var);
177extern void DVLock(ThreadSyncer *sync);
178extern void DVUnlock(ThreadSyncer *sync);
179extern IOReturn DVRequest(DVThread *thread, IOReturn (*func)(void *arg, UInt32 param), void *arg, UInt32 param);
180
181extern IOReturn openFireWireUnit(IOFireWireAVCLibUnitInterface **avcInterface, IOFireWireSessionRef session, IOFireWireLibDeviceRef *retInterface, DVThread *thread);
182extern IOReturn openAVCUnit(io_object_t obj, IOFireWireAVCLibUnitInterface ***retInterface, DVThread *thread);
183extern IOReturn openAVCProto(IOFireWireAVCLibUnitInterface **avcInterface, IOFireWireAVCLibProtocolInterface ***retInterface, DVThread *thread);
184
185extern IOReturn DVDeviceInit(DVThread *thread, DVDevice *device,
186        io_object_t obj, IOServiceInterestCallback deviceMessage, void * refCon);
187extern void DVDeviceTerminate(DVDevice *device);
188extern IOReturn DVDeviceOpen(DVThread *thread, DVDevice *device);
189extern void DVDeviceClose(DVDevice *device);
190
191extern DVGlobalOutPtr DVAllocWrite(DVDevice *device, DVThread *thread);
192extern IOReturn DVWriteSetSignalMode(DVGlobalOutPtr globs, UInt8 mode);
193extern IOReturn DVWriteAllocFrames(DVGlobalOutPtr globs, UInt32 numFrames,
194        DVFrameVars **frameVars, UInt8 **frames);
195extern UInt8 * DVWriteGetDCLBuffer(DVGlobalOutPtr globs, DVSharedVars **varPtr);
196extern IOReturn DVWriteStart(DVGlobalOutPtr globs);
197extern void DVWriteStop(DVGlobalOutPtr globs);
198extern void DVWriteFreeFrames(DVGlobalOutPtr globs);
199extern void DVWriteFree(DVGlobalOutPtr globs);
200
201extern DVGlobalInPtr DVAllocRead(DVDevice *device, DVThread *thread);
202extern IOReturn DVReadSetSignalMode(DVGlobalInPtr globs, UInt8 mode);
203extern IOReturn DVReadAllocFrames(DVGlobalInPtr globs, UInt32 numFrames,
204        DVFrameVars **frameVars, UInt8 **frames);
205extern IOReturn DVReadStart(DVGlobalInPtr globs);
206extern void DVReadStop(DVGlobalInPtr globs);
207extern void DVReadFreeFrames(DVGlobalInPtr globs);
208extern void DVReadFree(DVGlobalInPtr globs);
209
210extern void DVSilenceFrame(UInt8 mode, UInt8* frame);
211
212extern void DVLog(DVThread *thread, UInt32 tag, CFAbsoluteTime start, CFAbsoluteTime end);
213extern void DVDumpLog(DVThread *thread);
214