#ifndef __CAMRY_SERL_H__
#define __CAMRY_SERL_H__

#include "tx_api.h"
#include "serial_common.h"
#include "serial_help.h"

#define ENABLE_TESTPAT_CHECKER 0
#if ENABLE_TESTPAT_CHECKER
#include "checker.hh"
#endif

/* Serial register definitions */

typedef volatile struct camry_serial_t {
    volatile uint32 wrap_conf;
#define RXEN  (1 << 30)   /* enable wrapper to process rx char */
#define TXEN  (1 << 29)   /* enable wrapper to process tx char */
#define UART_MODE (0 << 28)
#define RTSEN  (1 << 19)
#define DTREN  (0 << 18)
#define RXFLUSH (1 << 17) /* write 1 then 0 to reset rx fifo */
#define TXFLUSH (1 << 16) /* write 1 then 0 to reset rx fifo */
#define RXBYTES(x) ((x >> 14) & 0x3) /* bytes pending in the wrapper */
#define RXCLOSE (1 << 13) /* software initiate buffer close */
#define TXFLOW_CTS (1 << 6) /* CTS enabled */
#define TXFLOW_DCD (1 << 7) /* DCD enabled */
#define TXFLOW_DSR (1 << 8) /* DSR enabled */
#define TXFLOW_RI (1 << 9) /* RI enabled */
#define TXFLOW_SOFT (1 << 10) /* software enabled TX enable -- enable transmitter*/
#define TXFLOW_RXCBFC (1 << 11) /* receive char-based flow control */
#define RL            (1 << 5)  /* remote loopback */
#define RTS_CTRL            (1 << 4) /* deasserted when TX fifo is half full */

    volatile uint32 int_enable;
#define UINT (1 << 21) /* enable interrupt from uart */
#define FORCE (1 << 20) /* enable force complete  interrupt */
#define OFLOW (1 << 19) /* enable overflow error interrupt */
#define PARITY (1 << 18) /* enable parity error interrupt */
#define FRAME (1 << 17) /* enable frame error interrupt */
#define BREAK (1 << 16) /* enable line break error interrupt */
#define BGAP (1 << 15) /* enable buffer gap time out interrupt */
#define RXCLS (1 << 14) /* enable sw-initiated buffer close has completed interrupt */
#define CGAP (1 << 13) /* enable char gap time out interrupt */
#define MATCH4 (1 << 12) /* enable char match 4 interrupt */
#define MATCH3 (1 << 11) /* enable char match 3 interrupt */
#define MATCH2 (1 << 10) /* enable char match 2 interrupt */
#define MATCH1 (1 << 9) /* enable char match 1 interrupt */
#define MATCH0 (1 << 8) /* enable char match 0 interrupt */
#define DSR_INT (1 << 7) /* enable DSR state change interrupt */
#define DCD_INT (1 << 6) /* enable DCD state change interrupt */
#define CTS_INT (1 << 5) /* enable CTS state change interrupt */
#define RI_INT (1 << 4) /* enable RI state change interrupt */
#define TBC_INT (1 << 3) /* enable TX buffer close interrupt */
#define RBC_INT (1 << 2) /* enable RX buffer close interrupt */
#define TX_IDLE (1 << 1) /* enable TX FIFO empty interrupt */
#define RX_IDLE (1 << 0) /* enable RX idle interrupt */


    volatile uint32 int_status; /* same bit fields as above, write 1 to clean */
    
    volatile uint32 char_gap_timer;
    volatile uint32 buffer_gap_timer;
#define BUFFER_GAP_TIME 100 /* ms */
#define GAP_EN (1 << 31)  /* enable TX bit rate generator*/
#define GAP_MASK 0x1ffffff

    volatile uint32 match_reg[5]; 
#define MATCH_ENABLE (1 << 31)
#define MATCH_MASK   (0xff << 16)

    volatile uint32 flow_ctrl;
#define FLOW_STATE (1 << 10)
#define HW_XOFF (1 << 10)  /* 0 HW_XON, 1 HW_XOFF */

    volatile uint32 force_reg;
#define FORCE_EN (1 << 31)
#define FORCE_BUSY            (1 << 30) /* force operation is in progress */

    volatile uint32 wakeup_ctrl;
#define WAKE_ENABLE      1

    volatile uint32 tx_count;
#define TX_COUNT_EN (1 << 31)
#define TX_COUNT_MASK   0xffffff

    uint32 pad[50]; // Or is it 49 longs?
   // volatile uint32 rx_buf; /* for diagnostic only */
   // volatile uint32 tx_buf; /* for diagnostic only */
    
    volatile uint32 baud_div_lsb;
    volatile uint32 baud_div_msb; 
    
#define uart_int_enable baud_div_msb
//    volatile uint32 uart_int_enable;
#define EDSSI (1 << 3) /* modem status interrupt */
#define ELSI  (1 << 2) /* receive line status interrupt */
#define ETBEI (1 << 1) /* tx holding reg empty interrupt */
#define ERBFI  1      /* rx data avail interrupt */

    volatile uint32 fifo_ctrl;  /* uart fifo control -- write only */
#define FIFO_EN  1  /* fifo enable */

#define uart_int_iden	fifo_ctrl    /* read only */
//    volatile uint32 uart_int_iden;  /*interrupt source*/
#define  IS_DSSI 0x0
#define  IS_LSI  0x6
#define  IS TBEI 0x2
#define  IS_RBFI 0x4

    volatile uint32 line_ctrl;  /* uart line control*/
#define DLAB  (1 << 7) /* enable baud rate div MSB and LSB */
#define BRK ( 1 << 6) /* set break, if set, TX data is set to 0 */
#define STICKP (1 << 5) /* Stick parity */
#define EPS (1 << 4)   /* Even parity select */
#define PE ( 1 << 3)  /* parity enable */
#define PARITY_MASK (STICKP | EPS | PE)
#define ODD_PARITY  (PE)
#define EVEN_PARITY (PE | EPS)
/* TODO:Confirm EPS for mark/space */
#define MARK_PARITY (PE | STICKP | EPS) 
#define SPACE_PARITY    (PE | STICKP)

#define STOP  (1<< 2) /* 0: 1 stop; 1: 1.5 or 2 stop*/
#define   ONE_STOP_BIT  (0 << 2)
#define   TWO_STOP_BITS (1 << 2)

#define WLS (3)   /* World Length Select */
#define WORD_LEN(x) (((x) - 5)  & WLS)
#define   FIVE_BIT_WORD     0x0
#define   SIX_BIT_WORD      0x1
#define   SEVEN_BIT_WORD    0x2
#define   EIGHT_BIT_WORD    0x3


    volatile uint32 modem_ctrl;  /* uart modem control*/
#define AFE (1 << 5) /* 0: RTS controlled by bit 1 (RTS); 1: RTS controlled by 4-byte RX FIFO status*/
#define LLB (1 << 4)
#define RTS (1 << 1) /* 0:RTS = 1; 1:RTS = 0 */
#define DTR (1 << 0)       /* 0:DTR = 1; 1:DTR = 0*/
#define S_RTS (1 << 1) /* 0:RTS = 1; 1:RTS = 0 */
#define S_DTR (1 << 0)       /* 0:DTR = 1; 1:DTR = 0*/

    volatile uint32 line_status;  /* line status register*/
    volatile uint32 modem_status;  /* modem status register*/
#define S_DCD  (1 << 7)
#define S_RI   (1 << 6)
#define S_DSR  (1 << 5)
#define S_CTS  (1 << 4)
#define S_DCDC (1 << 3)
#define S_TERI (1 << 2)
#define S_DDSR (1 << 1)
#define S_DCTS (1 << 0)

#define   FS_XOFF       (1 << 8)
#define   FS_HW         (1 << 9)

#define   SW_XON        (0 << 8)
#define   SW_XOFF       (1 << 8)
#define   HW_XON        (2 << 8)
#define   HW_XOFF       (1 << 10)

#define FLOW_MASK(x)            (3 << (((x) - 1) * 2 ))
#define FLOW(x, y)      ((y) << (((x) - 1) * 2))
#define   FLOW_XON      0x2
#define   FLOW_XOFF     0x3
 
#define TX_DIS      (1 << 17)   /* Disable transmit state machine */

#define FORCE_CHAR  (0xff << 0) /* Character to force */
    uint32 scratch;
} camry_serl_t;

