/*
 * (C) Copyright Cogent Real-Time Systems Inc., 1997-2000.
 *     All rights reserved.
 *
 * This file constitutes a part of the Cascade (TM) C-Language
 * application programming interface.  It is not to be modified.  This
 * file is licensed for the purpose of creating programs that will
 * communicate with Cogent's products, and for no other purpose.
 * Cogent claims no rights in any program created by a party other than
 * Cogent by compiling this file, and accepts no responsibility or
 * liability in such a program.
 *
 * It is illegal for any party other than Cogent to sell the contents of
 * this file, or any part thereof, or to attempt to gain in any way from
 * the transmission of this file.  It is illegal to remove this notice
 * from this file.
 */

/*
* ****************************************************************************
*
*  Filename:     driver.h
*  Description:  Cogent 'standardized' driver header file
*
*  Created:	  
*  Last Updated: March 1 2000
*  Author:		 Andrew Thomas, Manuel Dias, Cogent Real-Time Systems Inc
*
*
* *****************************************************************************
*
*
*/
#ifndef DRIVER_H
#define DRIVER_H

#ifdef __cplusplus
extern "C" {
#endif

#include <cogent/machdep.h>
#include <semaphore.h>
#ifdef __QNXNTO__
#include <hw/pci.h>
#else
#include <sys/pci.h>
#endif

#ifndef STDTOOL_H
#include <cogent/stdtool.h>
#endif

#ifndef IPC_H
#include <cogent/ipc.h>
#define IPC_H
#endif

#ifndef POINT_H
#include <cogent/point.h>
#define POINT_H
#endif	
	
/* ----------------------- ref: dr_phys.c -------------------------------- */

void* DR_MmapPhysical(off_t offset, size_t length);
int   DR_MunmapPhysical(void* start, size_t length);
int	  DR_IoAvailable();

/*============ Generic Driver-specific User Object Prototypes ============== */
/*
*    This structure provides for a set of facilities standard to all drivers
*    as well as containing a driver-specific user-defined object.
*    The generic object provides:
*      - a reply buffer area, available for use by user functions, that is
*        returned as the reply data of synchronous IPC messages.
*    The user must create the driver specific object, and attach it to the
*    generic driver object.
*    The entire object is passed to the driver subsystem via the DR_MainLoop
*    function.
*/
typedef struct 
{
	unsigned	reply_buffer_length;
	char		*reply_buffer;
	IP_Msg		*reply_msg;
	char		*user_data;
#ifdef __QNXNTO__
	struct sigevent	si;
#endif
} DR_stData;

typedef DR_stData *DR_pData;


#define	DR_DATA_REPLY_BUF(obj)		(((DR_pData )(obj))->reply_buffer)
#define DR_DataReplyBuf(obj) 		DR_DATA_REPLY_BUF(obj)

#define DR_DATA_REPLY_BUF_LEN(obj) 	(((DR_pData )(obj))->reply_buffer_length)
#define DR_DataReplyBufLen(obj) 	DR_DATA_REPLY_BUF_LEN(obj)

#define DR_DATA_REPLY_MSG(obj) 		(((DR_pData )(obj))->reply_msg)

#define DR_DATA_USER_OBJ(obj)	 	(((DR_pData )(obj))->user_data)
#define DR_DataUserObj(obj) 		DR_DATA_USER_OBJ(obj)

/*	see methods in dr_setup.c section:
     DR_newData()
	 DR_deleteData()
*/

/* ========== Point Structure and related Definitions ====================== */
#define FIVAL(name)	union { long i; float r;} name;
typedef union { long i; float r; } FIVALUnion_t;

#define FISVAL(name) union { long i; float r; char* s;} name;
#define FISLVAL(name) union { long i; float r; char* s; LL_LIST list;} name;

enum DR_POINT_TYPE
{
	DR_POINT_NO_TYPE=0,
	DR_POINT_STRING=1, DR_POINT_REAL, DR_POINT_INTEGER, DR_POINT_VOID,
	DR_POINT_DIGITAL, DR_POINT_MULTI, DR_POINT_GROUP, DR_POINT_HEARTBEAT,
	DR_POINT_USER_TYPE, DR_POINT_NUM_TYPES
};

typedef struct DR_stPOINT
{
	char		*name;
	char		*address;
	char		*status_tag;
	char		type;
	char		sub_type;
	int			conf;
	
	int			needreport : 1;
	int			reporting : 1;
	int			valid : 1;
	int			writable : 1;
	int			was_written : 1;
	int			write_pending :	1;
	int			write_confirmed : 1;
	int			readable : 1;
	int			was_read : 1;
	int			update_required : 1;
	int			enabled : 1;
	int			driver_status : 1;

	double		cycle_msecs;
	time_t		next_sec;
	time_t		next_nsec;

	struct DR_stPOINT *parent;
	short		nchildren;

	FISLVAL(val);				/* Actual value, may be list of children */
	FISVAL(lastval);			/* Previous value.  Must be leaf point */
	FISVAL(outval);				/* Last write value (could be pending).  Must be leaf point */
	FISVAL(lastoutval);			/* Last write value actually written.  Must be leaf point */
	FIVAL(eumin);				/* Eng. unit min.  Must be numeric point */
	FIVAL(eumax);				/* Eng. unit max.  Must be numeric point */
	FIVAL(rawmin);				/* Raw unit min.  Must be numeric point */
	FIVAL(rawmax);				/* Raw unit max.  Must be numeric point */

	void		*user;
} DR_stPOINT;

typedef DR_stPOINT	*DR_pPOINT;

typedef struct DR_stTYPE
{
	char		*name;
	char		*description;
	int			argc;
	char		**argv;
} DR_stTYPE;

typedef DR_stTYPE	*DR_pTYPE;

typedef struct DR_stDEFN
{
	char		*name;
	char		*value;
} DR_stDEFN;

typedef DR_stDEFN	*DR_pDEFN;


/* =========== Block Structure and related Definitions ===================== */
/*
   Block and BlockSegment Objects:
      used to describe the type of data contained in a memory buffer block.
		  
	  Blocks are tagged with an associated data type, as well as contain a list
	  of segment descriptors.
	  The purpose of this tagging is to facilitate operations on blocks by
	  identifying not just the types of data contained within a block, but
	  also the location and length of segments of such data. In systems that
	  need to, or can be made to, provide data in groups of the same type,
	  this knowledge permits just the required portion of the block to be
	  accessed.
	  
	  A block can contain none or many segments of data, readable or writeable.
	  Each segment of data is a contiguous region, within the block, starting
	  at some offset from the beginning of the block, and continuing for the
	  specified length. However, there is no requirement that a segment actually
	  be filled with the data of the given type, and segments of different types
	  may overlap within a buffer block.  This effectively permits the user to,
	  for example in the case where data of different types alternates within
	  the block, to either define many small non-overlapping segments, or to
	  define larger, overlapping segments, one per type, that will obviously
	  not contain contiguous data of the same type.  The approach depends
	  on how the user intends to apply this block description information.
	  Note that the block type can be any user-defined data attribute, although
	  the DR_POINT_TYPE is typically used.
*/

/* =========== Shared Memory Structure and related Definitions ============= */
/* ----------------------- ref: dr_shmem.c (structure definitions) --------- */
#include <semaphore.h>
	
#define DR_SHMEM_MAX_NAME_LENGTH 32
#define DR_SHMEM_MAX_BASENAME_LENGTH (DR_SHMEM_MAX_NAME_LENGTH - 6) 

typedef struct
{
	char		name [DR_SHMEM_MAX_NAME_LENGTH];
	unsigned	flags;			/* access control flags 					*/
	unsigned	fd;				/* file descriptor for memory				*/

	sem_t		access_sem;		/* primary access semaphore					*/
	sem_t		read_lock_sem;	/* multiple reader access semaphore			*/
	unsigned	num_reading;	/* number of users granted read access		*/

} DR_stShmemCtrl;				/* 72 bytes long */

typedef DR_stShmemCtrl *DR_pShmemCtrl;

#define		DR_SHMEM_FLAG_SHARED	1
#define		DR_SHMEM_FLAG_READING	2
#define		DR_SHMEM_FLAG_WRITING	4

#define		DR_ShmemFlags(ctl)		((ctl).flags)
#define		DR_ShmemPtrFlags(ctl)	((ctl)->flags)
#define 	DR_ShmemShared(ctl)		(((ctl).flags) & DR_SHMEM_FLAG_SHARED)
#define 	DR_ShmemReading(ctl)	(((ctl).flags) & DR_SHMEM_FLAG_READING)
#define 	DR_ShmemWriting(ctl)	(((ctl).flags) & DR_SHMEM_FLAG_WRITING)

/* ----------------------- ref: dr_block.c --------------------------------- */

typedef struct DR_stBlock
{
	unsigned short		dev;		/* device address					*/
	unsigned short		blk_id;		/* block id							*/
	size_t	 			blk_length;	/* total length of the block		*/
	size_t	 			hdr_length;	/* length of this header minus data */
	size_t	 			data_length;/* length of data in bytes			*/
	size_t				active_length;	/* # of bytes 'in use'			*/

	struct DR_stBlockSegment *type; /* list of block type descriptors 	*/

	DR_stShmemCtrl		shmem;		/* shared memory control block		*/
	int					reserved [16];
	
	char				*data_ptr;	/* ptr to data buffer 				*/
	char				data[1];	/* data allocated as part of block	*/

} DR_stBlock;

typedef DR_stBlock *DR_pBlock;

DR_pBlock 		DR_newBlock (unsigned dev, unsigned blk,
							 unsigned length, char * external_data);
DR_pBlock  		DR_deleteBlock (DR_pBlock obj);

#define			DR_BlockData(blk)		  ((blk)->data_ptr)

#define			DR_BlockShmem(blk) 		  ((blk)->shmem)
#define			DR_BlockShmemPtr(blk) 	  (&DR_BlockShmem(blk))
#define			DR_BlockShmemFlags(blk)	  (((blk)->shmem).flags)
#define			DR_BlockShmemShared(blk)  (DR_ShmemShared(DR_BlockShmem(blk)))
#define			DR_BlockShmemReading(blk) (DR_ShmemReading(DR_BlockShmem(blk)))
#define			DR_BlockShmemWriting(blk) (DR_ShmemWriting(DR_BlockShmem(blk)))
#define			DR_BlockShmemName(blk) 	  (DR_BlockShmem(blk).name)

DR_pBlock 	DR_ShareBlock (char *name, DR_pBlock block, unsigned oflags);
DR_pBlock 	DR_UnshareBlock (DR_pBlock block);
DR_pBlock 	DR_AttachSharedBlock (char * name, unsigned mode);
DR_pBlock 	DR_CloseSharedBlock (DR_pBlock shmemblk);

/* ------------------- ref: dr_shmem.c  (functions) ----------------------- */
						   
int		 	DR_AccessShmemWrite (DR_pBlock shmemblk);
int	 		DR_ReleaseShmemWrite (DR_pBlock shmemblk);
int	 		DR_AccessShmemRead (DR_pBlock shmemblk);
int	 		DR_ReleaseShmemRead (DR_pBlock shmemblk);
int	 		DR_ReleaseShmem (DR_pBlock shmemblk);
int	 		DR_ReadShmem (DR_pBlock shmemblk, unsigned offs,
						  size_t length, void *data);
int	 		DR_WriteShmem (DR_pBlock shmemblk, unsigned offs,
						   size_t length, void *data);

/* ----------------------- ref: dr_blkseg.c -------------------------------- */
/*
   BlockSegment Object: defines a segment descriptor.
   --------------------
*/

typedef struct DR_stBlockSegment
{
	unsigned short		dev, id;		/* reference dev:blk_id for segment	*/
	unsigned short		type;			/* indicates data type in segment	*/
	unsigned short		readable : 1;	/* segment/type is readable			*/
	unsigned short		writeable : 1;	/* segment/type is writeable		*/
	unsigned short		offset;			/* segment offset into buffer		*/
	unsigned short		size;			/* segment length in # bytes		*/
	struct DR_stBlockSegment *next;		/* support for linked list of tags  */
	
} DR_stBlockSegment;

typedef DR_stBlockSegment *DR_pBlockSegment;

DR_pBlockSegment	DR_newBlockSegment (unsigned short dev, unsigned short id,
										char type);
void		  		DR_deleteBlockSegment (DR_pBlockSegment *obj);
DR_pBlockSegment 	DR_BlockAddSegment (DR_pBlock obj, char type);
DR_pBlockSegment 	DR_BlockRemoveAllSegments (DR_pBlock obj);

/* =========== Error Structure and related Definitions ===================== */
/*                         ref: dr_setup.c                                   */
/*
*	The errorList object provides for an expandable listing of error names.
*
*/
typedef struct
{
	int		num;
	char	*name;
	char	*desc;
} DR_stErrorList;

typedef DR_stErrorList *DR_pErrorList;

ST_STATUS DR_AddErrorNames (DR_pErrorList errors, DR_pErrorList new_errors);
char 	 *DR_ErrorName (DR_pErrorList errlist, int errnum, char **errstr);

extern DR_stErrorList 	DR_ErrorList[];

typedef enum 
{
	DR_ERRORS = 5000,
	DR_ERR_NO_USER_OBJECT, DR_ERR_BAD_LICENSE,
	DR_ERR_INSUF_PARMS, DR_ERR_CMD_INVALID,
	DR_ERR_NO_NAMESERVER, DR_ERR_ATTACH_TASKNAME, DR_ERR_ATTACH_NAMESERVER,
	DR_ERR_DEV_INVALID, DR_ERR_DEV_IO_FAILURE, DR_ERR_DEV_IO_FAILED,

	DR_ERR_PNT_ERRORS = DR_ERRORS + 100,
	DR_ERR_PNT_NOT_FOUND, DR_ERR_PNT_NOT_DISABLED, DR_ERR_PNT_NOT_ENABLED,	
	DR_ERR_PNT_NOT_READABLE, DR_ERR_PNT_NOT_WRITEABLE,
	DR_ERR_PNT_TYPE_UNKNOWN, DR_ERR_PNT_TYPE_NO_REP,	

	DR_ERR_BLK_ERRORS = DR_ERRORS + 200,
	DR_ERR_BLK_INVALID,	DR_ERR_BLK_NOT_FOUND,
	DR_ERR_BLK_OFS_INVALID, DR_ERR_BLK_SIZE_INVALID,
	DR_ERR_BLK_TYPE_INVALID, DR_ERR_BLK_TYPE_CREATE, DR_ERR_BLK_BUFFER_SMALL,
	DR_ERR_MSG_REQUEST_ERROR, DR_ERR_MSG_RESPONSE_ERROR,

	DR_ERR_INTR_ERRORS = DR_ERRORS + 300,
	DR_ERR_INTR_ATTACH_FAILED, DR_ERR_INTR_PROXY_FAILED,
	
	DR_ERR_NUM_TYPES
		
} DR_ERROR_TYPE;

/* =========== Driver Hook Definitions (internal) ====================== */

typedef ST_STATUS (*DR_pfAddChildHook)(DR_pPOINT point, DR_pPOINT child);
typedef ST_STATUS (*DR_pfRemoveChildHook)(DR_pPOINT point, DR_pPOINT child);
typedef ST_STATUS (*DR_pfBuildPointHook)(DR_pPOINT point, int argc, char** argv);
typedef void 	  (*DR_pfDestroyHook)(DR_pPOINT point);
typedef ST_STATUS (*DR_pfConfigLineHook)(int argc, char** argv, DR_pData data);
typedef ST_STATUS (*DR_pfWritePointHook)(int argc, char** argv, DR_pData data);
typedef int 	  (*DR_pfLogHook)(const char* format, ...);
typedef ST_STATUS (*DR_pfProcessPointHook)(DR_pPOINT point, DR_pData data);
typedef int		  (*DR_pfRawMsgHook)(char *msg, pid_t sender, DR_pData dObj);
typedef int		  (*DR_pfPulseMsgHook)(IP_MsgBuffer *msg, pid_t sender, DR_pData dObj);
typedef ST_STATUS (*DR_pfHeartbeatHook)(DR_pPOINT point, DR_pData data);
typedef ST_STATUS (*DR_pfShutdownHook)(DR_pData data);

/* ========================= GLOBAL VARIABLES ========================= */

/*
 * Called whenever a child point is added to a multi-point class
 */
extern DR_pfAddChildHook DR_AddChildHook;
/*
 * Called whenever a child point is removed from a multi-point class
 */
extern DR_pfRemoveChildHook DR_RemoveChildHook;
/*
 * Called whenever a new point is created from a configuration command
 */
extern DR_pfBuildPointHook DR_BuildPointHook;
/*
 * Called whenever a point is destroyed
 */
extern DR_pfDestroyHook DR_DestroyHook;
/*
 * Called whenever an unknown config line or command is read
 */
extern DR_pfConfigLineHook DR_ConfigLineHook;
/*
 * Called whenever a point needs to be written to the PLC
 */
extern DR_pfWritePointHook DR_WritePointHook;
/*
 * Called whenever an error in the driver occurs
 */
extern DR_pfLogHook DR_ErrorHook;
/*
 * Called whenever a debug statement in the driver occurs
 */
extern DR_pfLogHook DR_DebugHook;
/*
 * Called whenever a point must be processed as part of the main loop
 */
extern DR_pfProcessPointHook DR_ProcessPointHook;
/*
 * Called whenever a raw message is received as part of the main loop
 */
extern DR_pfRawMsgHook DR_RawMsgHook;
/*
 * Called whenever a pulse/proxy message is received as part of the main loop
 */
extern DR_pfPulseMsgHook DR_PulseMsgHook;
/*
 * Called whenever a point of type heartbeat triggers if there is no expression to execute
 */
extern DR_pfHeartbeatHook DR_HeartbeatHook;
/*
 * Called when the driver loop is exited
 */
extern DR_pfShutdownHook DR_ShutdownHook;


/* ========================= GLOBAL CONSTANTS ========================= */

#define DR_COMMON_ARGS		7
#define DR_GROUP_ARGS		5
#define DR_HEARTBEAT_ARGS	4
#define DR_ANALOG_ARGS		(DR_COMMON_ARGS + 4)
#define DR_DIGITAL_ARGS		(DR_COMMON_ARGS + 0)

/* ======================= FUNCTION DEFINITIONS ======================= */

/* --------------------------- dr_loop.c ----------------------------- */

extern int		DR_Started;

int		DR_ProcessListEmpty ();
LL_LIST DR_ProcessListAdd (DR_pPOINT point);
LL_LIST DR_ProcessListRemove (DR_pPOINT point);
LL_LIST DR_ProcessListModifyCycle(DR_pPOINT point, double cycle);
LL_LIST DR_ProcessListGet ();

#ifdef IPC_H
ST_STATUS DR_MainLoop (IP_Task *myself, IP_Msg *hmsg,
					   UT_pCMD commands, int ncmds,
					   LL_LIST points, DR_pData data, char* retbuf);
#endif

/* --------------------------- dr_setup.c ----------------------------- */

extern LL_LIST 	DR_AllPoints;
extern UT_pCMD 	DR_Commands;
extern unsigned DR_Ncmds;
extern int 		DR_DataHubActive;
extern int 		DR_NameServerAttached;
extern int 		DR_Verbose;
extern int		DR_ExitStatus;

char *		DR_Version ();
char * 		DR_PointTypeName (int type);
int  		DR_PointNameType (char *name);

DR_pPOINT 	DR_NewPoint (void);
void 		DR_DestroyPoint (DR_pPOINT point);
DR_pPOINT 	DR_LookupPoint (char* name);
DR_pPOINT 	DR_LookupAddress (char* name);
void 		DR_ValidatePoint (DR_pPOINT point);
void 		DR_InvalidatePoint (DR_pPOINT point);

DR_pPOINT DR_BuildPoint			(int argc, char** argv, ST_STATUS *status);
ST_STATUS DR_FillCommonPoint 	(DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_FillAnalogPoint 	(DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_FillDigitalPoint 	(DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_FillUserPoint 		(DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_FillGroupPoint 	(DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_FillHeartbeatPoint (DR_pPOINT point, int argc, char** argv);
ST_STATUS DR_PointAddChild 		(DR_pPOINT point, DR_pPOINT child);
ST_STATUS DR_PointRemoveChild 	(DR_pPOINT point, DR_pPOINT child);

/* MANUEL! Do not change this void* to a DR_pDATA!  That would be a bug
   that does not show up with Watcom's shitty compiler. */
ST_STATUS DR_CmdModifyPointCycle (int argc, char **argv, void* data);

/* support for dedicated status point */
ST_STATUS 		DR_CmdDrvStatusPoint (int argc, char ** argv, DR_pData data);
unsigned long 	DR_GetDrvStatus ();
int 	  		DR_SetDrvStatus (unsigned long status);
int 			DR_SetDrvStatusMasked (unsigned long value,unsigned long mask);

ST_STATUS DR_ReadConfigFile (char* filename, UT_pCMD commands, int ncmds,
							 DR_pData data);

int DR_UpdateIntValue (DR_pPOINT point, int ivalue);
int DR_WriteIntValue (DR_pPOINT point, int ivalue);
int DR_UpdateRealValue (DR_pPOINT point, double value);
int DR_WriteRealValue (DR_pPOINT point, double value);
int DR_ConfirmWrite (DR_pPOINT point);

int DR_TestIntRawRange (DR_pPOINT point, int ivalue);
int DR_TestRealRawRange (DR_pPOINT point, double rvalue);
int DR_TestRawRange (DR_pPOINT point, FIVALUnion_t *raw_val);

int DR_EU_Available (DR_pPOINT point);
int DR_ConvertIntToEU (DR_pPOINT point, int iraw_val, double *eu_val);
int DR_ConvertRealToEU (DR_pPOINT point, double rraw_val, double *eu_val);
int DR_ConvertToEU (DR_pPOINT point, FIVALUnion_t *raw_val, double *eu_val);
int DR_ConvertEUtoInt (DR_pPOINT point, double eu_val, int *iraw_val);
int DR_ConvertEUtoReal (DR_pPOINT point, double eu_val, double *rraw_val);
int DR_ConvertEU (DR_pPOINT point, double eu_val, FIVALUnion_t *x);

typedef struct timespec * DR_ElapsedTime_t;

int DR_ElapsedTimeInit(DR_ElapsedTime_t *timer);
int DR_ElapsedTime(DR_ElapsedTime_t timer, int ms);

int       DR_IsTypeName (char* name);
DR_pTYPE  DR_NewType (int argc, char** argv);
ST_STATUS DR_ApplyType (char* name, int *argc, char** argv);
int       DR_IsDefnName (char* name);
void      DR_NewDefn (int argc, char** argv);

DR_pData  DR_newData (unsigned buffer_length, void *user_data);
void	  DR_deleteData (DR_pData *pData);

ST_STATUS DR_ApplyDefns (int argc, char** argv);
ST_STATUS DR_CmdDebug (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdType (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdTypeDesc (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdDefine (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdPoint (int argc, char** argv, DR_pData data);
ST_STATUS DR_ApplyCommand (UT_pCMD commands, int ncmds,
						   int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdAddPoint (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdRemovePoint (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdDisable (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdEnable (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdActive (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdReadable (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdWritable (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdCycleTime (int argc, char** argv, DR_pData data);
ST_STATUS DR_CmdExit (int argc, char** argv, DR_pData data);

ST_STATUS DR_CmdAproposCmds (int argc, char ** argv, DR_pData data);
ST_STATUS DR_CmdAproposCmdDesc (int argc, char ** argv, DR_pData data);
ST_STATUS DR_CmdAproposPoints (int argc, char ** argv, DR_pData data);
ST_STATUS DR_CmdDescribePoint (int argc, char ** argv, DR_pData data);

int 	  DR_MakeError (char *buf, int buf_len, int var_len,
						char *cmd, int err_num, const char *err_str_format, ...);
int 	  DR_GetError (char *buf, char **cmd, int *err_num, char **err_str);

ST_STATUS DR_CmdSchedParms (int argc, char ** argv, DR_pData data);
ST_STATUS DR_CmdTickSize (int argc, char ** argv, DR_pData data);

/* ================== Interrupt Handler Information ==================== */

#if defined(HAVE_QNX_INTERRUPTS) || defined(HAVE_NTO_INTERRUPTS)
#define HAVE_INTERRUPTS	
#else
#undef HAVE_INTERRUPTS
#endif

/* define the type of the interrupt handler */
#if defined (HAVE_QNX_INTERRUPTS)
typedef pid_t (far * DR_IntrHandlerFn_t)(void);
#elif defined(HAVE_NTO_INTERRUPTS)
typedef const struct sigevent* (far * DR_IntrHandlerFn_t)(void* area, int id);
#else
typedef int (*DR_IntrHandlerFn_t)(void);
#endif

/* define data type containing everything associated with
   handling interrupts */

typedef struct DR_IntrHandlerData_t
{
	DR_IntrHandlerFn_t	fn;		/* the default ISR */
	int					irq;	/* the actual IRQ attached */
	pid_t				proxy;	/* the proxy to send, or 0 if none */
	int					ihand; 	/* interrupt handler id */
	int					count;	/* internal counter to track use */
	int32_t				pmsg;	/* 32-bit proxy message */		
} DR_IntrHandlerData_t;

#define DR_INT

#ifdef __QNXNTO__
#define DR_INT32_PULSE_DATA(msg) (((struct sigevent*)msg)->sigev_value.sival_int)
#else
#define DR_INT32_PULSE_DATA(msg) (*((int32_t*)msg))
#endif

int 	DR_AttachIntrHandler (int intr, DR_pData data);
#if defined(HAVE_QNX_INTERRUPTS)
int		DR_AttachUserIntrHandler (int intr, DR_IntrHandlerFn_t fn,
								  unsigned ds);
#elif defined(HAVE_NTO_INTERRUPTS)
int		DR_AttachUserIntrHandler (int intr, DR_IntrHandlerFn_t fn,
								  void* area, int size);
#else /* !HAVE_INTERRUPTS */
int		DR_AttachUserIntrHandler (int intr, DR_IntrHandlerFn_t fn,
								  unsigned ds);
#endif

int 	DR_DetachIntrHandler (int intr);
int 	DR_EnableIntrHandler (int intr);
int 	DR_DisableIntrHandler (int intr);
int 	DR_QueryIntrHandler (int intr);
void	DR_TriggerIntrHandler (int intr, IP_Task *myself, void* area,
							   int length);

pid_t 	DR_AttachIntrProxy (int intr, char *proxy_msg, int length);
pid_t 	DR_AttachIntrBinProxy (int intr, char *proxy_msg, int length);
pid_t 	DR_AttachIntrPulse (int intr, uint32_t pmsg);
int 	DR_DetachIntrProxy (int intr);

extern DR_IntrHandlerData_t* DR_GetInterruptInfoByPulse (pid_t pulse);
extern DR_IntrHandlerData_t* DR_GetInterruptInfoByIRQ (int irq);

/* DataHub and IPC related functions */
#ifdef IPC_H
ST_STATUS DR_CreateIPCTask (char *taskname, char *qname, char *domain);
ST_STATUS DR_SetIPCTask (IP_Task *myself, IP_Msg *hmsg);
ST_STATUS DR_GetIPCTask (IP_Task **myself, IP_Msg **hmsg);
ST_STATUS DR_CmdAttachName (int argc, char ** argv, DR_pData data);
ST_STATUS DR_CmdAttachNS (int argc, char ** argv, DR_pData data);

ST_STATUS DR_CmdDataHubMode (int argc, char ** argv, DR_pData data);
ST_STATUS DR_RegisterPoint (DR_pPOINT point);
ST_STATUS DR_UnRegisterPoint (DR_pPOINT point);
ST_STATUS DR_ReRegisterPoints ();
ST_STATUS DR_WritePointToDh (DR_pPOINT point);
ST_STATUS DR_ReadPointFromDh (DR_pPOINT point);
ST_STATUS DR_WriteDbPointToDh (PT_pCPOINT point, int set_time);

ST_STATUS DR_CmdWriteHeartbeatToDh (int argc, char** argv, DR_pData data);
ST_STATUS DR_WriteHeartbeatToDh (DR_pPOINT point, DR_pData data);
#endif

/* --------------------------- dr_pci.c ----------------------------- */

typedef struct 
{
	unsigned	lastbus;
	unsigned	version;
	unsigned	hardware;
	unsigned	cfg_mech1_support : 1;
	unsigned	cfg_mech2_support : 1;
	unsigned	special_cycle_cfg_mech1 : 1;
	unsigned	special_cycle_cfg_mech2 : 1;
} DR_PciInfo_t;

typedef enum {DR_PCI_NONE, DR_PCI_IO, DR_PCI_MEM} DR_PciMemBase_t;

#ifdef __QNX__WE_HAVE_THIS_ELSEWHERE
struct _pci_config_regs
{
	unsigned short	   	Vendor_ID;
	unsigned short	   	Device_ID;
	unsigned short	   	Command;
	unsigned short	   	Status;
	char			   	Revision_ID;
	char			   	Class_Code[3];
	char			   	Cache_Line_Size;
	char			   	Latency_Timer;
	char			   	Header_Type;
	char			   	BIST;
	unsigned long	   	Base_Address_Regs[6];
	unsigned short		Sub_System_ID;
	unsigned short		Sub_Vendor_ID;
	unsigned long	   	Reserved1[1];
	unsigned long	   	ROM_Base_Address;
	unsigned long	   	Reserved2[2];
	char			   	Interrupt_Line;
	char				Interrupt_Pin;
	char				Min_Gnt;
	char				Max_Lat;
	char				Device_Dependent_Regs[192];
};
#endif

#ifdef __linux__
#include <cogent/qnxpci.h>
#endif

typedef struct
{
	unsigned short		Bus;
	unsigned short		Device;
	unsigned short		Function;
	
	unsigned short		VendorID;
	unsigned short		DeviceID;
	unsigned short		Class;				/* regs.Class[2] */
	unsigned short		SubClass;			/* regs.Class[1] */
	unsigned short		SubVendor;			/* regs.Reserved1[1] & (0xffff) */
	unsigned short		SubSystem;			/* regs.Reserved1[1] >> 16 */
	unsigned short		ProgIF;				/* regs.Class[0] */
	
	unsigned short		PciIndex;
	
	unsigned short		InterruptLine;
	unsigned short		InterruptPin;
	DR_PciMemBase_t		MemBaseType[6];
	unsigned long		MemBaseAddress[6];
	unsigned long		MemBaseLength[6];

	struct _pci_config_regs	regs;
	
} DR_PciDeviceInfo_t;	

#define	DR_PciDevFunc(device,func) (((device) << 3) | ((func) & 0x7))
#define	DR_PciDevFuncInfo(info) DR_PciDevFunc((info).Device,(info).Function)
#define	DR_PciDevFuncInfoPtr(info) DR_PciDevFunc((info)->Device,(info)->Function)

extern DR_PciInfo_t	DR_PCI_Info;

ST_STATUS DR_PciPresent(unsigned *busses_p, unsigned *version_p,
						unsigned *hardware_p);
ST_STATUS DR_PciLocateDevice(unsigned bus, unsigned device, unsigned *nfunc_p);
ST_STATUS DR_PciSummarizeDevice(unsigned bus, unsigned device, unsigned func,
								DR_PciDeviceInfo_t *info);
ST_STATUS DR_PciDeviceIndex (DR_PciDeviceInfo_t *info);
ST_STATUS DR_PciActivateInt (DR_PciDeviceInfo_t *info);
ST_STATUS DR_PciSearch (unsigned vendor_id, unsigned device_id,
						unsigned pciclass, unsigned subclass,
						unsigned subvendor, unsigned subsystem,
						unsigned index, int maxnum, int *count_p,
						DR_PciDeviceInfo_t *infolist);
								
char * DR_PciVendorNameLookup(unsigned id);
char * DR_PciVendorName(unsigned index, unsigned *id);
char * DR_PciDeviceNameLookup(unsigned vendor, unsigned id);
char * DR_PciClassNameLookup(unsigned pciclass, unsigned subclass,
							 char **subname_ptr);

void	DR_PciDescribe(DR_PciDeviceInfo_t *info);
void	DR_PciDescribeAll();

/* --------------------------- dr_pci.c ----------------------------- */

void DR_SerMonInit(int port);
void DR_SerMonOut (char chr);
void DR_SerMonOut16 (int value);
void DR_SerMonOutHex (int value);


#ifdef __cplusplus
};
#endif

#endif

/*
*****************************************************************************
*
*  End of File:     driver.h
*
******************************************************************************
*/

