FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/cy.c
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: releng/5.1/sys/i386/isa/cy.c 111821 2003-03-03 16:24:47Z phk $
31 */
32
33 #include "opt_compat.h"
34 #include "cy.h"
35
36 /*
37 * TODO:
38 * Atomic COR change.
39 * Consoles.
40 */
41
42 /*
43 * Temporary compile-time configuration options.
44 */
45 #define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2)
46 /* Number of chars in the receiver FIFO before an
47 * an interrupt is generated. Should depend on
48 * line speed. Needs to be about 6 on a 486DX33
49 * for 4 active ports at 115200 bps. Why doesn't
50 * 10 work?
51 */
52 #define PollMode /* Use polling-based irq service routine, not the
53 * hardware svcack lines. Must be defined for
54 * Cyclom-16Y boards. Less efficient for Cyclom-8Ys,
55 * and stops 4 * 115200 bps from working.
56 */
57 #undef Smarts /* Enable slightly more CD1400 intelligence. Mainly
58 * the output CR/LF processing, plus we can avoid a
59 * few checks usually done in ttyinput().
60 *
61 * XXX not fully implemented, and not particularly
62 * worthwhile.
63 */
64 #undef CyDebug /* Include debugging code (not very expensive). */
65
66 /* These will go away. */
67 #undef SOFT_CTS_OFLOW
68 #define SOFT_HOTCHAR
69
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/bus.h>
73 #include <sys/conf.h>
74 #include <sys/fcntl.h>
75 #include <sys/interrupt.h>
76 #include <sys/kernel.h>
77 #include <sys/lock.h>
78 #include <sys/malloc.h>
79 #include <sys/mutex.h>
80 #include <sys/syslog.h>
81 #include <sys/tty.h>
82
83 #include <machine/psl.h>
84
85 #include <i386/isa/isa_device.h>
86 #include <i386/isa/cyreg.h>
87 #include <i386/isa/ic/cd1400.h>
88
89 #ifndef COMPAT_OLDISA
90 #error "The cy device requires the old isa compatibility shims"
91 #endif
92
93 #ifdef SMP
94
95 #include <machine/smptests.h> /** xxx_LOCK */
96
97 #ifdef USE_COMLOCK
98 #define COM_LOCK() mtx_lock_spin(&com_mtx)
99 #define COM_UNLOCK() mtx_unlock_spin(&com_mtx)
100 #else
101 #define COM_LOCK()
102 #define COM_UNLOCK()
103 #endif /* USE_COMLOCK */
104
105 #else /* SMP */
106
107 #define COM_LOCK()
108 #define COM_UNLOCK()
109
110 #endif /* SMP */
111
112 extern 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
221 static 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 */
234 typedef u_char bool_t; /* boolean */
235 typedef u_char volatile *cy_addr;
236
237 /* queue of linear buffers */
238 struct 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 */
246 struct 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. */
346 int cyattach_common(cy_addr cy_iobase, int cy_align);
347 ointhand2_t siointr;
348
349 static int cy_units(cy_addr cy_iobase, int cy_align);
350 static int sioattach(struct isa_device *dev);
351 static void cd1400_channel_cmd(struct com_s *com, int cmd);
352 static void cd1400_channel_cmd_wait(struct com_s *com);
353 static void cd_etc(struct com_s *com, int etc);
354 static int cd_getreg(struct com_s *com, int reg);
355 static void cd_setreg(struct com_s *com, int reg, int val);
356 static timeout_t siodtrwakeup;
357 static void comhardclose(struct com_s *com);
358 static void sioinput(struct com_s *com);
359 #if 0
360 static void siointr1(struct com_s *com);
361 #endif
362 static int commctl(struct com_s *com, int bits, int how);
363 static int comparam(struct tty *tp, struct termios *t);
364 static void siopoll(void *arg);
365 static int sioprobe(struct isa_device *dev);
366 static void siosettimeout(void);
367 static int siosetwater(struct com_s *com, speed_t speed);
368 static int comspeed(speed_t speed, u_long cy_clock, int *prescaler_io);
369 static void comstart(struct tty *tp);
370 static void comstop(struct tty *tp, int rw);
371 static timeout_t comwakeup;
372 static void disc_optim(struct tty *tp, struct termios *t,
373 struct com_s *com);
374
375 #ifdef CyDebug
376 void cystatus(int unit);
377 #endif
378
379 static char driver_name[] = "cy";
380
381 /* table and macro for fast conversion from a unit number to its com struct */
382 static struct com_s *p_com_addr[NSIO];
383 #define com_addr(unit) (p_com_addr[unit])
384
385 struct isa_driver siodriver = {
386 INTR_TYPE_TTY | INTR_FAST,
387 sioprobe,
388 sioattach,
389 driver_name
390 };
391 COMPAT_ISA_DRIVER(cy, cydriver); /* XXX */
392
393 static d_open_t sioopen;
394 static d_close_t sioclose;
395 static d_write_t siowrite;
396 static d_ioctl_t sioioctl;
397
398 #define CDEV_MAJOR 48
399 static 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
412 static int comconsole = -1;
413 static speed_t comdefaultrate = TTYDEF_SPEED;
414 static u_int com_events; /* input chars + weighted output completions */
415 static void *sio_ih;
416 static int sio_timeout;
417 static int sio_timeouts_until_log;
418 static struct callout_handle sio_timeout_handle
419 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
420
421 #ifdef CyDebug
422 static u_int cd_inbs;
423 static u_int cy_inbs;
424 static u_int cd_outbs;
425 static u_int cy_outbs;
426 static u_int cy_svrr_probes;
427 static u_int cy_timeouts;
428 #endif
429
430 static int cy_chip_offset[] = {
431 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
432 };
433 static int cy_nr_cd1400s[NCY];
434 static int cy_total_devices;
435 #undef RxFifoThreshold
436 static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
437
438 static int
439 sioprobe(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
457 static int
458 cy_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
509 static int
510 sioattach(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
533 int
534 cyattach_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
660 static int
661 sioopen(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 */
686 open_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();
837 out:
838 splx(s);
839 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
840 comhardclose(com);
841 return (error);
842 }
843
844 static int
845 sioclose(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
877 static void
878 comhardclose(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
960 static int
961 siowrite(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
994 static void
995 siodtrwakeup(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 */
1010 static void
1011 sioinput(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
1112 void
1113 siointr(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 }
1308 cont:
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 */
1573 terminate_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
1593 static void
1594 siointr1(com)
1595 struct com_s *com;
1596 {
1597 }
1598 #endif
1599
1600 static int
1601 sioioctl(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
1760 static void
1761 siopoll(void *arg)
1762 {
1763 int unit;
1764
1765 #ifdef CyDebug
1766 ++cy_timeouts;
1767 #endif
1768 if (com_events == 0)
1769 return;
1770 repeat:
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
1860 static int
1861 comparam(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
2232 static int
2233 siosetwater(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
2304 static void
2305 comstart(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
2454 static void
2455 comstop(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
2497 static int
2498 commctl(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
2566 static void
2567 siosettimeout()
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
2606 static void
2607 comwakeup(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
2665 static void
2666 disc_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 */
2706 int
2707 cyinput(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
2718 static int
2719 comspeed(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
2765 static void
2766 cd1400_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
2775 static void
2776 cd1400_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
2801 static void
2802 cd_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);
2836 wait:
2837 COM_UNLOCK();
2838 critical_exit();
2839 while (com->etc == etc
2840 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2841 continue;
2842 }
2843
2844 static int
2845 cd_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
2873 static void
2874 cd_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 */
2903 void
2904 cystatus(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 */
Cache object: 19277b2907d344105892c2614fbb8686
|