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