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