1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
/*
** @file uart.h
**
** @author M. Reek
** @authors K. Reek, Warren R. Carithers
**
** Definitions for a 16540/16550 compatible UART. Definitions are taken
** from datasheets for the National Semiconductor INS8250, NS16450, and
** NS16550 UART chips, and the PC87309 Super I/O legacy peripheral chip.
**
** The naming convention is UAx_yyy_zzzzz. "x" is either 4 or 5 (see below),
** "yyy" is the name of the register to which this value applies, and
** "zzzzz" is the name of the value or field.
**
** The UA4 prefix denotes 16540 compatible functions, available in both
** chips. The UA5 prefix denotes 16550-only functions (primarily the FIFOs).
**
** For many items there are two names: one short one that matches the name
** in the chip manual, and another that is more readable.
*/
#ifndef UART_H
#define UART_H
/*********************************************************************
***************************** I/O PORTS ******************************
*********************************************************************/
/*
** Base port number assigned to the device
*/
#define UA4_COM1_PORT 0x3f8
#define UA4_COM2_PORT 0x2f8
#define UA4_COM3_PORT 0x3e8
#define UA4_COM4_PORT 0x2e8
// short name for the one we'll use
#define UA4_PORT UA4_COM1_PORT
#define UA5_PORT UA4_COM1_PORT
/*
** Registers
**
** The 164x0 chips have the following registers. The (RO) and (WO)
** suffixes indicate read-only and write-only access.
**
** Index Register(s)
** ===== =========================================
** 0 Receiver Data (RO), Transmitter Data (WO)
** 1 Interrupt Enable
** 2 Interrupt ID (RO), FIFO Control (WO)
** 3 Line Control, Divisor Latch
** 4 Modem Control
** 5 Line Status
** 6 Modem Status
** 7 Scratch
**
** Registers indices are relative to the base I/O port for the
** specific UART port being used (e.g., for COM1, the port addresses
** are 0x3f8 through 0x3ff). When two registers share a port and have
** different access methods (RO vs. WO), a read from the port accesses
** the RO register and a write to the port access the WO register.
**
** The Line Control and Divisor Latch registers are accessed by writing
** a byte to the port; the high-order bit determines which register is
** accessed (0 selects Line Control, 1 selects Divisor Latch), with the
** remaining bits selecting fields within the indicated register.
*/
/*
** Receiver Data Register (read-only)
*/
#define UA4_RXD (UA4_PORT + 0)
#define UA4_RX_DATA UA4_RXD
/*
** Transmitter Data Register (write-only)
*/
#define UA4_TXD (UA4_PORT + 0)
#define UA4_TX_DATA UA4_TXD
/*
** Interrupt Enable Register
*/
#define UA4_IER (UA4_PORT + 1)
#define UA4_INT_ENABLE_REG UA4_IER
// fields
#define UA4_IER_RX_IE 0x01 // Rcvr High-Data-Level Int Enable
#define UA4_IER_TX_IE 0x02 // Xmitter Low-data-level Int Enable
#define UA4_IER_LS_IE 0x04 // Line Status Int Enable
#define UA4_IER_MS_IE 0x08 // Modem Status Int Enable
// aliases
#define UA4_IER_RX_INT_ENABLE UA4_IER_RX_IE
#define UA4_IER_TX_INT_ENABLE UA4_IER_TX_IE
#define UA4_IER_LINE_STATUS_INT_ENABLE UA4_IER_LS_IE
#define UA4_IER_MODEM_STATUS_INT_ENABLE UA4_IER_MS_IE
/*
** Interrupt Identification Register (read-only)
**
** a.k.a. Event Identification Register
*/
#define UA4_IIR (UA4_PORT + 2)
#define UA4_EVENT_ID UA4_IIR
// fields
#define UA4_IIR_IPF 0x01 // Interrupt Pending flag
#define UA4_IIR_IPR_MASK 0x06 // Interrupt Priority mask
#define UA4_IIR_IPR0_MASK 0x02 // IPR bit 0 mask
#define UA4_IIR_IPR1_MASK 0x04 // IPR bit 1 mask
#define UA5_IIR_RXFT 0x08 // RX_FIFO Timeout
#define UA5_IIR_FEN0 0x40 // FIFOs Enabled
#define UA5_IIR_FEN1 0x80 // FIFOs Enabled
// aliases
#define UA4_IIR_INT_PENDING UA4_IIR_IPF
#define UA4_IIR_INT_PRIORITY UA4_IIR_IPR
#define UA5_IIR_RX_FIFO_TIMEOUT UA5_IIR_RXFT
#define UA5_IIR_FIFO_ENABLED_0 UA5_IIR_FEN0
#define UA5_IIR_FIFO_ENABLED_1 UA5_IIR_FEN1
// IIR interrupt priorities (four-bit values)
#define UA4_IIR_INT_PRI_MASK 0x0f // Mask for extracting int priority
#define UA4_IIR_NO_INT 0x01 // no interrupt
#define UA4_IIR_LINE_STATUS 0x06 // line status interrupt
#define UA4_IIR_RX 0x04 // Receiver High Data Level
#define UA5_IIR_RX_FIFO 0x0c // Receiver FIFO timeout (16550)
#define UA4_IIR_TX 0x02 // Transmitter Low Data level
#define UA4_IIR_MODEM_STATUS 0x00 // Modem Status
// aliases
#define UA4_IIR_NO_INT_PENDING UA4_IIR_NO_INT
#define UA4_IIR_LINE_STATUS_INT_PENDING UA4_IIR_LINE_STATUS
#define UA4_IIR_RX_INT_PENDING UA4_IIR_RX
#define UA5_IIR_RX_FIFO_TIMEOUT_INT_PENDING UA5_IIR_RX_FIFO
#define UA4_IIR_TX_INT_PENDING UA4_IIR_TX
#define UA4_IIR_MODEM_STATUS_INT_PENDING UA4_IIR_MODEM_STATUS
/*
** FIFO Control Register (16550 only, write-only)
*/
#define UA5_FCR (UA5_PORT + 2)
#define UA5_FIFO_CTL UA5_FCR
#define UA5_FCR_FIFO_RESET 0x00 // Reset the FIFO
#define UA5_FCR_FIFO_EN 0x01 // FIFO Enable
#define UA5_FCR_RXSR 0x02 // Receiver Soft Reset
#define UA5_FCR_TXSR 0x04 // Transmitter Soft Reset
#define UA5_FCR_TXFT_MASK 0x30 // TX_FIFO threshold level mask
#define UA5_FCR_TXFT0_MASK 0x10 // TXFT bit 0 mask
#define UA5_FCR_TXFT1_MASK 0x20 // TXFT bit 1 mask
#define UA5_FCR_TX_FIFO_1 0x00 // 1 char
#define UA5_FCR_TX_FIFO_3 0x10 // 3 char
#define UA5_FCR_TX_FIFO_9 0x20 // 9 char
#define UA5_FCR_TX_FIFO_13 0x30 // 13 char
#define UA5_FCR_RXFT_MASK 0xc0 // RX_FIFO threshold level mask
#define UA5_FCR_RXFT0_MASK 0x40 // RXFT bit 0 mask
#define UA5_FCR_RXFT1_MASK 0x80 // RXFT bit 1 mask
#define UA5_FCR_RX_FIFO_1 0x00 // 1 char
#define UA5_FCR_RX_FIFO_4 0x40 // 4 char
#define UA5_FCR_RX_FIFO_8 0x80 // 8 char
#define UA5_FCR_RX_FIFO_14 0xc0 // 14 char
// aliases
#define UA5_FCR_FIFO_ENABLED UA5_FCR_FIFO_EN
#define UA5_FCR_RX_SOFT_RESET UA5_FCR_RXSR
#define UA5_FCR_TX_SOFT_RESET UA5_FCR_TXSR
#define UA5_FCR_TX_FIFO_1_CHAR UA5_FCR_TX_FIFO_1
#define UA5_FCR_TX_FIFO_3_CHAR UA5_FCR_TX_FIFO_3
#define UA5_FCR_TX_FIFO_9_CHAR UA5_FCR_TX_FIFO_9
#define UA5_FCR_TX_FIFO_13_CHAR UA5_FCR_TX_FIFO_13
#define UA5_FCR_RX_FIFO_1_CHAR UA5_FCR_RX_FIFO_1
#define UA5_FCR_RX_FIFO_4_CHAR UA5_FCR_RX_FIFO_4
#define UA5_FCR_RX_FIFO_8_CHAR UA5_FCR_RX_FIFO_8
#define UA5_FCR_RX_FIFO_14_CHAR UA5_FCR_RX_FIFO_14
/*
** Line Control Register (available in all banks)
**
** Selected when bit 7 of the value written to the port is a 0.
*/
#define UA4_LCR (UA4_PORT + 3)
#define UA4_LINE_CTL UA4_LCR
#define UA4_LCR_WLS_MASK 0x03 // Word Length Select mask
#define UA4_LCR_WLS0_MASK 0x01 // WLS bit 0 mask
#define UA4_LCR_WLS1_MASK 0x02 // WLS bit 1 mask
#define UA4_LCR_WLS_5 0x00 // 5 bits per char
#define UA4_LCR_WLS_6 0x01 // 6 bits per char
#define UA4_LCR_WLS_7 0x02 // 7 bits per char
#define UA4_LCR_WLS_8 0x03 // 8 bits per char
#define UA4_LCR_STB 0x04 // Stop Bits
#define UA4_LCR_1_STOP_BIT 0x00
#define UA4_LCR_2_STOP_BIT 0x04
#define UA4_LCR_PEN 0x08 // Parity Enable
#define UA4_LCR_EPS 0x10 // Even Parity Select
#define UA4_LCR_STKP 0x20 // Sticky Parity
#define UA4_LCR_NO_PARITY 0x00
#define UA4_LCR_ODD_PARITY UA4_LCR_PEN
#define UA4_LCR_EVEN_PARITY (UA4_LCR_PEN | UA4_LCR_EPS)
#define UA4_LCR_PARITY_LOGIC_1 (UA4_LCR_PEN | UA4_LCR_STKP)
#define UA4_LCR_PARITY_LOGIC_0 (UA4_LCR_PEN | UA4_LCR_EPS | UA4_LCR_STKP)
#define UA4_LCR_SBRK 0x40 // Set Break
#define UA4_LCR_DLAB 0x80 // Divisor Latch select bit
// aliases
#define UA4_LCR_STOP_BITS UA4_LCR_STB
#define UA4_LCR_PARITY_ENABLE UA4_LCR_PEN
#define UA4_LCR_SET_BREAK UA4_LCR_SBRK
#define UA4_LCR_BANK_SELECT_ENABLE UA4_LCR_BKSE
/*
** Divisor Latch Registers
** Divisor Latch Least Significant (DLL)
** Divisor Latch Most Significant (DLM)
**
** These contain the lower and upper halves of the 16-bit divisor for
** baud rate generation.
**
** Accessing them requires sending a command to LCR with the most
** significant bit (0x80, the DLAB field) set. This "unlocks" the
** Divisor Latch registers, which are accessed at UA4_PORT+0 and
** UA4_PORT+1 (i.e., in place of the RXD/TXD and IE registers). To
** "re-lock" the Divisor Latch registers, write a command byte to
** LCR with 0 in the DLAB bit.
*/
#define UA4_DLL (UA4_PORT + 0) // Divisor Latch (least sig.)
#define UA4_DLM (UA4_PORT + 1) // Divisor Latch (most sig.)
// aliases
#define UA4_DIVISOR_LATCH_LS UA4_DLL
#define UA4_DIVISOR_LATCH_MS UA4_DLM
// Baud rate divisor high and low bytes
#define BAUD_HIGH_BYTE(x) (((x) >> 8) & 0xff)
#define BAUD_LOW_BYTE(x) ((x) & 0xff)
// Baud rate divisors
#define DL_BAUD_50 2304
#define DL_BAUD_75 1536
#define DL_BAUD_110 1047
#define DL_BAUD_150 768
#define DL_BAUD_300 384
#define DL_BAUD_600 192
#define DL_BAUD_1200 96
#define DL_BAUD_1800 64
#define DL_BAUD_2000 58
#define DL_BAUD_2400 48
#define DL_BAUD_3600 32
#define DL_BAUD_4800 24
#define DL_BAUD_7200 16
#define DL_BAUD_9600 12
#define DL_BAUD_14400 8
#define DL_BAUD_19200 6
#define DL_BAUD_28800 4
#define DL_BAUD_38400 3
#define DL_BAUD_57600 2
#define DL_BAUD_115200 1
/*
** Modem Control Register
*/
#define UA4_MCR (UA4_PORT + 4)
#define UA4_MODEM_CTL UA4_MCR
#define UA4_MCR_DTR 0x01 // Data Terminal Ready
#define UA4_MCR_RTS 0x02 // Ready to Send
#define UA4_MCR_RILP 0x04 // Loopback Interrupt Request
#define UA4_MCR_ISEN 0x08 // Interrupt Signal Enable
#define UA4_MCR_DCDLP 0x08 // DCD Loopback
#define UA4_MCR_LOOP 0x10 // Loopback Enable
// aliases
#define UA4_MCR_DATA_TERMINAL_READY UA4_MCR_DTR
#define UA4_MCR_READY_TO_SEND UA4_MCR_RTS
#define UA4_MCR_LOOPBACK_INT_REQ UA4_MCR_RILP
#define UA4_MCR_INT_SIGNAL_ENABLE UA4_MCR_ISEN
#define UA4_MCR_LOOPBACK_DCD UA4_MCR_DCDLP
#define UA4_MCR_LOOPBACK_ENABLE UA4_MCR_LOOP
/*
** Line Status Register
*/
#define UA4_LSR (UA4_PORT + 5)
#define UA4_LINE_STATUS UA4_LSR
#define UA4_LSR_RXDA 0x01 // Receiver Data Available
#define UA4_LSR_OE 0x02 // Overrun Error
#define UA4_LSR_PE 0x04 // Parity Error
#define UA4_LSR_FE 0x08 // Framing Error
#define UA4_LSR_BRK 0x10 // Break Event Detected
#define UA4_LSR_TXRDY 0x20 // Transmitter Ready
#define UA4_LSR_TXEMP 0x40 // Transmitter Empty
#define UA4_LSR_ER_INF 0x80 // Error in RX_FIFO
// aliases
#define UA4_LSR_RX_DATA_AVAILABLE UA4_LSR_RXDA
#define UA4_LSR_OVERRUN_ERROR UA4_LSR_OE
#define UA4_LSR_PARITY_ERROR UA4_LSR_PE
#define UA4_LSR_FRAMING_ERROR UA4_LSR_FE
#define UA4_LSR_BREAK_DETECTED UA4_LSR_BRK
#define UA4_LSR_TX_READY UA4_LSR_TXRDY
#define UA4_LSR_TX_EMPTY UA4_LSR_TXEMP
#define UA4_LSR_RX_FIFO_ERROR UA4_LSR_ER_INF
/*
** Modem Status Register
*/
#define UA4_MSR (UA4_PORT + 6)
#define UA4_MODEM_STATUS UA4_MSR
#define UA4_MSR_DCTS 0x01 // Delta Clear to Send
#define UA4_MSR_DDSR 0x02 // Delta Data Set Ready
#define UA4_MSR_TERI 0x04 // Trailing Edge Ring Indicate
#define UA4_MSR_DDCD 0x08 // Delta Data Carrier Detect
#define UA4_MSR_CTS 0x10 // Clear to Send
#define UA4_MSR_DSR 0x20 // Data Set Ready
#define UA4_MSR_RI 0x40 // Ring Indicate
#define UA4_MSR_DCD 0x80 // Data Carrier Detect
// aliases
#define UA4_MSR_DELTA_CLEAR_TO_SEND UA4_MSR_DCTS
#define UA4_MSR_DELTA_DATA_SET_READY UA4_MSR_DDSR
#define UA4_MSR_TRAILING_EDGE_RING UA4_MSR_TERI
#define UA4_MSR_DELTA_DATA_CARRIER_DETECT UA4_MSR_DDCD
#define UA4_MSR_CLEAR_TO_SEND UA4_MSR_CTS
#define UA4_MSR_DATA_SET_READY UA4_MSR_DSR
#define UA4_MSR_RING_INDICATE UA4_MSR_RI
#define UA4_MSR_DATA_CARRIER_DETECT UA4_MSR_DCD
/*
** Scratch Register
**
** Not used by the UART; usable as a "scratchpad" register for
** temporary storage.
*/
#define UA4_SCR (UA4_PORT + 7)
#define UA4_SCRATCH UA4_UA5_SCR
#endif /* uart.h */
|