/* Copyright Philips Research Labs, Redhill, UK. 2001
 *
 * Prototype Software
 *
 * Contact: Tim Everett (tim.everett@philips.com)
 *
 */
/* based on LinuxTM.h
 * ============================================================================
 *        Copyright (C) Philips Research Laboratories, Redhill, UK, 1998
 * ============================================================================
 *
 * PRL Prototype Software - This software must be maintained in accordance
 * with PRL engineering practices for Prototype Software.
 *
 * PRL Contact: Richard Miller-Smith
 * Group:       Interactive Systems Group
 * Project:     Digital Video Recorder (DVR)
 * Date:        19th May 1998
 *
 * Module:      Linux Device Driver - TriMedia (IREF) board
 * Sub-Module:  Global include file for external daemons/programs
 *
 */

#ifndef _LUDDEV_H
#define _LUDDEV_H

/** LUD Control Operations **/

/* Structures and typedefs */

typedef struct {
  char *name ;
  unsigned int  nameLength ;
  unsigned int  length ;
} tmMI_t, * ptmMI_t ;

typedef struct {
  unsigned int reg ;
  unsigned int val ;
} tmMMIOReg_t, *ptmMMIOReg_t ;

typedef struct {
  unsigned int pos ;
  unsigned int val ;
} tmDRAMAccess_t, *ptmDRAMAccess_t ;

/** LUD Control IOCTL Commands **/

#define LUDMOD_MAX_MODULES	32
#define LUDMOD_MAX_MOD_NAME 64

struct LUD_MODLIST {
	int n;
	char mod[LUDMOD_MAX_MODULES][LUDMOD_MAX_MOD_NAME];
};

typedef enum {
  LUD_CNTL_RESET = 0xea00,
  LUD_CNTL_START,
  LUD_CNTL_DL_MEMIMAGE,
  LUD_CNTL_GET_MMIO_REG,
  LUD_CNTL_GET_DRAM_WORD,
  LUD_CNTL_SET_MMIO_REG,
  LUD_CNTL_SET_DRAM_WORD,
  LUD_CNTL_ENABLE_FB,
  LUD_CNTL_ENABLE_VIDEO,
  LUD_CNTL_LOAD_DLL,
  LUD_CNTL_UNLOAD_DLL,
  LUD_CNTL_LIST_DLL,
  LUD_CNTL_GET_ID,
  LUD_CNTL_GET_DRAM_BASE,
  LUD_CNTL_GET_DRAM_LIMIT,
  LUD_CNTL_GET_MMIO_BASE,
  LUD_CNTL_GET_TARGET_FREQ,
  LUD_CNTL_GET_TARGET_STATE,
  LUD_CNTL_SET_DP_LEVEL,
  LUD_CNTL_GET_DP_LEVEL,
  LUD_CNTL_DEL_NODES,
  LUD_CNTL_START_LUDDITE,
  LUD_CNTL_GET_TYPE,
  LUD_CNTL_SET_COMM_VEC,
  LUD_CNTL_SET_DEBUG_EVENT,
  LUD_CNTL_GET_DEBUG_EVENT,
} ludCntlCmd_t ;
/* Structures and typedefs */

#define MAX_LUD_DEV 32

#define TM_INTERRUPT_NUM 28

#define LUD_DEF_STACK 0x6000

/*
 * Luddite node handles contain a CPU reference and a node reference.
 */
#define LUD_NODE_FROM_HANDLE(x)	((x)&0xffff)
#define LUD_CPU_FROM_HANDLE(x)	(((x)>>16)&0xffff)
#define LUD_CREATE_HANDLE(cpu,node)	(((cpu&0xffff)<<16)|(node&0xffff))

/**
 * @file
 * Generic ioctl() code.
 *
 * Note there are two different numbers here:
 * the Linux application-to-kernel ioctl() number, and
 * the Luddite Linux-to-TriMedia command number.
 *
 * These are different.  Linux uses a numbering scheme which is
 * different on each architecture.  Luddite uses a numbering
 * scheme which always gives the same numbers on any architecture,
 * so that the TriMedia modules do not need to be recompiled for
 * different host (Linux) architectures.
 */

/**
 * @addtogroup group_linux
 * @section group_linux_ioctls Ioctl Macros
 * This collection of macros, allow us to define ioctl command
 * values, that contain information about the required arguments
 * as well as being portable across linux architectures.
 *
 * There is also a list of pre defined ioctls used by luddite and its
 * various sub systems.
 *
 * @{
 */

#define LUD_IOCTL_TYPE_URGENT(type) (0x80 | (type))

#if defined(__KERNEL__) || defined(__TCS__)

#define LUD_IOCTL_URGENT 0x00800000
#define LUD_IOCTL_READ   0x01000000
#define LUD_IOCTL_CMASK  0x00ff0000
#define LUD_IOCTL_IMASK  0x0000ffff

/**
 * Encode a Luddite command number for a write-only ioctl().
 *
 * This should NOT be used from Linux userspace - only by kernel
 * modules and TriMedia modules.
 *
 * If you are writing a module, you should probably use
 * LUD_IOCTL_COMMAND() instead.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 */
#define LUD_IOCTL_CMD(sys,index) ((((sys)<<16)&LUD_IOCTL_CMASK)|((index)&LUD_IOCTL_IMASK))

#define LUD_IOCTL_CMD_URGENT(sys,index) LUD_IOCTL_CMD(LUD_IOCTL_TYPE_URGENT(sys),(index))

/**
 * Encode a Luddite request number for a read-write ioctl().
 *
 * This should NOT be used from Linux userspace - only by kernel
 * modules and TriMedia modules.
 *
 * If you are writing a module, you should probably use
 * LUD_IOCTL_REQUEST() instead.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 */
#define LUD_IOCTL_REQ(sys,index) (LUD_IOCTL_READ|LUD_IOCTL_CMD((sys),(index)))

#define LUD_IOCTL_REQ_URGENT(sys,index) LUD_IOCTL_REQ(LUD_IOCTL_TYPE_URGENT(sys),(index))

#endif /* defined(__KERNEL__) || defined(__TCS__) */

#ifdef __TCS__
/* On TriMedia side */

/**
 * Encode a write-only ioctl().
 *
 * On Linux, this gives a Linux ioctl() number.  On TriMedia, this gives
 * the Luddite command number which is generated from that ioctl().
 *
 * These numbers are different - the standard Luddite Linux-side module
 * performs the conversion.  Note that on Linux, the encoding used for
 * ioctl()s is the standard Linux one, which is architecture-dependent
 * (MIPS and x86 are different).  The Luddite command number is the
 * same on all platforms.
 *
 * Use this function for cross-platform header files, that can be used
 * by both Linux applications and TriMedia modules.
 *
 * For more details, see _IOW() in the Linux documentation.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 * @param size  The type used for the transfer.  sizeof(size) bytes will
 *              be copied from userspace and used for the arguments
 *              to the command.  sizeof(size) must be 4 (1 argument),
 *              8 (2 arguments), 12 (3 arguments), 16 (4 arguments),
 *              or 0 (1 argument - the actual ioctl() paramater).
 */
