#ifndef __LINUXIOCTL_H__
#define __LINUXIOCTL_H__


#include <iostream>
#include <pthread.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>          /* File control definitions */
#include <errno.h>          /* Error number definitions */
#include <unistd.h>         /* fork() */
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#ifdef __linux__
	#include <scsi/sg.h>
	#include <sys/ipc.h>
	#include <sys/shm.h>
#endif
#include <sys/ioctl.h>
#include <unistd.h>

#include "commdef.h"
#include "interface.h"


/*DeviceType*/
#define ARECA_SATA_RAID                      	0x90000000
/*FunctionCode*/
#define FUNCTION_READ_RQBUFFER               	0x0801
#define FUNCTION_WRITE_WQBUFFER              	0x0802
#define FUNCTION_CLEAR_RQBUFFER              	0x0803
#define FUNCTION_CLEAR_WQBUFFER              	0x0804
#define FUNCTION_CLEAR_ALLQBUFFER            	0x0805
#define FUNCTION_RETURN_CODE_3F              	0x0806
#define FUNCTION_SAY_HELLO                   	0x0807

#if defined(__linux__) || defined (__solaris__)
/* ARECA IO CONTROL CODE*/
	#define ARCMSR_IOCTL_READ_RQBUFFER           	ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER
	#define ARCMSR_IOCTL_WRITE_WQBUFFER          	ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER
	#define ARCMSR_IOCTL_CLEAR_RQBUFFER          	ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER
	#define ARCMSR_IOCTL_CLEAR_WQBUFFER          	ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER
	#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER        	ARECA_SATA_RAID | FUNCTION_CLEAR_ALLQBUFFER
	#define ARCMSR_IOCTL_RETURN_CODE_3F          	ARECA_SATA_RAID | FUNCTION_RETURN_CODE_3F
	#define ARCMSR_IOCTL_SAY_HELLO               	ARECA_SATA_RAID | FUNCTION_SAY_HELLO
#elif __FreeBSD__
	#define ARCMSR_IOCTL_READ_RQBUFFER           	_IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
	#define ARCMSR_IOCTL_WRITE_WQBUFFER          	_IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
	#define ARCMSR_IOCTL_CLEAR_RQBUFFER          	_IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
	#define ARCMSR_IOCTL_CLEAR_WQBUFFER          	_IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
	#define ARCMSR_IOCTL_CLEAR_ALLQBUFFER        	_IOWR('F', FUNCTION_CLEAR_ALLQBUFFER, sSRB_BUFFER)
	#define ARCMSR_IOCTL_RETURN_CODE_3F          	_IOWR('F', FUNCTION_RETURN_CODE_3F, sSRB_BUFFER)
	#define ARCMSR_IOCTL_SAY_HELLO               	_IOWR('F', FUNCTION_SAY_HELLO, sSRB_BUFFER)
#endif


/* ARECA IOCTL ReturnCode */
#define ARCMSR_IOCTL_RETURNCODE_OK              0x01
#define ARCMSR_IOCTL_RETURNCODE_ERROR           0x06
#define ARCMSR_IOCTL_RETURNCODE_3F              0x3F


typedef struct _SRB_IO_CONTROL
{
	unsigned int HeaderLength;
	UCHAR Signature[8];
	unsigned int Timeout;
	unsigned int ControlCode;
	unsigned int ReturnCode;
	unsigned int Length;
} sSRB_IO_CONTROL, *pSRB_IO_CONTROL;

typedef struct _SRB_BUFFER
{
	sSRB_IO_CONTROL                 srbioctl; 				// ioctl header
	UCHAR                           ioctldatabuffer[1032];	// areca gui program does not accept more than 1031 byte
} sSRB_BUFFER, *pSRB_BUFFER;


class LinuxIoctlInterface : public ArcInterface
{
public:
	LinuxIoctlInterface();
	~LinuxIoctlInterface();
	bool init(const int nScsiPort);
	int send(sIF_CMD_BLOCK *ifData);
	int recv(sIF_CMD_BLOCK *ifData);
	int syncSend(sIF_CMD_BLOCK *ifData);
	void requirelock();
	void releaselock();
	int	getMTU();
	void *getDeviceHandle();
private:
	BOOL ClearReadBuffer();
	BOOL ClearWriteBuffer();
	BOOL ClearReadWriteBuffer();
	HANDLE  m_hScsi;
	int fd;
	pthread_mutex_t mut;
};

#endif
