4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
21 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
23 /* All Rights Reserved */
26 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
33 #pragma ident "%Z%%M% %I% %E% SMI"
40 #include <sys/ksynch.h>
41 #include <sys/dditypes.h>
44 * internal bus type naming
46 #define ASY_BUS_PCI (0)
47 #define ASY_BUS_ISA (1)
48 #define ASY_BUS_UNKNOWN (-1)
50 #define ASY_MINOR_LEN (40)
52 #define COM1_IOADDR 0x3f8
53 #define COM2_IOADDR 0x2f8
54 #define COM3_IOADDR 0x3e8
55 #define COM4_IOADDR 0x2e8
58 * Definitions for INS8250 / 16550 chips
61 /* defined as offsets from the data register */
62 #define DAT 0 /* receive/transmit data */
63 #define ICR 1 /* interrupt control register */
64 #define ISR 2 /* interrupt status register */
65 #define LCR 3 /* line control register */
66 #define MCR 4 /* modem control register */
67 #define LSR 5 /* line status register */
68 #define MSR 6 /* modem status register */
69 #define SCR 7 /* scratch register */
70 #define DLL 0 /* divisor latch (lsb) */
71 #define DLH 1 /* divisor latch (msb) */
72 #define FIFOR ISR /* FIFO register for 16550 */
73 #define EFR ISR /* Enhanced feature register for 16650 */
76 * INTEL 8210-A/B & 16450/16550 Registers Structure.
79 /* Line Control Register */
80 #define WLS0 0x01 /* word length select bit 0 */
81 #define WLS1 0x02 /* word length select bit 2 */
82 #define STB 0x04 /* number of stop bits */
83 #define PEN 0x08 /* parity enable */
84 #define EPS 0x10 /* even parity select */
85 #define SETBREAK 0x40 /* break key */
86 #define DLAB 0x80 /* divisor latch access bit */
87 #define RXLEN 0x03 /* # of data bits per received/xmitted char */
94 #define EFRACCESS 0xBF /* magic value for 16650 EFR access */
96 #define BITS5 0x00 /* 5 bits per char */
97 #define BITS6 0x01 /* 6 bits per char */
98 #define BITS7 0x02 /* 7 bits per char */
99 #define BITS8 0x03 /* 8 bits per char */
101 /* Line Status Register */
102 #define RCA 0x01 /* data ready */
103 #define OVRRUN 0x02 /* overrun error */
104 #define PARERR 0x04 /* parity error */
105 #define FRMERR 0x08 /* framing error */
106 #define BRKDET 0x10 /* a break has arrived */
107 #define XHRE 0x20 /* tx hold reg is now empty */
108 #define XSRE 0x40 /* tx shift reg is now empty */
109 #define RFBE 0x80 /* rx FIFO Buffer error */
111 /* Interrupt Id Regisger */
112 #define MSTATUS 0x00 /* modem status changed */
113 #define NOINTERRUPT 0x01 /* no interrupt pending */
114 #define TxRDY 0x02 /* Transmitter Holding Register Empty */
115 #define RxRDY 0x04 /* Receiver Data Available */
116 #define FFTMOUT 0x0c /* FIFO timeout - 16550AF */
117 #define RSTATUS 0x06 /* Receiver Line Status */
119 /* Interrupt Enable Register */
120 #define RIEN 0x01 /* Received Data Ready */
121 #define TIEN 0x02 /* Tx Hold Register Empty */
122 #define SIEN 0x04 /* Receiver Line Status */
123 #define MIEN 0x08 /* Modem Status */
125 /* Modem Control Register */
126 #define DTR 0x01 /* Data Terminal Ready */
127 #define RTS 0x02 /* Request To Send */
128 #define OUT1 0x04 /* Aux output - not used */
129 #define OUT2 0x08 /* turns intr to 386 on/off */
130 #define ASY_LOOP 0x10 /* loopback for diagnostics */
132 /* Modem Status Register */
133 #define DCTS 0x01 /* Delta Clear To Send */
134 #define DDSR 0x02 /* Delta Data Set Ready */
135 #define DRI 0x04 /* Trail Edge Ring Indicator */
136 #define DDCD 0x08 /* Delta Data Carrier Detect */
137 #define CTS 0x10 /* Clear To Send */
138 #define DSR 0x20 /* Data Set Ready */
139 #define RI 0x40 /* Ring Indicator */
140 #define DCD 0x80 /* Data Carrier Detect */
142 #define DELTAS(x) ((x)&(DCTS|DDSR|DRI|DDCD))
143 #define STATES(x) ((x)&(CTS|DSR|RI|DCD))
145 /* flags for FCR (FIFO Control register) */
146 #define FIFO_OFF 0x00 /* fifo disabled */
147 #define FIFO_ON 0x01 /* fifo enabled */
148 #define FIFORXFLSH 0x02 /* flush receiver FIFO */
149 #define FIFOTXFLSH 0x04 /* flush transmitter FIFO */
150 #define FIFODMA 0x08 /* DMA mode 1 */
151 #define FIFOEXTRA1 0x10 /* Longer fifos on some 16650's */
152 #define FIFOEXTRA2 0x20 /* Longer fifos on some 16650's and 16750 */
153 #define FIFO_TRIG_1 0x00 /* 1 byte trigger level */
154 #define FIFO_TRIG_4 0x40 /* 4 byte trigger level */
155 #define FIFO_TRIG_8 0x80 /* 8 byte trigger level */
156 #define FIFO_TRIG_14 0xC0 /* 14 byte trigger level */
158 /* Serial in/out requests */
160 #define OVERRUN 040000
161 #define FRERROR 020000
162 #define PERROR 010000
163 #define S_ERRORS (PERROR|OVERRUN|FRERROR)
165 /* EFR - Enhanced feature register for 16650 */
166 #define ENHENABLE 0x10
168 /* SCR - scratch register */
169 #define SCRTEST 0x5a /* arbritrary value for testing SCR register */
172 * Ring buffer and async line management definitions.
174 #define RINGBITS 10 /* # of bits in ring ptrs */
175 #define RINGSIZE (1<<RINGBITS) /* size of ring */
176 #define RINGMASK (RINGSIZE-1)
177 #define RINGFRAC 8 /* fraction of ring to force flush */
179 #define RING_INIT(ap) ((ap)->async_rput = (ap)->async_rget = 0)
180 #define RING_CNT(ap) (((ap)->async_rput >= (ap)->async_rget) ? \
181 ((ap)->async_rput - (ap)->async_rget):\
182 ((0x10000 - (ap)->async_rget) + (ap)->async_rput))
183 #define RING_FRAC(ap) ((int)RING_CNT(ap) >= (int)(RINGSIZE/RINGFRAC))
184 #define RING_POK(ap, n) ((int)RING_CNT(ap) < (int)(RINGSIZE-(n)))
185 #define RING_PUT(ap, c) \
186 ((ap)->async_ring[(ap)->async_rput++ & RINGMASK] = (uchar_t)(c))
187 #define RING_UNPUT(ap) ((ap)->async_rput--)
188 #define RING_GOK(ap, n) ((int)RING_CNT(ap) >= (int)(n))
189 #define RING_GET(ap) ((ap)->async_ring[(ap)->async_rget++ & RINGMASK])
190 #define RING_EAT(ap, n) ((ap)->async_rget += (n))
191 #define RING_MARK(ap, c, s) \
192 ((ap)->async_ring[(ap)->async_rput++ & RINGMASK] = ((uchar_t)(c)|(s)))
193 #define RING_UNMARK(ap) \
194 ((ap)->async_ring[((ap)->async_rget) & RINGMASK] &= ~S_ERRORS)
195 #define RING_ERR(ap, c) \
196 ((ap)->async_ring[((ap)->async_rget) & RINGMASK] & (c))
199 * Asy tracing macros. These are a bit similar to some macros in sys/vtrace.h .
201 * XXX - Needs review: would it be better to use the macros in sys/vtrace.h ?
204 #define DEBUGWARN0(fac, format) \
206 cmn_err(CE_WARN, format)
207 #define DEBUGNOTE0(fac, format) \
209 cmn_err(CE_NOTE, format)
210 #define DEBUGNOTE1(fac, format, arg1) \
212 cmn_err(CE_NOTE, format, arg1)
213 #define DEBUGNOTE2(fac, format, arg1, arg2) \
215 cmn_err(CE_NOTE, format, arg1, arg2)
216 #define DEBUGNOTE3(fac, format, arg1, arg2, arg3) \
218 cmn_err(CE_NOTE, format, arg1, arg2, arg3)
219 #define DEBUGCONT0(fac, format) \
221 cmn_err(CE_CONT, format)
222 #define DEBUGCONT1(fac, format, arg1) \
224 cmn_err(CE_CONT, format, arg1)
225 #define DEBUGCONT2(fac, format, arg1, arg2) \
227 cmn_err(CE_CONT, format, arg1, arg2)
228 #define DEBUGCONT3(fac, format, arg1, arg2, arg3) \
230 cmn_err(CE_CONT, format, arg1, arg2, arg3)
231 #define DEBUGCONT4(fac, format, arg1, arg2, arg3, arg4) \
233 cmn_err(CE_CONT, format, arg1, arg2, arg3, arg4)
234 #define DEBUGCONT10(fac, format, \
235 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \
237 cmn_err(CE_CONT, format, \
238 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
240 #define DEBUGWARN0(fac, format)
241 #define DEBUGNOTE0(fac, format)
242 #define DEBUGNOTE1(fac, format, arg1)
243 #define DEBUGNOTE2(fac, format, arg1, arg2)
244 #define DEBUGNOTE3(fac, format, arg1, arg2, arg3)
245 #define DEBUGCONT0(fac, format)
246 #define DEBUGCONT1(fac, format, arg1)
247 #define DEBUGCONT2(fac, format, arg1, arg2)
248 #define DEBUGCONT3(fac, format, arg1, arg2, arg3)
249 #define DEBUGCONT4(fac, format, arg1, arg2, arg3, arg4)
250 #define DEBUGCONT10(fac, format, \
251 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
255 * Hardware channel common data. One structure per port.
256 * Each of the fields in this structure is required to be protected by a
257 * mutex lock at the highest priority at which it can be altered.
258 * The asy_flags, and asy_next fields can be altered by interrupt
259 * handling code that must be protected by the mutex whose handle is
260 * stored in asy_excl_hi. All others can be protected by the asy_excl
261 * mutex, which is lower priority and adaptive.
265 int asy_flags
; /* random flags */
266 /* protected by asy_excl_hi lock */
267 uint_t asy_hwtype
; /* HW type: ASY16550A, etc. */
268 uint_t asy_use_fifo
; /* HW FIFO use it or not ?? */
269 uint_t asy_fifo_buf
; /* With FIFO = 16, otherwise = 1 */
270 uint_t asy_flags2
; /* flags which don't change, no lock */
271 uint8_t *asy_ioaddr
; /* i/o address of ASY port */
272 struct asyncline
*asy_priv
; /* protocol private data -- asyncline */
273 dev_info_t
*asy_dip
; /* dev_info */
274 int asy_unit
; /* which port */
275 ddi_iblock_cookie_t asy_iblock
;
276 kmutex_t asy_excl
; /* asy adaptive mutex */
277 kmutex_t asy_excl_hi
; /* asy spinlock mutex */
280 * The asy_soft_sr mutex should only be taken by the soft interrupt
281 * handler and the driver DDI_SUSPEND/DDI_RESUME code. It
282 * shouldn't be taken by any code that may get called indirectly
283 * by the soft interrupt handler (e.g. as a result of a put or
286 kmutex_t asy_soft_sr
; /* soft int suspend/resume mutex */
287 uchar_t asy_msr
; /* saved modem status */
288 uchar_t asy_mcr
; /* soft carrier bits */
289 uchar_t asy_lcr
; /* console lcr bits */
290 uchar_t asy_bidx
; /* console baud rate index */
291 tcflag_t asy_cflag
; /* console mode bits */
292 struct cons_polledio polledio
; /* polled I/O functions */
293 ddi_acc_handle_t asy_iohandle
; /* Data access handle */
294 tcflag_t asy_ocflag
; /* old console mode bits */
295 uchar_t asy_com_port
; /* COM port number, or zero */
296 uchar_t asy_fifor
; /* FIFOR register setting */
298 int asy_msint_cnt
; /* number of times in async_msint */
303 * Asychronous protocol private data structure for ASY.
304 * Each of the fields in the structure is required to be protected by
305 * the lower priority lock except the fields that are set only at
306 * base level but cleared (with out lock) at interrupt level.
310 int async_flags
; /* random flags */
311 kcondvar_t async_flags_cv
; /* condition variable for flags */
312 kcondvar_t async_ops_cv
; /* condition variable for async_ops */
313 dev_t async_dev
; /* device major/minor numbers */
314 mblk_t
*async_xmitblk
; /* transmit: active msg block */
315 struct asycom
*async_common
; /* device common data */
316 tty_common_t async_ttycommon
; /* tty driver common data */
317 bufcall_id_t async_wbufcid
; /* id for pending write-side bufcall */
318 size_t async_wbufcds
; /* Buffer size requested in bufcall */
319 timeout_id_t async_polltid
; /* softint poll timeout id */
320 timeout_id_t async_dtrtid
; /* delaying DTR turn on */
321 timeout_id_t async_utbrktid
; /* hold minimum untimed break time id */
324 * The following fields are protected by the asy_excl_hi lock.
325 * Some, such as async_flowc, are set only at the base level and
326 * cleared (without the lock) only by the interrupt level.
328 uchar_t
*async_optr
; /* output pointer */
329 int async_ocnt
; /* output count */
330 ushort_t async_rput
; /* producing pointer for input */
331 ushort_t async_rget
; /* consuming pointer for input */
334 * Each character stuffed into the ring has two bytes associated
335 * with it. The first byte is used to indicate special conditions
336 * and the second byte is the actual data. The ring buffer
337 * needs to be defined as ushort_t to accomodate this.
339 ushort_t async_ring
[RINGSIZE
];
341 short async_break
; /* break count */
342 int async_inflow_source
; /* input flow control type */
346 uchar_t _hw
; /* overrun (hw) */
347 uchar_t _sw
; /* overrun (sw) */
349 ushort_t uover_overrun
;
351 #define async_overrun async_uover._a.uover_overrun
352 #define async_hw_overrun async_uover._a._hw
353 #define async_sw_overrun async_uover._a._sw
354 short async_ext
; /* modem status change count */
355 short async_work
; /* work to do flag */
356 timeout_id_t async_timer
; /* close drain progress timer */
358 mblk_t
*async_suspqf
; /* front of suspend queue */
359 mblk_t
*async_suspqb
; /* back of suspend queue */
360 int async_ops
; /* active operations counter */
363 /* definitions for async_flags field */
364 #define ASYNC_EXCL_OPEN 0x10000000 /* exclusive open */
365 #define ASYNC_WOPEN 0x00000001 /* waiting for open to complete */
366 #define ASYNC_ISOPEN 0x00000002 /* open is complete */
367 #define ASYNC_OUT 0x00000004 /* line being used for dialout */
368 #define ASYNC_CARR_ON 0x00000008 /* carrier on last time we looked */
369 #define ASYNC_STOPPED 0x00000010 /* output is stopped */
370 #define ASYNC_DELAY 0x00000020 /* waiting for delay to finish */
371 #define ASYNC_BREAK 0x00000040 /* waiting for break to finish */
372 #define ASYNC_BUSY 0x00000080 /* waiting for transmission to finish */
373 #define ASYNC_DRAINING 0x00000100 /* waiting for output to drain */
374 #define ASYNC_SERVICEIMM 0x00000200 /* queue soft interrupt as soon as */
375 #define ASYNC_HW_IN_FLOW 0x00000400 /* input flow control in effect */
376 #define ASYNC_HW_OUT_FLW 0x00000800 /* output flow control in effect */
377 #define ASYNC_PROGRESS 0x00001000 /* made progress on output effort */
378 #define ASYNC_CLOSING 0x00002000 /* processing close on stream */
379 #define ASYNC_OUT_SUSPEND 0x00004000 /* waiting for TIOCSBRK to finish */
380 #define ASYNC_HOLD_UTBRK 0x00008000 /* waiting for untimed break hold */
381 /* the minimum time */
382 #define ASYNC_DTR_DELAY 0x00010000 /* delaying DTR turn on */
383 #define ASYNC_SW_IN_FLOW 0x00020000 /* sw input flow control in effect */
384 #define ASYNC_SW_OUT_FLW 0x00040000 /* sw output flow control in effect */
385 #define ASYNC_SW_IN_NEEDED 0x00080000 /* sw input flow control char is */
386 /* needed to be sent */
387 #define ASYNC_OUT_FLW_RESUME 0x00100000 /* output need to be resumed */
388 /* because of transition of flow */
389 /* control from stop to start */
390 #define ASYNC_DDI_SUSPENDED 0x00200000 /* suspended by DDI */
391 #define ASYNC_RESUME_BUFCALL 0x00400000 /* call bufcall when resumed by DDI */
393 /* asy_hwtype definitions */
394 #define ASY8250A 0x2 /* 8250A or 16450 */
395 #define ASY16550 0x3 /* broken FIFO which must not be used */
396 #define ASY16550A 0x4 /* usable FIFO */
400 /* definitions for asy_flags field */
401 #define ASY_NEEDSOFT 0x00000001
402 #define ASY_DOINGSOFT 0x00000002
403 #define ASY_PPS 0x00000004
404 #define ASY_PPS_EDGE 0x00000008
405 #define ASY_DOINGSOFT_RETRY 0x00000010
406 #define ASY_RTS_DTR_OFF 0x00000020
407 #define ASY_IGNORE_CD 0x00000040
408 #define ASY_CONSOLE 0x00000080
409 #define ASY_DDI_SUSPENDED 0x00000100 /* suspended by DDI */
411 /* definitions for asy_flags2 field */
412 #define ASY2_NO_LOOPBACK 0x00000001 /* Device doesn't support loopback */
414 /* definitions for async_inflow_source field in struct asyncline */
415 #define IN_FLOW_NULL 0x00000000
416 #define IN_FLOW_RINGBUFF 0x00000001
417 #define IN_FLOW_STREAMS 0x00000002
418 #define IN_FLOW_USER 0x00000004
421 * OUTLINE defines the high-order flag bit in the minor device number that
422 * controls use of a tty line for dialin and dialout simultaneously.
425 #define OUTLINE (1 << (NBITSMINOR32 - 1))
427 #define OUTLINE (1 << (NBITSMINOR - 1))
429 #define UNIT(x) (getminor(x) & ~OUTLINE)
432 * ASYSETSOFT macro to pend a soft interrupt if one isn't already pending.
435 extern kmutex_t asy_soft_lock
; /* ptr to lock for asysoftpend */
436 extern int asysoftpend
; /* secondary interrupt pending */
438 #define ASYSETSOFT(asy) { \
439 mutex_enter(&asy_soft_lock); \
440 asy->asy_flags |= ASY_NEEDSOFT; \
441 if (!asysoftpend) { \
443 mutex_exit(&asy_soft_lock); \
444 ddi_trigger_softintr(asy_softintr_id); \
447 mutex_exit(&asy_soft_lock); \
454 #endif /* _SYS_ASY_H */