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