/* DMA register definitions */

typedef struct camry_dma_regs_t {

    volatile uint32 status;  /* uart interrupt and fifo status reg */
#define RXNCIP    (1 << 31)   /* Normal Completion Int. Pending */
#define RXECIP    (1 << 30)   /* Error Completion Int. Pending */
#define RXNRIP    (1 << 29)   /* Not-Ready Int. Pending */
#define RXCAIP    (1 << 28)   /* Channel abort Int. Pending */
#define RXPCIP    (1 << 27)   /* Premature Completion Int. Pending */
#define RXFOFIP   (1 << 26)   /* rx fifo overflow int. pending */
#define RXFSRIP   (1 << 25)   /* rx fifo service request int. pending */
#define RXDMA_ERRORS (RXECIP | RXNRIP | RXCAIP | RXPCIP)
#define RX_INT_MASK (RXNCIP | RXDMA_ERRORS | RXFOFIP | RXFSRIP)

#define TXNCIP    (1 << 24)   /* Normal Completion Int. Pending */
#define TXECIP    (1 << 23)   /* Error Completion Int. Pending */
#define TXNRIP    (1 << 22)   /* Not-Ready Int. Pending */
#define TXCAIP    (1 << 21)   /* Channel abort Int. Pending */
#define TXFUFIP   (1 << 20)   /* tx fifo underflow int. pending */
#define TXFSRIP   (1 << 19)   /* tx fifo service request int. pending */
#define TXDMA_ERRORS (TXECIP | TXNRIP | TXCAIP)

#define MODIP    (1 << 18)  /* module interrupt pending */
#define RXPBUSY  (1 << 15)  /* for flex I/O only */
#define RX_FF    (1 << 14)  /* rx fifo full */
#define RX_FE    (1 << 13)  /* rx fifo empty */
#define TXPBUSY  (1 << 12)  /* for flex I/O only */
#define TX_FF    (1 << 11)  /* tx fifo full */
#define TX_FE    (1 << 10)  /* tx fifo empty */

    volatile uint32 rx_ctrl;  /* dma rx control reg */
#define DMA_CE   (1 << 31) /* channel enable */
#define DMA_CA   (1 << 30) /* channel abort */ 
#define DMA_FLEX (1 << 29) /* DMA controlled by flex io only on channel 0, 1 */
#define DMA_MODE (0 << 28) 
#define DIRECT_MODE (1 << 28)
#define INDEXEN     (1 << 27)
#define DMA_INDEX   (0x3ff << 0)
#define STATE_MASK  (0x3f << 10)

    volatile uint32 rx_bdp;  /* dma rx buff descriptor pointer reg */
    volatile uint32 rx_int_conf;  /* dma rx buff descriptor pointer reg */
#define RXTHRS (7 << 29)
#define RXFOFIE (1 << 26)
#define RXFSRIE (1 << 25)
#define RXNCIE    (1 << 24)   /* Normal Completion Int. Enable */
#define RXECIE    (1 << 23)   /* Error Completion Int. Enable */
#define RXNRIE    (1 << 22)   /* Not-ready Int. Enable */
#define RXCAIE    (1 << 21)   /* Channel abort Int. Enable */
#define RXPCIE    (1 << 20)   /* Premature Completion Int. Enable */

#define WRAP    (1 << 19)   /* last descriptor, read-only debug */
#define IDONE   (1 << 18)   /* interrupt on done, read-only debug */
#define LAST    (1 << 17)   /* last buffer in frame, read-only debug */
#define FULL    (1 << 16)   /* buffer full, read-only debug */
#define BLEN    (0xffff << 0)   /* remaining byte count, read-only debug */

    volatile uint32 rx_fifo_status;  /* direct mode rx fifo status reg */
    volatile uint32 rx_fifo_data;  /* direct mode rx fifo status reg */
    
    volatile uint32 tx_ctrl;  /* dma tx control reg */
    volatile uint32 tx_bdp;  /* dma tx buff descriptor pointer reg */
    volatile uint32 tx_int_conf;  /* dma tx buff descriptor pointer reg */
#define TXTHRS (0 << 29)
#define TXFUFIE (1 << 26)
#define TXFSRIE (1 << 25)
#define TXNCIE    (1 << 24)   /* Normal Completion Int. Enable */
#define TXECIE    (1 << 23)   /* Error Completion Int. Enable */
#define TXNRIE    (1 << 22)   /* Not-ready Int. Enable */
#define TXCAIE    (1 << 21)   /* Channel abort Int. Enable */

    volatile uint32 reserved;   
    volatile uint32 tx_fifo_data;  /* direct mode tx fifo status reg */
    volatile uint32 tx_fifo_data_last;  /* tx data with last status fifo write reg */
    
} camry_dma_t;
 

