1/*	$OpenBSD: com.c,v 1.179 2024/05/13 01:15:50 jsg Exp $	*/
2/*	$NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $	*/
3
4/*
5 * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*-
29 * Copyright (c) 1993, 1994, 1995, 1996
30 *	Charles M. Hannum.  All rights reserved.
31 * Copyright (c) 1991 The Regents of the University of California.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 *    notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 *    notice, this list of conditions and the following disclaimer in the
41 *    documentation and/or other materials provided with the distribution.
42 * 3. Neither the name of the University nor the names of its contributors
43 *    may be used to endorse or promote products derived from this software
44 *    without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 *	@(#)com.c	7.5 (Berkeley) 5/16/91
59 */
60
61/*
62 * COM driver, based on HP dca driver
63 * uses National Semiconductor NS16450/NS16550AF UART
64 */
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/ioctl.h>
68#include <sys/tty.h>
69#include <sys/conf.h>
70#include <sys/fcntl.h>
71#include <sys/uio.h>
72#include <sys/kernel.h>
73#include <sys/syslog.h>
74#include <sys/device.h>
75#include <sys/vnode.h>
76#ifdef DDB
77#include <ddb/db_var.h>
78#endif
79
80#include <machine/bus.h>
81#include <machine/intr.h>
82
83#define	COM_CONSOLE
84#include <dev/cons.h>
85
86#include <dev/ic/comreg.h>
87#include <dev/ic/comvar.h>
88#include <dev/ic/ns16550reg.h>
89#define	com_lcr	com_cfcr
90
91cdev_decl(com);
92
93static u_char tiocm_xxx2mcr(int);
94
95void	compwroff(struct com_softc *);
96void	cominit(bus_space_tag_t, bus_space_handle_t, int, int);
97
98struct cfdriver com_cd = {
99	NULL, "com", DV_TTY
100};
101
102int	comdefaultrate = TTYDEF_SPEED;
103#ifdef COM_CONSOLE
104int	comconsfreq;
105int	comconsrate = TTYDEF_SPEED;
106bus_addr_t comconsaddr = 0;
107int	comconsattached;
108bus_space_tag_t comconsiot;
109bus_space_handle_t comconsioh;
110int	comconsunit;
111tcflag_t comconscflag = TTYDEF_CFLAG;
112#endif
113
114int	commajor;
115
116#define	DEVUNIT(x)	(minor(x) & 0x7f)
117#define	DEVCUA(x)	(minor(x) & 0x80)
118
119int
120comspeed(long freq, long speed)
121{
122#define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */
123
124	int x, err;
125
126	if (speed == 0)
127		return 0;
128	if (speed < 0)
129		return -1;
130	x = divrnd((freq / 16), speed);
131	if (x <= 0)
132		return -1;
133	err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
134	if (err < 0)
135		err = -err;
136	if (err > COM_TOLERANCE)
137		return -1;
138	return x;
139
140#undef	divrnd
141}
142
143#ifdef COM_CONSOLE
144int
145comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
146{
147	int i;
148
149	/* force access to id reg */
150	bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
151	bus_space_write_1(iot, ioh, com_iir, 0);
152	for (i = 0; i < 32; i++) {
153		if ((bus_space_read_1(iot, ioh, com_lcr) != LCR_8BITS) ||
154		    (bus_space_read_1(iot, ioh, com_iir) & 0x38)) {
155			bus_space_read_1(iot, ioh, com_data); /* cleanup */
156		} else
157			break;
158	}
159	if (i >= 32)
160		return 0;
161
162	return 1;
163}
164#endif
165
166int
167com_detach(struct device *self, int flags)
168{
169	struct com_softc *sc = (struct com_softc *)self;
170	int maj, mn;
171
172	sc->sc_swflags |= COM_SW_DEAD;
173
174	/* Locate the major number. */
175	for (maj = 0; maj < nchrdev; maj++)
176		if (cdevsw[maj].d_open == comopen)
177			break;
178
179	/* Nuke the vnodes for any open instances. */
180	mn = self->dv_unit;
181	vdevgone(maj, mn, mn, VCHR);
182
183	/* XXX a symbolic constant for the cua bit would be nicer. */
184	mn |= 0x80;
185	vdevgone(maj, mn, mn, VCHR);
186
187	timeout_del(&sc->sc_dtr_tmo);
188	timeout_del(&sc->sc_diag_tmo);
189	softintr_disestablish(sc->sc_si);
190
191	/* Detach and free the tty. */
192	if (sc->sc_tty) {
193		ttyfree(sc->sc_tty);
194	}
195
196	return (0);
197}
198
199int
200com_activate(struct device *self, int act)
201{
202	struct com_softc *sc = (struct com_softc *)self;
203	int s, rv = 0;
204
205	switch (act) {
206	case DVACT_SUSPEND:
207		if (timeout_del(&sc->sc_dtr_tmo)) {
208			/* Make sure DTR gets raised upon resume. */
209			SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
210		}
211		timeout_del(&sc->sc_diag_tmo);
212		break;
213	case DVACT_RESUME:
214		com_resume(sc);
215		break;
216	case DVACT_DEACTIVATE:
217		if (sc->sc_hwflags & COM_HW_CONSOLE) {
218			rv = EBUSY;
219			break;
220		}
221
222		s = spltty();
223		if (sc->disable != NULL && sc->enabled != 0) {
224			(*sc->disable)(sc);
225			sc->enabled = 0;
226		}
227		splx(s);
228		break;
229	}
230	return (rv);
231}
232
233int
234comopen(dev_t dev, int flag, int mode, struct proc *p)
235{
236	int unit = DEVUNIT(dev);
237	struct com_softc *sc;
238	struct tty *tp;
239	int s;
240	int error = 0;
241
242	if (unit >= com_cd.cd_ndevs)
243		return ENXIO;
244	sc = com_cd.cd_devs[unit];
245	if (!sc)
246		return ENXIO;
247
248	s = spltty();
249	if (!sc->sc_tty) {
250		tp = sc->sc_tty = ttymalloc(1000000);
251	} else
252		tp = sc->sc_tty;
253	splx(s);
254
255	tp->t_oproc = comstart;
256	tp->t_param = comparam;
257	tp->t_dev = dev;
258	if (!ISSET(tp->t_state, TS_ISOPEN)) {
259		SET(tp->t_state, TS_WOPEN);
260		ttychars(tp);
261		tp->t_iflag = TTYDEF_IFLAG;
262		tp->t_oflag = TTYDEF_OFLAG;
263#ifdef COM_CONSOLE
264		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
265			tp->t_cflag = comconscflag;
266			tp->t_ispeed = tp->t_ospeed = comconsrate;
267		} else
268#endif
269		{
270			tp->t_cflag = TTYDEF_CFLAG;
271			tp->t_ispeed = tp->t_ospeed = comdefaultrate;
272		}
273		if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
274			SET(tp->t_cflag, CLOCAL);
275		if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
276			SET(tp->t_cflag, CRTSCTS);
277		if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
278			SET(tp->t_cflag, MDMBUF);
279		tp->t_lflag = TTYDEF_LFLAG;
280
281		s = spltty();
282
283		sc->sc_initialize = 1;
284		comparam(tp, &tp->t_termios);
285		ttsetwater(tp);
286
287		sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
288		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
289		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
290
291		/*
292		 * Wake up the sleepy heads.
293		 */
294		if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
295			switch (sc->sc_uarttype) {
296			case COM_UART_ST16650:
297			case COM_UART_ST16650V2:
298				com_write_reg(sc, com_lcr, LCR_EFR);
299				com_write_reg(sc, com_efr, EFR_ECB);
300				com_write_reg(sc, com_ier, 0);
301				com_write_reg(sc, com_efr, 0);
302				com_write_reg(sc, com_lcr, 0);
303				break;
304			case COM_UART_TI16750:
305				com_write_reg(sc, com_ier, 0);
306				break;
307			case COM_UART_XR17V35X:
308				com_write_reg(sc, UART_EXAR_SLEEP, 0);
309				break;
310			}
311		}
312
313		if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
314			u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
315			u_int8_t lcr;
316
317			if (tp->t_ispeed <= 1200)
318				fifo |= FIFO_TRIGGER_1;
319			else if (tp->t_ispeed <= 38400)
320				fifo |= FIFO_TRIGGER_4;
321			else
322				fifo |= FIFO_TRIGGER_8;
323			if (sc->sc_uarttype == COM_UART_TI16750) {
324				fifo |= FIFO_ENABLE_64BYTE;
325				lcr = com_read_reg(sc, com_lcr);
326				com_write_reg(sc, com_lcr,
327				    lcr | LCR_DLAB);
328			}
329
330			/*
331			 * (Re)enable and drain FIFOs.
332			 *
333			 * Certain SMC chips cause problems if the FIFOs are
334			 * enabled while input is ready. Turn off the FIFO
335			 * if necessary to clear the input. Test the input
336			 * ready bit after enabling the FIFOs to handle races
337			 * between enabling and fresh input.
338			 *
339			 * Set the FIFO threshold based on the receive speed.
340			 */
341			for (;;) {
342				com_write_reg(sc, com_fifo, 0);
343				delay(100);
344				(void) com_read_reg(sc, com_data);
345				com_write_reg(sc, com_fifo, fifo |
346				    FIFO_RCV_RST | FIFO_XMT_RST);
347				delay(100);
348				if(!ISSET(com_read_reg(sc,
349				    com_lsr), LSR_RXRDY))
350					break;
351			}
352			if (sc->sc_uarttype == COM_UART_TI16750)
353				com_write_reg(sc, com_lcr, lcr);
354		}
355
356		/* Flush any pending I/O. */
357		while (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
358			(void) com_read_reg(sc, com_data);
359
360		/* You turn me on, baby! */
361		sc->sc_mcr = MCR_DTR | MCR_RTS;
362		if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
363			SET(sc->sc_mcr, MCR_IENABLE);
364		com_write_reg(sc, com_mcr, sc->sc_mcr);
365		sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
366		com_write_reg(sc, com_ier, sc->sc_ier);
367
368		sc->sc_msr = com_read_reg(sc, com_msr);
369		if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
370		    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
371			SET(tp->t_state, TS_CARR_ON);
372		else
373			CLR(tp->t_state, TS_CARR_ON);
374	} else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0)
375		return EBUSY;
376	else
377		s = spltty();
378
379	if (DEVCUA(dev)) {
380		if (ISSET(tp->t_state, TS_ISOPEN)) {
381			/* Ah, but someone already is dialed in... */
382			splx(s);
383			return EBUSY;
384		}
385		sc->sc_cua = 1;		/* We go into CUA mode. */
386	} else {
387		/* tty (not cua) device; wait for carrier if necessary. */
388		if (ISSET(flag, O_NONBLOCK)) {
389			if (sc->sc_cua) {
390				/* Opening TTY non-blocking... but the CUA is busy. */
391				splx(s);
392				return EBUSY;
393			}
394		} else {
395			while (sc->sc_cua ||
396			    (!ISSET(tp->t_cflag, CLOCAL) &&
397				!ISSET(tp->t_state, TS_CARR_ON))) {
398				SET(tp->t_state, TS_WOPEN);
399				error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen);
400				/*
401				 * If TS_WOPEN has been reset, that means the cua device
402				 * has been closed.  We don't want to fail in that case,
403				 * so just go around again.
404				 */
405				if (error && ISSET(tp->t_state, TS_WOPEN)) {
406					CLR(tp->t_state, TS_WOPEN);
407					if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
408						compwroff(sc);
409					splx(s);
410					return error;
411				}
412			}
413		}
414	}
415	splx(s);
416
417	return (*linesw[tp->t_line].l_open)(dev, tp, p);
418}
419
420int
421comclose(dev_t dev, int flag, int mode, struct proc *p)
422{
423	int unit = DEVUNIT(dev);
424	struct com_softc *sc = com_cd.cd_devs[unit];
425	struct tty *tp = sc->sc_tty;
426	int s;
427
428#ifdef COM_CONSOLE
429	/* XXX This is for cons.c. */
430	if (!ISSET(tp->t_state, TS_ISOPEN))
431		return 0;
432#endif
433
434	if(sc->sc_swflags & COM_SW_DEAD)
435		return 0;
436
437	(*linesw[tp->t_line].l_close)(tp, flag, p);
438	s = spltty();
439	if (ISSET(tp->t_state, TS_WOPEN)) {
440		/* tty device is waiting for carrier; drop dtr then re-raise */
441		CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
442		com_write_reg(sc, com_mcr, sc->sc_mcr);
443		timeout_add_sec(&sc->sc_dtr_tmo, 2);
444	} else {
445		/* no one else waiting; turn off the uart */
446		compwroff(sc);
447	}
448	CLR(tp->t_state, TS_BUSY | TS_FLUSH);
449	sc->sc_cua = 0;
450	splx(s);
451	ttyclose(tp);
452
453#ifdef COM_CONSOLE
454#ifdef notyet /* XXXX */
455	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
456		ttyfree(tp);
457		sc->sc_tty = 0;
458	}
459#endif
460#endif
461	return 0;
462}
463
464void
465compwroff(struct com_softc *sc)
466{
467	struct tty *tp = sc->sc_tty;
468
469	CLR(sc->sc_lcr, LCR_SBREAK);
470	com_write_reg(sc, com_lcr, sc->sc_lcr);
471	com_write_reg(sc, com_ier, 0);
472	if (ISSET(tp->t_cflag, HUPCL) &&
473	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
474		/* XXX perhaps only clear DTR */
475		sc->sc_mcr = 0;
476		com_write_reg(sc, com_mcr, sc->sc_mcr);
477	}
478
479	/*
480	 * Turn FIFO off; enter sleep mode if possible.
481	 */
482	com_write_reg(sc, com_fifo, 0);
483	delay(100);
484	if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
485		(void) com_read_reg(sc, com_data);
486	delay(100);
487	com_write_reg(sc, com_fifo,
488			  FIFO_RCV_RST | FIFO_XMT_RST);
489
490	if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
491		switch (sc->sc_uarttype) {
492		case COM_UART_ST16650:
493		case COM_UART_ST16650V2:
494			com_write_reg(sc, com_lcr, LCR_EFR);
495			com_write_reg(sc, com_efr, EFR_ECB);
496			com_write_reg(sc, com_ier, IER_SLEEP);
497			com_write_reg(sc, com_lcr, 0);
498			break;
499		case COM_UART_TI16750:
500			com_write_reg(sc, com_ier, IER_SLEEP);
501			break;
502		case COM_UART_XR17V35X:
503			com_write_reg(sc, UART_EXAR_SLEEP, 0xff);
504			break;
505		}
506	}
507}
508
509void
510com_resume(struct com_softc *sc)
511{
512	struct tty *tp = sc->sc_tty;
513	int ospeed;
514
515	if (!tp || !ISSET(tp->t_state, TS_ISOPEN)) {
516#ifdef COM_CONSOLE
517		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
518			cominit(comconsiot, comconsioh, comconsrate,
519			    comconsfreq);
520#endif
521		return;
522	}
523
524	/*
525	 * Wake up the sleepy heads.
526	 */
527	if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
528		switch (sc->sc_uarttype) {
529		case COM_UART_ST16650:
530		case COM_UART_ST16650V2:
531			com_write_reg(sc, com_lcr, LCR_EFR);
532			com_write_reg(sc, com_efr, EFR_ECB);
533			com_write_reg(sc, com_ier, 0);
534			com_write_reg(sc, com_efr, 0);
535			com_write_reg(sc, com_lcr, 0);
536			break;
537		case COM_UART_TI16750:
538			com_write_reg(sc, com_ier, 0);
539			break;
540		case COM_UART_XR17V35X:
541			com_write_reg(sc, UART_EXAR_SLEEP, 0);
542			break;
543		}
544	}
545
546	ospeed = comspeed(sc->sc_frequency, tp->t_ospeed);
547
548	if (ospeed != 0) {
549		com_write_reg(sc, com_lcr, sc->sc_lcr | LCR_DLAB);
550		com_write_reg(sc, com_dlbl, ospeed);
551		com_write_reg(sc, com_dlbh, ospeed >> 8);
552		com_write_reg(sc, com_lcr, sc->sc_lcr);
553	} else {
554		com_write_reg(sc, com_lcr, sc->sc_lcr);
555	}
556
557	if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
558		u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
559		u_int8_t lcr;
560
561		if (tp->t_ispeed <= 1200)
562			fifo |= FIFO_TRIGGER_1;
563		else if (tp->t_ispeed <= 38400)
564			fifo |= FIFO_TRIGGER_4;
565		else
566			fifo |= FIFO_TRIGGER_8;
567		if (sc->sc_uarttype == COM_UART_TI16750) {
568			fifo |= FIFO_ENABLE_64BYTE;
569			lcr = com_read_reg(sc, com_lcr);
570			com_write_reg(sc, com_lcr,
571			    lcr | LCR_DLAB);
572		}
573
574		/*
575		 * (Re)enable and drain FIFOs.
576		 *
577		 * Certain SMC chips cause problems if the FIFOs are
578		 * enabled while input is ready. Turn off the FIFO
579		 * if necessary to clear the input. Test the input
580		 * ready bit after enabling the FIFOs to handle races
581		 * between enabling and fresh input.
582		 *
583		 * Set the FIFO threshold based on the receive speed.
584		 */
585		for (;;) {
586			com_write_reg(sc, com_fifo, 0);
587			delay(100);
588			(void) com_read_reg(sc, com_data);
589			com_write_reg(sc, com_fifo, fifo |
590			    FIFO_RCV_RST | FIFO_XMT_RST);
591			delay(100);
592			if(!ISSET(com_read_reg(sc,
593			    com_lsr), LSR_RXRDY))
594				break;
595		}
596		if (sc->sc_uarttype == COM_UART_TI16750)
597			com_write_reg(sc, com_lcr, lcr);
598	}
599
600	/* You turn me on, baby! */
601	com_write_reg(sc, com_mcr, sc->sc_mcr);
602	com_write_reg(sc, com_ier, sc->sc_ier);
603}
604
605void
606com_raisedtr(void *arg)
607{
608	struct com_softc *sc = arg;
609
610	SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
611	com_write_reg(sc, com_mcr, sc->sc_mcr);
612}
613
614int
615comread(dev_t dev, struct uio *uio, int flag)
616{
617	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
618	struct tty *tp = sc->sc_tty;
619
620	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
621}
622
623int
624comwrite(dev_t dev, struct uio *uio, int flag)
625{
626	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
627	struct tty *tp = sc->sc_tty;
628
629	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
630}
631
632struct tty *
633comtty(dev_t dev)
634{
635	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
636	struct tty *tp = sc->sc_tty;
637
638	return (tp);
639}
640
641static u_char
642tiocm_xxx2mcr(int data)
643{
644	u_char m = 0;
645
646	if (ISSET(data, TIOCM_DTR))
647		SET(m, MCR_DTR);
648	if (ISSET(data, TIOCM_RTS))
649		SET(m, MCR_RTS);
650	return m;
651}
652
653int
654comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
655{
656	int unit = DEVUNIT(dev);
657	struct com_softc *sc = com_cd.cd_devs[unit];
658	struct tty *tp = sc->sc_tty;
659	int error;
660
661	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
662	if (error >= 0)
663		return error;
664	error = ttioctl(tp, cmd, data, flag, p);
665	if (error >= 0)
666		return error;
667
668	switch (cmd) {
669	case TIOCSBRK:
670		SET(sc->sc_lcr, LCR_SBREAK);
671		com_write_reg(sc, com_lcr, sc->sc_lcr);
672		break;
673	case TIOCCBRK:
674		CLR(sc->sc_lcr, LCR_SBREAK);
675		com_write_reg(sc, com_lcr, sc->sc_lcr);
676		break;
677	case TIOCSDTR:
678		SET(sc->sc_mcr, sc->sc_dtr);
679		com_write_reg(sc, com_mcr, sc->sc_mcr);
680		break;
681	case TIOCCDTR:
682		CLR(sc->sc_mcr, sc->sc_dtr);
683		com_write_reg(sc, com_mcr, sc->sc_mcr);
684		break;
685	case TIOCMSET:
686		CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
687	case TIOCMBIS:
688		SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
689		com_write_reg(sc, com_mcr, sc->sc_mcr);
690		break;
691	case TIOCMBIC:
692		CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
693		com_write_reg(sc, com_mcr, sc->sc_mcr);
694		break;
695	case TIOCMGET: {
696		u_char m;
697		int bits = 0;
698
699		m = sc->sc_mcr;
700		if (ISSET(m, MCR_DTR))
701			SET(bits, TIOCM_DTR);
702		if (ISSET(m, MCR_RTS))
703			SET(bits, TIOCM_RTS);
704		m = sc->sc_msr;
705		if (ISSET(m, MSR_DCD))
706			SET(bits, TIOCM_CD);
707		if (ISSET(m, MSR_CTS))
708			SET(bits, TIOCM_CTS);
709		if (ISSET(m, MSR_DSR))
710			SET(bits, TIOCM_DSR);
711		if (ISSET(m, MSR_RI | MSR_TERI))
712			SET(bits, TIOCM_RI);
713		if (com_read_reg(sc, com_ier))
714			SET(bits, TIOCM_LE);
715		*(int *)data = bits;
716		break;
717	}
718	case TIOCGFLAGS: {
719		int driverbits, userbits = 0;
720
721		driverbits = sc->sc_swflags;
722		if (ISSET(driverbits, COM_SW_SOFTCAR))
723			SET(userbits, TIOCFLAG_SOFTCAR);
724		if (ISSET(driverbits, COM_SW_CLOCAL))
725			SET(userbits, TIOCFLAG_CLOCAL);
726		if (ISSET(driverbits, COM_SW_CRTSCTS))
727			SET(userbits, TIOCFLAG_CRTSCTS);
728		if (ISSET(driverbits, COM_SW_MDMBUF))
729			SET(userbits, TIOCFLAG_MDMBUF);
730		if (ISSET(driverbits, COM_SW_PPS))
731			SET(userbits, TIOCFLAG_PPS);
732
733		*(int *)data = userbits;
734		break;
735	}
736	case TIOCSFLAGS: {
737		int userbits, driverbits = 0;
738
739		error = suser(p);
740		if (error != 0)
741			return(EPERM);
742
743		userbits = *(int *)data;
744		if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
745		    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
746			SET(driverbits, COM_SW_SOFTCAR);
747		if (ISSET(userbits, TIOCFLAG_CLOCAL))
748			SET(driverbits, COM_SW_CLOCAL);
749		if (ISSET(userbits, TIOCFLAG_CRTSCTS))
750			SET(driverbits, COM_SW_CRTSCTS);
751		if (ISSET(userbits, TIOCFLAG_MDMBUF))
752			SET(driverbits, COM_SW_MDMBUF);
753		if (ISSET(userbits, TIOCFLAG_PPS))
754			SET(driverbits, COM_SW_PPS);
755
756		sc->sc_swflags = driverbits;
757		break;
758	}
759	default:
760		return ENOTTY;
761	}
762
763	return 0;
764}
765
766/* already called at spltty */
767int
768comparam(struct tty *tp, struct termios *t)
769{
770	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
771	int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
772	u_char lcr;
773	tcflag_t oldcflag;
774
775	/* Check requested parameters. */
776	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
777		return EINVAL;
778
779	lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
780
781	switch (ISSET(t->c_cflag, CSIZE)) {
782	case CS5:
783		SET(lcr, LCR_5BITS);
784		break;
785	case CS6:
786		SET(lcr, LCR_6BITS);
787		break;
788	case CS7:
789		SET(lcr, LCR_7BITS);
790		break;
791	case CS8:
792		SET(lcr, LCR_8BITS);
793		break;
794	}
795	if (ISSET(t->c_cflag, PARENB)) {
796		SET(lcr, LCR_PENAB);
797		if (!ISSET(t->c_cflag, PARODD))
798			SET(lcr, LCR_PEVEN);
799	}
800	if (ISSET(t->c_cflag, CSTOPB))
801		SET(lcr, LCR_STOPB);
802
803	sc->sc_lcr = lcr;
804
805	if (ospeed == 0) {
806		CLR(sc->sc_mcr, MCR_DTR);
807		com_write_reg(sc, com_mcr, sc->sc_mcr);
808	}
809
810	/*
811	 * Set the FIFO threshold based on the receive speed, if we are
812	 * changing it.
813	 */
814	if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
815		sc->sc_initialize = 0;
816
817		if (ospeed != 0) {
818			/*
819			 * Make sure the transmit FIFO is empty before
820			 * proceeding.  If we don't do this, some revisions
821			 * of the UART will hang.  Interestingly enough,
822			 * even if we do this while the last character is
823			 * still being pushed out, they don't hang.  This
824			 * seems good enough.
825			 */
826			while (ISSET(tp->t_state, TS_BUSY)) {
827				int error;
828
829				++sc->sc_halt;
830				error = ttysleep(tp, &tp->t_outq,
831				    TTOPRI | PCATCH, "comprm");
832				--sc->sc_halt;
833				if (error) {
834					comstart(tp);
835					return (error);
836				}
837			}
838
839			com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
840			com_write_reg(sc, com_dlbl, ospeed);
841			com_write_reg(sc, com_dlbh, ospeed >> 8);
842			com_write_reg(sc, com_lcr, lcr);
843			SET(sc->sc_mcr, MCR_DTR);
844			com_write_reg(sc, com_mcr, sc->sc_mcr);
845		} else
846			com_write_reg(sc, com_lcr, lcr);
847
848		if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
849			if (sc->sc_uarttype == COM_UART_TI16750) {
850				com_write_reg(sc, com_lcr,
851				    lcr | LCR_DLAB);
852				com_write_reg(sc, com_fifo,
853				    FIFO_ENABLE | FIFO_ENABLE_64BYTE |
854				    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
855				com_write_reg(sc, com_lcr, lcr);
856			} else
857				com_write_reg(sc, com_fifo,
858				    FIFO_ENABLE |
859				    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
860		}
861	} else
862		com_write_reg(sc, com_lcr, lcr);
863
864	/* When not using CRTSCTS, RTS follows DTR. */
865	if (!ISSET(t->c_cflag, CRTSCTS)) {
866		if (ISSET(sc->sc_mcr, MCR_DTR)) {
867			if (!ISSET(sc->sc_mcr, MCR_RTS)) {
868				SET(sc->sc_mcr, MCR_RTS);
869				com_write_reg(sc, com_mcr, sc->sc_mcr);
870			}
871		} else {
872			if (ISSET(sc->sc_mcr, MCR_RTS)) {
873				CLR(sc->sc_mcr, MCR_RTS);
874				com_write_reg(sc, com_mcr, sc->sc_mcr);
875			}
876		}
877		sc->sc_dtr = MCR_DTR | MCR_RTS;
878	} else
879		sc->sc_dtr = MCR_DTR;
880
881	/* and copy to tty */
882	tp->t_ispeed = t->c_ispeed;
883	tp->t_ospeed = t->c_ospeed;
884	oldcflag = tp->t_cflag;
885	tp->t_cflag = t->c_cflag;
886
887	/*
888	 * If DCD is off and MDMBUF is changed, ask the tty layer if we should
889	 * stop the device.
890	 */
891	if (!ISSET(sc->sc_msr, MSR_DCD) &&
892	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
893	    ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
894	    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
895		CLR(sc->sc_mcr, sc->sc_dtr);
896		com_write_reg(sc, com_mcr, sc->sc_mcr);
897	}
898
899	/* Just to be sure... */
900	comstart(tp);
901	return 0;
902}
903
904void
905comstart(struct tty *tp)
906{
907	struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
908	int s;
909
910	s = spltty();
911	if (ISSET(tp->t_state, TS_BUSY))
912		goto out;
913	if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
914		goto stopped;
915	if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
916		goto stopped;
917	ttwakeupwr(tp);
918	if (tp->t_outq.c_cc == 0)
919		goto stopped;
920	SET(tp->t_state, TS_BUSY);
921
922	/* Enable transmit completion interrupts. */
923	if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
924		SET(sc->sc_ier, IER_ETXRDY);
925		com_write_reg(sc, com_ier, sc->sc_ier);
926	}
927
928	if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
929		u_char buffer[256];	/* largest fifo */
930		int i, n;
931
932		n = q_to_b(&tp->t_outq, buffer,
933		    min(sc->sc_fifolen, sizeof buffer));
934		for (i = 0; i < n; i++) {
935			com_write_reg(sc, com_data, buffer[i]);
936		}
937		bzero(buffer, n);
938	} else if (tp->t_outq.c_cc != 0)
939		com_write_reg(sc, com_data, getc(&tp->t_outq));
940out:
941	splx(s);
942	return;
943stopped:
944	if (ISSET(sc->sc_ier, IER_ETXRDY)) {
945		CLR(sc->sc_ier, IER_ETXRDY);
946		com_write_reg(sc, com_ier, sc->sc_ier);
947	}
948	splx(s);
949}
950
951/*
952 * Stop output on a line.
953 */
954int
955comstop(struct tty *tp, int flag)
956{
957	int s;
958
959	s = spltty();
960	if (ISSET(tp->t_state, TS_BUSY))
961		if (!ISSET(tp->t_state, TS_TTSTOP))
962			SET(tp->t_state, TS_FLUSH);
963	splx(s);
964	return 0;
965}
966
967void
968comdiag(void *arg)
969{
970	struct com_softc *sc = arg;
971	int overflows, floods;
972	int s;
973
974	s = spltty();
975	sc->sc_errors = 0;
976	overflows = sc->sc_overflows;
977	sc->sc_overflows = 0;
978	floods = sc->sc_floods;
979	sc->sc_floods = 0;
980	splx(s);
981	log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
982	    sc->sc_dev.dv_xname,
983	    overflows, overflows == 1 ? "" : "s",
984	    floods, floods == 1 ? "" : "s");
985}
986
987void
988comsoft(void *arg)
989{
990	struct com_softc *sc = (struct com_softc *)arg;
991	struct tty *tp;
992	u_char *ibufp;
993	u_char *ibufend;
994	int c;
995	int s;
996	static int lsrmap[8] = {
997		0,      TTY_PE,
998		TTY_FE, TTY_PE|TTY_FE,
999		TTY_FE, TTY_PE|TTY_FE,
1000		TTY_FE, TTY_PE|TTY_FE
1001	};
1002
1003	if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf)
1004		return;
1005
1006	tp = sc->sc_tty;
1007
1008	s = spltty();
1009
1010	ibufp = sc->sc_ibuf;
1011	ibufend = sc->sc_ibufp;
1012
1013	if (ibufp == ibufend) {
1014		splx(s);
1015		return;
1016	}
1017
1018	sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
1019				     sc->sc_ibufs[1] : sc->sc_ibufs[0];
1020	sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
1021	sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
1022
1023	if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) {
1024		splx(s);
1025		return;
1026	}
1027
1028	if (ISSET(tp->t_cflag, CRTSCTS) &&
1029	    !ISSET(sc->sc_mcr, MCR_RTS)) {
1030		/* XXX */
1031		SET(sc->sc_mcr, MCR_RTS);
1032		com_write_reg(sc, com_mcr, sc->sc_mcr);
1033	}
1034
1035	splx(s);
1036
1037	while (ibufp < ibufend) {
1038		c = *ibufp++;
1039		if (ISSET(*ibufp, LSR_OE)) {
1040			sc->sc_overflows++;
1041			if (sc->sc_errors++ == 0)
1042				timeout_add_sec(&sc->sc_diag_tmo, 60);
1043		}
1044		/* This is ugly, but fast. */
1045		c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
1046		(*linesw[tp->t_line].l_rint)(c, tp);
1047	}
1048}
1049
1050int
1051comintr(void *arg)
1052{
1053	struct com_softc *sc = arg;
1054	struct tty *tp;
1055	u_char lsr, data, msr, delta;
1056
1057	if (!sc->sc_tty)
1058		return (0);		/* Can't do squat. */
1059
1060	if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND))
1061		return (0);
1062
1063	tp = sc->sc_tty;
1064
1065	for (;;) {
1066		lsr = com_read_reg(sc, com_lsr);
1067
1068		if (ISSET(lsr, LSR_RXRDY)) {
1069			u_char *p = sc->sc_ibufp;
1070
1071			softintr_schedule(sc->sc_si);
1072			do {
1073				data = com_read_reg(sc, com_data);
1074				if (ISSET(lsr, LSR_BI)) {
1075#if defined(COM_CONSOLE) && defined(DDB)
1076					if (ISSET(sc->sc_hwflags,
1077					    COM_HW_CONSOLE)) {
1078						if (db_console)
1079							db_enter();
1080						goto next;
1081					}
1082#endif
1083					data = 0;
1084				}
1085				if (p >= sc->sc_ibufend) {
1086					sc->sc_floods++;
1087					if (sc->sc_errors++ == 0)
1088						timeout_add_sec(&sc->sc_diag_tmo, 60);
1089				} else {
1090					*p++ = data;
1091					*p++ = lsr;
1092					if (p == sc->sc_ibufhigh &&
1093					    ISSET(tp->t_cflag, CRTSCTS)) {
1094						/* XXX */
1095						CLR(sc->sc_mcr, MCR_RTS);
1096						com_write_reg(sc, com_mcr,
1097						    sc->sc_mcr);
1098					}
1099				}
1100#if defined(COM_CONSOLE) && defined(DDB)
1101			next:
1102#endif
1103				lsr = com_read_reg(sc, com_lsr);
1104			} while (ISSET(lsr, LSR_RXRDY));
1105
1106			sc->sc_ibufp = p;
1107		}
1108		msr = com_read_reg(sc, com_msr);
1109
1110		if (msr != sc->sc_msr) {
1111			delta = msr ^ sc->sc_msr;
1112
1113			ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
1114			    sc->sc_msr & MSR_DCD, msr & MSR_DCD);
1115
1116			sc->sc_msr = msr;
1117			if (ISSET(delta, MSR_DCD)) {
1118				if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
1119				    (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
1120					CLR(sc->sc_mcr, sc->sc_dtr);
1121					com_write_reg(sc, com_mcr, sc->sc_mcr);
1122				}
1123			}
1124			if (ISSET(delta & msr, MSR_CTS) &&
1125			    ISSET(tp->t_cflag, CRTSCTS)) {
1126				/* the line is up and we want to do rts/cts flow control */
1127				(*linesw[tp->t_line].l_start)(tp);
1128			}
1129		}
1130
1131		if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
1132			CLR(tp->t_state, TS_BUSY | TS_FLUSH);
1133			if (sc->sc_halt > 0)
1134				wakeup(&tp->t_outq);
1135			(*linesw[tp->t_line].l_start)(tp);
1136		}
1137
1138		if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND))
1139			return (1);
1140	}
1141}
1142
1143void
1144cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate, int frequency)
1145{
1146	int s = splhigh();
1147	u_char stat;
1148
1149	bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1150	rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */
1151	bus_space_write_1(iot, ioh, com_dlbl, rate);
1152	bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
1153	bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
1154	bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
1155	bus_space_write_1(iot, ioh, com_ier, 0);  /* Make sure they are off */
1156	bus_space_write_1(iot, ioh, com_fifo,
1157	    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
1158	stat = bus_space_read_1(iot, ioh, com_iir);
1159	splx(s);
1160}
1161
1162#ifdef COM_CONSOLE
1163void
1164comcnprobe(struct consdev *cp)
1165{
1166	bus_space_handle_t ioh;
1167	int found = 1;
1168
1169	if (comconsaddr == 0)
1170		return;
1171
1172	if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &ioh))
1173		return;
1174	/* XXX Some com@acpi devices will fail the comprobe1() check */
1175	if (comcons_reg_width != 4)
1176		found = comprobe1(comconsiot, ioh);
1177	bus_space_unmap(comconsiot, ioh, COM_NPORTS);
1178	if (!found)
1179		return;
1180
1181	/* Locate the major number. */
1182	for (commajor = 0; commajor < nchrdev; commajor++)
1183		if (cdevsw[commajor].d_open == comopen)
1184			break;
1185
1186	/* Initialize required fields. */
1187	cp->cn_dev = makedev(commajor, comconsunit);
1188	cp->cn_pri = CN_HIGHPRI;
1189}
1190
1191void
1192comcninit(struct consdev *cp)
1193{
1194	if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
1195		panic("comcninit: mapping failed");
1196
1197	if (comconsfreq == 0)
1198		comconsfreq = COM_FREQ;
1199
1200	cominit(comconsiot, comconsioh, comconsrate, comconsfreq);
1201}
1202
1203int
1204comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
1205    int frequency, tcflag_t cflag)
1206{
1207	static struct consdev comcons = {
1208		NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL,
1209		NODEV, CN_LOWPRI
1210	};
1211
1212#ifndef __sparc64__
1213	if (bus_space_map(iot, iobase, COM_NPORTS, 0, &comconsioh))
1214		return ENOMEM;
1215#endif
1216
1217	cominit(iot, comconsioh, rate, frequency);
1218
1219	cn_tab = &comcons;
1220
1221	comconsiot = iot;
1222	comconsaddr = iobase;
1223	comconscflag = cflag;
1224	comconsfreq = frequency;
1225	comconsrate = rate;
1226
1227	return (0);
1228}
1229
1230int
1231comcngetc(dev_t dev)
1232{
1233	int s = splhigh();
1234	u_char stat, c;
1235
1236	/* Block until a character becomes available. */
1237	while (!ISSET(stat = comcn_read_reg(com_lsr), LSR_RXRDY))
1238		continue;
1239
1240	c = comcn_read_reg(com_data);
1241
1242	/* Clear any interrupts generated by this transmission. */
1243	stat = comcn_read_reg(com_iir);
1244	splx(s);
1245	return (c);
1246}
1247
1248/*
1249 * Console kernel output character routine.
1250 */
1251void
1252comcnputc(dev_t dev, int c)
1253{
1254	int s = spltty();
1255	int timo;
1256
1257	/* Wait for any pending transmission to finish. */
1258	timo = 2000;
1259	while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo)
1260		delay(1);
1261
1262	comcn_write_reg(com_data, (u_int8_t)(c & 0xff));
1263	bus_space_barrier(comconsiot, comconsioh, 0,
1264	    COM_NPORTS << comcons_reg_shift,
1265	    (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE));
1266
1267	/* Wait for this transmission to complete. */
1268	timo = 2000;
1269	while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo)
1270		delay(1);
1271
1272	splx(s);
1273}
1274
1275void
1276comcnpollc(dev_t dev, int on)
1277{
1278}
1279#endif	/* COM_CONSOLE */
1280
1281void	com_enable_debugport(struct com_softc *);
1282void	com_fifo_probe(struct com_softc *);
1283
1284#ifdef COM_CONSOLE
1285void
1286com_enable_debugport(struct com_softc *sc)
1287{
1288	int s;
1289
1290	/* Turn on line break interrupt, set carrier. */
1291	s = splhigh();
1292	SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
1293	com_write_reg(sc, com_mcr, sc->sc_mcr);
1294
1295	splx(s);
1296}
1297#endif	/* COM_CONSOLE */
1298
1299void
1300com_attach_subr(struct com_softc *sc)
1301{
1302	int probe = 0;
1303	u_int8_t lcr, fifo;
1304	u_int32_t cpr;
1305
1306	sc->sc_ier = 0;
1307	/* disable interrupts */
1308	com_write_reg(sc, com_ier, sc->sc_ier);
1309
1310#ifdef COM_CONSOLE
1311	if (sc->sc_iot == comconsiot && sc->sc_iobase == comconsaddr) {
1312		comconsattached = 1;
1313		delay(10000);			/* wait for output to finish */
1314		SET(sc->sc_hwflags, COM_HW_CONSOLE);
1315		SET(sc->sc_swflags, COM_SW_SOFTCAR);
1316	}
1317#endif
1318
1319	/*
1320	 * Probe for all known forms of UART.
1321	 */
1322	lcr = com_read_reg(sc, com_lcr);
1323	com_write_reg(sc, com_lcr, LCR_EFR);
1324	com_write_reg(sc, com_efr, 0);
1325	com_write_reg(sc, com_lcr, 0);
1326
1327	com_write_reg(sc, com_fifo, FIFO_ENABLE);
1328	delay(100);
1329
1330	/*
1331	 * Skip specific probes if attachment code knows it already.
1332	 */
1333	if (sc->sc_uarttype == COM_UART_UNKNOWN) {
1334		switch (com_read_reg(sc, com_iir) >> 6) {
1335		case 0:
1336			sc->sc_uarttype = COM_UART_16450;
1337			break;
1338		case 2:
1339			sc->sc_uarttype = COM_UART_16550;
1340			break;
1341		case 3:
1342			sc->sc_uarttype = COM_UART_16550A;
1343			break;
1344		default:
1345			sc->sc_uarttype = COM_UART_UNKNOWN;
1346			break;
1347		}
1348		probe = 1;
1349	}
1350
1351	/* Probe for ST16650s */
1352	if (probe && sc->sc_uarttype == COM_UART_16550A) {
1353		com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
1354		if (com_read_reg(sc, com_efr) == 0) {
1355			com_write_reg(sc, com_efr, EFR_CTS);
1356			if (com_read_reg(sc, com_efr) != 0)
1357				sc->sc_uarttype = COM_UART_ST16650;
1358			com_write_reg(sc, com_efr, 0);
1359		} else {
1360			com_write_reg(sc, com_lcr, LCR_EFR);
1361			if (com_read_reg(sc, com_efr) == 0)
1362				sc->sc_uarttype = COM_UART_ST16650V2;
1363		}
1364	}
1365
1366#if 0	/* until com works with large FIFOs */
1367	/* Probe for XR16850s */
1368	if (probe && sc->sc_uarttype == COM_UART_ST16650V2) {
1369		u_int8_t dlbl, dlbh;
1370
1371		/* Enable latch access and get the current values. */
1372		com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
1373		dlbl = com_read_reg(sc, com_dlbl);
1374		dlbh = com_read_reg(sc, com_dlbh);
1375
1376		/* Zero out the latch divisors */
1377		com_write_reg(sc, com_dlbl, 0);
1378		com_write_reg(sc, com_dlbh, 0);
1379
1380		if (com_read_reg(sc, com_dlbh) == 0x10) {
1381			sc->sc_uarttype = COM_UART_XR16850;
1382			sc->sc_uartrev = com_read_reg(sc, com_dlbl);
1383		}
1384
1385		/* Reset to original. */
1386		com_write_reg(sc, com_dlbl, dlbl);
1387		com_write_reg(sc, com_dlbh, dlbh);
1388	}
1389#endif
1390
1391	/* Probe for TI16750s */
1392	if (probe && sc->sc_uarttype == COM_UART_16550A) {
1393		com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
1394		com_write_reg(sc, com_fifo,
1395		    FIFO_ENABLE | FIFO_ENABLE_64BYTE);
1396		if ((com_read_reg(sc, com_iir) >> 5) == 7) {
1397#if 0
1398			com_write_reg(sc, com_lcr, 0);
1399			if ((com_read_reg(sc, com_iir) >> 5) == 6)
1400#endif
1401				sc->sc_uarttype = COM_UART_TI16750;
1402		}
1403		com_write_reg(sc, com_fifo, FIFO_ENABLE);
1404	}
1405
1406	/* Reset the LCR (latch access is probably enabled). */
1407	com_write_reg(sc, com_lcr, lcr);
1408
1409	/* Probe for 8250 */
1410	if (probe && sc->sc_uarttype == COM_UART_16450) {
1411		u_int8_t scr0, scr1, scr2;
1412
1413		scr0 = com_read_reg(sc, com_scratch);
1414		com_write_reg(sc, com_scratch, 0xa5);
1415		scr1 = com_read_reg(sc, com_scratch);
1416		com_write_reg(sc, com_scratch, 0x5a);
1417		scr2 = com_read_reg(sc, com_scratch);
1418		com_write_reg(sc, com_scratch, scr0);
1419
1420		if ((scr1 != 0xa5) || (scr2 != 0x5a))
1421			sc->sc_uarttype = COM_UART_8250;
1422	}
1423
1424	/*
1425	 * Print UART type and initialize ourself.
1426	 */
1427	switch (sc->sc_uarttype) {
1428	case COM_UART_UNKNOWN:
1429		printf(": unknown uart\n");
1430		break;
1431	case COM_UART_8250:
1432		printf(": ns8250, no fifo\n");
1433		break;
1434	case COM_UART_16450:
1435		printf(": ns16450, no fifo\n");
1436		break;
1437	case COM_UART_16550:
1438		printf(": ns16550, no working fifo\n");
1439		break;
1440	case COM_UART_16550A:
1441		if (sc->sc_fifolen == 0)
1442			sc->sc_fifolen = 16;
1443		printf(": ns16550a, %d byte fifo\n", sc->sc_fifolen);
1444		SET(sc->sc_hwflags, COM_HW_FIFO);
1445		break;
1446	case COM_UART_ST16650:
1447		printf(": st16650, no working fifo\n");
1448		break;
1449	case COM_UART_ST16650V2:
1450		if (sc->sc_fifolen == 0)
1451			sc->sc_fifolen = 32;
1452		printf(": st16650, %d byte fifo\n", sc->sc_fifolen);
1453		SET(sc->sc_hwflags, COM_HW_FIFO);
1454		break;
1455	case COM_UART_ST16C654:
1456		printf(": st16c654, 64 byte fifo\n");
1457		SET(sc->sc_hwflags, COM_HW_FIFO);
1458		sc->sc_fifolen = 64;
1459		break;
1460	case COM_UART_TI16750:
1461		printf(": ti16750, 64 byte fifo\n");
1462		SET(sc->sc_hwflags, COM_HW_FIFO);
1463		sc->sc_fifolen = 64;
1464		break;
1465#if 0
1466	case COM_UART_XR16850:
1467		printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
1468		SET(sc->sc_hwflags, COM_HW_FIFO);
1469		sc->sc_fifolen = 128;
1470		break;
1471#ifdef COM_UART_OX16C950
1472	case COM_UART_OX16C950:
1473		printf(": ox16c950 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
1474		SET(sc->sc_hwflags, COM_HW_FIFO);
1475		sc->sc_fifolen = 128;
1476		break;
1477#endif
1478#endif
1479	case COM_UART_XR17V35X:
1480		printf(": xr17v35x, 256 byte fifo\n");
1481		SET(sc->sc_hwflags, COM_HW_FIFO);
1482		sc->sc_fifolen = 256;
1483		break;
1484	case COM_UART_DW_APB:
1485		printf(": dw16550");
1486		SET(sc->sc_hwflags, COM_HW_FIFO);
1487		cpr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, com_cpr << 2);
1488		sc->sc_fifolen = CPR_FIFO_MODE(cpr) * 16;
1489		if (sc->sc_fifolen) {
1490			printf(", %d byte fifo\n", sc->sc_fifolen);
1491		} else {
1492			printf("\n");
1493			/*
1494			 * The DW-APB configuration on the Allwinner H6 SoC
1495			 * does not provide the CPR register and will be
1496			 * detected as having no FIFO.  But it does have a
1497			 * 256-byte FIFO and with the FIFO disabled the
1498			 * LSR_RXRDY bit remains set even if the input
1499			 * buffer is empty.  As a workaround, treat as a
1500			 * 1-byte FIFO.
1501			 */
1502			sc->sc_fifolen = 1;
1503		}
1504		break;
1505	default:
1506		panic("comattach: bad fifo type");
1507	}
1508
1509#ifdef COM_CONSOLE
1510	if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
1511#endif
1512		if (sc->sc_fifolen < 256)
1513			com_fifo_probe(sc);
1514
1515	if (sc->sc_fifolen == 0) {
1516		CLR(sc->sc_hwflags, COM_HW_FIFO);
1517		sc->sc_fifolen = 1;
1518	}
1519
1520	/* clear and disable fifo */
1521	/* DW-APB UART cannot turn off FIFO here (ddb will not work) */
1522	fifo = (sc->sc_uarttype == COM_UART_DW_APB) ?
1523		(FIFO_ENABLE | FIFO_TRIGGER_1) : 0;
1524	com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST);
1525	if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
1526		(void)com_read_reg(sc, com_data);
1527	com_write_reg(sc, com_fifo, fifo);
1528
1529	sc->sc_mcr = 0;
1530	com_write_reg(sc, com_mcr, sc->sc_mcr);
1531
1532#ifdef COM_CONSOLE
1533	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1534		int maj;
1535
1536		/* locate the major number */
1537		for (maj = 0; maj < nchrdev; maj++)
1538			if (cdevsw[maj].d_open == comopen)
1539				break;
1540
1541		KASSERT(maj < nchrdev);
1542		cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
1543
1544		printf("%s: console\n", sc->sc_dev.dv_xname);
1545	}
1546#endif
1547
1548	timeout_set(&sc->sc_diag_tmo, comdiag, sc);
1549	timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc);
1550	sc->sc_si = softintr_establish(IPL_TTY, comsoft, sc);
1551	if (sc->sc_si == NULL)
1552		panic("%s: can't establish soft interrupt",
1553		    sc->sc_dev.dv_xname);
1554
1555	/*
1556	 * If there are no enable/disable functions, assume the device
1557	 * is always enabled.
1558	 */
1559	if (!sc->enable)
1560		sc->enabled = 1;
1561
1562#ifdef COM_CONSOLE
1563	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
1564		com_enable_debugport(sc);
1565#endif
1566}
1567
1568void
1569com_fifo_probe(struct com_softc *sc)
1570{
1571	u_int8_t fifo, ier;
1572	int timo, len;
1573
1574	if (!ISSET(sc->sc_hwflags, COM_HW_FIFO))
1575		return;
1576
1577	ier = 0;
1578	com_write_reg(sc, com_ier, ier);
1579	com_write_reg(sc, com_lcr, LCR_DLAB);
1580	com_write_reg(sc, com_dlbl, 3);
1581	com_write_reg(sc, com_dlbh, 0);
1582	com_write_reg(sc, com_lcr, LCR_PNONE | LCR_8BITS);
1583	com_write_reg(sc, com_mcr, MCR_LOOPBACK);
1584
1585	fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;
1586	if (sc->sc_uarttype == COM_UART_TI16750)
1587		fifo |= FIFO_ENABLE_64BYTE;
1588
1589	com_write_reg(sc, com_fifo, fifo);
1590
1591	for (len = 0; len < 256; len++) {
1592		com_write_reg(sc, com_data, (len + 1));
1593		timo = 2000;
1594		while (!ISSET(com_read_reg(sc, com_lsr),
1595		    LSR_TXRDY) && --timo)
1596			delay(1);
1597		if (!timo)
1598			break;
1599	}
1600
1601	delay(100);
1602
1603	for (len = 0; len < 256; len++) {
1604		timo = 2000;
1605		while (!ISSET(com_read_reg(sc, com_lsr),
1606		    LSR_RXRDY) && --timo)
1607			delay(1);
1608		if (!timo || com_read_reg(sc, com_data) != (len + 1))
1609			break;
1610	}
1611
1612	/* For safety, always use the smaller value. */
1613	if (sc->sc_fifolen > len) {
1614		printf("%s: probed fifo depth: %d bytes\n",
1615		    sc->sc_dev.dv_xname, len);
1616		sc->sc_fifolen = len;
1617	}
1618}
1619
1620uint8_t
1621com_read_reg(struct com_softc *sc, bus_size_t reg)
1622{
1623	reg <<= sc->sc_reg_shift;
1624
1625	if (sc->sc_reg_width == 4)
1626		return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
1627	else
1628		return bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg);
1629}
1630
1631void
1632com_write_reg(struct com_softc *sc, bus_size_t reg, uint8_t value)
1633{
1634	reg <<= sc->sc_reg_shift;
1635
1636	if (sc->sc_reg_width == 4)
1637		bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, value);
1638	else
1639		bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, value);
1640}
1641
1642#ifdef COM_CONSOLE
1643
1644u_char comcons_reg_width;
1645u_char comcons_reg_shift;
1646
1647uint8_t
1648comcn_read_reg(bus_size_t reg)
1649{
1650	reg <<= comcons_reg_shift;
1651
1652	if (comcons_reg_width == 4)
1653		return bus_space_read_4(comconsiot, comconsioh, reg);
1654	else
1655		return bus_space_read_1(comconsiot, comconsioh, reg);
1656}
1657
1658void
1659comcn_write_reg(bus_size_t reg, uint8_t value)
1660{
1661	reg <<= comcons_reg_shift;
1662
1663	if (comcons_reg_width == 4)
1664		bus_space_write_4(comconsiot, comconsioh, reg, value);
1665	else
1666		bus_space_write_1(comconsiot, comconsioh, reg, value);
1667}
1668
1669#endif
1670