#define LUD_IOCTL_COMMAND(sys,index,size) LUD_IOCTL_CMD(sys,index)

#define LUD_IOCTL_COMMAND_0(sys,index) LUD_IOCTL_CMD(sys,index)

/**
 * Encode a read-write ioctl().
 *
 * On Linux, this gives a Linux ioctl() number.  On TriMedia, this gives
 * the Luddite request number which is generated from that ioctl().
 *
 * These numbers are different - the standard Luddite Linux-side module
 * performs the conversion.  Note that on Linux, the encoding used for
 * ioctl()s is the standard Linux one, which is architecture-dependent
 * (MIPS and x86 are different).  The Luddite request number is the
 * same on all platforms.
 *
 * Use this function for cross-platform header files, that can be used
 * by both Linux applications and TriMedia modules.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 * @param size  The type used for the transfer.  sizeof(size) bytes will
 *              be copied from userspace and used for the arguments
 *              to the request.  After the request completes, sizeof(size)
 *              bytes will be copied back to userspace from the reply.
 *              sizeof(size) must be 4 (1 argument), 8 (2 arguments),
 *              12 (3 arguments), 16 (4 arguments), or 0 (1 argument -
 *              the actual ioctl() paramater is the argument, and the
 *              reply is used as the ioctl() return value).
 */
#define LUD_IOCTL_REQUEST(sys,index,size) LUD_IOCTL_REQ(sys,index)

#define LUD_IOCTL_REQUEST_0(sys,index) LUD_IOCTL_REQ(sys,index)

#else /* ifndef __TCS__ */
/* On Linux side */

#ifndef _IOW
#include <linux/ioctl.h>
#endif /* ndef _IOW */

/**
 * Encode a write-only ioctl().
 *
 * On Linux, this gives a Linux ioctl() number.  On TriMedia, this gives
 * the Luddite command number which is generated from that ioctl().
 *
 * These numbers are different - the standard Luddite Linux-side module
 * performs the conversion.  Note that on Linux, the encoding used for
 * ioctl()s is the standard Linux one, which is architecture-dependent
 * (MIPS and x86 are different).  The Luddite command number is the
 * same on all platforms.
 *
 * Use this function for cross-platform header files, that can be used
 * by both Linux applications and TriMedia modules.
 *
 * For more details, see _IOW() in the Linux documentation.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 * @param size  The type used for the transfer.  sizeof(size) bytes will
 *              be copied from userspace and used for the arguments
 *              to the command.  sizeof(size) must be 4 (1 argument),
 *              8 (2 arguments), 12 (3 arguments), 16 (4 arguments),
 *              or 0 (1 argument - the actual ioctl() paramater).
 */
#define LUD_IOCTL_COMMAND(sys,index,size) _IOW((sys),(index),size)

#define LUD_IOCTL_COMMAND_0(sys,index) _IOC(_IOC_WRITE,(sys),(index),0)


/**
 * Encode a read-write ioctl().
 *
 * On Linux, this gives a Linux ioctl() number.  On TriMedia, this gives
 * the Luddite request number which is generated from that ioctl().
 *
 * These numbers are different - the standard Luddite Linux-side module
 * performs the conversion.  Note that on Linux, the encoding used for
 * ioctl()s is the standard Linux one, which is architecture-dependent
 * (MIPS and x86 are different).  The Luddite request number is the
 * same on all platforms.
 *
 * Use this function for cross-platform header files, that can be used
 * by both Linux applications and TriMedia modules.
 *
 * @param sys   Identifier for the driver.  A positive 8-bit integer, often
 *              an ASCII letter.  Note that the top bit is the 'urgent' flag.
 * @param index Identifier for the ioctl().  A positive 8-bit integer.
 * @param size  The type used for the transfer.  sizeof(size) bytes will
 *              be copied from userspace and used for the arguments
 *              to the request.  After the request completes, sizeof(size)
 *              bytes will be copied back to userspace from the reply.
 *              sizeof(size) must be 4 (1 argument), 8 (2 arguments),
 *              12 (3 arguments), 16 (4 arguments), or 0 (1 argument -
 *              the actual ioctl() paramater is the argument, and the
 *              reply is used as the ioctl() return value).
 */
#define LUD_IOCTL_REQUEST(sys,index,size) _IOWR(sys,index,size)

#define LUD_IOCTL_REQUEST_0(sys,index) _IOC(_IOC_READ|_IOC_WRITE,(sys),(index),0)


#ifdef __KERNEL__
/**
 * Convert a Linux ioctl number to a TriMedia ioctl number.
 *
 * @param cmd Linux ioctl number
 * @return    TriMedia request/command number
 */
#define LUD_IOCTL_LINUX_TO_TARGET(cmd) \
	( \
		(_IOC_DIR(cmd) & _IOC_READ) \
	? \
		LUD_IOCTL_REQ(_IOC_TYPE(cmd),_IOC_NR(cmd)) \
	: \
		LUD_IOCTL_CMD(_IOC_TYPE(cmd),_IOC_NR(cmd)) \
	)

#endif /* def __KERNEL__ */
#endif /* ndef __TCS__ */

#define LUD_IOCTL_COMMAND_URGENT(sys,index,size) LUD_IOCTL_COMMAND(LUD_IOCTL_TYPE_URGENT(sys),(index),size)
#define LUD_IOCTL_REQUEST_URGENT(sys,index,size) LUD_IOCTL_REQUEST(LUD_IOCTL_TYPE_URGENT(sys),(index),size)
#define LUD_IOCTL_COMMAND_URGENT_0(sys,index) LUD_IOCTL_COMMAND_0(LUD_IOCTL_TYPE_URGENT(sys),(index))
#define LUD_IOCTL_REQUEST_URGENT_0(sys,index) LUD_IOCTL_REQUEST_0(LUD_IOCTL_TYPE_URGENT(sys),(index))


#ifdef __TCS__
#ifndef LUD_PORT_AND_NODE_TYPEDEF_DONE
#define LUD_PORT_AND_NODE_TYPEDEF_DONE
/**
 * An endpoint for recieving data from nodes.
 */
typedef struct LN_PORT LUD_PORT;

/**
 * A node.
 */
typedef struct LN_ENTRY LUD_NODE;
#endif /* ndef LUD_PORT_AND_NODE_TYPEDEF_DONE */
#endif /* def __TCS__ */

#if defined(__KERNEL__) || defined(__TCS__)

typedef struct LUD_REPLY_ {
	int cpu;
	int pointer;
} LUD_REPLY;

