#define PORT_STATUS_OPEN 1
#define PORT_STATUS_TXMSB 2
#define PORT_STATUS_PAR 4
#define PORT_STATUS_PARODD 8
#define PORT_STATUS_8PLUS1 16
#define PORT_STATUS_SHIRQ 32
struct tsuart_port {
  struct uart_port u;
  struct tsuart_port *nextd; // next tsuart_port with different IRQ
                             // must be NULL unless root == this
  struct tsuart_port *next;  // next tsuart_port with same IRQ
  struct tsuart_port *root;  // first tsuart_port with same IRQ
  unsigned (*get)(struct tsuart_port *,int); // get register function
  void (*put)(struct tsuart_port *,int,unsigned); // put register function
  int debugFlags;
  int gotBytes;
  int data;
  int *portStatus,pstatus,rxsize,localStatus;
  struct uart_driver *driver;
  unsigned *parity;
  int dataMask,dataMask2;
  int boardId; // gives us a way to associate a port with a board
  int (*mdmctrl)(struct tsuart_port *,int cmd);
  unsigned int old_status;
};
#define TSPORT(port) ((struct tsuart_port *)port)

#define PORTNUM(port) port->line
MODULE_AUTHOR("Technologic Systems");
MODULE_LICENSE("Dual BSD/GPL"); 

// accepts the value read from the TS UART STAT register
// returns TRUE if the TBRE bit is set, and FALSE if it is clear
static inline int bit_TBRE(unsigned char reg_value) {
  return (reg_value & 0x01) == 0x01;
}

// accepts the value read from the TS UART STAT register
// returns TRUE if the DR bit is set, and FALSE if it is clear
static inline int bit_DR(unsigned char reg_value) {
  return (reg_value & 0x02) == 0x02;
}

// accepts the value read from the TS UART STAT register
// returns TRUE if the OERR bit is set, and FALSE if it is clear
static inline int bit_OERR(unsigned char reg_value) {
  return (reg_value & 0x04) == 0x04;
}

// accepts the value read from the TS UART STAT register
// returns TRUE if the CTS bit is set, and FALSE if it is clear
static inline int bit_CTS(unsigned char reg_value) {
  return (reg_value & 0x08) == 0x08;
}

// accepts the value read from the TS UART STAT register
// returns TRUE if the RTS bit is set, and FALSE if it is clear
static inline int bit_RTS(unsigned char reg_value) {
  return (reg_value & 0x10) == 0x10;
}

// accepts the value read from the TS UART STAT register
// If set is TRUE, sets the RTS bit, others clears it,
// and returns the new value to be written back to the STAT register
static inline unsigned assign_bit_RTS(unsigned reg_value,int set) {
  return (reg_value & ~0x10) | (set ? 0x10 : 0);
}

static inline unsigned short assign_bit_MODE9(unsigned reg_value,int set)
{
  return (reg_value & ~0x100) | (set ? 0x100 : 0);
}

static int portDebug=0;
MODULE_PARM(portDebug,"i");

extern int tsuart_register_port(struct uart_driver *,struct tsuart_port *);
extern int tsuart_unregister_port(struct tsuart_port *);
extern unsigned tsuartGetIO8(struct tsuart_port *,int offset);
extern void tsuartPutIO8(struct tsuart_port *,int offset,unsigned value);
extern unsigned tsuartGetMEM8(struct tsuart_port *port,int offset);
extern unsigned tsuartGetMEM16(struct tsuart_port *port,int offset);
extern unsigned tsuartGetMEM16_9(struct tsuart_port *port,int offset);
extern void tsuartPutMEM8(struct tsuart_port *port,int offset,unsigned value);
extern void tsuartPutMEM16(struct tsuart_port *port,int offset,unsigned value);
extern void tsuartPutMEM16_9(struct tsuart_port *port,int offset,unsigned value);
extern int tsuart_configure_driver(struct uart_driver *dr,int major,int minor,
				   char *tty,char *cua,int maxports);


#define UART_CLOCK	14745600	// not used
#define UART_FIFOSIZE	5		// not used
#define TS_MODEL_REG 0x2000000

#define TS_MODEL_7200 0
#define TS_MODEL_7250 1
#define TS_MODEL_7260 2
#define TS_MODEL_7300 3
#define TS_MODEL_7400 4
#define TS_MODEL_JNS200 6
#define TS_MODEL_PAC4 2  // really going to be 5 

static inline int get_ts_model(void) {
  return (inw(TS7XXX_IO16_BASE + TS_MODEL_REG)) & 7;
}

// This is inline for a couple of reasons:
// 1. We want to share the code among all driver modules
// 2. We don't want to put it in the core module, as its initialization
#ifndef TSUART_CORE
static inline void init_tsuart_port(struct tsuart_port *p) {
  p->u.irq = 0;
  p->u.uartclk = UART_CLOCK;
  p->u.fifosize = UART_FIFOSIZE;
  p->u.ops = 0;
  p->u.flags = ASYNC_BOOT_AUTOCONF;
  p->u.line = 0;
  p->u.iobase = 0;
  p->u.membase = 0;
  p->u.mapbase = 0;
  p->nextd = p->next = p->root = 0;
  p->get = 0;
  p->put = 0;
  p->debugFlags = 0;
  p->gotBytes = 0;
  p->data = 0;
  p->rxsize = 1;
  p->parity = 0;
  p->dataMask = p->dataMask2 = 0xFF;
  p->localStatus = 0;
  p->portStatus = 0;
  p->boardId = 0;
}
#endif
