/*-----------------------------------------------------------------------------
dpm.h -- Linux driver of DPM interface to VMOD

Copyright (c) 1996 JANZ Computer AG
All Rights Reserved

Created 96/01/23 by Stefan Althoefer

Version 1.12 of 96/09/27

This file is for both, the "dpm" and the "dpmw" driver.
The only difference, besides the names of the driver functions, are the in 
the INKERNEL structures. But these are not visible to the user.

-----------------------------------------------------------------------------*/

#ifndef __INCdpmh
#define __INCdpmh

#ifdef __cplusplus
extern "C" {
#endif

#include "defs.h"
#include "vmod.h"

/* Max. Count of Devices for the dpm driver. */
/*#define	DPM_MAJOR_NUMBER	57 */
#define	MAX_BOARDS		16	/* max. # of boards supported	*/
#define	MAX_MODUL_BOARDS	4	/* max. # of modules supported	*/
					/* with one board		*/
#define MAX_DPM_DEV 		(MAX_BOARDS * MAX_MODUL_BOARDS)

#define	FAST_QUEUE		'\0'	/* flag for fast queue 		*/
#define	PLAIN_QUEUE		'\1'	/* flag for normal queue 	*/

/* Data type of messages */
#define MSGLEN		252	/* Maximum length of a message */
#define MSGHDLEN	  4	/* Length of message head */

#define	ICAN2	1
#define	ICAN3	2

/* -*-Struct-*-
 *
 * Message - local message buffer for standard host interface
 *
 * This structure stores a message to be send to or received from
 * a VMOD-ICAN module via the standard host interface.
 *
 * <cmd> is a 8 bit command specifier. Refer to the VMOD-ICAN manual
 * to find out which services are provided by the different <cmd>
 * specifiers. The data length to be transfered is stored in <len>, thereby
 * <len> specifies how many bytes of the vector <data> are valid. The data
 * have to be interpreted by means of <cmd>.
 *
 * At most MSGLEN bytes can be stored in a message. MSGLEN is 252 bytes
 * for all current VMOD-ICAN modules.
 */
typedef struct {
	BYTE_t	cmd;           /* Message specifier */
	BYTE_t	gap1;
	WORD_t	len;           /* Message length (<= MSGLEN) */
	BYTE_t	data[MSGLEN];  /* Data array of Message */
} Message;


/* -*-Struct-*-
 *
 * FastMessage - local message buffer for fast host interface
 *
 * This structure stores a CANbus message to be send to or received from
 * a VMOD-ICAN modules fast interface.
 *
 * <cmd> is a 8 bit service multiplexor. Currently only <cmd>='0' is used.
 *
 * Through <data> the actual CANbus message is transfered if <cmd> equals '0'.
 * The first two bytes store the message descriptor, that contains the
 * ID, RTR-flag and CANbus data length code (DLC), the remaining bytes store
 * the CANbus data bytes.
 *
 * .CS
 *     data[0]  = ID/8;
 *     data[1]  = 32(ID%8) + 16RTR + DLC
 *     data[2]  = CAN BYTE 1
 *     data[:]  = :
 *     data[9]  = CAN BYTE 8
 *     data[10] = unused
 *     data[:]  = :
 *     data[13] = unused
 * .CE
 * 
 */
typedef struct {
	BYTE_t	unused;
	BYTE_t	cmd;           /* Service specifier */
	BYTE_t	data[14];      /* Data array */
} FastMessage;



/*** DPM: Special Driver Functions (Driver management) *********************/
#ifdef nodef

/* Create the dpm driver. */
extern STATUS dpmDrv(void);

/* Remove the dpm driver from the system. */
extern STATUS dpmDrvRemove(void);

/* Add a dpm device. */
extern STATUS dpmDevCreate(
	int		modno,
	UINT	baddr
);

/* Delete a dpm device. */
extern STATUS dpmDevDelete(
	const char *name
);

/* Main ioctl function. */
extern dpmIoctl(
	int	modno,
	int	cmd,
	int	arg
);

/* interrupt function. */
extern void dpmInt (int	modno);


/*** DPMW: Special Driver Functions (Driver management) *********************/

/* Create the dpmw driver. */
extern STATUS dpmwDrv(void);

/* Remove the dpmw driver from the system. */
extern STATUS dpmwDrvRemove(void);

/* Add a dpmw device. */
extern STATUS dpmwDevCreate(
	const char *name,
	int	modno,
	UINT	baddr,
	int	vector,
	int	level
);

/* Delete a dpmw device. */
extern STATUS dpmwDevDelete(
	const char *name
);
#endif

/*** IOCTL commands *****************************************************/
#define	WOS			0x8000	/* offset into user fuction codes */

					/* getstat:			*/
#define DPM_READ_MBOX		(128 + WOS)	/* function code READ     	*/
#define DPM_COPY_FROM		(129 + WOS)	/* copy data from dpm		*/
#define DPM_READ_FAST_MBOX	(130 + WOS)	/* function code READ FAST    	*/

					/* putstat:			*/
#define DPM_WRITE_MBOX		(528 + WOS)	/* function code WRITE mid prio	*/
#define DPM_WRITE_MBOX_HI	(539 + WOS)	/* function code WRITE high prio*/
#define DPM_WRITE_MBOX_LOW	(540 + WOS)	/* function code WRITE low prio	*/
#define DPM_COPY_TO		(529 + WOS)	/* copy data to dpm		*/
#define	DPM_DEL_SIGNAL		(530 + WOS)	/* delete signal entry		*/
#define	DPM_SET_SIGNAL		(531 + WOS)	/* set signal entry		*/
#define	DPM_RESET		(532 + WOS)	/* reset the module		*/
#define DPM_INIT_NEW_HOSTIF	(533 + WOS)	/* init new hostif		*/
#define DPM_INIT_NEW_HOSTIF_PRIO    (545 + WOS) /* init new hostif (priorized)  */
#define DPM_SET_SEM		(534 + WOS)	/* create semaphor for read	*/
#define DPM_INIT_FAST_CAN	(535 + WOS)	/* init fast CAN access		*/
#define DPM_INIT_FAST_CAN_PRIO	(551 + WOS)	/* init fast CAN access         */
#define DPM_WRITE_FAST_CAN	(536 + WOS)	/* send trougth fast interface  */
#define DPM_WRITE_FAST_CAN_PRIO (552 + WOS)	/* send trougth prioritized fast interface  */

#define DPM_DEINIT_FAST_CAN	(537 + WOS)	/* deinit fast CAN access	*/
#define DPM_DEL_SEM		(538 + WOS)	/* delete semaphor for read	*/
			/*	(539 + WOS)	   see above! */
			/*	(540 + WOS)	   see above! */
#define DPM_INIT_ID_MSG_Q_TABLE (541 + WOS)	/* allocates memory for table,	*/
					/* where message-queue-Ids for	*/
					/* fast can access are stored	*/
#define DPM_DEINIT_ID_MSG_Q_TABLE   (542 + WOS)	/* deallocates memory for table	*/
#define DPM_ADD_ID_TO_MSG_Q_TABLE   (543 + WOS)	/* adds queue entry to ID-table	*/
#define DPM_REM_ID_FROM_MSG_Q_TABLE (544 + WOS)	/* removes entry from ID-table	*/
			/*	(545 + WOS)	   see above! */
#define DPM_INIT_L2_ROUTING	(546 + WOS)	/* inits the Layer2 routing cap	*/
#define DPM_DEINIT_L2_ROUTING	(547 + WOS)	/* deinits Layer2 routing cap	*/
#define DPM_INIT_ROUTE_ID	(548 + WOS)	/* lets _one_ ID being routable	*/
#define DPM_ADD_ROUTE_TO_ID	(549 + WOS)	/* adds _one_ routing way to ID	*/
#define DPM_MAP_FD_TO_MOD	(550 + WOS)	/* map the fd to board/module */

#define DPM_DEV_CREATE		(600 + WOS)	/* WINDOWS specific ioctl function code */
#define DPM_DEV_DELETE		(601 + WOS)	/* deletes device from slot */
#define	DPM_READ_INTCOUNT	(602 + WOS)
#define DPM_REGISTER_APC	(603 + WOS)	/* Register APC function */
#define DPM_TPU_REQ             (604 + WOS)     /* initiates TPU request IR */
#define DPM_OBJDIC_REQ          (605 + WOS)     /* access to object dict. */

#define DPM_DRV_IDVERS          (606 + WOS)     /* get driver version */
#define DPM_WRITE_PP		(607 + WOS)     /* write CANopen process picture */
#define DPM_READ_PP		(608 + WOS)     /* read CANopen process picture */


struct signal_dpm {
	int		task_id;
	int		signal_code;
	unsigned char	*param_addr;
};

struct dpm_copy_desc {
        unsigned int	memory;
        unsigned int	dpm;
        int		len;
};

struct dpm_rw_can_desc {
	int		rval;
	Message		*pm;
};

struct dpm_new_hostif_desc {
        int             fromhost_len;
        int             tohost_len;
};

struct dpm_new_hostif_desc_prio {
        int             fromhost_hi_len;
        int             fromhost_low_len;
        int             fromhost_len;
        int             tohost_len;
};

struct dpm_fast_can_desc {
        int             fromhost_len;
        int             tohost_len;
/*	MSG_Q_ID	read_queue; */
};

struct dpm_fast_can_desc_prio {
        int             numOfPrioQueues;
        int             fromhost_len;
        int             tohost_len;
/*        MSG_Q_ID        read_queue; */
};

struct dpm_write_fast_can_desc {
        int             rval;
        FastMessage	*pm;
};

struct dpm_write_fast_can_desc_prio {
        int             rval;
        int             prioQueue;
        FastMessage     *pm;
};

struct dpm_fast_can_desc_win {
        int             fromhost_len;
        int             tohost_len;
	int		fkt_addr;
};

struct dpm_msg_q_id_desc {
	unsigned short	id;
	/* MSG_Q_ID	target_queue; */
};

struct dpm_layer_2_routing_desc {
	int	rval;
	int	Id;
	int	max_routes;
	int	source_Id;
	int	dest_Id;
	int	dest_Board;
	int	dest_Modul;
};

struct io_args {
	int modno;	/* slot of interesing module */
	int arg;	/* place of some arguments */
};


struct dpm_dev_create_desc {
	int	modno;
};

struct dpm_objdic_desc {
        int     objdic_index;
        int     objdic_subindex;
        int     access_type;
        void    *entry_structure;
};

struct dpm_readpp_desc {
        int     dataSize;
        int     offset;
        int     dataValid;
        char    *buffer;
};
 
struct dpm_writepp_desc {
        int     dataSize;
        int     offset;
        char    *buffer;
};

#define TS_TO_HOST      1       /* read modules timestamp counter */
                                /* of last SYNC message */
#define TS_TO_MODULE    0       /* synchronizing module by writing timestamp */


#ifdef INKERNEL
/************************************************************************/
/* DEFINES								*/
/************************************************************************/

#define	MAXNDEV		1		/* I/O-channel per module	*/
#define	BOARDTYP	(1<<7)		/* d7=1 VMOD-IG, d7=0 VMOD-IO	*/
#define	I_ENABLE	1

/* MICAN3 */
#define DPM_PAGEWIDTH	256		/* ICAN3			*/

#ifdef BIG_ENDIAN
struct dpmw {			/* structure for BIG_ENDIAN		*/
	unsigned char	unused;
	unsigned char	spec;		/* message specifier		*/
	unsigned char	len_l;		/* data length low byte		*/
	unsigned char	len_h;		/* data length high byte	*/
	unsigned char	data[MSGLEN];	/* raw data			*/
	unsigned char	page_sel;	/* page selector		*/
	unsigned char	gap1;
	unsigned char	intgen;		/* wr: generate inter. on ICAN3	*/ 
					/* rd: clear MODULbus interrupt	*/
	unsigned char	gap2;
	unsigned char	reset;		/* generate reset on ICAN3	*/
	unsigned char	gap3;
	unsigned char	tpureq;		/* signal to tpu on ICAN3	*/
};
#endif

#ifdef LITTLE_ENDIAN
struct dpmw {			/* structure for LITTLE_ENDIAN		*/
	unsigned char	spec;		/* message specifier		*/
	unsigned char	unused;
	unsigned char	len_h;		/* data length high byte	*/
	unsigned char	len_l;		/* data length low byte		*/
	unsigned char	data[MSGLEN];	/* raw data			*/
	unsigned char	gap1;
	unsigned char	page_sel;	/* page selector		*/
	unsigned char	gap2;
	unsigned char	intgen;		/* wr: generate inter. on ICAN3	*/ 
					/* rd: clear MODULbus interrupt	*/
	unsigned char	gap3;
	unsigned char	reset;		/* generate reset on ICAN3	*/
	unsigned char	gap4;
	unsigned char	tpureq;		/* signal to tpu on ICAN3	*/
};
#endif


#define START_BUFF	9		/* first free page within DPM */

/* New stylish host interface */

#ifdef BIG_ENDIAN
struct dpmw_desc {
        unsigned char   control;        /* control byte */
        unsigned char   buffer;         /* buffer pointer */
};
#endif

#ifdef LITTLE_ENDIAN
struct dpmw_desc {
        unsigned char   buffer;         /* buffer pointer */
        unsigned char   control;        /* control byte */
};
#endif

#define DPM_DESC_VALID          (1<<7)
#define DPM_DESC_WRAP           (1<<6)
#define DPM_DESC_INTR           (1<<5)
#define DPM_DESC_IVALID         (1<<4)
#define DPM_DESC_LEN            (7<<0)


/* Fast dpmqueue host interface */

#define FDPMQUEUE_LEN	14		/* data elements in each buffer */


#ifdef BIG_ENDIAN
struct fdpmw_desc {
	unsigned char control;
	unsigned char spec;
	unsigned char data[FDPMQUEUE_LEN];
};
#endif

#ifdef LITTLE_ENDIAN
struct fdpmw_desc {
	unsigned char spec;
	unsigned char control;
	unsigned char data[FDPMQUEUE_LEN];
};
#endif

#define FDPM_DESC_VALID		(1<<7)
#define FDPM_DESC_WRAP		(1<<6)
#define FDPM_DESC_IVALID	(1<<4)

/* Definition of fast-queue-fromhost priorization */
#define FDPMQUEUE_FROMHOST_NO_INIT      0
#define FDPMQUEUE_FROMHOST_1_PRIO       1
#define FDPMQUEUE_FROMHOST_N_PRIO       3

#ifdef BIG_ENDIAN
#define DPMW_MSYNC_LOCL_ADDR	0x1
#define DPMW_MSYNC_PEER_ADDR	0x0
#define DPMW_TARGET_RUN_ADDR	0x2
#define TIME_STAMP_0_ADDR       0x10
#define TIME_STAMP_1_ADDR       0x11
#define TIME_STAMP_2_ADDR       0x12
#define TIME_STAMP_3_ADDR       0x13
#endif

#ifdef LITTLE_ENDIAN
#define DPMW_MSYNC_LOCL_ADDR	0x0
#define DPMW_MSYNC_PEER_ADDR	0x1
#define DPMW_TARGET_RUN_ADDR	0x3
#define TIME_STAMP_0_ADDR       0x12
#define TIME_STAMP_1_ADDR       0x13
#define TIME_STAMP_2_ADDR       0x10
#define TIME_STAMP_3_ADDR       0x11
#endif

/* end of defined MICAN3 */

/* MICAN2 */

#ifdef BIG_ENDIAN
struct dpm {			/* structure for MOTOROLA type		*/
	unsigned char	page_sel;	/* page selector		*/
	unsigned char	unused;
	unsigned char	intgen;		/* wr: generate inter. on ICAN2	*/ 
					/* rd: clear MODULbus interrupt	*/
	unsigned char	spec;		/* message specifier		*/
	unsigned char	reset;		/* generate reset on ICAN2	*/
	unsigned char	len_l;		/* data length low byte		*/
	unsigned char	gap0;
	unsigned char	len_h;		/* data length high byte	*/
	unsigned char	gap_1;
	unsigned char	data[MSGLEN * 2];	/* raw data		*/
};
#endif

#ifdef LITTLE_ENDIAN
struct dpm {			/* structure for INTEL-LIKE type        */
	unsigned char	unused;
	unsigned char	page_sel;	/* page selector		*/
	unsigned char	spec;		/* message specifier		*/
	unsigned char	intgen;		/* wr: generate inter. on ICAN2	*/ 
					/* rd: clear MODULbus interrupt	*/
	unsigned char	len_l;		/* data length low byte		*/
	unsigned char	reset;		/* generate reset on ICAN2	*/
	unsigned char	len_h;		/* data length high byte	*/
	unsigned char	gap0;
	unsigned char	data[MSGLEN * 2];	/* raw data		*/
	unsigned char	gap_1;
};
#endif

/* New stylish host interface */

#ifdef BIG_ENDIAN
struct dpm_desc {
        unsigned char   gap1;
        unsigned char   control;        /* control byte */
        unsigned char   gap2;
        unsigned char   buffer;         /* buffer pointer */
};
#endif

#ifdef LITTLE_ENDIAN
struct dpm_desc {
        unsigned char   control;        /* control byte */
        unsigned char   gap1;
        unsigned char   buffer;         /* buffer pointer */
        unsigned char   gap2;
};
#endif

#define DPM_DESC_VALID          (1<<7)
#define DPM_DESC_WRAP           (1<<6)
#define DPM_DESC_INTR           (1<<5)
#define DPM_DESC_IVALID         (1<<4)
#define DPM_DESC_LEN            (7<<0)


/* Fast dpmqueue host interface */

#define FDPMQUEUE_LEN 14

#ifdef BIG_ENDIAN
struct fdpm_desc {
	unsigned char gap1;
	unsigned char control;
	unsigned char gap2;
	unsigned char spec;
	unsigned char gap3;
	unsigned char data[2*FDPMQUEUE_LEN-1];
};
#endif

#ifdef LITTLE_ENDIAN
struct fdpm_desc {
	unsigned char control;
	unsigned char gap1;
	unsigned char spec;
	unsigned char gap2;
	unsigned char data[2*FDPMQUEUE_LEN-1];
	unsigned char gap3;
};
#endif

#ifdef BIG_ENDIAN
#define DPM_MSYNC_LOCL_ADDR		0x3
#define DPM_MSYNC_PEER_ADDR		0x1
#define DPM_TARGET_RUN_ADDR		0x5
#endif

#ifdef LITTLE_ENDIAN
#define DPM_MSYNC_LOCL_ADDR		0x2
#define DPM_MSYNC_PEER_ADDR		0x0
#define DPM_TARGET_RUN_ADDR		0x4
#endif

/* swap macro for MOTOROLA <-> INTEL access on ICAN3 */
#ifdef LITTLE_ENDIAN
#define SWAP_WORD(x) (((x & 0xff) << 8) | (0xff & (x >> 8)))
#endif
#ifdef BIG_ENDIAN
#define SWAP_WORD(x) (x)
#endif

#endif /* #ifdef INKERNEL */

#define TOHOST_DPM_QUEUE_PAGE		5 /* tohost_dpmqueue page */
#define FROMHOST_DPM_QUEUE_PAGE		6 /* fromhost_dpmqueue page prio mid */
#define FROMHOST_DPM_QUEUE_HI_PAGE	7 /* fromhost_dpmqueue page prio high */
#define FROMHOST_DPM_QUEUE_LOW_PAGE	8 /* fromhost_dpmqueue page prio low */
#define START_BUFF			9 /* first free page within DPM */


/*----------routing specific defines ------------------------*/ 

/* CAN Identifiers used by CAL (cf. CiA/DS204-1, Annex I) */
#define ID_START_STOP		   0	/* Node Start, Stop, Disconnect */
#define ID_CMS_NIL		   0	/* invalid CMS Id */
#define ID_CMS_MIN		   1	/* range of CMS   */
#define ID_CMS_MAX		1760	/*    identifiers */
#define ID_GUARD_NIL		   0	/* invalid guard Id */
#define ID_GUARD_MIN		1761	/* range of guarding */
#define ID_GUARD_MAX		2015	/*    identifiers    */
#define ID_LMT_S		2020	/* from LMT Slave */
#define ID_LMT_M		2021	/* from LMT Master */
#define ID_NMT_IDENTIFY		2022	/* Identify Node Protocol */
#define ID_DBT_S		2023	/* from DBT Slave */
#define ID_DBT_M		2024	/* from DBT Master */
#define ID_NMT_S		2025	/* from NMT Slave */
#define ID_NMT_M		2026	/* from NMT Master */
#define ID_SELFTEST		2027	/* for module selftest */
#define ID_MIN			   0	/* range of identifiers */
#define ID_MAX			2031	/*    controlled by CiA */

#define	MAX_ROUTES_PER_ID		(ID_MAX * 2)
					/* should be enough... */

#define	NIL_ROUT		(struct rout_target *) 0
					/* NIL pointer for "no routing" */

#define	NIL_NIL_ROUT		(struct rout_target **) 0
					/* NIL pointer for "no routing" */

#define NIL_DPM_DEV		(DPM_DEV *) -1
					/* NIL pointer for "no routing" */

#define BLANC			0xffff	/* empty / last entry indicator in */
					/* rout_target->target_id struct */
					/* member */
					
/* prioritized fast-fromhost-queue specific defines/structures */
 
struct fromHostFastDpmQPrioEntry {
        unsigned short                          priority;
        volatile struct fdpmw_desc              *fhfdpmQueue;
        int                                     fhfdpmQueueP;
        int                                     fhfdpmQueueStartP;
        struct fromHostFastDpmQPrioEntry        *next;
};
#define NIL_FHFDQ_PRIO_ENTRY (struct fromHostFastDpmQPrioEntry *)0

#ifdef __cplusplus
}
#endif

#endif /* __INCdpmh */