/* These should fit in 16 bits */
#define LUD_REPLY_CPU_NONE  0xffff /**< No CPU.       */
#define LUD_REPLY_CPU_HOST  0xfffe /**< The host.     */
#define LUD_REPLY_CPU_LOCAL lud_cpu_id	/* the local tm */

#define LUD_REPLY_INITIALIZER { LUD_REPLY_CPU_NONE, 0 }

#define MAX_COM_ARG_STRING 32
/**
 * A comand.  This is the basic unit of Luddite communications.
 */
typedef struct tmcommand {
    unsigned int      command; /**< The command ID  */
    LUD_REPLY         reply;   /**< Information used to send a reply */
    int               arg0;    /**< First argument  */
    int               arg1;    /**< Second argument */
    int               arg2;    /**< Third argument  */
    int               arg3;    /**< Fourth argument */
    int               ref;     /**< Reference count - do not access directly. */
/* On Linux, kludge this */
#ifdef __TCS__
    LUD_NODE*         via;     /**< Source node pointer */
#else /* ifndef __TCS__ */
    int               via;     /**< Source node pointer. (Really a LUD_NODE *) */
#endif /* ndef __TCS__ */

    int               from;    /**< Source node handle */
    struct tmcommand* next;    /**< Used if this is stored in a linked list */
    unsigned int      sanity ;
    unsigned char     args[MAX_COM_ARG_STRING+1];
} LUD_COMMAND ;

/* the number of cache rows used per comvec entry */
#define LUD_COMVEC_C_ROWS 2
/*
 *  The following structure needs to be a multiple of 64 bytes in size.
 *  We added 4 bytes padding (major_pad) after field major for 32 bit
 *  host and target systems. For 64 bit hosts (e.g. sparc) GCC adds
 *  4 bytes padding after field major, so we don't use field major_pad.
 */
typedef struct tmcomvec {
	volatile unsigned int	major;
#ifndef __sparc__
	char major_pad[4] ;	/* Sparc 64 kernel silently adds 4 bytes pad */
#endif
	volatile LUD_COMMAND	com;
	unsigned char	pad[(64*LUD_COMVEC_C_ROWS)-sizeof(LUD_COMMAND)-8];
} LUD_COMVEC ;


#define LUD_SYSTEM_MAJOR	1
#define LUD_LOADER_MAJOR	2

#endif /* defined(__KERNEL__) || defined(__TCS__) */

#define LUD_DEF_PRI 120

#define LUD_SYS_NOOP	0

/* used for basic luddite commands */
#define LUD_SYSTEM_ID '4'

/* used for "extra" generic av commands */
#define LUD_AV_ID '5'

#if defined(__KERNEL__) || defined(__TCS__)

#define LUD_SYS_PRINTK		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 1)
#define LUD_SYS_READ		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 2)
#define LUD_SYS_CLOSE		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 3)
#define LUD_SYS_REQUEST_ACK	LUD_IOCTL_CMD(LUD_SYSTEM_ID, 4)
#define LUD_SYS_CLEANUP		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 5)
#define LUD_SYS_REGISTER	LUD_IOCTL_CMD(LUD_SYSTEM_ID, 6)
#define LUD_SYS_XFER_BUFFER	LUD_IOCTL_CMD(LUD_SYSTEM_ID, 7)
#define LUD_SYS_BUFFER		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 8)
#define LUD_SYS_DONE		LUD_IOCTL_CMD(LUD_SYSTEM_ID, 9)
#define LUD_SYS_NEW_NODE	LUD_IOCTL_CMD(LUD_SYSTEM_ID,10)
#define LUD_SYS_DEL_NODE	LUD_IOCTL_CMD(LUD_SYSTEM_ID,11)
#define LUD_SYS_LOAD		LUD_IOCTL_CMD(LUD_SYSTEM_ID,12)
#define LUD_SYS_UNLOAD		LUD_IOCTL_CMD(LUD_SYSTEM_ID,13)
#define LUD_SYS_LOAD_ACK	LUD_IOCTL_CMD(LUD_SYSTEM_ID,14)
#define LUD_SYS_INIT_ACK	LUD_IOCTL_CMD(LUD_SYSTEM_ID,15)
#define LUD_SYS_CLEAN_ACK	LUD_IOCTL_CMD(LUD_SYSTEM_ID,16)
#define LUD_SYS_UNLOAD_ACK	LUD_IOCTL_CMD(LUD_SYSTEM_ID,17)
#define LUD_SYS_PRELOAD		LUD_IOCTL_CMD(LUD_SYSTEM_ID,18)
#define LUD_SYS_PAGE_SIZE	LUD_IOCTL_CMD(LUD_SYSTEM_ID,19)
#define LUD_SYS_TASKS    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,20)
#define LUD_SYS_MEMORY    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,21)
#define LUD_SYS_PROPERTIES 	LUD_IOCTL_CMD(LUD_SYSTEM_ID,22)
#define LUD_SYS_OPEN_CHANNEL	LUD_IOCTL_CMD(LUD_SYSTEM_ID,23)
#define LUD_SYS_READ_CHANNEL	LUD_IOCTL_CMD(LUD_SYSTEM_ID,24)
#define LUD_SYS_WRITE_CHANNEL	LUD_IOCTL_CMD(LUD_SYSTEM_ID,25)
#define LUD_SYS_CLOSE_CHANNEL	LUD_IOCTL_REQ(LUD_SYSTEM_ID,26)
#define LUD_SYS_GET_BLOCKSIZE	LUD_IOCTL_CMD(LUD_SYSTEM_ID,27)
#define LUD_SYS_OPEN_CHANNEL_D	LUD_IOCTL_CMD_URGENT(LUD_SYSTEM_ID,28)
#define LUD_SYS_READ_CHANNEL_D	LUD_IOCTL_CMD_URGENT(LUD_SYSTEM_ID,29)
#define LUD_SYS_WRITE_CHANNEL_D	LUD_IOCTL_CMD_URGENT(LUD_SYSTEM_ID,30)
#define LUD_SYS_CLOSE_CHANNEL_D	LUD_IOCTL_CMD_URGENT(LUD_SYSTEM_ID,31)
#define LUD_SYS_POOLS    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,32)
#define LUD_SYS_QUEUES    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,33)
#define LUD_SYS_ADD_TARGET    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,34)
#define LUD_SYS_DEL_TARGET    	LUD_IOCTL_CMD(LUD_SYSTEM_ID,35)
#define LUD_SYS_NODE_BIND	LUD_IOCTL_REQ(LUD_SYSTEM_ID,36)
#define LUD_SYS_NODE_GETB	LUD_IOCTL_REQ(LUD_SYSTEM_ID,37)
#define LUD_SYS_NODE_FREEB	LUD_IOCTL_REQ(LUD_SYSTEM_ID,38)
#define LUD_SYS_NODE_REFB	LUD_IOCTL_REQ(LUD_SYSTEM_ID,39)
#define LUD_SYS_SET_TIME	LUD_IOCTL_CMD(LUD_SYSTEM_ID,40)
#define LUD_SYS_LUDDITE_STARTED LUD_IOCTL_CMD(LUD_SYSTEM_ID,41)
#define LUD_SYS_NODE_LISTEN	LUD_IOCTL_REQ(LUD_SYSTEM_ID,42)
#define LUD_SYS_NODE_FORGET	LUD_IOCTL_REQ(LUD_SYSTEM_ID,43)
#define LUD_SYS_NODE_FORWARD	LUD_IOCTL_REQ(LUD_SYSTEM_ID,44)
#define LUD_SYS_NODE_PUSH	LUD_IOCTL_REQ(LUD_SYSTEM_ID,45)
#define LUD_SYS_ISRS		LUD_IOCTL_CMD(LUD_SYSTEM_ID,47)
#define LUD_SYS_SET_DEBUG_EVENT	LUD_IOCTL_CMD(LUD_SYSTEM_ID,48)
#define LUD_SYS_GET_DEBUG_EVENT	LUD_IOCTL_REQ(LUD_SYSTEM_ID,49)
#define LUD_SYS_ROUNDTRIP	LUD_IOCTL_REQ(LUD_SYSTEM_ID,50)

