1/*- 2 * cyclades cyclom-y serial driver 3 * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993 4 * 5 * Copyright (c) 1993 Andrew Herbert. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name Andrew Herbert may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 22 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 *
| 1/*- 2 * cyclades cyclom-y serial driver 3 * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993 4 * 5 * Copyright (c) 1993 Andrew Herbert. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name Andrew Herbert may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 22 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 *
|
30 * $FreeBSD: head/sys/dev/cy/cy_isa.c 50477 1999-08-28 01:08:13Z peter $
| 30 * $FreeBSD: head/sys/dev/cy/cy_isa.c 51654 1999-09-25 16:21:39Z phk $
|
31 */ 32 33#include "opt_compat.h" 34#include "cy.h" 35 36/* 37 * TODO: 38 * Atomic COR change. 39 * Consoles. 40 */ 41 42/* 43 * Temporary compile-time configuration options. 44 */ 45#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) 46 /* Number of chars in the receiver FIFO before an 47 * an interrupt is generated. Should depend on 48 * line speed. Needs to be about 6 on a 486DX33 49 * for 4 active ports at 115200 bps. Why doesn't 50 * 10 work? 51 */ 52#define PollMode /* Use polling-based irq service routine, not the 53 * hardware svcack lines. Must be defined for 54 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, 55 * and stops 4 * 115200 bps from working. 56 */ 57#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly 58 * the output CR/LF processing, plus we can avoid a 59 * few checks usually done in ttyinput(). 60 * 61 * XXX not fully implemented, and not particularly 62 * worthwhile. 63 */ 64#undef CyDebug /* Include debugging code (not very expensive). */ 65 66/* These will go away. */ 67#undef SOFT_CTS_OFLOW 68#define SOFT_HOTCHAR 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/tty.h> 73#include <sys/proc.h> 74#include <sys/conf.h> 75#include <sys/dkstat.h> 76#include <sys/fcntl.h> 77#include <sys/interrupt.h> 78#include <sys/kernel.h> 79#include <sys/malloc.h> 80#include <sys/syslog.h> 81#include <machine/clock.h> 82#include <machine/ipl.h> 83#ifndef SMP 84#include <machine/lock.h> 85#endif 86#include <machine/psl.h> 87 88#include <i386/isa/isa_device.h> 89#include <i386/isa/cyreg.h> 90#include <i386/isa/ic/cd1400.h> 91 92#ifdef SMP 93#define disable_intr() COM_DISABLE_INTR() 94#define enable_intr() COM_ENABLE_INTR() 95#endif /* SMP */ 96 97/* 98 * Dictionary so that I can name everything *sio* or *com* to compare with 99 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to 100 * simplify the comparision. These will go away. 101 */ 102#define LSR_BI CD1400_RDSR_BREAK 103#define LSR_FE CD1400_RDSR_FE 104#define LSR_OE CD1400_RDSR_OE 105#define LSR_PE CD1400_RDSR_PE 106#define MCR_DTR CD1400_MSVR2_DTR 107#define MCR_RTS CD1400_MSVR1_RTS 108#define MSR_CTS CD1400_MSVR2_CTS 109#define MSR_DCD CD1400_MSVR2_CD 110#define MSR_DSR CD1400_MSVR2_DSR 111#define MSR_RI CD1400_MSVR2_RI 112#define NSIO (NCY * CY_MAX_PORTS) 113#define comconsole cyconsole 114#define comdefaultrate cydefaultrate 115#define com_events cy_events 116#define comhardclose cyhardclose 117#define commctl cymctl 118#define comparam cyparam 119#define comspeed cyspeed 120#define comstart cystart 121#define comwakeup cywakeup 122#define nsio_tty ncy_tty 123#define p_com_addr p_cy_addr 124#define sioattach cyattach 125#define sioclose cyclose
| 31 */ 32 33#include "opt_compat.h" 34#include "cy.h" 35 36/* 37 * TODO: 38 * Atomic COR change. 39 * Consoles. 40 */ 41 42/* 43 * Temporary compile-time configuration options. 44 */ 45#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) 46 /* Number of chars in the receiver FIFO before an 47 * an interrupt is generated. Should depend on 48 * line speed. Needs to be about 6 on a 486DX33 49 * for 4 active ports at 115200 bps. Why doesn't 50 * 10 work? 51 */ 52#define PollMode /* Use polling-based irq service routine, not the 53 * hardware svcack lines. Must be defined for 54 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, 55 * and stops 4 * 115200 bps from working. 56 */ 57#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly 58 * the output CR/LF processing, plus we can avoid a 59 * few checks usually done in ttyinput(). 60 * 61 * XXX not fully implemented, and not particularly 62 * worthwhile. 63 */ 64#undef CyDebug /* Include debugging code (not very expensive). */ 65 66/* These will go away. */ 67#undef SOFT_CTS_OFLOW 68#define SOFT_HOTCHAR 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/tty.h> 73#include <sys/proc.h> 74#include <sys/conf.h> 75#include <sys/dkstat.h> 76#include <sys/fcntl.h> 77#include <sys/interrupt.h> 78#include <sys/kernel.h> 79#include <sys/malloc.h> 80#include <sys/syslog.h> 81#include <machine/clock.h> 82#include <machine/ipl.h> 83#ifndef SMP 84#include <machine/lock.h> 85#endif 86#include <machine/psl.h> 87 88#include <i386/isa/isa_device.h> 89#include <i386/isa/cyreg.h> 90#include <i386/isa/ic/cd1400.h> 91 92#ifdef SMP 93#define disable_intr() COM_DISABLE_INTR() 94#define enable_intr() COM_ENABLE_INTR() 95#endif /* SMP */ 96 97/* 98 * Dictionary so that I can name everything *sio* or *com* to compare with 99 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to 100 * simplify the comparision. These will go away. 101 */ 102#define LSR_BI CD1400_RDSR_BREAK 103#define LSR_FE CD1400_RDSR_FE 104#define LSR_OE CD1400_RDSR_OE 105#define LSR_PE CD1400_RDSR_PE 106#define MCR_DTR CD1400_MSVR2_DTR 107#define MCR_RTS CD1400_MSVR1_RTS 108#define MSR_CTS CD1400_MSVR2_CTS 109#define MSR_DCD CD1400_MSVR2_CD 110#define MSR_DSR CD1400_MSVR2_DSR 111#define MSR_RI CD1400_MSVR2_RI 112#define NSIO (NCY * CY_MAX_PORTS) 113#define comconsole cyconsole 114#define comdefaultrate cydefaultrate 115#define com_events cy_events 116#define comhardclose cyhardclose 117#define commctl cymctl 118#define comparam cyparam 119#define comspeed cyspeed 120#define comstart cystart 121#define comwakeup cywakeup 122#define nsio_tty ncy_tty 123#define p_com_addr p_cy_addr 124#define sioattach cyattach 125#define sioclose cyclose
|
126#define siodevtotty cydevtotty
| |
127#define siodriver cydriver 128#define siodtrwakeup cydtrwakeup 129#define sioinput cyinput 130#define siointr cyintr 131#define siointr1 cyintr1 132#define sioioctl cyioctl 133#define sioopen cyopen 134#define siopoll cypoll 135#define sioprobe cyprobe 136#define sioread cyread 137#define siosettimeout cysettimeout 138#define siosetwater cysetwater
| 126#define siodriver cydriver 127#define siodtrwakeup cydtrwakeup 128#define sioinput cyinput 129#define siointr cyintr 130#define siointr1 cyintr1 131#define sioioctl cyioctl 132#define sioopen cyopen 133#define siopoll cypoll 134#define sioprobe cyprobe 135#define sioread cyread 136#define siosettimeout cysettimeout 137#define siosetwater cysetwater
|
139#define siostop cystop
| 138#define comstop cystop
|
140#define siowrite cywrite 141#define sio_registered cy_registered 142#define sio_timeout cy_timeout 143#define sio_timeout_handle cy_timeout_handle 144#define sio_timeouts_until_log cy_timeouts_until_log 145#define sio_tty cy_tty 146 147#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) 148 149/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ 150#define CD1400_xIVR_CHAN_SHIFT 3 151#define CD1400_xIVR_CHAN 0x1F 152 153/* 154 * ETC states. com->etc may also contain a hardware ETC command value, 155 * meaning that execution of that command is pending. 156 */ 157#define ETC_NONE 0 /* we depend on bzero() setting this */ 158#define ETC_BREAK_STARTING 1 159#define ETC_BREAK_STARTED 2 160#define ETC_BREAK_ENDING 3 161#define ETC_BREAK_ENDED 4 162 163#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 164 165#define CALLOUT_MASK 0x80 166#define CONTROL_MASK 0x60 167#define CONTROL_INIT_STATE 0x20 168#define CONTROL_LOCK_STATE 0x40 169#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 170#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 171#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 172 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 173 174/* 175 * com state bits. 176 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 177 * than the other bits so that they can be tested as a group without masking 178 * off the low bits. 179 * 180 * The following com and tty flags correspond closely: 181 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
| 139#define siowrite cywrite 140#define sio_registered cy_registered 141#define sio_timeout cy_timeout 142#define sio_timeout_handle cy_timeout_handle 143#define sio_timeouts_until_log cy_timeouts_until_log 144#define sio_tty cy_tty 145 146#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) 147 148/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ 149#define CD1400_xIVR_CHAN_SHIFT 3 150#define CD1400_xIVR_CHAN 0x1F 151 152/* 153 * ETC states. com->etc may also contain a hardware ETC command value, 154 * meaning that execution of that command is pending. 155 */ 156#define ETC_NONE 0 /* we depend on bzero() setting this */ 157#define ETC_BREAK_STARTING 1 158#define ETC_BREAK_STARTED 2 159#define ETC_BREAK_ENDING 3 160#define ETC_BREAK_ENDED 4 161 162#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ 163 164#define CALLOUT_MASK 0x80 165#define CONTROL_MASK 0x60 166#define CONTROL_INIT_STATE 0x20 167#define CONTROL_LOCK_STATE 0x40 168#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 169#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 170#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ 171 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) 172 173/* 174 * com state bits. 175 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher 176 * than the other bits so that they can be tested as a group without masking 177 * off the low bits. 178 * 179 * The following com and tty flags correspond closely: 180 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
|
182 * siostop())
| 181 * comstop())
|
183 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 184 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 185 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 186 * TS_FLUSH is not used. 187 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 188 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 189 */ 190#define CS_BUSY 0x80 /* output in progress */ 191#define CS_TTGO 0x40 /* output not stopped by XOFF */ 192#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 193#define CS_CHECKMSR 1 /* check of MSR scheduled */ 194#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 195#define CS_DTR_OFF 0x10 /* DTR held off */ 196#define CS_ODONE 4 /* output completed */ 197#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 198#define CSE_ODONE 1 /* output transmitted */ 199 200static char const * const error_desc[] = { 201#define CE_OVERRUN 0 202 "silo overflow", 203#define CE_INTERRUPT_BUF_OVERFLOW 1 204 "interrupt-level buffer overflow", 205#define CE_TTY_BUF_OVERFLOW 2 206 "tty-level buffer overflow", 207}; 208 209#define CE_NTYPES 3 210#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 211 212/* types. XXX - should be elsewhere */ 213typedef u_char bool_t; /* boolean */ 214typedef u_char volatile *cy_addr; 215 216/* queue of linear buffers */ 217struct lbq { 218 u_char *l_head; /* next char to process */ 219 u_char *l_tail; /* one past the last char to process */ 220 struct lbq *l_next; /* next in queue */ 221 bool_t l_queued; /* nonzero if queued */ 222}; 223 224/* com device structure */ 225struct com_s { 226 u_char state; /* miscellaneous flag bits */ 227 bool_t active_out; /* nonzero if the callout device is open */ 228#if 0 229 u_char cfcr_image; /* copy of value written to CFCR */ 230#endif 231 u_char etc; /* pending Embedded Transmit Command */ 232 u_char extra_state; /* more flag bits, separate for order trick */ 233#if 0 234 u_char fifo_image; /* copy of value written to FIFO */ 235#endif 236 u_char gfrcr_image; /* copy of value read from GFRCR */ 237#if 0 238 bool_t hasfifo; /* nonzero for 16550 UARTs */ 239 bool_t loses_outints; /* nonzero if device loses output interrupts */ 240#endif 241 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 242 u_char mcr_image; /* copy of value written to MCR */ 243 u_char mcr_rts; /* MCR bit that is wired to RTS */ 244#if 0 245#ifdef COM_MULTIPORT 246 bool_t multiport; /* is this unit part of a multiport device? */ 247#endif /* COM_MULTIPORT */ 248 bool_t no_irq; /* nonzero if irq is not attached */ 249 bool_t poll; /* nonzero if polling is required */ 250 bool_t poll_output; /* nonzero if polling for output is required */ 251#endif 252 int unit; /* unit number */ 253 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 254#if 0 255 u_int tx_fifo_size; 256#endif 257 u_int wopeners; /* # processes waiting for DCD in open() */ 258 259 /* 260 * The high level of the driver never reads status registers directly 261 * because there would be too many side effects to handle conveniently. 262 * Instead, it reads copies of the registers stored here by the 263 * interrupt handler. 264 */ 265 u_char last_modem_status; /* last MSR read by intr handler */ 266 u_char prev_modem_status; /* last MSR handled by high level */ 267 268 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 269 u_char *ibuf; /* start of input buffer */ 270 u_char *ibufend; /* end of input buffer */ 271 u_char *ibufold; /* old input buffer, to be freed */ 272 u_char *ihighwater; /* threshold in input buffer */ 273 u_char *iptr; /* next free spot in input buffer */ 274 int ibufsize; /* size of ibuf (not include error bytes) */ 275 int ierroff; /* offset of error bytes in ibuf */ 276 277 struct lbq obufq; /* head of queue of output buffers */ 278 struct lbq obufs[2]; /* output buffers */ 279 280 int cy_align; /* index for register alignment */ 281 cy_addr cy_iobase; /* base address of this port's cyclom */ 282 cy_addr iobase; /* base address of this port's cd1400 */ 283 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 284 285 struct tty *tp; /* cross reference */ 286 287 /* Initial state. */ 288 struct termios it_in; /* should be in struct tty */ 289 struct termios it_out; 290 291 /* Lock state. */ 292 struct termios lt_in; /* should be in struct tty */ 293 struct termios lt_out; 294 295 bool_t do_timestamp; 296 bool_t do_dcd_timestamp; 297 struct timeval timestamp; 298 struct timeval dcd_timestamp; 299 300 u_long bytes_in; /* statistics */ 301 u_long bytes_out; 302 u_int delta_error_counts[CE_NTYPES]; 303 u_long error_counts[CE_NTYPES]; 304 305 u_int recv_exception; /* exception chars received */ 306 u_int mdm; /* modem signal changes */ 307#ifdef CyDebug 308 u_int start_count; /* no. of calls to comstart() */ 309 u_int start_real; /* no. of calls that did something */ 310#endif 311 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 312 u_char channel_control;/* CD1400 CCR control command shadow */ 313 u_char cor[3]; /* CD1400 COR1-3 shadows */ 314 u_char intr_enable; /* CD1400 SRER shadow */ 315 316 /* 317 * Data area for output buffers. Someday we should build the output 318 * buffer queue without copying data. 319 */ 320 u_char obuf1[256]; 321 u_char obuf2[256]; 322}; 323 324/* PCI driver entry point. */ 325int cyattach_common __P((cy_addr cy_iobase, int cy_align)); 326ointhand2_t siointr; 327 328static int cy_units __P((cy_addr cy_iobase, int cy_align)); 329static int sioattach __P((struct isa_device *dev)); 330static void cd1400_channel_cmd __P((struct com_s *com, int cmd)); 331static void cd1400_channel_cmd_wait __P((struct com_s *com)); 332static void cd_etc __P((struct com_s *com, int etc)); 333static int cd_getreg __P((struct com_s *com, int reg)); 334static void cd_setreg __P((struct com_s *com, int reg, int val)); 335static timeout_t siodtrwakeup; 336static void comhardclose __P((struct com_s *com)); 337static void sioinput __P((struct com_s *com)); 338#if 0 339static void siointr1 __P((struct com_s *com)); 340#endif 341static int commctl __P((struct com_s *com, int bits, int how)); 342static int comparam __P((struct tty *tp, struct termios *t)); 343static swihand_t siopoll; 344static int sioprobe __P((struct isa_device *dev)); 345static void siosettimeout __P((void)); 346static int siosetwater __P((struct com_s *com, speed_t speed)); 347static int comspeed __P((speed_t speed, u_long cy_clock, 348 int *prescaler_io)); 349static void comstart __P((struct tty *tp));
| 182 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) 183 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) 184 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) 185 * TS_FLUSH is not used. 186 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. 187 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). 188 */ 189#define CS_BUSY 0x80 /* output in progress */ 190#define CS_TTGO 0x40 /* output not stopped by XOFF */ 191#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ 192#define CS_CHECKMSR 1 /* check of MSR scheduled */ 193#define CS_CTS_OFLOW 2 /* use CTS output flow control */ 194#define CS_DTR_OFF 0x10 /* DTR held off */ 195#define CS_ODONE 4 /* output completed */ 196#define CS_RTS_IFLOW 8 /* use RTS input flow control */ 197#define CSE_ODONE 1 /* output transmitted */ 198 199static char const * const error_desc[] = { 200#define CE_OVERRUN 0 201 "silo overflow", 202#define CE_INTERRUPT_BUF_OVERFLOW 1 203 "interrupt-level buffer overflow", 204#define CE_TTY_BUF_OVERFLOW 2 205 "tty-level buffer overflow", 206}; 207 208#define CE_NTYPES 3 209#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) 210 211/* types. XXX - should be elsewhere */ 212typedef u_char bool_t; /* boolean */ 213typedef u_char volatile *cy_addr; 214 215/* queue of linear buffers */ 216struct lbq { 217 u_char *l_head; /* next char to process */ 218 u_char *l_tail; /* one past the last char to process */ 219 struct lbq *l_next; /* next in queue */ 220 bool_t l_queued; /* nonzero if queued */ 221}; 222 223/* com device structure */ 224struct com_s { 225 u_char state; /* miscellaneous flag bits */ 226 bool_t active_out; /* nonzero if the callout device is open */ 227#if 0 228 u_char cfcr_image; /* copy of value written to CFCR */ 229#endif 230 u_char etc; /* pending Embedded Transmit Command */ 231 u_char extra_state; /* more flag bits, separate for order trick */ 232#if 0 233 u_char fifo_image; /* copy of value written to FIFO */ 234#endif 235 u_char gfrcr_image; /* copy of value read from GFRCR */ 236#if 0 237 bool_t hasfifo; /* nonzero for 16550 UARTs */ 238 bool_t loses_outints; /* nonzero if device loses output interrupts */ 239#endif 240 u_char mcr_dtr; /* MCR bit that is wired to DTR */ 241 u_char mcr_image; /* copy of value written to MCR */ 242 u_char mcr_rts; /* MCR bit that is wired to RTS */ 243#if 0 244#ifdef COM_MULTIPORT 245 bool_t multiport; /* is this unit part of a multiport device? */ 246#endif /* COM_MULTIPORT */ 247 bool_t no_irq; /* nonzero if irq is not attached */ 248 bool_t poll; /* nonzero if polling is required */ 249 bool_t poll_output; /* nonzero if polling for output is required */ 250#endif 251 int unit; /* unit number */ 252 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ 253#if 0 254 u_int tx_fifo_size; 255#endif 256 u_int wopeners; /* # processes waiting for DCD in open() */ 257 258 /* 259 * The high level of the driver never reads status registers directly 260 * because there would be too many side effects to handle conveniently. 261 * Instead, it reads copies of the registers stored here by the 262 * interrupt handler. 263 */ 264 u_char last_modem_status; /* last MSR read by intr handler */ 265 u_char prev_modem_status; /* last MSR handled by high level */ 266 267 u_char hotchar; /* ldisc-specific char to be handled ASAP */ 268 u_char *ibuf; /* start of input buffer */ 269 u_char *ibufend; /* end of input buffer */ 270 u_char *ibufold; /* old input buffer, to be freed */ 271 u_char *ihighwater; /* threshold in input buffer */ 272 u_char *iptr; /* next free spot in input buffer */ 273 int ibufsize; /* size of ibuf (not include error bytes) */ 274 int ierroff; /* offset of error bytes in ibuf */ 275 276 struct lbq obufq; /* head of queue of output buffers */ 277 struct lbq obufs[2]; /* output buffers */ 278 279 int cy_align; /* index for register alignment */ 280 cy_addr cy_iobase; /* base address of this port's cyclom */ 281 cy_addr iobase; /* base address of this port's cd1400 */ 282 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ 283 284 struct tty *tp; /* cross reference */ 285 286 /* Initial state. */ 287 struct termios it_in; /* should be in struct tty */ 288 struct termios it_out; 289 290 /* Lock state. */ 291 struct termios lt_in; /* should be in struct tty */ 292 struct termios lt_out; 293 294 bool_t do_timestamp; 295 bool_t do_dcd_timestamp; 296 struct timeval timestamp; 297 struct timeval dcd_timestamp; 298 299 u_long bytes_in; /* statistics */ 300 u_long bytes_out; 301 u_int delta_error_counts[CE_NTYPES]; 302 u_long error_counts[CE_NTYPES]; 303 304 u_int recv_exception; /* exception chars received */ 305 u_int mdm; /* modem signal changes */ 306#ifdef CyDebug 307 u_int start_count; /* no. of calls to comstart() */ 308 u_int start_real; /* no. of calls that did something */ 309#endif 310 u_char car; /* CD1400 CAR shadow (if first unit in cd) */ 311 u_char channel_control;/* CD1400 CCR control command shadow */ 312 u_char cor[3]; /* CD1400 COR1-3 shadows */ 313 u_char intr_enable; /* CD1400 SRER shadow */ 314 315 /* 316 * Data area for output buffers. Someday we should build the output 317 * buffer queue without copying data. 318 */ 319 u_char obuf1[256]; 320 u_char obuf2[256]; 321}; 322 323/* PCI driver entry point. */ 324int cyattach_common __P((cy_addr cy_iobase, int cy_align)); 325ointhand2_t siointr; 326 327static int cy_units __P((cy_addr cy_iobase, int cy_align)); 328static int sioattach __P((struct isa_device *dev)); 329static void cd1400_channel_cmd __P((struct com_s *com, int cmd)); 330static void cd1400_channel_cmd_wait __P((struct com_s *com)); 331static void cd_etc __P((struct com_s *com, int etc)); 332static int cd_getreg __P((struct com_s *com, int reg)); 333static void cd_setreg __P((struct com_s *com, int reg, int val)); 334static timeout_t siodtrwakeup; 335static void comhardclose __P((struct com_s *com)); 336static void sioinput __P((struct com_s *com)); 337#if 0 338static void siointr1 __P((struct com_s *com)); 339#endif 340static int commctl __P((struct com_s *com, int bits, int how)); 341static int comparam __P((struct tty *tp, struct termios *t)); 342static swihand_t siopoll; 343static int sioprobe __P((struct isa_device *dev)); 344static void siosettimeout __P((void)); 345static int siosetwater __P((struct com_s *com, speed_t speed)); 346static int comspeed __P((speed_t speed, u_long cy_clock, 347 int *prescaler_io)); 348static void comstart __P((struct tty *tp));
|
| 349static void comstop __P((struct tty *tp, int rw));
|
350static timeout_t comwakeup; 351static void disc_optim __P((struct tty *tp, struct termios *t, 352 struct com_s *com)); 353 354#ifdef CyDebug 355void cystatus __P((int unit)); 356#endif 357 358static char driver_name[] = "cy"; 359 360/* table and macro for fast conversion from a unit number to its com struct */ 361static struct com_s *p_com_addr[NSIO]; 362#define com_addr(unit) (p_com_addr[unit]) 363 364struct isa_driver siodriver = { 365 sioprobe, sioattach, driver_name 366}; 367 368static d_open_t sioopen; 369static d_close_t sioclose; 370static d_read_t sioread; 371static d_write_t siowrite; 372static d_ioctl_t sioioctl;
| 350static timeout_t comwakeup; 351static void disc_optim __P((struct tty *tp, struct termios *t, 352 struct com_s *com)); 353 354#ifdef CyDebug 355void cystatus __P((int unit)); 356#endif 357 358static char driver_name[] = "cy"; 359 360/* table and macro for fast conversion from a unit number to its com struct */ 361static struct com_s *p_com_addr[NSIO]; 362#define com_addr(unit) (p_com_addr[unit]) 363 364struct isa_driver siodriver = { 365 sioprobe, sioattach, driver_name 366}; 367 368static d_open_t sioopen; 369static d_close_t sioclose; 370static d_read_t sioread; 371static d_write_t siowrite; 372static d_ioctl_t sioioctl;
|
373static d_stop_t siostop; 374static d_devtotty_t siodevtotty;
| |
375 376#define CDEV_MAJOR 48 377static struct cdevsw sio_cdevsw = { 378 /* open */ sioopen, 379 /* close */ sioclose, 380 /* read */ sioread, 381 /* write */ siowrite, 382 /* ioctl */ sioioctl,
| 373 374#define CDEV_MAJOR 48 375static struct cdevsw sio_cdevsw = { 376 /* open */ sioopen, 377 /* close */ sioclose, 378 /* read */ sioread, 379 /* write */ siowrite, 380 /* ioctl */ sioioctl,
|
383 /* stop */ siostop,
| 381 /* stop */ nostop,
|
384 /* reset */ noreset,
| 382 /* reset */ noreset,
|
385 /* devtotty */ siodevtotty, 386 /* poll */ ttpoll,
| 383 /* devtotty */ nodevtotty, 384 /* poll */ ttypoll,
|
387 /* mmap */ nommap, 388 /* strategy */ nostrategy, 389 /* name */ driver_name, 390 /* parms */ noparms, 391 /* maj */ CDEV_MAJOR, 392 /* dump */ nodump, 393 /* psize */ nopsize, 394 /* flags */ D_TTY, 395 /* maxio */ 0, 396 /* bmaj */ -1 397}; 398 399static int comconsole = -1; 400static speed_t comdefaultrate = TTYDEF_SPEED; 401static u_int com_events; /* input chars + weighted output completions */ 402static bool_t sio_registered; 403static int sio_timeout; 404static int sio_timeouts_until_log; 405static struct callout_handle sio_timeout_handle 406 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 407#if 0 /* XXX */ 408static struct tty *sio_tty[NSIO]; 409#else 410static struct tty sio_tty[NSIO]; 411#endif 412static const int nsio_tty = NSIO; 413 414#ifdef CyDebug 415static u_int cd_inbs; 416static u_int cy_inbs; 417static u_int cd_outbs; 418static u_int cy_outbs; 419static u_int cy_svrr_probes; 420static u_int cy_timeouts; 421#endif 422 423static int cy_chip_offset[] = { 424 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 425}; 426static int cy_nr_cd1400s[NCY]; 427static int cy_total_devices; 428#undef RxFifoThreshold 429static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 430 431static int 432sioprobe(dev) 433 struct isa_device *dev; 434{ 435 cy_addr iobase; 436 437 iobase = (cy_addr)dev->id_maddr; 438 439 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 440 cy_inb(iobase, CY16_RESET, 0); /* XXX? */ 441 DELAY(500); /* wait for the board to get its act together */ 442 443 /* this is needed to get the board out of reset */ 444 cy_outb(iobase, CY_CLEAR_INTR, 0, 0); 445 DELAY(500); 446 447 return (cy_units(iobase, 0) == 0 ? 0 : -1); 448} 449 450static int 451cy_units(cy_iobase, cy_align) 452 cy_addr cy_iobase; 453 int cy_align; 454{ 455 int cyu; 456 u_char firmware_version; 457 int i; 458 cy_addr iobase; 459 460 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 461 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 462 463 /* wait for chip to become ready for new command */ 464 for (i = 0; i < 10; i++) { 465 DELAY(50); 466 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 467 break; 468 } 469 470 /* clear the GFRCR register */ 471 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 472 473 /* issue a reset command */ 474 cd_outb(iobase, CD1400_CCR, cy_align, 475 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 476 477 /* wait for the CD1400 to initialize itself */ 478 for (i = 0; i < 200; i++) { 479 DELAY(50); 480 481 /* retrieve firmware version */ 482 firmware_version = cd_inb(iobase, CD1400_GFRCR, 483 cy_align); 484 if ((firmware_version & 0xf0) == 0x40) 485 break; 486 } 487 488 /* 489 * Anything in the 0x40-0x4F range is fine. 490 * If one CD1400 is bad then we don't support higher 491 * numbered good ones on this board. 492 */ 493 if ((firmware_version & 0xf0) != 0x40) 494 break; 495 } 496 return (cyu); 497} 498 499static int 500sioattach(isdp) 501 struct isa_device *isdp; 502{ 503 int adapter; 504 505 adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); 506 if (adapter < 0) 507 return (0); 508 509 /* 510 * XXX 511 * This kludge is to allow ISA/PCI device specifications in the 512 * kernel config file to be in any order. 513 */ 514 if (isdp->id_unit != adapter) { 515 printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter); 516 isdp->id_unit = adapter; /* XXX */ 517 } 518 isdp->id_ointr = siointr; 519 isdp->id_ri_flags |= RI_FAST; 520 return (1); 521} 522 523int 524cyattach_common(cy_iobase, cy_align) 525 cy_addr cy_iobase; 526 int cy_align; 527{ 528 int adapter; 529 int cyu; 530 u_char firmware_version; 531 cy_addr iobase; 532 int ncyu; 533 int unit; 534 535 adapter = cy_total_devices; 536 if ((u_int)adapter >= NCY) { 537 printf( 538 "cy%d: can't attach adapter: insufficient cy devices configured\n", 539 adapter); 540 return (-1); 541 } 542 ncyu = cy_units(cy_iobase, cy_align); 543 if (ncyu == 0) 544 return (-1); 545 cy_nr_cd1400s[adapter] = ncyu; 546 cy_total_devices++; 547 548 unit = adapter * CY_MAX_PORTS; 549 for (cyu = 0; cyu < ncyu; ++cyu) { 550 int cdu; 551 552 iobase = (cy_addr) (cy_iobase 553 + (cy_chip_offset[cyu] << cy_align)); 554 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 555 556 /* Set up a receive timeout period of than 1+ ms. */ 557 cd_outb(iobase, CD1400_PPR, cy_align, 558 howmany(CY_CLOCK(firmware_version) 559 / CD1400_PPR_PRESCALER, 1000)); 560 561 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 562 struct com_s *com; 563 int s; 564 565 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT); 566 if (com == NULL) 567 break; 568 bzero(com, sizeof *com); 569 com->unit = unit; 570 com->gfrcr_image = firmware_version; 571 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 572 com->mcr_dtr = MCR_RTS; 573 com->mcr_rts = MCR_DTR; 574 com->mcr_rts_reg = CD1400_MSVR2; 575 } else { 576 com->mcr_dtr = MCR_DTR; 577 com->mcr_rts = MCR_RTS; 578 com->mcr_rts_reg = CD1400_MSVR1; 579 } 580 com->dtr_wait = 3 * hz; 581 com->obufs[0].l_head = com->obuf1; 582 com->obufs[1].l_head = com->obuf2; 583 584 com->cy_align = cy_align; 585 com->cy_iobase = cy_iobase; 586 com->iobase = iobase; 587 com->car = ~CD1400_CAR_CHAN; 588 589 /* 590 * We don't use all the flags from <sys/ttydefaults.h> since they 591 * are only relevant for logins. It's important to have echo off 592 * initially so that the line doesn't start blathering before the 593 * echo flag can be turned off. 594 */ 595 com->it_in.c_iflag = 0; 596 com->it_in.c_oflag = 0; 597 com->it_in.c_cflag = TTYDEF_CFLAG; 598 com->it_in.c_lflag = 0; 599 if (unit == comconsole) { 600 com->it_in.c_iflag = TTYDEF_IFLAG; 601 com->it_in.c_oflag = TTYDEF_OFLAG; 602 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 603 com->it_in.c_lflag = TTYDEF_LFLAG; 604 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 605 } 606 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 607 enable_intr(); 608 free(com, M_DEVBUF); 609 return (0); 610 } 611 enable_intr(); 612 termioschars(&com->it_in); 613 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 614 com->it_out = com->it_in; 615 616 s = spltty(); 617 com_addr(unit) = com; 618 splx(s); 619 620 if (!sio_registered) { 621 cdevsw_add(&sio_cdevsw); 622 register_swi(SWI_TTY, siopoll); 623 sio_registered = TRUE; 624 } 625 make_dev(&sio_cdevsw, unit, 626 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 627 unit % CY_MAX_PORTS); 628 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE, 629 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 630 unit % CY_MAX_PORTS); 631 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE, 632 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 633 unit % CY_MAX_PORTS); 634 make_dev(&sio_cdevsw, unit | CALLOUT_MASK, 635 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 636 unit % CY_MAX_PORTS); 637 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE, 638 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 639 unit % CY_MAX_PORTS); 640 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 641 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 642 unit % CY_MAX_PORTS); 643 } 644 } 645 646 /* ensure an edge for the next interrupt */ 647 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 648 649 return (adapter); 650} 651 652static int 653sioopen(dev, flag, mode, p) 654 dev_t dev; 655 int flag; 656 int mode; 657 struct proc *p; 658{ 659 struct com_s *com; 660 int error; 661 int mynor; 662 int s; 663 struct tty *tp; 664 int unit; 665 666 mynor = minor(dev); 667 unit = MINOR_TO_UNIT(mynor); 668 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 669 return (ENXIO); 670 if (mynor & CONTROL_MASK) 671 return (0); 672#if 0 /* XXX */ 673 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 674#else 675 tp = com->tp = &sio_tty[unit]; 676#endif
| 385 /* mmap */ nommap, 386 /* strategy */ nostrategy, 387 /* name */ driver_name, 388 /* parms */ noparms, 389 /* maj */ CDEV_MAJOR, 390 /* dump */ nodump, 391 /* psize */ nopsize, 392 /* flags */ D_TTY, 393 /* maxio */ 0, 394 /* bmaj */ -1 395}; 396 397static int comconsole = -1; 398static speed_t comdefaultrate = TTYDEF_SPEED; 399static u_int com_events; /* input chars + weighted output completions */ 400static bool_t sio_registered; 401static int sio_timeout; 402static int sio_timeouts_until_log; 403static struct callout_handle sio_timeout_handle 404 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); 405#if 0 /* XXX */ 406static struct tty *sio_tty[NSIO]; 407#else 408static struct tty sio_tty[NSIO]; 409#endif 410static const int nsio_tty = NSIO; 411 412#ifdef CyDebug 413static u_int cd_inbs; 414static u_int cy_inbs; 415static u_int cd_outbs; 416static u_int cy_outbs; 417static u_int cy_svrr_probes; 418static u_int cy_timeouts; 419#endif 420 421static int cy_chip_offset[] = { 422 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, 423}; 424static int cy_nr_cd1400s[NCY]; 425static int cy_total_devices; 426#undef RxFifoThreshold 427static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); 428 429static int 430sioprobe(dev) 431 struct isa_device *dev; 432{ 433 cy_addr iobase; 434 435 iobase = (cy_addr)dev->id_maddr; 436 437 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ 438 cy_inb(iobase, CY16_RESET, 0); /* XXX? */ 439 DELAY(500); /* wait for the board to get its act together */ 440 441 /* this is needed to get the board out of reset */ 442 cy_outb(iobase, CY_CLEAR_INTR, 0, 0); 443 DELAY(500); 444 445 return (cy_units(iobase, 0) == 0 ? 0 : -1); 446} 447 448static int 449cy_units(cy_iobase, cy_align) 450 cy_addr cy_iobase; 451 int cy_align; 452{ 453 int cyu; 454 u_char firmware_version; 455 int i; 456 cy_addr iobase; 457 458 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { 459 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); 460 461 /* wait for chip to become ready for new command */ 462 for (i = 0; i < 10; i++) { 463 DELAY(50); 464 if (!cd_inb(iobase, CD1400_CCR, cy_align)) 465 break; 466 } 467 468 /* clear the GFRCR register */ 469 cd_outb(iobase, CD1400_GFRCR, cy_align, 0); 470 471 /* issue a reset command */ 472 cd_outb(iobase, CD1400_CCR, cy_align, 473 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); 474 475 /* wait for the CD1400 to initialize itself */ 476 for (i = 0; i < 200; i++) { 477 DELAY(50); 478 479 /* retrieve firmware version */ 480 firmware_version = cd_inb(iobase, CD1400_GFRCR, 481 cy_align); 482 if ((firmware_version & 0xf0) == 0x40) 483 break; 484 } 485 486 /* 487 * Anything in the 0x40-0x4F range is fine. 488 * If one CD1400 is bad then we don't support higher 489 * numbered good ones on this board. 490 */ 491 if ((firmware_version & 0xf0) != 0x40) 492 break; 493 } 494 return (cyu); 495} 496 497static int 498sioattach(isdp) 499 struct isa_device *isdp; 500{ 501 int adapter; 502 503 adapter = cyattach_common((cy_addr) isdp->id_maddr, 0); 504 if (adapter < 0) 505 return (0); 506 507 /* 508 * XXX 509 * This kludge is to allow ISA/PCI device specifications in the 510 * kernel config file to be in any order. 511 */ 512 if (isdp->id_unit != adapter) { 513 printf("cy%d: attached as cy%d\n", isdp->id_unit, adapter); 514 isdp->id_unit = adapter; /* XXX */ 515 } 516 isdp->id_ointr = siointr; 517 isdp->id_ri_flags |= RI_FAST; 518 return (1); 519} 520 521int 522cyattach_common(cy_iobase, cy_align) 523 cy_addr cy_iobase; 524 int cy_align; 525{ 526 int adapter; 527 int cyu; 528 u_char firmware_version; 529 cy_addr iobase; 530 int ncyu; 531 int unit; 532 533 adapter = cy_total_devices; 534 if ((u_int)adapter >= NCY) { 535 printf( 536 "cy%d: can't attach adapter: insufficient cy devices configured\n", 537 adapter); 538 return (-1); 539 } 540 ncyu = cy_units(cy_iobase, cy_align); 541 if (ncyu == 0) 542 return (-1); 543 cy_nr_cd1400s[adapter] = ncyu; 544 cy_total_devices++; 545 546 unit = adapter * CY_MAX_PORTS; 547 for (cyu = 0; cyu < ncyu; ++cyu) { 548 int cdu; 549 550 iobase = (cy_addr) (cy_iobase 551 + (cy_chip_offset[cyu] << cy_align)); 552 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); 553 554 /* Set up a receive timeout period of than 1+ ms. */ 555 cd_outb(iobase, CD1400_PPR, cy_align, 556 howmany(CY_CLOCK(firmware_version) 557 / CD1400_PPR_PRESCALER, 1000)); 558 559 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { 560 struct com_s *com; 561 int s; 562 563 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT); 564 if (com == NULL) 565 break; 566 bzero(com, sizeof *com); 567 com->unit = unit; 568 com->gfrcr_image = firmware_version; 569 if (CY_RTS_DTR_SWAPPED(firmware_version)) { 570 com->mcr_dtr = MCR_RTS; 571 com->mcr_rts = MCR_DTR; 572 com->mcr_rts_reg = CD1400_MSVR2; 573 } else { 574 com->mcr_dtr = MCR_DTR; 575 com->mcr_rts = MCR_RTS; 576 com->mcr_rts_reg = CD1400_MSVR1; 577 } 578 com->dtr_wait = 3 * hz; 579 com->obufs[0].l_head = com->obuf1; 580 com->obufs[1].l_head = com->obuf2; 581 582 com->cy_align = cy_align; 583 com->cy_iobase = cy_iobase; 584 com->iobase = iobase; 585 com->car = ~CD1400_CAR_CHAN; 586 587 /* 588 * We don't use all the flags from <sys/ttydefaults.h> since they 589 * are only relevant for logins. It's important to have echo off 590 * initially so that the line doesn't start blathering before the 591 * echo flag can be turned off. 592 */ 593 com->it_in.c_iflag = 0; 594 com->it_in.c_oflag = 0; 595 com->it_in.c_cflag = TTYDEF_CFLAG; 596 com->it_in.c_lflag = 0; 597 if (unit == comconsole) { 598 com->it_in.c_iflag = TTYDEF_IFLAG; 599 com->it_in.c_oflag = TTYDEF_OFLAG; 600 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; 601 com->it_in.c_lflag = TTYDEF_LFLAG; 602 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; 603 } 604 if (siosetwater(com, com->it_in.c_ispeed) != 0) { 605 enable_intr(); 606 free(com, M_DEVBUF); 607 return (0); 608 } 609 enable_intr(); 610 termioschars(&com->it_in); 611 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; 612 com->it_out = com->it_in; 613 614 s = spltty(); 615 com_addr(unit) = com; 616 splx(s); 617 618 if (!sio_registered) { 619 cdevsw_add(&sio_cdevsw); 620 register_swi(SWI_TTY, siopoll); 621 sio_registered = TRUE; 622 } 623 make_dev(&sio_cdevsw, unit, 624 UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, 625 unit % CY_MAX_PORTS); 626 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE, 627 UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, 628 unit % CY_MAX_PORTS); 629 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE, 630 UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, 631 unit % CY_MAX_PORTS); 632 make_dev(&sio_cdevsw, unit | CALLOUT_MASK, 633 UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, 634 unit % CY_MAX_PORTS); 635 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE, 636 UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, 637 unit % CY_MAX_PORTS); 638 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE, 639 UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, 640 unit % CY_MAX_PORTS); 641 } 642 } 643 644 /* ensure an edge for the next interrupt */ 645 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 646 647 return (adapter); 648} 649 650static int 651sioopen(dev, flag, mode, p) 652 dev_t dev; 653 int flag; 654 int mode; 655 struct proc *p; 656{ 657 struct com_s *com; 658 int error; 659 int mynor; 660 int s; 661 struct tty *tp; 662 int unit; 663 664 mynor = minor(dev); 665 unit = MINOR_TO_UNIT(mynor); 666 if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) 667 return (ENXIO); 668 if (mynor & CONTROL_MASK) 669 return (0); 670#if 0 /* XXX */ 671 tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); 672#else 673 tp = com->tp = &sio_tty[unit]; 674#endif
|
| 675 dev->si_tty = tp;
|
677 s = spltty(); 678 /* 679 * We jump to this label after all non-interrupted sleeps to pick 680 * up any changes of the device state. 681 */ 682open_top: 683 while (com->state & CS_DTR_OFF) { 684 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 685 if (error != 0) 686 goto out; 687 } 688 if (tp->t_state & TS_ISOPEN) { 689 /* 690 * The device is open, so everything has been initialized. 691 * Handle conflicts. 692 */ 693 if (mynor & CALLOUT_MASK) { 694 if (!com->active_out) { 695 error = EBUSY; 696 goto out; 697 } 698 } else { 699 if (com->active_out) { 700 if (flag & O_NONBLOCK) { 701 error = EBUSY; 702 goto out; 703 } 704 error = tsleep(&com->active_out, 705 TTIPRI | PCATCH, "cybi", 0); 706 if (error != 0) 707 goto out; 708 goto open_top; 709 } 710 } 711 if (tp->t_state & TS_XCLUDE && 712 suser(p)) { 713 error = EBUSY; 714 goto out; 715 } 716 } else { 717 /* 718 * The device isn't open, so there are no conflicts. 719 * Initialize it. Initialization is done twice in many 720 * cases: to preempt sleeping callin opens if we are 721 * callout, and to complete a callin open after DCD rises. 722 */ 723 tp->t_oproc = comstart;
| 676 s = spltty(); 677 /* 678 * We jump to this label after all non-interrupted sleeps to pick 679 * up any changes of the device state. 680 */ 681open_top: 682 while (com->state & CS_DTR_OFF) { 683 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "cydtr", 0); 684 if (error != 0) 685 goto out; 686 } 687 if (tp->t_state & TS_ISOPEN) { 688 /* 689 * The device is open, so everything has been initialized. 690 * Handle conflicts. 691 */ 692 if (mynor & CALLOUT_MASK) { 693 if (!com->active_out) { 694 error = EBUSY; 695 goto out; 696 } 697 } else { 698 if (com->active_out) { 699 if (flag & O_NONBLOCK) { 700 error = EBUSY; 701 goto out; 702 } 703 error = tsleep(&com->active_out, 704 TTIPRI | PCATCH, "cybi", 0); 705 if (error != 0) 706 goto out; 707 goto open_top; 708 } 709 } 710 if (tp->t_state & TS_XCLUDE && 711 suser(p)) { 712 error = EBUSY; 713 goto out; 714 } 715 } else { 716 /* 717 * The device isn't open, so there are no conflicts. 718 * Initialize it. Initialization is done twice in many 719 * cases: to preempt sleeping callin opens if we are 720 * callout, and to complete a callin open after DCD rises. 721 */ 722 tp->t_oproc = comstart;
|
| 723 tp->t_stop = comstop;
|
724 tp->t_param = comparam; 725 tp->t_dev = dev; 726 tp->t_termios = mynor & CALLOUT_MASK 727 ? com->it_out : com->it_in; 728 729 /* Encode per-board unit in LIVR for access in intr routines. */ 730 cd_setreg(com, CD1400_LIVR, 731 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 732 733 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 734#if 0 735 com->poll = com->no_irq; 736 com->poll_output = com->loses_outints; 737#endif 738 ++com->wopeners; 739 error = comparam(tp, &tp->t_termios); 740 --com->wopeners; 741 if (error != 0) 742 goto out; 743#if 0 744 if (com->hasfifo) { 745 /* 746 * (Re)enable and flush fifos. 747 * 748 * Certain SMC chips cause problems if the fifos 749 * are enabled while input is ready. Turn off the 750 * fifo if necessary to clear the input. We test 751 * the input ready bit after enabling the fifos 752 * since we've already enabled them in comparam() 753 * and to handle races between enabling and fresh 754 * input. 755 */ 756 while (TRUE) { 757 outb(iobase + com_fifo, 758 FIFO_RCV_RST | FIFO_XMT_RST 759 | com->fifo_image); 760 DELAY(100); 761 if (!(inb(com->line_status_port) & LSR_RXRDY)) 762 break; 763 outb(iobase + com_fifo, 0); 764 DELAY(100); 765 (void) inb(com->data_port); 766 } 767 } 768 769 disable_intr(); 770 (void) inb(com->line_status_port); 771 (void) inb(com->data_port); 772 com->prev_modem_status = com->last_modem_status 773 = inb(com->modem_status_port); 774 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 775 | IER_EMSC); 776 enable_intr(); 777#else /* !0 */ 778 /* 779 * Flush fifos. This requires a full channel reset which 780 * also disables the transmitter and receiver. Recover 781 * from this. 782 */ 783 cd1400_channel_cmd(com, 784 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 785 cd1400_channel_cmd(com, com->channel_control); 786 787 disable_intr(); 788 com->prev_modem_status = com->last_modem_status 789 = cd_getreg(com, CD1400_MSVR2); 790 cd_setreg(com, CD1400_SRER, 791 com->intr_enable 792 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 793 enable_intr(); 794#endif /* 0 */ 795 /* 796 * Handle initial DCD. Callout devices get a fake initial 797 * DCD (trapdoor DCD). If we are callout, then any sleeping 798 * callin opens get woken up and resume sleeping on "cybi" 799 * instead of "cydcd". 800 */ 801 /* 802 * XXX `mynor & CALLOUT_MASK' should be 803 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 804 * TRAPDOOR_CARRIER is the default initial state for callout 805 * devices and SOFT_CARRIER is like CLOCAL except it hides 806 * the true carrier. 807 */ 808 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 809 (*linesw[tp->t_line].l_modem)(tp, 1); 810 } 811 /* 812 * Wait for DCD if necessary. 813 */ 814 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 815 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 816 ++com->wopeners; 817 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 818 --com->wopeners; 819 if (error != 0) 820 goto out; 821 goto open_top; 822 } 823 error = (*linesw[tp->t_line].l_open)(dev, tp); 824 disc_optim(tp, &tp->t_termios, com); 825 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 826 com->active_out = TRUE; 827 siosettimeout(); 828out: 829 splx(s); 830 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 831 comhardclose(com); 832 return (error); 833} 834 835static int 836sioclose(dev, flag, mode, p) 837 dev_t dev; 838 int flag; 839 int mode; 840 struct proc *p; 841{ 842 struct com_s *com; 843 int mynor; 844 int s; 845 struct tty *tp; 846 847 mynor = minor(dev); 848 if (mynor & CONTROL_MASK) 849 return (0); 850 com = com_addr(MINOR_TO_UNIT(mynor)); 851 tp = com->tp; 852 s = spltty(); 853 cd_etc(com, CD1400_ETC_STOPBREAK); 854 (*linesw[tp->t_line].l_close)(tp, flag); 855 disc_optim(tp, &tp->t_termios, com);
| 724 tp->t_param = comparam; 725 tp->t_dev = dev; 726 tp->t_termios = mynor & CALLOUT_MASK 727 ? com->it_out : com->it_in; 728 729 /* Encode per-board unit in LIVR for access in intr routines. */ 730 cd_setreg(com, CD1400_LIVR, 731 (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); 732 733 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); 734#if 0 735 com->poll = com->no_irq; 736 com->poll_output = com->loses_outints; 737#endif 738 ++com->wopeners; 739 error = comparam(tp, &tp->t_termios); 740 --com->wopeners; 741 if (error != 0) 742 goto out; 743#if 0 744 if (com->hasfifo) { 745 /* 746 * (Re)enable and flush fifos. 747 * 748 * Certain SMC chips cause problems if the fifos 749 * are enabled while input is ready. Turn off the 750 * fifo if necessary to clear the input. We test 751 * the input ready bit after enabling the fifos 752 * since we've already enabled them in comparam() 753 * and to handle races between enabling and fresh 754 * input. 755 */ 756 while (TRUE) { 757 outb(iobase + com_fifo, 758 FIFO_RCV_RST | FIFO_XMT_RST 759 | com->fifo_image); 760 DELAY(100); 761 if (!(inb(com->line_status_port) & LSR_RXRDY)) 762 break; 763 outb(iobase + com_fifo, 0); 764 DELAY(100); 765 (void) inb(com->data_port); 766 } 767 } 768 769 disable_intr(); 770 (void) inb(com->line_status_port); 771 (void) inb(com->data_port); 772 com->prev_modem_status = com->last_modem_status 773 = inb(com->modem_status_port); 774 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS 775 | IER_EMSC); 776 enable_intr(); 777#else /* !0 */ 778 /* 779 * Flush fifos. This requires a full channel reset which 780 * also disables the transmitter and receiver. Recover 781 * from this. 782 */ 783 cd1400_channel_cmd(com, 784 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); 785 cd1400_channel_cmd(com, com->channel_control); 786 787 disable_intr(); 788 com->prev_modem_status = com->last_modem_status 789 = cd_getreg(com, CD1400_MSVR2); 790 cd_setreg(com, CD1400_SRER, 791 com->intr_enable 792 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); 793 enable_intr(); 794#endif /* 0 */ 795 /* 796 * Handle initial DCD. Callout devices get a fake initial 797 * DCD (trapdoor DCD). If we are callout, then any sleeping 798 * callin opens get woken up and resume sleeping on "cybi" 799 * instead of "cydcd". 800 */ 801 /* 802 * XXX `mynor & CALLOUT_MASK' should be 803 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where 804 * TRAPDOOR_CARRIER is the default initial state for callout 805 * devices and SOFT_CARRIER is like CLOCAL except it hides 806 * the true carrier. 807 */ 808 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) 809 (*linesw[tp->t_line].l_modem)(tp, 1); 810 } 811 /* 812 * Wait for DCD if necessary. 813 */ 814 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) 815 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 816 ++com->wopeners; 817 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "cydcd", 0); 818 --com->wopeners; 819 if (error != 0) 820 goto out; 821 goto open_top; 822 } 823 error = (*linesw[tp->t_line].l_open)(dev, tp); 824 disc_optim(tp, &tp->t_termios, com); 825 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 826 com->active_out = TRUE; 827 siosettimeout(); 828out: 829 splx(s); 830 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) 831 comhardclose(com); 832 return (error); 833} 834 835static int 836sioclose(dev, flag, mode, p) 837 dev_t dev; 838 int flag; 839 int mode; 840 struct proc *p; 841{ 842 struct com_s *com; 843 int mynor; 844 int s; 845 struct tty *tp; 846 847 mynor = minor(dev); 848 if (mynor & CONTROL_MASK) 849 return (0); 850 com = com_addr(MINOR_TO_UNIT(mynor)); 851 tp = com->tp; 852 s = spltty(); 853 cd_etc(com, CD1400_ETC_STOPBREAK); 854 (*linesw[tp->t_line].l_close)(tp, flag); 855 disc_optim(tp, &tp->t_termios, com);
|
856 siostop(tp, FREAD | FWRITE);
| 856 comstop(tp, FREAD | FWRITE);
|
857 comhardclose(com); 858 ttyclose(tp); 859 siosettimeout(); 860 splx(s); 861#ifdef broken /* session holds a ref to the tty; can't deallocate */ 862 ttyfree(tp); 863 com->tp = sio_tty[unit] = NULL; 864#endif 865 return (0); 866} 867 868static void 869comhardclose(com) 870 struct com_s *com; 871{ 872 cy_addr iobase; 873 int s; 874 struct tty *tp; 875 int unit; 876 877 unit = com->unit; 878 iobase = com->iobase; 879 s = spltty(); 880#if 0 881 com->poll = FALSE; 882 com->poll_output = FALSE; 883#endif 884 com->do_timestamp = 0; 885#if 0 886 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 887#else 888 /* XXX */ 889 disable_intr(); 890 com->etc = ETC_NONE; 891 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 892 enable_intr(); 893 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 894#endif 895 896 { 897#if 0 898 outb(iobase + com_ier, 0); 899#else 900 disable_intr(); 901 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 902 enable_intr(); 903#endif 904 tp = com->tp; 905 if ((tp->t_cflag & HUPCL) 906 /* 907 * XXX we will miss any carrier drop between here and the 908 * next open. Perhaps we should watch DCD even when the 909 * port is closed; it is not sufficient to check it at 910 * the next open because it might go up and down while 911 * we're not watching. 912 */ 913 || (!com->active_out 914 && !(com->prev_modem_status & MSR_DCD) 915 && !(com->it_in.c_cflag & CLOCAL)) 916 || !(tp->t_state & TS_ISOPEN)) { 917 (void)commctl(com, TIOCM_DTR, DMBIC); 918 919 /* Disable receiver (leave transmitter enabled). */ 920 com->channel_control = CD1400_CCR_CMDCHANCTL 921 | CD1400_CCR_XMTEN 922 | CD1400_CCR_RCVDIS; 923 cd1400_channel_cmd(com, com->channel_control); 924 925 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 926 timeout(siodtrwakeup, com, com->dtr_wait); 927 com->state |= CS_DTR_OFF; 928 } 929 } 930 } 931#if 0 932 if (com->hasfifo) { 933 /* 934 * Disable fifos so that they are off after controlled 935 * reboots. Some BIOSes fail to detect 16550s when the 936 * fifos are enabled. 937 */ 938 outb(iobase + com_fifo, 0); 939 } 940#endif 941 com->active_out = FALSE; 942 wakeup(&com->active_out); 943 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 944 splx(s); 945} 946 947static int 948sioread(dev, uio, flag) 949 dev_t dev; 950 struct uio *uio; 951 int flag; 952{ 953 int mynor; 954 struct tty *tp; 955 956 mynor = minor(dev); 957 if (mynor & CONTROL_MASK) 958 return (ENODEV); 959 tp = com_addr(MINOR_TO_UNIT(mynor))->tp; 960 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 961} 962 963static int 964siowrite(dev, uio, flag) 965 dev_t dev; 966 struct uio *uio; 967 int flag; 968{ 969 int mynor; 970 struct tty *tp; 971 int unit; 972 973 mynor = minor(dev); 974 if (mynor & CONTROL_MASK) 975 return (ENODEV); 976 977 unit = MINOR_TO_UNIT(mynor); 978 tp = com_addr(unit)->tp; 979 /* 980 * (XXX) We disallow virtual consoles if the physical console is 981 * a serial port. This is in case there is a display attached that 982 * is not the console. In that situation we don't need/want the X 983 * server taking over the console. 984 */ 985 if (constty != NULL && unit == comconsole) 986 constty = NULL; 987#ifdef Smarts 988 /* XXX duplicate ttwrite(), but without so much output processing on 989 * CR & LF chars. Hardly worth the effort, given that high-throughput 990 * sessions are raw anyhow. 991 */ 992#else 993 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 994#endif 995} 996 997static void 998siodtrwakeup(chan) 999 void *chan; 1000{ 1001 struct com_s *com; 1002 1003 com = (struct com_s *)chan; 1004 com->state &= ~CS_DTR_OFF; 1005 wakeup(&com->dtr_wait); 1006} 1007 1008static void 1009sioinput(com) 1010 struct com_s *com; 1011{ 1012 u_char *buf; 1013 int incc; 1014 u_char line_status; 1015 int recv_data; 1016 struct tty *tp; 1017 1018 buf = com->ibuf; 1019 tp = com->tp; 1020 if (!(tp->t_state & TS_ISOPEN)) { 1021 com_events -= (com->iptr - com->ibuf); 1022 com->iptr = com->ibuf; 1023 return; 1024 } 1025 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1026 /* 1027 * Avoid the grotesquely inefficient lineswitch routine 1028 * (ttyinput) in "raw" mode. It usually takes about 450 1029 * instructions (that's without canonical processing or echo!). 1030 * slinput is reasonably fast (usually 40 instructions plus 1031 * call overhead). 1032 */ 1033 do { 1034 enable_intr(); 1035 incc = com->iptr - buf; 1036 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1037 && (com->state & CS_RTS_IFLOW 1038 || tp->t_iflag & IXOFF) 1039 && !(tp->t_state & TS_TBLOCK)) 1040 ttyblock(tp); 1041 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1042 += b_to_q((char *)buf, incc, &tp->t_rawq); 1043 buf += incc; 1044 tk_nin += incc; 1045 tk_rawcc += incc; 1046 tp->t_rawcc += incc; 1047 ttwakeup(tp); 1048 if (tp->t_state & TS_TTSTOP 1049 && (tp->t_iflag & IXANY 1050 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1051 tp->t_state &= ~TS_TTSTOP; 1052 tp->t_lflag &= ~FLUSHO; 1053 comstart(tp); 1054 } 1055 disable_intr(); 1056 } while (buf < com->iptr); 1057 } else { 1058 do { 1059 enable_intr(); 1060 line_status = buf[com->ierroff]; 1061 recv_data = *buf++; 1062 if (line_status 1063 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1064 if (line_status & LSR_BI) 1065 recv_data |= TTY_BI; 1066 if (line_status & LSR_FE) 1067 recv_data |= TTY_FE; 1068 if (line_status & LSR_OE) 1069 recv_data |= TTY_OE; 1070 if (line_status & LSR_PE) 1071 recv_data |= TTY_PE; 1072 } 1073 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1074 disable_intr(); 1075 } while (buf < com->iptr); 1076 } 1077 com_events -= (com->iptr - com->ibuf); 1078 com->iptr = com->ibuf; 1079 1080 /* 1081 * There is now room for another low-level buffer full of input, 1082 * so enable RTS if it is now disabled and there is room in the 1083 * high-level buffer. 1084 */ 1085 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1086 !(tp->t_state & TS_TBLOCK)) 1087#if 0 1088 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1089#else 1090 cd_setreg(com, com->mcr_rts_reg, 1091 com->mcr_image |= com->mcr_rts); 1092#endif 1093} 1094 1095void 1096siointr(unit) 1097 int unit; 1098{ 1099 int baseu; 1100 int cy_align; 1101 cy_addr cy_iobase; 1102 int cyu; 1103 cy_addr iobase; 1104 u_char status; 1105 1106 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1107 1108 baseu = unit * CY_MAX_PORTS; 1109 cy_align = com_addr(baseu)->cy_align; 1110 cy_iobase = com_addr(baseu)->cy_iobase; 1111 1112 /* check each CD1400 in turn */ 1113 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1114 iobase = (cy_addr) (cy_iobase 1115 + (cy_chip_offset[cyu] << cy_align)); 1116 /* poll to see if it has any work */ 1117 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1118 if (status == 0) 1119 continue; 1120#ifdef CyDebug 1121 ++cy_svrr_probes; 1122#endif 1123 /* service requests as appropriate, giving priority to RX */ 1124 if (status & CD1400_SVRR_RXRDY) { 1125 struct com_s *com; 1126 u_int count; 1127 u_char *ioptr; 1128 u_char line_status; 1129 u_char recv_data; 1130 u_char serv_type; 1131#ifdef PollMode 1132 u_char save_rir; 1133#endif 1134 1135#ifdef PollMode 1136 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1137 1138 /* enter rx service */ 1139 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1140 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1141 = save_rir & CD1400_CAR_CHAN; 1142 1143 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1144 com = com_addr(baseu 1145 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1146 & CD1400_xIVR_CHAN)); 1147#else 1148 /* ack receive service */ 1149 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1150 1151 com = com_addr(baseu + 1152 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1153 & CD1400_xIVR_CHAN)); 1154#endif 1155 1156 if (serv_type & CD1400_RIVR_EXCEPTION) { 1157 ++com->recv_exception; 1158 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1159 /* break/unnattached error bits or real input? */ 1160 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1161#ifndef SOFT_HOTCHAR 1162 if (line_status & CD1400_RDSR_SPECIAL 1163 && com->hotchar != 0) 1164 setsofttty(); 1165#endif 1166#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1167 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1168 /* 1169 Don't store PE if IGNPAR and BI if IGNBRK, 1170 this hack allows "raw" tty optimization 1171 works even if IGN* is set. 1172 */ 1173 if ( com->tp == NULL 1174 || !(com->tp->t_state & TS_ISOPEN) 1175 || ((line_status & (LSR_PE|LSR_FE)) 1176 && (com->tp->t_iflag & IGNPAR)) 1177 || ((line_status & LSR_BI) 1178 && (com->tp->t_iflag & IGNBRK))) 1179 goto cont; 1180 if ( (line_status & (LSR_PE|LSR_FE)) 1181 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1182 && ((line_status & LSR_FE) 1183 || ((line_status & LSR_PE) 1184 && (com->tp->t_iflag & INPCK)))) 1185 recv_data = 0; 1186 } 1187#endif /* 1 */ 1188 ++com->bytes_in; 1189#ifdef SOFT_HOTCHAR 1190 if (com->hotchar != 0 && recv_data == com->hotchar) 1191 setsofttty(); 1192#endif 1193 ioptr = com->iptr; 1194 if (ioptr >= com->ibufend) 1195 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1196 else { 1197 if (com->do_timestamp) 1198 microtime(&com->timestamp); 1199 ++com_events; 1200 ioptr[0] = recv_data; 1201 ioptr[com->ierroff] = line_status; 1202 com->iptr = ++ioptr; 1203 if (ioptr == com->ihighwater 1204 && com->state & CS_RTS_IFLOW) 1205#if 0 1206 outb(com->modem_ctl_port, 1207 com->mcr_image &= ~MCR_RTS); 1208#else 1209 cd_outb(iobase, com->mcr_rts_reg, 1210 cy_align, 1211 com->mcr_image &= 1212 ~com->mcr_rts); 1213#endif 1214 if (line_status & LSR_OE) 1215 CE_RECORD(com, CE_OVERRUN); 1216 } 1217 goto cont; 1218 } else { 1219 int ifree; 1220 1221 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1222 if (!count) 1223 goto cont; 1224 com->bytes_in += count; 1225 ioptr = com->iptr; 1226 ifree = com->ibufend - ioptr; 1227 if (count > ifree) { 1228 count -= ifree; 1229 com_events += ifree; 1230 if (ifree != 0) { 1231 if (com->do_timestamp) 1232 microtime(&com->timestamp); 1233 do { 1234 recv_data = cd_inb(iobase, 1235 CD1400_RDSR, 1236 cy_align); 1237#ifdef SOFT_HOTCHAR 1238 if (com->hotchar != 0 1239 && recv_data 1240 == com->hotchar) 1241 setsofttty(); 1242#endif 1243 ioptr[0] = recv_data; 1244 ioptr[com->ierroff] = 0; 1245 ++ioptr; 1246 } while (--ifree != 0); 1247 } 1248 com->delta_error_counts 1249 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1250 do { 1251 recv_data = cd_inb(iobase, CD1400_RDSR, 1252 cy_align); 1253#ifdef SOFT_HOTCHAR 1254 if (com->hotchar != 0 1255 && recv_data == com->hotchar) 1256 setsofttty(); 1257#endif 1258 } while (--count != 0); 1259 } else { 1260 if (com->do_timestamp) 1261 microtime(&com->timestamp); 1262 if (ioptr <= com->ihighwater 1263 && ioptr + count > com->ihighwater 1264 && com->state & CS_RTS_IFLOW) 1265#if 0 1266 outb(com->modem_ctl_port, 1267 com->mcr_image &= ~MCR_RTS); 1268#else 1269 cd_outb(iobase, com->mcr_rts_reg, 1270 cy_align, 1271 com->mcr_image 1272 &= ~com->mcr_rts); 1273#endif 1274 com_events += count; 1275 do { 1276 recv_data = cd_inb(iobase, CD1400_RDSR, 1277 cy_align); 1278#ifdef SOFT_HOTCHAR 1279 if (com->hotchar != 0 1280 && recv_data == com->hotchar) 1281 setsofttty(); 1282#endif 1283 ioptr[0] = recv_data; 1284 ioptr[com->ierroff] = 0; 1285 ++ioptr; 1286 } while (--count != 0); 1287 } 1288 com->iptr = ioptr; 1289 } 1290cont: 1291 1292 /* terminate service context */ 1293#ifdef PollMode 1294 cd_outb(iobase, CD1400_RIR, cy_align, 1295 save_rir 1296 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1297#else 1298 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1299#endif 1300 } 1301 if (status & CD1400_SVRR_MDMCH) { 1302 struct com_s *com; 1303 u_char modem_status; 1304#ifdef PollMode 1305 u_char save_mir; 1306#else 1307 u_char vector; 1308#endif 1309 1310#ifdef PollMode 1311 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1312 1313 /* enter modem service */ 1314 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1315 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1316 = save_mir & CD1400_CAR_CHAN; 1317 1318 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1319 + (save_mir & CD1400_MIR_CHAN)); 1320#else 1321 /* ack modem service */ 1322 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1323 1324 com = com_addr(baseu 1325 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1326 & CD1400_xIVR_CHAN)); 1327#endif 1328 ++com->mdm; 1329 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1330 if (modem_status != com->last_modem_status) { 1331 if (com->do_dcd_timestamp 1332 && !(com->last_modem_status & MSR_DCD) 1333 && modem_status & MSR_DCD) 1334 microtime(&com->dcd_timestamp); 1335 1336 /* 1337 * Schedule high level to handle DCD changes. Note 1338 * that we don't use the delta bits anywhere. Some 1339 * UARTs mess them up, and it's easy to remember the 1340 * previous bits and calculate the delta. 1341 */ 1342 com->last_modem_status = modem_status; 1343 if (!(com->state & CS_CHECKMSR)) { 1344 com_events += LOTS_OF_EVENTS; 1345 com->state |= CS_CHECKMSR; 1346 setsofttty(); 1347 } 1348 1349#ifdef SOFT_CTS_OFLOW 1350 /* handle CTS change immediately for crisp flow ctl */ 1351 if (com->state & CS_CTS_OFLOW) { 1352 if (modem_status & MSR_CTS) { 1353 com->state |= CS_ODEVREADY; 1354 if (com->state >= (CS_BUSY | CS_TTGO 1355 | CS_ODEVREADY) 1356 && !(com->intr_enable 1357 & CD1400_SRER_TXRDY)) 1358 cd_outb(iobase, CD1400_SRER, 1359 cy_align, 1360 com->intr_enable 1361 = com->intr_enable 1362 & ~CD1400_SRER_TXMPTY 1363 | CD1400_SRER_TXRDY); 1364 } else { 1365 com->state &= ~CS_ODEVREADY; 1366 if (com->intr_enable 1367 & CD1400_SRER_TXRDY) 1368 cd_outb(iobase, CD1400_SRER, 1369 cy_align, 1370 com->intr_enable 1371 = com->intr_enable 1372 & ~CD1400_SRER_TXRDY 1373 | CD1400_SRER_TXMPTY); 1374 } 1375 } 1376#endif 1377 } 1378 1379 /* terminate service context */ 1380#ifdef PollMode 1381 cd_outb(iobase, CD1400_MIR, cy_align, 1382 save_mir 1383 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1384#else 1385 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1386#endif 1387 } 1388 if (status & CD1400_SVRR_TXRDY) { 1389 struct com_s *com; 1390#ifdef PollMode 1391 u_char save_tir; 1392#else 1393 u_char vector; 1394#endif 1395 1396#ifdef PollMode 1397 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1398 1399 /* enter tx service */ 1400 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1401 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1402 = save_tir & CD1400_CAR_CHAN; 1403 1404 com = com_addr(baseu 1405 + cyu * CD1400_NO_OF_CHANNELS 1406 + (save_tir & CD1400_TIR_CHAN)); 1407#else 1408 /* ack transmit service */ 1409 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1410 1411 com = com_addr(baseu 1412 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1413 & CD1400_xIVR_CHAN)); 1414#endif 1415 1416 if (com->etc != ETC_NONE) { 1417 if (com->intr_enable & CD1400_SRER_TXRDY) { 1418 /* 1419 * Here due to sloppy SRER_TXRDY 1420 * enabling. Ignore. Come back when 1421 * tx is empty. 1422 */ 1423 cd_outb(iobase, CD1400_SRER, cy_align, 1424 com->intr_enable 1425 = (com->intr_enable 1426 & ~CD1400_SRER_TXRDY) 1427 | CD1400_SRER_TXMPTY); 1428 goto terminate_tx_service; 1429 } 1430 switch (com->etc) { 1431 case CD1400_ETC_SENDBREAK: 1432 case CD1400_ETC_STOPBREAK: 1433 /* 1434 * Start the command. Come back on 1435 * next tx empty interrupt, hopefully 1436 * after command has been executed. 1437 */ 1438 cd_outb(iobase, CD1400_COR2, cy_align, 1439 com->cor[1] |= CD1400_COR2_ETC); 1440 cd_outb(iobase, CD1400_TDR, cy_align, 1441 CD1400_ETC_CMD); 1442 cd_outb(iobase, CD1400_TDR, cy_align, 1443 com->etc); 1444 if (com->etc == CD1400_ETC_SENDBREAK) 1445 com->etc = ETC_BREAK_STARTING; 1446 else 1447 com->etc = ETC_BREAK_ENDING; 1448 goto terminate_tx_service; 1449 case ETC_BREAK_STARTING: 1450 /* 1451 * BREAK is now on. Continue with 1452 * SRER_TXMPTY processing, hopefully 1453 * don't come back. 1454 */ 1455 com->etc = ETC_BREAK_STARTED; 1456 break; 1457 case ETC_BREAK_STARTED: 1458 /* 1459 * Came back due to sloppy SRER_TXMPTY 1460 * enabling. Hope again. 1461 */ 1462 break; 1463 case ETC_BREAK_ENDING: 1464 /* 1465 * BREAK is now off. Continue with 1466 * SRER_TXMPTY processing and don't 1467 * come back. The SWI handler will 1468 * restart tx interrupts if necessary. 1469 */ 1470 cd_outb(iobase, CD1400_COR2, cy_align, 1471 com->cor[1] 1472 &= ~CD1400_COR2_ETC); 1473 com->etc = ETC_BREAK_ENDED; 1474 if (!(com->state & CS_ODONE)) { 1475 com_events += LOTS_OF_EVENTS; 1476 com->state |= CS_ODONE; 1477 setsofttty(); 1478 } 1479 break; 1480 case ETC_BREAK_ENDED: 1481 /* 1482 * Shouldn't get here. Hope again. 1483 */ 1484 break; 1485 } 1486 } 1487 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1488 if (!(com->extra_state & CSE_ODONE)) { 1489 com_events += LOTS_OF_EVENTS; 1490 com->extra_state |= CSE_ODONE; 1491 setsofttty(); 1492 } 1493 cd_outb(iobase, CD1400_SRER, cy_align, 1494 com->intr_enable 1495 &= ~CD1400_SRER_TXMPTY); 1496 goto terminate_tx_service; 1497 } 1498 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1499 u_char *ioptr; 1500 u_int ocount; 1501 1502 ioptr = com->obufq.l_head; 1503 ocount = com->obufq.l_tail - ioptr; 1504 if (ocount > CD1400_TX_FIFO_SIZE) 1505 ocount = CD1400_TX_FIFO_SIZE; 1506 com->bytes_out += ocount; 1507 do 1508 cd_outb(iobase, CD1400_TDR, cy_align, 1509 *ioptr++); 1510 while (--ocount != 0); 1511 com->obufq.l_head = ioptr; 1512 if (ioptr >= com->obufq.l_tail) { 1513 struct lbq *qp; 1514 1515 qp = com->obufq.l_next; 1516 qp->l_queued = FALSE; 1517 qp = qp->l_next; 1518 if (qp != NULL) { 1519 com->obufq.l_head = qp->l_head; 1520 com->obufq.l_tail = qp->l_tail; 1521 com->obufq.l_next = qp; 1522 } else { 1523 /* output just completed */ 1524 com->state &= ~CS_BUSY; 1525 1526 /* 1527 * The setting of CSE_ODONE may be 1528 * stale here. We currently only 1529 * use it when CS_BUSY is set, and 1530 * fixing it when we clear CS_BUSY 1531 * is easiest. 1532 */ 1533 if (com->extra_state & CSE_ODONE) { 1534 com_events -= LOTS_OF_EVENTS; 1535 com->extra_state &= ~CSE_ODONE; 1536 } 1537 1538 cd_outb(iobase, CD1400_SRER, cy_align, 1539 com->intr_enable 1540 = (com->intr_enable 1541 & ~CD1400_SRER_TXRDY) 1542 | CD1400_SRER_TXMPTY); 1543 } 1544 if (!(com->state & CS_ODONE)) { 1545 com_events += LOTS_OF_EVENTS; 1546 com->state |= CS_ODONE; 1547 1548 /* handle at high level ASAP */ 1549 setsofttty(); 1550 } 1551 } 1552 } 1553 1554 /* terminate service context */ 1555terminate_tx_service: 1556#ifdef PollMode 1557 cd_outb(iobase, CD1400_TIR, cy_align, 1558 save_tir 1559 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1560#else 1561 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1562#endif 1563 } 1564 } 1565 1566 /* ensure an edge for the next interrupt */ 1567 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1568 1569 schedsofttty(); 1570 1571 COM_UNLOCK(); 1572} 1573 1574#if 0 1575static void 1576siointr1(com) 1577 struct com_s *com; 1578{ 1579} 1580#endif 1581 1582static int 1583sioioctl(dev, cmd, data, flag, p) 1584 dev_t dev; 1585 u_long cmd; 1586 caddr_t data; 1587 int flag; 1588 struct proc *p; 1589{ 1590 struct com_s *com; 1591 int error; 1592 int mynor; 1593 int s; 1594 struct tty *tp; 1595#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1596 int oldcmd; 1597 struct termios term; 1598#endif 1599 1600 mynor = minor(dev); 1601 com = com_addr(MINOR_TO_UNIT(mynor)); 1602 if (mynor & CONTROL_MASK) { 1603 struct termios *ct; 1604 1605 switch (mynor & CONTROL_MASK) { 1606 case CONTROL_INIT_STATE: 1607 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1608 break; 1609 case CONTROL_LOCK_STATE: 1610 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1611 break; 1612 default: 1613 return (ENODEV); /* /dev/nodev */ 1614 } 1615 switch (cmd) { 1616 case TIOCSETA: 1617 error = suser(p); 1618 if (error != 0) 1619 return (error); 1620 *ct = *(struct termios *)data; 1621 return (0); 1622 case TIOCGETA: 1623 *(struct termios *)data = *ct; 1624 return (0); 1625 case TIOCGETD: 1626 *(int *)data = TTYDISC; 1627 return (0); 1628 case TIOCGWINSZ: 1629 bzero(data, sizeof(struct winsize)); 1630 return (0); 1631 default: 1632 return (ENOTTY); 1633 } 1634 } 1635 tp = com->tp; 1636#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1637 term = tp->t_termios; 1638 oldcmd = cmd; 1639 error = ttsetcompat(tp, &cmd, data, &term); 1640 if (error != 0) 1641 return (error); 1642 if (cmd != oldcmd) 1643 data = (caddr_t)&term; 1644#endif 1645 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1646 int cc; 1647 struct termios *dt = (struct termios *)data; 1648 struct termios *lt = mynor & CALLOUT_MASK 1649 ? &com->lt_out : &com->lt_in; 1650 1651 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1652 | (dt->c_iflag & ~lt->c_iflag); 1653 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1654 | (dt->c_oflag & ~lt->c_oflag); 1655 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1656 | (dt->c_cflag & ~lt->c_cflag); 1657 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1658 | (dt->c_lflag & ~lt->c_lflag); 1659 for (cc = 0; cc < NCCS; ++cc) 1660 if (lt->c_cc[cc] != 0) 1661 dt->c_cc[cc] = tp->t_cc[cc]; 1662 if (lt->c_ispeed != 0) 1663 dt->c_ispeed = tp->t_ispeed; 1664 if (lt->c_ospeed != 0) 1665 dt->c_ospeed = tp->t_ospeed; 1666 } 1667 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1668 if (error != ENOIOCTL) 1669 return (error); 1670 s = spltty(); 1671 error = ttioctl(tp, cmd, data, flag); 1672 disc_optim(tp, &tp->t_termios, com); 1673 if (error != ENOIOCTL) { 1674 splx(s); 1675 return (error); 1676 } 1677 switch (cmd) { 1678 case TIOCSBRK: 1679#if 0 1680 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1681#else 1682 cd_etc(com, CD1400_ETC_SENDBREAK); 1683#endif 1684 break; 1685 case TIOCCBRK: 1686#if 0 1687 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1688#else 1689 cd_etc(com, CD1400_ETC_STOPBREAK); 1690#endif 1691 break; 1692 case TIOCSDTR: 1693 (void)commctl(com, TIOCM_DTR, DMBIS); 1694 break; 1695 case TIOCCDTR: 1696 (void)commctl(com, TIOCM_DTR, DMBIC); 1697 break; 1698 /* 1699 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1700 * changes get undone on the next call to comparam(). 1701 */ 1702 case TIOCMSET: 1703 (void)commctl(com, *(int *)data, DMSET); 1704 break; 1705 case TIOCMBIS: 1706 (void)commctl(com, *(int *)data, DMBIS); 1707 break; 1708 case TIOCMBIC: 1709 (void)commctl(com, *(int *)data, DMBIC); 1710 break; 1711 case TIOCMGET: 1712 *(int *)data = commctl(com, 0, DMGET); 1713 break; 1714 case TIOCMSDTRWAIT: 1715 /* must be root since the wait applies to following logins */ 1716 error = suser(p); 1717 if (error != 0) { 1718 splx(s); 1719 return (error); 1720 } 1721 com->dtr_wait = *(int *)data * hz / 100; 1722 break; 1723 case TIOCMGDTRWAIT: 1724 *(int *)data = com->dtr_wait * 100 / hz; 1725 break; 1726 case TIOCTIMESTAMP: 1727 com->do_timestamp = TRUE; 1728 *(struct timeval *)data = com->timestamp; 1729 break; 1730 case TIOCDCDTIMESTAMP: 1731 com->do_dcd_timestamp = TRUE; 1732 *(struct timeval *)data = com->dcd_timestamp; 1733 break; 1734 default: 1735 splx(s); 1736 return (ENOTTY); 1737 } 1738 splx(s); 1739 return (0); 1740} 1741 1742static void 1743siopoll() 1744{ 1745 int unit; 1746 1747#ifdef CyDebug 1748 ++cy_timeouts; 1749#endif 1750 if (com_events == 0) 1751 return; 1752repeat: 1753 for (unit = 0; unit < NSIO; ++unit) { 1754 struct com_s *com; 1755 int incc; 1756 struct tty *tp; 1757 1758 com = com_addr(unit); 1759 if (com == NULL) 1760 continue; 1761 tp = com->tp; 1762 if (tp == NULL) { 1763 /* 1764 * XXX forget any events related to closed devices 1765 * (actually never opened devices) so that we don't 1766 * loop. 1767 */ 1768 disable_intr(); 1769 incc = com->iptr - com->ibuf; 1770 com->iptr = com->ibuf; 1771 if (com->state & CS_CHECKMSR) { 1772 incc += LOTS_OF_EVENTS; 1773 com->state &= ~CS_CHECKMSR; 1774 } 1775 com_events -= incc; 1776 enable_intr(); 1777 if (incc != 0) 1778 log(LOG_DEBUG, 1779 "sio%d: %d events for device with no tp\n", 1780 unit, incc); 1781 continue; 1782 } 1783 if (com->iptr != com->ibuf) { 1784 disable_intr(); 1785 sioinput(com); 1786 enable_intr(); 1787 } 1788 if (com->state & CS_CHECKMSR) { 1789 u_char delta_modem_status; 1790 1791 disable_intr(); 1792 delta_modem_status = com->last_modem_status 1793 ^ com->prev_modem_status; 1794 com->prev_modem_status = com->last_modem_status; 1795 com_events -= LOTS_OF_EVENTS; 1796 com->state &= ~CS_CHECKMSR; 1797 enable_intr(); 1798 if (delta_modem_status & MSR_DCD) 1799 (*linesw[tp->t_line].l_modem) 1800 (tp, com->prev_modem_status & MSR_DCD); 1801 } 1802 if (com->extra_state & CSE_ODONE) { 1803 disable_intr(); 1804 com_events -= LOTS_OF_EVENTS; 1805 com->extra_state &= ~CSE_ODONE; 1806 enable_intr(); 1807 if (!(com->state & CS_BUSY)) { 1808 tp->t_state &= ~TS_BUSY; 1809 ttwwakeup(com->tp); 1810 } 1811 if (com->etc != ETC_NONE) { 1812 if (com->etc == ETC_BREAK_ENDED) 1813 com->etc = ETC_NONE; 1814 wakeup(&com->etc); 1815 } 1816 } 1817 if (com->state & CS_ODONE) { 1818 disable_intr(); 1819 com_events -= LOTS_OF_EVENTS; 1820 com->state &= ~CS_ODONE; 1821 enable_intr(); 1822 (*linesw[tp->t_line].l_start)(tp); 1823 } 1824 if (com_events == 0) 1825 break; 1826 } 1827 if (com_events >= LOTS_OF_EVENTS) 1828 goto repeat; 1829} 1830 1831static int 1832comparam(tp, t) 1833 struct tty *tp; 1834 struct termios *t; 1835{ 1836 int bits; 1837 int cflag; 1838 struct com_s *com; 1839 u_char cor_change; 1840 u_long cy_clock; 1841 int idivisor; 1842 int iflag; 1843 int iprescaler; 1844 int itimeout; 1845 int odivisor; 1846 int oprescaler; 1847 u_char opt; 1848 int s; 1849 int unit; 1850 1851 /* do historical conversions */ 1852 if (t->c_ispeed == 0) 1853 t->c_ispeed = t->c_ospeed; 1854 1855 unit = DEV_TO_UNIT(tp->t_dev); 1856 com = com_addr(unit); 1857 1858 /* check requested parameters */ 1859 cy_clock = CY_CLOCK(com->gfrcr_image); 1860 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1861 if (idivisor < 0) 1862 return (EINVAL); 1863 odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); 1864 if (odivisor < 0) 1865 return (EINVAL); 1866 1867 /* parameters are OK, convert them to the com struct and the device */ 1868 s = spltty(); 1869 if (odivisor == 0) 1870 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1871 else 1872 (void)commctl(com, TIOCM_DTR, DMBIS); 1873 1874 /* 1875 * This returns with interrupts disabled so that we can complete 1876 * the speed change atomically. 1877 */ 1878 (void) siosetwater(com, t->c_ispeed); 1879 1880 /* XXX we don't actually change the speed atomically. */ 1881 enable_intr(); 1882 1883 if (idivisor != 0) { 1884 cd_setreg(com, CD1400_RBPR, idivisor); 1885 cd_setreg(com, CD1400_RCOR, iprescaler); 1886 } 1887 if (odivisor != 0) { 1888 cd_setreg(com, CD1400_TBPR, odivisor); 1889 cd_setreg(com, CD1400_TCOR, oprescaler); 1890 } 1891 1892 /* 1893 * channel control 1894 * receiver enable 1895 * transmitter enable (always set) 1896 */ 1897 cflag = t->c_cflag; 1898 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1899 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1900 if (opt != com->channel_control) { 1901 com->channel_control = opt; 1902 cd1400_channel_cmd(com, opt); 1903 } 1904 1905#ifdef Smarts 1906 /* set special chars */ 1907 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1908 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1909 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1910 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1911 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1912 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1913 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1914 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1915 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1916#endif 1917 1918 /* 1919 * set channel option register 1 - 1920 * parity mode 1921 * stop bits 1922 * char length 1923 */ 1924 opt = 0; 1925 /* parity */ 1926 if (cflag & PARENB) { 1927 if (cflag & PARODD) 1928 opt |= CD1400_COR1_PARODD; 1929 opt |= CD1400_COR1_PARNORMAL; 1930 } 1931 iflag = t->c_iflag; 1932 if (!(iflag & INPCK)) 1933 opt |= CD1400_COR1_NOINPCK; 1934 bits = 1 + 1; 1935 /* stop bits */ 1936 if (cflag & CSTOPB) { 1937 ++bits; 1938 opt |= CD1400_COR1_STOP2; 1939 } 1940 /* char length */ 1941 switch (cflag & CSIZE) { 1942 case CS5: 1943 bits += 5; 1944 opt |= CD1400_COR1_CS5; 1945 break; 1946 case CS6: 1947 bits += 6; 1948 opt |= CD1400_COR1_CS6; 1949 break; 1950 case CS7: 1951 bits += 7; 1952 opt |= CD1400_COR1_CS7; 1953 break; 1954 default: 1955 bits += 8; 1956 opt |= CD1400_COR1_CS8; 1957 break; 1958 } 1959 cor_change = 0; 1960 if (opt != com->cor[0]) { 1961 cor_change |= CD1400_CCR_COR1; 1962 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1963 } 1964 1965 /* 1966 * Set receive time-out period, normally to max(one char time, 5 ms). 1967 */ 1968 if (t->c_ispeed == 0) 1969 itimeout = cd_getreg(com, CD1400_RTPR); 1970 else { 1971 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1972#ifdef SOFT_HOTCHAR 1973#define MIN_RTP 1 1974#else 1975#define MIN_RTP 5 1976#endif 1977 if (itimeout < MIN_RTP) 1978 itimeout = MIN_RTP; 1979 } 1980 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1981 && t->c_cc[VTIME] * 10 > itimeout) 1982 itimeout = t->c_cc[VTIME] * 10; 1983 if (itimeout > 255) 1984 itimeout = 255; 1985 cd_setreg(com, CD1400_RTPR, itimeout); 1986 1987 /* 1988 * set channel option register 2 - 1989 * flow control 1990 */ 1991 opt = 0; 1992#ifdef Smarts 1993 if (iflag & IXANY) 1994 opt |= CD1400_COR2_IXANY; 1995 if (iflag & IXOFF) 1996 opt |= CD1400_COR2_IXOFF; 1997#endif 1998#ifndef SOFT_CTS_OFLOW 1999 if (cflag & CCTS_OFLOW) 2000 opt |= CD1400_COR2_CCTS_OFLOW; 2001#endif 2002 disable_intr(); 2003 if (opt != com->cor[1]) { 2004 cor_change |= CD1400_CCR_COR2; 2005 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2006 } 2007 enable_intr(); 2008 2009 /* 2010 * set channel option register 3 - 2011 * receiver FIFO interrupt threshold 2012 * flow control 2013 */ 2014 opt = RxFifoThreshold; 2015#ifdef Smarts 2016 if (t->c_lflag & ICANON) 2017 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2018 if (iflag & IXOFF) 2019 /* detect and transparently handle START and STOP chars */ 2020 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2021#endif 2022 if (opt != com->cor[2]) { 2023 cor_change |= CD1400_CCR_COR3; 2024 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2025 } 2026 2027 /* notify the CD1400 if COR1-3 have changed */ 2028 if (cor_change) 2029 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2030 2031 /* 2032 * set channel option register 4 - 2033 * CR/NL processing 2034 * break processing 2035 * received exception processing 2036 */ 2037 opt = 0; 2038 if (iflag & IGNCR) 2039 opt |= CD1400_COR4_IGNCR; 2040#ifdef Smarts 2041 /* 2042 * we need a new ttyinput() for this, as we don't want to 2043 * have ICRNL && INLCR being done in both layers, or to have 2044 * synchronisation problems 2045 */ 2046 if (iflag & ICRNL) 2047 opt |= CD1400_COR4_ICRNL; 2048 if (iflag & INLCR) 2049 opt |= CD1400_COR4_INLCR; 2050#endif 2051 if (iflag & IGNBRK) 2052 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2053 /* 2054 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2055 * so only tell the hardware about -brkint if -parmrk. 2056 */ 2057 if (!(iflag & (BRKINT | PARMRK))) 2058 opt |= CD1400_COR4_NOBRKINT; 2059#if 0 2060 /* XXX using this "intelligence" breaks reporting of overruns. */ 2061 if (iflag & IGNPAR) 2062 opt |= CD1400_COR4_PFO_DISCARD; 2063 else { 2064 if (iflag & PARMRK) 2065 opt |= CD1400_COR4_PFO_ESC; 2066 else 2067 opt |= CD1400_COR4_PFO_NUL; 2068 } 2069#else 2070 opt |= CD1400_COR4_PFO_EXCEPTION; 2071#endif 2072 cd_setreg(com, CD1400_COR4, opt); 2073 2074 /* 2075 * set channel option register 5 - 2076 */ 2077 opt = 0; 2078 if (iflag & ISTRIP) 2079 opt |= CD1400_COR5_ISTRIP; 2080 if (t->c_iflag & IEXTEN) 2081 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2082 opt |= CD1400_COR5_LNEXT; 2083#ifdef Smarts 2084 if (t->c_oflag & ONLCR) 2085 opt |= CD1400_COR5_ONLCR; 2086 if (t->c_oflag & OCRNL) 2087 opt |= CD1400_COR5_OCRNL; 2088#endif 2089 cd_setreg(com, CD1400_COR5, opt); 2090 2091 /* 2092 * We always generate modem status change interrupts for CD changes. 2093 * Among other things, this is necessary to track TS_CARR_ON for 2094 * pstat to print even when the driver doesn't care. CD changes 2095 * should be rare so interrupts for them are not worth extra code to 2096 * avoid. We avoid interrupts for other modem status changes (except 2097 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2098 * simplest and best. 2099 */ 2100 2101 /* 2102 * set modem change option register 1 2103 * generate modem interrupts on which 1 -> 0 input transitions 2104 * also controls auto-DTR output flow-control, which we don't use 2105 */ 2106 opt = CD1400_MCOR1_CDzd; 2107#ifdef SOFT_CTS_OFLOW 2108 if (cflag & CCTS_OFLOW) 2109 opt |= CD1400_MCOR1_CTSzd; 2110#endif 2111 cd_setreg(com, CD1400_MCOR1, opt); 2112 2113 /* 2114 * set modem change option register 2 2115 * generate modem interrupts on specific 0 -> 1 input transitions 2116 */ 2117 opt = CD1400_MCOR2_CDod; 2118#ifdef SOFT_CTS_OFLOW 2119 if (cflag & CCTS_OFLOW) 2120 opt |= CD1400_MCOR2_CTSod; 2121#endif 2122 cd_setreg(com, CD1400_MCOR2, opt); 2123 2124 /* 2125 * XXX should have done this long ago, but there is too much state 2126 * to change all atomically. 2127 */ 2128 disable_intr(); 2129 2130 com->state &= ~CS_TTGO; 2131 if (!(tp->t_state & TS_TTSTOP)) 2132 com->state |= CS_TTGO; 2133 if (cflag & CRTS_IFLOW) { 2134 com->state |= CS_RTS_IFLOW; 2135 /* 2136 * If CS_RTS_IFLOW just changed from off to on, the change 2137 * needs to be propagated to MCR_RTS. This isn't urgent, 2138 * so do it later by calling comstart() instead of repeating 2139 * a lot of code from comstart() here. 2140 */ 2141 } else if (com->state & CS_RTS_IFLOW) { 2142 com->state &= ~CS_RTS_IFLOW; 2143 /* 2144 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2145 * on here, since comstart() won't do it later. 2146 */ 2147#if 0 2148 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2149#else 2150 cd_setreg(com, com->mcr_rts_reg, 2151 com->mcr_image |= com->mcr_rts); 2152#endif 2153 } 2154 2155 /* 2156 * Set up state to handle output flow control. 2157 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2158 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2159 */ 2160 com->state |= CS_ODEVREADY; 2161#ifdef SOFT_CTS_OFLOW 2162 com->state &= ~CS_CTS_OFLOW; 2163 if (cflag & CCTS_OFLOW) { 2164 com->state |= CS_CTS_OFLOW; 2165 if (!(com->last_modem_status & MSR_CTS)) 2166 com->state &= ~CS_ODEVREADY; 2167 } 2168#endif 2169 /* XXX shouldn't call functions while intrs are disabled. */ 2170 disc_optim(tp, t, com); 2171#if 0 2172 /* 2173 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2174 * unconditionally, but that defeated the careful discarding of 2175 * stale input in sioopen(). 2176 */ 2177 if (com->state >= (CS_BUSY | CS_TTGO)) 2178 siointr1(com); 2179#endif 2180 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2181 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2182 cd_setreg(com, CD1400_SRER, 2183 com->intr_enable 2184 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2185 | CD1400_SRER_TXRDY); 2186 } else { 2187 if (com->intr_enable & CD1400_SRER_TXRDY) 2188 cd_setreg(com, CD1400_SRER, 2189 com->intr_enable 2190 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2191 | CD1400_SRER_TXMPTY); 2192 } 2193 2194 enable_intr(); 2195 splx(s); 2196 comstart(tp); 2197 if (com->ibufold != NULL) { 2198 free(com->ibufold, M_DEVBUF); 2199 com->ibufold = NULL; 2200 } 2201 return (0); 2202} 2203 2204static int 2205siosetwater(com, speed) 2206 struct com_s *com; 2207 speed_t speed; 2208{ 2209 int cp4ticks; 2210 u_char *ibuf; 2211 int ibufsize; 2212 struct tty *tp; 2213 2214 /* 2215 * Make the buffer size large enough to handle a softtty interrupt 2216 * latency of about 2 ticks without loss of throughput or data 2217 * (about 3 ticks if input flow control is not used or not honoured, 2218 * but a bit less for CS5-CS7 modes). 2219 */ 2220 cp4ticks = speed / 10 / hz * 4; 2221 for (ibufsize = 128; ibufsize < cp4ticks;) 2222 ibufsize <<= 1; 2223 if (ibufsize == com->ibufsize) { 2224 disable_intr(); 2225 return (0); 2226 } 2227 2228 /* 2229 * Allocate input buffer. The extra factor of 2 in the size is 2230 * to allow for an error byte for each input byte. 2231 */ 2232 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2233 if (ibuf == NULL) { 2234 disable_intr(); 2235 return (ENOMEM); 2236 } 2237 2238 /* Initialize non-critical variables. */ 2239 com->ibufold = com->ibuf; 2240 com->ibufsize = ibufsize; 2241 tp = com->tp; 2242 if (tp != NULL) { 2243 tp->t_ififosize = 2 * ibufsize; 2244 tp->t_ispeedwat = (speed_t)-1; 2245 tp->t_ospeedwat = (speed_t)-1; 2246 } 2247 2248 /* 2249 * Read current input buffer, if any. Continue with interrupts 2250 * disabled. 2251 */ 2252 disable_intr(); 2253 if (com->iptr != com->ibuf) 2254 sioinput(com); 2255 2256 /*- 2257 * Initialize critical variables, including input buffer watermarks. 2258 * The external device is asked to stop sending when the buffer 2259 * exactly reaches high water, or when the high level requests it. 2260 * The high level is notified immediately (rather than at a later 2261 * clock tick) when this watermark is reached. 2262 * The buffer size is chosen so the watermark should almost never 2263 * be reached. 2264 * The low watermark is invisibly 0 since the buffer is always 2265 * emptied all at once. 2266 */ 2267 com->iptr = com->ibuf = ibuf; 2268 com->ibufend = ibuf + ibufsize; 2269 com->ierroff = ibufsize; 2270 com->ihighwater = ibuf + 3 * ibufsize / 4; 2271 return (0); 2272} 2273 2274static void 2275comstart(tp) 2276 struct tty *tp; 2277{ 2278 struct com_s *com; 2279 int s; 2280#ifdef CyDebug 2281 bool_t started; 2282#endif 2283 int unit; 2284 2285 unit = DEV_TO_UNIT(tp->t_dev); 2286 com = com_addr(unit); 2287 s = spltty(); 2288 2289#ifdef CyDebug 2290 ++com->start_count; 2291 started = FALSE; 2292#endif 2293 2294 disable_intr(); 2295 if (tp->t_state & TS_TTSTOP) { 2296 com->state &= ~CS_TTGO; 2297 if (com->intr_enable & CD1400_SRER_TXRDY) 2298 cd_setreg(com, CD1400_SRER, 2299 com->intr_enable 2300 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2301 | CD1400_SRER_TXMPTY); 2302 } else { 2303 com->state |= CS_TTGO; 2304 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2305 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2306 cd_setreg(com, CD1400_SRER, 2307 com->intr_enable 2308 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2309 | CD1400_SRER_TXRDY); 2310 } 2311 if (tp->t_state & TS_TBLOCK) { 2312 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2313#if 0 2314 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2315#else 2316 cd_setreg(com, com->mcr_rts_reg, 2317 com->mcr_image &= ~com->mcr_rts); 2318#endif 2319 } else { 2320 if (!(com->mcr_image & com->mcr_rts) 2321 && com->iptr < com->ihighwater 2322 && com->state & CS_RTS_IFLOW) 2323#if 0 2324 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2325#else 2326 cd_setreg(com, com->mcr_rts_reg, 2327 com->mcr_image |= com->mcr_rts); 2328#endif 2329 } 2330 enable_intr(); 2331 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2332 ttwwakeup(tp); 2333 splx(s); 2334 return; 2335 } 2336 if (tp->t_outq.c_cc != 0) { 2337 struct lbq *qp; 2338 struct lbq *next; 2339 2340 if (!com->obufs[0].l_queued) { 2341#ifdef CyDebug 2342 started = TRUE; 2343#endif 2344 com->obufs[0].l_tail 2345 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2346 sizeof com->obuf1); 2347 com->obufs[0].l_next = NULL; 2348 com->obufs[0].l_queued = TRUE; 2349 disable_intr(); 2350 if (com->state & CS_BUSY) { 2351 qp = com->obufq.l_next; 2352 while ((next = qp->l_next) != NULL) 2353 qp = next; 2354 qp->l_next = &com->obufs[0]; 2355 } else { 2356 com->obufq.l_head = com->obufs[0].l_head; 2357 com->obufq.l_tail = com->obufs[0].l_tail; 2358 com->obufq.l_next = &com->obufs[0]; 2359 com->state |= CS_BUSY; 2360 if (com->state >= (CS_BUSY | CS_TTGO 2361 | CS_ODEVREADY)) 2362 cd_setreg(com, CD1400_SRER, 2363 com->intr_enable 2364 = (com->intr_enable 2365 & ~CD1400_SRER_TXMPTY) 2366 | CD1400_SRER_TXRDY); 2367 } 2368 enable_intr(); 2369 } 2370 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2371#ifdef CyDebug 2372 started = TRUE; 2373#endif 2374 com->obufs[1].l_tail 2375 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2376 sizeof com->obuf2); 2377 com->obufs[1].l_next = NULL; 2378 com->obufs[1].l_queued = TRUE; 2379 disable_intr(); 2380 if (com->state & CS_BUSY) { 2381 qp = com->obufq.l_next; 2382 while ((next = qp->l_next) != NULL) 2383 qp = next; 2384 qp->l_next = &com->obufs[1]; 2385 } else { 2386 com->obufq.l_head = com->obufs[1].l_head; 2387 com->obufq.l_tail = com->obufs[1].l_tail; 2388 com->obufq.l_next = &com->obufs[1]; 2389 com->state |= CS_BUSY; 2390 if (com->state >= (CS_BUSY | CS_TTGO 2391 | CS_ODEVREADY)) 2392 cd_setreg(com, CD1400_SRER, 2393 com->intr_enable 2394 = (com->intr_enable 2395 & ~CD1400_SRER_TXMPTY) 2396 | CD1400_SRER_TXRDY); 2397 } 2398 enable_intr(); 2399 } 2400 tp->t_state |= TS_BUSY; 2401 } 2402#ifdef CyDebug 2403 if (started) 2404 ++com->start_real; 2405#endif 2406#if 0 2407 disable_intr(); 2408 if (com->state >= (CS_BUSY | CS_TTGO)) 2409 siointr1(com); /* fake interrupt to start output */ 2410 enable_intr(); 2411#endif 2412 ttwwakeup(tp); 2413 splx(s); 2414} 2415 2416static void
| 857 comhardclose(com); 858 ttyclose(tp); 859 siosettimeout(); 860 splx(s); 861#ifdef broken /* session holds a ref to the tty; can't deallocate */ 862 ttyfree(tp); 863 com->tp = sio_tty[unit] = NULL; 864#endif 865 return (0); 866} 867 868static void 869comhardclose(com) 870 struct com_s *com; 871{ 872 cy_addr iobase; 873 int s; 874 struct tty *tp; 875 int unit; 876 877 unit = com->unit; 878 iobase = com->iobase; 879 s = spltty(); 880#if 0 881 com->poll = FALSE; 882 com->poll_output = FALSE; 883#endif 884 com->do_timestamp = 0; 885#if 0 886 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 887#else 888 /* XXX */ 889 disable_intr(); 890 com->etc = ETC_NONE; 891 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); 892 enable_intr(); 893 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 894#endif 895 896 { 897#if 0 898 outb(iobase + com_ier, 0); 899#else 900 disable_intr(); 901 cd_setreg(com, CD1400_SRER, com->intr_enable = 0); 902 enable_intr(); 903#endif 904 tp = com->tp; 905 if ((tp->t_cflag & HUPCL) 906 /* 907 * XXX we will miss any carrier drop between here and the 908 * next open. Perhaps we should watch DCD even when the 909 * port is closed; it is not sufficient to check it at 910 * the next open because it might go up and down while 911 * we're not watching. 912 */ 913 || (!com->active_out 914 && !(com->prev_modem_status & MSR_DCD) 915 && !(com->it_in.c_cflag & CLOCAL)) 916 || !(tp->t_state & TS_ISOPEN)) { 917 (void)commctl(com, TIOCM_DTR, DMBIC); 918 919 /* Disable receiver (leave transmitter enabled). */ 920 com->channel_control = CD1400_CCR_CMDCHANCTL 921 | CD1400_CCR_XMTEN 922 | CD1400_CCR_RCVDIS; 923 cd1400_channel_cmd(com, com->channel_control); 924 925 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { 926 timeout(siodtrwakeup, com, com->dtr_wait); 927 com->state |= CS_DTR_OFF; 928 } 929 } 930 } 931#if 0 932 if (com->hasfifo) { 933 /* 934 * Disable fifos so that they are off after controlled 935 * reboots. Some BIOSes fail to detect 16550s when the 936 * fifos are enabled. 937 */ 938 outb(iobase + com_fifo, 0); 939 } 940#endif 941 com->active_out = FALSE; 942 wakeup(&com->active_out); 943 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ 944 splx(s); 945} 946 947static int 948sioread(dev, uio, flag) 949 dev_t dev; 950 struct uio *uio; 951 int flag; 952{ 953 int mynor; 954 struct tty *tp; 955 956 mynor = minor(dev); 957 if (mynor & CONTROL_MASK) 958 return (ENODEV); 959 tp = com_addr(MINOR_TO_UNIT(mynor))->tp; 960 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 961} 962 963static int 964siowrite(dev, uio, flag) 965 dev_t dev; 966 struct uio *uio; 967 int flag; 968{ 969 int mynor; 970 struct tty *tp; 971 int unit; 972 973 mynor = minor(dev); 974 if (mynor & CONTROL_MASK) 975 return (ENODEV); 976 977 unit = MINOR_TO_UNIT(mynor); 978 tp = com_addr(unit)->tp; 979 /* 980 * (XXX) We disallow virtual consoles if the physical console is 981 * a serial port. This is in case there is a display attached that 982 * is not the console. In that situation we don't need/want the X 983 * server taking over the console. 984 */ 985 if (constty != NULL && unit == comconsole) 986 constty = NULL; 987#ifdef Smarts 988 /* XXX duplicate ttwrite(), but without so much output processing on 989 * CR & LF chars. Hardly worth the effort, given that high-throughput 990 * sessions are raw anyhow. 991 */ 992#else 993 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 994#endif 995} 996 997static void 998siodtrwakeup(chan) 999 void *chan; 1000{ 1001 struct com_s *com; 1002 1003 com = (struct com_s *)chan; 1004 com->state &= ~CS_DTR_OFF; 1005 wakeup(&com->dtr_wait); 1006} 1007 1008static void 1009sioinput(com) 1010 struct com_s *com; 1011{ 1012 u_char *buf; 1013 int incc; 1014 u_char line_status; 1015 int recv_data; 1016 struct tty *tp; 1017 1018 buf = com->ibuf; 1019 tp = com->tp; 1020 if (!(tp->t_state & TS_ISOPEN)) { 1021 com_events -= (com->iptr - com->ibuf); 1022 com->iptr = com->ibuf; 1023 return; 1024 } 1025 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1026 /* 1027 * Avoid the grotesquely inefficient lineswitch routine 1028 * (ttyinput) in "raw" mode. It usually takes about 450 1029 * instructions (that's without canonical processing or echo!). 1030 * slinput is reasonably fast (usually 40 instructions plus 1031 * call overhead). 1032 */ 1033 do { 1034 enable_intr(); 1035 incc = com->iptr - buf; 1036 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat 1037 && (com->state & CS_RTS_IFLOW 1038 || tp->t_iflag & IXOFF) 1039 && !(tp->t_state & TS_TBLOCK)) 1040 ttyblock(tp); 1041 com->delta_error_counts[CE_TTY_BUF_OVERFLOW] 1042 += b_to_q((char *)buf, incc, &tp->t_rawq); 1043 buf += incc; 1044 tk_nin += incc; 1045 tk_rawcc += incc; 1046 tp->t_rawcc += incc; 1047 ttwakeup(tp); 1048 if (tp->t_state & TS_TTSTOP 1049 && (tp->t_iflag & IXANY 1050 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { 1051 tp->t_state &= ~TS_TTSTOP; 1052 tp->t_lflag &= ~FLUSHO; 1053 comstart(tp); 1054 } 1055 disable_intr(); 1056 } while (buf < com->iptr); 1057 } else { 1058 do { 1059 enable_intr(); 1060 line_status = buf[com->ierroff]; 1061 recv_data = *buf++; 1062 if (line_status 1063 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { 1064 if (line_status & LSR_BI) 1065 recv_data |= TTY_BI; 1066 if (line_status & LSR_FE) 1067 recv_data |= TTY_FE; 1068 if (line_status & LSR_OE) 1069 recv_data |= TTY_OE; 1070 if (line_status & LSR_PE) 1071 recv_data |= TTY_PE; 1072 } 1073 (*linesw[tp->t_line].l_rint)(recv_data, tp); 1074 disable_intr(); 1075 } while (buf < com->iptr); 1076 } 1077 com_events -= (com->iptr - com->ibuf); 1078 com->iptr = com->ibuf; 1079 1080 /* 1081 * There is now room for another low-level buffer full of input, 1082 * so enable RTS if it is now disabled and there is room in the 1083 * high-level buffer. 1084 */ 1085 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && 1086 !(tp->t_state & TS_TBLOCK)) 1087#if 0 1088 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 1089#else 1090 cd_setreg(com, com->mcr_rts_reg, 1091 com->mcr_image |= com->mcr_rts); 1092#endif 1093} 1094 1095void 1096siointr(unit) 1097 int unit; 1098{ 1099 int baseu; 1100 int cy_align; 1101 cy_addr cy_iobase; 1102 int cyu; 1103 cy_addr iobase; 1104 u_char status; 1105 1106 COM_LOCK(); /* XXX could this be placed down lower in the loop? */ 1107 1108 baseu = unit * CY_MAX_PORTS; 1109 cy_align = com_addr(baseu)->cy_align; 1110 cy_iobase = com_addr(baseu)->cy_iobase; 1111 1112 /* check each CD1400 in turn */ 1113 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { 1114 iobase = (cy_addr) (cy_iobase 1115 + (cy_chip_offset[cyu] << cy_align)); 1116 /* poll to see if it has any work */ 1117 status = cd_inb(iobase, CD1400_SVRR, cy_align); 1118 if (status == 0) 1119 continue; 1120#ifdef CyDebug 1121 ++cy_svrr_probes; 1122#endif 1123 /* service requests as appropriate, giving priority to RX */ 1124 if (status & CD1400_SVRR_RXRDY) { 1125 struct com_s *com; 1126 u_int count; 1127 u_char *ioptr; 1128 u_char line_status; 1129 u_char recv_data; 1130 u_char serv_type; 1131#ifdef PollMode 1132 u_char save_rir; 1133#endif 1134 1135#ifdef PollMode 1136 save_rir = cd_inb(iobase, CD1400_RIR, cy_align); 1137 1138 /* enter rx service */ 1139 cd_outb(iobase, CD1400_CAR, cy_align, save_rir); 1140 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1141 = save_rir & CD1400_CAR_CHAN; 1142 1143 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); 1144 com = com_addr(baseu 1145 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1146 & CD1400_xIVR_CHAN)); 1147#else 1148 /* ack receive service */ 1149 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); 1150 1151 com = com_addr(baseu + 1152 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) 1153 & CD1400_xIVR_CHAN)); 1154#endif 1155 1156 if (serv_type & CD1400_RIVR_EXCEPTION) { 1157 ++com->recv_exception; 1158 line_status = cd_inb(iobase, CD1400_RDSR, cy_align); 1159 /* break/unnattached error bits or real input? */ 1160 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); 1161#ifndef SOFT_HOTCHAR 1162 if (line_status & CD1400_RDSR_SPECIAL 1163 && com->hotchar != 0) 1164 setsofttty(); 1165#endif 1166#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ 1167 if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { 1168 /* 1169 Don't store PE if IGNPAR and BI if IGNBRK, 1170 this hack allows "raw" tty optimization 1171 works even if IGN* is set. 1172 */ 1173 if ( com->tp == NULL 1174 || !(com->tp->t_state & TS_ISOPEN) 1175 || ((line_status & (LSR_PE|LSR_FE)) 1176 && (com->tp->t_iflag & IGNPAR)) 1177 || ((line_status & LSR_BI) 1178 && (com->tp->t_iflag & IGNBRK))) 1179 goto cont; 1180 if ( (line_status & (LSR_PE|LSR_FE)) 1181 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) 1182 && ((line_status & LSR_FE) 1183 || ((line_status & LSR_PE) 1184 && (com->tp->t_iflag & INPCK)))) 1185 recv_data = 0; 1186 } 1187#endif /* 1 */ 1188 ++com->bytes_in; 1189#ifdef SOFT_HOTCHAR 1190 if (com->hotchar != 0 && recv_data == com->hotchar) 1191 setsofttty(); 1192#endif 1193 ioptr = com->iptr; 1194 if (ioptr >= com->ibufend) 1195 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); 1196 else { 1197 if (com->do_timestamp) 1198 microtime(&com->timestamp); 1199 ++com_events; 1200 ioptr[0] = recv_data; 1201 ioptr[com->ierroff] = line_status; 1202 com->iptr = ++ioptr; 1203 if (ioptr == com->ihighwater 1204 && com->state & CS_RTS_IFLOW) 1205#if 0 1206 outb(com->modem_ctl_port, 1207 com->mcr_image &= ~MCR_RTS); 1208#else 1209 cd_outb(iobase, com->mcr_rts_reg, 1210 cy_align, 1211 com->mcr_image &= 1212 ~com->mcr_rts); 1213#endif 1214 if (line_status & LSR_OE) 1215 CE_RECORD(com, CE_OVERRUN); 1216 } 1217 goto cont; 1218 } else { 1219 int ifree; 1220 1221 count = cd_inb(iobase, CD1400_RDCR, cy_align); 1222 if (!count) 1223 goto cont; 1224 com->bytes_in += count; 1225 ioptr = com->iptr; 1226 ifree = com->ibufend - ioptr; 1227 if (count > ifree) { 1228 count -= ifree; 1229 com_events += ifree; 1230 if (ifree != 0) { 1231 if (com->do_timestamp) 1232 microtime(&com->timestamp); 1233 do { 1234 recv_data = cd_inb(iobase, 1235 CD1400_RDSR, 1236 cy_align); 1237#ifdef SOFT_HOTCHAR 1238 if (com->hotchar != 0 1239 && recv_data 1240 == com->hotchar) 1241 setsofttty(); 1242#endif 1243 ioptr[0] = recv_data; 1244 ioptr[com->ierroff] = 0; 1245 ++ioptr; 1246 } while (--ifree != 0); 1247 } 1248 com->delta_error_counts 1249 [CE_INTERRUPT_BUF_OVERFLOW] += count; 1250 do { 1251 recv_data = cd_inb(iobase, CD1400_RDSR, 1252 cy_align); 1253#ifdef SOFT_HOTCHAR 1254 if (com->hotchar != 0 1255 && recv_data == com->hotchar) 1256 setsofttty(); 1257#endif 1258 } while (--count != 0); 1259 } else { 1260 if (com->do_timestamp) 1261 microtime(&com->timestamp); 1262 if (ioptr <= com->ihighwater 1263 && ioptr + count > com->ihighwater 1264 && com->state & CS_RTS_IFLOW) 1265#if 0 1266 outb(com->modem_ctl_port, 1267 com->mcr_image &= ~MCR_RTS); 1268#else 1269 cd_outb(iobase, com->mcr_rts_reg, 1270 cy_align, 1271 com->mcr_image 1272 &= ~com->mcr_rts); 1273#endif 1274 com_events += count; 1275 do { 1276 recv_data = cd_inb(iobase, CD1400_RDSR, 1277 cy_align); 1278#ifdef SOFT_HOTCHAR 1279 if (com->hotchar != 0 1280 && recv_data == com->hotchar) 1281 setsofttty(); 1282#endif 1283 ioptr[0] = recv_data; 1284 ioptr[com->ierroff] = 0; 1285 ++ioptr; 1286 } while (--count != 0); 1287 } 1288 com->iptr = ioptr; 1289 } 1290cont: 1291 1292 /* terminate service context */ 1293#ifdef PollMode 1294 cd_outb(iobase, CD1400_RIR, cy_align, 1295 save_rir 1296 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); 1297#else 1298 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1299#endif 1300 } 1301 if (status & CD1400_SVRR_MDMCH) { 1302 struct com_s *com; 1303 u_char modem_status; 1304#ifdef PollMode 1305 u_char save_mir; 1306#else 1307 u_char vector; 1308#endif 1309 1310#ifdef PollMode 1311 save_mir = cd_inb(iobase, CD1400_MIR, cy_align); 1312 1313 /* enter modem service */ 1314 cd_outb(iobase, CD1400_CAR, cy_align, save_mir); 1315 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1316 = save_mir & CD1400_CAR_CHAN; 1317 1318 com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS 1319 + (save_mir & CD1400_MIR_CHAN)); 1320#else 1321 /* ack modem service */ 1322 vector = cy_inb(iobase, CY8_SVCACKM, cy_align); 1323 1324 com = com_addr(baseu 1325 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1326 & CD1400_xIVR_CHAN)); 1327#endif 1328 ++com->mdm; 1329 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); 1330 if (modem_status != com->last_modem_status) { 1331 if (com->do_dcd_timestamp 1332 && !(com->last_modem_status & MSR_DCD) 1333 && modem_status & MSR_DCD) 1334 microtime(&com->dcd_timestamp); 1335 1336 /* 1337 * Schedule high level to handle DCD changes. Note 1338 * that we don't use the delta bits anywhere. Some 1339 * UARTs mess them up, and it's easy to remember the 1340 * previous bits and calculate the delta. 1341 */ 1342 com->last_modem_status = modem_status; 1343 if (!(com->state & CS_CHECKMSR)) { 1344 com_events += LOTS_OF_EVENTS; 1345 com->state |= CS_CHECKMSR; 1346 setsofttty(); 1347 } 1348 1349#ifdef SOFT_CTS_OFLOW 1350 /* handle CTS change immediately for crisp flow ctl */ 1351 if (com->state & CS_CTS_OFLOW) { 1352 if (modem_status & MSR_CTS) { 1353 com->state |= CS_ODEVREADY; 1354 if (com->state >= (CS_BUSY | CS_TTGO 1355 | CS_ODEVREADY) 1356 && !(com->intr_enable 1357 & CD1400_SRER_TXRDY)) 1358 cd_outb(iobase, CD1400_SRER, 1359 cy_align, 1360 com->intr_enable 1361 = com->intr_enable 1362 & ~CD1400_SRER_TXMPTY 1363 | CD1400_SRER_TXRDY); 1364 } else { 1365 com->state &= ~CS_ODEVREADY; 1366 if (com->intr_enable 1367 & CD1400_SRER_TXRDY) 1368 cd_outb(iobase, CD1400_SRER, 1369 cy_align, 1370 com->intr_enable 1371 = com->intr_enable 1372 & ~CD1400_SRER_TXRDY 1373 | CD1400_SRER_TXMPTY); 1374 } 1375 } 1376#endif 1377 } 1378 1379 /* terminate service context */ 1380#ifdef PollMode 1381 cd_outb(iobase, CD1400_MIR, cy_align, 1382 save_mir 1383 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); 1384#else 1385 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1386#endif 1387 } 1388 if (status & CD1400_SVRR_TXRDY) { 1389 struct com_s *com; 1390#ifdef PollMode 1391 u_char save_tir; 1392#else 1393 u_char vector; 1394#endif 1395 1396#ifdef PollMode 1397 save_tir = cd_inb(iobase, CD1400_TIR, cy_align); 1398 1399 /* enter tx service */ 1400 cd_outb(iobase, CD1400_CAR, cy_align, save_tir); 1401 com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car 1402 = save_tir & CD1400_CAR_CHAN; 1403 1404 com = com_addr(baseu 1405 + cyu * CD1400_NO_OF_CHANNELS 1406 + (save_tir & CD1400_TIR_CHAN)); 1407#else 1408 /* ack transmit service */ 1409 vector = cy_inb(iobase, CY8_SVCACKT, cy_align); 1410 1411 com = com_addr(baseu 1412 + ((vector >> CD1400_xIVR_CHAN_SHIFT) 1413 & CD1400_xIVR_CHAN)); 1414#endif 1415 1416 if (com->etc != ETC_NONE) { 1417 if (com->intr_enable & CD1400_SRER_TXRDY) { 1418 /* 1419 * Here due to sloppy SRER_TXRDY 1420 * enabling. Ignore. Come back when 1421 * tx is empty. 1422 */ 1423 cd_outb(iobase, CD1400_SRER, cy_align, 1424 com->intr_enable 1425 = (com->intr_enable 1426 & ~CD1400_SRER_TXRDY) 1427 | CD1400_SRER_TXMPTY); 1428 goto terminate_tx_service; 1429 } 1430 switch (com->etc) { 1431 case CD1400_ETC_SENDBREAK: 1432 case CD1400_ETC_STOPBREAK: 1433 /* 1434 * Start the command. Come back on 1435 * next tx empty interrupt, hopefully 1436 * after command has been executed. 1437 */ 1438 cd_outb(iobase, CD1400_COR2, cy_align, 1439 com->cor[1] |= CD1400_COR2_ETC); 1440 cd_outb(iobase, CD1400_TDR, cy_align, 1441 CD1400_ETC_CMD); 1442 cd_outb(iobase, CD1400_TDR, cy_align, 1443 com->etc); 1444 if (com->etc == CD1400_ETC_SENDBREAK) 1445 com->etc = ETC_BREAK_STARTING; 1446 else 1447 com->etc = ETC_BREAK_ENDING; 1448 goto terminate_tx_service; 1449 case ETC_BREAK_STARTING: 1450 /* 1451 * BREAK is now on. Continue with 1452 * SRER_TXMPTY processing, hopefully 1453 * don't come back. 1454 */ 1455 com->etc = ETC_BREAK_STARTED; 1456 break; 1457 case ETC_BREAK_STARTED: 1458 /* 1459 * Came back due to sloppy SRER_TXMPTY 1460 * enabling. Hope again. 1461 */ 1462 break; 1463 case ETC_BREAK_ENDING: 1464 /* 1465 * BREAK is now off. Continue with 1466 * SRER_TXMPTY processing and don't 1467 * come back. The SWI handler will 1468 * restart tx interrupts if necessary. 1469 */ 1470 cd_outb(iobase, CD1400_COR2, cy_align, 1471 com->cor[1] 1472 &= ~CD1400_COR2_ETC); 1473 com->etc = ETC_BREAK_ENDED; 1474 if (!(com->state & CS_ODONE)) { 1475 com_events += LOTS_OF_EVENTS; 1476 com->state |= CS_ODONE; 1477 setsofttty(); 1478 } 1479 break; 1480 case ETC_BREAK_ENDED: 1481 /* 1482 * Shouldn't get here. Hope again. 1483 */ 1484 break; 1485 } 1486 } 1487 if (com->intr_enable & CD1400_SRER_TXMPTY) { 1488 if (!(com->extra_state & CSE_ODONE)) { 1489 com_events += LOTS_OF_EVENTS; 1490 com->extra_state |= CSE_ODONE; 1491 setsofttty(); 1492 } 1493 cd_outb(iobase, CD1400_SRER, cy_align, 1494 com->intr_enable 1495 &= ~CD1400_SRER_TXMPTY); 1496 goto terminate_tx_service; 1497 } 1498 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 1499 u_char *ioptr; 1500 u_int ocount; 1501 1502 ioptr = com->obufq.l_head; 1503 ocount = com->obufq.l_tail - ioptr; 1504 if (ocount > CD1400_TX_FIFO_SIZE) 1505 ocount = CD1400_TX_FIFO_SIZE; 1506 com->bytes_out += ocount; 1507 do 1508 cd_outb(iobase, CD1400_TDR, cy_align, 1509 *ioptr++); 1510 while (--ocount != 0); 1511 com->obufq.l_head = ioptr; 1512 if (ioptr >= com->obufq.l_tail) { 1513 struct lbq *qp; 1514 1515 qp = com->obufq.l_next; 1516 qp->l_queued = FALSE; 1517 qp = qp->l_next; 1518 if (qp != NULL) { 1519 com->obufq.l_head = qp->l_head; 1520 com->obufq.l_tail = qp->l_tail; 1521 com->obufq.l_next = qp; 1522 } else { 1523 /* output just completed */ 1524 com->state &= ~CS_BUSY; 1525 1526 /* 1527 * The setting of CSE_ODONE may be 1528 * stale here. We currently only 1529 * use it when CS_BUSY is set, and 1530 * fixing it when we clear CS_BUSY 1531 * is easiest. 1532 */ 1533 if (com->extra_state & CSE_ODONE) { 1534 com_events -= LOTS_OF_EVENTS; 1535 com->extra_state &= ~CSE_ODONE; 1536 } 1537 1538 cd_outb(iobase, CD1400_SRER, cy_align, 1539 com->intr_enable 1540 = (com->intr_enable 1541 & ~CD1400_SRER_TXRDY) 1542 | CD1400_SRER_TXMPTY); 1543 } 1544 if (!(com->state & CS_ODONE)) { 1545 com_events += LOTS_OF_EVENTS; 1546 com->state |= CS_ODONE; 1547 1548 /* handle at high level ASAP */ 1549 setsofttty(); 1550 } 1551 } 1552 } 1553 1554 /* terminate service context */ 1555terminate_tx_service: 1556#ifdef PollMode 1557 cd_outb(iobase, CD1400_TIR, cy_align, 1558 save_tir 1559 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); 1560#else 1561 cd_outb(iobase, CD1400_EOSRR, cy_align, 0); 1562#endif 1563 } 1564 } 1565 1566 /* ensure an edge for the next interrupt */ 1567 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); 1568 1569 schedsofttty(); 1570 1571 COM_UNLOCK(); 1572} 1573 1574#if 0 1575static void 1576siointr1(com) 1577 struct com_s *com; 1578{ 1579} 1580#endif 1581 1582static int 1583sioioctl(dev, cmd, data, flag, p) 1584 dev_t dev; 1585 u_long cmd; 1586 caddr_t data; 1587 int flag; 1588 struct proc *p; 1589{ 1590 struct com_s *com; 1591 int error; 1592 int mynor; 1593 int s; 1594 struct tty *tp; 1595#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1596 int oldcmd; 1597 struct termios term; 1598#endif 1599 1600 mynor = minor(dev); 1601 com = com_addr(MINOR_TO_UNIT(mynor)); 1602 if (mynor & CONTROL_MASK) { 1603 struct termios *ct; 1604 1605 switch (mynor & CONTROL_MASK) { 1606 case CONTROL_INIT_STATE: 1607 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; 1608 break; 1609 case CONTROL_LOCK_STATE: 1610 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; 1611 break; 1612 default: 1613 return (ENODEV); /* /dev/nodev */ 1614 } 1615 switch (cmd) { 1616 case TIOCSETA: 1617 error = suser(p); 1618 if (error != 0) 1619 return (error); 1620 *ct = *(struct termios *)data; 1621 return (0); 1622 case TIOCGETA: 1623 *(struct termios *)data = *ct; 1624 return (0); 1625 case TIOCGETD: 1626 *(int *)data = TTYDISC; 1627 return (0); 1628 case TIOCGWINSZ: 1629 bzero(data, sizeof(struct winsize)); 1630 return (0); 1631 default: 1632 return (ENOTTY); 1633 } 1634 } 1635 tp = com->tp; 1636#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1637 term = tp->t_termios; 1638 oldcmd = cmd; 1639 error = ttsetcompat(tp, &cmd, data, &term); 1640 if (error != 0) 1641 return (error); 1642 if (cmd != oldcmd) 1643 data = (caddr_t)&term; 1644#endif 1645 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1646 int cc; 1647 struct termios *dt = (struct termios *)data; 1648 struct termios *lt = mynor & CALLOUT_MASK 1649 ? &com->lt_out : &com->lt_in; 1650 1651 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1652 | (dt->c_iflag & ~lt->c_iflag); 1653 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1654 | (dt->c_oflag & ~lt->c_oflag); 1655 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1656 | (dt->c_cflag & ~lt->c_cflag); 1657 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1658 | (dt->c_lflag & ~lt->c_lflag); 1659 for (cc = 0; cc < NCCS; ++cc) 1660 if (lt->c_cc[cc] != 0) 1661 dt->c_cc[cc] = tp->t_cc[cc]; 1662 if (lt->c_ispeed != 0) 1663 dt->c_ispeed = tp->t_ispeed; 1664 if (lt->c_ospeed != 0) 1665 dt->c_ospeed = tp->t_ospeed; 1666 } 1667 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1668 if (error != ENOIOCTL) 1669 return (error); 1670 s = spltty(); 1671 error = ttioctl(tp, cmd, data, flag); 1672 disc_optim(tp, &tp->t_termios, com); 1673 if (error != ENOIOCTL) { 1674 splx(s); 1675 return (error); 1676 } 1677 switch (cmd) { 1678 case TIOCSBRK: 1679#if 0 1680 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); 1681#else 1682 cd_etc(com, CD1400_ETC_SENDBREAK); 1683#endif 1684 break; 1685 case TIOCCBRK: 1686#if 0 1687 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); 1688#else 1689 cd_etc(com, CD1400_ETC_STOPBREAK); 1690#endif 1691 break; 1692 case TIOCSDTR: 1693 (void)commctl(com, TIOCM_DTR, DMBIS); 1694 break; 1695 case TIOCCDTR: 1696 (void)commctl(com, TIOCM_DTR, DMBIC); 1697 break; 1698 /* 1699 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The 1700 * changes get undone on the next call to comparam(). 1701 */ 1702 case TIOCMSET: 1703 (void)commctl(com, *(int *)data, DMSET); 1704 break; 1705 case TIOCMBIS: 1706 (void)commctl(com, *(int *)data, DMBIS); 1707 break; 1708 case TIOCMBIC: 1709 (void)commctl(com, *(int *)data, DMBIC); 1710 break; 1711 case TIOCMGET: 1712 *(int *)data = commctl(com, 0, DMGET); 1713 break; 1714 case TIOCMSDTRWAIT: 1715 /* must be root since the wait applies to following logins */ 1716 error = suser(p); 1717 if (error != 0) { 1718 splx(s); 1719 return (error); 1720 } 1721 com->dtr_wait = *(int *)data * hz / 100; 1722 break; 1723 case TIOCMGDTRWAIT: 1724 *(int *)data = com->dtr_wait * 100 / hz; 1725 break; 1726 case TIOCTIMESTAMP: 1727 com->do_timestamp = TRUE; 1728 *(struct timeval *)data = com->timestamp; 1729 break; 1730 case TIOCDCDTIMESTAMP: 1731 com->do_dcd_timestamp = TRUE; 1732 *(struct timeval *)data = com->dcd_timestamp; 1733 break; 1734 default: 1735 splx(s); 1736 return (ENOTTY); 1737 } 1738 splx(s); 1739 return (0); 1740} 1741 1742static void 1743siopoll() 1744{ 1745 int unit; 1746 1747#ifdef CyDebug 1748 ++cy_timeouts; 1749#endif 1750 if (com_events == 0) 1751 return; 1752repeat: 1753 for (unit = 0; unit < NSIO; ++unit) { 1754 struct com_s *com; 1755 int incc; 1756 struct tty *tp; 1757 1758 com = com_addr(unit); 1759 if (com == NULL) 1760 continue; 1761 tp = com->tp; 1762 if (tp == NULL) { 1763 /* 1764 * XXX forget any events related to closed devices 1765 * (actually never opened devices) so that we don't 1766 * loop. 1767 */ 1768 disable_intr(); 1769 incc = com->iptr - com->ibuf; 1770 com->iptr = com->ibuf; 1771 if (com->state & CS_CHECKMSR) { 1772 incc += LOTS_OF_EVENTS; 1773 com->state &= ~CS_CHECKMSR; 1774 } 1775 com_events -= incc; 1776 enable_intr(); 1777 if (incc != 0) 1778 log(LOG_DEBUG, 1779 "sio%d: %d events for device with no tp\n", 1780 unit, incc); 1781 continue; 1782 } 1783 if (com->iptr != com->ibuf) { 1784 disable_intr(); 1785 sioinput(com); 1786 enable_intr(); 1787 } 1788 if (com->state & CS_CHECKMSR) { 1789 u_char delta_modem_status; 1790 1791 disable_intr(); 1792 delta_modem_status = com->last_modem_status 1793 ^ com->prev_modem_status; 1794 com->prev_modem_status = com->last_modem_status; 1795 com_events -= LOTS_OF_EVENTS; 1796 com->state &= ~CS_CHECKMSR; 1797 enable_intr(); 1798 if (delta_modem_status & MSR_DCD) 1799 (*linesw[tp->t_line].l_modem) 1800 (tp, com->prev_modem_status & MSR_DCD); 1801 } 1802 if (com->extra_state & CSE_ODONE) { 1803 disable_intr(); 1804 com_events -= LOTS_OF_EVENTS; 1805 com->extra_state &= ~CSE_ODONE; 1806 enable_intr(); 1807 if (!(com->state & CS_BUSY)) { 1808 tp->t_state &= ~TS_BUSY; 1809 ttwwakeup(com->tp); 1810 } 1811 if (com->etc != ETC_NONE) { 1812 if (com->etc == ETC_BREAK_ENDED) 1813 com->etc = ETC_NONE; 1814 wakeup(&com->etc); 1815 } 1816 } 1817 if (com->state & CS_ODONE) { 1818 disable_intr(); 1819 com_events -= LOTS_OF_EVENTS; 1820 com->state &= ~CS_ODONE; 1821 enable_intr(); 1822 (*linesw[tp->t_line].l_start)(tp); 1823 } 1824 if (com_events == 0) 1825 break; 1826 } 1827 if (com_events >= LOTS_OF_EVENTS) 1828 goto repeat; 1829} 1830 1831static int 1832comparam(tp, t) 1833 struct tty *tp; 1834 struct termios *t; 1835{ 1836 int bits; 1837 int cflag; 1838 struct com_s *com; 1839 u_char cor_change; 1840 u_long cy_clock; 1841 int idivisor; 1842 int iflag; 1843 int iprescaler; 1844 int itimeout; 1845 int odivisor; 1846 int oprescaler; 1847 u_char opt; 1848 int s; 1849 int unit; 1850 1851 /* do historical conversions */ 1852 if (t->c_ispeed == 0) 1853 t->c_ispeed = t->c_ospeed; 1854 1855 unit = DEV_TO_UNIT(tp->t_dev); 1856 com = com_addr(unit); 1857 1858 /* check requested parameters */ 1859 cy_clock = CY_CLOCK(com->gfrcr_image); 1860 idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); 1861 if (idivisor < 0) 1862 return (EINVAL); 1863 odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); 1864 if (odivisor < 0) 1865 return (EINVAL); 1866 1867 /* parameters are OK, convert them to the com struct and the device */ 1868 s = spltty(); 1869 if (odivisor == 0) 1870 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ 1871 else 1872 (void)commctl(com, TIOCM_DTR, DMBIS); 1873 1874 /* 1875 * This returns with interrupts disabled so that we can complete 1876 * the speed change atomically. 1877 */ 1878 (void) siosetwater(com, t->c_ispeed); 1879 1880 /* XXX we don't actually change the speed atomically. */ 1881 enable_intr(); 1882 1883 if (idivisor != 0) { 1884 cd_setreg(com, CD1400_RBPR, idivisor); 1885 cd_setreg(com, CD1400_RCOR, iprescaler); 1886 } 1887 if (odivisor != 0) { 1888 cd_setreg(com, CD1400_TBPR, odivisor); 1889 cd_setreg(com, CD1400_TCOR, oprescaler); 1890 } 1891 1892 /* 1893 * channel control 1894 * receiver enable 1895 * transmitter enable (always set) 1896 */ 1897 cflag = t->c_cflag; 1898 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN 1899 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); 1900 if (opt != com->channel_control) { 1901 com->channel_control = opt; 1902 cd1400_channel_cmd(com, opt); 1903 } 1904 1905#ifdef Smarts 1906 /* set special chars */ 1907 /* XXX if one is _POSIX_VDISABLE, can't use some others */ 1908 if (t->c_cc[VSTOP] != _POSIX_VDISABLE) 1909 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); 1910 if (t->c_cc[VSTART] != _POSIX_VDISABLE) 1911 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); 1912 if (t->c_cc[VINTR] != _POSIX_VDISABLE) 1913 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); 1914 if (t->c_cc[VSUSP] != _POSIX_VDISABLE) 1915 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); 1916#endif 1917 1918 /* 1919 * set channel option register 1 - 1920 * parity mode 1921 * stop bits 1922 * char length 1923 */ 1924 opt = 0; 1925 /* parity */ 1926 if (cflag & PARENB) { 1927 if (cflag & PARODD) 1928 opt |= CD1400_COR1_PARODD; 1929 opt |= CD1400_COR1_PARNORMAL; 1930 } 1931 iflag = t->c_iflag; 1932 if (!(iflag & INPCK)) 1933 opt |= CD1400_COR1_NOINPCK; 1934 bits = 1 + 1; 1935 /* stop bits */ 1936 if (cflag & CSTOPB) { 1937 ++bits; 1938 opt |= CD1400_COR1_STOP2; 1939 } 1940 /* char length */ 1941 switch (cflag & CSIZE) { 1942 case CS5: 1943 bits += 5; 1944 opt |= CD1400_COR1_CS5; 1945 break; 1946 case CS6: 1947 bits += 6; 1948 opt |= CD1400_COR1_CS6; 1949 break; 1950 case CS7: 1951 bits += 7; 1952 opt |= CD1400_COR1_CS7; 1953 break; 1954 default: 1955 bits += 8; 1956 opt |= CD1400_COR1_CS8; 1957 break; 1958 } 1959 cor_change = 0; 1960 if (opt != com->cor[0]) { 1961 cor_change |= CD1400_CCR_COR1; 1962 cd_setreg(com, CD1400_COR1, com->cor[0] = opt); 1963 } 1964 1965 /* 1966 * Set receive time-out period, normally to max(one char time, 5 ms). 1967 */ 1968 if (t->c_ispeed == 0) 1969 itimeout = cd_getreg(com, CD1400_RTPR); 1970 else { 1971 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; 1972#ifdef SOFT_HOTCHAR 1973#define MIN_RTP 1 1974#else 1975#define MIN_RTP 5 1976#endif 1977 if (itimeout < MIN_RTP) 1978 itimeout = MIN_RTP; 1979 } 1980 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 1981 && t->c_cc[VTIME] * 10 > itimeout) 1982 itimeout = t->c_cc[VTIME] * 10; 1983 if (itimeout > 255) 1984 itimeout = 255; 1985 cd_setreg(com, CD1400_RTPR, itimeout); 1986 1987 /* 1988 * set channel option register 2 - 1989 * flow control 1990 */ 1991 opt = 0; 1992#ifdef Smarts 1993 if (iflag & IXANY) 1994 opt |= CD1400_COR2_IXANY; 1995 if (iflag & IXOFF) 1996 opt |= CD1400_COR2_IXOFF; 1997#endif 1998#ifndef SOFT_CTS_OFLOW 1999 if (cflag & CCTS_OFLOW) 2000 opt |= CD1400_COR2_CCTS_OFLOW; 2001#endif 2002 disable_intr(); 2003 if (opt != com->cor[1]) { 2004 cor_change |= CD1400_CCR_COR2; 2005 cd_setreg(com, CD1400_COR2, com->cor[1] = opt); 2006 } 2007 enable_intr(); 2008 2009 /* 2010 * set channel option register 3 - 2011 * receiver FIFO interrupt threshold 2012 * flow control 2013 */ 2014 opt = RxFifoThreshold; 2015#ifdef Smarts 2016 if (t->c_lflag & ICANON) 2017 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ 2018 if (iflag & IXOFF) 2019 /* detect and transparently handle START and STOP chars */ 2020 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; 2021#endif 2022 if (opt != com->cor[2]) { 2023 cor_change |= CD1400_CCR_COR3; 2024 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2025 } 2026 2027 /* notify the CD1400 if COR1-3 have changed */ 2028 if (cor_change) 2029 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); 2030 2031 /* 2032 * set channel option register 4 - 2033 * CR/NL processing 2034 * break processing 2035 * received exception processing 2036 */ 2037 opt = 0; 2038 if (iflag & IGNCR) 2039 opt |= CD1400_COR4_IGNCR; 2040#ifdef Smarts 2041 /* 2042 * we need a new ttyinput() for this, as we don't want to 2043 * have ICRNL && INLCR being done in both layers, or to have 2044 * synchronisation problems 2045 */ 2046 if (iflag & ICRNL) 2047 opt |= CD1400_COR4_ICRNL; 2048 if (iflag & INLCR) 2049 opt |= CD1400_COR4_INLCR; 2050#endif 2051 if (iflag & IGNBRK) 2052 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; 2053 /* 2054 * The `-ignbrk -brkint parmrk' case is not handled by the hardware, 2055 * so only tell the hardware about -brkint if -parmrk. 2056 */ 2057 if (!(iflag & (BRKINT | PARMRK))) 2058 opt |= CD1400_COR4_NOBRKINT; 2059#if 0 2060 /* XXX using this "intelligence" breaks reporting of overruns. */ 2061 if (iflag & IGNPAR) 2062 opt |= CD1400_COR4_PFO_DISCARD; 2063 else { 2064 if (iflag & PARMRK) 2065 opt |= CD1400_COR4_PFO_ESC; 2066 else 2067 opt |= CD1400_COR4_PFO_NUL; 2068 } 2069#else 2070 opt |= CD1400_COR4_PFO_EXCEPTION; 2071#endif 2072 cd_setreg(com, CD1400_COR4, opt); 2073 2074 /* 2075 * set channel option register 5 - 2076 */ 2077 opt = 0; 2078 if (iflag & ISTRIP) 2079 opt |= CD1400_COR5_ISTRIP; 2080 if (t->c_iflag & IEXTEN) 2081 /* enable LNEXT (e.g. ctrl-v quoting) handling */ 2082 opt |= CD1400_COR5_LNEXT; 2083#ifdef Smarts 2084 if (t->c_oflag & ONLCR) 2085 opt |= CD1400_COR5_ONLCR; 2086 if (t->c_oflag & OCRNL) 2087 opt |= CD1400_COR5_OCRNL; 2088#endif 2089 cd_setreg(com, CD1400_COR5, opt); 2090 2091 /* 2092 * We always generate modem status change interrupts for CD changes. 2093 * Among other things, this is necessary to track TS_CARR_ON for 2094 * pstat to print even when the driver doesn't care. CD changes 2095 * should be rare so interrupts for them are not worth extra code to 2096 * avoid. We avoid interrupts for other modem status changes (except 2097 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is 2098 * simplest and best. 2099 */ 2100 2101 /* 2102 * set modem change option register 1 2103 * generate modem interrupts on which 1 -> 0 input transitions 2104 * also controls auto-DTR output flow-control, which we don't use 2105 */ 2106 opt = CD1400_MCOR1_CDzd; 2107#ifdef SOFT_CTS_OFLOW 2108 if (cflag & CCTS_OFLOW) 2109 opt |= CD1400_MCOR1_CTSzd; 2110#endif 2111 cd_setreg(com, CD1400_MCOR1, opt); 2112 2113 /* 2114 * set modem change option register 2 2115 * generate modem interrupts on specific 0 -> 1 input transitions 2116 */ 2117 opt = CD1400_MCOR2_CDod; 2118#ifdef SOFT_CTS_OFLOW 2119 if (cflag & CCTS_OFLOW) 2120 opt |= CD1400_MCOR2_CTSod; 2121#endif 2122 cd_setreg(com, CD1400_MCOR2, opt); 2123 2124 /* 2125 * XXX should have done this long ago, but there is too much state 2126 * to change all atomically. 2127 */ 2128 disable_intr(); 2129 2130 com->state &= ~CS_TTGO; 2131 if (!(tp->t_state & TS_TTSTOP)) 2132 com->state |= CS_TTGO; 2133 if (cflag & CRTS_IFLOW) { 2134 com->state |= CS_RTS_IFLOW; 2135 /* 2136 * If CS_RTS_IFLOW just changed from off to on, the change 2137 * needs to be propagated to MCR_RTS. This isn't urgent, 2138 * so do it later by calling comstart() instead of repeating 2139 * a lot of code from comstart() here. 2140 */ 2141 } else if (com->state & CS_RTS_IFLOW) { 2142 com->state &= ~CS_RTS_IFLOW; 2143 /* 2144 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS 2145 * on here, since comstart() won't do it later. 2146 */ 2147#if 0 2148 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2149#else 2150 cd_setreg(com, com->mcr_rts_reg, 2151 com->mcr_image |= com->mcr_rts); 2152#endif 2153 } 2154 2155 /* 2156 * Set up state to handle output flow control. 2157 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? 2158 * Now has 10+ msec latency, while CTS flow has 50- usec latency. 2159 */ 2160 com->state |= CS_ODEVREADY; 2161#ifdef SOFT_CTS_OFLOW 2162 com->state &= ~CS_CTS_OFLOW; 2163 if (cflag & CCTS_OFLOW) { 2164 com->state |= CS_CTS_OFLOW; 2165 if (!(com->last_modem_status & MSR_CTS)) 2166 com->state &= ~CS_ODEVREADY; 2167 } 2168#endif 2169 /* XXX shouldn't call functions while intrs are disabled. */ 2170 disc_optim(tp, t, com); 2171#if 0 2172 /* 2173 * Recover from fiddling with CS_TTGO. We used to call siointr1() 2174 * unconditionally, but that defeated the careful discarding of 2175 * stale input in sioopen(). 2176 */ 2177 if (com->state >= (CS_BUSY | CS_TTGO)) 2178 siointr1(com); 2179#endif 2180 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { 2181 if (!(com->intr_enable & CD1400_SRER_TXRDY)) 2182 cd_setreg(com, CD1400_SRER, 2183 com->intr_enable 2184 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2185 | CD1400_SRER_TXRDY); 2186 } else { 2187 if (com->intr_enable & CD1400_SRER_TXRDY) 2188 cd_setreg(com, CD1400_SRER, 2189 com->intr_enable 2190 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2191 | CD1400_SRER_TXMPTY); 2192 } 2193 2194 enable_intr(); 2195 splx(s); 2196 comstart(tp); 2197 if (com->ibufold != NULL) { 2198 free(com->ibufold, M_DEVBUF); 2199 com->ibufold = NULL; 2200 } 2201 return (0); 2202} 2203 2204static int 2205siosetwater(com, speed) 2206 struct com_s *com; 2207 speed_t speed; 2208{ 2209 int cp4ticks; 2210 u_char *ibuf; 2211 int ibufsize; 2212 struct tty *tp; 2213 2214 /* 2215 * Make the buffer size large enough to handle a softtty interrupt 2216 * latency of about 2 ticks without loss of throughput or data 2217 * (about 3 ticks if input flow control is not used or not honoured, 2218 * but a bit less for CS5-CS7 modes). 2219 */ 2220 cp4ticks = speed / 10 / hz * 4; 2221 for (ibufsize = 128; ibufsize < cp4ticks;) 2222 ibufsize <<= 1; 2223 if (ibufsize == com->ibufsize) { 2224 disable_intr(); 2225 return (0); 2226 } 2227 2228 /* 2229 * Allocate input buffer. The extra factor of 2 in the size is 2230 * to allow for an error byte for each input byte. 2231 */ 2232 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); 2233 if (ibuf == NULL) { 2234 disable_intr(); 2235 return (ENOMEM); 2236 } 2237 2238 /* Initialize non-critical variables. */ 2239 com->ibufold = com->ibuf; 2240 com->ibufsize = ibufsize; 2241 tp = com->tp; 2242 if (tp != NULL) { 2243 tp->t_ififosize = 2 * ibufsize; 2244 tp->t_ispeedwat = (speed_t)-1; 2245 tp->t_ospeedwat = (speed_t)-1; 2246 } 2247 2248 /* 2249 * Read current input buffer, if any. Continue with interrupts 2250 * disabled. 2251 */ 2252 disable_intr(); 2253 if (com->iptr != com->ibuf) 2254 sioinput(com); 2255 2256 /*- 2257 * Initialize critical variables, including input buffer watermarks. 2258 * The external device is asked to stop sending when the buffer 2259 * exactly reaches high water, or when the high level requests it. 2260 * The high level is notified immediately (rather than at a later 2261 * clock tick) when this watermark is reached. 2262 * The buffer size is chosen so the watermark should almost never 2263 * be reached. 2264 * The low watermark is invisibly 0 since the buffer is always 2265 * emptied all at once. 2266 */ 2267 com->iptr = com->ibuf = ibuf; 2268 com->ibufend = ibuf + ibufsize; 2269 com->ierroff = ibufsize; 2270 com->ihighwater = ibuf + 3 * ibufsize / 4; 2271 return (0); 2272} 2273 2274static void 2275comstart(tp) 2276 struct tty *tp; 2277{ 2278 struct com_s *com; 2279 int s; 2280#ifdef CyDebug 2281 bool_t started; 2282#endif 2283 int unit; 2284 2285 unit = DEV_TO_UNIT(tp->t_dev); 2286 com = com_addr(unit); 2287 s = spltty(); 2288 2289#ifdef CyDebug 2290 ++com->start_count; 2291 started = FALSE; 2292#endif 2293 2294 disable_intr(); 2295 if (tp->t_state & TS_TTSTOP) { 2296 com->state &= ~CS_TTGO; 2297 if (com->intr_enable & CD1400_SRER_TXRDY) 2298 cd_setreg(com, CD1400_SRER, 2299 com->intr_enable 2300 = (com->intr_enable & ~CD1400_SRER_TXRDY) 2301 | CD1400_SRER_TXMPTY); 2302 } else { 2303 com->state |= CS_TTGO; 2304 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) 2305 && !(com->intr_enable & CD1400_SRER_TXRDY)) 2306 cd_setreg(com, CD1400_SRER, 2307 com->intr_enable 2308 = (com->intr_enable & ~CD1400_SRER_TXMPTY) 2309 | CD1400_SRER_TXRDY); 2310 } 2311 if (tp->t_state & TS_TBLOCK) { 2312 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) 2313#if 0 2314 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); 2315#else 2316 cd_setreg(com, com->mcr_rts_reg, 2317 com->mcr_image &= ~com->mcr_rts); 2318#endif 2319 } else { 2320 if (!(com->mcr_image & com->mcr_rts) 2321 && com->iptr < com->ihighwater 2322 && com->state & CS_RTS_IFLOW) 2323#if 0 2324 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); 2325#else 2326 cd_setreg(com, com->mcr_rts_reg, 2327 com->mcr_image |= com->mcr_rts); 2328#endif 2329 } 2330 enable_intr(); 2331 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 2332 ttwwakeup(tp); 2333 splx(s); 2334 return; 2335 } 2336 if (tp->t_outq.c_cc != 0) { 2337 struct lbq *qp; 2338 struct lbq *next; 2339 2340 if (!com->obufs[0].l_queued) { 2341#ifdef CyDebug 2342 started = TRUE; 2343#endif 2344 com->obufs[0].l_tail 2345 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, 2346 sizeof com->obuf1); 2347 com->obufs[0].l_next = NULL; 2348 com->obufs[0].l_queued = TRUE; 2349 disable_intr(); 2350 if (com->state & CS_BUSY) { 2351 qp = com->obufq.l_next; 2352 while ((next = qp->l_next) != NULL) 2353 qp = next; 2354 qp->l_next = &com->obufs[0]; 2355 } else { 2356 com->obufq.l_head = com->obufs[0].l_head; 2357 com->obufq.l_tail = com->obufs[0].l_tail; 2358 com->obufq.l_next = &com->obufs[0]; 2359 com->state |= CS_BUSY; 2360 if (com->state >= (CS_BUSY | CS_TTGO 2361 | CS_ODEVREADY)) 2362 cd_setreg(com, CD1400_SRER, 2363 com->intr_enable 2364 = (com->intr_enable 2365 & ~CD1400_SRER_TXMPTY) 2366 | CD1400_SRER_TXRDY); 2367 } 2368 enable_intr(); 2369 } 2370 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { 2371#ifdef CyDebug 2372 started = TRUE; 2373#endif 2374 com->obufs[1].l_tail 2375 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, 2376 sizeof com->obuf2); 2377 com->obufs[1].l_next = NULL; 2378 com->obufs[1].l_queued = TRUE; 2379 disable_intr(); 2380 if (com->state & CS_BUSY) { 2381 qp = com->obufq.l_next; 2382 while ((next = qp->l_next) != NULL) 2383 qp = next; 2384 qp->l_next = &com->obufs[1]; 2385 } else { 2386 com->obufq.l_head = com->obufs[1].l_head; 2387 com->obufq.l_tail = com->obufs[1].l_tail; 2388 com->obufq.l_next = &com->obufs[1]; 2389 com->state |= CS_BUSY; 2390 if (com->state >= (CS_BUSY | CS_TTGO 2391 | CS_ODEVREADY)) 2392 cd_setreg(com, CD1400_SRER, 2393 com->intr_enable 2394 = (com->intr_enable 2395 & ~CD1400_SRER_TXMPTY) 2396 | CD1400_SRER_TXRDY); 2397 } 2398 enable_intr(); 2399 } 2400 tp->t_state |= TS_BUSY; 2401 } 2402#ifdef CyDebug 2403 if (started) 2404 ++com->start_real; 2405#endif 2406#if 0 2407 disable_intr(); 2408 if (com->state >= (CS_BUSY | CS_TTGO)) 2409 siointr1(com); /* fake interrupt to start output */ 2410 enable_intr(); 2411#endif 2412 ttwwakeup(tp); 2413 splx(s); 2414} 2415 2416static void
|
2417siostop(tp, rw)
| 2417comstop(tp, rw)
|
2418 struct tty *tp; 2419 int rw; 2420{ 2421 struct com_s *com; 2422 bool_t wakeup_etc; 2423 2424 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2425 wakeup_etc = FALSE; 2426 disable_intr(); 2427 if (rw & FWRITE) { 2428 com->obufs[0].l_queued = FALSE; 2429 com->obufs[1].l_queued = FALSE; 2430 if (com->extra_state & CSE_ODONE) { 2431 com_events -= LOTS_OF_EVENTS; 2432 com->extra_state &= ~CSE_ODONE; 2433 if (com->etc != ETC_NONE) { 2434 if (com->etc == ETC_BREAK_ENDED) 2435 com->etc = ETC_NONE; 2436 wakeup_etc = TRUE; 2437 } 2438 } 2439 com->tp->t_state &= ~TS_BUSY; 2440 if (com->state & CS_ODONE) 2441 com_events -= LOTS_OF_EVENTS; 2442 com->state &= ~(CS_ODONE | CS_BUSY); 2443 } 2444 if (rw & FREAD) { 2445 /* XXX no way to reset only input fifo. */ 2446 com_events -= (com->iptr - com->ibuf); 2447 com->iptr = com->ibuf; 2448 } 2449 enable_intr(); 2450 if (wakeup_etc) 2451 wakeup(&com->etc); 2452 if (rw & FWRITE && com->etc == ETC_NONE) 2453 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2454 comstart(tp); 2455} 2456
| 2418 struct tty *tp; 2419 int rw; 2420{ 2421 struct com_s *com; 2422 bool_t wakeup_etc; 2423 2424 com = com_addr(DEV_TO_UNIT(tp->t_dev)); 2425 wakeup_etc = FALSE; 2426 disable_intr(); 2427 if (rw & FWRITE) { 2428 com->obufs[0].l_queued = FALSE; 2429 com->obufs[1].l_queued = FALSE; 2430 if (com->extra_state & CSE_ODONE) { 2431 com_events -= LOTS_OF_EVENTS; 2432 com->extra_state &= ~CSE_ODONE; 2433 if (com->etc != ETC_NONE) { 2434 if (com->etc == ETC_BREAK_ENDED) 2435 com->etc = ETC_NONE; 2436 wakeup_etc = TRUE; 2437 } 2438 } 2439 com->tp->t_state &= ~TS_BUSY; 2440 if (com->state & CS_ODONE) 2441 com_events -= LOTS_OF_EVENTS; 2442 com->state &= ~(CS_ODONE | CS_BUSY); 2443 } 2444 if (rw & FREAD) { 2445 /* XXX no way to reset only input fifo. */ 2446 com_events -= (com->iptr - com->ibuf); 2447 com->iptr = com->ibuf; 2448 } 2449 enable_intr(); 2450 if (wakeup_etc) 2451 wakeup(&com->etc); 2452 if (rw & FWRITE && com->etc == ETC_NONE) 2453 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); 2454 comstart(tp); 2455} 2456
|
2457static struct tty * 2458siodevtotty(dev) 2459 dev_t dev; 2460{ 2461 int mynor; 2462 int unit; 2463 2464 mynor = minor(dev); 2465 if (mynor & CONTROL_MASK) 2466 return (NULL); 2467 unit = MINOR_TO_UNIT(mynor); 2468 if ((u_int) unit >= NSIO) 2469 return (NULL); 2470 return (&sio_tty[unit]); 2471} 2472
| |
2473static int 2474commctl(com, bits, how) 2475 struct com_s *com; 2476 int bits; 2477 int how; 2478{ 2479 int mcr; 2480 int msr; 2481 2482 if (how == DMGET) { 2483 if (com->channel_control & CD1400_CCR_RCVEN) 2484 bits |= TIOCM_LE; 2485 mcr = com->mcr_image; 2486 if (mcr & com->mcr_dtr) 2487 bits |= TIOCM_DTR; 2488 if (mcr & com->mcr_rts) 2489 /* XXX wired on for Cyclom-8Ys */ 2490 bits |= TIOCM_RTS; 2491 2492 /* 2493 * We must read the modem status from the hardware because 2494 * we don't generate modem status change interrupts for all 2495 * changes, so com->prev_modem_status is not guaranteed to 2496 * be up to date. This is safe, unlike for sio, because 2497 * reading the status register doesn't clear pending modem 2498 * status change interrupts. 2499 */ 2500 msr = cd_getreg(com, CD1400_MSVR2); 2501 2502 if (msr & MSR_CTS) 2503 bits |= TIOCM_CTS; 2504 if (msr & MSR_DCD) 2505 bits |= TIOCM_CD; 2506 if (msr & MSR_DSR) 2507 bits |= TIOCM_DSR; 2508 if (msr & MSR_RI) 2509 /* XXX not connected except for Cyclom-16Y? */ 2510 bits |= TIOCM_RI; 2511 return (bits); 2512 } 2513 mcr = 0; 2514 if (bits & TIOCM_DTR) 2515 mcr |= com->mcr_dtr; 2516 if (bits & TIOCM_RTS) 2517 mcr |= com->mcr_rts; 2518 disable_intr(); 2519 switch (how) { 2520 case DMSET: 2521 com->mcr_image = mcr; 2522 cd_setreg(com, CD1400_MSVR1, mcr); 2523 cd_setreg(com, CD1400_MSVR2, mcr); 2524 break; 2525 case DMBIS: 2526 com->mcr_image = mcr = com->mcr_image | mcr; 2527 cd_setreg(com, CD1400_MSVR1, mcr); 2528 cd_setreg(com, CD1400_MSVR2, mcr); 2529 break; 2530 case DMBIC: 2531 com->mcr_image = mcr = com->mcr_image & ~mcr; 2532 cd_setreg(com, CD1400_MSVR1, mcr); 2533 cd_setreg(com, CD1400_MSVR2, mcr); 2534 break; 2535 } 2536 enable_intr(); 2537 return (0); 2538} 2539 2540static void 2541siosettimeout() 2542{ 2543 struct com_s *com; 2544 bool_t someopen; 2545 int unit; 2546 2547 /* 2548 * Set our timeout period to 1 second if no polled devices are open. 2549 * Otherwise set it to max(1/200, 1/hz). 2550 * Enable timeouts iff some device is open. 2551 */ 2552 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2553 sio_timeout = hz; 2554 someopen = FALSE; 2555 for (unit = 0; unit < NSIO; ++unit) { 2556 com = com_addr(unit); 2557 if (com != NULL && com->tp != NULL 2558 && com->tp->t_state & TS_ISOPEN) { 2559 someopen = TRUE; 2560#if 0 2561 if (com->poll || com->poll_output) { 2562 sio_timeout = hz > 200 ? hz / 200 : 1; 2563 break; 2564 } 2565#endif 2566 } 2567 } 2568 if (someopen) { 2569 sio_timeouts_until_log = hz / sio_timeout; 2570 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2571 sio_timeout); 2572 } else { 2573 /* Flush error messages, if any. */ 2574 sio_timeouts_until_log = 1; 2575 comwakeup((void *)NULL); 2576 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2577 } 2578} 2579 2580static void 2581comwakeup(chan) 2582 void *chan; 2583{ 2584 struct com_s *com; 2585 int unit; 2586 2587 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2588 2589#if 0 2590 /* 2591 * Recover from lost output interrupts. 2592 * Poll any lines that don't use interrupts. 2593 */ 2594 for (unit = 0; unit < NSIO; ++unit) { 2595 com = com_addr(unit); 2596 if (com != NULL 2597 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2598 disable_intr(); 2599 siointr1(com); 2600 enable_intr(); 2601 } 2602 } 2603#endif 2604 2605 /* 2606 * Check for and log errors, but not too often. 2607 */ 2608 if (--sio_timeouts_until_log > 0) 2609 return; 2610 sio_timeouts_until_log = hz / sio_timeout; 2611 for (unit = 0; unit < NSIO; ++unit) { 2612 int errnum; 2613 2614 com = com_addr(unit); 2615 if (com == NULL) 2616 continue; 2617 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2618 u_int delta; 2619 u_long total; 2620 2621 disable_intr(); 2622 delta = com->delta_error_counts[errnum]; 2623 com->delta_error_counts[errnum] = 0; 2624 enable_intr(); 2625 if (delta == 0) 2626 continue; 2627 total = com->error_counts[errnum] += delta; 2628 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2629 unit, delta, error_desc[errnum], 2630 delta == 1 ? "" : "s", total); 2631 } 2632 } 2633} 2634 2635static void 2636disc_optim(tp, t, com) 2637 struct tty *tp; 2638 struct termios *t; 2639 struct com_s *com; 2640{ 2641#ifndef SOFT_HOTCHAR 2642 u_char opt; 2643#endif 2644 2645 /* 2646 * XXX can skip a lot more cases if Smarts. Maybe 2647 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2648 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2649 */ 2650 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2651 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2652 && (!(t->c_iflag & PARMRK) 2653 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2654 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2655 && linesw[tp->t_line].l_rint == ttyinput) 2656 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2657 else 2658 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2659 com->hotchar = linesw[tp->t_line].l_hotchar; 2660#ifndef SOFT_HOTCHAR 2661 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2662 if (com->hotchar != 0) { 2663 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2664 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2665 opt |= CD1400_COR3_SCD34; 2666 } 2667 if (opt != com->cor[2]) { 2668 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2669 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2670 } 2671#endif 2672} 2673 2674#ifdef Smarts 2675/* standard line discipline input routine */ 2676int 2677cyinput(c, tp) 2678 int c; 2679 struct tty *tp; 2680{ 2681 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2682 * bits, as they are done by the CD1400. Hardly worth the effort, 2683 * given that high-throughput sessions are raw anyhow. 2684 */ 2685} 2686#endif /* Smarts */ 2687 2688static int 2689comspeed(speed, cy_clock, prescaler_io) 2690 speed_t speed; 2691 u_long cy_clock; 2692 int *prescaler_io; 2693{ 2694 int actual; 2695 int error; 2696 int divider; 2697 int prescaler; 2698 int prescaler_unit; 2699 2700 if (speed == 0) 2701 return (0); 2702 if (speed < 0 || speed > 150000) 2703 return (-1); 2704 2705 /* determine which prescaler to use */ 2706 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2707 prescaler_unit--, prescaler >>= 2) { 2708 if (cy_clock / prescaler / speed > 63) 2709 break; 2710 } 2711 2712 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2713 if (divider > 255) 2714 divider = 255; 2715 actual = cy_clock/prescaler/divider; 2716 2717 /* 10 times error in percent: */ 2718 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2719 2720 /* 3.0% max error tolerance */ 2721 if (error < -30 || error > 30) 2722 return (-1); 2723 2724#if 0 2725 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2726 printf("divider = %d (%x)\n", divider, divider); 2727 printf("actual = %d\n", actual); 2728 printf("error = %d\n", error); 2729#endif 2730 2731 *prescaler_io = prescaler_unit; 2732 return (divider); 2733} 2734 2735static void 2736cd1400_channel_cmd(com, cmd) 2737 struct com_s *com; 2738 int cmd; 2739{ 2740 cd1400_channel_cmd_wait(com); 2741 cd_setreg(com, CD1400_CCR, cmd); 2742 cd1400_channel_cmd_wait(com); 2743} 2744 2745static void 2746cd1400_channel_cmd_wait(com) 2747 struct com_s *com; 2748{ 2749 struct timeval start; 2750 struct timeval tv; 2751 long usec; 2752 2753 if (cd_getreg(com, CD1400_CCR) == 0) 2754 return; 2755 microtime(&start); 2756 for (;;) { 2757 if (cd_getreg(com, CD1400_CCR) == 0) 2758 return; 2759 microtime(&tv); 2760 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2761 tv.tv_usec - start.tv_usec; 2762 if (usec >= 5000) { 2763 log(LOG_ERR, 2764 "cy%d: channel command timeout (%ld usec)\n", 2765 com->unit, usec); 2766 return; 2767 } 2768 } 2769} 2770 2771static void 2772cd_etc(com, etc) 2773 struct com_s *com; 2774 int etc; 2775{ 2776 /* 2777 * We can't change the hardware's ETC state while there are any 2778 * characters in the tx fifo, since those characters would be 2779 * interpreted as commands! Unputting characters from the fifo 2780 * is difficult, so we wait up to 12 character times for the fifo 2781 * to drain. The command will be delayed for up to 2 character 2782 * times for the tx to become empty. Unputting characters from 2783 * the tx holding and shift registers is impossible, so we wait 2784 * for the tx to become empty so that the command is sure to be 2785 * executed soon after we issue it. 2786 */ 2787 disable_intr(); 2788 if (com->etc == etc) { 2789 enable_intr(); 2790 goto wait; 2791 } 2792 if ((etc == CD1400_ETC_SENDBREAK 2793 && (com->etc == ETC_BREAK_STARTING 2794 || com->etc == ETC_BREAK_STARTED)) 2795 || (etc == CD1400_ETC_STOPBREAK 2796 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2797 || com->etc == ETC_NONE))) { 2798 enable_intr(); 2799 return; 2800 } 2801 com->etc = etc; 2802 cd_setreg(com, CD1400_SRER, 2803 com->intr_enable 2804 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2805 enable_intr(); 2806wait: 2807 while (com->etc == etc 2808 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2809 continue; 2810} 2811 2812static int 2813cd_getreg(com, reg) 2814 struct com_s *com; 2815 int reg; 2816{ 2817 struct com_s *basecom; 2818 u_char car; 2819 int cy_align; 2820 u_long ef; 2821 cy_addr iobase; 2822 int val; 2823 2824 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2825 car = com->unit & CD1400_CAR_CHAN; 2826 cy_align = com->cy_align; 2827 iobase = com->iobase; 2828 ef = read_eflags(); 2829 if (ef & PSL_I) 2830 disable_intr(); 2831 if (basecom->car != car) 2832 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2833 val = cd_inb(iobase, reg, cy_align); 2834 if (ef & PSL_I) 2835 enable_intr(); 2836 return (val); 2837} 2838 2839static void 2840cd_setreg(com, reg, val) 2841 struct com_s *com; 2842 int reg; 2843 int val; 2844{ 2845 struct com_s *basecom; 2846 u_char car; 2847 int cy_align; 2848 u_long ef; 2849 cy_addr iobase; 2850 2851 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2852 car = com->unit & CD1400_CAR_CHAN; 2853 cy_align = com->cy_align; 2854 iobase = com->iobase; 2855 ef = read_eflags(); 2856 if (ef & PSL_I) 2857 disable_intr(); 2858 if (basecom->car != car) 2859 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2860 cd_outb(iobase, reg, cy_align, val); 2861 if (ef & PSL_I) 2862 enable_intr(); 2863} 2864 2865#ifdef CyDebug 2866/* useful in ddb */ 2867void 2868cystatus(unit) 2869 int unit; 2870{ 2871 struct com_s *com; 2872 cy_addr iobase; 2873 u_int ocount; 2874 struct tty *tp; 2875 2876 com = com_addr(unit); 2877 printf("info for channel %d\n", unit); 2878 printf("------------------\n"); 2879 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2880 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2881 if (com == NULL) 2882 return; 2883 iobase = com->iobase; 2884 printf("\n"); 2885 printf("cd1400 base address:\\tt%p\n", iobase); 2886 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2887 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2888 com->cor[0], com->cor[1], com->cor[2]); 2889 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2890 cd_getreg(com, CD1400_SRER), com->intr_enable); 2891 printf("service request register:\t0x%02x\n", 2892 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2893 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2894 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2895 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2896 cd_inb(iobase, CD1400_RIR, com->cy_align), 2897 cd_inb(iobase, CD1400_TIR, com->cy_align), 2898 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2899 printf("\n"); 2900 printf("com state:\t\t\t0x%02x\n", com->state); 2901 printf("calls to comstart():\t\t%d (%d useful)\n", 2902 com->start_count, com->start_real); 2903 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2904 ocount = 0; 2905 if (com->obufs[0].l_queued) 2906 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2907 if (com->obufs[1].l_queued) 2908 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2909 printf("tx buffer chars:\t\t%u\n", ocount); 2910 printf("received chars:\t\t\t%d\n", com->bytes_in); 2911 printf("received exceptions:\t\t%d\n", com->recv_exception); 2912 printf("modem signal deltas:\t\t%d\n", com->mdm); 2913 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2914 printf("\n"); 2915 tp = com->tp; 2916 if (tp != NULL) { 2917 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2918 printf( 2919 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2920 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2921 } else 2922 printf("tty state:\t\t\tclosed\n"); 2923} 2924#endif /* CyDebug */
| 2457static int 2458commctl(com, bits, how) 2459 struct com_s *com; 2460 int bits; 2461 int how; 2462{ 2463 int mcr; 2464 int msr; 2465 2466 if (how == DMGET) { 2467 if (com->channel_control & CD1400_CCR_RCVEN) 2468 bits |= TIOCM_LE; 2469 mcr = com->mcr_image; 2470 if (mcr & com->mcr_dtr) 2471 bits |= TIOCM_DTR; 2472 if (mcr & com->mcr_rts) 2473 /* XXX wired on for Cyclom-8Ys */ 2474 bits |= TIOCM_RTS; 2475 2476 /* 2477 * We must read the modem status from the hardware because 2478 * we don't generate modem status change interrupts for all 2479 * changes, so com->prev_modem_status is not guaranteed to 2480 * be up to date. This is safe, unlike for sio, because 2481 * reading the status register doesn't clear pending modem 2482 * status change interrupts. 2483 */ 2484 msr = cd_getreg(com, CD1400_MSVR2); 2485 2486 if (msr & MSR_CTS) 2487 bits |= TIOCM_CTS; 2488 if (msr & MSR_DCD) 2489 bits |= TIOCM_CD; 2490 if (msr & MSR_DSR) 2491 bits |= TIOCM_DSR; 2492 if (msr & MSR_RI) 2493 /* XXX not connected except for Cyclom-16Y? */ 2494 bits |= TIOCM_RI; 2495 return (bits); 2496 } 2497 mcr = 0; 2498 if (bits & TIOCM_DTR) 2499 mcr |= com->mcr_dtr; 2500 if (bits & TIOCM_RTS) 2501 mcr |= com->mcr_rts; 2502 disable_intr(); 2503 switch (how) { 2504 case DMSET: 2505 com->mcr_image = mcr; 2506 cd_setreg(com, CD1400_MSVR1, mcr); 2507 cd_setreg(com, CD1400_MSVR2, mcr); 2508 break; 2509 case DMBIS: 2510 com->mcr_image = mcr = com->mcr_image | mcr; 2511 cd_setreg(com, CD1400_MSVR1, mcr); 2512 cd_setreg(com, CD1400_MSVR2, mcr); 2513 break; 2514 case DMBIC: 2515 com->mcr_image = mcr = com->mcr_image & ~mcr; 2516 cd_setreg(com, CD1400_MSVR1, mcr); 2517 cd_setreg(com, CD1400_MSVR2, mcr); 2518 break; 2519 } 2520 enable_intr(); 2521 return (0); 2522} 2523 2524static void 2525siosettimeout() 2526{ 2527 struct com_s *com; 2528 bool_t someopen; 2529 int unit; 2530 2531 /* 2532 * Set our timeout period to 1 second if no polled devices are open. 2533 * Otherwise set it to max(1/200, 1/hz). 2534 * Enable timeouts iff some device is open. 2535 */ 2536 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2537 sio_timeout = hz; 2538 someopen = FALSE; 2539 for (unit = 0; unit < NSIO; ++unit) { 2540 com = com_addr(unit); 2541 if (com != NULL && com->tp != NULL 2542 && com->tp->t_state & TS_ISOPEN) { 2543 someopen = TRUE; 2544#if 0 2545 if (com->poll || com->poll_output) { 2546 sio_timeout = hz > 200 ? hz / 200 : 1; 2547 break; 2548 } 2549#endif 2550 } 2551 } 2552 if (someopen) { 2553 sio_timeouts_until_log = hz / sio_timeout; 2554 sio_timeout_handle = timeout(comwakeup, (void *)NULL, 2555 sio_timeout); 2556 } else { 2557 /* Flush error messages, if any. */ 2558 sio_timeouts_until_log = 1; 2559 comwakeup((void *)NULL); 2560 untimeout(comwakeup, (void *)NULL, sio_timeout_handle); 2561 } 2562} 2563 2564static void 2565comwakeup(chan) 2566 void *chan; 2567{ 2568 struct com_s *com; 2569 int unit; 2570 2571 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); 2572 2573#if 0 2574 /* 2575 * Recover from lost output interrupts. 2576 * Poll any lines that don't use interrupts. 2577 */ 2578 for (unit = 0; unit < NSIO; ++unit) { 2579 com = com_addr(unit); 2580 if (com != NULL 2581 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { 2582 disable_intr(); 2583 siointr1(com); 2584 enable_intr(); 2585 } 2586 } 2587#endif 2588 2589 /* 2590 * Check for and log errors, but not too often. 2591 */ 2592 if (--sio_timeouts_until_log > 0) 2593 return; 2594 sio_timeouts_until_log = hz / sio_timeout; 2595 for (unit = 0; unit < NSIO; ++unit) { 2596 int errnum; 2597 2598 com = com_addr(unit); 2599 if (com == NULL) 2600 continue; 2601 for (errnum = 0; errnum < CE_NTYPES; ++errnum) { 2602 u_int delta; 2603 u_long total; 2604 2605 disable_intr(); 2606 delta = com->delta_error_counts[errnum]; 2607 com->delta_error_counts[errnum] = 0; 2608 enable_intr(); 2609 if (delta == 0) 2610 continue; 2611 total = com->error_counts[errnum] += delta; 2612 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", 2613 unit, delta, error_desc[errnum], 2614 delta == 1 ? "" : "s", total); 2615 } 2616 } 2617} 2618 2619static void 2620disc_optim(tp, t, com) 2621 struct tty *tp; 2622 struct termios *t; 2623 struct com_s *com; 2624{ 2625#ifndef SOFT_HOTCHAR 2626 u_char opt; 2627#endif 2628 2629 /* 2630 * XXX can skip a lot more cases if Smarts. Maybe 2631 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we 2632 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. 2633 */ 2634 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 2635 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 2636 && (!(t->c_iflag & PARMRK) 2637 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 2638 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 2639 && linesw[tp->t_line].l_rint == ttyinput) 2640 tp->t_state |= TS_CAN_BYPASS_L_RINT; 2641 else 2642 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 2643 com->hotchar = linesw[tp->t_line].l_hotchar; 2644#ifndef SOFT_HOTCHAR 2645 opt = com->cor[2] & ~CD1400_COR3_SCD34; 2646 if (com->hotchar != 0) { 2647 cd_setreg(com, CD1400_SCHR3, com->hotchar); 2648 cd_setreg(com, CD1400_SCHR4, com->hotchar); 2649 opt |= CD1400_COR3_SCD34; 2650 } 2651 if (opt != com->cor[2]) { 2652 cd_setreg(com, CD1400_COR3, com->cor[2] = opt); 2653 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); 2654 } 2655#endif 2656} 2657 2658#ifdef Smarts 2659/* standard line discipline input routine */ 2660int 2661cyinput(c, tp) 2662 int c; 2663 struct tty *tp; 2664{ 2665 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK 2666 * bits, as they are done by the CD1400. Hardly worth the effort, 2667 * given that high-throughput sessions are raw anyhow. 2668 */ 2669} 2670#endif /* Smarts */ 2671 2672static int 2673comspeed(speed, cy_clock, prescaler_io) 2674 speed_t speed; 2675 u_long cy_clock; 2676 int *prescaler_io; 2677{ 2678 int actual; 2679 int error; 2680 int divider; 2681 int prescaler; 2682 int prescaler_unit; 2683 2684 if (speed == 0) 2685 return (0); 2686 if (speed < 0 || speed > 150000) 2687 return (-1); 2688 2689 /* determine which prescaler to use */ 2690 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; 2691 prescaler_unit--, prescaler >>= 2) { 2692 if (cy_clock / prescaler / speed > 63) 2693 break; 2694 } 2695 2696 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ 2697 if (divider > 255) 2698 divider = 255; 2699 actual = cy_clock/prescaler/divider; 2700 2701 /* 10 times error in percent: */ 2702 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; 2703 2704 /* 3.0% max error tolerance */ 2705 if (error < -30 || error > 30) 2706 return (-1); 2707 2708#if 0 2709 printf("prescaler = %d (%d)\n", prescaler, prescaler_unit); 2710 printf("divider = %d (%x)\n", divider, divider); 2711 printf("actual = %d\n", actual); 2712 printf("error = %d\n", error); 2713#endif 2714 2715 *prescaler_io = prescaler_unit; 2716 return (divider); 2717} 2718 2719static void 2720cd1400_channel_cmd(com, cmd) 2721 struct com_s *com; 2722 int cmd; 2723{ 2724 cd1400_channel_cmd_wait(com); 2725 cd_setreg(com, CD1400_CCR, cmd); 2726 cd1400_channel_cmd_wait(com); 2727} 2728 2729static void 2730cd1400_channel_cmd_wait(com) 2731 struct com_s *com; 2732{ 2733 struct timeval start; 2734 struct timeval tv; 2735 long usec; 2736 2737 if (cd_getreg(com, CD1400_CCR) == 0) 2738 return; 2739 microtime(&start); 2740 for (;;) { 2741 if (cd_getreg(com, CD1400_CCR) == 0) 2742 return; 2743 microtime(&tv); 2744 usec = 1000000 * (tv.tv_sec - start.tv_sec) + 2745 tv.tv_usec - start.tv_usec; 2746 if (usec >= 5000) { 2747 log(LOG_ERR, 2748 "cy%d: channel command timeout (%ld usec)\n", 2749 com->unit, usec); 2750 return; 2751 } 2752 } 2753} 2754 2755static void 2756cd_etc(com, etc) 2757 struct com_s *com; 2758 int etc; 2759{ 2760 /* 2761 * We can't change the hardware's ETC state while there are any 2762 * characters in the tx fifo, since those characters would be 2763 * interpreted as commands! Unputting characters from the fifo 2764 * is difficult, so we wait up to 12 character times for the fifo 2765 * to drain. The command will be delayed for up to 2 character 2766 * times for the tx to become empty. Unputting characters from 2767 * the tx holding and shift registers is impossible, so we wait 2768 * for the tx to become empty so that the command is sure to be 2769 * executed soon after we issue it. 2770 */ 2771 disable_intr(); 2772 if (com->etc == etc) { 2773 enable_intr(); 2774 goto wait; 2775 } 2776 if ((etc == CD1400_ETC_SENDBREAK 2777 && (com->etc == ETC_BREAK_STARTING 2778 || com->etc == ETC_BREAK_STARTED)) 2779 || (etc == CD1400_ETC_STOPBREAK 2780 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED 2781 || com->etc == ETC_NONE))) { 2782 enable_intr(); 2783 return; 2784 } 2785 com->etc = etc; 2786 cd_setreg(com, CD1400_SRER, 2787 com->intr_enable 2788 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); 2789 enable_intr(); 2790wait: 2791 while (com->etc == etc 2792 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) 2793 continue; 2794} 2795 2796static int 2797cd_getreg(com, reg) 2798 struct com_s *com; 2799 int reg; 2800{ 2801 struct com_s *basecom; 2802 u_char car; 2803 int cy_align; 2804 u_long ef; 2805 cy_addr iobase; 2806 int val; 2807 2808 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2809 car = com->unit & CD1400_CAR_CHAN; 2810 cy_align = com->cy_align; 2811 iobase = com->iobase; 2812 ef = read_eflags(); 2813 if (ef & PSL_I) 2814 disable_intr(); 2815 if (basecom->car != car) 2816 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2817 val = cd_inb(iobase, reg, cy_align); 2818 if (ef & PSL_I) 2819 enable_intr(); 2820 return (val); 2821} 2822 2823static void 2824cd_setreg(com, reg, val) 2825 struct com_s *com; 2826 int reg; 2827 int val; 2828{ 2829 struct com_s *basecom; 2830 u_char car; 2831 int cy_align; 2832 u_long ef; 2833 cy_addr iobase; 2834 2835 basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); 2836 car = com->unit & CD1400_CAR_CHAN; 2837 cy_align = com->cy_align; 2838 iobase = com->iobase; 2839 ef = read_eflags(); 2840 if (ef & PSL_I) 2841 disable_intr(); 2842 if (basecom->car != car) 2843 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); 2844 cd_outb(iobase, reg, cy_align, val); 2845 if (ef & PSL_I) 2846 enable_intr(); 2847} 2848 2849#ifdef CyDebug 2850/* useful in ddb */ 2851void 2852cystatus(unit) 2853 int unit; 2854{ 2855 struct com_s *com; 2856 cy_addr iobase; 2857 u_int ocount; 2858 struct tty *tp; 2859 2860 com = com_addr(unit); 2861 printf("info for channel %d\n", unit); 2862 printf("------------------\n"); 2863 printf("total cyclom service probes:\t%d\n", cy_svrr_probes); 2864 printf("calls to upper layer:\t\t%d\n", cy_timeouts); 2865 if (com == NULL) 2866 return; 2867 iobase = com->iobase; 2868 printf("\n"); 2869 printf("cd1400 base address:\\tt%p\n", iobase); 2870 printf("saved channel_control:\t\t0x%02x\n", com->channel_control); 2871 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", 2872 com->cor[0], com->cor[1], com->cor[2]); 2873 printf("service request enable reg:\t0x%02x (0x%02x cached)\n", 2874 cd_getreg(com, CD1400_SRER), com->intr_enable); 2875 printf("service request register:\t0x%02x\n", 2876 cd_inb(iobase, CD1400_SVRR, com->cy_align)); 2877 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", 2878 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); 2879 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", 2880 cd_inb(iobase, CD1400_RIR, com->cy_align), 2881 cd_inb(iobase, CD1400_TIR, com->cy_align), 2882 cd_inb(iobase, CD1400_MIR, com->cy_align)); 2883 printf("\n"); 2884 printf("com state:\t\t\t0x%02x\n", com->state); 2885 printf("calls to comstart():\t\t%d (%d useful)\n", 2886 com->start_count, com->start_real); 2887 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); 2888 ocount = 0; 2889 if (com->obufs[0].l_queued) 2890 ocount += com->obufs[0].l_tail - com->obufs[0].l_head; 2891 if (com->obufs[1].l_queued) 2892 ocount += com->obufs[1].l_tail - com->obufs[1].l_head; 2893 printf("tx buffer chars:\t\t%u\n", ocount); 2894 printf("received chars:\t\t\t%d\n", com->bytes_in); 2895 printf("received exceptions:\t\t%d\n", com->recv_exception); 2896 printf("modem signal deltas:\t\t%d\n", com->mdm); 2897 printf("transmitted chars:\t\t%d\n", com->bytes_out); 2898 printf("\n"); 2899 tp = com->tp; 2900 if (tp != NULL) { 2901 printf("tty state:\t\t\t0x%08x\n", tp->t_state); 2902 printf( 2903 "upper layer queue lengths:\t%d raw, %d canon, %d output\n", 2904 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); 2905 } else 2906 printf("tty state:\t\t\tclosed\n"); 2907} 2908#endif /* CyDebug */
|