/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
++*/
/*--
Module Name:  
hw16950.h
Abstract:
    Type definitions and data for the 16C950 based serial port driver

Notes:
--*/

#ifndef __HW_16950_H_
#define __HW_16950_H_

#ifdef __cplusplus
extern "C" {
#endif

//
// Offsets from the base register address of the
// various registers for the 8250/16440 family of UARTS.
//
#define RECEIVE_BUFFER_REGISTER    0x00
#define TRANSMIT_HOLDING_REGISTER  0x00
#define INTERRUPT_ENABLE_REGISTER  0x01
#define INTERRUPT_IDENT_REGISTER   0x02
#define FIFO_CONTROL_REGISTER	   0x02
#define LINE_CONTROL_REGISTER	   0x03
#define MODEM_CONTROL_REGISTER	   0x04
#define LINE_STATUS_REGISTER	   0x05
#define MODEM_STATUS_REGISTER	   0x06
#define SCRATCH_REGISTER	       0x07
// Additional standard registers (access requires LCR[7] = 1)
#define DIVISOR_LATCH_LSB	       0x00
#define DIVISOR_LATCH_MSB	       0x01

// 650 compatible registers (access requires LCR = 0xBF)
#define ENHANCED_FEATURES_REGISTER 0x02
#define XON_CHARACTER_1_REGISTER   0x04
#define XON_CHARACTER_2_REGISTER   0x05
#define XOFF_CHARACTER_1_REGISTER  0x06
#define XOFF_CHARACTER_2_REGISTER  0x07

// 950 special registers
#define ADDITIONAL_STATUS_REGISTER       0x01
#define RECEIVE_FIFO_LEVEL_REGISTER      0x03
#define TRANSMIT_FIFO_LEVEL_REGISTER     0x04
#define INDEXED_CONTROL_REGISTER         0x05

// Indexed Control Registers
#define ADDITIONAL_CONTROL_REGISTER      0x00
#define CLOCK_PRESCALER_REGISTER         0x01
#define TIMES_CLOCK_REGISTER             0x02
#define CLOCK_SELECT_REGISTER            0x03
#define XMIT_INT_TRIGGER_LEVEL_REGISTER  0x04
#define RECV_INT_TRIGGER_LEVEL_REGISTER  0x05
#define RECV_FLOW_ON_LEVEL_REGISTER      0x06
#define RECV_FLOW_OFF_LEVEL_REGISTER     0x07
#define HARDWARE_ID_BYTE_1_REGISTER      0x08
#define HARDWARE_ID_BYTE_2_REGISTER      0x09
#define HARDWARE_ID_BYTE_3_REGISTER      0x0A
#define HARDWARE_REVISION_BYTE_REGISTER  0x0B
#define CHANNEL_SOFTWARE_RESET_REGISTER  0x0C
#define NINE_BIT_MODE_REGISTER           0x0D
#define MODEM_DISABLE_MASK_REGISTER      0x0E
#define READABLE_FCR_REGISTER            0x0F
#define GOOD_DATA_STATUS_REGISTER        0x10
#define DMA_STATUS_REGISTER              0x11
#define PORT_INDEX_REGISTER              0x12
#define CLOCK_ALTERNATION_REGISTER       0x13
//
// All 16950 has 128 byte depth FIFOs
//
#define SERIAL_FIFO_DEPTH 128

//
// Bitmask definitions for accessing the 8250 device registers.
//
//
// These bits define the number of data bits trasmitted in
// the Serial Data Unit (SDU - Start,data, parity, and stop bits)
//
#define SERIAL_DATA_LENGTH_5 0x00
#define SERIAL_DATA_LENGTH_6 0x01
#define SERIAL_DATA_LENGTH_7 0x02
#define SERIAL_DATA_LENGTH_8 0x03
//
// These masks define the interrupts that can be enabled or disabled.
//
//
// This interrupt is used to notify that there is new incomming
// data available.  The SERIAL_RDA interrupt is enabled by this bit.
//
#define SERIAL_IER_RDA   0x01
//
// This interrupt is used to notify that there is space available
// in the transmitter for another character.  The SERIAL_THR
// interrupt is enabled by this bit.
//
#define SERIAL_IER_THR   0x02

//
// This interrupt is used to notify that some sort of error occured
// with the incomming data.  The SERIAL_RLS interrupt is enabled by
// this bit.
#define SERIAL_IER_RLS   0x04
//
// This interrupt is used to notify that some sort of change has
// taken place in the modem control line.  The SERIAL_MS interrupt is
// enabled by this bit.
//
#define SERIAL_IER_MS    0x08

// Sleep mode enable/disable (by switching off/on internal clockof the channel
#define SERIAL_IER_SM    0x10

// Enable/disable special charactor detect interrupt
#define SERIAL_IER_SCD   0x20

// Enable/disable RTS flow control signal interrupt
#define SERIAL_IER_RTS   0x40

// Enable/disable CTS flow control signal interrupt
#define SERIAL_IER_CTS   0x80

// If bit 0 of IIR != 0, then the interrupt vector is invalid
#define SERIAL_IIR_INT_INVALID   0x01

// The bits 1..5 of the IIR indicate the source of the interrupts
#define SERIAL_IIR_INT_MASK      0x3f

//
// These defines represent the interrupt values of the interrupt identification
// register.  The values are listed below in decreasing order
// of priority.  Note that a higher ordinal value does NOT
// imply a higher priority interrupt.
//

#define SERIAL_IIR_RLS      0x06  // Receiver Line Status
#define SERIAL_IIR_RDA      0x04  // Receive Data Available
#define SERIAL_IIR_CTI      0x0C  // Character Timeout Indicator
#define SERIAL_IIR_CTI_2    0x0E  // Yet Another Character Timeout Indicator (not used by ox16c950)
#define SERIAL_IIR_THRE     0x02  // Transmit Holding Register Empty
#define SERIAL_IIR_MS       0x00  // Check Modem Status Register
#define SERIAL_IIR_XOFF     0x10  // In-band flow control Xoff of special Xoff2
#define SERIAL_IIR_CTS_RTS  0x20  // CTS or RTS change of state
//
// This bit mask get the value of the high two bits of the
// interrupt id register.  If this is a 16550/950 class chip
// these bits will be a one if the fifo's are enbled, otherwise
// they will always be zero.
//
#define SERIAL_IIR_FIFOS_ENABLED 0xc0

//
// If the low bit is logic one in the interrupt identification register
// this implies that *NO* interrupts are pending on the device.
//
#define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01

//
// These masks define access to the fifo control register.
//
//
// Enabling this bit in the fifo control register will turn
// on the fifos.  If the fifos are enabled then the high two
// bits of the interrupt id register will be set to one.  Note
// that this only occurs on a 16550/950 class chips.  If the high
// two bits in the interrupt id register are not one then
// we know we have a lower model chip.
//
//
#define SERIAL_FCR_ENABLE     ((UCHAR)0x01)
#define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02)
#define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04)

//
// This set of values define the high water marks (when the
// interrupts trip) for the receive fifo.
// ToDo: in 950 mode, receiver interrupt is controlled by RTL register
// not by FCR[7:6] like in 650 & 750 modes 
#define SERIAL_1_BYTE_HIGH_WATER   ((UCHAR)0x00)
#define SERIAL_4_BYTE_HIGH_WATER   ((UCHAR)0x40)
#define SERIAL_8_BYTE_HIGH_WATER   ((UCHAR)0x80)
#define SERIAL_14_BYTE_HIGH_WATER  ((UCHAR)0xc0)

//
// These masks define access to the line control register.
//
//
// This defines the bit used to control the definition of the "first"
// two registers for the 8250.  These registers are the input/output
// register and the interrupt enable register.  When the DLAB bit is
// enabled these registers become the least significant and most
// significant bytes of the divisor value.
//
#define SERIAL_LCR_DLAB     0x80

//
// This defines the bit used to control whether the device is sending
// a break.  When this bit is set the device is sending a space (logic 0).
//
// Most protocols will assume that this is a hangup.
//
#define SERIAL_LCR_BREAK    0x40

//
// These defines are used to set the line control register.
//
#define SERIAL_5_DATA       ((UCHAR)0x00)
#define SERIAL_6_DATA       ((UCHAR)0x01)
#define SERIAL_7_DATA       ((UCHAR)0x02)
#define SERIAL_8_DATA       ((UCHAR)0x03)
#define SERIAL_DATA_MASK    ((UCHAR)0x03)

#define SERIAL_1_STOP       ((UCHAR)0x00)
#define SERIAL_1_5_STOP     ((UCHAR)0x04) /* Only valid for 5 data bits */
#define SERIAL_2_STOP       ((UCHAR)0x04) /* Not valid for 5 data bits */
#define SERIAL_STOP_MASK    ((UCHAR)0x04)

#define SERIAL_NONE_PARITY  ((UCHAR)0x00)
#define SERIAL_ODD_PARITY   ((UCHAR)0x08)
#define SERIAL_EVEN_PARITY  ((UCHAR)0x18)
#define SERIAL_MARK_PARITY  ((UCHAR)0x28)
#define SERIAL_SPACE_PARITY ((UCHAR)0x38)
#define SERIAL_PARITY_MASK  ((UCHAR)0x38)

//
// These masks define access the modem control register.
//
//
// This bit controls the data terminal ready (DTR) line.  When
// this bit is set the line goes to logic 0 (which is then inverted
// by normal hardware).  This is normally used to indicate that
// the device is available to be used.  Some hardware
// protocols (like the kernel debugger) use this for handshaking
// purposes.
//
#define SERIAL_MCR_DTR      0x01
//
// This bit controls the ready to send (RTS) line.  When this bit
// is set the line goes to logic 0 (which is then inverted by the normal
// hardware).  This is used for hardware handshaking.  It indicates that
// the hardware is ready to send data and it is waiting for the
// receiving end to set clear to send (CTS).
//
#define SERIAL_MCR_RTS      0x02
//
// This bit is used for general purpose output.
//
#define SERIAL_MCR_OUT1     0x04

//
// OUT2 en/disables serial interrupts 
//
#define SERIAL_MCR_OUT2         0x08
#define SERIAL_MCR_IRQ_ENABLE   SERIAL_MCR_OUT2

//
// This bit controls the loopback testing mode of the device.  Basically
// the outputs are connected to the inputs (and vice versa).
//
#define SERIAL_MCR_LOOP     0x10

// Enable XON-Any
#define SERIAL_MCR_XON_ANY  0x20
// Enable IrDA format
#define SERIAL_MCR_IRDA_FMT 0x40
// Baud rate prescaler select
#define SERIAL_MCR_PRESCALE 0x80

//
// These masks define access to the line status register.  The line
// status register contains information about the status of data
// transfer.  The first five bits deal with receive data and the
// last two bits deal with transmission.  An interrupt is generated
// whenever bits 1 through 4 in this register are set.
//

//
// This bit is the data ready indicator.  It is set to indicate that
// a complete character has been received.  This bit is cleared whenever
// the receive buffer register has been read.
//

#define SERIAL_LSR_DR       0x01

//
// This is the overrun indicator.  It is set to indicate that the receive
// buffer register was not read befor a new character was transferred
// into the buffer.  This bit is cleared when this register is read.
//
#define SERIAL_LSR_OE       0x02

//
// This is the parity error indicator.  It is set whenever the hardware
// detects that the incoming serial data unit does not have the correct
// parity as defined by the parity select in the line control register.
// This bit is cleared by reading this register.
//
#define SERIAL_LSR_PE       0x04

//
// This is the framing error indicator.  It is set whenever the hardware
// detects that the incoming serial data unit does not have a valid
// stop bit.  This bit is cleared by reading this register.
//
#define SERIAL_LSR_FE       0x08

//
// This is the break interrupt indicator.  It is set whenever the data
// line is held to logic 0 for more than the amount of time it takes
// to send one serial data unit.  This bit is cleared whenever the
// this register is read.
//
#define SERIAL_LSR_BI       0x10

//
// This is the transmit holding register empty indicator.  It is set
// to indicate that the hardware is ready to accept another character
// for transmission.  This bit is cleared whenever a character is
// written to the transmit holding register.
//
#define SERIAL_LSR_THRE     0x20

//
// This bit is the transmitter empty indicator.  It is set whenever the
// transmit holding buffer is empty and the transmit shift register
// (a non-software accessable register that is used to actually put
// the data out on the wire) is empty.  Basically this means that all
// data has been sent.  It is cleared whenever the transmit holding or
// the shift registers contain data.
//
#define SERIAL_LSR_TEMT     0x40

//
// This bit indicates that there is at least one error in the fifo.
// The bit will not be turned off until there are no more errors
// in the fifo.
//

#define SERIAL_LSR_FIFOERR  0x80

// Bit 4..1 of LS indicate error in the data on top of rx fifo
#define SERIAL_LSR_ERR_MASK 0x1e

//
// These masks are used to access the modem status register.
// Whenever one of the first four bits in the modem status
// register changes state a modem status interrupt is generated.
//

//
// This bit is the delta clear to send.  It is used to indicate
// that the clear to send bit (in this register) has *changed*
// since this register was last read by the CPU.
//
#define SERIAL_MSR_DCTS     0x01
//
// This bit is the delta data set ready.  It is used to indicate
// that the data set ready bit (in this register) has *changed*
// since this register was last read by the CPU.
//
#define SERIAL_MSR_DDSR     0x02
//
// This is the trailing edge ring indicator.  It is used to indicate
// that the ring indicator input has changed from a low to high state.
//
#define SERIAL_MSR_TERI     0x04

//
// This bit is the delta data carrier detect.  It is used to indicate
// that the data carrier bit (in this register) has *changed*
// since this register was last read by the CPU.
//
#define SERIAL_MSR_DDCD     0x08

//
// This bit contains the (complemented) state of the clear to send
// (CTS) line.
//
#define SERIAL_MSR_CTS      0x10

//
// This bit contains the (complemented) state of the data set ready
// (DSR) line.
//
#define SERIAL_MSR_DSR      0x20

//
// This bit contains the (complemented) state of the ring indicator
// (RI) line.
//
#define SERIAL_MSR_RI       0x40

//
// This bit contains the (complemented) state of the data carrier detect
// (DCD) line.
//
#define SERIAL_MSR_DCD      0x80
// 
// Enhanced Features Register EFR
//
// select in-band receive flow control mode
#define SERIAL_EFR_RECV_FLOW_CTRL_DISABLE   0x00
#define SERIAL_EFR_RECV_FLOW_CTRL_X2        0x01
#define SERIAL_EFR_RECV_FLOW_CTRL_X1        0x02
#define SERIAL_EFR_RECV_FLOW_CTRL_X1_X2     0x03
#define SERIAL_EFR_RECV_FLOW_CTRL_MASK      0x03
// select in-band transmit flow control mode
#define SERIAL_EFR_XMIT_FLOW_CTRL_DISABLE   (0x00 << 2)
#define SERIAL_EFR_XMIT_FLOW_CTRL_X2        (0x01 << 2)
#define SERIAL_EFR_XMIT_FLOW_CTRL_X1        (0x02 << 2)
#define SERIAL_EFR_XMIT_FLOW_CTRL_MASK      (0x03 << 2)
// Enable enhanced mode
#define SERIAL_EFR_ENABLE_ENHANCED_MODE     0x10
// Enable special charactor detection
#define SERIAL_EFR_SPECIAL_CHAR_DETECT      0x20
//Enable automatic RTS flow control
#define SERIAL_EFR_AUTO_RTS_FLOW_CTRL       0x40
//Enable automatic RTS flow control
#define SERIAL_EFR_AUTO_CTS_FLOW_CTRL       0x80

//
// Additional Control Register ACR
//
// Receiver disabled
#define SERIAL_ACR_RECVER_DISABLE  0x01
// Transmitter disabled
#define SERIAL_ACR_XMITER_DISABLE  0x02
// Enable DSR flow control
#define SERIAL_ACR_DSR_FLOW_CTRL    0x04
//
#define SERIAL_ACR_DTR_MODE_MASK    (0x03 << 3)
// 16550 DSR flow control mode
#define SERIAL_ACR_DTR_550_MODE     (0x00 << 3)
// 16950 DSR flow control mode
#define SERIAL_ACR_DTR_950_MODE     (0x01 << 3)
#define SERIAL_ACR_DTR_485_MODE     (0x01 << 4)
// DTR drive active low RS485 buffer
#define SERIAL_ACR_DTR_485_LOW      (0x02 << 3)
// DTR drive active high RS485 buffer
#define SERIAL_ACR_DTR_485_HIGH     (0x03 << 3)
// 16950 mode trigger levels enable
#define SERIAL_ACR_950_TRIG_MODE    0x20
// ICR Read Enable
#define SERIAL_ACR_ICR_READ_ENABLE  0x40
// Additional status enable
#define SERIAL_ACR_ADDITIONAL_STATUS 0x80

//
// Additional Status Register
// 
// Transmitter is disabled by receiving Xoff
#define SERIAL_ASR_XMITER_DISABLED  0x01
// Remote transmitter is disabled/enabled by sending Xoff/Xon
#define SERIAL_ASR_REMOTE_DISABLED  0x02
// Transmitter is idle
#define SERIAL_ASR_XMITER_IS_IDLE   0x80

//
// This should be more than enough space to hold then
// numeric suffix of the device name.
//
#define DEVICE_NAME_DELTA 20

//
// Default xon/xoff characters.
//
#define SERIAL_DEF_XON  0x11
#define SERIAL_DEF_XOFF 0x13

//
// Reasons that recption may be held up.
//
#define SERIAL_RX_DTR	    ((UCHAR)0x01)
#define SERIAL_RX_XOFF	    ((UCHAR)0x02)
#define SERIAL_RX_RTS	    ((UCHAR)0x04)
#define SERIAL_RX_DSR	    ((UCHAR)0x08)

//
// Reasons that transmission may be held up.
//
#define SERIAL_TX_CTS	    ((UCHAR)0x01)
#define SERIAL_TX_DSR	    ((UCHAR)0x02)
#define SERIAL_TX_DCD	    ((UCHAR)0x04)
#define SERIAL_TX_XOFF	    ((UCHAR)0x08)
#define SERIAL_TX_BREAK     ((UCHAR)0x10)

//
// These values are used by the routines that can be used
// to complete a read (other than interval timeout) to indicate
// to the interval timeout that it should complete.
//
#define SERIAL_COMPLETE_READ_CANCEL ((CHAR)-1)
#define SERIAL_COMPLETE_READ_TOTAL ((CHAR)-2)
#define SERIAL_COMPLETE_READ_COMPLETE ((CHAR)-3)

// Macros for 650 compatible register access
#define ENABLE_650_REGISTER_ACCESS 0xBF

#ifdef __cplusplus
}
#endif

#endif // __HW_16950_H_