/**
 * Open a connection to a node that was created with #LUD_NODE_SERVER.
 * See #LUD_NODE_SERVER for details.
 *
 * Source: Server node.
 *
 * Args: None
 *
 * Reply:
 * args[0] = Node handle, or -1 to reject the connection.
 */
#define LUD_SYS_NEW_CONNECTION		LUD_IOCTL_REQ(LUD_SYSTEM_ID,46)

#endif /* defined(__KERNEL__) || defined(__TCS__) */

/**
 * ioctl to get the current scr.
 * Valid on mpg-*
 *
 * Returns the SCR, or LUD_INVALID_PTS if none.
 */
#define LUD_SYS_GET_SCR		LUD_IOCTL_REQUEST(LUD_AV_ID,1,int[2])

#define LUD_SYS_SET_SCR		LUD_IOCTL_COMMAND(LUD_AV_ID,2,int[2])

/**
 * ioctl to flush any write buffers.
 * Valid on any node.
 */
#define LUD_SYS_FLUSH	LUD_IOCTL_COMMAND_0(LUD_AV_ID,3)


/**
 * Indicates a co-ordinate is not to be animated.
 * Used by LUD_VIDEO_ZOOM.
 */
#define LUD_VIDEO_IGNORE_VAL	10000

/**
 * Indicates a co-ordinate is not to be animated.
 * Used by LUD_VIDEO_ZOOMWINDOW.
 */
#define LUD_VIDEO_WINDOW_IGNORE_VAL ((unsigned)0x01ffffff)


/**
 * ioctl to set the video size.  Valid on vo*-*
 *
 * args[0] = width
 * args[1] = height
 *
 * width = height = 0 is a special case meaning unscaled video.
 */
#define LUD_VIDEO_SET_SIZE	LUD_IOCTL_COMMAND(LUD_AV_ID,20,int[2])

/**
 * ioctl to set the video position.  Valid on vo*-*
 *
 * args[0] = xpos
 * args[1] = ypos
 */
#define LUD_VIDEO_SET_POS	LUD_IOCTL_COMMAND(LUD_AV_ID,21,int[2])

/**
 * ioctl to set the video source window.  Valid on vo*-*
 *
 * Note that the arguments are specified as floats in the range 0.0 to 1.0
 * inclusive.
 *
 * args[0] = xpos
 * args[1] = ypos
 * args[2] = width
 * args[3] = height
 */
#define LUD_VIDEO_SET_WINDOW	LUD_IOCTL_COMMAND(LUD_AV_ID,22,float[4])

/**
 * ioctl to set the video visibility.  Valid on vo*-*
 *
 * args[0] = nonzero to show, zero to hide.
 */
#define LUD_VIDEO_SET_VISIBLE		LUD_IOCTL_COMMAND(LUD_AV_ID,23,int)

/**
 * ioctl to animate the video resizing and/or repositioning.  Valid on vo*-*
 *
 * args[0] = (xpos  << 16) + ypos
 * args[1] = (width << 16) + height
 * args[2] = (number of frames to animate over) * (block ? -1 : 1)
 *
 * Default is to acknowledge immediately and run asynchronously.
 * To block until the animation is complete, negate args[2].
 *
 * If you do not want to animate a paramater, set it to LUD_VIDEO_IGNORE_VAL.
 * This applies to xpos, ypos, width, and height.
 */
#define LUD_VIDEO_ZOOM		LUD_IOCTL_REQUEST(LUD_AV_ID,24,int[3])

/**
 * ioctl to animate the video source window resizing and/or repositioning.  Valid on vo*-*
 *
 * Note that the co-ordinates are specified as fixed-point numbers in the range
 * 0.0 to 1.0 inclusive.  There are seven padding bits (set to zeros), one bit
 * before the fixed  binary point, then 24 fractional bits.  If you do not want
 * to animate a co-ordinate, set it to LUD_VIDEO_WINDOW_IGNORE_VAL (all non-padding
 * bits set to ones).
 *
 * The number of frames to animate over is an unsigned 14-bit quantity.
 *
 * Paramaters:
 * args[0] = xpos   | (block ? (1<<31) : 0)
 * args[1] = ypos
 * args[2] = width  | (((numframes >> 7  ) << 25) & 0xfe000000)
 * args[3] = height | (((numframes & 0x7f) << 25) & 0xfe000000)
 *
 * Default is to acknowledge immediately and run asynchronously.
 * To block until the animation is complete, set the MSB of args[0].
 */
#define LUD_VIDEO_ZOOMWINDOW	LUD_IOCTL_REQUEST(LUD_AV_ID,25,int[4])

#if defined(__KERNEL__) || defined(__TCS__)

#define LUD_VIDEO_IN_FIELD	LUD_IOCTL_CMD(LUD_AV_ID,26)
#define LUD_VIDEO_OUT_FIELD	LUD_IOCTL_CMD(LUD_AV_ID,27)

#endif /* defined(__KERNEL__) || defined(__TCS__) */

/**
 * Marker used to represent an invalid time/lack of scr when used
 * as the high 32 bits of the 64 bit time.
 */
#define LUD_NO_SCR 0xffffffff

/**
 * ioctl to get the video display size.  Valid on vo*-*
 *
 * On return:
 * args[0] = width
 * args[1] = height
 *
 */
#define LUD_VIDEO_GET_DISPLAY_SIZE	LUD_IOCTL_REQUEST(LUD_AV_ID,19,int[2])

