xref: /original-bsd/sys/hp/dev/dca.c (revision 3705696b)
1 /*
2  * Copyright (c) 1982, 1986, 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)dca.c	8.1 (Berkeley) 06/10/93
8  */
9 
10 #include "dca.h"
11 #if NDCA > 0
12 /*
13  *  Driver for National Semiconductor INS8250/NS16550AF/WD16C552 UARTs.
14  *  Includes:
15  *	98626/98644/internal serial interface on hp300/hp400
16  *	internal serial ports on hp700
17  *
18  *  N.B. On the hp700, there is a "secret bit" with undocumented behavior.
19  *  The third bit of the Modem Control Register (MCR_IEN == 0x08) must be
20  *  set to enable interrupts.
21  */
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/ioctl.h>
25 #include <sys/proc.h>
26 #include <sys/tty.h>
27 #include <sys/conf.h>
28 #include <sys/file.h>
29 #include <sys/uio.h>
30 #include <sys/kernel.h>
31 #include <sys/syslog.h>
32 
33 #include <hp/dev/device.h>
34 #include <hp/dev/dcareg.h>
35 
36 #include <machine/cpu.h>
37 #ifdef hp300
38 #include <hp300/hp300/isr.h>
39 #endif
40 #ifdef hp700
41 #include <machine/asp.h>
42 #endif
43 
44 int	dcaprobe();
45 struct	driver dcadriver = {
46 	dcaprobe, "dca",
47 };
48 
49 void	dcastart();
50 int	dcaparam(), dcaintr();
51 int	dcasoftCAR;
52 int	dca_active;
53 int	dca_hasfifo;
54 int	ndca = NDCA;
55 #ifdef DCACONSOLE
56 int	dcaconsole = DCACONSOLE;
57 #else
58 int	dcaconsole = -1;
59 #endif
60 int	dcaconsinit;
61 int	dcadefaultrate = TTYDEF_SPEED;
62 int	dcamajor;
63 struct	dcadevice *dca_addr[NDCA];
64 struct	tty dca_tty[NDCA];
65 #ifdef hp300
66 struct	isr dcaisr[NDCA];
67 int	dcafastservice;
68 #endif
69 int	dcaoflows[NDCA];
70 
71 struct speedtab dcaspeedtab[] = {
72 	0,	0,
73 	50,	DCABRD(50),
74 	75,	DCABRD(75),
75 	110,	DCABRD(110),
76 	134,	DCABRD(134),
77 	150,	DCABRD(150),
78 	200,	DCABRD(200),
79 	300,	DCABRD(300),
80 	600,	DCABRD(600),
81 	1200,	DCABRD(1200),
82 	1800,	DCABRD(1800),
83 	2400,	DCABRD(2400),
84 	4800,	DCABRD(4800),
85 	9600,	DCABRD(9600),
86 	19200,	DCABRD(19200),
87 	38400,	DCABRD(38400),
88 	-1,	-1
89 };
90 
91 #ifdef KGDB
92 #include <machine/remote-sl.h>
93 
94 extern dev_t kgdb_dev;
95 extern int kgdb_rate;
96 extern int kgdb_debug_init;
97 #endif
98 
99 #define	UNIT(x)		minor(x)
100 
101 #ifdef DEBUG
102 long	fifoin[17];
103 long	fifoout[17];
104 long	dcaintrcount[16];
105 long	dcamintcount[16];
106 #endif
107 
108 dcaprobe(hd)
109 	register struct hp_device *hd;
110 {
111 	register struct dcadevice *dca;
112 	register int unit;
113 
114 	dca = (struct dcadevice *)hd->hp_addr;
115 #ifdef hp300
116 	if (dca->dca_id != DCAID0 &&
117 	    dca->dca_id != DCAREMID0 &&
118 	    dca->dca_id != DCAID1 &&
119 	    dca->dca_id != DCAREMID1)
120 		return (0);
121 #endif
122 	unit = hd->hp_unit;
123 	if (unit == dcaconsole)
124 		DELAY(100000);
125 #ifdef hp300
126 	dca->dca_reset = 0xFF;
127 	DELAY(100);
128 #endif
129 
130 	/* look for a NS 16550AF UART with FIFOs */
131 	dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
132 	DELAY(100);
133 	if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK)
134 		dca_hasfifo |= 1 << unit;
135 
136 	dca_addr[unit] = dca;
137 #ifdef hp300
138 	hd->hp_ipl = DCAIPL(dca->dca_ic);
139 	dcaisr[unit].isr_ipl = hd->hp_ipl;
140 	dcaisr[unit].isr_arg = unit;
141 	dcaisr[unit].isr_intr = dcaintr;
142 	isrlink(&dcaisr[unit]);
143 #endif
144 	dca_active |= 1 << unit;
145 	if (hd->hp_flags)
146 		dcasoftCAR |= (1 << unit);
147 #ifdef KGDB
148 	if (kgdb_dev == makedev(dcamajor, unit)) {
149 		if (dcaconsole == unit)
150 			kgdb_dev = NODEV; /* can't debug over console port */
151 		else {
152 			(void) dcainit(unit, kgdb_rate);
153 			dcaconsinit = 1;	/* don't re-init in dcaputc */
154 			if (kgdb_debug_init) {
155 				/*
156 				 * Print prefix of device name,
157 				 * let kgdb_connect print the rest.
158 				 */
159 				printf("dca%d: ", unit);
160 				kgdb_connect(1);
161 			} else
162 				printf("dca%d: kgdb enabled\n", unit);
163 		}
164 	}
165 #endif
166 #ifdef hp300
167 	dca->dca_ic = IC_IE;
168 #endif
169 	/*
170 	 * Need to reset baud rate, etc. of next print so reset dcaconsinit.
171 	 * Also make sure console is always "hardwired."
172 	 */
173 	if (unit == dcaconsole) {
174 		dcaconsinit = 0;
175 		dcasoftCAR |= (1 << unit);
176 	}
177 	return (1);
178 }
179 
180 /* ARGSUSED */
181 #ifdef __STDC__
182 dcaopen(dev_t dev, int flag, int mode, struct proc *p)
183 #else
184 dcaopen(dev, flag, mode, p)
185 	dev_t dev;
186 	int flag, mode;
187 	struct proc *p;
188 #endif
189 {
190 	register struct tty *tp;
191 	register int unit;
192 	int error = 0;
193 
194 	unit = UNIT(dev);
195 	if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
196 		return (ENXIO);
197 	tp = &dca_tty[unit];
198 	tp->t_oproc = dcastart;
199 	tp->t_param = dcaparam;
200 	tp->t_dev = dev;
201 	if ((tp->t_state & TS_ISOPEN) == 0) {
202 		tp->t_state |= TS_WOPEN;
203 		ttychars(tp);
204 		if (tp->t_ispeed == 0) {
205 			tp->t_iflag = TTYDEF_IFLAG;
206 			tp->t_oflag = TTYDEF_OFLAG;
207 			tp->t_cflag = TTYDEF_CFLAG;
208 			tp->t_lflag = TTYDEF_LFLAG;
209 			tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
210 		}
211 		dcaparam(tp, &tp->t_termios);
212 		ttsetwater(tp);
213 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
214 		return (EBUSY);
215 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
216 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
217 		tp->t_state |= TS_CARR_ON;
218 	(void) spltty();
219 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
220 	       (tp->t_state & TS_CARR_ON) == 0) {
221 		tp->t_state |= TS_WOPEN;
222 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
223 		    ttopen, 0))
224 			break;
225 	}
226 	(void) spl0();
227 	if (error == 0)
228 		error = (*linesw[tp->t_line].l_open)(dev, tp);
229 #ifdef hp300
230 	/*
231 	 * XXX hack to speed up unbuffered builtin port.
232 	 * If dca_fastservice is set, a level 5 interrupt
233 	 * will be directed to dcaintr first.
234 	 */
235 	if (error == 0 && unit == 0 && (dca_hasfifo & 1) == 0)
236 		dcafastservice = 1;
237 #endif
238 	return (error);
239 }
240 
241 /*ARGSUSED*/
242 dcaclose(dev, flag, mode, p)
243 	dev_t dev;
244 	int flag, mode;
245 	struct proc *p;
246 {
247 	register struct tty *tp;
248 	register struct dcadevice *dca;
249 	register int unit;
250 
251 	unit = UNIT(dev);
252 #ifdef hp300
253 	if (unit == 0)
254 		dcafastservice = 0;
255 #endif
256 	dca = dca_addr[unit];
257 	tp = &dca_tty[unit];
258 	(*linesw[tp->t_line].l_close)(tp, flag);
259 	dca->dca_cfcr &= ~CFCR_SBREAK;
260 #ifdef KGDB
261 	/* do not disable interrupts if debugging */
262 	if (dev != kgdb_dev)
263 #endif
264 	dca->dca_ier = 0;
265 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
266 	    (tp->t_state&TS_ISOPEN) == 0)
267 		(void) dcamctl(dev, 0, DMSET);
268 	ttyclose(tp);
269 	return (0);
270 }
271 
272 dcaread(dev, uio, flag)
273 	dev_t dev;
274 	struct uio *uio;
275 {
276 	int unit = UNIT(dev);
277 	register struct tty *tp = &dca_tty[unit];
278 	int error, of;
279 
280 	of = dcaoflows[unit];
281 	error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
282 	/*
283 	 * XXX hardly a reasonable thing to do, but reporting overflows
284 	 * at interrupt time just exacerbates the problem.
285 	 */
286 	if (dcaoflows[unit] != of)
287 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
288 	return (error);
289 }
290 
291 dcawrite(dev, uio, flag)
292 	dev_t dev;
293 	struct uio *uio;
294 {
295 	int unit = UNIT(dev);
296 	register struct tty *tp = &dca_tty[unit];
297 	extern struct tty *constty;
298 
299 	/*
300 	 * (XXX) We disallow virtual consoles if the physical console is
301 	 * a serial port.  This is in case there is a display attached that
302 	 * is not the console.  In that situation we don't need/want the X
303 	 * server taking over the console.
304 	 */
305 	if (constty && unit == dcaconsole)
306 		constty = NULL;
307 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
308 }
309 
310 dcaintr(unit)
311 	register int unit;
312 {
313 	register struct dcadevice *dca;
314 	register u_char code;
315 	register struct tty *tp;
316 	int iflowdone = 0;
317 
318 	dca = dca_addr[unit];
319 #ifdef hp300
320 	if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE))
321 		return (0);
322 #endif
323 	tp = &dca_tty[unit];
324 	while (1) {
325 		code = dca->dca_iir;
326 #ifdef DEBUG
327 		dcaintrcount[code & IIR_IMASK]++;
328 #endif
329 		switch (code & IIR_IMASK) {
330 		case IIR_NOPEND:
331 			return (1);
332 		case IIR_RXTOUT:
333 		case IIR_RXRDY:
334 			/* do time-critical read in-line */
335 /*
336  * Process a received byte.  Inline for speed...
337  */
338 #ifdef KGDB
339 #define	RCVBYTE() \
340 			code = dca->dca_data; \
341 			if ((tp->t_state & TS_ISOPEN) == 0) { \
342 				if (code == FRAME_END && \
343 				    kgdb_dev == makedev(dcamajor, unit)) \
344 					kgdb_connect(0); /* trap into kgdb */ \
345 			} else \
346 				(*linesw[tp->t_line].l_rint)(code, tp)
347 #else
348 #define	RCVBYTE() \
349 			code = dca->dca_data; \
350 			if ((tp->t_state & TS_ISOPEN) != 0) \
351 				(*linesw[tp->t_line].l_rint)(code, tp)
352 #endif
353 			RCVBYTE();
354 			if (dca_hasfifo & (1 << unit)) {
355 #ifdef DEBUG
356 				register int fifocnt = 1;
357 #endif
358 				while ((code = dca->dca_lsr) & LSR_RCV_MASK) {
359 					if (code == LSR_RXRDY) {
360 						RCVBYTE();
361 					} else
362 						dcaeint(unit, code, dca);
363 #ifdef DEBUG
364 					fifocnt++;
365 #endif
366 				}
367 #ifdef DEBUG
368 				if (fifocnt > 16)
369 					fifoin[0]++;
370 				else
371 					fifoin[fifocnt]++;
372 #endif
373 			}
374 			if (!iflowdone && (tp->t_cflag&CRTS_IFLOW) &&
375 			    tp->t_rawq.c_cc > TTYHOG/2) {
376 				dca->dca_mcr &= ~MCR_RTS;
377 				iflowdone = 1;
378 			}
379 			break;
380 		case IIR_TXRDY:
381 			tp->t_state &=~ (TS_BUSY|TS_FLUSH);
382 			if (tp->t_line)
383 				(*linesw[tp->t_line].l_start)(tp);
384 			else
385 				dcastart(tp);
386 			break;
387 		case IIR_RLS:
388 			dcaeint(unit, dca->dca_lsr, dca);
389 			break;
390 		default:
391 			if (code & IIR_NOPEND)
392 				return (1);
393 			log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n",
394 			    unit, code);
395 			/* fall through */
396 		case IIR_MLSC:
397 			dcamint(unit, dca);
398 			break;
399 		}
400 	}
401 }
402 
403 dcaeint(unit, stat, dca)
404 	register int unit, stat;
405 	register struct dcadevice *dca;
406 {
407 	register struct tty *tp;
408 	register int c;
409 
410 	tp = &dca_tty[unit];
411 	c = dca->dca_data;
412 	if ((tp->t_state & TS_ISOPEN) == 0) {
413 #ifdef KGDB
414 		/* we don't care about parity errors */
415 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
416 		    kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END)
417 			kgdb_connect(0); /* trap into kgdb */
418 #endif
419 		return;
420 	}
421 	if (stat & (LSR_BI | LSR_FE))
422 		c |= TTY_FE;
423 	else if (stat & LSR_PE)
424 		c |= TTY_PE;
425 	else if (stat & LSR_OE)
426 		dcaoflows[unit]++;
427 	(*linesw[tp->t_line].l_rint)(c, tp);
428 }
429 
430 dcamint(unit, dca)
431 	register int unit;
432 	register struct dcadevice *dca;
433 {
434 	register struct tty *tp;
435 	register u_char stat;
436 
437 	tp = &dca_tty[unit];
438 	stat = dca->dca_msr;
439 #ifdef DEBUG
440 	dcamintcount[stat & 0xf]++;
441 #endif
442 	if ((stat & MSR_DDCD) &&
443 	    (dcasoftCAR & (1 << unit)) == 0) {
444 		if (stat & MSR_DCD)
445 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
446 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
447 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
448 	}
449 	/*
450 	 * CTS change.
451 	 * If doing HW output flow control start/stop output as appropriate.
452 	 */
453 	if ((stat & MSR_DCTS) &&
454 	    (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
455 		if (stat & MSR_CTS) {
456 			tp->t_state &=~ TS_TTSTOP;
457 			dcastart(tp);
458 		} else {
459 			tp->t_state |= TS_TTSTOP;
460 		}
461 	}
462 }
463 
464 dcaioctl(dev, cmd, data, flag, p)
465 	dev_t dev;
466 	int cmd;
467 	caddr_t data;
468 	int flag;
469 	struct proc *p;
470 {
471 	register struct tty *tp;
472 	register int unit = UNIT(dev);
473 	register struct dcadevice *dca;
474 	register int error;
475 
476 	tp = &dca_tty[unit];
477 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
478 	if (error >= 0)
479 		return (error);
480 	error = ttioctl(tp, cmd, data, flag);
481 	if (error >= 0)
482 		return (error);
483 
484 	dca = dca_addr[unit];
485 	switch (cmd) {
486 
487 	case TIOCSBRK:
488 		dca->dca_cfcr |= CFCR_SBREAK;
489 		break;
490 
491 	case TIOCCBRK:
492 		dca->dca_cfcr &= ~CFCR_SBREAK;
493 		break;
494 
495 	case TIOCSDTR:
496 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
497 		break;
498 
499 	case TIOCCDTR:
500 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
501 		break;
502 
503 	case TIOCMSET:
504 		(void) dcamctl(dev, *(int *)data, DMSET);
505 		break;
506 
507 	case TIOCMBIS:
508 		(void) dcamctl(dev, *(int *)data, DMBIS);
509 		break;
510 
511 	case TIOCMBIC:
512 		(void) dcamctl(dev, *(int *)data, DMBIC);
513 		break;
514 
515 	case TIOCMGET:
516 		*(int *)data = dcamctl(dev, 0, DMGET);
517 		break;
518 
519 	default:
520 		return (ENOTTY);
521 	}
522 	return (0);
523 }
524 
525 dcaparam(tp, t)
526 	register struct tty *tp;
527 	register struct termios *t;
528 {
529 	register struct dcadevice *dca;
530 	register int cfcr, cflag = t->c_cflag;
531 	int unit = UNIT(tp->t_dev);
532 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
533 
534 	/* check requested parameters */
535         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
536                 return (EINVAL);
537         /* and copy to tty */
538         tp->t_ispeed = t->c_ispeed;
539         tp->t_ospeed = t->c_ospeed;
540         tp->t_cflag = cflag;
541 
542 	dca = dca_addr[unit];
543 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
544 #ifdef hp700
545 	dca->dca_mcr |= MCR_IEN;
546 #endif
547 	if (ospeed == 0) {
548 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
549 		return (0);
550 	}
551 	dca->dca_cfcr |= CFCR_DLAB;
552 	dca->dca_data = ospeed & 0xFF;
553 	dca->dca_ier = ospeed >> 8;
554 	switch (cflag&CSIZE) {
555 	case CS5:
556 		cfcr = CFCR_5BITS; break;
557 	case CS6:
558 		cfcr = CFCR_6BITS; break;
559 	case CS7:
560 		cfcr = CFCR_7BITS; break;
561 	case CS8:
562 		cfcr = CFCR_8BITS; break;
563 	}
564 	if (cflag&PARENB) {
565 		cfcr |= CFCR_PENAB;
566 		if ((cflag&PARODD) == 0)
567 			cfcr |= CFCR_PEVEN;
568 	}
569 	if (cflag&CSTOPB)
570 		cfcr |= CFCR_STOPB;
571 	dca->dca_cfcr = cfcr;
572 	if (dca_hasfifo & (1 << unit))
573 		dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14;
574 	return (0);
575 }
576 
577 void
578 dcastart(tp)
579 	register struct tty *tp;
580 {
581 	register struct dcadevice *dca;
582 	int s, unit, c;
583 
584 	unit = UNIT(tp->t_dev);
585 	dca = dca_addr[unit];
586 	s = spltty();
587 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
588 		goto out;
589 	if (tp->t_outq.c_cc <= tp->t_lowat) {
590 		if (tp->t_state&TS_ASLEEP) {
591 			tp->t_state &= ~TS_ASLEEP;
592 			wakeup((caddr_t)&tp->t_outq);
593 		}
594 		selwakeup(&tp->t_wsel);
595 	}
596 	if (tp->t_outq.c_cc == 0)
597 		goto out;
598 	if (dca->dca_lsr & LSR_TXRDY) {
599 		c = getc(&tp->t_outq);
600 		tp->t_state |= TS_BUSY;
601 		dca->dca_data = c;
602 		if (dca_hasfifo & (1 << unit)) {
603 			for (c = 1; c < 16 && tp->t_outq.c_cc; ++c)
604 				dca->dca_data = getc(&tp->t_outq);
605 #ifdef DEBUG
606 			if (c > 16)
607 				fifoout[0]++;
608 			else
609 				fifoout[c]++;
610 #endif
611 		}
612 	}
613 out:
614 	splx(s);
615 }
616 
617 /*
618  * Stop output on a line.
619  */
620 /*ARGSUSED*/
621 dcastop(tp, flag)
622 	register struct tty *tp;
623 {
624 	register int s;
625 
626 	s = spltty();
627 	if (tp->t_state & TS_BUSY) {
628 		if ((tp->t_state&TS_TTSTOP)==0)
629 			tp->t_state |= TS_FLUSH;
630 	}
631 	splx(s);
632 }
633 
634 dcamctl(dev, bits, how)
635 	dev_t dev;
636 	int bits, how;
637 {
638 	register struct dcadevice *dca;
639 	register int unit;
640 	int s;
641 
642 	unit = UNIT(dev);
643 	dca = dca_addr[unit];
644 #ifdef hp700
645 	/*
646 	 * Always make sure MCR_IEN is set (unless setting to 0)
647 	 */
648 #ifdef KGDB
649 	if (how == DMSET && kgdb_dev == makedev(dcamajor, unit))
650 		bits |= MCR_IEN;
651 	else
652 #endif
653 	if (how == DMBIS || (how == DMSET && bits))
654 		bits |= MCR_IEN;
655 	else if (how == DMBIC)
656 		bits &= ~MCR_IEN;
657 #endif
658 	s = spltty();
659 	switch (how) {
660 
661 	case DMSET:
662 		dca->dca_mcr = bits;
663 		break;
664 
665 	case DMBIS:
666 		dca->dca_mcr |= bits;
667 		break;
668 
669 	case DMBIC:
670 		dca->dca_mcr &= ~bits;
671 		break;
672 
673 	case DMGET:
674 		bits = dca->dca_msr;
675 		break;
676 	}
677 	(void) splx(s);
678 	return (bits);
679 }
680 
681 /*
682  * Following are all routines needed for DCA to act as console
683  */
684 #include <hp/dev/cons.h>
685 
686 dcacnprobe(cp)
687 	struct consdev *cp;
688 {
689 	int unit;
690 
691 	/* locate the major number */
692 	for (dcamajor = 0; dcamajor < nchrdev; dcamajor++)
693 		if (cdevsw[dcamajor].d_open == dcaopen)
694 			break;
695 
696 	/* XXX: ick */
697 	unit = CONUNIT;
698 #ifdef hp300
699 	dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE);
700 
701 	/* make sure hardware exists */
702 	if (badaddr((short *)dca_addr[unit])) {
703 		cp->cn_pri = CN_DEAD;
704 		return;
705 	}
706 #endif
707 #ifdef hp700
708 	dca_addr[CONUNIT] = CONPORT;
709 #endif
710 
711 	/* initialize required fields */
712 	cp->cn_dev = makedev(dcamajor, unit);
713 	cp->cn_tp = &dca_tty[unit];
714 #ifdef hp300
715 	switch (dca_addr[unit]->dca_id) {
716 	case DCAID0:
717 	case DCAID1:
718 		cp->cn_pri = CN_NORMAL;
719 		break;
720 	case DCAREMID0:
721 	case DCAREMID1:
722 		cp->cn_pri = CN_REMOTE;
723 		break;
724 	default:
725 		cp->cn_pri = CN_DEAD;
726 		break;
727 	}
728 #endif
729 #ifdef hp700
730 	cp->cn_pri = CN_NORMAL;
731 #endif
732 	/*
733 	 * If dcaconsole is initialized, raise our priority.
734 	 */
735 	if (dcaconsole == unit)
736 		cp->cn_pri = CN_REMOTE;
737 #ifdef KGDB
738 	if (major(kgdb_dev) == 1)			/* XXX */
739 		kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
740 #endif
741 }
742 
743 dcacninit(cp)
744 	struct consdev *cp;
745 {
746 	int unit = UNIT(cp->cn_dev);
747 
748 	dcainit(unit, dcadefaultrate);
749 	dcaconsole = unit;
750 	dcaconsinit = 1;
751 }
752 
753 dcainit(unit, rate)
754 	int unit, rate;
755 {
756 	register struct dcadevice *dca;
757 	int s;
758 	short stat;
759 
760 #ifdef lint
761 	stat = unit; if (stat) return;
762 #endif
763 	dca = dca_addr[unit];
764 	s = splhigh();
765 #ifdef hp300
766 	dca->dca_reset = 0xFF;
767 	DELAY(100);
768 	dca->dca_ic = IC_IE;
769 #endif
770 	dca->dca_cfcr = CFCR_DLAB;
771 	rate = ttspeedtab(rate, dcaspeedtab);
772 	dca->dca_data = rate & 0xFF;
773 	dca->dca_ier = rate >> 8;
774 	dca->dca_cfcr = CFCR_8BITS;
775 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
776 #ifdef hp700
777 	dca->dca_mcr |= MCR_IEN;
778 #endif
779 	dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
780 	DELAY(100);
781 	stat = dca->dca_iir;
782 	splx(s);
783 }
784 
785 dcacngetc(dev)
786 {
787 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
788 	register u_char stat;
789 	int c, s;
790 
791 #ifdef lint
792 	stat = dev; if (stat) return (0);
793 #endif
794 	s = splhigh();
795 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
796 		;
797 	c = dca->dca_data;
798 	stat = dca->dca_iir;
799 	splx(s);
800 	return (c);
801 }
802 
803 /*
804  * Console kernel output character routine.
805  */
806 dcacnputc(dev, c)
807 	dev_t dev;
808 	register int c;
809 {
810 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
811 	register int timo;
812 	register u_char stat;
813 	int s = splhigh();
814 
815 #ifdef lint
816 	stat = dev; if (stat) return;
817 #endif
818 	if (dcaconsinit == 0) {
819 		(void) dcainit(UNIT(dev), dcadefaultrate);
820 		dcaconsinit = 1;
821 	}
822 	/* wait for any pending transmission to finish */
823 	timo = 50000;
824 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
825 		;
826 	dca->dca_data = c;
827 	/* wait for this transmission to complete */
828 	timo = 1500000;
829 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
830 		;
831 	/*
832 	 * If the "normal" interface was busy transfering a character
833 	 * we must let our interrupt through to keep things moving.
834 	 * Otherwise, we clear the interrupt that we have caused.
835 	 */
836 	if ((dca_tty[UNIT(dev)].t_state & TS_BUSY) == 0)
837 		stat = dca->dca_iir;
838 	splx(s);
839 }
840 #endif
841