Home | History | Annotate | Download | only in sys
      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 2007 Sun Microsystems, Inc.  All rights reserved.
     27  * Use is subject to license terms.
     28  */
     29 
     30 #ifndef	_SYS_ASY_H
     31 #define	_SYS_ASY_H
     32 
     33 #pragma ident	"@(#)asy.h	1.39	07/10/18 SMI"
     34 
     35 #ifdef __cplusplus
     36 extern "C" {
     37 #endif
     38 
     39 #include <sys/tty.h>
     40 #include <sys/ksynch.h>
     41 #include <sys/dditypes.h>
     42 
     43 /*
     44  * internal bus type naming
     45  */
     46 #define	ASY_BUS_PCI	(0)
     47 #define	ASY_BUS_ISA	(1)
     48 #define	ASY_BUS_UNKNOWN	(-1)
     49 
     50 #define	ASY_MINOR_LEN	(40)
     51 
     52 #define	COM1_IOADDR	0x3f8
     53 #define	COM2_IOADDR	0x2f8
     54 #define	COM3_IOADDR	0x3e8
     55 #define	COM4_IOADDR	0x2e8
     56 
     57 /*
     58  * Definitions for INS8250 / 16550  chips
     59  */
     60 
     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 */
     74 
     75 /*
     76  * INTEL 8210-A/B & 16450/16550 Registers Structure.
     77  */
     78 
     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 */
     88 #define	STOP1   	0x00
     89 #define	STOP2   	0x04
     90 #define	PAREN   	0x08
     91 #define	PAREVN  	0x10
     92 #define	PARMARK 	0x20
     93 #define	SNDBRK  	0x40
     94 #define	EFRACCESS	0xBF	/* magic value for 16650 EFR access */
     95 
     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 */
    100 
    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 */
    110 
    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 */
    118 
    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 */
    124 
    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 */
    131 
    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 */
    141 
    142 #define	DELTAS(x)	((x)&(DCTS|DDSR|DRI|DDCD))
    143 #define	STATES(x)	((x)&(CTS|DSR|RI|DCD))
    144 
    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 */
    157 
    158 /* Serial in/out requests */
    159 
    160 #define	OVERRUN		040000
    161 #define	FRERROR		020000
    162 #define	PERROR		010000
    163 #define	S_ERRORS	(PERROR|OVERRUN|FRERROR)
    164 
    165 /* EFR - Enhanced feature register for 16650 */
    166 #define	ENHENABLE	0x10
    167 
    168 /* SCR - scratch register */
    169 #define	SCRTEST		0x5a	/* arbritrary value for testing SCR register */
    170 
    171 /*
    172  * Ring buffer and async line management definitions.
    173  */
    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 */
    178 
    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))
    197 
    198 /*
    199  * Asy tracing macros.  These are a bit similar to some macros in sys/vtrace.h .
    200  *
    201  * XXX - Needs review:  would it be better to use the macros in sys/vtrace.h ?
    202  */
    203 #ifdef DEBUG
    204 #define	DEBUGWARN0(fac, format) \
    205 	if (debug & (fac)) \
    206 		cmn_err(CE_WARN, format)
    207 #define	DEBUGNOTE0(fac, format) \
    208 	if (debug & (fac)) \
    209 		cmn_err(CE_NOTE, format)
    210 #define	DEBUGNOTE1(fac, format, arg1) \
    211 	if (debug & (fac)) \
    212 		cmn_err(CE_NOTE, format, arg1)
    213 #define	DEBUGNOTE2(fac, format, arg1, arg2) \
    214 	if (debug & (fac)) \
    215 		cmn_err(CE_NOTE, format, arg1, arg2)
    216 #define	DEBUGNOTE3(fac, format, arg1, arg2, arg3) \
    217 	if (debug & (fac)) \
    218 		cmn_err(CE_NOTE, format, arg1, arg2, arg3)
    219 #define	DEBUGCONT0(fac, format) \
    220 	if (debug & (fac)) \
    221 		cmn_err(CE_CONT, format)
    222 #define	DEBUGCONT1(fac, format, arg1) \
    223 	if (debug & (fac)) \
    224 		cmn_err(CE_CONT, format, arg1)
    225 #define	DEBUGCONT2(fac, format, arg1, arg2) \
    226 	if (debug & (fac)) \
    227 		cmn_err(CE_CONT, format, arg1, arg2)
    228 #define	DEBUGCONT3(fac, format, arg1, arg2, arg3) \
    229 	if (debug & (fac)) \
    230 		cmn_err(CE_CONT, format, arg1, arg2, arg3)
    231 #define	DEBUGCONT4(fac, format, arg1, arg2, arg3, arg4) \
    232 	if (debug & (fac)) \
    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) \
    236 	if (debug & (fac)) \
    237 		cmn_err(CE_CONT, format, \
    238 		arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
    239 #else
    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)
    252 #endif
    253 
    254 /*
    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.
    262  */
    263 
    264 struct asycom {
    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 */
    278 
    279 	/*
    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
    284 	 * putnext call).
    285 	 */
    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 */
    297 #ifdef DEBUG
    298 	int		asy_msint_cnt;	/* number of times in async_msint */
    299 #endif
    300 };
    301 
    302 /*
    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.
    307  */
    308 
    309 struct asyncline {
    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 */
    322 
    323 	/*
    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.
    327 	 */
    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 */
    332 
    333 	/*
    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.
    338 	 */
    339 	ushort_t	async_ring[RINGSIZE];
    340 
    341 	short		async_break;	/* break count */
    342 	int		async_inflow_source; /* input flow control type */
    343 
    344 	union {
    345 		struct {
    346 			uchar_t _hw;	/* overrun (hw) */
    347 			uchar_t _sw;	/* overrun (sw) */
    348 		} _a;
    349 		ushort_t uover_overrun;
    350 	} async_uover;
    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 */
    357 
    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 */
    361 };
    362 
    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 */
    392 
    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 */
    397 #define	ASY16650	0x5
    398 #define	ASY16750	0x6
    399 
    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 */
    410 
    411 /* definitions for asy_flags2 field */
    412 #define	ASY2_NO_LOOPBACK 0x00000001	/* Device doesn't support loopback */
    413 
    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
    419 
    420 /*
    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.
    423  */
    424 #ifdef _LP64
    425 #define	OUTLINE		(1 << (NBITSMINOR32 - 1))
    426 #else
    427 #define	OUTLINE		(1 << (NBITSMINOR - 1))
    428 #endif
    429 #define	UNIT(x)		(getminor(x) & ~OUTLINE)
    430 
    431 /*
    432  * ASYSETSOFT macro to pend a soft interrupt if one isn't already pending.
    433  */
    434 
    435 extern kmutex_t	asy_soft_lock;		/* ptr to lock for asysoftpend */
    436 extern int asysoftpend;			/* secondary interrupt pending */
    437 
    438 #define	ASYSETSOFT(asy)	{			\
    439 	mutex_enter(&asy_soft_lock);		\
    440 	asy->asy_flags |= ASY_NEEDSOFT;		\
    441 	if (!asysoftpend) {			\
    442 		asysoftpend = 1;		\
    443 		mutex_exit(&asy_soft_lock);	\
    444 		ddi_trigger_softintr(asy_softintr_id);	\
    445 	}					\
    446 	else					\
    447 		mutex_exit(&asy_soft_lock);	\
    448 }
    449 
    450 #ifdef __cplusplus
    451 }
    452 #endif
    453 
    454 #endif	/* _SYS_ASY_H */
    455