/**
 * ioctl to get the video size.  Valid on vo*-*
 *
 * On return:
 * args[0] = width
 * args[1] = height
 *
 * width = height = 0 is a special case meaning unscaled video.
 */
#define LUD_VIDEO_GET_SIZE	LUD_IOCTL_REQUEST(LUD_AV_ID,28,int[2])

/**
 * ioctl to get the video position.  Valid on vo*-*
 *
 * On return:
 * args[0] = xpos
 * args[1] = ypos
 */
#define LUD_VIDEO_GET_POS	LUD_IOCTL_REQUEST(LUD_AV_ID,29,int[2])

/**
 * ioctl to get the video source window.  Valid on vo*-*
 *
 * On return:
 * args[0] = xpos
 * args[1] = ypos
 * args[2] = width
 * args[3] = height
 *
 * width = height = 0 is a special case meaning the entire video frame.
 */
#define LUD_VIDEO_GET_WINDOW	LUD_IOCTL_REQUEST(LUD_AV_ID,30,int[4])

/**
 * ioctl to get the video visibility.  Valid on vo*-*
 *
 * On return:
 * args[0] = nonzero to show, zero to hide.
 */
#define LUD_VIDEO_GET_VISIBLE		LUD_IOCTL_REQUEST(LUD_AV_ID,31,int)

/**
 * ioctl to set the video target.  Valid on vo*-*
 *
 * args[0] = xpos
 * args[1] = ypos
 * args[2] = width
 * args[3] = height
 *
 * width = height = 0 is a special case meaning unscaled video.
 */
#define LUD_VIDEO_SET_TARGET	LUD_IOCTL_COMMAND(LUD_AV_ID,32,int[4])

/**
 * ioctl to get the video target.  Valid on vo*-*
 *
 * On return:
 * args[0] = xpos
 * args[1] = ypos
 * args[2] = width
 * args[3] = height
 *
 * width = height = 0 is a special case meaning unscaled video.
 */
#define LUD_VIDEO_GET_TARGET	LUD_IOCTL_REQUEST(LUD_AV_ID,33,int[4])

/**
 * ioctl to get the output layer for a video device.
 * Valid on mpv-*, mpg-*, vo*-*.
 * On mpa-* and ao*-*, it will work but return -1,-1,-1.
 *
 * On return:
 * args[0] = output device index
 * args[1] = output layer index
 * args[2] = video-for-linux device index, or -1 for none
 *
 * Use these numbers to construct a device name of the form
 * /dev/luddite/TTT/voDDD-LLL
 * where TTT is the index of the TriMedia you did the ioctl on,
 * DDD is args[0] and LLL is args[1].
 *
 * Or use these numbers to construct a device name of the form:
 * /dev/v4l/video/videoNNN
 * where NNN is args[2].
 */
#define LUD_VIDEO_GET_LAYER	LUD_IOCTL_REQUEST(LUD_AV_ID,34,int[3])


/**
 * ioctl to set the video background color.  This is a per-video-device
 * setting, but since the video device nodes are not visible to Linux
 * you use this ioctl on a layer instead.  Valid on vo*-*
 *
 * args[0] = red << 16 + green << 8 + blue
 *
 * red, green, blue are all in the range [0, 255].
 *
 * @todo FIXME add LUD_VIDEO_GET_BACKGROUND - need YUV to RGB conversion.
 */
#define LUD_VIDEO_SET_BACKGROUND	LUD_IOCTL_COMMAND(LUD_AV_ID,35,int[1])




/**
 * Command to set the video-for-Linux device for a video out device.
 * Do not call from userspace without a good reason.  Valid on vo*-*.
 *
 * Param:
 * args[0] = video-for-linux device index.
 *
 * @internal
 */
#define LUD_VIDEO_SET_V4L_DEVICE	LUD_IOCTL_COMMAND(LUD_AV_ID,36,int[1])




/**
 * ioctl to start or stop pause (freeze-frame) mode.
 * Valid on vo*-*
 *
 * args[0] = nonzero to pause (freeze-frame), zero for normal playback.
 */
#define LUD_VIDEO_SET_PAUSED	LUD_IOCTL_COMMAND(LUD_AV_ID,37,int[1])


/**
 * ioctl to test if in pause (freeze-frame) mode.
 * Valid on vo*-*
 *
 * On return:
 * args[0] = nonzero if paused (freeze-frame), zero if normal playback.
 */
#define LUD_VIDEO_GET_PAUSED	LUD_IOCTL_REQUEST(LUD_AV_ID,38,int[1])

#ifdef __TCS__
/**
 * Internal only call to get the output layer pointer for a video device.
 * Valid on mpv-*, mpg-*, vo*-*.
 * On mpa-* and ao*-*, it will work but return NULL.
 *
 * Intended for use on the TriMedia only - not usable from Linux userspace,
 * and probably useless from Linux kernelspace.
 *
 * @internal
 */
#define LUD_VIDEO_GET_LAYER_INTERNAL	LUD_IOCTL_REQ(LUD_AV_ID,39)
#endif /* def __TCS__ */

/**
 * Flush a video decoder.
 * Valid on mpg-*, mpv-*.
 *
 * This will cause the decoder to enter free-running mode (i.e.
 * it will ignore SCR) until it has processed all pending data.
 * It will then optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0] = new SCR low 32 bits,
 * args[1] = new SCR high bit, or LUD_NO_SCR to leave it alone.
 */
#define LUD_VIDEO_FLUSH	LUD_IOCTL_COMMAND(LUD_AV_ID,40,int[2])

#ifdef __TCS__
/**
 * Finished flushing a video decoder.
 * Valid on mpg-*, mpv-*.
 *
 * Used internally by lud_vo_layer_flush()
 *
 * This will optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0] = new SCR, or LUD_INVALID_DTS to leave it alone.
 * args[1] = Pointer to the layer that is being flushed.
 *
 * @internal
 */
#define LUD_VIDEO_FLUSH_DONE	LUD_IOCTL_COMMAND(LUD_AV_ID,41,int[2])
#endif

/**
 * Discard queued data in a video decoder.
 * Valid on mpg-*, mpv-*.
 *
 * This will cause the decoder to throw away all pending data.
 * It will then optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0] = new SCR low 32 bits,
 * args[1] = new SCR high bit, or LUD_NO_SCR to leave it alone.
 */
#define LUD_VIDEO_DISCARD	LUD_IOCTL_COMMAND(LUD_AV_ID,42,int)

#ifdef __TCS__
/**
 * Finished discarding queued data in a video decoder.
 * Valid on mpg-*, mpv-*.
 *
 * Used internally by lud_vo_layer_discard()
 *
 * This will then optionally set the SCR to the specified value,
 * and automatically return to normal playback mode.
 *
 * args[0] = new SCR, or LUD_INVALID_DTS to leave it alone.
 * args[1] = Pointer to the layer that is being flushed
 *
 * @internal
 */
