#ifndef _RDMA_ADC_APP_REG_H_
#define _RDMA_ADC_APP_REG_H_

#include <stdint.h>
#include <netinet/in.h>

/* Basic properties */
#define REG_ADDR_WIDTH		32
#define REG_WIDTH			32
#define MAX_REGS_IN_MESSAGE	7
#define MAGIC_NUMBER		0xdfc1dfc

/* Message types */
#define MSG_TYPE_WRITE		0x1
#define MSG_TYPE_READ		0x2
#define MSG_TYPE_INFO		0x3
#define MSG_TYPE_RESP		0x4
#define MSG_TYPE_ERR		0x8

/* Register addresses */
#define REG_DST_IP		0x00000000
#define REG_DST_MAC_HIGH	0x00000001
#define REG_DST_MAC_LOW		0x00000002
#define REG_DST_UDP		0x00000003
#define REG_DST_QP		0x00000004
#define REG_FIRST_PSN		0x00000005
#define REG_Q_KEY		0x00000006
#define REG_CONTROL		0x00000007
#define REG_STATUS		0x00000008
#define REG_WORD_CNT_HIGH	0x00000009
#define REG_WORD_CNT_LOW	0x0000000A
#define REG_ID			0x0000000B

/* Error codes */
#define ERR_OK			0x00000000
#define ERR_REG_NOT_EXIST	0x00000001
#define ERR_OVERFLOW		0x00000010
#define ERR_READ_ONLY		0x00000100

/* Used insted of invalid register address to indicate that it doesn't exist */
#define ERR_REG_UNKNOWN		0x11111111	

/* Message header */
#define PACKET_HEADER(MAGIC, TYPE)	(((MAGIC) << 4) | (TYPE))
#define MSG_WRITE_HEADER	PACKET_HEADER(MAGIC_NUMBER, MSG_TYPE_WRITE)
#define MSG_READ_HEADER		PACKET_HEADER(MAGIC_NUMBER, MSG_TYPE_READ)
#define MSG_INFO_HEADER		PACKET_HEADER(MAGIC_NUMBER, MSG_TYPE_INFO)
#define MSG_RESP_HEADER		PACKET_HEADER(MAGIC_NUMBER, MSG_TYPE_RESP)
#define MSG_ERR_HEADER		PACKET_HEADER(MAGIC_NUMBER, MSG_TYPE_ERR)

#define REGISTER_NUM		12

/* Control register values */
#define CONTROL_REG_START	0x00000001
#define CONTROL_REG_STOP	0x00000002

struct cecilie_rdma_app_reg_t {
	uint32_t reg_addr;
	char* name;
	char *description;
};

void print_register_description();

typedef struct cecilie_reg_t{
	uint32_t reg_addr;
	uint32_t reg_val;
} cecilie_reg_t;

/* Structure defining packet carrying Xenie's network settings */
#pragma pack(push)
typedef struct cecilie_net_info_t {
	uint8_t mac_addr[6];
	uint8_t pad[2];
	struct in_addr ip_addr;
	struct in_addr net_mask;
} cecilie_net_info_t;
#pragma pack(pop)

typedef struct cecilie_t {
	/* network info of cecilie board */
	cecilie_net_info_t	net;
	/* adapter name */
	char			adapter_name[100];
	/* pointer to next board */
	struct cecilie_t 	*next;

} cecilie_t;

cecilie_t * get_cecilie_from_list(cecilie_t *list, int num);
int insert_cecilie_to_list(cecilie_t *cecilie, cecilie_t **list);
void clear_cecilie_list(cecilie_t **list);
void print_cecilie_list(cecilie_t *list);
void print_cecilie(cecilie_t *dev);
int get_adapter_names(char ***if_names);
int get_mac_ip(char *if_name, unsigned char *mac, struct in_addr *ip);
void print_register_description();

#endif

