/*                                                 -*-mode:C;tab-width:8-*-
 * 
 * cxdrv.h  -- the public include file
 *
 * Copyright (C) 1995 Alessandro Rubini  -- rubini@ipvvis.unipv.it
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _CXDRV_H_
#define _CXDRV_H_

#include <linux/timer.h> /* damn it -- missing irq */

#define CXG_RELEASE "0.85"
#define _CXG_REV1    0
#define _CXG_REV2      85
#define CXG_RELEASE_TIME "October 1995"

/* the PDEBUG symbol masks fprintf */

#ifndef PDEBUG
#  ifdef DEBUG_CX100
#    ifdef __KERNEL__
#      define PDEBUG(data) printk data
#    else
#      define PDEBUG(data) fprintf data
#    endif
#  else
#    define PDEBUG(data)
#  endif
#endif

/* the PDEBUGG symbol hides everything */

#ifndef PDEBUGG
#  define PDEBUGG(data)
#endif


/*------------------ data structures ------------------*/

/* Roi */

typedef struct Cxg_Roi {
  unsigned short x,wid,y,hei;
  struct Cxg_Roi *next;
  unsigned long count;
  union {
    void *data;
    char header[16];      /* "P5\n123\n456\n255\n\0" */
    } xtra;
  }            Cxg_Roi;

#define _CXG_PGM_OFFSET  15


/*
 * This is the hardware info, current to more than one open file.
 */
typedef struct Cxg_Board {
  int base;
  unsigned long volatile irq_count;
  short hwirq;
  short irq;
  short ram;
  unsigned char has_video;
  unsigned char usecount;
  unsigned long jiffies;
  unsigned long volatile fields; /* keep a 32bit field counter */
  unsigned long field_w;         /* next awake time */
  struct wait_queue *waitq;
  unsigned char lowres;
  unsigned char may_overlay;
  unsigned char status;
  unsigned char fake;
  unsigned char fpga_rev;
  unsigned char micro_rev;
  unsigned char driver_rev1;
  unsigned char driver_rev2;
  Cxg_Roi *roi;               /* for pgm r/w */
  struct timer_list timer;    /* needed if no irq */
  unsigned char grabreq;      /* after sleeping, shall I grab? */
  }            Cxg_Board;


/*
 * This is the soft info, it can be different in different open files,
 * In particular, the Roi list is per-file
 */
typedef struct Cxg_Clientdata {
  Cxg_Board *cd_board;
  unsigned short cd_type;
  unsigned short cd_ispgm;
  unsigned long cd_next; /* used to awake a process on a specific field */
  unsigned long cd_step; /* used to "grab once a second" or such */
  unsigned long cd_fstart;
  Cxg_Roi *cd_rois;
  Cxg_Roi *cd_currRoi;
  }            Cxg_Clientdata;


#ifdef __KERNEL__

/*
 * Rules to split minors
 */

#define BOARDNO(dev)   (MINOR(dev)&0x0f)
#define DEVTYPE(dev)   (MINOR(dev)>>4)

enum devtypes {CX_RAW=0,CX_OVL=1,CX_FULL=2,CX_PGM=3};

/*
 * HW parameters
 */

#define  PORT_MIN         0x230
#define  PORT_STEP            8
#define  PORT_MAX         0x2b0

#define  MAX_BOARDS           4

#define  PORT0(b) ((b)->base)
#define  PORT1(b) ((b)->base+1)
#define  PORT2(b) ((b)->base+2)
#define  PORT6(b) ((b)->base+6)

/*
 * full faking is only available when debugging is on
 */

#ifdef DEBUG_CX100
#  define fs_inp(b,p)        ( (b)->fake ? (p)&0xff : inp(p))
#  define fs_outp(b,v,p)     ( (b)->fake ? 0        : outp((v),(p)) )
#  define FAKE_BEGIN       if (board->fake) {
#  define FAKE_ELSE          } else {
#  define FAKE_END           }
#else
#  define fs_inp(b,p)      inp(p)
#  define fs_outp(b,v,p)   outp((v),(p))
#  define FAKE_BEGIN       if (0) {
#  define FAKE_ELSE          } else {
#  define FAKE_END           }
#endif


