xref: /illumos-gate/usr/src/uts/common/sys/asy.h (revision aecc710ab066150d47e5e9e7269e2e0d69107b4e)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
23 /*	  All Rights Reserved	*/
24 
25 /*
26  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27  * Copyright 2026 Oxide Computer Company
28  * Copyright 2024 Hans Rosenfeld
29  */
30 
31 #ifndef	_SYS_ASY_H
32 #define	_SYS_ASY_H
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 #include <sys/tty.h>
39 #include <sys/ksynch.h>
40 #include <sys/dditypes.h>
41 
42 /*
43  * internal bus type naming
44  */
45 #define	ASY_BUS_PCI	(0)
46 #define	ASY_BUS_ISA	(1)
47 #define	ASY_BUS_UNKNOWN	(-1)
48 
49 #define	ASY_MINOR_LEN	(40)
50 
51 #define	COM1_IOADDR	0x3f8
52 #define	COM2_IOADDR	0x2f8
53 #define	COM3_IOADDR	0x3e8
54 #define	COM4_IOADDR	0x2e8
55 
56 /*
57  * asy_hwtype definitions
58  *
59  * W.r.t the supported device registers, the 16650 actually a superset of the
60  * 16750, hence the ordering.
61  */
62 #define	ASY_8250A	0x00008250	/* 8250A or 16450 */
63 #define	ASY_16550	0x10016550	/* broken FIFO which must not be used */
64 #define	ASY_16550A	0x20016551	/* usable FIFO */
65 #define	ASY_16750	0x30016750	/* 64 byte FIFO, auto flow control */
66 #define	ASY_16650	0x40016650	/* 32 byte FIFO, auto flow control */
67 #define	ASY_16950	0x50016950	/* 128 byte FIFO, auto flow control */
68 #define	ASY_MAXCHIP	ASY_16950
69 
70 /*
71  * Definitions for INS8250 / 16550  chips
72  */
73 typedef enum {
74 	ASY_ILLEGAL = 0,
75 	/* 8250 / 16450 / 16550 registers */
76 	ASY_THR,		/* Transmitter Holding Register	(W) */
77 	ASY_RHR,		/* Receiver Holding Register	(R) */
78 	ASY_IER,		/* Interrupt Enable Register	(R/W) */
79 	ASY_FCR,		/* FIFO Control Register	(W) */
80 	ASY_ISR,		/* Interrupt Status Register	(R) */
81 	ASY_LCR,		/* Line Control Register	(R/W) */
82 	ASY_MCR,		/* Modem Control Register	(R/W) */
83 	ASY_LSR,		/* Line Status Register		(R) */
84 	ASY_MSR,		/* Modem Status Register	(R) */
85 	ASY_SPR,		/* Scratch Pad Register		(R/W) */
86 	ASY_DLL,		/* Divisor Latch Low		(R/W) */
87 	ASY_DLH,		/* Divisor Latch High		(R/W) */
88 
89 	/* 16750 extended register */
90 	ASY_EFR,		/* Extended Feature Register	(R/W) */
91 
92 	/* 16650 extended registers */
93 	ASY_XON1,		/* XON Character 1		(R/W) */
94 	ASY_XON2,		/* XON Character 2		(R/W) */
95 	ASY_XOFF1,		/* XOFF Character 1		(R/W) */
96 	ASY_XOFF2,		/* XOFF Character 2		(R/W) */
97 
98 	/* 16950 additional registers */
99 	ASY_ASR,		/* Additional Status Register	(R/W) */
100 	ASY_RFL,		/* Receiver FIFO Length		(R/W) */
101 	ASY_TFL,		/* Transmitter FIFO Length	(R/W) */
102 	ASY_ICR,		/* Indexed Control Register	(R/W) */
103 
104 	/* 16950 indexed registers */
105 	ASY_ACR,		/* Additional Control Register  (R/W) */
106 	ASY_CPR,		/* Clock Prescaler Register	(R/W) */
107 	ASY_TCR,		/* Times Clock Register		(R/W) */
108 	ASY_CKS,		/* Clock Select Register	(R/W) */
109 	ASY_TTL,		/* Transmitter Trigger Level	(R/W) */
110 	ASY_RTL,		/* Receiver Trigger Level	(R/W) */
111 	ASY_FCL,		/* Flow Control Low-Level	(R/W) */
112 	ASY_FCH,		/* Flow Control High-Level	(R/W) */
113 	ASY_ID1,		/* Device Identification 1	(R) */
114 	ASY_ID2,		/* Device Identification 2	(R) */
115 	ASY_ID3,		/* Device Identification 3	(R) */
116 	ASY_REV,		/* Device Revision		(R) */
117 	ASY_CSR,		/* Channel Software Reset	(W) */
118 	ASY_NMR,		/* Nine-Bit Mode Register	(R/W) */
119 
120 	ASY_NREG,
121 } asy_reg_t;
122 
123 /*
124  * INTEL 8210-A/B & 16450/16550 Registers Structure.
125  */
126 
127 /* Interrupt Enable Register */
128 typedef enum {
129 	ASY_IER_RIEN = 1 << 0,	/* Received Data Ready */
130 	ASY_IER_TIEN = 1 << 1,	/* Tx Hold Register Empty */
131 	ASY_IER_SIEN = 1 << 2,	/* Receiver Line Status */
132 	ASY_IER_MIEN = 1 << 3	/* Modem Status */
133 } asy_ier_t;
134 
135 #define	ASY_IER_ALL	\
136 	(ASY_IER_RIEN | ASY_IER_TIEN | ASY_IER_SIEN | ASY_IER_MIEN)
137 
138 /* FIFO Control register */
139 typedef enum {
140 	ASY_FCR_FIFO_EN =	1 << 0,	/* FIFOs enabled */
141 	ASY_FCR_RHR_FL =	1 << 1,	/* flush receiver FIFO */
142 	ASY_FCR_THR_FL =	1 << 2,	/* flush transmitter FIFO */
143 	ASY_FCR_DMA =		1 << 3,	/* DMA mode 1 */
144 	ASY_FCR_THR_TR0 =	1 << 4,	/* xmit trigger level bit 0 (16650) */
145 	ASY_FCR_THR_TR1 =	1 << 5,	/* xmit trigger level bit 1 (16650) */
146 	ASY_FCR_RHR_TR0 =	1 << 6,	/* receiver trigger level bit 0 */
147 	ASY_FCR_RHR_TR1 =	1 << 7,	/* receiver trigger level bit 1 */
148 } asy_fcr_t;
149 
150 #define	ASY_FCR_FIFO64		ASY_FCR_THR_TR1	/* 64 byte FIFO en (16750) */
151 
152 /* 16550 receiver trigger levels */
153 #define	ASY_FCR_RHR_TRIG_1	0		/*  1 byte RX trigger level */
154 #define	ASY_FCR_RHR_TRIG_4	ASY_FCR_RHR_TR0	/*  4 byte RX trigger level */
155 #define	ASY_FCR_RHR_TRIG_8	ASY_FCR_RHR_TR1	/*  8 byte RX trigger level */
156 #define	ASY_FCR_RHR_TRIG_14	\
157 	(ASY_FCR_THR_TR0 | ASY_FCR_THR_TR1)	/* 14 byte RX trigger level */
158 
159 /* 16650 transmitter trigger levels */
160 #define	ASY_FCR_THR_TRIG_16	0		/* 16 byte TX trigger level */
161 #define	ASY_FCR_THR_TRIG_8	ASY_FCR_THR_TR0	/*  8 byte TX trigger level */
162 #define	ASY_FCR_THR_TRIG_24	ASY_FCR_THR_TR1	/* 24 byte TX trigger level */
163 #define	ASY_FCR_THR_TRIG_30	\
164 	(ASY_FCR_THR_TR0 | ASY_FCR_THR_TR1)	/* 30 byte TX trigger level */
165 
166 #define	ASY_FCR_FIFO_OFF 0	/* FIFOs disabled */
167 
168 /* Interrupt Status Register */
169 #define	ASY_ISR_NOINTR	0x01	/* no interrupt pending */
170 #define	ASY_ISR_MASK	0x0e	/* interrupt identification mask */
171 #define	ASY_ISR_EMASK	0x3e	/* interrupt id mask when EFR[4] = 1 (16650) */
172 
173 #define	ASY_ISR_FIFO64	0x20	/* 64 byte FIFOs enabled (16750) */
174 #define	ASY_ISR_FIFOEN	0xc0	/* FIFOs enabled (16550A and up) */
175 
176 #define	ASY_ISR_ID_RLST	0x06	/* Receiver Line Status */
177 #define	ASY_ISR_ID_RDA	0x04	/* Receiver Data Available */
178 #define	ASY_ISR_ID_TMO	0x0c	/* Character timeout (16550A and up) */
179 #define	ASY_ISR_ID_THRE	0x02	/* Transmitter Holding Register Empty */
180 #define	ASY_ISR_ID_MST	0x00	/* Modem Status changed */
181 #define	ASY_ISR_ID_XOFF	0x10	/* Received XOFF / special character (16650) */
182 #define	ASY_ISR_ID_RCTS	0x20	/* RTS/CTS changed (16650) */
183 
184 /* Line Control Register */
185 typedef enum {
186 	ASY_LCR_WLS0 =	1 << 0,	/* word length select bit 0 */
187 	ASY_LCR_WLS1 =	1 << 1,	/* word length select bit 2 */
188 	ASY_LCR_STB =	1 << 2,	/* number of stop bits */
189 	ASY_LCR_PEN =	1 << 3,	/* parity enable */
190 	ASY_LCR_EPS =	1 << 4,	/* even parity select */
191 	ASY_LCR_SPS =	1 << 5,	/* stick parity select */
192 	ASY_LCR_SETBRK = 1 << 6, /* break key */
193 	ASY_LCR_DLAB =	1 << 7	/* divisor latch access bit */
194 } asy_lcr_t;
195 
196 #define	ASY_LCR_STOP1	0x00
197 #define	ASY_LCR_STOP2	ASY_LCR_STB
198 
199 #define	ASY_LCR_EFRACCESS	0xBF	/* magic value for 16650 EFR access */
200 
201 #define	ASY_LCR_BITS5	0x00				/* 5 bits per char */
202 #define	ASY_LCR_BITS6	ASY_LCR_WLS0			/* 6 bits per char */
203 #define	ASY_LCR_BITS7	ASY_LCR_WLS1			/* 7 bits per char */
204 #define	ASY_LCR_BITS8	(ASY_LCR_WLS0 | ASY_LCR_WLS1)	/* 8 bits per char */
205 
206 /* Modem Control Register */
207 typedef enum {
208 	ASY_MCR_DTR =	1 << 0,	/* Data Terminal Ready */
209 	ASY_MCR_RTS =	1 << 1,	/* Request To Send */
210 	ASY_MCR_OUT1 =	1 << 2,	/* Aux output - not used */
211 	ASY_MCR_OUT2 =	1 << 3,	/* turns intr to 386 on/off */
212 	ASY_MCR_LOOP =	1 << 4	/* loopback for diagnostics */
213 } asy_mcr_t;
214 
215 #define	ASY_MCR_LOOPBACK	\
216 	(ASY_MCR_DTR | ASY_MCR_RTS | ASY_MCR_OUT1 | ASY_MCR_OUT2 | ASY_MCR_LOOP)
217 
218 /* Line Status Register */
219 typedef enum {
220 	ASY_LSR_DR =	1 << 0,	/* data ready */
221 	ASY_LSR_OE =	1 << 1,	/* overrun error */
222 	ASY_LSR_PE =	1 << 2,	/* parity error */
223 	ASY_LSR_FE =	1 << 3,	/* framing error */
224 	ASY_LSR_BI =	1 << 4,	/* break interrupt */
225 	ASY_LSR_THRE =	1 << 5,	/* transmitter holding register empty */
226 	ASY_LSR_TEMT =	1 << 6,	/* transmitter empty (THR + TSR empty) */
227 	ASY_LSR_DE =	1 << 7	/* Receiver FIFO data error */
228 } asy_lsr_t;
229 
230 #define	ASY_LSR_ERRORS	\
231 	(ASY_LSR_OE | ASY_LSR_PE | ASY_LSR_FE | ASY_LSR_BI)
232 
233 /* Modem Status Register */
234 typedef enum {
235 	ASY_MSR_DCTS =	1 << 0,	/* Delta Clear To Send */
236 	ASY_MSR_DDSR =	1 << 1,	/* Delta Data Set Ready */
237 	ASY_MSR_TERI =	1 << 2,	/* Trailing Edge Ring Indicator */
238 	ASY_MSR_DDCD =	1 << 3,	/* Delta Data Carrier Detect */
239 	ASY_MSR_CTS =	1 << 4,	/* Clear To Send */
240 	ASY_MSR_DSR =	1 << 5,	/* Data Set Ready */
241 	ASY_MSR_RI =	1 << 6,	/* Ring Indicator */
242 	ASY_MSR_DCD =	1 << 7	/* Data Carrier Detect */
243 } asy_msr_t;
244 
245 #define	ASY_MSR_DELTAS(x)	\
246 	((x) & (ASY_MSR_DCTS | ASY_MSR_DDSR | ASY_MSR_TERI | ASY_MSR_DDCD))
247 #define	ASY_MSR_STATES(x)	\
248 	((x) & (ASY_MSR_CTS | ASY_MSR_DSR | ASY_MSR_RI | ASY_MSR_DCD))
249 
250 /* Scratch Pad Register */
251 #define	ASY_SPR_TEST	0x5a	/* arbritrary value for testing SPR */
252 
253 /* Extended Feature Register (16650) */
254 #define	ASY_EFR_ENH_EN	0x10	/* IER[4:7], ISR[4,5], FCR[4,5], MCR[5:7] */
255 
256 /* Additional Status Register (16950) */
257 typedef enum {
258 	ASY_ASR_TD =	1 << 0,	/* Transmitter Disabled */
259 	ASY_ASR_RTD =	1 << 1,	/* Remote Transmitter Disabled */
260 	ASY_ASR_RTS =	1 << 2,	/* RTS status */
261 	ASY_ASR_DTR =	1 << 3,	/* DTR status */
262 	ASY_ASR_SCD =	1 << 4,	/* Special Character detected */
263 	ASY_ASR_FIFOSEL = 1 << 5, /* FIFOSEL pin status */
264 	ASY_ASR_FIFOSZ = 1 << 6, /* FIFO size */
265 	ASY_ASR_TI =	1 << 7	/* Transmitter Idle */
266 } asy_16950_asr_t;
267 
268 /* Additional Control Register (16950) */
269 #define	ASY_ACR_RD	0x01	/* Receiver Disable */
270 #define	ASY_ACR_TD	0x02	/* Transmitter Disable */
271 #define	ASY_ACR_DSR	0x04	/* Automatic DSR flow control */
272 #define	ASY_ACR_DTR	0x18	/* DTR line configuration */
273 #define	ASY_ACR_TRIG	0x20	/* 950 mode trigger levels enable */
274 #define	ASY_ACR_ICR	0x40	/* ICR read enable */
275 #define	ASY_ACR_ASR	0x80	/* Additional Status Enable */
276 
277 #define	ASY_ACR_DTR_NORM	0x00	/* DTR normal (compatible) */
278 #define	ASY_ACR_DTR_FLOW	0x08	/* DTR used for flow-control */
279 #define	ASY_ACR_DTR_RS485_LOW	0x10	/* DTR drives ext. RS485 buffer low */
280 #define	ASY_ACR_DTR_RS485_HIGH	0x18	/* DTR drives ext. RS485 buffer high */
281 
282 /* Clock Select Register (16950) */
283 #define	ASY_CKS_RCLK	0x00	/* RCLK pin drives receiver clock */
284 #define	ASY_CKS_RDSR	0x01	/* DSR pin drives receiver clock */
285 #define	ASY_CKS_RBDOUT	0x02	/* BDOUT pint drives receiver clock */
286 #define	ASY_CKS_RTCLK	0x03	/* transmitter clock drives receiver clock */
287 
288 #define	ASY_CKS_BDO_DIS	0x04	/* Disable BDOUT pin */
289 #define	ASY_CKS_RCLK_1X	0x08	/* Receiver clock in isochronous 1x mode */
290 
291 #define	ASY_CKS_DTR_NO	0x00	/* DTR pin defined by ACR[ASY_ACR_DTR] */
292 #define	ASY_CKS_DTR_T1X	0x10	/* Transmitter 1x clock on DTR pin */
293 #define	ASY_CKS_DTR_BDO	0x20	/* Baud rate generator output on DTR pin */
294 
295 #define	ASY_CKS_TCLK_RI	0x40	/* External transmitter clock on RI pin */
296 #define	ASY_CKS_TCLK_1X	0x80	/* Transmitter clock in isochronous 1x mode */
297 
298 /* Serial in/out requests */
299 
300 #define	OVERRUN		040000
301 #define	FRERROR		020000
302 #define	PERROR		010000
303 #define	S_ERRORS	(PERROR|OVERRUN|FRERROR)
304 
305 /*
306  * Ring buffer and async line management definitions.
307  */
308 #define	RINGBITS	16		/* # of bits in ring ptrs */
309 #define	RINGSIZE	(1<<RINGBITS)   /* size of ring */
310 #define	RINGMASK	(RINGSIZE-1)
311 #define	RINGFRAC	12		/* fraction of ring to force flush */
312 
313 #define	RING_INIT(ap)  ((ap)->async_rput = (ap)->async_rget = 0)
314 #define	RING_CNT(ap)   (((ap)->async_rput >= (ap)->async_rget) ? \
315 	((ap)->async_rput - (ap)->async_rget):\
316 	((0x10000 - (ap)->async_rget) + (ap)->async_rput))
317 #define	RING_FRAC(ap)  ((int)RING_CNT(ap) >= (int)(RINGSIZE/RINGFRAC))
318 #define	RING_POK(ap, n) ((int)RING_CNT(ap) < (int)(RINGSIZE-(n)))
319 #define	RING_PUT(ap, c) \
320 	((ap)->async_ring[(ap)->async_rput++ & RINGMASK] =  (uchar_t)(c))
321 #define	RING_UNPUT(ap) ((ap)->async_rput--)
322 #define	RING_GOK(ap, n) ((int)RING_CNT(ap) >= (int)(n))
323 #define	RING_GET(ap)   ((ap)->async_ring[(ap)->async_rget++ & RINGMASK])
324 #define	RING_EAT(ap, n) ((ap)->async_rget += (n))
325 #define	RING_MARK(ap, c, s) \
326 	((ap)->async_ring[(ap)->async_rput++ & RINGMASK] = ((uchar_t)(c)|(s)))
327 #define	RING_UNMARK(ap) \
328 	((ap)->async_ring[((ap)->async_rget) & RINGMASK] &= ~S_ERRORS)
329 #define	RING_ERR(ap, c) \
330 	((ap)->async_ring[((ap)->async_rget) & RINGMASK] & (c))
331 
332 /* definitions for asy_progress */
333 typedef enum {
334 	ASY_PROGRESS_REGS =	1 << 0,
335 	ASY_PROGRESS_SOFTINT =	1 << 1,
336 	ASY_PROGRESS_INT =	1 << 2,
337 	ASY_PROGRESS_MUTEX =	1 << 3,
338 	ASY_PROGRESS_ASYNC =	1 << 4,
339 	ASY_PROGRESS_MINOR =	1 << 5
340 } asy_progress_t;
341 
342 
343 /* definitions for asy_flags field */
344 typedef enum {
345 	ASY_NEEDSOFT =		1 << 0,
346 	ASY_DOINGSOFT =		1 << 1,
347 	ASY_PPS =		1 << 2,
348 	ASY_PPS_EDGE =		1 << 3,
349 	ASY_DOINGSOFT_RETRY =	1 << 4,
350 	ASY_RTS_DTR_OFF =	1 << 5,
351 	ASY_IGNORE_CD =		1 << 6,
352 	ASY_CONSOLE =		1 << 7,
353 	ASY_DDI_SUSPENDED =	1 << 8, /* suspended by DDI */
354 } asy_flags_t;
355 
356 /* definitions for asy_flags2 field */
357 typedef enum {
358 	ASY2_NO_LOOPBACK = 1 << 0	/* Device doesn't support loopback */
359 } asy_flags2_t;
360 
361 /*
362  * Hardware channel common data. One structure per port.
363  * Each of the fields in this structure is required to be protected by a
364  * mutex lock at the highest priority at which it can be altered.
365  * The asy_flags, and asy_next fields can be altered by interrupt
366  * handling code that must be protected by the mutex whose handle is
367  * stored in asy_excl_hi.  All others can be protected by the asy_excl
368  * mutex, which is lower priority and adaptive.
369  */
370 
371 struct asycom {
372 #ifdef DEBUG
373 	int		asy_debug;	/* per-instance debug flags */
374 #endif
375 	asy_progress_t	asy_progress;	/* attach progress */
376 	asy_flags_t	asy_flags;	/* random flags  */
377 					/* protected by asy_excl_hi lock */
378 	uint_t		asy_hwtype;	/* HW type: ASY16550A, etc. */
379 	uint_t		asy_use_fifo;	/* HW FIFO use it or not ?? */
380 	uint_t		asy_fifo_buf;	/* With FIFO = 16, otherwise = 1 */
381 	asy_flags2_t	asy_flags2;	/* flags which don't change, no lock */
382 	uint8_t		*asy_ioaddr;	/* i/o address of ASY port */
383 	struct asyncline *asy_priv;	/* protocol private data -- asyncline */
384 	dev_info_t	*asy_dip;	/* dev_info */
385 	int		asy_unit;	/* which port */
386 	kmutex_t	asy_excl;	/* asy adaptive mutex */
387 	kmutex_t	asy_excl_hi;	/* asy spinlock mutex */
388 	kmutex_t	asy_soft_lock;	/* soft lock for guarding softpend. */
389 	int		asysoftpend;	/* Flag indicating soft int pending. */
390 
391 	ddi_softint_handle_t asy_soft_inth;
392 	uint_t		asy_soft_intr_pri;
393 
394 	ddi_intr_handle_t *asy_inth;
395 	size_t		asy_inth_sz;
396 	uint_t		asy_intr_pri;
397 	int		asy_intr_cnt;
398 	int		asy_intr_cap;
399 	int		asy_intr_type;
400 	int		asy_intr_types;
401 
402 	/*
403 	 * The asy_soft_sr mutex should only be taken by the soft interrupt
404 	 * handler and the driver DDI_SUSPEND/DDI_RESUME code.  It
405 	 * shouldn't be taken by any code that may get called indirectly
406 	 * by the soft interrupt handler (e.g. as a result of a put or
407 	 * putnext call).
408 	 */
409 	kmutex_t	asy_soft_sr;	/* soft int suspend/resume mutex */
410 	uchar_t		asy_msr;	/* saved modem status */
411 	uchar_t		asy_mcr;	/* soft carrier bits */
412 	uchar_t		asy_lcr;	/* console lcr bits */
413 	uchar_t		asy_bidx;	/* console baud rate index */
414 	tcflag_t	asy_cflag;	/* console mode bits */
415 	struct cons_polledio	polledio;	/* polled I/O functions */
416 	ddi_acc_handle_t	asy_iohandle;	/* Data access handle */
417 	tcflag_t	asy_ocflag;	/* old console mode bits */
418 	uchar_t		asy_com_port;	/* COM port number, or zero */
419 	uchar_t		asy_fifor;	/* FIFOR register setting */
420 	uint8_t		asy_acr;	/* 16950 additional control register */
421 #ifdef DEBUG
422 	int		asy_msint_cnt;	/* number of times in async_msint */
423 #endif
424 };
425 
426 /* definitions for async_flags field */
427 typedef enum {
428 	ASYNC_EXCL_OPEN =	1 << 28, /* exclusive open */
429 	ASYNC_WOPEN =		1 << 0,  /* waiting for open to complete */
430 	ASYNC_ISOPEN =		1 << 1,  /* open is complete */
431 	ASYNC_OUT =		1 << 2,  /* line being used for dialout */
432 	ASYNC_CARR_ON =		1 << 3,  /* carrier on last time we looked */
433 	ASYNC_STOPPED =		1 << 4,  /* output is stopped */
434 	ASYNC_DELAY =		1 << 5,  /* waiting for delay to finish */
435 	ASYNC_BREAK =		1 << 6,  /* waiting for break to finish */
436 	ASYNC_BUSY =		1 << 7,  /* waiting for transmission finish */
437 	ASYNC_DRAINING =	1 << 8,  /* waiting for output to drain */
438 	ASYNC_SERVICEIMM =	1 << 9,  /* queue soft interrupt as soon as */
439 	ASYNC_HW_IN_FLOW =	1 << 10, /* input flow control in effect */
440 	ASYNC_HW_OUT_FLW =	1 << 11, /* output flow control in effect */
441 	ASYNC_PROGRESS =	1 << 12, /* made progress on output effort */
442 	ASYNC_CLOSING =		1 << 13, /* processing close on stream */
443 	ASYNC_OUT_SUSPEND =	1 << 14, /* waiting for TIOCSBRK to finish */
444 	ASYNC_HOLD_UTBRK =	1 << 15, /* waiting for untimed break hold */
445 					/* the minimum time */
446 	ASYNC_DTR_DELAY =	1 << 16, /* delaying DTR turn on */
447 	ASYNC_SW_IN_FLOW =	1 << 17, /* sw input flow control in effect */
448 	ASYNC_SW_OUT_FLW =	1 << 18, /* sw output flow control in effect */
449 	ASYNC_SW_IN_NEEDED =	1 << 19, /* sw input flow control char is */
450 					/* needed to be sent */
451 	ASYNC_OUT_FLW_RESUME =	1 << 20, /* output need to be resumed */
452 					/* because of transition of flow */
453 					/* control from stop to start */
454 	ASYNC_DDI_SUSPENDED =	1 << 21, /* suspended by DDI */
455 	ASYNC_RESUME_BUFCALL =	1 << 22  /* call bufcall when resumed by DDI */
456 } async_flags_t;
457 
458 /* definitions for async_inflow_source field in struct asyncline */
459 typedef enum {
460 	IN_FLOW_NULL =		0 << 0,
461 	IN_FLOW_RINGBUFF =	1 << 0,
462 	IN_FLOW_STREAMS =	1 << 1,
463 	IN_FLOW_USER =		1 << 2
464 } async_inflow_t;
465 
466 /*
467  * Asychronous protocol private data structure for ASY.
468  * Each of the fields in the structure is required to be protected by
469  * the lower priority lock except the fields that are set only at
470  * base level but cleared (with out lock) at interrupt level.
471  */
472 
473 struct asyncline {
474 	async_flags_t	async_flags;	/* random flags */
475 	kcondvar_t	async_flags_cv; /* condition variable for flags */
476 	kcondvar_t	async_ops_cv;	/* condition variable for async_ops */
477 	dev_t		async_dev;	/* device major/minor numbers */
478 	mblk_t		*async_xmitblk;	/* transmit: active msg block */
479 	struct asycom	*async_common;	/* device common data */
480 	tty_common_t	async_ttycommon; /* tty driver common data */
481 	bufcall_id_t	async_wbufcid;	/* id for pending write-side bufcall */
482 	size_t		async_wbufcds;	/* Buffer size requested in bufcall */
483 	timeout_id_t	async_polltid;	/* softint poll timeout id */
484 	timeout_id_t    async_dtrtid;   /* delaying DTR turn on */
485 	timeout_id_t    async_utbrktid; /* hold minimum untimed break time id */
486 
487 	/*
488 	 * The following fields are protected by the asy_excl_hi lock.
489 	 * Some, such as async_flowc, are set only at the base level and
490 	 * cleared (without the lock) only by the interrupt level.
491 	 */
492 	uchar_t		*async_optr;	/* output pointer */
493 	int		async_ocnt;	/* output count */
494 	uint_t		async_rput;	/* producing pointer for input */
495 	uint_t		async_rget;	/* consuming pointer for input */
496 
497 	/*
498 	 * Each character stuffed into the ring has two bytes associated
499 	 * with it.  The first byte is used to indicate special conditions
500 	 * and the second byte is the actual data.  The ring buffer
501 	 * needs to be defined as ushort_t to accomodate this.
502 	 */
503 	ushort_t	async_ring[RINGSIZE];
504 
505 	short		async_break;	/* break count */
506 	async_inflow_t	async_inflow_source; /* input flow control type */
507 
508 	/*
509 	 * This union presumably exists to support a change that happened some
510 	 * time in the distant past.  The two overrun fields are used as
511 	 * booleans; one imagines that the split between hardware and software
512 	 * overruns was made some time after the driver was initially written
513 	 * and that the earliest versions just had the single `async_overrun`
514 	 * field.
515 	 *
516 	 * By using the union, out-of-tree consumers could presumably still
517 	 * detect any type of overrun via testing the `async_overrun` field,
518 	 * which would _de facto_ combine the two, while the driver keeps
519 	 * finer-grained track of the specific kind of overrun.  Of course,
520 	 * this only works if consuming code treats any non-zero value as true,
521 	 * and does not compare against 1 specifically.
522 	 *
523 	 * It is unclear if this is still necessary.  One hopes that any such
524 	 * consumers, if they exist, neither assign through `async_overrun` nor
525 	 * look specifically for the value one to mean true.
526 	 */
527 	union {
528 		struct {
529 			uint8_t _hw;	/* overrun (hw) */
530 			uint8_t _sw;	/* overrun (sw) */
531 		} _a;
532 		uint16_t uover_overrun;
533 	} async_uover;
534 #define	async_overrun		async_uover._a.uover_overrun
535 #define	async_hw_overrun	async_uover._a._hw
536 #define	async_sw_overrun	async_uover._a._sw
537 	short		async_ext;	/* modem status change count */
538 	short		async_work;	/* work to do flag */
539 	timeout_id_t	async_timer;	/* close drain progress timer */
540 
541 	mblk_t		*async_suspqf;	/* front of suspend queue */
542 	mblk_t		*async_suspqb;	/* back of suspend queue */
543 	int		async_ops;	/* active operations counter */
544 };
545 
546 /*
547  * OUTLINE defines the high-order flag bit in the minor device number that
548  * controls use of a tty line for dialin and dialout simultaneously.
549  */
550 #ifdef _LP64
551 #define	OUTLINE		(1 << (NBITSMINOR32 - 1))
552 #else
553 #define	OUTLINE		(1 << (NBITSMINOR - 1))
554 #endif
555 #define	UNIT(x)		(getminor(x) & ~OUTLINE)
556 
557 /* This corresponds to DDI_SOFTINT_MED used by the old softint routines. */
558 #define	ASY_SOFT_INT_PRI	6
559 
560 #ifdef __cplusplus
561 }
562 #endif
563 
564 #endif	/* _SYS_ASY_H */
565