#define LUD_VIDEO_DISCARD_DONE 	LUD_IOCTL_COMMAND(LUD_AV_ID,43,int[2])
#endif


/**
 * ioctl to get the depth of a layer.
 * Valid on vo*-*
 *
 * Position 0 is the front, higher numbers are towards the back.
 * On error, returns -1 (should never happen).
 *
 * On return:
 * args[0] = depth of this layer.
 */
#define LUD_VIDEO_GET_DEPTH	LUD_IOCTL_REQUEST(LUD_AV_ID,44,int[1])


/**
 * ioctl to raise or lower a layer so it is at the specified depth.
 * Valid on vo*-*
 *
 * Position 0 is the front, higher numbers are towards the back.
 * If the specified position is out of bounds, it will be clipped
 * to the valid range.
 *
 * E.g. pass zero to move a layer to the front, or
 *      MAX_INT to move a layer to the back.
 *
 * args[0] = desired depth of the layer.
 */
#define LUD_VIDEO_SET_DEPTH	LUD_IOCTL_COMMAND(LUD_AV_ID,45,int[1])


/**
 * ioctl to raise or lower a layer by a specified amount.
 * Valid on vo*-*
 *
 * Negative numbers move the layer towards the front, positive
 * numbers move the layer towards the back.
 *
 * If the specified delta leads to a position which is out of bounds,
 * it will be clipped to the valid range.
 *
 * E.g. pass -1 to move the layer one step towards the front, or
 *      pass +1 to move the layer one step towards the back.
 *
 * args[0] = desired change in the depth of the layer.
 */
#define LUD_VIDEO_SET_DEPTH_RELATIVE	LUD_IOCTL_COMMAND(LUD_AV_ID,46,int[1])

/**
 * ioctl to set the aspect ratio of the image data for this layer
 * the two parameters are the aspect ratio expressed as two integers.
 * The first refers to the width and the second to the height. I.e for a 4:3
 * aspect ratio, the values would be four and three respectively.
 * This ratio is used to calculate window sizes when video layers are in forced aspect
 * mode.
 */
#define LUD_VIDEO_SET_ASPECT		LUD_IOCTL_COMMAND(LUD_AV_ID,47,int[2])
/**
 * ioctl to set the aspect ratio of the display device
 * the two parameters are the aspect ratio expressed as two integers.
 * The first refers to the width and the second to the height. I.e for a 4:3
 * aspect ratio, the values would be four and three respectively.
 * This ratio is used to calculate window sizes when video layers are in forced aspect
 * mode.
 */
#define LUD_VIDEO_SET_DISPLAY_ASPECT	LUD_IOCTL_COMMAND(LUD_AV_ID,48,int[2])
/**
 * ioctl to return the current aspect ratio for this video layer.
 * the value is returned as a float, and is width/height.
 */
#define LUD_VIDEO_GET_ASPECT		LUD_IOCTL_REQUEST(LUD_AV_ID,49,float[1])
/**
 * Return the current aspect ratio modifier for the display. This is not the
 * value specified by LUD_VIDEO_SET_DISPLAY_ASPECT, but that modified by a
 * factor of 4/3.
 */
#define LUD_VIDEO_GET_DISPLAY_ASPECT	LUD_IOCTL_REQUEST(LUD_AV_ID,50,float[1])

#define LUD_VIDEO_FORCE_ASPECT		LUD_IOCTL_COMMAND(LUD_AV_ID,51,int)

#define LUD_VIDEO_GET_FLAGS		LUD_IOCTL_COMMAND(LUD_AV_ID,52,int)


/*
 * For backwards compatibility only.
 * Use LUD_VIDEO_SET_VISIBLE instead (identical ioctl number and usage,
 * but more descriptive name).
 */
/* #define LUD_VIDEO_SHOW LUD_VIDEO_SET_VISIBLE */


/**
 * Set the number of channels in the audio stream.
 *
 * args[0] = Number of channels - must be 1 or 2.
 *
 * @internal
 */
#define LUD_AUDIO_SET_CHANNELS	LUD_IOCTL_COMMAND(LUD_AV_ID,70,int)

/**
 * Set the sample frequency of the audio stream.
 *
 * args[0] = Samples per second.
 *
 * @internal
 */
#define LUD_AUDIO_SET_RATE	LUD_IOCTL_COMMAND(LUD_AV_ID,71,int)

/**
 * Set the current volume.
 * Valid on ao*-*.
 *
 * Parameters:
 * args[0] = left channel volume (0=mute, 256=max)
 * args[1] = right channel volume (0=mute, 256=max)
 *
 * @see LUD_AUDIO_GET_VOLUME
 */
#define LUD_AUDIO_SET_VOLUME	LUD_IOCTL_COMMAND(LUD_AV_ID,72,int[2])

#if defined(__KERNEL__) || defined(__TCS__)

#define LUD_AUDIO_IN_BUFFER	LUD_IOCTL_CMD(LUD_AV_ID,73)
#define LUD_AUDIO_OUT_BUFFER	LUD_IOCTL_CMD(LUD_AV_ID,74)

#endif /* defined(__KERNEL__) || defined(__TCS__) */

/**
 * ioctl to get the output layer for an audio device.
 * Valid on mpa-*, mpg-* and ao*-*.
 * On mpv-* and vo*-*, it will work but return -1,-1.
 *
 * On return:
 * args[0] = output device index.
 * args[1] = output layer index.
 *
 * Use these numbers to construct a device name of the form
 * /dev/luddite/TTT/aoDDD-LLL
 * where TTT is the index of the TriMedia you did the ioctl on,
 * DDD is args[0] and LLL is args[1].
 */
#define LUD_AUDIO_GET_LAYER	LUD_IOCTL_REQUEST(LUD_AV_ID,75,int[2])


#ifdef __TCS__
/**
 * Internal only call to get the output layer pointer for an audio device.
 * Valid on mpa-*, mpg-* and ao*-*.
 * On mpv-* and vo*-*, it will work but return NULL.
 *
 * Intended for use on the TriMedia only - not usable from Linux userspace,
 * and probably useless from Linux kernelspace.
 *
 * @internal
 */
#define LUD_AUDIO_GET_LAYER_INTERNAL	LUD_IOCTL_REQ(LUD_AV_ID,76)
#endif /* def __TCS__ */


/**
 * Flush an audio decoder.
 * Valid on mpg-*, mpa-*.
 *
 * This will cause the decoder to enter free-running mode (i.e.
 * it will ignore SCR) until it has processed all pending data.
 * It will then optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0] = new SCR low word.
 * args[1] = new SCR high bit  or LUD_NO_SCR to leave it alone.
 */
#define LUD_AUDIO_FLUSH	LUD_IOCTL_COMMAND(LUD_AV_ID,77,int[2])