/*
 * and finally, utility functions
 */
#define inp  inb_p
#define outp outb_p

#define  COMMAND(b,c)  (fs_outp((b),(c),(b)->base+3), \
			busywait(1),fs_inp((b),(b)->base+3))
#define  PDEBUGCMD(i,o) PDEBUGG(("cx cmd 0x%x returned 0x%x\n",i,o));

#define  GETPORT(b,p)   (fs_inp((b),(b)->base+p))

#define  SETPAGE(b,p)   (fs_outp((b),(p)&0x3,PORT6(b)))
#define  GETPAGE(b)     (fs_inp((b),PORT0(b))&0x03) 
#define  INCPAGE(b)     (SETPAGE((b),GETPAGE(b)+1))
#define  DECPAGE(b)     (SETPAGE((b),GETPAGE(b)-1))

#define  SETBITV(b,bit,v) (fs_outp((b),(bit)*2+(v),PORT6(b)))
#define  SETBIT(b,bit)    SETBITV(b,bit,1)
#define  CLRBIT(b,bit)    SETBITV(b,bit,0)
#define  GETBIT(b,bit)    (fs_inp((b),(b)->base+((bit)>>3)) & (1<<((bit)&7)))

#endif /* __KERNEL__ */





/*========== bit definitions, to set/reset them ========*/

enum Cxg_bits {

   CXG_BIT_PS0 = 0,    /* port 0 */
   CXG_BIT_PS1,
   CXG_BIT_VERTICAL,
   CXG_BIT_ACQ_REQ,
   CXG_BIT_DISP_RAM,
   CXG_BIT_LOW_RES,
   CXG_BIT_STROBE,
   CXG_BIT_HALF_PG,

   CXG_BIT_IRQ_ENB = 8,  /* port 1 */
   CXG_BIT_TRIG_ENB,
   CXG_BIT_ILUT_ENB,
   CXG_BIT_BLNK_DISP,
   CXG_BIT_AB_SEL,
   CXG_BIT_RAM_ENB,
   CXG_BIT_MP_ACC,
   CXG_BIT_BUF_FULL,

   CXG_BIT_FLD_GRAB = 0x10,  /* port 2 */
   CXG_BIT_FRM_GRAB,
   CXG_BIT_OLUT_ENB,
   CXG_BIT_DSPL_OL,
   CXG_BIT_OL_ENB,
   CXG_BIT_MSK_ENB,
   CXG_BIT_INDP_PG,

#define CXG_MAX_WR_BIT CXG_BIT_INDP_PG  /* last writable bit */

   CXG_BIT_INT_ACK = 0x30,   /* port 6 */
   CXG_BIT_ADC_OVER,
   CXG_BIT_FIELD,
   CXG_BIT_VBLANK,
   CXG_BIT_TRIG_ACK,
   CXG_BIT_ACQ_ACK,
   CXG_BIT_ADC_UNDER,
   CXG_BIT_HAVE_VID
   };

/*========== commands, to invoke them ========*/
 
enum Cxg_commands {
   CXG_CMD_BOGUS =      0x00,
   CXG_CMD_GETDIPS =    0x40,
   CXG_CMD_GETGAV =     0x41,
   CXG_CMD_GETFWV =     0x42,
   CXG_CMD_GETSTATUS =  0x43,

   #define CXG_SBIT_TRIGPOL 0x01
   #define CXG_SBIT_INTSYNC 0x02
   #define CXG_SBIT_CCIR    0x04
   #define CXG_SBIT_CX100   0x08
   #define CXG_SBIT_ONEFLD  0x20
   #define CXG_SBIT_CURFLD  0x40
   #define CXG_SBIT_SNGFLD  0x80