/* Camry DMA buffer descriptor */
typedef struct camry_dma_bmd_t {
    uint8  *src_addr;
    uint32 length;
    uint32 dst_addr; /*as reserved in camry */

#define DMA_WRAP    (1 << 15)
#define DMA_INT     (1 << 14)
#define DMA_LAST    (1 << 13)

#define DMA_FLYBY   (1 << 12)
#define DMA_FULL    DMA_FLYBY

#ifdef _LITTLE_ENDIAN
    uint16 status;
	uint16 flags; /* control */
#else
	uint16 flags; /* control */
	uint16 status;
#endif

#define DMA_MASK    (3 << 5)
#define DMA_ERR     (1 << 5)
#define DMA_MATCH   (3 << 5)
#define DMA_CLOSE   (0 << 5)


#define DMA_MATCH0  (1 << 0)
#define DMA_MATCH1  (1 << 1)
#define DMA_MATCH2  (1 << 2)
#define DMA_MATCH3  (1 << 3)
#define DMA_MATCH4  (1 << 4)

#define DMA_BGAP    (1 << 2)
#define DMA_SW_C    (1 << 1)
#define DMA_CGAP    (1)

#define DMA_RBRK    (1 << 0)
#define DMA_RFE     (1 << 1)
#define DMA_RPE     (1 << 2)
#define DMA_ROVER   (1 << 3)

} camry_bmd_t;

