/*
 * Copyright (C) 2002 Andreas Thiede ( a.thiede@berlin.de )
 * 
 * based on:
 *
 * Copyright (c) 1998-2000 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@
 */
/*
 * Copyright (c) 2000 Apple Computer, Inc.  All rights reserved.
 *
 *  DRI: Josh de Cesare
 *
 */

#include <IOKit/IOService.h>
#include <IOKit/IOUserClient.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <iokit/IOInterruptEventSource.h>
#include <IOKit/IOSyncer.h>

#include "../lib/Bt8xxLib.h"

// Bt8xx chip typesred

enum {
    kBt8xx = 0,
    kBt848,
    kBt848A,
    kBt849A,
    kBt878,
    kBt878A,
    kBt879
};

enum eBtMode {
  kBtModeReset = 0,
  kBtModeStopped,
  kBtModeRunning
};

typedef enum eBtMode eBtMode;

class Bt8xxUserClient;

class WorkLoop : public IOWorkLoop {
 
    public:
    
        WorkLoop() : IOWorkLoop() {}
        
        ~WorkLoop() {}
        
        void OpenGate() {
            IOWorkLoop::openGate();
        }

        void CloseGate() {
            IOWorkLoop::closeGate();
        }
};
  

class GateGuard {
  
        WorkLoop * workLoop;
        
    public:
    
        GateGuard( WorkLoop * loop ) {
        
            //IOLog( "GateGuard thisThread(%x)\n", IOThreadSelf() );
            workLoop = loop;
            
            if( workLoop )
                workLoop->CloseGate();
        }
        
        ~GateGuard() {

            if( workLoop )
                workLoop->OpenGate();
        }
};
  

class Bt8xxMemDescriptor : public OSObject {

public:

  OSDeclareDefaultStructors( Bt8xxMemDescriptor );

public:

  MemoryDescriptor   mData;
  IOMemoryMap      * mMemMap;
};

class Bt8xxImpl : public OSObject
{

public:

  OSDeclareDefaultStructors( Bt8xxImpl );

public:

  void initWithOwner( Bt8xx * anOwner );
  
  void finit();
  
  IOService * owner();
  
  WorkLoop * getWorkLoop(void);
  
  
  IOReturn wait4Video();
  IOReturn wait4VBI();
  IOReturn readAudio( char * buffer, UInt32 swcount );
    
  void handleInterrupt( IOInterruptEventSource * src, int count );

  void maskVideoInterrupts(void);
  void unmaskVideoInterrupts(void);

  void maskAudioInterrupts(void);
  void unmaskAudioInterrupts(void);

  void audioCaptured( UInt32 blockNr );
  
  UInt32	identifyChipType(IOPCIDevice *pciNub);
  
  IOReturn     reset(void);
  IOReturn     setup( eCaptureFormat fmt, UInt32 colFmt );
  IOReturn     clientStart(void);
  IOReturn     clientStop(void);
 
  bool start( IOService *provider );
  void stop ( IOService *provider );
  
  void powerDown();
  
  void startAudio();

  void setupAudioSpeed( int val );
    
  int getDimension( UInt32 & _width, UInt32 & _height, int & nVBILines );

  // DMA programing methods
  void         setupVideoDMA(void);
  void         setupAudioDMA(void);
  
  // Register accessor methods
  UInt8        readVideoReg8 (UInt32 reg);
  UInt16       readVideoReg16(UInt32 reg);
  UInt32       readVideoReg32(UInt32 reg);
  
  void         writeVideoReg8 (UInt32 reg, UInt8  data);
  void         writeVideoReg16(UInt32 reg, UInt16 data);
  void         writeVideoReg32(UInt32 reg, UInt32 data);
  
  UInt8        readAudioReg8(UInt32 reg);
  UInt16       readAudioReg16(UInt32 reg);
  UInt32       readAudioReg32(UInt32 reg);
  
  void         writeAudioReg8 (UInt32 reg, UInt8  data);
  void         writeAudioReg16(UInt32 reg, UInt16 data);
  void         writeAudioReg32(UInt32 reg, UInt32 data);

#if 0
  IOReturn allocPages( UInt32 nPages, MemoryDescriptor * md, task_t task );
  IOReturn freePages ( MemoryDescriptor * md );
#endif

  IOService              * mOwner;
  WorkLoop               * mWorkLoop;
  IOUserClient           * mUserClient;
  IOPCIDevice            * mVideoNub;
  IOPCIDevice            * mAudioNub;
  
  IOInterruptEventSource * mVideoInterruptSource;
  //IOInterruptEventSource * mAudioInterruptSource;
  
  UInt32	           mVideoChipType;
  UInt32	           mAudioChipType;
  IOMemoryMap            * mVideoMemoryMap;
  IOMemoryMap            * mAudioMemoryMap;
  IOVirtualAddress         mVideoBaseAddress;
  IOVirtualAddress         mAudioBaseAddress;
  semaphore_port_t         mSemVideoAvailable;
  semaphore_port_t         mSemVBIAvailable;
  semaphore_port_t         mSemAudioAvailable;
  semaphore_port_t         mSemIrq;
  vm_size_t                mVideoBufSize;
  vm_size_t                mVBIBufSize;
  vm_size_t                mAudioBufSize;
  void *                   mVideoVirtAddr;
  void *                   mVBIVirtAddr;
  void *                   mAudioVirtAddr;
  IOPhysicalAddress        mVideoPhysAddr;
  IOPhysicalAddress        mVBIPhysAddr;
  IOPhysicalAddress        mAudioPhysAddr;
  eBtMode                  mCurrentMode;
  UInt32                   mAudioMask;
  IOVirtualAddress         mAudioCmdPage;
  IOPhysicalAddress        mAudioCmdPagePhys;  
  IOVirtualAddress         mVideoCmdPage;
  IOPhysicalAddress        mVideoCmdPagePhys;
  IOVirtualAddress         mVideoEvenPage;
  IOPhysicalAddress        mVideoEvenPagePhys;
  IOVirtualAddress         mVideoOddPage;
  IOPhysicalAddress        mVideoOddPagePhys;
  eCaptureFormat      	   mCaptureFormat;

  int                      mVideoReadCount;
  int                      mVideoReadOffset;

  int                      mVBIReadCount;
  int                      mVBIReadOffset;

  unsigned long            mAudioBlockBytes;
  unsigned long            mAudioBlockCount;
  unsigned long            mAudioLineBytes;
  unsigned long            mAudioLineCount;
  unsigned long            mAudioDmaBlock;
  int                      mAudioAnalog;
  int                      mAudioBits;
  int                      mAudioSource;
  int                      mAudioDecimation;
  int                      mAudioGain;
  int                      mAudioReadCount;
  int                      mAudioReadOffset;
  long long                mAudioIrqCount;
  int 			   mAudioSampleShift;
  int 			   mAudioChannels;
  unsigned long            mCurrentAudioBlock;
  unsigned long            mVideoIrqCount;
  UInt32                   mDeviceID;
//  OSDictionary           * mMemoryList;
  long long                mMemoryHandleCounter;
  int                      mAudioStarted;
};
