/******************************************************************************
 *
 *                               Sio_16552
 *
 * This module contains the serial I/O driver for the NS16552 UART.
 * and the compatible INS8250 IBM-PC card.
 * History:
 *   +----------+------------+------------------------------------------------+
 *   |   Date   |     by     |     Description                                |
 *   +----------+------------+------------------------------------------------+
 *   |          |            | Written                                        |
 *   +----------+------------+------------------------------------------------+
 * 
 * Uart is defined as array of volatile bytes.
 * The registers are defined as constants elments of the array.
 * UART_BUS_OFFSET  is default to 1.
 * 
 *****************************************************************************/
 
#ifndef UART_BUS_OFFSET
#   define UART_BUS_OFFSET   1
#endif

#define	IOP	0 * UART_BUS_OFFSET	    /* IO register                  */
#define	IER	1 * UART_BUS_OFFSET	    /* Interrupt enable register    */
#define	IIR	2 * UART_BUS_OFFSET	    /* Interrupt ident register     */
#define	FCR	2 * UART_BUS_OFFSET	    /* Fifo control register        */
#define	LCR	3 * UART_BUS_OFFSET	    /* Line control register        */
#define	MCR	4 * UART_BUS_OFFSET	    /* Modem control register       */
#define	LSR	5 * UART_BUS_OFFSET	    /* Line  status register        */
#define	MSR	6 * UART_BUS_OFFSET	    /* Modem status register        */
#define	SCR	7 * UART_BUS_OFFSET	    /* Scratch register             */
#define	DLL	0 * UART_BUS_OFFSET	    /* Divisor latch LSB            */
#define	DLM	1 * UART_BUS_OFFSET	    /* Divisor latch MSB            */
#define	AFR	2 * UART_BUS_OFFSET	    /* Alternate function register  */


#define UART0  ((volatile byte *) UART_0_ADDR)
#ifdef  UART_1_ADDR
#define UART1  ((volatile byte *) UART_1_ADDR)
#else
#define UART1 UART0
#endif

/* Frequently used bits of different registers. */

/* Frequently used bits of different registers. */
/************************************************/
#define OUT_READY    5           /* Transmit ready bit of LSRx               */
#define IN_READY     0           /* Receive  ready bit of LSRx               */
#define PORT_0_STATUS  UART0[LSR]
#define PORT_0_IO      UART0[IOP]
#define PORT_1_STATUS  UART1[LSR]
#define PORT_1_IO      UART1[IOP]

/* Primitive macros requierd by sio_d.c */
/****************************************/
 
#define READ_CHAR_IS_READY(port)  ((port) == 1 ? BIT_ON(IN_READY,UART1[LSR]) \
					       : BIT_ON(IN_READY,UART0[LSR]))
#define GET_CHAR(port)  ((port) == 1 ? UART1[IOP] : UART0[IOP])
#define READY_TO_WRITE_CHAR(port)  ((port) == 1 ? BIT_ON(OUT_READY,UART1[LSR])\
                                                : BIT_ON(OUT_READY,UART0[LSR]))
#define PUT_CHAR(port, ch)   if((port) == 1) UART1[IOP] = ch; \
                                        else UART0[IOP] = ch;

#define DIVISOR_PORT0	((unsigned) UART0[DLL] + ((unsigned) UART0[DLM] << 8))
#define DIVISOR_PORT1	((unsigned) UART1[DLL] + ((unsigned) UART1[DLM] << 8))
#define DIVISOR(divisor, port)	if(port == 1) {  \
					UART1[LCR] = 0x80;\
					divisor = DIVISOR_PORT1; \
					UART1[LCR] = 0x3; \
				} else { \
					UART0[LCR] = 0x80;\
					divisor =  DIVISOR_PORT0; \
					UART0[LCR] = 0x3; \
				}
#   define LOOPBIT	4
#   define RX_INT  0

#   define LOOPBACK(port)	((port) == 1 ? SET_BIT(LOOPBIT, UART1[MCR]): \
					SET_BIT(LOOPBIT, UART0[MCR]))
#   define INT_MODE(port)      ((port) == 1 ? SET_BIT(RX_INT, UART1[IER]) : \
					   SET_BIT (RX_INT, UART0[IER])) 
#   define INT_ENA(port)      ((port) == 1 ? SET_BIT(3, UART1[MCR]) : \
					   SET_BIT (3, UART0[MCR])) 

/*****************************************************************************
 *
 *	init_uart()
 *
 * Divisors table to initialize the uart.  Baud table:
 *    9600,   9600,   38.4K   19.2K,  9600,   4800,    2400,   1200
 * Mode of initialization     :
 *   0 ->  Polled Asynchronous
 *   1 ->  Polled Asynchronous with local loopback
 *   2 ->  Interrupt Asynchronous mode 
 *   3 ->  Interrupt Asynchronous mode with local loopback
 *
 ****************************************************************************/
    
    
private void init_uart (port, divisor, mode)
    int	    port;
    unsigned int divisor;
    int mode;  
{
    char    ch;

    if (port ==  1) {
	UART1[LCR] = 0x80; 			/* Enable divisor latch	  */ 
	 	/* Load the divisor latches according to needed baud rate */
	UART1[DLL] = (byte) (divisor & 0xff);
	UART1[DLM] = (byte) ((divisor >> 8)  & 0xff);

	UART1[LCR] = 0x3; 	/* Turn off divisor latch 		  */ 
				/* Set: 8 bits, 1 stop bit and no parity  */
	UART1[MCR] = 0xb; 	/* Initialize modem control register	  */
	UART1[FCR] = 0x0; 	/* Clear & Activate uarts fifos.  */
	UART1[FCR] = 0x1; 	/* Disable all interrupt.	  */
	UART1[IER] = 0;

	ch = UART1[IOP]; 	/* read I/O reg` to flush the uarts */
    }
    else { 

	UART0[LCR] = 0x80; 	/* Enable divisor latch		  */ 
	 	/* Load the divisor latches according to needed baud rate */
	UART0[DLL] = (byte) (divisor & 0xff);
	UART0[DLM] = (byte) ((divisor >> 8)  & 0xff);
	UART0[LCR] = 0x3; 	/* Turn off divisor latch	  */ 
				/* Set: 8 bits, 1 stop bit and no parity  */
	UART0[MCR] = 0xb; 	/* Initialize modem control register */
	UART0[FCR] = 0x0; 	/* Clear & Activate uarts fifos.  */
	UART0[FCR] = 0x1; 	/* Disable all interrupt.	  */
	UART0[IER] = 0;

	ch = UART0[IOP]; 	/* read I/O reg` to flush the uarts */
    }
    if (mode == 1 OR mode == 3) {
	LOOPBACK(port);
    }
    if (mode == 2 OR mode == 3) {
	INT_MODE(port);
	INT_ENA(port);
    }
    DELAY(10000);
    ch = UART1[IOP];
    ch = UART0[IOP];
       
}