/*  Data declarations for shared data structs */
#define NUM_CAMRY_SERL_PORTS 4
#define NUM_BMDS_PER_CHANNEL    32

#define SERL_POLL_RATE      4 /* ms */

#define RX_BUF_SIZE     16384    /* Doubled from 8192 to improve performance at 921600 baudrate */
/* NOTE: RX_BMD_SIZE must be a multiple of the cache line size, which is
 * 32 on Mercury.
 */
#define RX_BMD_SIZE     (RX_BUF_SIZE / NUM_BMDS_PER_CHANNEL)
#define RX_BMD_HIWAT        (NUM_BMDS_PER_CHANNEL * 2 / 3)
#define RX_BMD_LOWAT        (NUM_BMDS_PER_CHANNEL / 3)
#define CH_INSERT_SIZE      4 /* Room to insert chars at end of BMD */

#define TX_BUF_SIZE     8192
#define TX_BUF_MASK     (TX_BUF_SIZE - 1)

#define CAMRY_REGS_0  ((void*)0x90011000)
#define CAMRY_REGS_1  ((void*)0x90019000)
#define CAMRY_REGS_2  ((void*)0x90021000)
#define CAMRY_REGS_3  ((void*)0x90029000)

#define DMA_CONTROL_REG0       ((void*)0x90010000)
#define DMA_CONTROL_REG1       ((void*)0x90018000)
#define DMA_CONTROL_REG2       ((void*)0x90020000)
#define DMA_CONTROL_REG3       ((void*)0x90028000)

#define CAMRY_MODULE_RESET_REGISTER (volatile unsigned long *)0xA0900180


