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