FreeBSD/Linux Kernel Cross Reference
sys/dev/cy/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
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: releng/6.0/sys/dev/cy/cy.c 136139 2004-10-05 07:42:19Z phk $");
33
34 #include "opt_compat.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/serial.h>
81 #include <sys/syslog.h>
82 #include <sys/tty.h>
83
84 #include <machine/psl.h>
85
86 #include <dev/ic/cd1400.h>
87
88 #include <dev/cy/cyreg.h>
89 #include <dev/cy/cyvar.h>
90
91 #define NCY 10 /* KLUDGE */
92
93 #define NPORTS (NCY * CY_MAX_PORTS)
94
95 #define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s)
96
97 /* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */
98 #define CD1400_xIVR_CHAN_SHIFT 3
99 #define CD1400_xIVR_CHAN 0x1F
100
101 /*
102 * ETC states. com->etc may also contain a hardware ETC command value,
103 * meaning that execution of that command is pending.
104 */
105 #define ETC_NONE 0 /* we depend on bzero() setting this */
106 #define ETC_BREAK_STARTING 1
107 #define ETC_BREAK_STARTED 2
108 #define ETC_BREAK_ENDING 3
109 #define ETC_BREAK_ENDED 4
110
111 #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
112
113 /*
114 * com state bits.
115 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
116 * than the other bits so that they can be tested as a group without masking
117 * off the low bits.
118 *
119 * The following com and tty flags correspond closely:
120 * CS_BUSY = TS_BUSY (maintained by cystart(), cypoll() and
121 * comstop())
122 * CS_TTGO = ~TS_TTSTOP (maintained by cyparam() and cystart())
123 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by cyparam())
124 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by cyparam())
125 * TS_FLUSH is not used.
126 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
127 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
128 */
129 #define CS_BUSY 0x80 /* output in progress */
130 #define CS_TTGO 0x40 /* output not stopped by XOFF */
131 #define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */
132 #define CS_CHECKMSR 1 /* check of MSR scheduled */
133 #define CS_CTS_OFLOW 2 /* use CTS output flow control */
134 #define CS_ODONE 4 /* output completed */
135 #define CS_RTS_IFLOW 8 /* use RTS input flow control */
136 #define CSE_ODONE 1 /* output transmitted */
137
138 static char const * const error_desc[] = {
139 #define CE_OVERRUN 0
140 "silo overflow",
141 #define CE_INTERRUPT_BUF_OVERFLOW 1
142 "interrupt-level buffer overflow",
143 #define CE_TTY_BUF_OVERFLOW 2
144 "tty-level buffer overflow",
145 };
146
147 #define CE_NTYPES 3
148 #define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
149
150 #ifdef SMP
151 #define COM_LOCK() mtx_lock_spin(&cy_lock)
152 #define COM_UNLOCK() mtx_unlock_spin(&cy_lock)
153 #else
154 #define COM_LOCK()
155 #define COM_UNLOCK()
156 #endif
157
158 /* types. XXX - should be elsewhere */
159 typedef u_char bool_t; /* boolean */
160
161 /* queue of linear buffers */
162 struct lbq {
163 u_char *l_head; /* next char to process */
164 u_char *l_tail; /* one past the last char to process */
165 struct lbq *l_next; /* next in queue */
166 bool_t l_queued; /* nonzero if queued */
167 };
168
169 /* com device structure */
170 struct com_s {
171 u_char state; /* miscellaneous flag bits */
172 u_char etc; /* pending Embedded Transmit Command */
173 u_char extra_state; /* more flag bits, separate for order trick */
174 u_char gfrcr_image; /* copy of value read from GFRCR */
175 u_char mcr_dtr; /* MCR bit that is wired to DTR */
176 u_char mcr_image; /* copy of value written to MCR */
177 u_char mcr_rts; /* MCR bit that is wired to RTS */
178 int unit; /* unit number */
179
180 /*
181 * The high level of the driver never reads status registers directly
182 * because there would be too many side effects to handle conveniently.
183 * Instead, it reads copies of the registers stored here by the
184 * interrupt handler.
185 */
186 u_char last_modem_status; /* last MSR read by intr handler */
187 u_char prev_modem_status; /* last MSR handled by high level */
188
189 u_char *ibuf; /* start of input buffer */
190 u_char *ibufend; /* end of input buffer */
191 u_char *ibufold; /* old input buffer, to be freed */
192 u_char *ihighwater; /* threshold in input buffer */
193 u_char *iptr; /* next free spot in input buffer */
194 int ibufsize; /* size of ibuf (not include error bytes) */
195 int ierroff; /* offset of error bytes in ibuf */
196
197 struct lbq obufq; /* head of queue of output buffers */
198 struct lbq obufs[2]; /* output buffers */
199
200 int cy_align; /* index for register alignment */
201 cy_addr cy_iobase; /* base address of this port's cyclom */
202 cy_addr iobase; /* base address of this port's cd1400 */
203 int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */
204
205 struct tty *tp; /* cross reference */
206
207 u_long bytes_in; /* statistics */
208 u_long bytes_out;
209 u_int delta_error_counts[CE_NTYPES];
210 u_long error_counts[CE_NTYPES];
211
212 u_int recv_exception; /* exception chars received */
213 u_int mdm; /* modem signal changes */
214 #ifdef CyDebug
215 u_int start_count; /* no. of calls to cystart() */
216 u_int start_real; /* no. of calls that did something */
217 #endif
218 u_char car; /* CD1400 CAR shadow (if first unit in cd) */
219 u_char channel_control;/* CD1400 CCR control command shadow */
220 u_char cor[3]; /* CD1400 COR1-3 shadows */
221 u_char intr_enable; /* CD1400 SRER shadow */
222
223 /*
224 * Data area for output buffers. Someday we should build the output
225 * buffer queue without copying data.
226 */
227 u_char obuf1[256];
228 u_char obuf2[256];
229 };
230
231 devclass_t cy_devclass;
232 char cy_driver_name[] = "cy";
233
234 static void cd1400_channel_cmd(struct com_s *com, int cmd);
235 static void cd1400_channel_cmd_wait(struct com_s *com);
236 static void cd_etc(struct com_s *com, int etc);
237 static int cd_getreg(struct com_s *com, int reg);
238 static void cd_setreg(struct com_s *com, int reg, int val);
239 static void cyinput(struct com_s *com);
240 static int cyparam(struct tty *tp, struct termios *t);
241 static void cypoll(void *arg);
242 static void cysettimeout(void);
243 static int cysetwater(struct com_s *com, speed_t speed);
244 static int cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io);
245 static void cystart(struct tty *tp);
246 static void comstop(struct tty *tp, int rw);
247 static timeout_t cywakeup;
248 static void disc_optim(struct tty *tp, struct termios *t,
249 struct com_s *com);
250
251 static t_break_t cybreak;
252 static t_modem_t cymodem;
253 static t_open_t cyopen;
254 static t_close_t cyclose;
255
256 #ifdef CyDebug
257 void cystatus(int unit);
258 #endif
259
260 static struct mtx cy_lock;
261 static int cy_inited;
262
263 /* table and macro for fast conversion from a unit number to its com struct */
264 static struct com_s *p_cy_addr[NPORTS];
265 #define cy_addr(unit) (p_cy_addr[unit])
266
267 static u_int cy_events; /* input chars + weighted output completions */
268 static void *cy_fast_ih;
269 static void *cy_slow_ih;
270 static int cy_timeout;
271 static int cy_timeouts_until_log;
272 static struct callout_handle cy_timeout_handle
273 = CALLOUT_HANDLE_INITIALIZER(&cy_timeout_handle);
274
275 #ifdef CyDebug
276 static u_int cd_inbs;
277 static u_int cy_inbs;
278 static u_int cd_outbs;
279 static u_int cy_outbs;
280 static u_int cy_svrr_probes;
281 static u_int cy_timeouts;
282 #endif
283
284 static int cy_chip_offset[] = {
285 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00,
286 };
287 static int cy_nr_cd1400s[NCY];
288 static int cy_total_devices;
289 #undef RxFifoThreshold
290 static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2);
291
292 int
293 cy_units(cy_addr cy_iobase, int cy_align)
294 {
295 int cyu;
296 u_char firmware_version;
297 int i;
298 cy_addr iobase;
299
300 for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) {
301 iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align);
302
303 /* wait for chip to become ready for new command */
304 for (i = 0; i < 10; i++) {
305 DELAY(50);
306 if (!cd_inb(iobase, CD1400_CCR, cy_align))
307 break;
308 }
309
310 /* clear the GFRCR register */
311 cd_outb(iobase, CD1400_GFRCR, cy_align, 0);
312
313 /* issue a reset command */
314 cd_outb(iobase, CD1400_CCR, cy_align,
315 CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
316
317 /* XXX bogus initialization to avoid a gcc bug/warning. */
318 firmware_version = 0;
319
320 /* wait for the CD1400 to initialize itself */
321 for (i = 0; i < 200; i++) {
322 DELAY(50);
323
324 /* retrieve firmware version */
325 firmware_version = cd_inb(iobase, CD1400_GFRCR,
326 cy_align);
327 if ((firmware_version & 0xf0) == 0x40)
328 break;
329 }
330
331 /*
332 * Anything in the 0x40-0x4F range is fine.
333 * If one CD1400 is bad then we don't support higher
334 * numbered good ones on this board.
335 */
336 if ((firmware_version & 0xf0) != 0x40)
337 break;
338 }
339 return (cyu);
340 }
341
342 void *
343 cyattach_common(cy_addr cy_iobase, int cy_align)
344 {
345 int adapter;
346 int cyu;
347 u_char firmware_version;
348 cy_addr iobase;
349 int ncyu;
350 int unit;
351 struct tty *tp;
352
353 while (cy_inited != 2)
354 if (atomic_cmpset_int(&cy_inited, 0, 1)) {
355 mtx_init(&cy_lock, cy_driver_name, NULL, MTX_SPIN);
356 atomic_store_rel_int(&cy_inited, 2);
357 }
358
359 adapter = cy_total_devices;
360 if ((u_int)adapter >= NCY) {
361 printf(
362 "cy%d: can't attach adapter: insufficient cy devices configured\n",
363 adapter);
364 return (NULL);
365 }
366 ncyu = cy_units(cy_iobase, cy_align);
367 if (ncyu == 0)
368 return (NULL);
369 cy_nr_cd1400s[adapter] = ncyu;
370 cy_total_devices++;
371
372 unit = adapter * CY_MAX_PORTS;
373 for (cyu = 0; cyu < ncyu; ++cyu) {
374 int cdu;
375
376 iobase = (cy_addr) (cy_iobase
377 + (cy_chip_offset[cyu] << cy_align));
378 firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align);
379
380 /* Set up a receive timeout period of than 1+ ms. */
381 cd_outb(iobase, CD1400_PPR, cy_align,
382 howmany(CY_CLOCK(firmware_version)
383 / CD1400_PPR_PRESCALER, 1000));
384
385 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) {
386 struct com_s *com;
387 int s;
388
389 com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO);
390 if (com == NULL)
391 break;
392 com->unit = unit;
393 com->gfrcr_image = firmware_version;
394 if (CY_RTS_DTR_SWAPPED(firmware_version)) {
395 com->mcr_dtr = CD1400_MSVR1_RTS;
396 com->mcr_rts = CD1400_MSVR2_DTR;
397 com->mcr_rts_reg = CD1400_MSVR2;
398 } else {
399 com->mcr_dtr = CD1400_MSVR2_DTR;
400 com->mcr_rts = CD1400_MSVR1_RTS;
401 com->mcr_rts_reg = CD1400_MSVR1;
402 }
403 com->obufs[0].l_head = com->obuf1;
404 com->obufs[1].l_head = com->obuf2;
405
406 com->cy_align = cy_align;
407 com->cy_iobase = cy_iobase;
408 com->iobase = iobase;
409 com->car = ~CD1400_CAR_CHAN;
410
411 tp = com->tp = ttyalloc();
412 tp->t_open = cyopen;
413 tp->t_close = cyclose;
414 tp->t_oproc = cystart;
415 tp->t_stop = comstop;
416 tp->t_param = cyparam;
417 tp->t_break = cybreak;
418 tp->t_modem = cymodem;
419 tp->t_sc = com;
420
421 if (cysetwater(com, tp->t_init_in.c_ispeed) != 0) {
422 free(com, M_DEVBUF);
423 return (NULL);
424 }
425
426 s = spltty();
427 cy_addr(unit) = com;
428 splx(s);
429
430 if (cy_fast_ih == NULL) {
431 swi_add(&tty_ithd, "cy", cypoll, NULL, SWI_TTY, 0,
432 &cy_fast_ih);
433 swi_add(&clk_ithd, "cy", cypoll, NULL, SWI_CLOCK, 0,
434 &cy_slow_ih);
435 }
436 ttycreate(tp, NULL, 0, MINOR_CALLOUT, "c%r%r",
437 adapter, unit % CY_MAX_PORTS);
438 }
439 }
440
441 /* ensure an edge for the next interrupt */
442 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
443
444 return (cy_addr(adapter * CY_MAX_PORTS));
445 }
446
447 static int
448 cyopen(struct tty *tp, struct cdev *dev)
449 {
450 struct com_s *com;
451 int s;
452
453 com = tp->t_sc;
454 s = spltty();
455 /*
456 * We jump to this label after all non-interrupted sleeps to pick
457 * up any changes of the device state.
458 */
459
460 /* Encode per-board unit in LIVR for access in intr routines. */
461 cd_setreg(com, CD1400_LIVR,
462 (com->unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT);
463
464 /*
465 * Flush fifos. This requires a full channel reset which
466 * also disables the transmitter and receiver. Recover
467 * from this.
468 */
469 cd1400_channel_cmd(com,
470 CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET);
471 cd1400_channel_cmd(com, com->channel_control);
472
473 critical_enter();
474 COM_LOCK();
475 com->prev_modem_status = com->last_modem_status
476 = cd_getreg(com, CD1400_MSVR2);
477 cd_setreg(com, CD1400_SRER,
478 com->intr_enable
479 = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
480 COM_UNLOCK();
481 critical_exit();
482 cysettimeout();
483 return (0);
484 }
485
486
487 static void
488 cyclose(struct tty *tp)
489 {
490 cy_addr iobase;
491 struct com_s *com;
492 int s;
493 int unit;
494
495 com = tp->t_sc;
496 unit = com->unit;
497 iobase = com->iobase;
498 s = spltty();
499 /* XXX */
500 critical_enter();
501 COM_LOCK();
502 com->etc = ETC_NONE;
503 cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC);
504 COM_UNLOCK();
505 critical_exit();
506 cd_etc(com, CD1400_ETC_STOPBREAK);
507 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
508
509 {
510 critical_enter();
511 COM_LOCK();
512 cd_setreg(com, CD1400_SRER, com->intr_enable = 0);
513 COM_UNLOCK();
514 critical_exit();
515 tp = com->tp;
516 if ((tp->t_cflag & HUPCL)
517 /*
518 * XXX we will miss any carrier drop between here and the
519 * next open. Perhaps we should watch DCD even when the
520 * port is closed; it is not sufficient to check it at
521 * the next open because it might go up and down while
522 * we're not watching.
523 */
524 || (!tp->t_actout
525 && !(com->prev_modem_status & CD1400_MSVR2_CD)
526 && !(tp->t_init_in.c_cflag & CLOCAL))
527 || !(tp->t_state & TS_ISOPEN)) {
528 (void)cymodem(tp, 0, SER_DTR);
529
530 /* Disable receiver (leave transmitter enabled). */
531 com->channel_control = CD1400_CCR_CMDCHANCTL
532 | CD1400_CCR_XMTEN
533 | CD1400_CCR_RCVDIS;
534 cd1400_channel_cmd(com, com->channel_control);
535
536 ttydtrwaitstart(tp);
537 }
538 }
539 tp->t_actout = FALSE;
540 wakeup(&tp->t_actout);
541 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */
542 splx(s);
543 }
544
545 /*
546 * This function:
547 * a) needs to be called with COM_LOCK() held, and
548 * b) needs to return with COM_LOCK() held.
549 */
550 static void
551 cyinput(struct com_s *com)
552 {
553 u_char *buf;
554 int incc;
555 u_char line_status;
556 int recv_data;
557 struct tty *tp;
558
559 buf = com->ibuf;
560 tp = com->tp;
561 if (!(tp->t_state & TS_ISOPEN)) {
562 cy_events -= (com->iptr - com->ibuf);
563 com->iptr = com->ibuf;
564 return;
565 }
566 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
567 /*
568 * Avoid the grotesquely inefficient lineswitch routine
569 * (ttyinput) in "raw" mode. It usually takes about 450
570 * instructions (that's without canonical processing or echo!).
571 * slinput is reasonably fast (usually 40 instructions plus
572 * call overhead).
573 */
574
575 do {
576 /*
577 * This may look odd, but it is using save-and-enable
578 * semantics instead of the save-and-disable semantics
579 * that are used everywhere else.
580 */
581 COM_UNLOCK();
582 critical_exit();
583 incc = com->iptr - buf;
584 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
585 && (com->state & CS_RTS_IFLOW
586 || tp->t_iflag & IXOFF)
587 && !(tp->t_state & TS_TBLOCK))
588 ttyblock(tp);
589 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
590 += b_to_q((char *)buf, incc, &tp->t_rawq);
591 buf += incc;
592 tk_nin += incc;
593 tk_rawcc += incc;
594 tp->t_rawcc += incc;
595 ttwakeup(tp);
596 if (tp->t_state & TS_TTSTOP
597 && (tp->t_iflag & IXANY
598 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
599 tp->t_state &= ~TS_TTSTOP;
600 tp->t_lflag &= ~FLUSHO;
601 cystart(tp);
602 }
603 critical_enter();
604 COM_LOCK();
605 } while (buf < com->iptr);
606 } else {
607 do {
608 /*
609 * This may look odd, but it is using save-and-enable
610 * semantics instead of the save-and-disable semantics
611 * that are used everywhere else.
612 */
613 COM_UNLOCK();
614 critical_exit();
615 line_status = buf[com->ierroff];
616 recv_data = *buf++;
617 if (line_status
618 & (CD1400_RDSR_BREAK | CD1400_RDSR_FE | CD1400_RDSR_OE | CD1400_RDSR_PE)) {
619 if (line_status & CD1400_RDSR_BREAK)
620 recv_data |= TTY_BI;
621 if (line_status & CD1400_RDSR_FE)
622 recv_data |= TTY_FE;
623 if (line_status & CD1400_RDSR_OE)
624 recv_data |= TTY_OE;
625 if (line_status & CD1400_RDSR_PE)
626 recv_data |= TTY_PE;
627 }
628 ttyld_rint(tp, recv_data);
629 critical_enter();
630 COM_LOCK();
631 } while (buf < com->iptr);
632 }
633 cy_events -= (com->iptr - com->ibuf);
634 com->iptr = com->ibuf;
635
636 /*
637 * There is now room for another low-level buffer full of input,
638 * so enable RTS if it is now disabled and there is room in the
639 * high-level buffer.
640 */
641 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) &&
642 !(tp->t_state & TS_TBLOCK))
643 cd_setreg(com, com->mcr_rts_reg,
644 com->mcr_image |= com->mcr_rts);
645 }
646
647 void
648 cyintr(void *vcom)
649 {
650 struct com_s *basecom;
651 int baseu;
652 int cy_align;
653 cy_addr cy_iobase;
654 int cyu;
655 cy_addr iobase;
656 u_char status;
657 int unit;
658
659 COM_LOCK(); /* XXX could this be placed down lower in the loop? */
660
661 basecom = (struct com_s *)vcom;
662 baseu = basecom->unit;
663 cy_align = basecom->cy_align;
664 cy_iobase = basecom->cy_iobase;
665 unit = baseu / CY_MAX_PORTS;
666
667 /* check each CD1400 in turn */
668 for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) {
669 iobase = (cy_addr) (cy_iobase
670 + (cy_chip_offset[cyu] << cy_align));
671 /* poll to see if it has any work */
672 status = cd_inb(iobase, CD1400_SVRR, cy_align);
673 if (status == 0)
674 continue;
675 #ifdef CyDebug
676 ++cy_svrr_probes;
677 #endif
678 /* service requests as appropriate, giving priority to RX */
679 if (status & CD1400_SVRR_RXRDY) {
680 struct com_s *com;
681 u_int count;
682 u_char *ioptr;
683 u_char line_status;
684 u_char recv_data;
685 u_char serv_type;
686 #ifdef PollMode
687 u_char save_rir;
688 #endif
689
690 #ifdef PollMode
691 save_rir = cd_inb(iobase, CD1400_RIR, cy_align);
692
693 /* enter rx service */
694 cd_outb(iobase, CD1400_CAR, cy_align, save_rir);
695 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
696 = save_rir & CD1400_CAR_CHAN;
697
698 serv_type = cd_inb(iobase, CD1400_RIVR, cy_align);
699 com = cy_addr(baseu
700 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
701 & CD1400_xIVR_CHAN));
702 #else
703 /* ack receive service */
704 serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align);
705
706 com = cy_addr(baseu +
707 + ((serv_type >> CD1400_xIVR_CHAN_SHIFT)
708 & CD1400_xIVR_CHAN));
709 #endif
710
711 if (serv_type & CD1400_RIVR_EXCEPTION) {
712 ++com->recv_exception;
713 line_status = cd_inb(iobase, CD1400_RDSR, cy_align);
714 /* break/unnattached error bits or real input? */
715 recv_data = cd_inb(iobase, CD1400_RDSR, cy_align);
716 #ifndef SOFT_HOTCHAR
717 if (line_status & CD1400_RDSR_SPECIAL
718 && com->tp->t_hotchar != 0)
719 swi_sched(cy_fast_ih, 0);
720
721 #endif
722 #if 1 /* XXX "intelligent" PFO error handling would break O error handling */
723 if (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE|CD1400_RDSR_BREAK)) {
724 /*
725 Don't store PE if IGNPAR and BI if IGNBRK,
726 this hack allows "raw" tty optimization
727 works even if IGN* is set.
728 */
729 if ( com->tp == NULL
730 || !(com->tp->t_state & TS_ISOPEN)
731 || ((line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE))
732 && (com->tp->t_iflag & IGNPAR))
733 || ((line_status & CD1400_RDSR_BREAK)
734 && (com->tp->t_iflag & IGNBRK)))
735 goto cont;
736 if ( (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE))
737 && (com->tp->t_state & TS_CAN_BYPASS_L_RINT)
738 && ((line_status & CD1400_RDSR_FE)
739 || ((line_status & CD1400_RDSR_PE)
740 && (com->tp->t_iflag & INPCK))))
741 recv_data = 0;
742 }
743 #endif /* 1 */
744 ++com->bytes_in;
745 #ifdef SOFT_HOTCHAR
746 if (com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar)
747 swi_sched(cy_fast_ih, 0);
748 #endif
749 ioptr = com->iptr;
750 if (ioptr >= com->ibufend)
751 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
752 else {
753 if (com->tp != NULL && com->tp->t_do_timestamp)
754 microtime(&com->tp->t_timestamp);
755 ++cy_events;
756 ioptr[0] = recv_data;
757 ioptr[com->ierroff] = line_status;
758 com->iptr = ++ioptr;
759 if (ioptr == com->ihighwater
760 && com->state & CS_RTS_IFLOW)
761 cd_outb(iobase, com->mcr_rts_reg,
762 cy_align,
763 com->mcr_image &=
764 ~com->mcr_rts);
765 if (line_status & CD1400_RDSR_OE)
766 CE_RECORD(com, CE_OVERRUN);
767 }
768 goto cont;
769 } else {
770 int ifree;
771
772 count = cd_inb(iobase, CD1400_RDCR, cy_align);
773 if (!count)
774 goto cont;
775 com->bytes_in += count;
776 ioptr = com->iptr;
777 ifree = com->ibufend - ioptr;
778 if (count > ifree) {
779 count -= ifree;
780 cy_events += ifree;
781 if (ifree != 0) {
782 if (com->tp != NULL && com->tp->t_do_timestamp)
783 microtime(&com->tp->t_timestamp);
784 do {
785 recv_data = cd_inb(iobase,
786 CD1400_RDSR,
787 cy_align);
788 #ifdef SOFT_HOTCHAR
789 if (com->tp->t_hotchar != 0
790 && recv_data
791 == com->tp->t_hotchar)
792 swi_sched(cy_fast_ih,
793 0);
794 #endif
795 ioptr[0] = recv_data;
796 ioptr[com->ierroff] = 0;
797 ++ioptr;
798 } while (--ifree != 0);
799 }
800 com->delta_error_counts
801 [CE_INTERRUPT_BUF_OVERFLOW] += count;
802 do {
803 recv_data = cd_inb(iobase, CD1400_RDSR,
804 cy_align);
805 #ifdef SOFT_HOTCHAR
806 if (com->tp->t_hotchar != 0
807 && recv_data == com->tp->t_hotchar)
808 swi_sched(cy_fast_ih, 0);
809 #endif
810 } while (--count != 0);
811 } else {
812 if (com->tp != NULL && com->tp->t_do_timestamp)
813 microtime(&com->tp->t_timestamp);
814 if (ioptr <= com->ihighwater
815 && ioptr + count > com->ihighwater
816 && com->state & CS_RTS_IFLOW)
817 cd_outb(iobase, com->mcr_rts_reg,
818 cy_align,
819 com->mcr_image
820 &= ~com->mcr_rts);
821 cy_events += count;
822 do {
823 recv_data = cd_inb(iobase, CD1400_RDSR,
824 cy_align);
825 #ifdef SOFT_HOTCHAR
826 if (com->tp->t_hotchar != 0
827 && recv_data == com->tp->t_hotchar)
828 swi_sched(cy_fast_ih, 0);
829 #endif
830 ioptr[0] = recv_data;
831 ioptr[com->ierroff] = 0;
832 ++ioptr;
833 } while (--count != 0);
834 }
835 com->iptr = ioptr;
836 }
837 cont:
838
839 /* terminate service context */
840 #ifdef PollMode
841 cd_outb(iobase, CD1400_RIR, cy_align,
842 save_rir
843 & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY));
844 #else
845 cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
846 #endif
847 }
848 if (status & CD1400_SVRR_MDMCH) {
849 struct com_s *com;
850 u_char modem_status;
851 #ifdef PollMode
852 u_char save_mir;
853 #else
854 u_char vector;
855 #endif
856
857 #ifdef PollMode
858 save_mir = cd_inb(iobase, CD1400_MIR, cy_align);
859
860 /* enter modem service */
861 cd_outb(iobase, CD1400_CAR, cy_align, save_mir);
862 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
863 = save_mir & CD1400_CAR_CHAN;
864
865 com = cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS
866 + (save_mir & CD1400_MIR_CHAN));
867 #else
868 /* ack modem service */
869 vector = cy_inb(iobase, CY8_SVCACKM, cy_align);
870
871 com = cy_addr(baseu
872 + ((vector >> CD1400_xIVR_CHAN_SHIFT)
873 & CD1400_xIVR_CHAN));
874 #endif
875 ++com->mdm;
876 modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align);
877 if (modem_status != com->last_modem_status) {
878 /*
879 * Schedule high level to handle DCD changes. Note
880 * that we don't use the delta bits anywhere. Some
881 * UARTs mess them up, and it's easy to remember the
882 * previous bits and calculate the delta.
883 */
884 com->last_modem_status = modem_status;
885 if (!(com->state & CS_CHECKMSR)) {
886 cy_events += LOTS_OF_EVENTS;
887 com->state |= CS_CHECKMSR;
888 swi_sched(cy_fast_ih, 0);
889 }
890
891 #ifdef SOFT_CTS_OFLOW
892 /* handle CTS change immediately for crisp flow ctl */
893 if (com->state & CS_CTS_OFLOW) {
894 if (modem_status & CD1400_MSVR2_CTS) {
895 com->state |= CS_ODEVREADY;
896 if (com->state >= (CS_BUSY | CS_TTGO
897 | CS_ODEVREADY)
898 && !(com->intr_enable
899 & CD1400_SRER_TXRDY))
900 cd_outb(iobase, CD1400_SRER,
901 cy_align,
902 com->intr_enable
903 = com->intr_enable
904 & ~CD1400_SRER_TXMPTY
905 | CD1400_SRER_TXRDY);
906 } else {
907 com->state &= ~CS_ODEVREADY;
908 if (com->intr_enable
909 & CD1400_SRER_TXRDY)
910 cd_outb(iobase, CD1400_SRER,
911 cy_align,
912 com->intr_enable
913 = com->intr_enable
914 & ~CD1400_SRER_TXRDY
915 | CD1400_SRER_TXMPTY);
916 }
917 }
918 #endif
919 }
920
921 /* terminate service context */
922 #ifdef PollMode
923 cd_outb(iobase, CD1400_MIR, cy_align,
924 save_mir
925 & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY));
926 #else
927 cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
928 #endif
929 }
930 if (status & CD1400_SVRR_TXRDY) {
931 struct com_s *com;
932 #ifdef PollMode
933 u_char save_tir;
934 #else
935 u_char vector;
936 #endif
937
938 #ifdef PollMode
939 save_tir = cd_inb(iobase, CD1400_TIR, cy_align);
940
941 /* enter tx service */
942 cd_outb(iobase, CD1400_CAR, cy_align, save_tir);
943 cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car
944 = save_tir & CD1400_CAR_CHAN;
945
946 com = cy_addr(baseu
947 + cyu * CD1400_NO_OF_CHANNELS
948 + (save_tir & CD1400_TIR_CHAN));
949 #else
950 /* ack transmit service */
951 vector = cy_inb(iobase, CY8_SVCACKT, cy_align);
952
953 com = cy_addr(baseu
954 + ((vector >> CD1400_xIVR_CHAN_SHIFT)
955 & CD1400_xIVR_CHAN));
956 #endif
957
958 if (com->etc != ETC_NONE) {
959 if (com->intr_enable & CD1400_SRER_TXRDY) {
960 /*
961 * Here due to sloppy SRER_TXRDY
962 * enabling. Ignore. Come back when
963 * tx is empty.
964 */
965 cd_outb(iobase, CD1400_SRER, cy_align,
966 com->intr_enable
967 = (com->intr_enable
968 & ~CD1400_SRER_TXRDY)
969 | CD1400_SRER_TXMPTY);
970 goto terminate_tx_service;
971 }
972 switch (com->etc) {
973 case CD1400_ETC_SENDBREAK:
974 case CD1400_ETC_STOPBREAK:
975 /*
976 * Start the command. Come back on
977 * next tx empty interrupt, hopefully
978 * after command has been executed.
979 */
980 cd_outb(iobase, CD1400_COR2, cy_align,
981 com->cor[1] |= CD1400_COR2_ETC);
982 cd_outb(iobase, CD1400_TDR, cy_align,
983 CD1400_ETC_CMD);
984 cd_outb(iobase, CD1400_TDR, cy_align,
985 com->etc);
986 if (com->etc == CD1400_ETC_SENDBREAK)
987 com->etc = ETC_BREAK_STARTING;
988 else
989 com->etc = ETC_BREAK_ENDING;
990 goto terminate_tx_service;
991 case ETC_BREAK_STARTING:
992 /*
993 * BREAK is now on. Continue with
994 * SRER_TXMPTY processing, hopefully
995 * don't come back.
996 */
997 com->etc = ETC_BREAK_STARTED;
998 break;
999 case ETC_BREAK_STARTED:
1000 /*
1001 * Came back due to sloppy SRER_TXMPTY
1002 * enabling. Hope again.
1003 */
1004 break;
1005 case ETC_BREAK_ENDING:
1006 /*
1007 * BREAK is now off. Continue with
1008 * SRER_TXMPTY processing and don't
1009 * come back. The SWI handler will
1010 * restart tx interrupts if necessary.
1011 */
1012 cd_outb(iobase, CD1400_COR2, cy_align,
1013 com->cor[1]
1014 &= ~CD1400_COR2_ETC);
1015 com->etc = ETC_BREAK_ENDED;
1016 if (!(com->state & CS_ODONE)) {
1017 cy_events += LOTS_OF_EVENTS;
1018 com->state |= CS_ODONE;
1019 swi_sched(cy_fast_ih, 0);
1020 }
1021 break;
1022 case ETC_BREAK_ENDED:
1023 /*
1024 * Shouldn't get here. Hope again.
1025 */
1026 break;
1027 }
1028 }
1029 if (com->intr_enable & CD1400_SRER_TXMPTY) {
1030 if (!(com->extra_state & CSE_ODONE)) {
1031 cy_events += LOTS_OF_EVENTS;
1032 com->extra_state |= CSE_ODONE;
1033 swi_sched(cy_fast_ih, 0);
1034 }
1035 cd_outb(iobase, CD1400_SRER, cy_align,
1036 com->intr_enable
1037 &= ~CD1400_SRER_TXMPTY);
1038 goto terminate_tx_service;
1039 }
1040 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1041 u_char *ioptr;
1042 u_int ocount;
1043
1044 ioptr = com->obufq.l_head;
1045 ocount = com->obufq.l_tail - ioptr;
1046 if (ocount > CD1400_TX_FIFO_SIZE)
1047 ocount = CD1400_TX_FIFO_SIZE;
1048 com->bytes_out += ocount;
1049 do
1050 cd_outb(iobase, CD1400_TDR, cy_align,
1051 *ioptr++);
1052 while (--ocount != 0);
1053 com->obufq.l_head = ioptr;
1054 if (ioptr >= com->obufq.l_tail) {
1055 struct lbq *qp;
1056
1057 qp = com->obufq.l_next;
1058 qp->l_queued = FALSE;
1059 qp = qp->l_next;
1060 if (qp != NULL) {
1061 com->obufq.l_head = qp->l_head;
1062 com->obufq.l_tail = qp->l_tail;
1063 com->obufq.l_next = qp;
1064 } else {
1065 /* output just completed */
1066 com->state &= ~CS_BUSY;
1067
1068 /*
1069 * The setting of CSE_ODONE may be
1070 * stale here. We currently only
1071 * use it when CS_BUSY is set, and
1072 * fixing it when we clear CS_BUSY
1073 * is easiest.
1074 */
1075 if (com->extra_state & CSE_ODONE) {
1076 cy_events -= LOTS_OF_EVENTS;
1077 com->extra_state &= ~CSE_ODONE;
1078 }
1079
1080 cd_outb(iobase, CD1400_SRER, cy_align,
1081 com->intr_enable
1082 = (com->intr_enable
1083 & ~CD1400_SRER_TXRDY)
1084 | CD1400_SRER_TXMPTY);
1085 }
1086 if (!(com->state & CS_ODONE)) {
1087 cy_events += LOTS_OF_EVENTS;
1088 com->state |= CS_ODONE;
1089
1090 /* handle at high level ASAP */
1091 swi_sched(cy_fast_ih, 0);
1092 }
1093 }
1094 }
1095
1096 /* terminate service context */
1097 terminate_tx_service:
1098 #ifdef PollMode
1099 cd_outb(iobase, CD1400_TIR, cy_align,
1100 save_tir
1101 & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY));
1102 #else
1103 cd_outb(iobase, CD1400_EOSRR, cy_align, 0);
1104 #endif
1105 }
1106 }
1107
1108 /* ensure an edge for the next interrupt */
1109 cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0);
1110
1111 swi_sched(cy_slow_ih, SWI_DELAY);
1112
1113 COM_UNLOCK();
1114 }
1115
1116 static void
1117 cybreak(struct tty *tp, int sig)
1118 {
1119 struct com_s *com;
1120
1121 com = tp->t_sc;
1122 if (sig)
1123 cd_etc(com, CD1400_ETC_SENDBREAK);
1124 else
1125 cd_etc(com, CD1400_ETC_STOPBREAK);
1126 }
1127
1128 static void
1129 cypoll(void *arg)
1130 {
1131 int unit;
1132
1133 #ifdef CyDebug
1134 ++cy_timeouts;
1135 #endif
1136 if (cy_events == 0)
1137 return;
1138 repeat:
1139 for (unit = 0; unit < NPORTS; ++unit) {
1140 struct com_s *com;
1141 int incc;
1142 struct tty *tp;
1143
1144 com = cy_addr(unit);
1145 if (com == NULL)
1146 continue;
1147 tp = com->tp;
1148 if (tp == NULL) {
1149 /*
1150 * XXX forget any events related to closed devices
1151 * (actually never opened devices) so that we don't
1152 * loop.
1153 */
1154 critical_enter();
1155 COM_LOCK();
1156 incc = com->iptr - com->ibuf;
1157 com->iptr = com->ibuf;
1158 if (com->state & CS_CHECKMSR) {
1159 incc += LOTS_OF_EVENTS;
1160 com->state &= ~CS_CHECKMSR;
1161 }
1162 cy_events -= incc;
1163 COM_UNLOCK();
1164 critical_exit();
1165 if (incc != 0)
1166 log(LOG_DEBUG,
1167 "cy%d: %d events for device with no tp\n",
1168 unit, incc);
1169 continue;
1170 }
1171 if (com->iptr != com->ibuf) {
1172 critical_enter();
1173 COM_LOCK();
1174 cyinput(com);
1175 COM_UNLOCK();
1176 critical_exit();
1177 }
1178 if (com->state & CS_CHECKMSR) {
1179 u_char delta_modem_status;
1180
1181 critical_enter();
1182 COM_LOCK();
1183 cyinput(com);
1184 delta_modem_status = com->last_modem_status
1185 ^ com->prev_modem_status;
1186 com->prev_modem_status = com->last_modem_status;
1187 cy_events -= LOTS_OF_EVENTS;
1188 com->state &= ~CS_CHECKMSR;
1189 COM_UNLOCK();
1190 critical_exit();
1191 if (delta_modem_status & CD1400_MSVR2_CD)
1192 ttyld_modem(tp,
1193 com->prev_modem_status & CD1400_MSVR2_CD);
1194 }
1195 if (com->extra_state & CSE_ODONE) {
1196 critical_enter();
1197 COM_LOCK();
1198 cy_events -= LOTS_OF_EVENTS;
1199 com->extra_state &= ~CSE_ODONE;
1200 COM_UNLOCK();
1201 critical_exit();
1202 if (!(com->state & CS_BUSY)) {
1203 tp->t_state &= ~TS_BUSY;
1204 ttwwakeup(com->tp);
1205 }
1206 if (com->etc != ETC_NONE) {
1207 if (com->etc == ETC_BREAK_ENDED)
1208 com->etc = ETC_NONE;
1209 wakeup(&com->etc);
1210 }
1211 }
1212 if (com->state & CS_ODONE) {
1213 critical_enter();
1214 COM_LOCK();
1215 cy_events -= LOTS_OF_EVENTS;
1216 com->state &= ~CS_ODONE;
1217 COM_UNLOCK();
1218 critical_exit();
1219 ttyld_start(tp);
1220 }
1221 if (cy_events == 0)
1222 break;
1223 }
1224 if (cy_events >= LOTS_OF_EVENTS)
1225 goto repeat;
1226 }
1227
1228 static int
1229 cyparam(struct tty *tp, struct termios *t)
1230 {
1231 int bits;
1232 int cflag;
1233 struct com_s *com;
1234 u_char cor_change;
1235 u_long cy_clock;
1236 int idivisor;
1237 int iflag;
1238 int iprescaler;
1239 int itimeout;
1240 int odivisor;
1241 int oprescaler;
1242 u_char opt;
1243 int s;
1244
1245 com = tp->t_sc;
1246
1247 /* check requested parameters */
1248 cy_clock = CY_CLOCK(com->gfrcr_image);
1249 idivisor = cyspeed(t->c_ispeed, cy_clock, &iprescaler);
1250 if (idivisor <= 0)
1251 return (EINVAL);
1252 odivisor = cyspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed,
1253 cy_clock, &oprescaler);
1254 if (odivisor <= 0)
1255 return (EINVAL);
1256
1257 /* parameters are OK, convert them to the com struct and the device */
1258 s = spltty();
1259 if (t->c_ospeed == 0)
1260 (void)cymodem(tp, 0, SER_DTR);
1261 else
1262 (void)cymodem(tp, SER_DTR, 0);
1263
1264 (void) cysetwater(com, t->c_ispeed);
1265
1266 /* XXX we don't actually change the speed atomically. */
1267
1268 cd_setreg(com, CD1400_RBPR, idivisor);
1269 cd_setreg(com, CD1400_RCOR, iprescaler);
1270 cd_setreg(com, CD1400_TBPR, odivisor);
1271 cd_setreg(com, CD1400_TCOR, oprescaler);
1272
1273 /*
1274 * channel control
1275 * receiver enable
1276 * transmitter enable (always set)
1277 */
1278 cflag = t->c_cflag;
1279 opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
1280 | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
1281 if (opt != com->channel_control) {
1282 com->channel_control = opt;
1283 cd1400_channel_cmd(com, opt);
1284 }
1285
1286 #ifdef Smarts
1287 /* set special chars */
1288 /* XXX if one is _POSIX_VDISABLE, can't use some others */
1289 if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
1290 cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]);
1291 if (t->c_cc[VSTART] != _POSIX_VDISABLE)
1292 cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]);
1293 if (t->c_cc[VINTR] != _POSIX_VDISABLE)
1294 cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]);
1295 if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
1296 cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]);
1297 #endif
1298
1299 /*
1300 * set channel option register 1 -
1301 * parity mode
1302 * stop bits
1303 * char length
1304 */
1305 opt = 0;
1306 /* parity */
1307 if (cflag & PARENB) {
1308 if (cflag & PARODD)
1309 opt |= CD1400_COR1_PARODD;
1310 opt |= CD1400_COR1_PARNORMAL;
1311 }
1312 iflag = t->c_iflag;
1313 if (!(iflag & INPCK))
1314 opt |= CD1400_COR1_NOINPCK;
1315 bits = 1 + 1;
1316 /* stop bits */
1317 if (cflag & CSTOPB) {
1318 ++bits;
1319 opt |= CD1400_COR1_STOP2;
1320 }
1321 /* char length */
1322 switch (cflag & CSIZE) {
1323 case CS5:
1324 bits += 5;
1325 opt |= CD1400_COR1_CS5;
1326 break;
1327 case CS6:
1328 bits += 6;
1329 opt |= CD1400_COR1_CS6;
1330 break;
1331 case CS7:
1332 bits += 7;
1333 opt |= CD1400_COR1_CS7;
1334 break;
1335 default:
1336 bits += 8;
1337 opt |= CD1400_COR1_CS8;
1338 break;
1339 }
1340 cor_change = 0;
1341 if (opt != com->cor[0]) {
1342 cor_change |= CD1400_CCR_COR1;
1343 cd_setreg(com, CD1400_COR1, com->cor[0] = opt);
1344 }
1345
1346 /*
1347 * Set receive time-out period, normally to max(one char time, 5 ms).
1348 */
1349 itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed;
1350 #ifdef SOFT_HOTCHAR
1351 #define MIN_RTP 1
1352 #else
1353 #define MIN_RTP 5
1354 #endif
1355 if (itimeout < MIN_RTP)
1356 itimeout = MIN_RTP;
1357 if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
1358 && t->c_cc[VTIME] * 10 > itimeout)
1359 itimeout = t->c_cc[VTIME] * 10;
1360 if (itimeout > 255)
1361 itimeout = 255;
1362 cd_setreg(com, CD1400_RTPR, itimeout);
1363
1364 /*
1365 * set channel option register 2 -
1366 * flow control
1367 */
1368 opt = 0;
1369 #ifdef Smarts
1370 if (iflag & IXANY)
1371 opt |= CD1400_COR2_IXANY;
1372 if (iflag & IXOFF)
1373 opt |= CD1400_COR2_IXOFF;
1374 #endif
1375 #ifndef SOFT_CTS_OFLOW
1376 if (cflag & CCTS_OFLOW)
1377 opt |= CD1400_COR2_CCTS_OFLOW;
1378 #endif
1379 critical_enter();
1380 COM_LOCK();
1381 if (opt != com->cor[1]) {
1382 cor_change |= CD1400_CCR_COR2;
1383 cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
1384 }
1385 COM_UNLOCK();
1386 critical_exit();
1387
1388 /*
1389 * set channel option register 3 -
1390 * receiver FIFO interrupt threshold
1391 * flow control
1392 */
1393 opt = RxFifoThreshold;
1394 #ifdef Smarts
1395 if (t->c_lflag & ICANON)
1396 opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */
1397 if (iflag & IXOFF)
1398 /* detect and transparently handle START and STOP chars */
1399 opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
1400 #endif
1401 if (opt != com->cor[2]) {
1402 cor_change |= CD1400_CCR_COR3;
1403 cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
1404 }
1405
1406 /* notify the CD1400 if COR1-3 have changed */
1407 if (cor_change)
1408 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change);
1409
1410 /*
1411 * set channel option register 4 -
1412 * CR/NL processing
1413 * break processing
1414 * received exception processing
1415 */
1416 opt = 0;
1417 if (iflag & IGNCR)
1418 opt |= CD1400_COR4_IGNCR;
1419 #ifdef Smarts
1420 /*
1421 * we need a new ttyinput() for this, as we don't want to
1422 * have ICRNL && INLCR being done in both layers, or to have
1423 * synchronisation problems
1424 */
1425 if (iflag & ICRNL)
1426 opt |= CD1400_COR4_ICRNL;
1427 if (iflag & INLCR)
1428 opt |= CD1400_COR4_INLCR;
1429 #endif
1430 if (iflag & IGNBRK)
1431 opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT;
1432 /*
1433 * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
1434 * so only tell the hardware about -brkint if -parmrk.
1435 */
1436 if (!(iflag & (BRKINT | PARMRK)))
1437 opt |= CD1400_COR4_NOBRKINT;
1438 #if 0
1439 /* XXX using this "intelligence" breaks reporting of overruns. */
1440 if (iflag & IGNPAR)
1441 opt |= CD1400_COR4_PFO_DISCARD;
1442 else {
1443 if (iflag & PARMRK)
1444 opt |= CD1400_COR4_PFO_ESC;
1445 else
1446 opt |= CD1400_COR4_PFO_NUL;
1447 }
1448 #else
1449 opt |= CD1400_COR4_PFO_EXCEPTION;
1450 #endif
1451 cd_setreg(com, CD1400_COR4, opt);
1452
1453 /*
1454 * set channel option register 5 -
1455 */
1456 opt = 0;
1457 if (iflag & ISTRIP)
1458 opt |= CD1400_COR5_ISTRIP;
1459 if (t->c_iflag & IEXTEN)
1460 /* enable LNEXT (e.g. ctrl-v quoting) handling */
1461 opt |= CD1400_COR5_LNEXT;
1462 #ifdef Smarts
1463 if (t->c_oflag & ONLCR)
1464 opt |= CD1400_COR5_ONLCR;
1465 if (t->c_oflag & OCRNL)
1466 opt |= CD1400_COR5_OCRNL;
1467 #endif
1468 cd_setreg(com, CD1400_COR5, opt);
1469
1470 /*
1471 * We always generate modem status change interrupts for CD changes.
1472 * Among other things, this is necessary to track TS_CARR_ON for
1473 * pstat to print even when the driver doesn't care. CD changes
1474 * should be rare so interrupts for them are not worth extra code to
1475 * avoid. We avoid interrupts for other modem status changes (except
1476 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
1477 * simplest and best.
1478 */
1479
1480 /*
1481 * set modem change option register 1
1482 * generate modem interrupts on which 1 -> 0 input transitions
1483 * also controls auto-DTR output flow-control, which we don't use
1484 */
1485 opt = CD1400_MCOR1_CDzd;
1486 #ifdef SOFT_CTS_OFLOW
1487 if (cflag & CCTS_OFLOW)
1488 opt |= CD1400_MCOR1_CTSzd;
1489 #endif
1490 cd_setreg(com, CD1400_MCOR1, opt);
1491
1492 /*
1493 * set modem change option register 2
1494 * generate modem interrupts on specific 0 -> 1 input transitions
1495 */
1496 opt = CD1400_MCOR2_CDod;
1497 #ifdef SOFT_CTS_OFLOW
1498 if (cflag & CCTS_OFLOW)
1499 opt |= CD1400_MCOR2_CTSod;
1500 #endif
1501 cd_setreg(com, CD1400_MCOR2, opt);
1502
1503 /*
1504 * XXX should have done this long ago, but there is too much state
1505 * to change all atomically.
1506 */
1507 critical_enter();
1508 COM_LOCK();
1509
1510 com->state &= ~CS_TTGO;
1511 if (!(tp->t_state & TS_TTSTOP))
1512 com->state |= CS_TTGO;
1513 if (cflag & CRTS_IFLOW) {
1514 com->state |= CS_RTS_IFLOW;
1515 /*
1516 * If CS_RTS_IFLOW just changed from off to on, the change
1517 * needs to be propagated to CD1400_MSVR1_RTS. This isn't urgent,
1518 * so do it later by calling cystart() instead of repeating
1519 * a lot of code from cystart() here.
1520 */
1521 } else if (com->state & CS_RTS_IFLOW) {
1522 com->state &= ~CS_RTS_IFLOW;
1523 /*
1524 * CS_RTS_IFLOW just changed from on to off. Force CD1400_MSVR1_RTS
1525 * on here, since cystart() won't do it later.
1526 */
1527 cd_setreg(com, com->mcr_rts_reg,
1528 com->mcr_image |= com->mcr_rts);
1529 }
1530
1531 /*
1532 * Set up state to handle output flow control.
1533 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
1534 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
1535 */
1536 com->state |= CS_ODEVREADY;
1537 #ifdef SOFT_CTS_OFLOW
1538 com->state &= ~CS_CTS_OFLOW;
1539 if (cflag & CCTS_OFLOW) {
1540 com->state |= CS_CTS_OFLOW;
1541 if (!(com->last_modem_status & CD1400_MSVR2_CTS))
1542 com->state &= ~CS_ODEVREADY;
1543 }
1544 #endif
1545 /* XXX shouldn't call functions while intrs are disabled. */
1546 disc_optim(tp, t, com);
1547 #if 0
1548 /*
1549 * Recover from fiddling with CS_TTGO. We used to call cyintr1()
1550 * unconditionally, but that defeated the careful discarding of
1551 * stale input in cyopen().
1552 */
1553 if (com->state >= (CS_BUSY | CS_TTGO))
1554 cyintr1(com);
1555 #endif
1556 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1557 if (!(com->intr_enable & CD1400_SRER_TXRDY))
1558 cd_setreg(com, CD1400_SRER,
1559 com->intr_enable
1560 = (com->intr_enable & ~CD1400_SRER_TXMPTY)
1561 | CD1400_SRER_TXRDY);
1562 } else {
1563 if (com->intr_enable & CD1400_SRER_TXRDY)
1564 cd_setreg(com, CD1400_SRER,
1565 com->intr_enable
1566 = (com->intr_enable & ~CD1400_SRER_TXRDY)
1567 | CD1400_SRER_TXMPTY);
1568 }
1569
1570 COM_UNLOCK();
1571 critical_exit();
1572 splx(s);
1573 cystart(tp);
1574 if (com->ibufold != NULL) {
1575 free(com->ibufold, M_DEVBUF);
1576 com->ibufold = NULL;
1577 }
1578 return (0);
1579 }
1580
1581 static int
1582 cysetwater(struct com_s *com, speed_t speed)
1583 {
1584 int cp4ticks;
1585 u_char *ibuf;
1586 int ibufsize;
1587 struct tty *tp;
1588
1589 /*
1590 * Make the buffer size large enough to handle a softtty interrupt
1591 * latency of about 2 ticks without loss of throughput or data
1592 * (about 3 ticks if input flow control is not used or not honoured,
1593 * but a bit less for CS5-CS7 modes).
1594 */
1595 cp4ticks = speed / 10 / hz * 4;
1596 for (ibufsize = 128; ibufsize < cp4ticks;)
1597 ibufsize <<= 1;
1598 if (ibufsize == com->ibufsize) {
1599 return (0);
1600 }
1601
1602 /*
1603 * Allocate input buffer. The extra factor of 2 in the size is
1604 * to allow for an error byte for each input byte.
1605 */
1606 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
1607 if (ibuf == NULL) {
1608 return (ENOMEM);
1609 }
1610
1611 /* Initialize non-critical variables. */
1612 com->ibufold = com->ibuf;
1613 com->ibufsize = ibufsize;
1614 tp = com->tp;
1615 if (tp != NULL) {
1616 tp->t_ififosize = 2 * ibufsize;
1617 tp->t_ispeedwat = (speed_t)-1;
1618 tp->t_ospeedwat = (speed_t)-1;
1619 }
1620
1621 /*
1622 * Read current input buffer, if any. Continue with interrupts
1623 * disabled.
1624 */
1625 critical_enter();
1626 COM_LOCK();
1627 if (com->iptr != com->ibuf)
1628 cyinput(com);
1629
1630 /*-
1631 * Initialize critical variables, including input buffer watermarks.
1632 * The external device is asked to stop sending when the buffer
1633 * exactly reaches high water, or when the high level requests it.
1634 * The high level is notified immediately (rather than at a later
1635 * clock tick) when this watermark is reached.
1636 * The buffer size is chosen so the watermark should almost never
1637 * be reached.
1638 * The low watermark is invisibly 0 since the buffer is always
1639 * emptied all at once.
1640 */
1641 com->iptr = com->ibuf = ibuf;
1642 com->ibufend = ibuf + ibufsize;
1643 com->ierroff = ibufsize;
1644 com->ihighwater = ibuf + 3 * ibufsize / 4;
1645
1646 COM_UNLOCK();
1647 critical_exit();
1648 return (0);
1649 }
1650
1651 static void
1652 cystart(struct tty *tp)
1653 {
1654 struct com_s *com;
1655 int s;
1656 #ifdef CyDebug
1657 bool_t started;
1658 #endif
1659
1660 com = tp->t_sc;
1661 s = spltty();
1662
1663 #ifdef CyDebug
1664 ++com->start_count;
1665 started = FALSE;
1666 #endif
1667
1668 critical_enter();
1669 COM_LOCK();
1670 if (tp->t_state & TS_TTSTOP) {
1671 com->state &= ~CS_TTGO;
1672 if (com->intr_enable & CD1400_SRER_TXRDY)
1673 cd_setreg(com, CD1400_SRER,
1674 com->intr_enable
1675 = (com->intr_enable & ~CD1400_SRER_TXRDY)
1676 | CD1400_SRER_TXMPTY);
1677 } else {
1678 com->state |= CS_TTGO;
1679 if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
1680 && !(com->intr_enable & CD1400_SRER_TXRDY))
1681 cd_setreg(com, CD1400_SRER,
1682 com->intr_enable
1683 = (com->intr_enable & ~CD1400_SRER_TXMPTY)
1684 | CD1400_SRER_TXRDY);
1685 }
1686 if (tp->t_state & TS_TBLOCK) {
1687 if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW)
1688 #if 0
1689 outb(com->modem_ctl_port, com->mcr_image &= ~CD1400_MSVR1_RTS);
1690 #else
1691 cd_setreg(com, com->mcr_rts_reg,
1692 com->mcr_image &= ~com->mcr_rts);
1693 #endif
1694 } else {
1695 if (!(com->mcr_image & com->mcr_rts)
1696 && com->iptr < com->ihighwater
1697 && com->state & CS_RTS_IFLOW)
1698 #if 0
1699 outb(com->modem_ctl_port, com->mcr_image |= CD1400_MSVR1_RTS);
1700 #else
1701 cd_setreg(com, com->mcr_rts_reg,
1702 com->mcr_image |= com->mcr_rts);
1703 #endif
1704 }
1705 COM_UNLOCK();
1706 critical_exit();
1707 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1708 ttwwakeup(tp);
1709 splx(s);
1710 return;
1711 }
1712 if (tp->t_outq.c_cc != 0) {
1713 struct lbq *qp;
1714 struct lbq *next;
1715
1716 if (!com->obufs[0].l_queued) {
1717 #ifdef CyDebug
1718 started = TRUE;
1719 #endif
1720 com->obufs[0].l_tail
1721 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
1722 sizeof com->obuf1);
1723 com->obufs[0].l_next = NULL;
1724 com->obufs[0].l_queued = TRUE;
1725 critical_enter();
1726 COM_LOCK();
1727 if (com->state & CS_BUSY) {
1728 qp = com->obufq.l_next;
1729 while ((next = qp->l_next) != NULL)
1730 qp = next;
1731 qp->l_next = &com->obufs[0];
1732 } else {
1733 com->obufq.l_head = com->obufs[0].l_head;
1734 com->obufq.l_tail = com->obufs[0].l_tail;
1735 com->obufq.l_next = &com->obufs[0];
1736 com->state |= CS_BUSY;
1737 if (com->state >= (CS_BUSY | CS_TTGO
1738 | CS_ODEVREADY))
1739 cd_setreg(com, CD1400_SRER,
1740 com->intr_enable
1741 = (com->intr_enable
1742 & ~CD1400_SRER_TXMPTY)
1743 | CD1400_SRER_TXRDY);
1744 }
1745 COM_UNLOCK();
1746 critical_exit();
1747 }
1748 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
1749 #ifdef CyDebug
1750 started = TRUE;
1751 #endif
1752 com->obufs[1].l_tail
1753 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
1754 sizeof com->obuf2);
1755 com->obufs[1].l_next = NULL;
1756 com->obufs[1].l_queued = TRUE;
1757 critical_enter();
1758 COM_LOCK();
1759 if (com->state & CS_BUSY) {
1760 qp = com->obufq.l_next;
1761 while ((next = qp->l_next) != NULL)
1762 qp = next;
1763 qp->l_next = &com->obufs[1];
1764 } else {
1765 com->obufq.l_head = com->obufs[1].l_head;
1766 com->obufq.l_tail = com->obufs[1].l_tail;
1767 com->obufq.l_next = &com->obufs[1];
1768 com->state |= CS_BUSY;
1769 if (com->state >= (CS_BUSY | CS_TTGO
1770 | CS_ODEVREADY))
1771 cd_setreg(com, CD1400_SRER,
1772 com->intr_enable
1773 = (com->intr_enable
1774 & ~CD1400_SRER_TXMPTY)
1775 | CD1400_SRER_TXRDY);
1776 }
1777 COM_UNLOCK();
1778 critical_exit();
1779 }
1780 tp->t_state |= TS_BUSY;
1781 }
1782 #ifdef CyDebug
1783 if (started)
1784 ++com->start_real;
1785 #endif
1786 #if 0
1787 critical_enter();
1788 COM_LOCK();
1789 if (com->state >= (CS_BUSY | CS_TTGO))
1790 cyintr1(com); /* fake interrupt to start output */
1791 COM_UNLOCK();
1792 critical_exit();
1793 #endif
1794 ttwwakeup(tp);
1795 splx(s);
1796 }
1797
1798 static void
1799 comstop(struct tty *tp, int rw)
1800 {
1801 struct com_s *com;
1802 bool_t wakeup_etc;
1803
1804 com = tp->t_sc;
1805 wakeup_etc = FALSE;
1806 critical_enter();
1807 COM_LOCK();
1808 if (rw & FWRITE) {
1809 com->obufs[0].l_queued = FALSE;
1810 com->obufs[1].l_queued = FALSE;
1811 if (com->extra_state & CSE_ODONE) {
1812 cy_events -= LOTS_OF_EVENTS;
1813 com->extra_state &= ~CSE_ODONE;
1814 if (com->etc != ETC_NONE) {
1815 if (com->etc == ETC_BREAK_ENDED)
1816 com->etc = ETC_NONE;
1817 wakeup_etc = TRUE;
1818 }
1819 }
1820 com->tp->t_state &= ~TS_BUSY;
1821 if (com->state & CS_ODONE)
1822 cy_events -= LOTS_OF_EVENTS;
1823 com->state &= ~(CS_ODONE | CS_BUSY);
1824 }
1825 if (rw & FREAD) {
1826 /* XXX no way to reset only input fifo. */
1827 cy_events -= (com->iptr - com->ibuf);
1828 com->iptr = com->ibuf;
1829 }
1830 COM_UNLOCK();
1831 critical_exit();
1832 if (wakeup_etc)
1833 wakeup(&com->etc);
1834 if (rw & FWRITE && com->etc == ETC_NONE)
1835 cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
1836 cystart(tp);
1837 }
1838
1839 static int
1840 cymodem(struct tty *tp, int sigon, int sigoff)
1841 {
1842 struct com_s *com;
1843 int mcr;
1844 int msr;
1845
1846 com = tp->t_sc;
1847 if (sigon == 0 && sigoff == 0) {
1848 sigon = 0;
1849 mcr = com->mcr_image;
1850 if (mcr & com->mcr_dtr)
1851 sigon |= SER_DTR;
1852 if (mcr & com->mcr_rts)
1853 /* XXX wired on for Cyclom-8Ys */
1854 sigon |= SER_RTS;
1855
1856 /*
1857 * We must read the modem status from the hardware because
1858 * we don't generate modem status change interrupts for all
1859 * changes, so com->prev_modem_status is not guaranteed to
1860 * be up to date. This is safe, unlike for sio, because
1861 * reading the status register doesn't clear pending modem
1862 * status change interrupts.
1863 */
1864 msr = cd_getreg(com, CD1400_MSVR2);
1865
1866 if (msr & CD1400_MSVR2_CTS)
1867 sigon |= SER_CTS;
1868 if (msr & CD1400_MSVR2_CD)
1869 sigon |= SER_DCD;
1870 if (msr & CD1400_MSVR2_DSR)
1871 sigon |= SER_DSR;
1872 if (msr & CD1400_MSVR2_RI)
1873 /* XXX not connected except for Cyclom-16Y? */
1874 sigon |= SER_RI;
1875 return (sigon);
1876 }
1877 mcr = com->mcr_image;
1878 if (sigon & SER_DTR)
1879 mcr |= com->mcr_dtr;
1880 if (sigoff & SER_DTR)
1881 mcr &= ~com->mcr_dtr;
1882 if (sigon & SER_RTS)
1883 mcr |= com->mcr_rts;
1884 if (sigoff & SER_RTS)
1885 mcr &= ~com->mcr_rts;
1886 critical_enter();
1887 COM_LOCK();
1888 com->mcr_image = mcr;
1889 cd_setreg(com, CD1400_MSVR1, mcr);
1890 cd_setreg(com, CD1400_MSVR2, mcr);
1891 COM_UNLOCK();
1892 critical_exit();
1893 return (0);
1894 }
1895
1896 static void
1897 cysettimeout()
1898 {
1899 struct com_s *com;
1900 bool_t someopen;
1901 int unit;
1902
1903 /*
1904 * Set our timeout period to 1 second if no polled devices are open.
1905 * Otherwise set it to max(1/200, 1/hz).
1906 * Enable timeouts iff some device is open.
1907 */
1908 untimeout(cywakeup, (void *)NULL, cy_timeout_handle);
1909 cy_timeout = hz;
1910 someopen = FALSE;
1911 for (unit = 0; unit < NPORTS; ++unit) {
1912 com = cy_addr(unit);
1913 if (com != NULL && com->tp != NULL
1914 && com->tp->t_state & TS_ISOPEN) {
1915 someopen = TRUE;
1916 }
1917 }
1918 if (someopen) {
1919 cy_timeouts_until_log = hz / cy_timeout;
1920 cy_timeout_handle = timeout(cywakeup, (void *)NULL,
1921 cy_timeout);
1922 } else {
1923 /* Flush error messages, if any. */
1924 cy_timeouts_until_log = 1;
1925 cywakeup((void *)NULL);
1926 untimeout(cywakeup, (void *)NULL, cy_timeout_handle);
1927 }
1928 }
1929
1930 static void
1931 cywakeup(void *chan)
1932 {
1933 struct com_s *com;
1934 int unit;
1935
1936 cy_timeout_handle = timeout(cywakeup, (void *)NULL, cy_timeout);
1937
1938 /*
1939 * Check for and log errors, but not too often.
1940 */
1941 if (--cy_timeouts_until_log > 0)
1942 return;
1943 cy_timeouts_until_log = hz / cy_timeout;
1944 for (unit = 0; unit < NPORTS; ++unit) {
1945 int errnum;
1946
1947 com = cy_addr(unit);
1948 if (com == NULL)
1949 continue;
1950 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
1951 u_int delta;
1952 u_long total;
1953
1954 critical_enter();
1955 COM_LOCK();
1956 delta = com->delta_error_counts[errnum];
1957 com->delta_error_counts[errnum] = 0;
1958 COM_UNLOCK();
1959 critical_exit();
1960 if (delta == 0)
1961 continue;
1962 total = com->error_counts[errnum] += delta;
1963 log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
1964 unit, delta, error_desc[errnum],
1965 delta == 1 ? "" : "s", total);
1966 }
1967 }
1968 }
1969
1970 static void
1971 disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
1972 {
1973 #ifndef SOFT_HOTCHAR
1974 u_char opt;
1975 #endif
1976
1977 ttyldoptim(tp);
1978 #ifndef SOFT_HOTCHAR
1979 opt = com->cor[2] & ~CD1400_COR3_SCD34;
1980 if (com->tp->t_hotchar != 0) {
1981 cd_setreg(com, CD1400_SCHR3, com->tp->t_hotchar);
1982 cd_setreg(com, CD1400_SCHR4, com->tp->t_hotchar);
1983 opt |= CD1400_COR3_SCD34;
1984 }
1985 if (opt != com->cor[2]) {
1986 cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
1987 cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
1988 }
1989 #endif
1990 }
1991
1992 #ifdef Smarts
1993 /* standard line discipline input routine */
1994 int
1995 cyinput(int c, struct tty *tp)
1996 {
1997 /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
1998 * bits, as they are done by the CD1400. Hardly worth the effort,
1999 * given that high-throughput session are raw anyhow.
2000 */
2001 }
2002 #endif /* Smarts */
2003
2004 static int
2005 cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io)
2006 {
2007 int actual;
2008 int error;
2009 int divider;
2010 int prescaler;
2011 int prescaler_unit;
2012
2013 if (speed == 0)
2014 return (0);
2015 if (speed < 0 || speed > 150000)
2016 return (-1);
2017
2018 /* determine which prescaler to use */
2019 for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
2020 prescaler_unit--, prescaler >>= 2) {
2021 if (cy_clock / prescaler / speed > 63)
2022 break;
2023 }
2024
2025 divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */
2026 if (divider > 255)
2027 divider = 255;
2028 actual = cy_clock/prescaler/divider;
2029
2030 /* 10 times error in percent: */
2031 error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2;
2032
2033 /* 3.0% max error tolerance */
2034 if (error < -30 || error > 30)
2035 return (-1);
2036
2037 *prescaler_io = prescaler_unit;
2038 return (divider);
2039 }
2040
2041 static void
2042 cd1400_channel_cmd(struct com_s *com, int cmd)
2043 {
2044 cd1400_channel_cmd_wait(com);
2045 cd_setreg(com, CD1400_CCR, cmd);
2046 cd1400_channel_cmd_wait(com);
2047 }
2048
2049 static void
2050 cd1400_channel_cmd_wait(struct com_s *com)
2051 {
2052 struct timeval start;
2053 struct timeval tv;
2054 long usec;
2055
2056 if (cd_getreg(com, CD1400_CCR) == 0)
2057 return;
2058 microtime(&start);
2059 for (;;) {
2060 if (cd_getreg(com, CD1400_CCR) == 0)
2061 return;
2062 microtime(&tv);
2063 usec = 1000000 * (tv.tv_sec - start.tv_sec) +
2064 tv.tv_usec - start.tv_usec;
2065 if (usec >= 5000) {
2066 log(LOG_ERR,
2067 "cy%d: channel command timeout (%ld usec)\n",
2068 com->unit, usec);
2069 return;
2070 }
2071 }
2072 }
2073
2074 static void
2075 cd_etc(struct com_s *com, int etc)
2076 {
2077
2078 /*
2079 * We can't change the hardware's ETC state while there are any
2080 * characters in the tx fifo, since those characters would be
2081 * interpreted as commands! Unputting characters from the fifo
2082 * is difficult, so we wait up to 12 character times for the fifo
2083 * to drain. The command will be delayed for up to 2 character
2084 * times for the tx to become empty. Unputting characters from
2085 * the tx holding and shift registers is impossible, so we wait
2086 * for the tx to become empty so that the command is sure to be
2087 * executed soon after we issue it.
2088 */
2089 critical_enter();
2090 COM_LOCK();
2091 if (com->etc == etc)
2092 goto wait;
2093 if ((etc == CD1400_ETC_SENDBREAK
2094 && (com->etc == ETC_BREAK_STARTING
2095 || com->etc == ETC_BREAK_STARTED))
2096 || (etc == CD1400_ETC_STOPBREAK
2097 && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2098 || com->etc == ETC_NONE))) {
2099 COM_UNLOCK();
2100 critical_exit();
2101 return;
2102 }
2103 com->etc = etc;
2104 cd_setreg(com, CD1400_SRER,
2105 com->intr_enable
2106 = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
2107 wait:
2108 COM_UNLOCK();
2109 critical_exit();
2110 while (com->etc == etc
2111 && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2112 continue;
2113 }
2114
2115 static int
2116 cd_getreg(struct com_s *com, int reg)
2117 {
2118 struct com_s *basecom;
2119 u_char car;
2120 int cy_align;
2121 cy_addr iobase;
2122 #ifdef SMP
2123 int need_unlock;
2124 #endif
2125 int val;
2126
2127 basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2128 car = com->unit & CD1400_CAR_CHAN;
2129 cy_align = com->cy_align;
2130 iobase = com->iobase;
2131 critical_enter();
2132 #ifdef SMP
2133 need_unlock = 0;
2134 if (!mtx_owned(&cy_lock)) {
2135 COM_LOCK();
2136 need_unlock = 1;
2137 }
2138 #endif
2139 if (basecom->car != car)
2140 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2141 val = cd_inb(iobase, reg, cy_align);
2142 #ifdef SMP
2143 if (need_unlock)
2144 COM_UNLOCK();
2145 #endif
2146 critical_exit();
2147 return (val);
2148 }
2149
2150 static void
2151 cd_setreg(struct com_s *com, int reg, int val)
2152 {
2153 struct com_s *basecom;
2154 u_char car;
2155 int cy_align;
2156 cy_addr iobase;
2157 #ifdef SMP
2158 int need_unlock;
2159 #endif
2160
2161 basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2162 car = com->unit & CD1400_CAR_CHAN;
2163 cy_align = com->cy_align;
2164 iobase = com->iobase;
2165 critical_enter();
2166 #ifdef SMP
2167 need_unlock = 0;
2168 if (!mtx_owned(&cy_lock)) {
2169 COM_LOCK();
2170 need_unlock = 1;
2171 }
2172 #endif
2173 if (basecom->car != car)
2174 cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2175 cd_outb(iobase, reg, cy_align, val);
2176 #ifdef SMP
2177 if (need_unlock)
2178 COM_UNLOCK();
2179 #endif
2180 critical_exit();
2181 }
2182
2183 #ifdef CyDebug
2184 /* useful in ddb */
2185 void
2186 cystatus(int unit)
2187 {
2188 struct com_s *com;
2189 cy_addr iobase;
2190 u_int ocount;
2191 struct tty *tp;
2192
2193 com = cy_addr(unit);
2194 printf("info for channel %d\n", unit);
2195 printf("------------------\n");
2196 printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
2197 printf("calls to upper layer:\t\t%d\n", cy_timeouts);
2198 if (com == NULL)
2199 return;
2200 iobase = com->iobase;
2201 printf("\n");
2202 printf("cd1400 base address:\\tt%p\n", iobase);
2203 printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
2204 printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2205 com->cor[0], com->cor[1], com->cor[2]);
2206 printf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2207 cd_getreg(com, CD1400_SRER), com->intr_enable);
2208 printf("service request register:\t0x%02x\n",
2209 cd_inb(iobase, CD1400_SVRR, com->cy_align));
2210 printf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2211 cd_getreg(com, CD1400_MSVR2), com->prev_modem_status);
2212 printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2213 cd_inb(iobase, CD1400_RIR, com->cy_align),
2214 cd_inb(iobase, CD1400_TIR, com->cy_align),
2215 cd_inb(iobase, CD1400_MIR, com->cy_align));
2216 printf("\n");
2217 printf("com state:\t\t\t0x%02x\n", com->state);
2218 printf("calls to cystart():\t\t%d (%d useful)\n",
2219 com->start_count, com->start_real);
2220 printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
2221 ocount = 0;
2222 if (com->obufs[0].l_queued)
2223 ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
2224 if (com->obufs[1].l_queued)
2225 ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
2226 printf("tx buffer chars:\t\t%u\n", ocount);
2227 printf("received chars:\t\t\t%d\n", com->bytes_in);
2228 printf("received exceptions:\t\t%d\n", com->recv_exception);
2229 printf("modem signal deltas:\t\t%d\n", com->mdm);
2230 printf("transmitted chars:\t\t%d\n", com->bytes_out);
2231 printf("\n");
2232 tp = com->tp;
2233 if (tp != NULL) {
2234 printf("tty state:\t\t\t0x%08x\n", tp->t_state);
2235 printf(
2236 "upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2237 tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
2238 } else
2239 printf("tty state:\t\t\tclosed\n");
2240 }
2241 #endif /* CyDebug */
Cache object: 09f0208b30626f4c8ed0014ecd1199f9
|