#ifdef __TCS__
/**
 * Finished flushing an audio decoder.
 * Valid on mpg-*, mpa-*.
 *
 * Used internally by lud_ao_layer_flush()
 *
 * This will optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0/1] = new SCR, or LUD_INVALID_DTS to leave it alone.
 * args[2] = Pointer to the layer that is being flushed.
 *
 * @internal
 */
#define LUD_AUDIO_FLUSH_DONE	LUD_IOCTL_COMMAND(LUD_AV_ID,78,int[3])
#endif

/**
 * Discard queued data in an audio decoder.
 * Valid on mpg-*, mpa-*.
 *
 * This will cause the decoder to throw away all pending data.
 * It will then optionally set the SCR to the specified value,
 * and return to normal playback mode.
 *
 * args[0] = new SCR low 32 bits,
 * args[1] = new SCR high bit, or LUD_NO_SCR to leave it alone.
 */
#define LUD_AUDIO_DISCARD	LUD_IOCTL_COMMAND(LUD_AV_ID,79,int[2])

#ifdef __TCS__
/**
 * Finished discarding queued data in a video decoder.
 * Valid on mpg-*, mpa-*.
 *
 * Used internally by lud_ao_layer_discard()
 *
 * This will then optionally set the SCR to the specified value,
 * and automatically return to normal playback mode.
 *
 * args[0/1] = new SCR, or LUD_INVALID_DTS to leave it alone.
 * args[2] = Pointer to the layer that is being flushed
 *
 * @internal
 */
#define LUD_AUDIO_DISCARD_DONE 	LUD_IOCTL_COMMAND(LUD_AV_ID,80,int[3])
#endif

/**
 * Get the current volume.
 * Valid on ao*-*.
 *
 * On return:
 * args[0] = left channel volume (0=mute, 256=max),
 * args[1] = right channel volume (0=mute, 256=max).
 *
 * @see LUD_AUDIO_SET_VOLUME
 */
#define LUD_AUDIO_GET_VOLUME	LUD_IOCTL_COMMAND(LUD_AV_ID,81,int[2])


/*
 * placeholder for testing AV cleanup command
 */
#define LUD_AV_CLEANUP	LUD_IOCTL_COMMAND_URGENT(LUD_AV_ID,100,int)

#define LUD_AV_SYNC_OFFSET LUD_IOCTL_COMMAND(LUD_AV_ID,101,int[2])
#define LUD_AV_SYNC_AT LUD_IOCTL_COMMAND(LUD_AV_ID,102,int[2])

#define LUD_AV_FLUSH	LUD_IOCTL_COMMAND_URGENT(LUD_AV_ID,103,int)
#define LUD_AV_DISCARD	LUD_IOCTL_COMMAND_URGENT(LUD_AV_ID,104,int)
#define LUD_AV_CONTINUE LUD_IOCTL_COMMAND(LUD_AV_ID,105,int)

#define LUD_AV_SCALE	LUD_IOCTL_REQUEST(LUD_AV_ID,106,int[3])
#define LUD_H264_FILTER	LUD_IOCTL_REQUEST(LUD_AV_ID,107,int[3])

#ifdef __TCS__
/**
 * Pop the last strategy setting from the strategy stack
 * Used internally by the AV system
 * args[0] = Pointer to the layer
 */
#define LUD_AVTIME_STRATEGY_JUMP LUD_IOCTL_COMMAND(LUD_AV_ID,107,int)

#endif


/**
 * @}
 */

#define LUD_LOAD_BUSY		-1
#define LUD_LOAD_FILEERROR	-2
#define LUD_LOAD_SYSERROR	-3
#define LUD_LOAD_LOGICERROR	-4
#define LUD_LOAD_TIMEOUT		-5
#define LUD_LOAD_INITERROR	-6

#ifdef __KERNEL__

typedef enum {
  LUD_UNDEFINED = 0,
  LUD_RESET   = 1,
  LUD_RUNNING = 2,
  LUD_LUDDITE_STARTING = 3,
  LUD_LUDDITE = 4,
  LUD_CRASHED
} LUD_STATUS ;

#ifndef CONFIG_SYSFS
#include <linux/devfs_fs_kernel.h>
#endif
#include <linux/module.h>

struct LUD_DEV_LINK_S;

typedef struct LUD_DEV_S {
  unsigned char*  name;
  unsigned int	  lud_type;
  unsigned long	  target_comm_reg;
  unsigned long	  host_comm_reg;
  unsigned int	  target_int_vec;
  void		  (*init)(struct LUD_DEV_S*);
  void		  (*start)(struct LUD_DEV_S*);
  void		  (*reset)(struct LUD_DEV_S*);
  void		  (*send_command)(struct LUD_DEV_LINK_S*,int,int,int,int,int);
  int		  (*send_request)(struct LUD_DEV_LINK_S*,int,int,int,int,int);
  void		  (*send_ack)(struct LUD_DEV_LINK_S*,LUD_REPLY,int);
  unsigned int	  freq;
  unsigned long	  mmio_log ;
  unsigned long   mmio_offset;
  unsigned long   mmio_phy ;
  unsigned long   sdram_log ;
  unsigned long   sdram_phy ;
  unsigned int    sdram_size ;
  unsigned long   irq ;
  int             major ;
  int             minor ;
  unsigned long   target_comm_addr;
  unsigned long   host_comm_addr;
  unsigned long   target_comm_vec;
  unsigned long   host_comm_vec;
  unsigned long   status;
  unsigned long   scratch;
    struct proc_dir_entry* proc_root;
#ifdef CONFIG_SYSFS
  struct cdev	cdev;
  struct device	ldev;
  struct device* parent;
  struct class_device *classdev;
#else
    devfs_handle_t devfs_directory;
    devfs_handle_t devfs_handle;
#endif

  struct module *driver_module;
  LUD_STATUS	  state;
  wait_queue_head_t start_queue;
  unsigned int    flags;
  unsigned long   comvec;
  unsigned long	  ndkbis;
} LUD_DEV ;

typedef enum {
  LUD_LINK_UNDEFINED = 0,
  LUD_LINK_SETUP,
  LUD_LINK_CRASHED
} LUD_LINK_STATUS ;

typedef struct {
  LUD_STATUS   status ;
  char *          progFile ;
  LUD_LINK_STATUS  linkStatus ;
  int             inUse ;
  int             stdioInUse ;
} LUD_DEV_STATUS ;

/***** Definitions *****/

#define LUD_NAME        "Luddite"

#define LUD_MAJOR       38


/** TM Specific shouldn't be here **/

#define TM_MMIO_SIZE  0x200000

#include <asm/atomic.h>
#include <linux/poll.h>

