/*      $NetBSD: scnvar.h,v 1.2 2012/10/27 17:18:09 chs Exp $   */

/*
* Copyright (c) 1996, 1997 Philip L. Budne.
* Copyright (c) 1993 Philip A. Nelson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
*    must display the following acknowledgement:
*      This product includes software developed by Philip A. Nelson.
* 4. The name of Philip A. Nelson may not be used to endorse or promote
*    products derived from this software without specific prior written
*    permission.
*
* THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL PHILIP NELSON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*      scnvar.h: definitions for pc532 2681/2692/26c96 duart driver
*/

/* Constants. */
#ifdef COMDEF_SPEED
#undef  TTYDEF_SPEED
#define TTYDEF_SPEED    COMDEF_SPEED    /* default baud rate */
#endif

#define SCN_SIZE                 0x8    /* address space for port */

#define SCN_CONSOLE                0    /* minor number of console */
#define SCN_CONSDUART              0
#define SCN_CONSCHAN               0

/* output port bits */
#define OP_RTSA         OP_OP0
#define OP_RTSB         OP_OP1
#define OP_DTRA         OP_OP2
#define OP_DTRB         OP_OP3
/* OP4-7 not connected */

/* input port bits */
#define IP_CTSA         IP_IP0
#define IP_CTSB         IP_IP1
#define IP_DCDB         IP_IP2
#define IP_DCDA         IP_IP3
/* IP4-6 not connected */

#define ACR_DELTA_CTSA  ACR_DELTA_IP0
#define ACR_DELTA_CTSB  ACR_DELTA_IP1
#define ACR_DELTA_DCDB  ACR_DELTA_IP2
#define ACR_DELTA_DCDA  ACR_DELTA_IP3

#define IPCR_CTSA       IPCR_IP0
#define IPCR_CTSB       IPCR_IP1
#define IPCR_DCDB       IPCR_IP2
#define IPCR_DCDA       IPCR_IP3
#define IPCR_DELTA_CTSA IPCR_DELTA_IP0
#define IPCR_DELTA_CTSB IPCR_DELTA_IP1
#define IPCR_DELTA_DCDB IPCR_DELTA_IP2
#define IPCR_DELTA_DCDA IPCR_DELTA_IP3

#define SCN_OP_BIS(SC,VAL) ((SC)->sc_duart->base[DU_OPSET] = (VAL))
#define SCN_OP_BIC(SC,VAL) ((SC)->sc_duart->base[DU_OPCLR] = (VAL))

#define SCN_DCD(SC) (((SC)->sc_duart->base[DU_IP] & (SC)->sc_ip_dcd) == 0)

/* pc532 duarts are auto-sized to byte-wide */
#define CH_SZ           8
#define DUART_SZ        16
#define SCN_REG(n)      (n << 4)                /* 15 byte pad after each reg */

/* The DUART description struct; for data common to both channels */
struct duart {
       volatile u_char *base;
       struct chan {
               struct scn_softc *sc;
               struct tty *tty;
               int32_t ispeed, ospeed;
               u_char icode, ocode;
               u_char mr0;                     /* MR0[7:3] */
               u_char new_mr1;         /* held changes */
               u_char new_mr2;         /* held changes */
       } chan[2];
       enum scntype { SCNUNK, SCN2681, SCN2692, SC26C92 } type;
       uint16_t counter;               /* C/T generated bps, or zero */
       uint16_t ocounter;              /* last C/T generated bps, or zero */
       u_char  mode;                   /* ACR[7] + MR0[2:0] */
       u_char  acr;                    /* ACR[6:0]*/
       u_char  imr;                    /* IMR bits */
       u_char  opcr;                   /* OPCR bits */
};

#define SCN_RING_BITS   9       /* 512 byte buffers */
#define SCN_RING_SIZE   (1<<SCN_RING_BITS)      /* must be a power of two */
#define SCN_RING_MASK   (SCN_RING_SIZE-1)
#define SCN_RING_THRESH (SCN_RING_SIZE/2)
#define SCN_RING_HIWAT  (SCN_RING_SIZE - (SCN_RING_SIZE >> 2))

/* scn channel state */
struct scn_softc {
       struct tty *sc_tty;
       int     sc_unit;                /* unit number of this line (base 0) */
       int     sc_channel;
       int     sc_isconsole;
       int     sc_iskgdb;
       struct duart *sc_duart; /* pointer to duart struct */
       volatile u_char *sc_chbase;     /* per-channel registers (CH_xxx) */
       u_char  sc_swflags;             /* from config / TIOCxFLAGS */
#define SCN_SW_SOFTCAR  0x01
#define SCN_SW_CLOCAL   0x02
#define SCN_SW_CRTSCTS  0x04
#define SCN_SW_MDMBUF   0x08            /* not implemented */

/* I wish there was a TS_DIALOUT flag! */
       u_char  sc_dialout;             /* set if open for dialout */
#define SCN_DIALOUT(SCN) ((SCN)->sc_dialout)
#define SCN_SETDIALOUT(SCN) (SCN)->sc_dialout = 1
#define SCN_CLRDIALOUT(SCN) (SCN)->sc_dialout = 0

       u_char  sc_heldchanges;         /* waiting for output done */

/* bits in input port register */
       u_char  sc_ip_dcd;
       u_char  sc_ip_cts;

/* bits in output port registers */
       u_char  sc_op_rts;
       u_char  sc_op_dtr;

/* interrupt mask bits */
       u_char  sc_tx_int;
       u_char  sc_rx_int;

/* counters */
       u_long  sc_framing_errors;
       u_long  sc_parity_errors;
       u_long  sc_fifo_overruns;
       u_long  sc_breaks;

/* ring buffer for rxrdy interrupt */
       u_int   sc_rbget;               /* ring buffer `get' index */
       volatile u_int sc_rbput;        /* ring buffer `put' index */
       int     sc_rbhiwat;
       short   sc_rbuf[SCN_RING_SIZE]; /* status + data */
       long    sc_fotime;              /* last fifo overrun message */
       long    sc_rotime;              /* last ring overrun message */
       u_long  sc_ring_overruns;       /* number of ring buffer overruns */
       /* Flags to communicate with scntty_softint() */
       volatile char sc_rx_blocked;    /* input block at ring */
};