   /* get video seg (0x44) unused */
   CXG_CMD_GETKEY =     0x45,
   CXG_CMD_CORTEXMODE = 0x46,
   CXG_CMD_CXMODE =     0x47,
   CXG_CMD_GETCOUNTL =  0x48,
   CXG_CMD_GETCOUNTH =  0x49,
   CXG_CMD_CLRCOUNT =   0x4a,
   CXG_CMD_CLRCOUNTH =  0x4b,
   CXG_CMD_SETTRIGNEG = 0x4c,
   CXG_CMD_SETTRIGPOS = 0x4d,
   CXG_CMD_EXTSYNC =    0x4e,
   CXG_CMD_INTSYNC =    0x4f,
   /* 0x50 and 0x51 are reserved */
   CXG_CMD_FRMDISP =    0x52,
   CXG_CMD_FLDDISP =    0x53,
   CXG_CMD_DISP0 =      0x54,
   CXG_CMD_DISP1 =      0x55,
   /* interrupt polarity (0x56 and 0x57) not available on isa buses */
   CXG_CMD_SHUTDOWN =   0x58,
   CXG_CMD_RESETENB =   0x59,
   CXG_CMD_EDGETRIG =   0x5a,
   CXG_CMD_LEVELTRIG =  0x5b,
   /* 0x5c and 0x5d are reserved */
   CXG_CMD_NTSC =       0x5e,
   CXG_CMD_CCIR =       0x5f
   };

/*========== ioctl definitions, to set/reset them ========*/

/* Ok, I chose the '!' for the magic number. Look at /usr/src/linux/MAGIC */


#define    CXG_AUTODETECT 255 /* used in several places */

/*============================== bit manipulation */
#define CXG_GETPORTS   0x2181
#define CXG_SETBIT     0x2182
#define CXG_CLRBIT     0x2183
#define CXG_GETBIT     0x2184
#define CXG_SETBITV    0x2185

/*============================== command */
#define CXG_COMMAND    0x2180

/*============================== information retrivial */
#define CXG_GETHWINFO  0x2190
#define CXG_GETSWINFO  0x2191
#define CXG_GETRAMINFO 0x2192
#define    CXG_MEM_FREE 0
#define    CXG_MEM_BUSY 1
#define    CXG_MEM_RAM  2
#define    CXG_MEM_ROM  3

/* 21a[0-7] is no more used */

/*============================== grab control */
#define CXG_GRABCTL    0x21a8
#define    CXG_GRAB_FRAME      1
#define    CXG_GRAB_FIELD      2
#define    CXG_GRAB_FIELD0     3
#define    CXG_GRAB_FIELD1     4
#define    CXG_GRAB_TRIGGERED  5
#define       CXG_GRAB_WAIT  0x0100 /* this flag is or'ed */
#define CXG_SCHEDULE  0x21a9


/*============================== delays */
#define CXG_WAITVB     0x21ac

/*============================== setting modes */
#define CXG_SETIRQ     0x21b0
#define    CXG_IRQ_NONE       256 /* autodetect allowed */
#define CXG_RAMPAGE    0x21b1
#define    CXG_RAMPAGE_NONE    -1 /* autodetect allowed */
#define CXG_SETROI     0x21b2
#define CXG_SETPGMMODE 0x21b3
#define CXG_LOWRES     0x21b4
#define CXG_INTERVAL   0x21b5  /* enable blocking read() */


/*============================== field counter */
#define CXG_GETCOUNT   0x21bc
#define CXG_WAITCOUNT  0x21bd

/*============================== xfer region */
#define CXG_GETREGION  0x21e0
#define CXG_PUTREGION  0x21e1

/*============================== lut load/retrieve */
#define CXG_INLUT      0x21e8
#define CXG_INLUT1     0x21e9
#define CXG_GETINLUT   0x21ea
#define CXG_OUTLUT     0x21eb
#define CXG_OUTLUT1    0x21ec
#define CXG_GETOUTLUT  0x21ed

/*============================== gain/offset */
#define CXG_SETGAIN    0x21f0
#define CXG_SETOFFSET  0x21f1

/* more to come */

#ifndef __KERNEL__
/*=========================================================================*/
/*          This is user-space material (for the library)                  */
/*=========================================================================*/
#include <sys/ioctl.h>

/*========================================================== linux library */

extern unsigned int _cxg_tmp[2];
extern Cxg_Board _cxg_board;
extern Cxg_Clientdata _cxg_cd;


/* Some of these are macros, some not (lazy me) */

