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