typedef struct LUD_DEV_LINK_S {
	unsigned int		major;
	unsigned int		minor;
	int         		retval0;
	int         		status;
	atomic_t    		freecounter; /* Initially 1, free when it reaches zero. */
	wait_queue_head_t	q;
	LUD_DEV*		dev;
	int         		retval1;
	int         		retval2;
	int         		retval3;
} LUD_DEV_LINK;

/* Defined in lud-core.c */
struct LUD_CHANNEL_T;

/**
 * A one-way communications channel.  May be read or write (but not both).
 * The other end of this channel is an "Xfer" on the target CPU.
 *
 * Modules must only use pointers to this type.  The full definition
 * of the type is only available in lud-core.c.
 */
typedef struct LUD_CHANNEL_T LUD_CHANNEL;

#include <luddite/nodedefs.h>

/**
 * Type for Luddite callback handler function pointers.
 */
typedef void (*lud_handler_func_t)(LUD_COMMAND*,LUD_DEV*);

/**
 * This is the device driver structure representing a LUD_NODE
 * on the host side. A pointer to an instance of this structure is stored
 * as private_data in the linux file structure, and can be accessed by all
 * file operations.
 */
struct LUD_NODE_DEV {
	int               exists;     /**< Nonzero if the node exists. */
	int               state;      /**< What this node is currently open for.
				      Two bits: FREAD and FWRITE.  Must hold
                                      state_lock before modifying this field. */

	int               flags;      /**< Flags set from the TriMedia side when
                                                   this node was created. */
#ifdef CONFIG_SYSFS
	unsigned long*    dev_h;      /**< The handle to this device in devfs.*/
	struct cdev	 cdev;
	struct device    ldev;
	struct class_device    *classdev;
#else
	devfs_handle_t    dev_h;      /**< The handle to this device in devfs.*/
#endif
	char name[LUD_MAX_NODE_NAME_LENGTH]; /**< The node name. */
	LUD_CHANNEL*       read;       /**< The Xfer used for reading from the
                                       TriMedia.  Protected with read_sema. */
	LUD_CHANNEL*       write;      /**< The Xfer used for writing to the
                                        TriMedia.  Protected with write_sema. */
	struct semaphore  read_sema;  /**< Protects the read Xfer.
					   Prevents concurrent read()s. */
	struct semaphore  write_sema; /**< Protects the write Xfer.
                                       Prevents concurrent write()s. */
	lud_handler_func_t handler;    /**< If a Linux-side module has registered
					a message handler, this is it. */
	LUD_DEV_LINK           dev;        /**< The link to the TriMedia. */
	spinlock_t        state_lock; /**< Protects the state field.  Used to
					 prevent concurrent open()s. */
    void*	private_data;
};

#define LUD_REQUEST_WAITING	0
#define LUD_REQUEST_DONE		1

/* Routines exported from base.c */

extern LUD_DEV_LINK* lud_get_node_link(LUD_DEV_LINK*,char*,lud_handler_func_t);
extern LUD_DEV_LINK* lud_get_node_link_from_handle(LUD_DEV_LINK* parent,
		int handle,lud_handler_func_t handler);
extern void lud_free_node_link(LUD_DEV_LINK*);
extern unsigned long lud_remap_addr(LUD_DEV* minor,unsigned long);
extern void lud_send_command(LUD_DEV_LINK*,int,int,int,int,int);
extern int lud_send_request(LUD_DEV_LINK*,int,int,int,int,int);
extern void lud_send_ack(LUD_DEV_LINK*,LUD_REPLY,int);
extern LUD_DEV_LINK* lud_clone_link(LUD_DEV_LINK*);
extern void lud_free_link(LUD_DEV_LINK*);
extern void lud_wakeup(LUD_DEV_LINK*);
extern struct LUD_NODE_DEV* lud_get_node_from_link(LUD_DEV_LINK* l);

/* Routines exported from channels.c */
extern LUD_CHANNEL* lud_new_write_channel(LUD_DEV_LINK*);
extern LUD_CHANNEL* lud_new_read_channel(LUD_DEV_LINK*);
extern void lud_free_channel(LUD_CHANNEL*);

extern int lud_read_channel(LUD_CHANNEL*,unsigned char* b,int n,
			int kernel,int nonblock);
extern int lud_read_channel_buffered(LUD_CHANNEL*,unsigned char* b,int n,
			int kernel,int nonblock);

extern int lud_write_channel(LUD_CHANNEL*,const unsigned char* b,int n,
			int kernel,int nonblock);
extern int lud_write_channel_ex(LUD_CHANNEL*,const unsigned char* b,int n,
			int kernel,int nonblock, int flush);
extern int lud_write_channel_buffered(LUD_CHANNEL*,const unsigned char* b,int n,
			int kernel,int nonblock);
extern int lud_write_channel_buffered_ex(LUD_CHANNEL*,const unsigned char* b,
			int n,int kernel,int nonblock,int flush);
extern int lud_write_channel_flush(LUD_CHANNEL*);

extern unsigned int lud_poll_write_channel(LUD_CHANNEL*,struct file *,
			poll_table*);
extern unsigned int lud_poll_read_channel(LUD_CHANNEL*, struct file *,
			poll_table *);
extern unsigned int lud_wait_read_channel(LUD_CHANNEL* tmc,
			wait_queue_t *waitqueue_entry);
extern unsigned int lud_unwait_channel(LUD_CHANNEL* tmc,
			wait_queue_t *waitqueue_entry);

/* Routines exported from node.c */
extern ssize_t lud_generic_read(LUD_CHANNEL* xfer,struct semaphore * sema,
	struct file * file,       char * buffer, size_t count, loff_t *ppos);
extern ssize_t lud_generic_write(int flush, LUD_CHANNEL * xfer,
	struct semaphore * sema, struct file * file, const char * buffer,
	size_t count, loff_t *ppos);
extern int     lud_generic_ioctl(LUD_DEV_LINK *link, unsigned int cmd,
	unsigned long arg);
extern loff_t  lud_generic_llseek(struct file * file, loff_t off, int whence);

/**
 * Removes the existing devfs entry for the given node, then creates a new
 * entry with the same name, but using the new file_operations.
 * This allows device drivers to replace the linux side functionality
 * of nodes that have automatically been given file system entries.
 * The routine returns the handle of the new entry, or NULL if this fails,
 * or the node didn't have a file system entry in the first place.
 */
#ifdef CONFIG_SYSFS
extern unsigned long* lud_node_new_fops(struct LUD_NODE_DEV* node,
			struct file_operations* fops);
#else
extern devfs_handle_t lud_node_new_fops(struct LUD_NODE_DEV* node,
			struct file_operations* fops);
#endif

/**
 * Put back the original luddite file operations
 */
extern void lud_node_restore_fops(struct LUD_NODE_DEV* node);


#endif /* __KERNEL__ */
#endif /* _LUDDEV_H */