/*==================== bit manipulation */
#define Cxg_GetPorts(fd,where)           ioctl((fd),CXG_GETPORTS,(where))
#define Cxg_SetBit(fd,bit)               ioctl((fd),CXG_SETBIT,(bit))
#define Cxg_ClrBit(fd,bit)               ioctl((fd),CXG_CLRBIT,(bit))
#define Cxg_SetBitV(fd,bit,v)            ioctl((fd),CXG_SETBITV,2*(bit)+!!(v))
int Cxg_GetBit(int fd, int bit);
#define Cxg_SetPage(fd,p)                Cxg_SetBitV((fd),((p)&2)>>1,(p)&1)

/*==================== command */
int Cxg_Command(int fd, int cmd);

/*==================== information retrivial */
#define Cxg_GetHwInfo(fd,ptr)            ioctl((fd),CXG_GETHWINFO,(ptr))
#define Cxg_GetSwInfo(fd,ptr)            ioctl((fd),CXG_GETSWINFO,(ptr))
#define Cxg_GetRamInfo(fd,ptr)           ioctl((fd),CXG_GETRAMINFO,(ptr))
#define Cxg_LibVersion()                 CXG_RELEASE /* dirty */

/*==================== grab control */
#define Cxg_GrabFrame(fd,w)      ioctl((fd),CXG_GRABCTL,CXG_GRAB_FRAME \
				       | ((w) ? CXG_GRAB_WAIT : 0))
#define Cxg_GrabField(fd,w)      ioctl((fd),CXG_GRABCTL,CXG_GRAB_FIELD \
				       | ((w) ? CXG_GRAB_WAIT : 0))
#define Cxg_GrabFieldN(fd,n,w)   ioctl((fd),CXG_GRABCTL,(CXG_GRAB_FIELD0+(n)) \
				       | ((w) ? CXG_GRAB_WAIT : 0))
#define Cxg_GrabLive(fd)         Cxg_SetBit((fd),CXG_BIT_ACQ_REQ)
#define Cxg_GrabOff(fd)          Cxg_ClrBit((fd),CXG_BIT_ACQ_REQ)

/*==================== setting modes */
#define Cxg_SetIrq(fd,irq)               ioctl((fd),CXG_SETIRQ,(irq))
#define Cxg_RamPage(fd,ram)              ioctl((fd),CXG_RAMPAGE,(ram))
#define Cxg_SetRoi(fd,roi)               ioctl((fd),CXG_SETROI,(roi))
#define Cxg_PgmMode(fd,bool)             ioctl((fd),CXG_SETPGMMODE,(bool))
#define Cxg_LowRes(fd,bool)              ioctl((fd),CXG_LOWRES,(bool))
#define Cxg_Interval(fd,i1,i2)           (_cxg_tmp[0]=i1, _cxg_tmp[1]=i2, \
					  ioctl((fd),CXG_INTERVAL,_cxg_tmp))
#define Cxg_SetStep(fd,step)             Cxg_Interval((fd),(step),0)
#define Cxg_SetNext(fd,next)             Cxg_Interval((fd),0,(next))

/*==================== field counter */
#define Cxg_ClearFC(fd)          Cxg_Command((fd),CXG_CMD_CLRCOUNT)
#define Cxg_GetFC(fd)            (ioctl((fd),CXG_GETCOUNTER,&_cxg_tmp)<0 \
				  ? -1 : _cxg_tmp)

/*==================== delays */
#define Cxg_WaitVb(fd)           ioctl((fd),CXG_WAITVB,-1)
#define Cxg_WaitVbField(fd,f)    ioctl((fd),CXG_WAITVB,(f)&1)
#define Cxg_WaitCounter(fd,c)    (ioctl((fd),CXG_WAITCOUNT,_cxg_tmp)<0 \
                                  ? -1 : _cxg_tmp[0])

/*==================== xfer region */
#define Cxg_GetRegion(fd,roiptr) ioctl((fd),CXG_GETREGION,(roiptr))
#define Cxg_PutRegion(fd,roiptr) ioctl((fd),CXG_PUTREGION,(roiptr))



#endif /*  ! __KERNEL__  */

#endif /*   _CXDRV_H_    */