typedef struct camry_port_struct {
    int channel;

    int serial_channel; // Overall serial channel 
    int configured;
    int opened;
    int tcdrain_req;
    uint32 openflags;

#define RWOPTIONS  (O_RDONLY|O_WRONLY|O_RDWR|O_DMA)

    camry_serl_t * serl_regs;    /* Serial configuration registers */

    /* Termios data */
    struct termios      *current_termios;
    struct serial_cntr_t    *counters;
    struct serial_status_t  *status;
    struct sigchange_stats_t    *sigchange;

    /* TX break data */
    enum brk_states breakstatus;
    int breaktime;

    /* OPOST processing data */
    write_fn_t write_fn;
    int ocol;

    /* RTS Toggle data */
    TX_TIMER rtsup_timer;
    TX_TIMER rtsdown_timer;

    /* TX and RX DMA reg */
    camry_dma_t * dma_regs;
    
    /* RX DMA data */
    uint8 rx_dma_stalled;
    uint8 rx_dma_oflowon;

    /* TODO: Note, should probably do dynamic allocation of the BMDs
     * so that we don't waste memory on products that don't use all
     * four ports */
    camry_bmd_t  *rx_bmd_start;  /* Beginning of BMD list */
    camry_bmd_t  *rx_bmd_end;    /* One past end of BMD list */
    camry_bmd_t  *rx_bmd_in; /* DMA starts filling here */
    camry_bmd_t  *rx_bmd_out;    /* driver starts reading here */
    camry_bmd_t  *rx_bmd_scan;   /* Stores partial progress */

    uint32  rx_bmd_offset; /* Chars in bmd already processed */
    uint32  rx_bmd_lsr;    /* LSR for last char of bmd */

    /* Dfrags */
    dfrag       *dfrag_in ; // see dfrag.h for dfrag & rxmsg
    dfrag       *dfrag_out ;
    dfrag       *dfrag_start ;
    dfrag       *dfrag_end ;
    uint32      avail_dfrag ;

    /* RXMsgs */
    rxmsg       *rxmsg_in ;
    rxmsg       *rxmsg_out ;
    rxmsg       *rxmsg_start ;
    rxmsg       *rxmsg_end ;
    uint32      avail_rxmsg ;

    /* Data for building messages */
    uint32      rxd_count ; // bytes in msg being built
    int         rxflags ;
#define NEEDFRAGS   1
#define NEEDMSG     2

    int         rxlnext ; // set to 2 when last char was lnext
    int         int_rxlnext ; // same, for int level

    uint32      rqbytes; /* Bytes processed by assemble_messages */
    uint32      rdbytes; /* Bytes read with netos_serlread */

    /* TX DMA data */
    camry_bmd_t  *tx_bmd_start;  /* Beginning of BMD list */
    camry_bmd_t  *tx_bmd_end;    /* One past end of BMD list */
    camry_bmd_t  *tx_bmd_in; /* driver adds here */
    camry_bmd_t  *tx_bmd_out;    /* DMA engine starts consuming here */

    struct circ_queue *tx_buffer;
    unsigned long int tx_buffer_scan;

    /* Serialize reads/writes */
    TX_MUTEX rx_mutex;
    TX_MUTEX tx_mutex;
    TX_MUTEX assemble_mutex;

    /* Blocking */
    TX_EVENT_FLAGS_GROUP    blocking_flags;
    ULONG           actual_flags;

    /* Does serl_monitor do DMA chaining or netos_serlwrite */
    int             monitor_chains; 
 
    scan_t          int_scan_type ;
    scan_t          thread_scan_type ;
    unsigned int        int_match_mask ;
    unsigned int        thread_match_mask ;

    uint32          int_flags;
#define     IFL_IXANY   (1 << 0)

#if ENABLE_TESTPAT_CHECKER
    testpat_checker_handle_t tx_testpat_handle;
    testpat_checker_handle_t rx_testpat_handle;
#endif    

#if NETWORK_STACK == TRECK
    /* Select handling. */
    uint32	    select_context;
    int		    checkMask;
#endif

	/* RTS can't be used while CTS is used for HW flow control 
	   so we use RTS pin as GPIO output pin to control RTS. Refer to NS9215/NS9210 ASIC Errata*/
	int rts_gpio_pin;  /* gpio pin name for RTS */
	int cts_gpio_pin;  /* gpio pin name for CTS */
	/*
	 * Use HW RTS toggle to support CRTSTOGGLE when predelay and post delay are zero,
	 * in this case, the RTS pin has to use the default GPIO function for RTS.
	 */
	int rts_gpio_pin_default_func;  /* gpio default configuration function for RTS */

} camry_port_t;

#define SUPPORTED_IFLAGS (IXON   | IXOFF  | IXANY   | INPCK   | IGNBRK     | \
              IGNPAR | PARMRK | DOSMODE | ISTRIP)
#define SUPPORTED_XFLAGS (XPAR   | XTOSS  | XIXON   | XALTPIN | XFORCEDCD)
#define SUPPORTED_OFLAGS (ONLCR  | OCRNL  | ONOCR   | ONLRET  | TABDLY)
#define SUPPORTED_LFLAGS 0


#if 1 /* goal */ /* TODO: get to goal */
#define SUPPORTED_CFLAGS (CSIZE  | CSTOPB | PARENB  | PARODD  | CMFLOW) 
#else /* Currently */
#define SUPPORTED_CFLAGS ( (CSIZE  | CSTOPB | PARENB  | PARODD  | CMFLOW) \
               & ~(CRTSTOGGLE) )
#endif

#endif /* __CAMRY_SERL_H__ */


