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 "%Z%%M% %I% %E% 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