xref: /freebsd-12.1/sys/dev/cy/cy.c (revision 6469bdcd)
1 /*-
2  * cyclades cyclom-y serial driver
3  *	Andrew Herbert <[email protected]>, 17 August 1993
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Copyright (c) 1993 Andrew Herbert.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name Andrew Herbert may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
24  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
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
cy_units(cy_addr cy_iobase,int cy_align)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 *
cyattach_common(cy_addr cy_iobase,int cy_align)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_intr_event, "cy", cypoll, NULL, SWI_TTY, 0,
432 					&cy_fast_ih);
433 				swi_add(&clk_intr_event, "cy", cypoll, NULL, SWI_CLOCK, 0,
434 					&cy_slow_ih);
435 			}
436 			ttycreate(tp, TS_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
cyopen(struct tty * tp,struct cdev * dev)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
cyclose(struct tty * tp)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
cyinput(struct com_s * com)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 int
cyintr(void * vcom)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; // XXX - FILTER_STRAY?
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 	return (FILTER_HANDLED);
1115 }
1116 
1117 static void
cybreak(struct tty * tp,int sig)1118 cybreak(struct tty *tp, int sig)
1119 {
1120 	struct com_s	*com;
1121 
1122 	com = tp->t_sc;
1123 	if (sig)
1124 		cd_etc(com, CD1400_ETC_SENDBREAK);
1125 	else
1126 		cd_etc(com, CD1400_ETC_STOPBREAK);
1127 }
1128 
1129 static void
cypoll(void * arg)1130 cypoll(void *arg)
1131 {
1132 	int		unit;
1133 
1134 #ifdef CyDebug
1135 	++cy_timeouts;
1136 #endif
1137 	if (cy_events == 0)
1138 		return;
1139 repeat:
1140 	for (unit = 0; unit < NPORTS; ++unit) {
1141 		struct com_s	*com;
1142 		int		incc;
1143 		struct tty	*tp;
1144 
1145 		com = cy_addr(unit);
1146 		if (com == NULL)
1147 			continue;
1148 		tp = com->tp;
1149 		if (tp == NULL) {
1150 			/*
1151 			 * XXX forget any events related to closed devices
1152 			 * (actually never opened devices) so that we don't
1153 			 * loop.
1154 			 */
1155 			critical_enter();
1156 			COM_LOCK();
1157 			incc = com->iptr - com->ibuf;
1158 			com->iptr = com->ibuf;
1159 			if (com->state & CS_CHECKMSR) {
1160 				incc += LOTS_OF_EVENTS;
1161 				com->state &= ~CS_CHECKMSR;
1162 			}
1163 			cy_events -= incc;
1164 			COM_UNLOCK();
1165 			critical_exit();
1166 			if (incc != 0)
1167 				log(LOG_DEBUG,
1168 				    "cy%d: %d events for device with no tp\n",
1169 				    unit, incc);
1170 			continue;
1171 		}
1172 		if (com->iptr != com->ibuf) {
1173 			critical_enter();
1174 			COM_LOCK();
1175 			cyinput(com);
1176 			COM_UNLOCK();
1177 			critical_exit();
1178 		}
1179 		if (com->state & CS_CHECKMSR) {
1180 			u_char	delta_modem_status;
1181 
1182 			critical_enter();
1183 			COM_LOCK();
1184 			cyinput(com);
1185 			delta_modem_status = com->last_modem_status
1186 					     ^ com->prev_modem_status;
1187 			com->prev_modem_status = com->last_modem_status;
1188 			cy_events -= LOTS_OF_EVENTS;
1189 			com->state &= ~CS_CHECKMSR;
1190 			COM_UNLOCK();
1191 			critical_exit();
1192 			if (delta_modem_status & CD1400_MSVR2_CD)
1193 				ttyld_modem(tp,
1194 				    com->prev_modem_status & CD1400_MSVR2_CD);
1195 		}
1196 		if (com->extra_state & CSE_ODONE) {
1197 			critical_enter();
1198 			COM_LOCK();
1199 			cy_events -= LOTS_OF_EVENTS;
1200 			com->extra_state &= ~CSE_ODONE;
1201 			COM_UNLOCK();
1202 			critical_exit();
1203 			if (!(com->state & CS_BUSY)) {
1204 				tp->t_state &= ~TS_BUSY;
1205 				ttwwakeup(com->tp);
1206 			}
1207 			if (com->etc != ETC_NONE) {
1208 				if (com->etc == ETC_BREAK_ENDED)
1209 					com->etc = ETC_NONE;
1210 				wakeup(&com->etc);
1211 			}
1212 		}
1213 		if (com->state & CS_ODONE) {
1214 			critical_enter();
1215 			COM_LOCK();
1216 			cy_events -= LOTS_OF_EVENTS;
1217 			com->state &= ~CS_ODONE;
1218 			COM_UNLOCK();
1219 			critical_exit();
1220 			ttyld_start(tp);
1221 		}
1222 		if (cy_events == 0)
1223 			break;
1224 	}
1225 	if (cy_events >= LOTS_OF_EVENTS)
1226 		goto repeat;
1227 }
1228 
1229 static int
cyparam(struct tty * tp,struct termios * t)1230 cyparam(struct tty *tp, struct termios *t)
1231 {
1232 	int		bits;
1233 	int		cflag;
1234 	struct com_s	*com;
1235 	u_char		cor_change;
1236 	u_long		cy_clock;
1237 	int		idivisor;
1238 	int		iflag;
1239 	int		iprescaler;
1240 	int		itimeout;
1241 	int		odivisor;
1242 	int		oprescaler;
1243 	u_char		opt;
1244 	int		s;
1245 
1246 	com = tp->t_sc;
1247 
1248 	/* check requested parameters */
1249 	cy_clock = CY_CLOCK(com->gfrcr_image);
1250 	idivisor = cyspeed(t->c_ispeed, cy_clock, &iprescaler);
1251 	if (idivisor <= 0)
1252 		return (EINVAL);
1253 	odivisor = cyspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed,
1254 			    cy_clock, &oprescaler);
1255 	if (odivisor <= 0)
1256 		return (EINVAL);
1257 
1258 	/* parameters are OK, convert them to the com struct and the device */
1259 	s = spltty();
1260 	if (t->c_ospeed == 0)
1261 		(void)cymodem(tp, 0, SER_DTR);
1262 	else
1263 		(void)cymodem(tp, SER_DTR, 0);
1264 
1265 	(void) cysetwater(com, t->c_ispeed);
1266 
1267 	/* XXX we don't actually change the speed atomically. */
1268 
1269 	cd_setreg(com, CD1400_RBPR, idivisor);
1270 	cd_setreg(com, CD1400_RCOR, iprescaler);
1271 	cd_setreg(com, CD1400_TBPR, odivisor);
1272 	cd_setreg(com, CD1400_TCOR, oprescaler);
1273 
1274 	/*
1275 	 * channel control
1276 	 *	receiver enable
1277 	 *	transmitter enable (always set)
1278 	 */
1279 	cflag = t->c_cflag;
1280 	opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
1281 	      | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
1282 	if (opt != com->channel_control) {
1283 		com->channel_control = opt;
1284 		cd1400_channel_cmd(com, opt);
1285 	}
1286 
1287 #ifdef Smarts
1288 	/* set special chars */
1289 	/* XXX if one is _POSIX_VDISABLE, can't use some others */
1290 	if (t->c_cc[VSTOP] != _POSIX_VDISABLE)
1291 		cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]);
1292 	if (t->c_cc[VSTART] != _POSIX_VDISABLE)
1293 		cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]);
1294 	if (t->c_cc[VINTR] != _POSIX_VDISABLE)
1295 		cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]);
1296 	if (t->c_cc[VSUSP] != _POSIX_VDISABLE)
1297 		cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]);
1298 #endif
1299 
1300 	/*
1301 	 * set channel option register 1 -
1302 	 *	parity mode
1303 	 *	stop bits
1304 	 *	char length
1305 	 */
1306 	opt = 0;
1307 	/* parity */
1308 	if (cflag & PARENB) {
1309 		if (cflag & PARODD)
1310 			opt |= CD1400_COR1_PARODD;
1311 		opt |= CD1400_COR1_PARNORMAL;
1312 	}
1313 	iflag = t->c_iflag;
1314 	if (!(iflag & INPCK))
1315 		opt |= CD1400_COR1_NOINPCK;
1316 	bits = 1 + 1;
1317 	/* stop bits */
1318 	if (cflag & CSTOPB) {
1319 		++bits;
1320 		opt |= CD1400_COR1_STOP2;
1321 	}
1322 	/* char length */
1323 	switch (cflag & CSIZE) {
1324 	case CS5:
1325 		bits += 5;
1326 		opt |= CD1400_COR1_CS5;
1327 		break;
1328 	case CS6:
1329 		bits += 6;
1330 		opt |= CD1400_COR1_CS6;
1331 		break;
1332 	case CS7:
1333 		bits += 7;
1334 		opt |= CD1400_COR1_CS7;
1335 		break;
1336 	default:
1337 		bits += 8;
1338 		opt |= CD1400_COR1_CS8;
1339 		break;
1340 	}
1341 	cor_change = 0;
1342 	if (opt != com->cor[0]) {
1343 		cor_change |= CD1400_CCR_COR1;
1344 		cd_setreg(com, CD1400_COR1, com->cor[0] = opt);
1345 	}
1346 
1347 	/*
1348 	 * Set receive time-out period, normally to max(one char time, 5 ms).
1349 	 */
1350 	itimeout = howmany(1000 * bits, t->c_ispeed);
1351 #ifdef SOFT_HOTCHAR
1352 #define	MIN_RTP		1
1353 #else
1354 #define	MIN_RTP		5
1355 #endif
1356 	if (itimeout < MIN_RTP)
1357 		itimeout = MIN_RTP;
1358 	if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0
1359 	    && t->c_cc[VTIME] * 10 > itimeout)
1360 		itimeout = t->c_cc[VTIME] * 10;
1361 	if (itimeout > 255)
1362 		itimeout = 255;
1363 	cd_setreg(com, CD1400_RTPR, itimeout);
1364 
1365 	/*
1366 	 * set channel option register 2 -
1367 	 *	flow control
1368 	 */
1369 	opt = 0;
1370 #ifdef Smarts
1371 	if (iflag & IXANY)
1372 		opt |= CD1400_COR2_IXANY;
1373 	if (iflag & IXOFF)
1374 		opt |= CD1400_COR2_IXOFF;
1375 #endif
1376 #ifndef SOFT_CTS_OFLOW
1377 	if (cflag & CCTS_OFLOW)
1378 		opt |= CD1400_COR2_CCTS_OFLOW;
1379 #endif
1380 	critical_enter();
1381 	COM_LOCK();
1382 	if (opt != com->cor[1]) {
1383 		cor_change |= CD1400_CCR_COR2;
1384 		cd_setreg(com, CD1400_COR2, com->cor[1] = opt);
1385 	}
1386 	COM_UNLOCK();
1387 	critical_exit();
1388 
1389 	/*
1390 	 * set channel option register 3 -
1391 	 *	receiver FIFO interrupt threshold
1392 	 *	flow control
1393 	 */
1394 	opt = RxFifoThreshold;
1395 #ifdef Smarts
1396 	if (t->c_lflag & ICANON)
1397 		opt |= CD1400_COR3_SCD34;	/* detect INTR & SUSP chars */
1398 	if (iflag & IXOFF)
1399 		/* detect and transparently handle START and STOP chars */
1400 		opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12;
1401 #endif
1402 	if (opt != com->cor[2]) {
1403 		cor_change |= CD1400_CCR_COR3;
1404 		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
1405 	}
1406 
1407 	/* notify the CD1400 if COR1-3 have changed */
1408 	if (cor_change)
1409 		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change);
1410 
1411 	/*
1412 	 * set channel option register 4 -
1413 	 *	CR/NL processing
1414 	 *	break processing
1415 	 *	received exception processing
1416 	 */
1417 	opt = 0;
1418 	if (iflag & IGNCR)
1419 		opt |= CD1400_COR4_IGNCR;
1420 #ifdef Smarts
1421 	/*
1422 	 * we need a new ttyinput() for this, as we don't want to
1423 	 * have ICRNL && INLCR being done in both layers, or to have
1424 	 * synchronisation problems
1425 	 */
1426 	if (iflag & ICRNL)
1427 		opt |= CD1400_COR4_ICRNL;
1428 	if (iflag & INLCR)
1429 		opt |= CD1400_COR4_INLCR;
1430 #endif
1431 	if (iflag & IGNBRK)
1432 		opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT;
1433 	/*
1434 	 * The `-ignbrk -brkint parmrk' case is not handled by the hardware,
1435 	 * so only tell the hardware about -brkint if -parmrk.
1436 	 */
1437 	if (!(iflag & (BRKINT | PARMRK)))
1438 		opt |= CD1400_COR4_NOBRKINT;
1439 #if 0
1440 	/* XXX using this "intelligence" breaks reporting of overruns. */
1441 	if (iflag & IGNPAR)
1442 		opt |= CD1400_COR4_PFO_DISCARD;
1443 	else {
1444 		if (iflag & PARMRK)
1445 			opt |= CD1400_COR4_PFO_ESC;
1446 		else
1447 			opt |= CD1400_COR4_PFO_NUL;
1448 	}
1449 #else
1450 	opt |= CD1400_COR4_PFO_EXCEPTION;
1451 #endif
1452 	cd_setreg(com, CD1400_COR4, opt);
1453 
1454 	/*
1455 	 * set channel option register 5 -
1456 	 */
1457 	opt = 0;
1458 	if (iflag & ISTRIP)
1459 		opt |= CD1400_COR5_ISTRIP;
1460 	if (t->c_iflag & IEXTEN)
1461 		/* enable LNEXT (e.g. ctrl-v quoting) handling */
1462 		opt |= CD1400_COR5_LNEXT;
1463 #ifdef Smarts
1464 	if (t->c_oflag & ONLCR)
1465 		opt |= CD1400_COR5_ONLCR;
1466 	if (t->c_oflag & OCRNL)
1467 		opt |= CD1400_COR5_OCRNL;
1468 #endif
1469 	cd_setreg(com, CD1400_COR5, opt);
1470 
1471 	/*
1472 	 * We always generate modem status change interrupts for CD changes.
1473 	 * Among other things, this is necessary to track TS_CARR_ON for
1474 	 * pstat to print even when the driver doesn't care.  CD changes
1475 	 * should be rare so interrupts for them are not worth extra code to
1476 	 * avoid.  We avoid interrupts for other modem status changes (except
1477 	 * for CTS changes when SOFT_CTS_OFLOW is configured) since this is
1478 	 * simplest and best.
1479 	 */
1480 
1481 	/*
1482 	 * set modem change option register 1
1483 	 *	generate modem interrupts on which 1 -> 0 input transitions
1484 	 *	also controls auto-DTR output flow-control, which we don't use
1485 	 */
1486 	opt = CD1400_MCOR1_CDzd;
1487 #ifdef SOFT_CTS_OFLOW
1488 	if (cflag & CCTS_OFLOW)
1489 		opt |= CD1400_MCOR1_CTSzd;
1490 #endif
1491 	cd_setreg(com, CD1400_MCOR1, opt);
1492 
1493 	/*
1494 	 * set modem change option register 2
1495 	 *	generate modem interrupts on specific 0 -> 1 input transitions
1496 	 */
1497 	opt = CD1400_MCOR2_CDod;
1498 #ifdef SOFT_CTS_OFLOW
1499 	if (cflag & CCTS_OFLOW)
1500 		opt |= CD1400_MCOR2_CTSod;
1501 #endif
1502 	cd_setreg(com, CD1400_MCOR2, opt);
1503 
1504 	/*
1505 	 * XXX should have done this long ago, but there is too much state
1506 	 * to change all atomically.
1507 	 */
1508 	critical_enter();
1509 	COM_LOCK();
1510 
1511 	com->state &= ~CS_TTGO;
1512 	if (!(tp->t_state & TS_TTSTOP))
1513 		com->state |= CS_TTGO;
1514 	if (cflag & CRTS_IFLOW) {
1515 		com->state |= CS_RTS_IFLOW;
1516 		/*
1517 		 * If CS_RTS_IFLOW just changed from off to on, the change
1518 		 * needs to be propagated to CD1400_MSVR1_RTS.  This isn't urgent,
1519 		 * so do it later by calling cystart() instead of repeating
1520 		 * a lot of code from cystart() here.
1521 		 */
1522 	} else if (com->state & CS_RTS_IFLOW) {
1523 		com->state &= ~CS_RTS_IFLOW;
1524 		/*
1525 		 * CS_RTS_IFLOW just changed from on to off.  Force CD1400_MSVR1_RTS
1526 		 * on here, since cystart() won't do it later.
1527 		 */
1528 		cd_setreg(com, com->mcr_rts_reg,
1529 			  com->mcr_image |= com->mcr_rts);
1530 	}
1531 
1532 	/*
1533 	 * Set up state to handle output flow control.
1534 	 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
1535 	 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
1536 	 */
1537 	com->state |= CS_ODEVREADY;
1538 #ifdef SOFT_CTS_OFLOW
1539 	com->state &= ~CS_CTS_OFLOW;
1540 	if (cflag & CCTS_OFLOW) {
1541 		com->state |= CS_CTS_OFLOW;
1542 		if (!(com->last_modem_status & CD1400_MSVR2_CTS))
1543 			com->state &= ~CS_ODEVREADY;
1544 	}
1545 #endif
1546 	/* XXX shouldn't call functions while intrs are disabled. */
1547 	disc_optim(tp, t, com);
1548 #if 0
1549 	/*
1550 	 * Recover from fiddling with CS_TTGO.  We used to call cyintr1()
1551 	 * unconditionally, but that defeated the careful discarding of
1552 	 * stale input in cyopen().
1553 	 */
1554 	if (com->state >= (CS_BUSY | CS_TTGO))
1555 		cyintr1(com);
1556 #endif
1557 	if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1558 		if (!(com->intr_enable & CD1400_SRER_TXRDY))
1559 			cd_setreg(com, CD1400_SRER,
1560 				  com->intr_enable
1561 				  = (com->intr_enable & ~CD1400_SRER_TXMPTY)
1562 				    | CD1400_SRER_TXRDY);
1563 	} else {
1564 		if (com->intr_enable & CD1400_SRER_TXRDY)
1565 			cd_setreg(com, CD1400_SRER,
1566 				  com->intr_enable
1567 				  = (com->intr_enable & ~CD1400_SRER_TXRDY)
1568 				    | CD1400_SRER_TXMPTY);
1569 	}
1570 
1571 	COM_UNLOCK();
1572 	critical_exit();
1573 	splx(s);
1574 	cystart(tp);
1575 	if (com->ibufold != NULL) {
1576 		free(com->ibufold, M_DEVBUF);
1577 		com->ibufold = NULL;
1578 	}
1579 	return (0);
1580 }
1581 
1582 static int
cysetwater(struct com_s * com,speed_t speed)1583 cysetwater(struct com_s *com, speed_t speed)
1584 {
1585 	int		cp4ticks;
1586 	u_char		*ibuf;
1587 	int		ibufsize;
1588 	struct tty	*tp;
1589 
1590 	/*
1591 	 * Make the buffer size large enough to handle a softtty interrupt
1592 	 * latency of about 2 ticks without loss of throughput or data
1593 	 * (about 3 ticks if input flow control is not used or not honoured,
1594 	 * but a bit less for CS5-CS7 modes).
1595 	 */
1596 	cp4ticks = speed / 10 / hz * 4;
1597 	for (ibufsize = 128; ibufsize < cp4ticks;)
1598 		ibufsize <<= 1;
1599 	if (ibufsize == com->ibufsize) {
1600 		return (0);
1601 	}
1602 
1603 	/*
1604 	 * Allocate input buffer.  The extra factor of 2 in the size is
1605 	 * to allow for an error byte for each input byte.
1606 	 */
1607 	ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
1608 	if (ibuf == NULL) {
1609 		return (ENOMEM);
1610 	}
1611 
1612 	/* Initialize non-critical variables. */
1613 	com->ibufold = com->ibuf;
1614 	com->ibufsize = ibufsize;
1615 	tp = com->tp;
1616 	if (tp != NULL) {
1617 		tp->t_ififosize = 2 * ibufsize;
1618 		tp->t_ispeedwat = (speed_t)-1;
1619 		tp->t_ospeedwat = (speed_t)-1;
1620 	}
1621 
1622 	/*
1623 	 * Read current input buffer, if any.  Continue with interrupts
1624 	 * disabled.
1625 	 */
1626 	critical_enter();
1627 	COM_LOCK();
1628 	if (com->iptr != com->ibuf)
1629 		cyinput(com);
1630 
1631 	/*-
1632 	 * Initialize critical variables, including input buffer watermarks.
1633 	 * The external device is asked to stop sending when the buffer
1634 	 * exactly reaches high water, or when the high level requests it.
1635 	 * The high level is notified immediately (rather than at a later
1636 	 * clock tick) when this watermark is reached.
1637 	 * The buffer size is chosen so the watermark should almost never
1638 	 * be reached.
1639 	 * The low watermark is invisibly 0 since the buffer is always
1640 	 * emptied all at once.
1641 	 */
1642 	com->iptr = com->ibuf = ibuf;
1643 	com->ibufend = ibuf + ibufsize;
1644 	com->ierroff = ibufsize;
1645 	com->ihighwater = ibuf + 3 * ibufsize / 4;
1646 
1647 	COM_UNLOCK();
1648 	critical_exit();
1649 	return (0);
1650 }
1651 
1652 static void
cystart(struct tty * tp)1653 cystart(struct tty *tp)
1654 {
1655 	struct com_s	*com;
1656 	int		s;
1657 #ifdef CyDebug
1658 	bool_t		started;
1659 #endif
1660 
1661 	com = tp->t_sc;
1662 	s = spltty();
1663 
1664 #ifdef CyDebug
1665 	++com->start_count;
1666 	started = FALSE;
1667 #endif
1668 
1669 	critical_enter();
1670 	COM_LOCK();
1671 	if (tp->t_state & TS_TTSTOP) {
1672 		com->state &= ~CS_TTGO;
1673 		if (com->intr_enable & CD1400_SRER_TXRDY)
1674 			cd_setreg(com, CD1400_SRER,
1675 				  com->intr_enable
1676 				  = (com->intr_enable & ~CD1400_SRER_TXRDY)
1677 				    | CD1400_SRER_TXMPTY);
1678 	} else {
1679 		com->state |= CS_TTGO;
1680 		if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)
1681 		    && !(com->intr_enable & CD1400_SRER_TXRDY))
1682 			cd_setreg(com, CD1400_SRER,
1683 				  com->intr_enable
1684 				  = (com->intr_enable & ~CD1400_SRER_TXMPTY)
1685 				    | CD1400_SRER_TXRDY);
1686 	}
1687 	if (tp->t_state & TS_TBLOCK) {
1688 		if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW)
1689 #if 0
1690 			outb(com->modem_ctl_port, com->mcr_image &= ~CD1400_MSVR1_RTS);
1691 #else
1692 			cd_setreg(com, com->mcr_rts_reg,
1693 				  com->mcr_image &= ~com->mcr_rts);
1694 #endif
1695 	} else {
1696 		if (!(com->mcr_image & com->mcr_rts)
1697 		    && com->iptr < com->ihighwater
1698 		    && com->state & CS_RTS_IFLOW)
1699 #if 0
1700 			outb(com->modem_ctl_port, com->mcr_image |= CD1400_MSVR1_RTS);
1701 #else
1702 			cd_setreg(com, com->mcr_rts_reg,
1703 				  com->mcr_image |= com->mcr_rts);
1704 #endif
1705 	}
1706 	COM_UNLOCK();
1707 	critical_exit();
1708 	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1709 		ttwwakeup(tp);
1710 		splx(s);
1711 		return;
1712 	}
1713 	if (tp->t_outq.c_cc != 0) {
1714 		struct lbq	*qp;
1715 		struct lbq	*next;
1716 
1717 		if (!com->obufs[0].l_queued) {
1718 #ifdef CyDebug
1719 			started = TRUE;
1720 #endif
1721 			com->obufs[0].l_tail
1722 			    = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
1723 						  sizeof com->obuf1);
1724 			com->obufs[0].l_next = NULL;
1725 			com->obufs[0].l_queued = TRUE;
1726 			critical_enter();
1727 			COM_LOCK();
1728 			if (com->state & CS_BUSY) {
1729 				qp = com->obufq.l_next;
1730 				while ((next = qp->l_next) != NULL)
1731 					qp = next;
1732 				qp->l_next = &com->obufs[0];
1733 			} else {
1734 				com->obufq.l_head = com->obufs[0].l_head;
1735 				com->obufq.l_tail = com->obufs[0].l_tail;
1736 				com->obufq.l_next = &com->obufs[0];
1737 				com->state |= CS_BUSY;
1738 				if (com->state >= (CS_BUSY | CS_TTGO
1739 						   | CS_ODEVREADY))
1740 					cd_setreg(com, CD1400_SRER,
1741 						  com->intr_enable
1742 						  = (com->intr_enable
1743 						    & ~CD1400_SRER_TXMPTY)
1744 						    | CD1400_SRER_TXRDY);
1745 			}
1746 			COM_UNLOCK();
1747 			critical_exit();
1748 		}
1749 		if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
1750 #ifdef CyDebug
1751 			started = TRUE;
1752 #endif
1753 			com->obufs[1].l_tail
1754 			    = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
1755 						  sizeof com->obuf2);
1756 			com->obufs[1].l_next = NULL;
1757 			com->obufs[1].l_queued = TRUE;
1758 			critical_enter();
1759 			COM_LOCK();
1760 			if (com->state & CS_BUSY) {
1761 				qp = com->obufq.l_next;
1762 				while ((next = qp->l_next) != NULL)
1763 					qp = next;
1764 				qp->l_next = &com->obufs[1];
1765 			} else {
1766 				com->obufq.l_head = com->obufs[1].l_head;
1767 				com->obufq.l_tail = com->obufs[1].l_tail;
1768 				com->obufq.l_next = &com->obufs[1];
1769 				com->state |= CS_BUSY;
1770 				if (com->state >= (CS_BUSY | CS_TTGO
1771 						   | CS_ODEVREADY))
1772 					cd_setreg(com, CD1400_SRER,
1773 						  com->intr_enable
1774 						  = (com->intr_enable
1775 						    & ~CD1400_SRER_TXMPTY)
1776 						    | CD1400_SRER_TXRDY);
1777 			}
1778 			COM_UNLOCK();
1779 			critical_exit();
1780 		}
1781 		tp->t_state |= TS_BUSY;
1782 	}
1783 #ifdef CyDebug
1784 	if (started)
1785 		++com->start_real;
1786 #endif
1787 #if 0
1788 	critical_enter();
1789 	COM_LOCK();
1790 	if (com->state >= (CS_BUSY | CS_TTGO))
1791 		cyintr1(com);	/* fake interrupt to start output */
1792 	COM_UNLOCK();
1793 	critical_exit();
1794 #endif
1795 	ttwwakeup(tp);
1796 	splx(s);
1797 }
1798 
1799 static void
comstop(struct tty * tp,int rw)1800 comstop(struct tty *tp, int rw)
1801 {
1802 	struct com_s	*com;
1803 	bool_t		wakeup_etc;
1804 
1805 	com = tp->t_sc;
1806 	wakeup_etc = FALSE;
1807 	critical_enter();
1808 	COM_LOCK();
1809 	if (rw & FWRITE) {
1810 		com->obufs[0].l_queued = FALSE;
1811 		com->obufs[1].l_queued = FALSE;
1812 		if (com->extra_state & CSE_ODONE) {
1813 			cy_events -= LOTS_OF_EVENTS;
1814 			com->extra_state &= ~CSE_ODONE;
1815 			if (com->etc != ETC_NONE) {
1816 				if (com->etc == ETC_BREAK_ENDED)
1817 					com->etc = ETC_NONE;
1818 				wakeup_etc = TRUE;
1819 			}
1820 		}
1821 		com->tp->t_state &= ~TS_BUSY;
1822 		if (com->state & CS_ODONE)
1823 			cy_events -= LOTS_OF_EVENTS;
1824 		com->state &= ~(CS_ODONE | CS_BUSY);
1825 	}
1826 	if (rw & FREAD) {
1827 		/* XXX no way to reset only input fifo. */
1828 		cy_events -= (com->iptr - com->ibuf);
1829 		com->iptr = com->ibuf;
1830 	}
1831 	COM_UNLOCK();
1832 	critical_exit();
1833 	if (wakeup_etc)
1834 		wakeup(&com->etc);
1835 	if (rw & FWRITE && com->etc == ETC_NONE)
1836 		cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF);
1837 	cystart(tp);
1838 }
1839 
1840 static int
cymodem(struct tty * tp,int sigon,int sigoff)1841 cymodem(struct tty *tp, int sigon, int sigoff)
1842 {
1843 	struct com_s	*com;
1844 	int	mcr;
1845 	int	msr;
1846 
1847 	com = tp->t_sc;
1848 	if (sigon == 0 && sigoff == 0) {
1849 		sigon = 0;
1850 		mcr = com->mcr_image;
1851 		if (mcr & com->mcr_dtr)
1852 			sigon |= SER_DTR;
1853 		if (mcr & com->mcr_rts)
1854 			/* XXX wired on for Cyclom-8Ys */
1855 			sigon |= SER_RTS;
1856 
1857 		/*
1858 		 * We must read the modem status from the hardware because
1859 		 * we don't generate modem status change interrupts for all
1860 		 * changes, so com->prev_modem_status is not guaranteed to
1861 		 * be up to date.  This is safe, unlike for sio, because
1862 		 * reading the status register doesn't clear pending modem
1863 		 * status change interrupts.
1864 		 */
1865 		msr = cd_getreg(com, CD1400_MSVR2);
1866 
1867 		if (msr & CD1400_MSVR2_CTS)
1868 			sigon |= SER_CTS;
1869 		if (msr & CD1400_MSVR2_CD)
1870 			sigon |= SER_DCD;
1871 		if (msr & CD1400_MSVR2_DSR)
1872 			sigon |= SER_DSR;
1873 		if (msr & CD1400_MSVR2_RI)
1874 			/* XXX not connected except for Cyclom-16Y? */
1875 			sigon |= SER_RI;
1876 		return (sigon);
1877 	}
1878 	mcr = com->mcr_image;
1879 	if (sigon & SER_DTR)
1880 		mcr |= com->mcr_dtr;
1881 	if (sigoff & SER_DTR)
1882 		mcr &= ~com->mcr_dtr;
1883 	if (sigon & SER_RTS)
1884 		mcr |= com->mcr_rts;
1885 	if (sigoff & SER_RTS)
1886 		mcr &= ~com->mcr_rts;
1887 	critical_enter();
1888 	COM_LOCK();
1889 	com->mcr_image = mcr;
1890 	cd_setreg(com, CD1400_MSVR1, mcr);
1891 	cd_setreg(com, CD1400_MSVR2, mcr);
1892 	COM_UNLOCK();
1893 	critical_exit();
1894 	return (0);
1895 }
1896 
1897 static void
cysettimeout()1898 cysettimeout()
1899 {
1900 	struct com_s	*com;
1901 	bool_t		someopen;
1902 	int		unit;
1903 
1904 	/*
1905 	 * Set our timeout period to 1 second if no polled devices are open.
1906 	 * Otherwise set it to max(1/200, 1/hz).
1907 	 * Enable timeouts iff some device is open.
1908 	 */
1909 	untimeout(cywakeup, (void *)NULL, cy_timeout_handle);
1910 	cy_timeout = hz;
1911 	someopen = FALSE;
1912 	for (unit = 0; unit < NPORTS; ++unit) {
1913 		com = cy_addr(unit);
1914 		if (com != NULL && com->tp != NULL
1915 		    && com->tp->t_state & TS_ISOPEN) {
1916 			someopen = TRUE;
1917 		}
1918 	}
1919 	if (someopen) {
1920 		cy_timeouts_until_log = hz / cy_timeout;
1921 		cy_timeout_handle = timeout(cywakeup, (void *)NULL,
1922 					     cy_timeout);
1923 	} else {
1924 		/* Flush error messages, if any. */
1925 		cy_timeouts_until_log = 1;
1926 		cywakeup((void *)NULL);
1927 		untimeout(cywakeup, (void *)NULL, cy_timeout_handle);
1928 	}
1929 }
1930 
1931 static void
cywakeup(void * chan)1932 cywakeup(void *chan)
1933 {
1934 	struct com_s	*com;
1935 	int		unit;
1936 
1937 	cy_timeout_handle = timeout(cywakeup, (void *)NULL, cy_timeout);
1938 
1939 	/*
1940 	 * Check for and log errors, but not too often.
1941 	 */
1942 	if (--cy_timeouts_until_log > 0)
1943 		return;
1944 	cy_timeouts_until_log = hz / cy_timeout;
1945 	for (unit = 0; unit < NPORTS; ++unit) {
1946 		int	errnum;
1947 
1948 		com = cy_addr(unit);
1949 		if (com == NULL)
1950 			continue;
1951 		for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
1952 			u_int	delta;
1953 			u_long	total;
1954 
1955 			critical_enter();
1956 			COM_LOCK();
1957 			delta = com->delta_error_counts[errnum];
1958 			com->delta_error_counts[errnum] = 0;
1959 			COM_UNLOCK();
1960 			critical_exit();
1961 			if (delta == 0)
1962 				continue;
1963 			total = com->error_counts[errnum] += delta;
1964 			log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n",
1965 			    unit, delta, error_desc[errnum],
1966 			    delta == 1 ? "" : "s", total);
1967 		}
1968 	}
1969 }
1970 
1971 static void
disc_optim(struct tty * tp,struct termios * t,struct com_s * com)1972 disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
1973 {
1974 #ifndef SOFT_HOTCHAR
1975 	u_char	opt;
1976 #endif
1977 
1978 	ttyldoptim(tp);
1979 #ifndef SOFT_HOTCHAR
1980 	opt = com->cor[2] & ~CD1400_COR3_SCD34;
1981 	if (com->tp->t_hotchar != 0) {
1982 		cd_setreg(com, CD1400_SCHR3, com->tp->t_hotchar);
1983 		cd_setreg(com, CD1400_SCHR4, com->tp->t_hotchar);
1984 		opt |= CD1400_COR3_SCD34;
1985 	}
1986 	if (opt != com->cor[2]) {
1987 		cd_setreg(com, CD1400_COR3, com->cor[2] = opt);
1988 		cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3);
1989 	}
1990 #endif
1991 }
1992 
1993 #ifdef Smarts
1994 /* standard line discipline input routine */
1995 int
cyinput(int c,struct tty * tp)1996 cyinput(int c, struct tty *tp)
1997 {
1998 	/* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK
1999 	 * bits, as they are done by the CD1400.  Hardly worth the effort,
2000 	 * given that high-throughput session are raw anyhow.
2001 	 */
2002 }
2003 #endif /* Smarts */
2004 
2005 static int
cyspeed(speed_t speed,u_long cy_clock,int * prescaler_io)2006 cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io)
2007 {
2008 	int	actual;
2009 	int	error;
2010 	int	divider;
2011 	int	prescaler;
2012 	int	prescaler_unit;
2013 
2014 	if (speed == 0)
2015 		return (0);
2016 	if (speed < 0 || speed > 150000)
2017 		return (-1);
2018 
2019 	/* determine which prescaler to use */
2020 	for (prescaler_unit = 4, prescaler = 2048; prescaler_unit;
2021 		prescaler_unit--, prescaler >>= 2) {
2022 		if (cy_clock / prescaler / speed > 63)
2023 			break;
2024 	}
2025 
2026 	divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */
2027 	if (divider > 255)
2028 		divider = 255;
2029 	actual = cy_clock/prescaler/divider;
2030 
2031 	/* 10 times error in percent: */
2032 	error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2;
2033 
2034 	/* 3.0% max error tolerance */
2035 	if (error < -30 || error > 30)
2036 		return (-1);
2037 
2038 	*prescaler_io = prescaler_unit;
2039 	return (divider);
2040 }
2041 
2042 static void
cd1400_channel_cmd(struct com_s * com,int cmd)2043 cd1400_channel_cmd(struct com_s *com, int cmd)
2044 {
2045 	cd1400_channel_cmd_wait(com);
2046 	cd_setreg(com, CD1400_CCR, cmd);
2047 	cd1400_channel_cmd_wait(com);
2048 }
2049 
2050 static void
cd1400_channel_cmd_wait(struct com_s * com)2051 cd1400_channel_cmd_wait(struct com_s *com)
2052 {
2053 	struct timeval	start;
2054 	struct timeval	tv;
2055 	long		usec;
2056 
2057 	if (cd_getreg(com, CD1400_CCR) == 0)
2058 		return;
2059 	microtime(&start);
2060 	for (;;) {
2061 		if (cd_getreg(com, CD1400_CCR) == 0)
2062 			return;
2063 		microtime(&tv);
2064 		usec = 1000000 * (tv.tv_sec - start.tv_sec) +
2065 		    tv.tv_usec - start.tv_usec;
2066 		if (usec >= 5000) {
2067 			log(LOG_ERR,
2068 			    "cy%d: channel command timeout (%ld usec)\n",
2069 			    com->unit, usec);
2070 			return;
2071 		}
2072 	}
2073 }
2074 
2075 static void
cd_etc(struct com_s * com,int etc)2076 cd_etc(struct com_s *com, int etc)
2077 {
2078 
2079 	/*
2080 	 * We can't change the hardware's ETC state while there are any
2081 	 * characters in the tx fifo, since those characters would be
2082 	 * interpreted as commands!  Unputting characters from the fifo
2083 	 * is difficult, so we wait up to 12 character times for the fifo
2084 	 * to drain.  The command will be delayed for up to 2 character
2085 	 * times for the tx to become empty.  Unputting characters from
2086 	 * the tx holding and shift registers is impossible, so we wait
2087 	 * for the tx to become empty so that the command is sure to be
2088 	 * executed soon after we issue it.
2089 	 */
2090 	critical_enter();
2091 	COM_LOCK();
2092 	if (com->etc == etc)
2093 		goto wait;
2094 	if ((etc == CD1400_ETC_SENDBREAK
2095 	    && (com->etc == ETC_BREAK_STARTING
2096 		|| com->etc == ETC_BREAK_STARTED))
2097 	    || (etc == CD1400_ETC_STOPBREAK
2098 	       && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED
2099 		   || com->etc == ETC_NONE))) {
2100 		COM_UNLOCK();
2101 		critical_exit();
2102 		return;
2103 	}
2104 	com->etc = etc;
2105 	cd_setreg(com, CD1400_SRER,
2106 		  com->intr_enable
2107 		  = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY);
2108 wait:
2109 	COM_UNLOCK();
2110 	critical_exit();
2111 	while (com->etc == etc
2112 	       && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0)
2113 		continue;
2114 }
2115 
2116 static int
cd_getreg(struct com_s * com,int reg)2117 cd_getreg(struct com_s *com, int reg)
2118 {
2119 	struct com_s	*basecom;
2120 	u_char	car;
2121 	int	cy_align;
2122 	cy_addr	iobase;
2123 #ifdef SMP
2124 	int	need_unlock;
2125 #endif
2126 	int	val;
2127 
2128 	basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2129 	car = com->unit & CD1400_CAR_CHAN;
2130 	cy_align = com->cy_align;
2131 	iobase = com->iobase;
2132 	critical_enter();
2133 #ifdef SMP
2134 	need_unlock = 0;
2135 	if (!mtx_owned(&cy_lock)) {
2136 		COM_LOCK();
2137 		need_unlock = 1;
2138 	}
2139 #endif
2140 	if (basecom->car != car)
2141 		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2142 	val = cd_inb(iobase, reg, cy_align);
2143 #ifdef SMP
2144 	if (need_unlock)
2145 		COM_UNLOCK();
2146 #endif
2147 	critical_exit();
2148 	return (val);
2149 }
2150 
2151 static void
cd_setreg(struct com_s * com,int reg,int val)2152 cd_setreg(struct com_s *com, int reg, int val)
2153 {
2154 	struct com_s	*basecom;
2155 	u_char	car;
2156 	int	cy_align;
2157 	cy_addr	iobase;
2158 #ifdef SMP
2159 	int	need_unlock;
2160 #endif
2161 
2162 	basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1));
2163 	car = com->unit & CD1400_CAR_CHAN;
2164 	cy_align = com->cy_align;
2165 	iobase = com->iobase;
2166 	critical_enter();
2167 #ifdef SMP
2168 	need_unlock = 0;
2169 	if (!mtx_owned(&cy_lock)) {
2170 		COM_LOCK();
2171 		need_unlock = 1;
2172 	}
2173 #endif
2174 	if (basecom->car != car)
2175 		cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car);
2176 	cd_outb(iobase, reg, cy_align, val);
2177 #ifdef SMP
2178 	if (need_unlock)
2179 		COM_UNLOCK();
2180 #endif
2181 	critical_exit();
2182 }
2183 
2184 #ifdef CyDebug
2185 /* useful in ddb */
2186 void
cystatus(int unit)2187 cystatus(int unit)
2188 {
2189 	struct com_s	*com;
2190 	cy_addr		iobase;
2191 	u_int		ocount;
2192 	struct tty	*tp;
2193 
2194 	com = cy_addr(unit);
2195 	printf("info for channel %d\n", unit);
2196 	printf("------------------\n");
2197 	printf("total cyclom service probes:\t%d\n", cy_svrr_probes);
2198 	printf("calls to upper layer:\t\t%d\n", cy_timeouts);
2199 	if (com == NULL)
2200 		return;
2201 	iobase = com->iobase;
2202 	printf("\n");
2203 	printf("cd1400 base address:\\tt%p\n", iobase);
2204 	printf("saved channel_control:\t\t0x%02x\n", com->channel_control);
2205 	printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n",
2206 	       com->cor[0], com->cor[1], com->cor[2]);
2207 	printf("service request enable reg:\t0x%02x (0x%02x cached)\n",
2208 	       cd_getreg(com, CD1400_SRER), com->intr_enable);
2209 	printf("service request register:\t0x%02x\n",
2210 	       cd_inb(iobase, CD1400_SVRR, com->cy_align));
2211 	printf("modem status:\t\t\t0x%02x (0x%02x cached)\n",
2212 	       cd_getreg(com, CD1400_MSVR2), com->prev_modem_status);
2213 	printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n",
2214 	       cd_inb(iobase, CD1400_RIR, com->cy_align),
2215 	       cd_inb(iobase, CD1400_TIR, com->cy_align),
2216 	       cd_inb(iobase, CD1400_MIR, com->cy_align));
2217 	printf("\n");
2218 	printf("com state:\t\t\t0x%02x\n", com->state);
2219 	printf("calls to cystart():\t\t%d (%d useful)\n",
2220 	       com->start_count, com->start_real);
2221 	printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf);
2222 	ocount = 0;
2223 	if (com->obufs[0].l_queued)
2224 		ocount += com->obufs[0].l_tail - com->obufs[0].l_head;
2225 	if (com->obufs[1].l_queued)
2226 		ocount += com->obufs[1].l_tail - com->obufs[1].l_head;
2227 	printf("tx buffer chars:\t\t%u\n", ocount);
2228 	printf("received chars:\t\t\t%d\n", com->bytes_in);
2229 	printf("received exceptions:\t\t%d\n", com->recv_exception);
2230 	printf("modem signal deltas:\t\t%d\n", com->mdm);
2231 	printf("transmitted chars:\t\t%d\n", com->bytes_out);
2232 	printf("\n");
2233 	tp = com->tp;
2234 	if (tp != NULL) {
2235 		printf("tty state:\t\t\t0x%08x\n", tp->t_state);
2236 		printf(
2237 		"upper layer queue lengths:\t%d raw, %d canon, %d output\n",
2238 		       tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc);
2239 	} else
2240 		printf("tty state:\t\t\tclosed\n");
2241 }
2242 #endif /* CyDebug */
2243