2 * cyclades cyclom-y serial driver
3 * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
5 * Copyright (c) 1993 Andrew Herbert.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
30 * $FreeBSD: src/sys/i386/isa/cy.c,v 1.97.2.2 2001/08/22 13:04:58 bde Exp $
31 * $DragonFly: src/sys/dev/serial/cy/cy.c,v 1.30 2008/10/20 13:16:58 sephe Exp $
34 #include "opt_compat.h"
44 * Temporary compile-time configuration options.
46 #define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2)
47 /* Number of chars in the receiver FIFO before an
48 * an interrupt is generated. Should depend on
49 * line speed. Needs to be about 6 on a 486DX33
50 * for 4 active ports at 115200 bps. Why doesn't
53 #define PollMode /* Use polling-based irq service routine, not the
54 * hardware svcack lines. Must be defined for
55 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys,
56 * and stops 4 * 115200 bps from working.
58 #undef Smarts /* Enable slightly more CD1400 intelligence. Mainly
59 * the output CR/LF processing, plus we can avoid a
60 * few checks usually done in ttyinput().
62 * XXX not fully implemented, and not particularly
65 #undef CyDebug /* Include debugging code (not very expensive). */
67 /* These will go away. */
71 #include <sys/param.h>
72 #include <sys/systm.h>
77 #include <sys/dkstat.h>
78 #include <sys/fcntl.h>
79 #include <sys/interrupt.h>
80 #include <sys/kernel.h>
81 #include <sys/malloc.h>
82 #include <sys/syslog.h>
83 #include <sys/thread2.h>
84 #include <machine/clock.h>
86 #include <machine/lock.h>
88 #include <machine/psl.h>
90 #include <bus/isa/isa_device.h>
92 #include <machine_base/isa/ic/cd1400.h>
95 #define disable_intr() com_lock()
96 #define enable_intr() com_unlock()
98 #define disable_intr() ((void)0)
99 #define enable_intr() ((void)0)
103 * Dictionary so that I can name everything *sio* or *com* to compare with
104 * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to
105 * simplify the comparision. These will go away.
107 #define LSR_BI CD1400_RDSR_BREAK
108 #define LSR_FE CD1400_RDSR_FE
109 #define LSR_OE CD1400_RDSR_OE
110 #define LSR_PE CD1400_RDSR_PE
111 #define MCR_DTR CD1400_MSVR2_DTR
112 #define MCR_RTS CD1400_MSVR1_RTS
113 #define MSR_CTS CD1400_MSVR2_CTS
114 #define MSR_DCD CD1400_MSVR2_CD
115 #define MSR_DSR CD1400_MSVR2_DSR
116 #define MSR_RI CD1400_MSVR2_RI
117 #define NSIO (NCY * CY_MAX_PORTS)
118 #define comconsole cyconsole
119 #define comdefaultrate cydefaultrate
120 #define com_events cy_events
121 #define comhardclose cyhardclose
122 #define commctl cymctl
123 #define comparam cyparam
124 #define comspeed cyspeed
125 #define comstart cystart
126 #define comwakeup cywakeup
127 #define nsio_tty ncy_tty
128 #define p_com_addr p_cy_addr
129 #define sioattach cyattach
130 #define sioclose cyclose
131 #define siodriver cydriver
132 #define siodtrwakeup cydtrwakeup
133 #define sioinput cyinput
134 #define siointr cyintr
135 #define siointr1 cyintr1
136 #define sioioctl cyioctl
137 #define sioopen cyopen
138 #define siopoll cypoll
139 #define sioprobe cyprobe
140 #define siosettimeout cysettimeout
141 #define siosetwater cysetwater
142 #define comstop cystop
143 #define siowrite cywrite
144 #define sio_registered cy_registered
145 #define sio_timeout cy_timeout
146 #define sio_timeout_handle cy_timeout_handle
147 #define sio_timeouts_until_log cy_timeouts_until_log
148 #define sio_tty cy_tty
150 #define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
152 /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
153 #define CD1400_xIVR_CHAN_SHIFT 3
154 #define CD1400_xIVR_CHAN 0x1F
157 * ETC states. com->etc may also contain a hardware ETC command value,
158 * meaning that execution of that command is pending.
160 #define ETC_NONE 0 /* we depend on bzero() setting this */
161 #define ETC_BREAK_STARTING 1
162 #define ETC_BREAK_STARTED 2
163 #define ETC_BREAK_ENDING 3
164 #define ETC_BREAK_ENDED 4
166 #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
168 #define CALLOUT_MASK 0x80
169 #define CONTROL_MASK 0x60
170 #define CONTROL_INIT_STATE 0x20
171 #define CONTROL_LOCK_STATE 0x40
172 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
173 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
175 * Not all of the magic is parametrized in the following macros. 16 and
176 * 0xff are related to the bitfields in a udev_t. CY_MAX_PORTS must be
177 * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work.
179 #define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \
180 | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK))
181 #define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \
182 | (((unit) & 0xff) & ~MINOR_MAGIC_MASK))
186 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
187 * than the other bits so that they can be tested as a group without masking
190 * The following com and tty flags correspond closely:
191 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
193 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart())
194 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam())
195 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam())
196 * TS_FLUSH is not used.
197 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
198 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
200 #define CS_BUSY 0x80 /* output in progress */
201 #define CS_TTGO 0x40 /* output not stopped by XOFF */
202 #define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */
203 #define CS_CHECKMSR 1 /* check of MSR scheduled */
204 #define CS_CTS_OFLOW 2 /* use CTS output flow control */
205 #define CS_DTR_OFF 0x10 /* DTR held off */
206 #define CS_ODONE 4 /* output completed */
207 #define CS_RTS_IFLOW 8 /* use RTS input flow control */
208 #define CSE_ODONE 1 /* output transmitted */
210 static char const * const error_desc
[] = {
213 #define CE_INTERRUPT_BUF_OVERFLOW 1
214 "interrupt-level buffer overflow",
215 #define CE_TTY_BUF_OVERFLOW 2
216 "tty-level buffer overflow",
220 #define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
222 /* types. XXX - should be elsewhere */
223 typedef u_char bool_t
; /* boolean */
224 typedef u_char
volatile *cy_addr
;
226 /* queue of linear buffers */
228 u_char
*l_head
; /* next char to process */
229 u_char
*l_tail
; /* one past the last char to process */
230 struct lbq
*l_next
; /* next in queue */
231 bool_t l_queued
; /* nonzero if queued */
234 /* com device structure */
236 u_char state
; /* miscellaneous flag bits */
237 bool_t active_out
; /* nonzero if the callout device is open */
239 u_char cfcr_image
; /* copy of value written to CFCR */
241 u_char etc
; /* pending Embedded Transmit Command */
242 u_char extra_state
; /* more flag bits, separate for order trick */
244 u_char fifo_image
; /* copy of value written to FIFO */
246 u_char gfrcr_image
; /* copy of value read from GFRCR */
248 bool_t hasfifo
; /* nonzero for 16550 UARTs */
249 bool_t loses_outints
; /* nonzero if device loses output interrupts */
251 u_char mcr_dtr
; /* MCR bit that is wired to DTR */
252 u_char mcr_image
; /* copy of value written to MCR */
253 u_char mcr_rts
; /* MCR bit that is wired to RTS */
256 bool_t multiport
; /* is this unit part of a multiport device? */
257 #endif /* COM_MULTIPORT */
258 bool_t no_irq
; /* nonzero if irq is not attached */
259 bool_t poll
; /* nonzero if polling is required */
260 bool_t poll_output
; /* nonzero if polling for output is required */
262 int unit
; /* unit number */
263 int dtr_wait
; /* time to hold DTR down on close (* 1/hz) */
264 struct callout dtr_ch
;
268 u_int wopeners
; /* # processes waiting for DCD in open() */
271 * The high level of the driver never reads status registers directly
272 * because there would be too many side effects to handle conveniently.
273 * Instead, it reads copies of the registers stored here by the
276 u_char last_modem_status
; /* last MSR read by intr handler */
277 u_char prev_modem_status
; /* last MSR handled by high level */
279 u_char hotchar
; /* ldisc-specific char to be handled ASAP */
280 u_char
*ibuf
; /* start of input buffer */
281 u_char
*ibufend
; /* end of input buffer */
282 u_char
*ibufold
; /* old input buffer, to be freed */
283 u_char
*ihighwater
; /* threshold in input buffer */
284 u_char
*iptr
; /* next free spot in input buffer */
285 int ibufsize
; /* size of ibuf (not include error bytes) */
286 int ierroff
; /* offset of error bytes in ibuf */
288 struct lbq obufq
; /* head of queue of output buffers */
289 struct lbq obufs
[2]; /* output buffers */
291 int cy_align
; /* index for register alignment */
292 cy_addr cy_iobase
; /* base address of this port's cyclom */
293 cy_addr iobase
; /* base address of this port's cd1400 */
294 int mcr_rts_reg
; /* cd1400 reg number of reg holding mcr_rts */
296 struct tty
*tp
; /* cross reference */
299 struct termios it_in
; /* should be in struct tty */
300 struct termios it_out
;
303 struct termios lt_in
; /* should be in struct tty */
304 struct termios lt_out
;
307 bool_t do_dcd_timestamp
;
308 struct timeval timestamp
;
309 struct timeval dcd_timestamp
;
311 u_long bytes_in
; /* statistics */
313 u_int delta_error_counts
[CE_NTYPES
];
314 u_long error_counts
[CE_NTYPES
];
316 u_int recv_exception
; /* exception chars received */
317 u_int mdm
; /* modem signal changes */
319 u_int start_count
; /* no. of calls to comstart() */
320 u_int start_real
; /* no. of calls that did something */
322 u_char car
; /* CD1400 CAR shadow (if first unit in cd) */
323 u_char channel_control
;/* CD1400 CCR control command shadow */
324 u_char cor
[3]; /* CD1400 COR1-3 shadows */
325 u_char intr_enable
; /* CD1400 SRER shadow */
328 * Data area for output buffers. Someday we should build the output
329 * buffer queue without copying data.
335 /* PCI driver entry point. */
336 int cyattach_common (cy_addr cy_iobase
, int cy_align
);
337 void siointr(void *);
339 static int cy_units (cy_addr cy_iobase
, int cy_align
);
340 static int sioattach (struct isa_device
*dev
);
341 static void cd1400_channel_cmd (struct com_s
*com
, int cmd
);
342 static void cd1400_channel_cmd_wait (struct com_s
*com
);
343 static void cd_etc (struct com_s
*com
, int etc
);
344 static int cd_getreg (struct com_s
*com
, int reg
);
345 static void cd_setreg (struct com_s
*com
, int reg
, int val
);
346 static timeout_t siodtrwakeup
;
347 static void comhardclose (struct com_s
*com
);
348 static void sioinput (struct com_s
*com
);
350 static void siointr1 (struct com_s
*com
);
352 static int commctl (struct com_s
*com
, int bits
, int how
);
353 static int comparam (struct tty
*tp
, struct termios
*t
);
354 static inthand2_t siopoll
;
355 static int sioprobe (struct isa_device
*dev
);
356 static void siosettimeout (void);
357 static int siosetwater (struct com_s
*com
, speed_t speed
);
358 static int comspeed (speed_t speed
, u_long cy_clock
,
360 static void comstart (struct tty
*tp
);
361 static void comstop (struct tty
*tp
, int rw
);
362 static timeout_t comwakeup
;
363 static void disc_optim (struct tty
*tp
, struct termios
*t
,
367 void cystatus (int unit
);
370 static char driver_name
[] = "cy";
372 /* table and macro for fast conversion from a unit number to its com struct */
373 static struct com_s
*p_com_addr
[NSIO
];
374 #define com_addr(unit) (p_com_addr[unit])
376 struct isa_driver siodriver
= {
377 sioprobe
, sioattach
, driver_name
380 static d_open_t sioopen
;
381 static d_close_t sioclose
;
382 static d_write_t siowrite
;
383 static d_ioctl_t sioioctl
;
385 #define CDEV_MAJOR 48
386 static struct dev_ops sio_ops
= {
387 { driver_name
, CDEV_MAJOR
, D_TTY
| D_KQFILTER
},
394 .d_kqfilter
= ttykqfilter
397 static int comconsole
= -1;
398 static speed_t comdefaultrate
= TTYDEF_SPEED
;
399 static u_int com_events
; /* input chars + weighted output completions */
400 static bool_t sio_registered
;
401 static int sio_timeout
;
402 static int sio_timeouts_until_log
;
403 static struct callout sio_timeout_handle
;
405 static struct tty
*sio_tty
[NSIO
];
407 static struct tty sio_tty
[NSIO
];
409 static const int nsio_tty
= NSIO
;
412 static u_int cd_inbs
;
413 static u_int cy_inbs
;
414 static u_int cd_outbs
;
415 static u_int cy_outbs
;
416 static u_int cy_svrr_probes
;
417 static u_int cy_timeouts
;
420 static int cy_chip_offset
[] = {
421 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
423 static int cy_nr_cd1400s
[NCY
];
424 static int cy_total_devices
;
425 #undef RxFifoThreshold
426 static int volatile RxFifoThreshold
= (CD1400_RX_FIFO_SIZE
/ 2);
429 sioprobe(struct isa_device
*dev
)
433 iobase
= (cy_addr
)dev
->id_maddr
;
435 /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
436 cy_inb(iobase
, CY16_RESET
, 0); /* XXX? */
437 DELAY(500); /* wait for the board to get its act together */
439 /* this is needed to get the board out of reset */
440 cy_outb(iobase
, CY_CLEAR_INTR
, 0, 0);
443 return (cy_units(iobase
, 0) == 0 ? 0 : -1);
447 cy_units(cy_addr cy_iobase
, int cy_align
)
450 u_char firmware_version
= 0; /* assign to avoid warning */
454 for (cyu
= 0; cyu
< CY_MAX_CD1400s
; ++cyu
) {
455 iobase
= cy_iobase
+ (cy_chip_offset
[cyu
] << cy_align
);
457 /* wait for chip to become ready for new command */
458 for (i
= 0; i
< 10; i
++) {
460 if (!cd_inb(iobase
, CD1400_CCR
, cy_align
))
464 /* clear the GFRCR register */
465 cd_outb(iobase
, CD1400_GFRCR
, cy_align
, 0);
467 /* issue a reset command */
468 cd_outb(iobase
, CD1400_CCR
, cy_align
,
469 CD1400_CCR_CMDRESET
| CD1400_CCR_FULLRESET
);
471 /* wait for the CD1400 to initialize itself */
472 for (i
= 0; i
< 200; i
++) {
475 /* retrieve firmware version */
476 firmware_version
= cd_inb(iobase
, CD1400_GFRCR
,
478 if ((firmware_version
& 0xf0) == 0x40)
483 * Anything in the 0x40-0x4F range is fine.
484 * If one CD1400 is bad then we don't support higher
485 * numbered good ones on this board.
487 if ((firmware_version
& 0xf0) != 0x40)
494 sioattach(struct isa_device
*isdp
)
498 adapter
= cyattach_common((cy_addr
) isdp
->id_maddr
, 0);
504 * This kludge is to allow ISA/PCI device specifications in the
505 * kernel config file to be in any order.
507 if (isdp
->id_unit
!= adapter
) {
508 kprintf("cy%d: attached as cy%d\n", isdp
->id_unit
, adapter
);
509 isdp
->id_unit
= adapter
; /* XXX */
511 isdp
->id_intr
= (inthand2_t
*)siointr
;
512 /* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */
517 cyattach_common(cy_addr cy_iobase
, int cy_align
)
521 u_char firmware_version
;
527 adapter
= cy_total_devices
;
528 if ((u_int
)adapter
>= NCY
) {
530 "cy%d: can't attach adapter: insufficient cy devices configured\n",
534 ncyu
= cy_units(cy_iobase
, cy_align
);
537 cy_nr_cd1400s
[adapter
] = ncyu
;
540 unit
= adapter
* CY_MAX_PORTS
;
541 for (cyu
= 0; cyu
< ncyu
; ++cyu
) {
544 iobase
= (cy_addr
) (cy_iobase
545 + (cy_chip_offset
[cyu
] << cy_align
));
546 firmware_version
= cd_inb(iobase
, CD1400_GFRCR
, cy_align
);
548 /* Set up a receive timeout period of than 1+ ms. */
549 cd_outb(iobase
, CD1400_PPR
, cy_align
,
550 howmany(CY_CLOCK(firmware_version
)
551 / CD1400_PPR_PRESCALER
, 1000));
553 for (cdu
= 0; cdu
< CD1400_NO_OF_CHANNELS
; ++cdu
, ++unit
) {
556 com
= kmalloc(sizeof *com
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
558 callout_init(&com
->dtr_ch
);
559 com
->gfrcr_image
= firmware_version
;
560 if (CY_RTS_DTR_SWAPPED(firmware_version
)) {
561 com
->mcr_dtr
= MCR_RTS
;
562 com
->mcr_rts
= MCR_DTR
;
563 com
->mcr_rts_reg
= CD1400_MSVR2
;
565 com
->mcr_dtr
= MCR_DTR
;
566 com
->mcr_rts
= MCR_RTS
;
567 com
->mcr_rts_reg
= CD1400_MSVR1
;
569 com
->dtr_wait
= 3 * hz
;
570 com
->obufs
[0].l_head
= com
->obuf1
;
571 com
->obufs
[1].l_head
= com
->obuf2
;
573 com
->cy_align
= cy_align
;
574 com
->cy_iobase
= cy_iobase
;
575 com
->iobase
= iobase
;
576 com
->car
= ~CD1400_CAR_CHAN
;
579 * We don't use all the flags from <sys/ttydefaults.h> since they
580 * are only relevant for logins. It's important to have echo off
581 * initially so that the line doesn't start blathering before the
582 * echo flag can be turned off.
584 com
->it_in
.c_iflag
= 0;
585 com
->it_in
.c_oflag
= 0;
586 com
->it_in
.c_cflag
= TTYDEF_CFLAG
;
587 com
->it_in
.c_lflag
= 0;
588 if (unit
== comconsole
) {
589 com
->it_in
.c_iflag
= TTYDEF_IFLAG
;
590 com
->it_in
.c_oflag
= TTYDEF_OFLAG
;
591 com
->it_in
.c_cflag
= TTYDEF_CFLAG
| CLOCAL
;
592 com
->it_in
.c_lflag
= TTYDEF_LFLAG
;
593 com
->lt_out
.c_cflag
= com
->lt_in
.c_cflag
= CLOCAL
;
595 if (siosetwater(com
, com
->it_in
.c_ispeed
) != 0) {
597 kfree(com
, M_DEVBUF
);
601 termioschars(&com
->it_in
);
602 com
->it_in
.c_ispeed
= com
->it_in
.c_ospeed
= comdefaultrate
;
603 com
->it_out
= com
->it_in
;
606 com_addr(unit
) = com
;
609 if (!sio_registered
) {
610 callout_init(&sio_timeout_handle
);
611 register_swi(SWI_TTY
, siopoll
, NULL
, "cy", NULL
);
612 sio_registered
= TRUE
;
614 minorbase
= UNIT_TO_MINOR(unit
);
615 dev_ops_add(&sio_ops
, UNIT_TO_MINOR(-1), minorbase
);
616 make_dev(&sio_ops
, minorbase
,
617 UID_ROOT
, GID_WHEEL
, 0600, "ttyc%r%r", adapter
,
618 unit
% CY_MAX_PORTS
);
619 make_dev(&sio_ops
, minorbase
| CONTROL_INIT_STATE
,
620 UID_ROOT
, GID_WHEEL
, 0600, "ttyic%r%r", adapter
,
621 unit
% CY_MAX_PORTS
);
622 make_dev(&sio_ops
, minorbase
| CONTROL_LOCK_STATE
,
623 UID_ROOT
, GID_WHEEL
, 0600, "ttylc%r%r", adapter
,
624 unit
% CY_MAX_PORTS
);
625 make_dev(&sio_ops
, minorbase
| CALLOUT_MASK
,
626 UID_UUCP
, GID_DIALER
, 0660, "cuac%r%r", adapter
,
627 unit
% CY_MAX_PORTS
);
628 make_dev(&sio_ops
, minorbase
| CALLOUT_MASK
| CONTROL_INIT_STATE
,
629 UID_UUCP
, GID_DIALER
, 0660, "cuaic%r%r", adapter
,
630 unit
% CY_MAX_PORTS
);
631 make_dev(&sio_ops
, minorbase
| CALLOUT_MASK
| CONTROL_LOCK_STATE
,
632 UID_UUCP
, GID_DIALER
, 0660, "cualc%r%r", adapter
,
633 unit
% CY_MAX_PORTS
);
635 /* for(cdu...), for(cyu...) terminating blocks */
639 /* ensure an edge for the next interrupt */
640 cy_outb(cy_iobase
, CY_CLEAR_INTR
, cy_align
, 0);
646 sioopen(struct dev_open_args
*ap
)
648 cdev_t dev
= ap
->a_head
.a_dev
;
656 unit
= MINOR_TO_UNIT(mynor
);
657 if ((u_int
) unit
>= NSIO
|| (com
= com_addr(unit
)) == NULL
)
659 if (mynor
& CONTROL_MASK
)
662 tp
= com
->tp
= sio_tty
[unit
] = ttymalloc(sio_tty
[unit
]);
664 tp
= com
->tp
= &sio_tty
[unit
];
669 * We jump to this label after all non-interrupted sleeps to pick
670 * up any changes of the device state.
673 while (com
->state
& CS_DTR_OFF
) {
674 error
= tsleep(&com
->dtr_wait
, PCATCH
, "cydtr", 0);
678 if (tp
->t_state
& TS_ISOPEN
) {
680 * The device is open, so everything has been initialized.
683 if (mynor
& CALLOUT_MASK
) {
684 if (!com
->active_out
) {
689 if (com
->active_out
) {
690 if (ap
->a_oflags
& O_NONBLOCK
) {
694 error
= tsleep(&com
->active_out
,
701 if (tp
->t_state
& TS_XCLUDE
&&
702 priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0)) {
708 * The device isn't open, so there are no conflicts.
709 * Initialize it. Initialization is done twice in many
710 * cases: to preempt sleeping callin opens if we are
711 * callout, and to complete a callin open after DCD rises.
713 tp
->t_oproc
= comstart
;
714 tp
->t_stop
= comstop
;
715 tp
->t_param
= comparam
;
717 tp
->t_termios
= mynor
& CALLOUT_MASK
718 ? com
->it_out
: com
->it_in
;
720 /* Encode per-board unit in LIVR for access in intr routines. */
721 cd_setreg(com
, CD1400_LIVR
,
722 (unit
& CD1400_xIVR_CHAN
) << CD1400_xIVR_CHAN_SHIFT
);
724 (void)commctl(com
, TIOCM_DTR
| TIOCM_RTS
, DMSET
);
726 com
->poll
= com
->no_irq
;
727 com
->poll_output
= com
->loses_outints
;
730 error
= comparam(tp
, &tp
->t_termios
);
737 * (Re)enable and flush fifos.
739 * Certain SMC chips cause problems if the fifos
740 * are enabled while input is ready. Turn off the
741 * fifo if necessary to clear the input. We test
742 * the input ready bit after enabling the fifos
743 * since we've already enabled them in comparam()
744 * and to handle races between enabling and fresh
748 outb(iobase
+ com_fifo
,
749 FIFO_RCV_RST
| FIFO_XMT_RST
752 if (!(inb(com
->line_status_port
) & LSR_RXRDY
))
754 outb(iobase
+ com_fifo
, 0);
756 (void) inb(com
->data_port
);
761 (void) inb(com
->line_status_port
);
762 (void) inb(com
->data_port
);
763 com
->prev_modem_status
= com
->last_modem_status
764 = inb(com
->modem_status_port
);
765 outb(iobase
+ com_ier
, IER_ERXRDY
| IER_ETXRDY
| IER_ERLS
770 * Flush fifos. This requires a full channel reset which
771 * also disables the transmitter and receiver. Recover
774 cd1400_channel_cmd(com
,
775 CD1400_CCR_CMDRESET
| CD1400_CCR_CHANRESET
);
776 cd1400_channel_cmd(com
, com
->channel_control
);
779 com
->prev_modem_status
= com
->last_modem_status
780 = cd_getreg(com
, CD1400_MSVR2
);
781 cd_setreg(com
, CD1400_SRER
,
783 = CD1400_SRER_MDMCH
| CD1400_SRER_RXDATA
);
787 * Handle initial DCD. Callout devices get a fake initial
788 * DCD (trapdoor DCD). If we are callout, then any sleeping
789 * callin opens get woken up and resume sleeping on "cybi"
790 * instead of "cydcd".
793 * XXX `mynor & CALLOUT_MASK' should be
794 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
795 * TRAPDOOR_CARRIER is the default initial state for callout
796 * devices and SOFT_CARRIER is like CLOCAL except it hides
799 if (com
->prev_modem_status
& MSR_DCD
|| mynor
& CALLOUT_MASK
)
800 (*linesw
[tp
->t_line
].l_modem
)(tp
, 1);
803 * Wait for DCD if necessary.
805 if (!(tp
->t_state
& TS_CARR_ON
) && !(mynor
& CALLOUT_MASK
)
806 && !(tp
->t_cflag
& CLOCAL
) && !(ap
->a_oflags
& O_NONBLOCK
)) {
808 error
= tsleep(TSA_CARR_ON(tp
), PCATCH
, "cydcd", 0);
814 error
= (*linesw
[tp
->t_line
].l_open
)(dev
, tp
);
815 disc_optim(tp
, &tp
->t_termios
, com
);
816 if (tp
->t_state
& TS_ISOPEN
&& mynor
& CALLOUT_MASK
)
817 com
->active_out
= TRUE
;
821 if (!(tp
->t_state
& TS_ISOPEN
) && com
->wopeners
== 0)
827 sioclose(struct dev_close_args
*ap
)
829 cdev_t dev
= ap
->a_head
.a_dev
;
835 if (mynor
& CONTROL_MASK
)
837 com
= com_addr(MINOR_TO_UNIT(mynor
));
840 cd_etc(com
, CD1400_ETC_STOPBREAK
);
841 (*linesw
[tp
->t_line
].l_close
)(tp
, ap
->a_fflag
);
842 disc_optim(tp
, &tp
->t_termios
, com
);
843 comstop(tp
, FREAD
| FWRITE
);
848 #ifdef broken /* session holds a ref to the tty; can't deallocate */
850 com
->tp
= sio_tty
[unit
] = NULL
;
856 comhardclose(struct com_s
*com
)
863 iobase
= com
->iobase
;
867 com
->poll_output
= FALSE
;
869 com
->do_timestamp
= 0;
871 outb(iobase
+ com_cfcr
, com
->cfcr_image
&= ~CFCR_SBREAK
);
876 cd_setreg(com
, CD1400_COR2
, com
->cor
[1] &= ~CD1400_COR2_ETC
);
878 cd1400_channel_cmd(com
, CD1400_CCR_CMDRESET
| CD1400_CCR_FTF
);
883 outb(iobase
+ com_ier
, 0);
886 cd_setreg(com
, CD1400_SRER
, com
->intr_enable
= 0);
890 if ((tp
->t_cflag
& HUPCL
)
892 * XXX we will miss any carrier drop between here and the
893 * next open. Perhaps we should watch DCD even when the
894 * port is closed; it is not sufficient to check it at
895 * the next open because it might go up and down while
896 * we're not watching.
899 && !(com
->prev_modem_status
& MSR_DCD
)
900 && !(com
->it_in
.c_cflag
& CLOCAL
))
901 || !(tp
->t_state
& TS_ISOPEN
)) {
902 (void)commctl(com
, TIOCM_DTR
, DMBIC
);
904 /* Disable receiver (leave transmitter enabled). */
905 com
->channel_control
= CD1400_CCR_CMDCHANCTL
908 cd1400_channel_cmd(com
, com
->channel_control
);
910 if (com
->dtr_wait
!= 0 && !(com
->state
& CS_DTR_OFF
)) {
911 callout_reset(&com
->dtr_ch
, com
->dtr_wait
,
913 com
->state
|= CS_DTR_OFF
;
920 * Disable fifos so that they are off after controlled
921 * reboots. Some BIOSes fail to detect 16550s when the
924 outb(iobase
+ com_fifo
, 0);
927 com
->active_out
= FALSE
;
928 wakeup(&com
->active_out
);
929 wakeup(TSA_CARR_ON(tp
)); /* restart any wopeners */
934 siowrite(struct dev_write_args
*ap
)
936 cdev_t dev
= ap
->a_head
.a_dev
;
937 struct uio
*uio
= ap
->a_uio
;
943 if (mynor
& CONTROL_MASK
)
946 unit
= MINOR_TO_UNIT(mynor
);
947 tp
= com_addr(unit
)->tp
;
949 * (XXX) We disallow virtual consoles if the physical console is
950 * a serial port. This is in case there is a display attached that
951 * is not the console. In that situation we don't need/want the X
952 * server taking over the console.
954 if (constty
!= NULL
&& unit
== comconsole
)
957 /* XXX duplicate ttwrite(), but without so much output processing on
958 * CR & LF chars. Hardly worth the effort, given that high-throughput
959 * sessions are raw anyhow.
962 return ((*linesw
[tp
->t_line
].l_write
)(tp
, uio
, ap
->a_ioflag
));
967 siodtrwakeup(void *chan
)
971 com
= (struct com_s
*)chan
;
972 com
->state
&= ~CS_DTR_OFF
;
973 wakeup(&com
->dtr_wait
);
977 sioinput(struct com_s
*com
)
987 if (!(tp
->t_state
& TS_ISOPEN
)) {
988 com_events
-= (com
->iptr
- com
->ibuf
);
989 com
->iptr
= com
->ibuf
;
992 if (tp
->t_state
& TS_CAN_BYPASS_L_RINT
) {
994 * Avoid the grotesquely inefficient lineswitch routine
995 * (ttyinput) in "raw" mode. It usually takes about 450
996 * instructions (that's without canonical processing or echo!).
997 * slinput is reasonably fast (usually 40 instructions plus
1002 incc
= com
->iptr
- buf
;
1003 if (tp
->t_rawq
.c_cc
+ incc
> tp
->t_ihiwat
1004 && (com
->state
& CS_RTS_IFLOW
1005 || tp
->t_iflag
& IXOFF
)
1006 && !(tp
->t_state
& TS_TBLOCK
))
1008 com
->delta_error_counts
[CE_TTY_BUF_OVERFLOW
]
1009 += b_to_q((char *)buf
, incc
, &tp
->t_rawq
);
1013 tp
->t_rawcc
+= incc
;
1015 if (tp
->t_state
& TS_TTSTOP
1016 && (tp
->t_iflag
& IXANY
1017 || tp
->t_cc
[VSTART
] == tp
->t_cc
[VSTOP
])) {
1018 tp
->t_state
&= ~TS_TTSTOP
;
1019 tp
->t_lflag
&= ~FLUSHO
;
1023 } while (buf
< com
->iptr
);
1027 line_status
= buf
[com
->ierroff
];
1030 & (LSR_BI
| LSR_FE
| LSR_OE
| LSR_PE
)) {
1031 if (line_status
& LSR_BI
)
1032 recv_data
|= TTY_BI
;
1033 if (line_status
& LSR_FE
)
1034 recv_data
|= TTY_FE
;
1035 if (line_status
& LSR_OE
)
1036 recv_data
|= TTY_OE
;
1037 if (line_status
& LSR_PE
)
1038 recv_data
|= TTY_PE
;
1040 (*linesw
[tp
->t_line
].l_rint
)(recv_data
, tp
);
1042 } while (buf
< com
->iptr
);
1044 com_events
-= (com
->iptr
- com
->ibuf
);
1045 com
->iptr
= com
->ibuf
;
1048 * There is now room for another low-level buffer full of input,
1049 * so enable RTS if it is now disabled and there is room in the
1050 * high-level buffer.
1052 if ((com
->state
& CS_RTS_IFLOW
) && !(com
->mcr_image
& com
->mcr_rts
) &&
1053 !(tp
->t_state
& TS_TBLOCK
))
1055 outb(com
->modem_ctl_port
, com
->mcr_image
|= MCR_RTS
);
1057 cd_setreg(com
, com
->mcr_rts_reg
,
1058 com
->mcr_image
|= com
->mcr_rts
);
1065 int unit
= (int)arg
;
1073 com_lock(); /* XXX could this be placed down lower in the loop? */
1075 baseu
= unit
* CY_MAX_PORTS
;
1076 cy_align
= com_addr(baseu
)->cy_align
;
1077 cy_iobase
= com_addr(baseu
)->cy_iobase
;
1079 /* check each CD1400 in turn */
1080 for (cyu
= 0; cyu
< cy_nr_cd1400s
[unit
]; ++cyu
) {
1081 iobase
= (cy_addr
) (cy_iobase
1082 + (cy_chip_offset
[cyu
] << cy_align
));
1083 /* poll to see if it has any work */
1084 status
= cd_inb(iobase
, CD1400_SVRR
, cy_align
);
1090 /* service requests as appropriate, giving priority to RX */
1091 if (status
& CD1400_SVRR_RXRDY
) {
1103 save_rir
= cd_inb(iobase
, CD1400_RIR
, cy_align
);
1105 /* enter rx service */
1106 cd_outb(iobase
, CD1400_CAR
, cy_align
, save_rir
);
1107 com_addr(baseu
+ cyu
* CD1400_NO_OF_CHANNELS
)->car
1108 = save_rir
& CD1400_CAR_CHAN
;
1110 serv_type
= cd_inb(iobase
, CD1400_RIVR
, cy_align
);
1111 com
= com_addr(baseu
1112 + ((serv_type
>> CD1400_xIVR_CHAN_SHIFT
)
1113 & CD1400_xIVR_CHAN
));
1115 /* ack receive service */
1116 serv_type
= cy_inb(iobase
, CY8_SVCACKR
, cy_align
);
1118 com
= com_addr(baseu
+
1119 + ((serv_type
>> CD1400_xIVR_CHAN_SHIFT
)
1120 & CD1400_xIVR_CHAN
));
1123 if (serv_type
& CD1400_RIVR_EXCEPTION
) {
1124 ++com
->recv_exception
;
1125 line_status
= cd_inb(iobase
, CD1400_RDSR
, cy_align
);
1126 /* break/unnattached error bits or real input? */
1127 recv_data
= cd_inb(iobase
, CD1400_RDSR
, cy_align
);
1128 #ifndef SOFT_HOTCHAR
1129 if (line_status
& CD1400_RDSR_SPECIAL
1130 && com
->hotchar
!= 0)
1133 #if 1 /* XXX "intelligent" PFO error handling would break O error handling */
1134 if (line_status
& (LSR_PE
|LSR_FE
|LSR_BI
)) {
1136 Don't store PE if IGNPAR and BI if IGNBRK,
1137 this hack allows "raw" tty optimization
1138 works even if IGN* is set.
1140 if ( com
->tp
== NULL
1141 || !(com
->tp
->t_state
& TS_ISOPEN
)
1142 || ((line_status
& (LSR_PE
|LSR_FE
))
1143 && (com
->tp
->t_iflag
& IGNPAR
))
1144 || ((line_status
& LSR_BI
)
1145 && (com
->tp
->t_iflag
& IGNBRK
)))
1147 if ( (line_status
& (LSR_PE
|LSR_FE
))
1148 && (com
->tp
->t_state
& TS_CAN_BYPASS_L_RINT
)
1149 && ((line_status
& LSR_FE
)
1150 || ((line_status
& LSR_PE
)
1151 && (com
->tp
->t_iflag
& INPCK
))))
1157 if (com
->hotchar
!= 0 && recv_data
== com
->hotchar
)
1161 if (ioptr
>= com
->ibufend
)
1162 CE_RECORD(com
, CE_INTERRUPT_BUF_OVERFLOW
);
1164 if (com
->do_timestamp
)
1165 microtime(&com
->timestamp
);
1167 ioptr
[0] = recv_data
;
1168 ioptr
[com
->ierroff
] = line_status
;
1169 com
->iptr
= ++ioptr
;
1170 if (ioptr
== com
->ihighwater
1171 && com
->state
& CS_RTS_IFLOW
)
1173 outb(com
->modem_ctl_port
,
1174 com
->mcr_image
&= ~MCR_RTS
);
1176 cd_outb(iobase
, com
->mcr_rts_reg
,
1181 if (line_status
& LSR_OE
)
1182 CE_RECORD(com
, CE_OVERRUN
);
1188 count
= cd_inb(iobase
, CD1400_RDCR
, cy_align
);
1191 com
->bytes_in
+= count
;
1193 ifree
= com
->ibufend
- ioptr
;
1194 if (count
> ifree
) {
1196 com_events
+= ifree
;
1198 if (com
->do_timestamp
)
1199 microtime(&com
->timestamp
);
1201 recv_data
= cd_inb(iobase
,
1205 if (com
->hotchar
!= 0
1210 ioptr
[0] = recv_data
;
1211 ioptr
[com
->ierroff
] = 0;
1213 } while (--ifree
!= 0);
1215 com
->delta_error_counts
1216 [CE_INTERRUPT_BUF_OVERFLOW
] += count
;
1218 recv_data
= cd_inb(iobase
, CD1400_RDSR
,
1221 if (com
->hotchar
!= 0
1222 && recv_data
== com
->hotchar
)
1225 } while (--count
!= 0);
1227 if (com
->do_timestamp
)
1228 microtime(&com
->timestamp
);
1229 if (ioptr
<= com
->ihighwater
1230 && ioptr
+ count
> com
->ihighwater
1231 && com
->state
& CS_RTS_IFLOW
)
1233 outb(com
->modem_ctl_port
,
1234 com
->mcr_image
&= ~MCR_RTS
);
1236 cd_outb(iobase
, com
->mcr_rts_reg
,
1241 com_events
+= count
;
1243 recv_data
= cd_inb(iobase
, CD1400_RDSR
,
1246 if (com
->hotchar
!= 0
1247 && recv_data
== com
->hotchar
)
1250 ioptr
[0] = recv_data
;
1251 ioptr
[com
->ierroff
] = 0;
1253 } while (--count
!= 0);
1259 /* terminate service context */
1261 cd_outb(iobase
, CD1400_RIR
, cy_align
,
1263 & ~(CD1400_RIR_RDIREQ
| CD1400_RIR_RBUSY
));
1265 cd_outb(iobase
, CD1400_EOSRR
, cy_align
, 0);
1268 if (status
& CD1400_SVRR_MDMCH
) {
1270 u_char modem_status
;
1278 save_mir
= cd_inb(iobase
, CD1400_MIR
, cy_align
);
1280 /* enter modem service */
1281 cd_outb(iobase
, CD1400_CAR
, cy_align
, save_mir
);
1282 com_addr(baseu
+ cyu
* CD1400_NO_OF_CHANNELS
)->car
1283 = save_mir
& CD1400_CAR_CHAN
;
1285 com
= com_addr(baseu
+ cyu
* CD1400_NO_OF_CHANNELS
1286 + (save_mir
& CD1400_MIR_CHAN
));
1288 /* ack modem service */
1289 vector
= cy_inb(iobase
, CY8_SVCACKM
, cy_align
);
1291 com
= com_addr(baseu
1292 + ((vector
>> CD1400_xIVR_CHAN_SHIFT
)
1293 & CD1400_xIVR_CHAN
));
1296 modem_status
= cd_inb(iobase
, CD1400_MSVR2
, cy_align
);
1297 if (modem_status
!= com
->last_modem_status
) {
1298 if (com
->do_dcd_timestamp
1299 && !(com
->last_modem_status
& MSR_DCD
)
1300 && modem_status
& MSR_DCD
)
1301 microtime(&com
->dcd_timestamp
);
1304 * Schedule high level to handle DCD changes. Note
1305 * that we don't use the delta bits anywhere. Some
1306 * UARTs mess them up, and it's easy to remember the
1307 * previous bits and calculate the delta.
1309 com
->last_modem_status
= modem_status
;
1310 if (!(com
->state
& CS_CHECKMSR
)) {
1311 com_events
+= LOTS_OF_EVENTS
;
1312 com
->state
|= CS_CHECKMSR
;
1316 #ifdef SOFT_CTS_OFLOW
1317 /* handle CTS change immediately for crisp flow ctl */
1318 if (com
->state
& CS_CTS_OFLOW
) {
1319 if (modem_status
& MSR_CTS
) {
1320 com
->state
|= CS_ODEVREADY
;
1321 if (com
->state
>= (CS_BUSY
| CS_TTGO
1323 && !(com
->intr_enable
1324 & CD1400_SRER_TXRDY
))
1325 cd_outb(iobase
, CD1400_SRER
,
1329 & ~CD1400_SRER_TXMPTY
1330 | CD1400_SRER_TXRDY
);
1332 com
->state
&= ~CS_ODEVREADY
;
1333 if (com
->intr_enable
1334 & CD1400_SRER_TXRDY
)
1335 cd_outb(iobase
, CD1400_SRER
,
1339 & ~CD1400_SRER_TXRDY
1340 | CD1400_SRER_TXMPTY
);
1346 /* terminate service context */
1348 cd_outb(iobase
, CD1400_MIR
, cy_align
,
1350 & ~(CD1400_MIR_RDIREQ
| CD1400_MIR_RBUSY
));
1352 cd_outb(iobase
, CD1400_EOSRR
, cy_align
, 0);
1355 if (status
& CD1400_SVRR_TXRDY
) {
1364 save_tir
= cd_inb(iobase
, CD1400_TIR
, cy_align
);
1366 /* enter tx service */
1367 cd_outb(iobase
, CD1400_CAR
, cy_align
, save_tir
);
1368 com_addr(baseu
+ cyu
* CD1400_NO_OF_CHANNELS
)->car
1369 = save_tir
& CD1400_CAR_CHAN
;
1371 com
= com_addr(baseu
1372 + cyu
* CD1400_NO_OF_CHANNELS
1373 + (save_tir
& CD1400_TIR_CHAN
));
1375 /* ack transmit service */
1376 vector
= cy_inb(iobase
, CY8_SVCACKT
, cy_align
);
1378 com
= com_addr(baseu
1379 + ((vector
>> CD1400_xIVR_CHAN_SHIFT
)
1380 & CD1400_xIVR_CHAN
));
1383 if (com
->etc
!= ETC_NONE
) {
1384 if (com
->intr_enable
& CD1400_SRER_TXRDY
) {
1386 * Here due to sloppy SRER_TXRDY
1387 * enabling. Ignore. Come back when
1390 cd_outb(iobase
, CD1400_SRER
, cy_align
,
1393 & ~CD1400_SRER_TXRDY
)
1394 | CD1400_SRER_TXMPTY
);
1395 goto terminate_tx_service
;
1398 case CD1400_ETC_SENDBREAK
:
1399 case CD1400_ETC_STOPBREAK
:
1401 * Start the command. Come back on
1402 * next tx empty interrupt, hopefully
1403 * after command has been executed.
1405 cd_outb(iobase
, CD1400_COR2
, cy_align
,
1406 com
->cor
[1] |= CD1400_COR2_ETC
);
1407 cd_outb(iobase
, CD1400_TDR
, cy_align
,
1409 cd_outb(iobase
, CD1400_TDR
, cy_align
,
1411 if (com
->etc
== CD1400_ETC_SENDBREAK
)
1412 com
->etc
= ETC_BREAK_STARTING
;
1414 com
->etc
= ETC_BREAK_ENDING
;
1415 goto terminate_tx_service
;
1416 case ETC_BREAK_STARTING
:
1418 * BREAK is now on. Continue with
1419 * SRER_TXMPTY processing, hopefully
1422 com
->etc
= ETC_BREAK_STARTED
;
1424 case ETC_BREAK_STARTED
:
1426 * Came back due to sloppy SRER_TXMPTY
1427 * enabling. Hope again.
1430 case ETC_BREAK_ENDING
:
1432 * BREAK is now off. Continue with
1433 * SRER_TXMPTY processing and don't
1434 * come back. The SWI handler will
1435 * restart tx interrupts if necessary.
1437 cd_outb(iobase
, CD1400_COR2
, cy_align
,
1439 &= ~CD1400_COR2_ETC
);
1440 com
->etc
= ETC_BREAK_ENDED
;
1441 if (!(com
->state
& CS_ODONE
)) {
1442 com_events
+= LOTS_OF_EVENTS
;
1443 com
->state
|= CS_ODONE
;
1447 case ETC_BREAK_ENDED
:
1449 * Shouldn't get here. Hope again.
1454 if (com
->intr_enable
& CD1400_SRER_TXMPTY
) {
1455 if (!(com
->extra_state
& CSE_ODONE
)) {
1456 com_events
+= LOTS_OF_EVENTS
;
1457 com
->extra_state
|= CSE_ODONE
;
1460 cd_outb(iobase
, CD1400_SRER
, cy_align
,
1462 &= ~CD1400_SRER_TXMPTY
);
1463 goto terminate_tx_service
;
1465 if (com
->state
>= (CS_BUSY
| CS_TTGO
| CS_ODEVREADY
)) {
1469 ioptr
= com
->obufq
.l_head
;
1470 ocount
= com
->obufq
.l_tail
- ioptr
;
1471 if (ocount
> CD1400_TX_FIFO_SIZE
)
1472 ocount
= CD1400_TX_FIFO_SIZE
;
1473 com
->bytes_out
+= ocount
;
1475 cd_outb(iobase
, CD1400_TDR
, cy_align
,
1477 while (--ocount
!= 0);
1478 com
->obufq
.l_head
= ioptr
;
1479 if (ioptr
>= com
->obufq
.l_tail
) {
1482 qp
= com
->obufq
.l_next
;
1483 qp
->l_queued
= FALSE
;
1486 com
->obufq
.l_head
= qp
->l_head
;
1487 com
->obufq
.l_tail
= qp
->l_tail
;
1488 com
->obufq
.l_next
= qp
;
1490 /* output just completed */
1491 com
->state
&= ~CS_BUSY
;
1494 * The setting of CSE_ODONE may be
1495 * stale here. We currently only
1496 * use it when CS_BUSY is set, and
1497 * fixing it when we clear CS_BUSY
1500 if (com
->extra_state
& CSE_ODONE
) {
1501 com_events
-= LOTS_OF_EVENTS
;
1502 com
->extra_state
&= ~CSE_ODONE
;
1505 cd_outb(iobase
, CD1400_SRER
, cy_align
,
1508 & ~CD1400_SRER_TXRDY
)
1509 | CD1400_SRER_TXMPTY
);
1511 if (!(com
->state
& CS_ODONE
)) {
1512 com_events
+= LOTS_OF_EVENTS
;
1513 com
->state
|= CS_ODONE
;
1515 /* handle at high level ASAP */
1521 /* terminate service context */
1522 terminate_tx_service
:
1524 cd_outb(iobase
, CD1400_TIR
, cy_align
,
1526 & ~(CD1400_TIR_RDIREQ
| CD1400_TIR_RBUSY
));
1528 cd_outb(iobase
, CD1400_EOSRR
, cy_align
, 0);
1533 /* ensure an edge for the next interrupt */
1534 cy_outb(cy_iobase
, CY_CLEAR_INTR
, cy_align
, 0);
1543 siointr1(struct com_s
*com
)
1549 sioioctl(struct dev_ioctl_args
*ap
)
1551 cdev_t dev
= ap
->a_head
.a_dev
;
1552 caddr_t data
= ap
->a_data
;
1553 u_long cmd
= ap
->a_cmd
;
1558 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1560 struct termios term
;
1564 com
= com_addr(MINOR_TO_UNIT(mynor
));
1565 if (mynor
& CONTROL_MASK
) {
1568 switch (mynor
& CONTROL_MASK
) {
1569 case CONTROL_INIT_STATE
:
1570 ct
= mynor
& CALLOUT_MASK
? &com
->it_out
: &com
->it_in
;
1572 case CONTROL_LOCK_STATE
:
1573 ct
= mynor
& CALLOUT_MASK
? &com
->lt_out
: &com
->lt_in
;
1576 return (ENODEV
); /* /dev/nodev */
1580 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1583 *ct
= *(struct termios
*)data
;
1586 *(struct termios
*)data
= *ct
;
1589 *(int *)data
= TTYDISC
;
1592 bzero(data
, sizeof(struct winsize
));
1599 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1600 term
= tp
->t_termios
;
1602 error
= ttsetcompat(tp
, &cmd
, data
, &term
);
1606 data
= (caddr_t
)&term
;
1608 if (cmd
== TIOCSETA
|| cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
) {
1610 struct termios
*dt
= (struct termios
*)data
;
1611 struct termios
*lt
= mynor
& CALLOUT_MASK
1612 ? &com
->lt_out
: &com
->lt_in
;
1614 dt
->c_iflag
= (tp
->t_iflag
& lt
->c_iflag
)
1615 | (dt
->c_iflag
& ~lt
->c_iflag
);
1616 dt
->c_oflag
= (tp
->t_oflag
& lt
->c_oflag
)
1617 | (dt
->c_oflag
& ~lt
->c_oflag
);
1618 dt
->c_cflag
= (tp
->t_cflag
& lt
->c_cflag
)
1619 | (dt
->c_cflag
& ~lt
->c_cflag
);
1620 dt
->c_lflag
= (tp
->t_lflag
& lt
->c_lflag
)
1621 | (dt
->c_lflag
& ~lt
->c_lflag
);
1622 for (cc
= 0; cc
< NCCS
; ++cc
)
1623 if (lt
->c_cc
[cc
] != 0)
1624 dt
->c_cc
[cc
] = tp
->t_cc
[cc
];
1625 if (lt
->c_ispeed
!= 0)
1626 dt
->c_ispeed
= tp
->t_ispeed
;
1627 if (lt
->c_ospeed
!= 0)
1628 dt
->c_ospeed
= tp
->t_ospeed
;
1630 error
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, data
,
1631 ap
->a_fflag
, ap
->a_cred
);
1632 if (error
!= ENOIOCTL
)
1635 error
= ttioctl(tp
, cmd
, data
, ap
->a_fflag
);
1636 disc_optim(tp
, &tp
->t_termios
, com
);
1637 if (error
!= ENOIOCTL
) {
1644 outb(iobase
+ com_cfcr
, com
->cfcr_image
|= CFCR_SBREAK
);
1646 cd_etc(com
, CD1400_ETC_SENDBREAK
);
1651 outb(iobase
+ com_cfcr
, com
->cfcr_image
&= ~CFCR_SBREAK
);
1653 cd_etc(com
, CD1400_ETC_STOPBREAK
);
1657 (void)commctl(com
, TIOCM_DTR
, DMBIS
);
1660 (void)commctl(com
, TIOCM_DTR
, DMBIC
);
1663 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The
1664 * changes get undone on the next call to comparam().
1667 (void)commctl(com
, *(int *)data
, DMSET
);
1670 (void)commctl(com
, *(int *)data
, DMBIS
);
1673 (void)commctl(com
, *(int *)data
, DMBIC
);
1676 *(int *)data
= commctl(com
, 0, DMGET
);
1679 /* must be root since the wait applies to following logins */
1680 error
= priv_check_cred(ap
->a_cred
, PRIV_ROOT
, 0);
1685 com
->dtr_wait
= *(int *)data
* hz
/ 100;
1688 *(int *)data
= com
->dtr_wait
* 100 / hz
;
1691 com
->do_timestamp
= TRUE
;
1692 *(struct timeval
*)data
= com
->timestamp
;
1694 case TIOCDCDTIMESTAMP
:
1695 com
->do_dcd_timestamp
= TRUE
;
1696 *(struct timeval
*)data
= com
->dcd_timestamp
;
1707 siopoll(void *data
, void *frame
)
1714 if (com_events
== 0)
1717 for (unit
= 0; unit
< NSIO
; ++unit
) {
1722 com
= com_addr(unit
);
1728 * XXX forget any events related to closed devices
1729 * (actually never opened devices) so that we don't
1733 incc
= com
->iptr
- com
->ibuf
;
1734 com
->iptr
= com
->ibuf
;
1735 if (com
->state
& CS_CHECKMSR
) {
1736 incc
+= LOTS_OF_EVENTS
;
1737 com
->state
&= ~CS_CHECKMSR
;
1743 "sio%d: %d events for device with no tp\n",
1747 if (com
->iptr
!= com
->ibuf
) {
1752 if (com
->state
& CS_CHECKMSR
) {
1753 u_char delta_modem_status
;
1756 delta_modem_status
= com
->last_modem_status
1757 ^ com
->prev_modem_status
;
1758 com
->prev_modem_status
= com
->last_modem_status
;
1759 com_events
-= LOTS_OF_EVENTS
;
1760 com
->state
&= ~CS_CHECKMSR
;
1762 if (delta_modem_status
& MSR_DCD
)
1763 (*linesw
[tp
->t_line
].l_modem
)
1764 (tp
, com
->prev_modem_status
& MSR_DCD
);
1766 if (com
->extra_state
& CSE_ODONE
) {
1768 com_events
-= LOTS_OF_EVENTS
;
1769 com
->extra_state
&= ~CSE_ODONE
;
1771 if (!(com
->state
& CS_BUSY
)) {
1772 tp
->t_state
&= ~TS_BUSY
;
1775 if (com
->etc
!= ETC_NONE
) {
1776 if (com
->etc
== ETC_BREAK_ENDED
)
1777 com
->etc
= ETC_NONE
;
1781 if (com
->state
& CS_ODONE
) {
1783 com_events
-= LOTS_OF_EVENTS
;
1784 com
->state
&= ~CS_ODONE
;
1786 (*linesw
[tp
->t_line
].l_start
)(tp
);
1788 if (com_events
== 0)
1791 if (com_events
>= LOTS_OF_EVENTS
)
1796 comparam(struct tty
*tp
, struct termios
*t
)
1812 /* do historical conversions */
1813 if (t
->c_ispeed
== 0)
1814 t
->c_ispeed
= t
->c_ospeed
;
1816 unit
= DEV_TO_UNIT(tp
->t_dev
);
1817 com
= com_addr(unit
);
1819 /* check requested parameters */
1820 cy_clock
= CY_CLOCK(com
->gfrcr_image
);
1821 idivisor
= comspeed(t
->c_ispeed
, cy_clock
, &iprescaler
);
1824 odivisor
= comspeed(t
->c_ospeed
, cy_clock
, &oprescaler
);
1828 /* parameters are OK, convert them to the com struct and the device */
1831 (void)commctl(com
, TIOCM_DTR
, DMBIC
); /* hang up line */
1833 (void)commctl(com
, TIOCM_DTR
, DMBIS
);
1836 * This returns with interrupts disabled so that we can complete
1837 * the speed change atomically.
1839 (void) siosetwater(com
, t
->c_ispeed
);
1841 /* XXX we don't actually change the speed atomically. */
1844 if (idivisor
!= 0) {
1845 cd_setreg(com
, CD1400_RBPR
, idivisor
);
1846 cd_setreg(com
, CD1400_RCOR
, iprescaler
);
1848 if (odivisor
!= 0) {
1849 cd_setreg(com
, CD1400_TBPR
, odivisor
);
1850 cd_setreg(com
, CD1400_TCOR
, oprescaler
);
1856 * transmitter enable (always set)
1859 opt
= CD1400_CCR_CMDCHANCTL
| CD1400_CCR_XMTEN
1860 | (cflag
& CREAD
? CD1400_CCR_RCVEN
: CD1400_CCR_RCVDIS
);
1861 if (opt
!= com
->channel_control
) {
1862 com
->channel_control
= opt
;
1863 cd1400_channel_cmd(com
, opt
);
1867 /* set special chars */
1868 /* XXX if one is _POSIX_VDISABLE, can't use some others */
1869 if (t
->c_cc
[VSTOP
] != _POSIX_VDISABLE
)
1870 cd_setreg(com
, CD1400_SCHR1
, t
->c_cc
[VSTOP
]);
1871 if (t
->c_cc
[VSTART
] != _POSIX_VDISABLE
)
1872 cd_setreg(com
, CD1400_SCHR2
, t
->c_cc
[VSTART
]);
1873 if (t
->c_cc
[VINTR
] != _POSIX_VDISABLE
)
1874 cd_setreg(com
, CD1400_SCHR3
, t
->c_cc
[VINTR
]);
1875 if (t
->c_cc
[VSUSP
] != _POSIX_VDISABLE
)
1876 cd_setreg(com
, CD1400_SCHR4
, t
->c_cc
[VSUSP
]);
1880 * set channel option register 1 -
1887 if (cflag
& PARENB
) {
1889 opt
|= CD1400_COR1_PARODD
;
1890 opt
|= CD1400_COR1_PARNORMAL
;
1893 if (!(iflag
& INPCK
))
1894 opt
|= CD1400_COR1_NOINPCK
;
1897 if (cflag
& CSTOPB
) {
1899 opt
|= CD1400_COR1_STOP2
;
1902 switch (cflag
& CSIZE
) {
1905 opt
|= CD1400_COR1_CS5
;
1909 opt
|= CD1400_COR1_CS6
;
1913 opt
|= CD1400_COR1_CS7
;
1917 opt
|= CD1400_COR1_CS8
;
1921 if (opt
!= com
->cor
[0]) {
1922 cor_change
|= CD1400_CCR_COR1
;
1923 cd_setreg(com
, CD1400_COR1
, com
->cor
[0] = opt
);
1927 * Set receive time-out period, normally to max(one char time, 5 ms).
1929 if (t
->c_ispeed
== 0)
1930 itimeout
= cd_getreg(com
, CD1400_RTPR
);
1932 itimeout
= (1000 * bits
+ t
->c_ispeed
- 1) / t
->c_ispeed
;
1938 if (itimeout
< MIN_RTP
)
1941 if (!(t
->c_lflag
& ICANON
) && t
->c_cc
[VMIN
] != 0 && t
->c_cc
[VTIME
] != 0
1942 && t
->c_cc
[VTIME
] * 10 > itimeout
)
1943 itimeout
= t
->c_cc
[VTIME
] * 10;
1946 cd_setreg(com
, CD1400_RTPR
, itimeout
);
1949 * set channel option register 2 -
1955 opt
|= CD1400_COR2_IXANY
;
1957 opt
|= CD1400_COR2_IXOFF
;
1959 #ifndef SOFT_CTS_OFLOW
1960 if (cflag
& CCTS_OFLOW
)
1961 opt
|= CD1400_COR2_CCTS_OFLOW
;
1964 if (opt
!= com
->cor
[1]) {
1965 cor_change
|= CD1400_CCR_COR2
;
1966 cd_setreg(com
, CD1400_COR2
, com
->cor
[1] = opt
);
1971 * set channel option register 3 -
1972 * receiver FIFO interrupt threshold
1975 opt
= RxFifoThreshold
;
1977 if (t
->c_lflag
& ICANON
)
1978 opt
|= CD1400_COR3_SCD34
; /* detect INTR & SUSP chars */
1980 /* detect and transparently handle START and STOP chars */
1981 opt
|= CD1400_COR3_FCT
| CD1400_COR3_SCD12
;
1983 if (opt
!= com
->cor
[2]) {
1984 cor_change
|= CD1400_CCR_COR3
;
1985 cd_setreg(com
, CD1400_COR3
, com
->cor
[2] = opt
);
1988 /* notify the CD1400 if COR1-3 have changed */
1990 cd1400_channel_cmd(com
, CD1400_CCR_CMDCORCHG
| cor_change
);
1993 * set channel option register 4 -
1996 * received exception processing
2000 opt
|= CD1400_COR4_IGNCR
;
2003 * we need a new ttyinput() for this, as we don't want to
2004 * have ICRNL && INLCR being done in both layers, or to have
2005 * synchronisation problems
2008 opt
|= CD1400_COR4_ICRNL
;
2010 opt
|= CD1400_COR4_INLCR
;
2013 opt
|= CD1400_COR4_IGNBRK
| CD1400_COR4_NOBRKINT
;
2015 * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
2016 * so only tell the hardware about -brkint if -parmrk.
2018 if (!(iflag
& (BRKINT
| PARMRK
)))
2019 opt
|= CD1400_COR4_NOBRKINT
;
2021 /* XXX using this "intelligence" breaks reporting of overruns. */
2023 opt
|= CD1400_COR4_PFO_DISCARD
;
2026 opt
|= CD1400_COR4_PFO_ESC
;
2028 opt
|= CD1400_COR4_PFO_NUL
;
2031 opt
|= CD1400_COR4_PFO_EXCEPTION
;
2033 cd_setreg(com
, CD1400_COR4
, opt
);
2036 * set channel option register 5 -
2040 opt
|= CD1400_COR5_ISTRIP
;
2041 if (t
->c_iflag
& IEXTEN
)
2042 /* enable LNEXT (e.g. ctrl-v quoting) handling */
2043 opt
|= CD1400_COR5_LNEXT
;
2045 if (t
->c_oflag
& ONLCR
)
2046 opt
|= CD1400_COR5_ONLCR
;
2047 if (t
->c_oflag
& OCRNL
)
2048 opt
|= CD1400_COR5_OCRNL
;
2050 cd_setreg(com
, CD1400_COR5
, opt
);
2053 * We always generate modem status change interrupts for CD changes.
2054 * Among other things, this is necessary to track TS_CARR_ON for
2055 * pstat to print even when the driver doesn't care. CD changes
2056 * should be rare so interrupts for them are not worth extra code to
2057 * avoid. We avoid interrupts for other modem status changes (except
2058 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
2059 * simplest and best.
2063 * set modem change option register 1
2064 * generate modem interrupts on which 1 -> 0 input transitions
2065 * also controls auto-DTR output flow-control, which we don't use
2067 opt
= CD1400_MCOR1_CDzd
;
2068 #ifdef SOFT_CTS_OFLOW
2069 if (cflag
& CCTS_OFLOW
)
2070 opt
|= CD1400_MCOR1_CTSzd
;
2072 cd_setreg(com
, CD1400_MCOR1
, opt
);
2075 * set modem change option register 2
2076 * generate modem interrupts on specific 0 -> 1 input transitions
2078 opt
= CD1400_MCOR2_CDod
;
2079 #ifdef SOFT_CTS_OFLOW
2080 if (cflag
& CCTS_OFLOW
)
2081 opt
|= CD1400_MCOR2_CTSod
;
2083 cd_setreg(com
, CD1400_MCOR2
, opt
);
2086 * XXX should have done this long ago, but there is too much state
2087 * to change all atomically.
2091 com
->state
&= ~CS_TTGO
;
2092 if (!(tp
->t_state
& TS_TTSTOP
))
2093 com
->state
|= CS_TTGO
;
2094 if (cflag
& CRTS_IFLOW
) {
2095 com
->state
|= CS_RTS_IFLOW
;
2097 * If CS_RTS_IFLOW just changed from off to on, the change
2098 * needs to be propagated to MCR_RTS. This isn't urgent,
2099 * so do it later by calling comstart() instead of repeating
2100 * a lot of code from comstart() here.
2102 } else if (com
->state
& CS_RTS_IFLOW
) {
2103 com
->state
&= ~CS_RTS_IFLOW
;
2105 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS
2106 * on here, since comstart() won't do it later.
2109 outb(com
->modem_ctl_port
, com
->mcr_image
|= MCR_RTS
);
2111 cd_setreg(com
, com
->mcr_rts_reg
,
2112 com
->mcr_image
|= com
->mcr_rts
);
2117 * Set up state to handle output flow control.
2118 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2119 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2121 com
->state
|= CS_ODEVREADY
;
2122 #ifdef SOFT_CTS_OFLOW
2123 com
->state
&= ~CS_CTS_OFLOW
;
2124 if (cflag
& CCTS_OFLOW
) {
2125 com
->state
|= CS_CTS_OFLOW
;
2126 if (!(com
->last_modem_status
& MSR_CTS
))
2127 com
->state
&= ~CS_ODEVREADY
;
2130 /* XXX shouldn't call functions while intrs are disabled. */
2131 disc_optim(tp
, t
, com
);
2134 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2135 * unconditionally, but that defeated the careful discarding of
2136 * stale input in sioopen().
2138 if (com
->state
>= (CS_BUSY
| CS_TTGO
))
2141 if (com
->state
>= (CS_BUSY
| CS_TTGO
| CS_ODEVREADY
)) {
2142 if (!(com
->intr_enable
& CD1400_SRER_TXRDY
))
2143 cd_setreg(com
, CD1400_SRER
,
2145 = (com
->intr_enable
& ~CD1400_SRER_TXMPTY
)
2146 | CD1400_SRER_TXRDY
);
2148 if (com
->intr_enable
& CD1400_SRER_TXRDY
)
2149 cd_setreg(com
, CD1400_SRER
,
2151 = (com
->intr_enable
& ~CD1400_SRER_TXRDY
)
2152 | CD1400_SRER_TXMPTY
);
2158 if (com
->ibufold
!= NULL
) {
2159 kfree(com
->ibufold
, M_DEVBUF
);
2160 com
->ibufold
= NULL
;
2166 siosetwater(struct com_s
*com
, speed_t speed
)
2174 * Make the buffer size large enough to handle a softtty interrupt
2175 * latency of about 2 ticks without loss of throughput or data
2176 * (about 3 ticks if input flow control is not used or not honoured,
2177 * but a bit less for CS5-CS7 modes).
2179 cp4ticks
= speed
/ 10 / hz
* 4;
2180 for (ibufsize
= 128; ibufsize
< cp4ticks
;)
2182 if (ibufsize
== com
->ibufsize
) {
2188 * Allocate input buffer. The extra factor of 2 in the size is
2189 * to allow for an error byte for each input byte.
2191 ibuf
= kmalloc(2 * ibufsize
, M_DEVBUF
, M_WAITOK
);
2193 /* Initialize non-critical variables. */
2194 com
->ibufold
= com
->ibuf
;
2195 com
->ibufsize
= ibufsize
;
2198 tp
->t_ififosize
= 2 * ibufsize
;
2199 tp
->t_ispeedwat
= (speed_t
)-1;
2200 tp
->t_ospeedwat
= (speed_t
)-1;
2204 * Read current input buffer, if any. Continue with interrupts
2208 if (com
->iptr
!= com
->ibuf
)
2212 * Initialize critical variables, including input buffer watermarks.
2213 * The external device is asked to stop sending when the buffer
2214 * exactly reaches high water, or when the high level requests it.
2215 * The high level is notified immediately (rather than at a later
2216 * clock tick) when this watermark is reached.
2217 * The buffer size is chosen so the watermark should almost never
2219 * The low watermark is invisibly 0 since the buffer is always
2220 * emptied all at once.
2222 com
->iptr
= com
->ibuf
= ibuf
;
2223 com
->ibufend
= ibuf
+ ibufsize
;
2224 com
->ierroff
= ibufsize
;
2225 com
->ihighwater
= ibuf
+ 3 * ibufsize
/ 4;
2230 comstart(struct tty
*tp
)
2238 unit
= DEV_TO_UNIT(tp
->t_dev
);
2239 com
= com_addr(unit
);
2248 if (tp
->t_state
& TS_TTSTOP
) {
2249 com
->state
&= ~CS_TTGO
;
2250 if (com
->intr_enable
& CD1400_SRER_TXRDY
)
2251 cd_setreg(com
, CD1400_SRER
,
2253 = (com
->intr_enable
& ~CD1400_SRER_TXRDY
)
2254 | CD1400_SRER_TXMPTY
);
2256 com
->state
|= CS_TTGO
;
2257 if (com
->state
>= (CS_BUSY
| CS_TTGO
| CS_ODEVREADY
)
2258 && !(com
->intr_enable
& CD1400_SRER_TXRDY
))
2259 cd_setreg(com
, CD1400_SRER
,
2261 = (com
->intr_enable
& ~CD1400_SRER_TXMPTY
)
2262 | CD1400_SRER_TXRDY
);
2264 if (tp
->t_state
& TS_TBLOCK
) {
2265 if (com
->mcr_image
& com
->mcr_rts
&& com
->state
& CS_RTS_IFLOW
)
2267 outb(com
->modem_ctl_port
, com
->mcr_image
&= ~MCR_RTS
);
2269 cd_setreg(com
, com
->mcr_rts_reg
,
2270 com
->mcr_image
&= ~com
->mcr_rts
);
2273 if (!(com
->mcr_image
& com
->mcr_rts
)
2274 && com
->iptr
< com
->ihighwater
2275 && com
->state
& CS_RTS_IFLOW
)
2277 outb(com
->modem_ctl_port
, com
->mcr_image
|= MCR_RTS
);
2279 cd_setreg(com
, com
->mcr_rts_reg
,
2280 com
->mcr_image
|= com
->mcr_rts
);
2284 if (tp
->t_state
& (TS_TIMEOUT
| TS_TTSTOP
)) {
2289 if (tp
->t_outq
.c_cc
!= 0) {
2293 if (!com
->obufs
[0].l_queued
) {
2297 com
->obufs
[0].l_tail
2298 = com
->obuf1
+ q_to_b(&tp
->t_outq
, com
->obuf1
,
2300 com
->obufs
[0].l_next
= NULL
;
2301 com
->obufs
[0].l_queued
= TRUE
;
2303 if (com
->state
& CS_BUSY
) {
2304 qp
= com
->obufq
.l_next
;
2305 while ((next
= qp
->l_next
) != NULL
)
2307 qp
->l_next
= &com
->obufs
[0];
2309 com
->obufq
.l_head
= com
->obufs
[0].l_head
;
2310 com
->obufq
.l_tail
= com
->obufs
[0].l_tail
;
2311 com
->obufq
.l_next
= &com
->obufs
[0];
2312 com
->state
|= CS_BUSY
;
2313 if (com
->state
>= (CS_BUSY
| CS_TTGO
2315 cd_setreg(com
, CD1400_SRER
,
2318 & ~CD1400_SRER_TXMPTY
)
2319 | CD1400_SRER_TXRDY
);
2323 if (tp
->t_outq
.c_cc
!= 0 && !com
->obufs
[1].l_queued
) {
2327 com
->obufs
[1].l_tail
2328 = com
->obuf2
+ q_to_b(&tp
->t_outq
, com
->obuf2
,
2330 com
->obufs
[1].l_next
= NULL
;
2331 com
->obufs
[1].l_queued
= TRUE
;
2333 if (com
->state
& CS_BUSY
) {
2334 qp
= com
->obufq
.l_next
;
2335 while ((next
= qp
->l_next
) != NULL
)
2337 qp
->l_next
= &com
->obufs
[1];
2339 com
->obufq
.l_head
= com
->obufs
[1].l_head
;
2340 com
->obufq
.l_tail
= com
->obufs
[1].l_tail
;
2341 com
->obufq
.l_next
= &com
->obufs
[1];
2342 com
->state
|= CS_BUSY
;
2343 if (com
->state
>= (CS_BUSY
| CS_TTGO
2345 cd_setreg(com
, CD1400_SRER
,
2348 & ~CD1400_SRER_TXMPTY
)
2349 | CD1400_SRER_TXRDY
);
2353 tp
->t_state
|= TS_BUSY
;
2361 if (com
->state
>= (CS_BUSY
| CS_TTGO
))
2362 siointr1(com
); /* fake interrupt to start output */
2370 comstop(struct tty
*tp
, int rw
)
2375 com
= com_addr(DEV_TO_UNIT(tp
->t_dev
));
2379 com
->obufs
[0].l_queued
= FALSE
;
2380 com
->obufs
[1].l_queued
= FALSE
;
2381 if (com
->extra_state
& CSE_ODONE
) {
2382 com_events
-= LOTS_OF_EVENTS
;
2383 com
->extra_state
&= ~CSE_ODONE
;
2384 if (com
->etc
!= ETC_NONE
) {
2385 if (com
->etc
== ETC_BREAK_ENDED
)
2386 com
->etc
= ETC_NONE
;
2390 com
->tp
->t_state
&= ~TS_BUSY
;
2391 if (com
->state
& CS_ODONE
)
2392 com_events
-= LOTS_OF_EVENTS
;
2393 com
->state
&= ~(CS_ODONE
| CS_BUSY
);
2396 /* XXX no way to reset only input fifo. */
2397 com_events
-= (com
->iptr
- com
->ibuf
);
2398 com
->iptr
= com
->ibuf
;
2403 if (rw
& FWRITE
&& com
->etc
== ETC_NONE
)
2404 cd1400_channel_cmd(com
, CD1400_CCR_CMDRESET
| CD1400_CCR_FTF
);
2409 commctl(struct com_s
*com
, int bits
, int how
)
2415 if (com
->channel_control
& CD1400_CCR_RCVEN
)
2417 mcr
= com
->mcr_image
;
2418 if (mcr
& com
->mcr_dtr
)
2420 if (mcr
& com
->mcr_rts
)
2421 /* XXX wired on for Cyclom-8Ys */
2425 * We must read the modem status from the hardware because
2426 * we don't generate modem status change interrupts for all
2427 * changes, so com->prev_modem_status is not guaranteed to
2428 * be up to date. This is safe, unlike for sio, because
2429 * reading the status register doesn't clear pending modem
2430 * status change interrupts.
2432 msr
= cd_getreg(com
, CD1400_MSVR2
);
2441 /* XXX not connected except for Cyclom-16Y? */
2446 if (bits
& TIOCM_DTR
)
2447 mcr
|= com
->mcr_dtr
;
2448 if (bits
& TIOCM_RTS
)
2449 mcr
|= com
->mcr_rts
;
2453 com
->mcr_image
= mcr
;
2454 cd_setreg(com
, CD1400_MSVR1
, mcr
);
2455 cd_setreg(com
, CD1400_MSVR2
, mcr
);
2458 com
->mcr_image
= mcr
= com
->mcr_image
| mcr
;
2459 cd_setreg(com
, CD1400_MSVR1
, mcr
);
2460 cd_setreg(com
, CD1400_MSVR2
, mcr
);
2463 com
->mcr_image
= mcr
= com
->mcr_image
& ~mcr
;
2464 cd_setreg(com
, CD1400_MSVR1
, mcr
);
2465 cd_setreg(com
, CD1400_MSVR2
, mcr
);
2480 * Set our timeout period to 1 second if no polled devices are open.
2481 * Otherwise set it to max(1/200, 1/hz).
2482 * Enable timeouts iff some device is open.
2484 callout_stop(&sio_timeout_handle
);
2487 for (unit
= 0; unit
< NSIO
; ++unit
) {
2488 com
= com_addr(unit
);
2489 if (com
!= NULL
&& com
->tp
!= NULL
2490 && com
->tp
->t_state
& TS_ISOPEN
) {
2493 if (com
->poll
|| com
->poll_output
) {
2494 sio_timeout
= hz
> 200 ? hz
/ 200 : 1;
2501 sio_timeouts_until_log
= hz
/ sio_timeout
;
2502 callout_reset(&sio_timeout_handle
, sio_timeout
,
2505 /* Flush error messages, if any. */
2506 sio_timeouts_until_log
= 1;
2508 callout_stop(&sio_timeout_handle
);
2513 comwakeup(void *chan
)
2518 callout_reset(&sio_timeout_handle
, sio_timeout
, comwakeup
, NULL
);
2522 * Recover from lost output interrupts.
2523 * Poll any lines that don't use interrupts.
2525 for (unit
= 0; unit
< NSIO
; ++unit
) {
2526 com
= com_addr(unit
);
2528 && (com
->state
>= (CS_BUSY
| CS_TTGO
) || com
->poll
)) {
2537 * Check for and log errors, but not too often.
2539 if (--sio_timeouts_until_log
> 0)
2541 sio_timeouts_until_log
= hz
/ sio_timeout
;
2542 for (unit
= 0; unit
< NSIO
; ++unit
) {
2545 com
= com_addr(unit
);
2548 for (errnum
= 0; errnum
< CE_NTYPES
; ++errnum
) {
2553 delta
= com
->delta_error_counts
[errnum
];
2554 com
->delta_error_counts
[errnum
] = 0;
2558 total
= com
->error_counts
[errnum
] += delta
;
2559 log(LOG_ERR
, "cy%d: %u more %s%s (total %lu)\n",
2560 unit
, delta
, error_desc
[errnum
],
2561 delta
== 1 ? "" : "s", total
);
2567 disc_optim(struct tty
*tp
, struct termios
*t
, struct com_s
*com
)
2569 #ifndef SOFT_HOTCHAR
2574 * XXX can skip a lot more cases if Smarts. Maybe
2575 * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we
2576 * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state.
2578 if (!(t
->c_iflag
& (ICRNL
| IGNCR
| IMAXBEL
| INLCR
| ISTRIP
| IXON
))
2579 && (!(t
->c_iflag
& BRKINT
) || (t
->c_iflag
& IGNBRK
))
2580 && (!(t
->c_iflag
& PARMRK
)
2581 || (t
->c_iflag
& (IGNPAR
| IGNBRK
)) == (IGNPAR
| IGNBRK
))
2582 && !(t
->c_lflag
& (ECHO
| ICANON
| IEXTEN
| ISIG
| PENDIN
))
2583 && linesw
[tp
->t_line
].l_rint
== ttyinput
)
2584 tp
->t_state
|= TS_CAN_BYPASS_L_RINT
;
2586 tp
->t_state
&= ~TS_CAN_BYPASS_L_RINT
;
2587 com
->hotchar
= linesw
[tp
->t_line
].l_hotchar
;
2588 #ifndef SOFT_HOTCHAR
2589 opt
= com
->cor
[2] & ~CD1400_COR3_SCD34
;
2590 if (com
->hotchar
!= 0) {
2591 cd_setreg(com
, CD1400_SCHR3
, com
->hotchar
);
2592 cd_setreg(com
, CD1400_SCHR4
, com
->hotchar
);
2593 opt
|= CD1400_COR3_SCD34
;
2595 if (opt
!= com
->cor
[2]) {
2596 cd_setreg(com
, CD1400_COR3
, com
->cor
[2] = opt
);
2597 cd1400_channel_cmd(com
, CD1400_CCR_CMDCORCHG
| CD1400_CCR_COR3
);
2603 /* standard line discipline input routine */
2605 cyinput(int c
, struct tty
*tp
)
2607 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
2608 * bits, as they are done by the CD1400. Hardly worth the effort,
2609 * given that high-throughput sessions are raw anyhow.
2615 comspeed(speed_t speed
, u_long cy_clock
, int *prescaler_io
)
2625 if (speed
< 0 || speed
> 150000)
2628 /* determine which prescaler to use */
2629 for (prescaler_unit
= 4, prescaler
= 2048; prescaler_unit
;
2630 prescaler_unit
--, prescaler
>>= 2) {
2631 if (cy_clock
/ prescaler
/ speed
> 63)
2635 divider
= (cy_clock
/ prescaler
* 2 / speed
+ 1) / 2; /* round off */
2638 actual
= cy_clock
/prescaler
/divider
;
2640 /* 10 times error in percent: */
2641 error
= ((actual
- (long)speed
) * 2000 / (long)speed
+ 1) / 2;
2643 /* 3.0% max error tolerance */
2644 if (error
< -30 || error
> 30)
2648 kprintf("prescaler = %d (%d)\n", prescaler
, prescaler_unit
);
2649 kprintf("divider = %d (%x)\n", divider
, divider
);
2650 kprintf("actual = %d\n", actual
);
2651 kprintf("error = %d\n", error
);
2654 *prescaler_io
= prescaler_unit
;
2659 cd1400_channel_cmd(struct com_s
*com
, int cmd
)
2661 cd1400_channel_cmd_wait(com
);
2662 cd_setreg(com
, CD1400_CCR
, cmd
);
2663 cd1400_channel_cmd_wait(com
);
2667 cd1400_channel_cmd_wait(struct com_s
*com
)
2669 struct timeval start
;
2673 if (cd_getreg(com
, CD1400_CCR
) == 0)
2677 if (cd_getreg(com
, CD1400_CCR
) == 0)
2680 usec
= 1000000 * (tv
.tv_sec
- start
.tv_sec
) +
2681 tv
.tv_usec
- start
.tv_usec
;
2684 "cy%d: channel command timeout (%ld usec)\n",
2692 cd_etc(struct com_s
*com
, int etc
)
2695 * We can't change the hardware's ETC state while there are any
2696 * characters in the tx fifo, since those characters would be
2697 * interpreted as commands! Unputting characters from the fifo
2698 * is difficult, so we wait up to 12 character times for the fifo
2699 * to drain. The command will be delayed for up to 2 character
2700 * times for the tx to become empty. Unputting characters from
2701 * the tx holding and shift registers is impossible, so we wait
2702 * for the tx to become empty so that the command is sure to be
2703 * executed soon after we issue it.
2706 if (com
->etc
== etc
) {
2710 if ((etc
== CD1400_ETC_SENDBREAK
2711 && (com
->etc
== ETC_BREAK_STARTING
2712 || com
->etc
== ETC_BREAK_STARTED
))
2713 || (etc
== CD1400_ETC_STOPBREAK
2714 && (com
->etc
== ETC_BREAK_ENDING
|| com
->etc
== ETC_BREAK_ENDED
2715 || com
->etc
== ETC_NONE
))) {
2720 cd_setreg(com
, CD1400_SRER
,
2722 = (com
->intr_enable
& ~CD1400_SRER_TXRDY
) | CD1400_SRER_TXMPTY
);
2725 while (com
->etc
== etc
2726 && tsleep(&com
->etc
, PCATCH
, "cyetc", 0) == 0)
2731 cd_getreg(struct com_s
*com
, int reg
)
2733 struct com_s
*basecom
;
2740 basecom
= com_addr(com
->unit
& ~(CD1400_NO_OF_CHANNELS
- 1));
2741 car
= com
->unit
& CD1400_CAR_CHAN
;
2742 cy_align
= com
->cy_align
;
2743 iobase
= com
->iobase
;
2747 if (basecom
->car
!= car
)
2748 cd_outb(iobase
, CD1400_CAR
, cy_align
, basecom
->car
= car
);
2749 val
= cd_inb(iobase
, reg
, cy_align
);
2756 cd_setreg(struct com_s
*com
, int reg
, int val
)
2758 struct com_s
*basecom
;
2764 basecom
= com_addr(com
->unit
& ~(CD1400_NO_OF_CHANNELS
- 1));
2765 car
= com
->unit
& CD1400_CAR_CHAN
;
2766 cy_align
= com
->cy_align
;
2767 iobase
= com
->iobase
;
2771 if (basecom
->car
!= car
)
2772 cd_outb(iobase
, CD1400_CAR
, cy_align
, basecom
->car
= car
);
2773 cd_outb(iobase
, reg
, cy_align
, val
);
2788 com
= com_addr(unit
);
2789 kprintf("info for channel %d\n", unit
);
2790 kprintf("------------------\n");
2791 kprintf("total cyclom service probes:\t%d\n", cy_svrr_probes
);
2792 kprintf("calls to upper layer:\t\t%d\n", cy_timeouts
);
2795 iobase
= com
->iobase
;
2797 kprintf("cd1400 base address:\\tt%p\n", iobase
);
2798 kprintf("saved channel_control:\t\t0x%02x\n", com
->channel_control
);
2799 kprintf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2800 com
->cor
[0], com
->cor
[1], com
->cor
[2]);
2801 kprintf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2802 cd_getreg(com
, CD1400_SRER
), com
->intr_enable
);
2803 kprintf("service request register:\t0x%02x\n",
2804 cd_inb(iobase
, CD1400_SVRR
, com
->cy_align
));
2805 kprintf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2806 cd_getreg(com
, CD1400_MSVR2
), com
->prev_modem_status
);
2807 kprintf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2808 cd_inb(iobase
, CD1400_RIR
, com
->cy_align
),
2809 cd_inb(iobase
, CD1400_TIR
, com
->cy_align
),
2810 cd_inb(iobase
, CD1400_MIR
, com
->cy_align
));
2812 kprintf("com state:\t\t\t0x%02x\n", com
->state
);
2813 kprintf("calls to comstart():\t\t%d (%d useful)\n",
2814 com
->start_count
, com
->start_real
);
2815 kprintf("rx buffer chars free:\t\t%d\n", com
->iptr
- com
->ibuf
);
2817 if (com
->obufs
[0].l_queued
)
2818 ocount
+= com
->obufs
[0].l_tail
- com
->obufs
[0].l_head
;
2819 if (com
->obufs
[1].l_queued
)
2820 ocount
+= com
->obufs
[1].l_tail
- com
->obufs
[1].l_head
;
2821 kprintf("tx buffer chars:\t\t%u\n", ocount
);
2822 kprintf("received chars:\t\t\t%d\n", com
->bytes_in
);
2823 kprintf("received exceptions:\t\t%d\n", com
->recv_exception
);
2824 kprintf("modem signal deltas:\t\t%d\n", com
->mdm
);
2825 kprintf("transmitted chars:\t\t%d\n", com
->bytes_out
);
2829 kprintf("tty state:\t\t\t0x%08x\n", tp
->t_state
);
2831 "upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2832 tp
->t_rawq
.c_cc
, tp
->t_canq
.c_cc
, tp
->t_outq
.c_cc
);
2834 kprintf("tty state:\t\t\tclosed\n");
2836 #endif /* CyDebug */