xref: /original-bsd/sys/hp300/dev/dcm.c (revision 3d46ae69)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: $Hdr: dcm.c 1.17 89/10/01$
13  *
14  *	@(#)dcm.c	7.8 (Berkeley) 06/30/90
15  */
16 
17 /*
18  * TODO:
19  *	Timeouts
20  *	Test console/kgdb support.
21  */
22 
23 #include "dcm.h"
24 #if NDCM > 0
25 /*
26  *  98642/MUX
27  */
28 #include "param.h"
29 #include "systm.h"
30 #include "ioctl.h"
31 #include "tty.h"
32 #include "user.h"
33 #include "conf.h"
34 #include "file.h"
35 #include "uio.h"
36 #include "kernel.h"
37 #include "syslog.h"
38 #include "time.h"
39 
40 #include "device.h"
41 #include "dcmreg.h"
42 #include "machine/cpu.h"
43 #include "machine/isr.h"
44 
45 #ifndef DEFAULT_BAUD_RATE
46 #define DEFAULT_BAUD_RATE 9600
47 #endif
48 
49 int	ttrstrt();
50 int	dcmprobe(), dcmstart(), dcmintr(), dcmparam();
51 
52 struct	driver dcmdriver = {
53 	dcmprobe, "dcm",
54 };
55 
56 #define NDCMLINE (NDCM*4)
57 
58 struct	tty dcm_tty[NDCMLINE];
59 char	mcndlast[NDCMLINE];	/* XXX last modem status for line */
60 int	ndcm = NDCMLINE;
61 
62 int	dcm_active;
63 int	dcmsoftCAR[NDCM];
64 struct	dcmdevice *dcm_addr[NDCM];
65 struct	isr dcmisr[NDCM];
66 
67 struct speedtab dcmspeedtab[] = {
68 	0,	BR_0,
69 	50,	BR_50,
70 	75,	BR_75,
71 	110,	BR_110,
72 	134,	BR_134,
73 	150,	BR_150,
74 	300,	BR_300,
75 	600,	BR_600,
76 	1200,	BR_1200,
77 	1800,	BR_1800,
78 	2400,	BR_2400,
79 	4800,	BR_4800,
80 	9600,	BR_9600,
81 	19200,	BR_19200,
82 	38400,	BR_38400,
83 	-1,	-1
84 };
85 
86 /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
87 #define	DCM_USPERCH(s)	(10000000 / (s))
88 
89 /*
90  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
91  * (16.7ms is about 550 buad, 38.4k is 72 chars in 16.7ms).
92  */
93 #define DIS_TIMER	0
94 #define DIS_PERCHAR	1
95 #define DIS_RESET	2
96 
97 int	dcmistype = -1;		/* -1 == dynamic, 0 == timer, 1 == perchar */
98 int     dcminterval = 5;	/* interval (secs) between checks */
99 struct	dcmischeme {
100 	int	dis_perchar;	/* non-zero if interrupting per char */
101 	long	dis_time;	/* last time examined */
102 	int	dis_intr;	/* recv interrupts during last interval */
103 	int	dis_char;	/* characters read during last interval */
104 } dcmischeme[NDCM];
105 
106 /*
107  * Console support
108  */
109 int	dcmconsole = -1;
110 int	dcmdefaultrate = DEFAULT_BAUD_RATE;
111 int	dcmconbrdbusy = 0;
112 extern	struct tty *constty;
113 
114 #ifdef KGDB
115 /*
116  * Kernel GDB support
117  */
118 extern int kgdb_dev;
119 extern int kgdb_rate;
120 extern int kgdb_debug_init;
121 #endif
122 
123 /* #define IOSTATS */
124 
125 #ifdef DEBUG
126 int	dcmdebug = 0x00;
127 #define DDB_SIOERR	0x01
128 #define DDB_PARAM	0x02
129 #define DDB_INPUT	0x04
130 #define DDB_OUTPUT	0x08
131 #define DDB_INTR	0x10
132 #define DDB_IOCTL	0x20
133 #define DDB_INTSCHM	0x40
134 #define DDB_MODEM	0x80
135 #define DDB_OPENCLOSE	0x100
136 #endif
137 
138 #ifdef IOSTATS
139 #define	DCMRBSIZE	94
140 #define DCMXBSIZE	24
141 
142 struct	dcmstats {
143 	long	xints;		    /* # of xmit ints */
144 	long	xchars;		    /* # of xmit chars */
145 	long	xempty;		    /* times outq is empty in dcmstart */
146 	long	xrestarts;	    /* times completed while xmitting */
147 	long	rints;		    /* # of recv ints */
148 	long	rchars;		    /* # of recv chars */
149 	long	xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */
150 	long	rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */
151 } dcmstats[NDCM];
152 #endif
153 
154 #define UNIT(x)		minor(x)
155 #define	BOARD(x)	(((x) >> 2) & 0x3f)
156 #define PORT(x)		((x) & 3)
157 #define MKUNIT(b,p)	(((b) << 2) | (p))
158 
159 dcmprobe(hd)
160 	register struct hp_device *hd;
161 {
162 	register struct dcmdevice *dcm;
163 	register int i;
164 	register int timo = 0;
165 	int s, brd, isconsole;
166 
167 	dcm = (struct dcmdevice *)hd->hp_addr;
168 	if ((dcm->dcm_rsid & 0x1f) != DCMID)
169 		return (0);
170 	brd = hd->hp_unit;
171 	isconsole = (brd == BOARD(dcmconsole));
172 	/*
173 	 * XXX selected console device (CONSUNIT) as determined by
174 	 * dcmcnprobe does not agree with logical numbering imposed
175 	 * by the config file (i.e. lowest address DCM is not unit
176 	 * CONSUNIT).  Don't recognize this card.
177 	 */
178 	if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)])
179 		return(0);
180 
181 	/*
182 	 * Empirically derived self-test magic
183 	 */
184 	s = spltty();
185 	dcm->dcm_rsid = DCMRS;
186 	DELAY(50000);	/* 5000 is not long enough */
187 	dcm->dcm_rsid = 0;
188 	dcm->dcm_ic = IC_IE;
189 	dcm->dcm_cr = CR_SELFT;
190 	while ((dcm->dcm_ic & IC_IR) == 0)
191 		if (++timo == 20000)
192 			return(0);
193 	DELAY(50000)	/* XXX why is this needed ???? */
194 	while ((dcm->dcm_iir & IIR_SELFT) == 0)
195 		if (++timo == 400000)
196 			return(0);
197 	DELAY(50000)	/* XXX why is this needed ???? */
198 	if (dcm->dcm_stcon != ST_OK) {
199 		if (!isconsole)
200 			printf("dcm%d: self test failed: %x\n",
201 			       brd, dcm->dcm_stcon);
202 		return(0);
203 	}
204 	dcm->dcm_ic = IC_ID;
205 	splx(s);
206 
207 	hd->hp_ipl = DCMIPL(dcm->dcm_ic);
208 	dcm_addr[brd] = dcm;
209 	dcm_active |= 1 << brd;
210 	dcmsoftCAR[brd] = hd->hp_flags;
211 	dcmisr[brd].isr_ipl = hd->hp_ipl;
212 	dcmisr[brd].isr_arg = brd;
213 	dcmisr[brd].isr_intr = dcmintr;
214 	isrlink(&dcmisr[brd]);
215 #ifdef KGDB
216 	if (major(kgdb_dev) == 2 && BOARD(kgdb_dev) == brd) {
217 		if (dcmconsole == UNIT(kgdb_dev))
218 			kgdb_dev = -1;	/* can't debug over console port */
219 		else {
220 			(void) dcminit(kgdb_dev, kgdb_rate);
221 			if (kgdb_debug_init) {
222 				printf("dcm%d: kgdb waiting...",
223 				       UNIT(kgdb_dev));
224 				/* trap into kgdb */
225 				asm("trap #15;");
226 				printf("connected.\n");
227 			} else
228 				printf("dcm%d: kgdb enabled\n",
229 				       UNIT(kgdb_dev));
230 		}
231 	}
232 #endif
233 	if (dcmistype == DIS_TIMER)
234 		dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
235 	else
236 		dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
237 	dcm->dcm_mdmmsk = MI_CD|MI_CTS;	/* DCD (modem) and CTS (flow ctrl) */
238 	dcm->dcm_ic = IC_IE;		/* turn all interrupts on */
239 	/*
240 	 * Need to reset baud rate, etc. of next print so reset dcmconsole.
241 	 * Also make sure console is always "hardwired"
242 	 */
243 	if (isconsole) {
244 		dcmconsole = -1;
245 		dcmsoftCAR[brd] |= (1 << PORT(dcmconsole));
246 	}
247 	return (1);
248 }
249 
250 dcmopen(dev, flag)
251 	dev_t dev;
252 {
253 	register struct tty *tp;
254 	register int unit, brd;
255 	int error = 0;
256 
257 	unit = UNIT(dev);
258 	brd = BOARD(unit);
259 	if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0)
260 		return (ENXIO);
261 #ifdef KGDB
262 	if (unit == UNIT(kgdb_dev))
263 		return (EBUSY);
264 #endif
265 	tp = &dcm_tty[unit];
266 	tp->t_oproc = dcmstart;
267 	tp->t_param = dcmparam;
268 	tp->t_dev = dev;
269 	if ((tp->t_state & TS_ISOPEN) == 0) {
270 		tp->t_state |= TS_WOPEN;
271 		ttychars(tp);
272 		tp->t_iflag = TTYDEF_IFLAG;
273 		tp->t_oflag = TTYDEF_OFLAG;
274 		tp->t_cflag = TTYDEF_CFLAG;
275 		tp->t_lflag = TTYDEF_LFLAG;
276 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
277 		(void) dcmparam(tp, &tp->t_termios);
278 		ttsetwater(tp);
279 	} else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
280 		return (EBUSY);
281 	if (PORT(unit) == 0)	/* enable port 0 */
282 		(void) dcmmctl(dev, MO_ON, DMSET);
283 	if (dcmsoftCAR[brd] & (1 << PORT(unit)))
284 		tp->t_state |= TS_CARR_ON;
285 	else if (PORT(unit))		/* Only port 0 has modem control */
286 		tp->t_state |= TS_CARR_ON;
287 	else if (dcmmctl(dev, MO_OFF, DMGET) & MI_CD)
288 		tp->t_state |= TS_CARR_ON;
289 	(void) spltty();
290 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
291 	       (tp->t_state & TS_CARR_ON) == 0) {
292 		tp->t_state |= TS_WOPEN;
293 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
294 		    ttopen, 0))
295 			break;
296 	}
297 	(void) spl0();
298 #ifdef DEBUG
299 	if (dcmdebug & DDB_OPENCLOSE)
300 		printf("dcmopen: u %x st %x fl %x\n",
301 			unit, tp->t_state, tp->t_flags);
302 #endif
303 	if (error == 0)
304 		error = (*linesw[tp->t_line].l_open)(dev, tp);
305 	return (error);
306 }
307 
308 /*ARGSUSED*/
309 dcmclose(dev, flag)
310 	dev_t dev;
311 {
312 	register struct tty *tp;
313 	int unit;
314 
315 	unit = UNIT(dev);
316 	tp = &dcm_tty[unit];
317 	(*linesw[tp->t_line].l_close)(tp);
318 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
319 	    (tp->t_state&TS_ISOPEN) == 0)
320 		(void) dcmmctl(dev, MO_OFF, DMSET);
321 #ifdef DEBUG
322 	if (dcmdebug & DDB_OPENCLOSE)
323 		printf("dcmclose: u %x st %x fl %x\n",
324 			unit, tp->t_state, tp->t_flags);
325 #endif
326 	ttyclose(tp);
327 	return(0);
328 }
329 
330 dcmread(dev, uio, flag)
331 	dev_t dev;
332 	struct uio *uio;
333 {
334 	register struct tty *tp;
335 
336 	tp = &dcm_tty[UNIT(dev)];
337 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
338 }
339 
340 dcmwrite(dev, uio, flag)
341 	dev_t dev;
342 	struct uio *uio;
343 {
344 	int unit = UNIT(dev);
345 	register struct tty *tp;
346 
347 	tp = &dcm_tty[unit];
348 	/*
349 	 * XXX we disallow virtual consoles if the physical console is
350 	 * a serial port.  This is in case there is a display attached that
351 	 * is not the console.  In that situation we don't need/want the X
352 	 * server taking over the console.
353 	 */
354 	if (constty && unit == dcmconsole)
355 		constty = NULL;
356 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
357 }
358 
359 dcmintr(brd)
360 	register int brd;
361 {
362 	register struct dcmdevice *dcm = dcm_addr[brd];
363 	register struct dcmischeme *dis;
364 	int i, code, pcnd[4], mcnd, delta;
365 
366 	/*
367 	 * Do all guarded register accesses right off to minimize
368 	 * block out of hardware.
369 	 */
370 	SEM_LOCK(dcm);
371 	if ((dcm->dcm_ic & IC_IR) == 0) {
372 		SEM_UNLOCK(dcm);
373 		return(0);
374 	}
375 	for (i = 0; i < 4; i++) {
376 		pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
377 		dcm->dcm_icrtab[i].dcm_data = 0;
378 	}
379 	mcnd = dcm->dcm_mdmin;
380 	code = dcm->dcm_iir & IIR_MASK;
381 	dcm->dcm_iir = 0;	/* XXX doc claims read clears interrupt?! */
382 	SEM_UNLOCK(dcm);
383 
384 #ifdef DEBUG
385 	if (dcmdebug & DDB_INTR)
386 		printf("dcmintr(%d): iir %x p0 %x p1 %x p2 %x p3 %x m %x\n",
387 		       brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3], mcnd);
388 #endif
389 	if (code & IIR_TIMEO)
390 		dcmrint(brd, dcm);
391 	if (code & IIR_PORT0)
392 		dcmpint(MKUNIT(brd, 0), pcnd[0], dcm);
393 	if (code & IIR_PORT1)
394 		dcmpint(MKUNIT(brd, 1), pcnd[1],  dcm);
395 	if (code & IIR_PORT2)
396 		dcmpint(MKUNIT(brd, 2), pcnd[2], dcm);
397 	if (code & IIR_PORT3)
398 		dcmpint(MKUNIT(brd, 3), pcnd[3], dcm);
399 	if (code & IIR_MODM)
400 		dcmmint(MKUNIT(brd, 0), mcnd, dcm);	/* XXX always port 0 */
401 
402 	dis = &dcmischeme[brd];
403 	/*
404 	 * Chalk up a receiver interrupt if the timer running or one of
405 	 * the ports reports a special character interrupt.
406 	 */
407 	if ((code & IIR_TIMEO) ||
408 	    ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
409 		dis->dis_intr++;
410 	/*
411 	 * See if it is time to check/change the interrupt rate.
412 	 */
413 	if (dcmistype < 0 &&
414 	    (delta = time.tv_sec - dis->dis_time) >= dcminterval) {
415 		/*
416 		 * If currently per-character and averaged over 70 interrupts
417 		 * per-second (66 is threshold of 600 baud) in last interval,
418 		 * switch to timer mode.
419 		 *
420 		 * XXX decay counts ala load average to avoid spikes?
421 		 */
422 		if (dis->dis_perchar && dis->dis_intr > 70 * delta)
423 			dcmsetischeme(brd, DIS_TIMER);
424 		/*
425 		 * If currently using timer and had more interrupts than
426 		 * received characters in the last interval, switch back
427 		 * to per-character.  Note that after changing to per-char
428 		 * we must process any characters already in the queue
429 		 * since they may have arrived before the bitmap was setup.
430 		 *
431 		 * XXX decay counts?
432 		 */
433 		else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
434 			dcmsetischeme(brd, DIS_PERCHAR);
435 			dcmrint(brd, dcm);
436 		}
437 		dis->dis_intr = dis->dis_char = 0;
438 		dis->dis_time = time.tv_sec;
439 	}
440 	return(1);
441 }
442 
443 /*
444  *  Port interrupt.  Can be two things:
445  *	First, it might be a special character (exception interrupt);
446  *	Second, it may be a buffer empty (transmit interrupt);
447  */
448 dcmpint(unit, code, dcm)
449 	int unit, code;
450 	struct dcmdevice *dcm;
451 {
452 	struct tty *tp = &dcm_tty[unit];
453 
454 	if (code & IT_SPEC)
455 		dcmreadbuf(unit, dcm, tp);
456 	if (code & IT_TX)
457 		dcmxint(unit, dcm, tp);
458 }
459 
460 dcmrint(brd, dcm)
461 	int brd;
462 	register struct dcmdevice *dcm;
463 {
464 	register int i, unit;
465 	register struct tty *tp;
466 
467 	unit = MKUNIT(brd, 0);
468 	tp = &dcm_tty[unit];
469 	for (i = 0; i < 4; i++, tp++, unit++)
470 		dcmreadbuf(unit, dcm, tp);
471 }
472 
473 dcmreadbuf(unit, dcm, tp)
474 	int unit;
475 	register struct dcmdevice *dcm;
476 	register struct tty *tp;
477 {
478 	int port = PORT(unit);
479 	register struct dcmpreg *pp = dcm_preg(dcm, port);
480 	register struct dcmrfifo *fifo;
481 	register int c, stat;
482 	register unsigned head;
483 	int nch = 0;
484 #ifdef IOSTATS
485 	struct dcmstats *dsp = &dcmstats[BOARD(unit)];
486 
487 	dsp->rints++;
488 #endif
489 	if ((tp->t_state & TS_ISOPEN) == 0) {
490 #ifdef KGDB
491 		if (unit == UNIT(kgdb_dev) &&
492 		    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
493 		    dcm->dcm_rfifos[3-port][head>>1].data_char == '!') {
494 			pp->r_head = (head + 2) & RX_MASK;
495 			printf("kgdb trap from dcm%d\n", unit);
496 			/* trap into kgdb */
497 			asm("trap #15;");
498 			return;
499 		}
500 #endif
501 		pp->r_head = pp->r_tail & RX_MASK;
502 		return;
503 	}
504 
505 	head = pp->r_head & RX_MASK;
506 	fifo = &dcm->dcm_rfifos[3-port][head>>1];
507 	/*
508 	 * XXX upper bound on how many chars we will take in one swallow?
509 	 */
510 	while (head != (pp->r_tail & RX_MASK)) {
511 		/*
512 		 * Get character/status and update head pointer as fast
513 		 * as possible to make room for more characters.
514 		 */
515 		c = fifo->data_char;
516 		stat = fifo->data_stat;
517 		head = (head + 2) & RX_MASK;
518 		pp->r_head = head;
519 		fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
520 		nch++;
521 
522 #ifdef DEBUG
523 		if (dcmdebug & DDB_INPUT)
524 			printf("dcmreadbuf(%d): c%x('%c') s%x f%x h%x t%x\n",
525 			       unit, c&0xFF, c, stat&0xFF,
526 			       tp->t_flags, head, pp->r_tail);
527 #endif
528 		/*
529 		 * Check for and handle errors
530 		 */
531 		if (stat & RD_MASK) {
532 #ifdef DEBUG
533 			if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
534 				printf("dcmreadbuf(%d): err: c%x('%c') s%x\n",
535 				       unit, stat, c&0xFF, c);
536 #endif
537 			if (stat & (RD_BD | RD_FE))
538 				c |= TTY_FE;
539 			else if (stat & RD_PE)
540 				c |= TTY_PE;
541 			else if (stat & RD_OVF)
542 				log(LOG_WARNING,
543 				    "dcm%d: silo overflow\n", unit);
544 			else if (stat & RD_OE)
545 				log(LOG_WARNING,
546 				    "dcm%d: uart overflow\n", unit);
547 		}
548 		(*linesw[tp->t_line].l_rint)(c, tp);
549 	}
550 	dcmischeme[BOARD(unit)].dis_char += nch;
551 #ifdef IOSTATS
552 	dsp->rchars += nch;
553 	if (nch <= DCMRBSIZE)
554 		dsp->rsilo[nch]++;
555 	else
556 		dsp->rsilo[DCMRBSIZE+1]++;
557 #endif
558 }
559 
560 dcmxint(unit, dcm, tp)
561 	int unit;
562 	struct dcmdevice *dcm;
563 	register struct tty *tp;
564 {
565 	tp->t_state &= ~TS_BUSY;
566 	if (tp->t_state & TS_FLUSH)
567 		tp->t_state &= ~TS_FLUSH;
568 	if (tp->t_line)
569 		(*linesw[tp->t_line].l_start)(tp);
570 	else
571 		dcmstart(tp);
572 }
573 
574 dcmmint(unit, mcnd, dcm)
575 	register int unit;
576 	register struct dcmdevice *dcm;
577         int mcnd;
578 {
579 	register struct tty *tp;
580 	int delta;
581 
582 #ifdef DEBUG
583 	if (dcmdebug & DDB_MODEM)
584 		printf("dcmmint: unit %x mcnd %x mcndlast\n",
585 		       unit, mcnd, mcndlast[unit]);
586 #endif
587 	tp = &dcm_tty[unit];
588 	delta = mcnd ^ mcndlast[unit];
589 	mcndlast[unit] = mcnd;
590 	if ((delta & MI_CD) &&
591 	    (dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0) {
592 		if (mcnd & MI_CD)
593 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
594 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
595 			dcm->dcm_mdmout &= ~(MO_DTR|MO_RTS);
596 			SEM_LOCK(dcm);
597 			dcm->dcm_cr |= CR_MODM;
598 			SEM_UNLOCK(dcm);
599 			DELAY(10); /* time to change lines */
600 		}
601 	} else if ((delta & MI_CTS) &&
602 		   (tp->t_state & TS_ISOPEN) && (tp->t_flags & CRTSCTS)) {
603 		if (mcnd & MI_CTS) {
604 			tp->t_state &= ~TS_TTSTOP;
605 			ttstart(tp);
606 		} else
607 			tp->t_state |= TS_TTSTOP;	/* inline dcmstop */
608 	}
609 }
610 
611 dcmioctl(dev, cmd, data, flag)
612 	dev_t dev;
613 	caddr_t data;
614 {
615 	register struct tty *tp;
616 	register int unit = UNIT(dev);
617 	register struct dcmdevice *dcm;
618 	register int port;
619 	int error, s;
620 
621 #ifdef DEBUG
622 	if (dcmdebug & DDB_IOCTL)
623 		printf("dcmioctl: unit %d cmd %x data %x flag %x\n",
624 		       unit, cmd, *data, flag);
625 #endif
626 	tp = &dcm_tty[unit];
627 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
628 	if (error >= 0)
629 		return (error);
630 	error = ttioctl(tp, cmd, data, flag);
631 	if (error >= 0)
632 		return (error);
633 
634 	port = PORT(unit);
635 	dcm = dcm_addr[BOARD(unit)];
636 	switch (cmd) {
637 	case TIOCSBRK:
638 		/*
639 		 * Wait for transmitter buffer to empty
640 		 */
641 		s = spltty();
642 		while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
643 			DELAY(DCM_USPERCH(tp->t_ospeed));
644 		SEM_LOCK(dcm);
645 		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
646 		dcm->dcm_cr |= (1 << port);	/* start break */
647 		SEM_UNLOCK(dcm);
648 		splx(s);
649 		break;
650 
651 	case TIOCCBRK:
652 		SEM_LOCK(dcm);
653 		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
654 		dcm->dcm_cr |= (1 << port);	/* end break */
655 		SEM_UNLOCK(dcm);
656 		break;
657 
658 	case TIOCSDTR:
659 		(void) dcmmctl(dev, MO_ON, DMBIS);
660 		break;
661 
662 	case TIOCCDTR:
663 		(void) dcmmctl(dev, MO_ON, DMBIC);
664 		break;
665 
666 	case TIOCMSET:
667 		(void) dcmmctl(dev, *(int *)data, DMSET);
668 		break;
669 
670 	case TIOCMBIS:
671 		(void) dcmmctl(dev, *(int *)data, DMBIS);
672 		break;
673 
674 	case TIOCMBIC:
675 		(void) dcmmctl(dev, *(int *)data, DMBIC);
676 		break;
677 
678 	case TIOCMGET:
679 		*(int *)data = dcmmctl(dev, 0, DMGET);
680 		break;
681 
682 	default:
683 		return (ENOTTY);
684 	}
685 	return (0);
686 }
687 
688 dcmparam(tp, t)
689 	register struct tty *tp;
690 	register struct termios *t;
691 {
692 	register struct dcmdevice *dcm;
693 	register int port, mode, cflag = t->c_cflag;
694 	int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
695 
696 	/* check requested parameters */
697         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
698                 return(EINVAL);
699         /* and copy to tty */
700         tp->t_ispeed = t->c_ispeed;
701         tp->t_ospeed = t->c_ospeed;
702         tp->t_cflag = cflag;
703 	if (ospeed == 0) {
704 		(void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET);
705 		return(0);
706 	}
707 
708 	mode = 0;
709 	switch (cflag&CSIZE) {
710 	case CS5:
711 		mode = LC_5BITS; break;
712 	case CS6:
713 		mode = LC_6BITS; break;
714 	case CS7:
715 		mode = LC_7BITS; break;
716 	case CS8:
717 		mode = LC_8BITS; break;
718 	}
719 	if (cflag&PARENB) {
720 		if (cflag&PARODD)
721 			mode |= LC_PODD;
722 		else
723 			mode |= LC_PEVEN;
724 	}
725 	if (cflag&CSTOPB)
726 		mode |= LC_2STOP;
727 	else
728 		mode |= LC_1STOP;
729 #ifdef DEBUG
730 	if (dcmdebug & DDB_PARAM)
731 		printf("dcmparam(%d): cflag %x mode %x speed %d uperch %d\n",
732 		       UNIT(tp->t_dev), cflag, mode, tp->t_ospeed,
733 		       DCM_USPERCH(tp->t_ospeed));
734 #endif
735 
736 	port = PORT(tp->t_dev);
737 	dcm = dcm_addr[BOARD(tp->t_dev)];
738 	/*
739 	 * Wait for transmitter buffer to empty.
740 	 */
741 	while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
742 		DELAY(DCM_USPERCH(tp->t_ospeed));
743 	/*
744 	 * Make changes known to hardware.
745 	 */
746 	dcm->dcm_data[port].dcm_baud = ospeed;
747 	dcm->dcm_data[port].dcm_conf = mode;
748 	SEM_LOCK(dcm);
749 	dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
750 	dcm->dcm_cr |= (1 << port);
751 	SEM_UNLOCK(dcm);
752 	/*
753 	 * Delay for config change to take place. Weighted by buad.
754 	 * XXX why do we do this?
755 	 */
756 	DELAY(16 * DCM_USPERCH(tp->t_ospeed));
757 	return(0);
758 }
759 
760 dcmstart(tp)
761 	register struct tty *tp;
762 {
763 	register struct dcmdevice *dcm;
764 	register struct dcmpreg *pp;
765 	register struct dcmtfifo *fifo;
766 	register char *bp;
767 	register unsigned tail, next;
768 	register int port, nch;
769 	unsigned head;
770 	char buf[16];
771 	int s;
772 #ifdef IOSTATS
773 	struct dcmstats *dsp = &dcmstats[BOARD(tp->t_dev)];
774 	int tch = 0;
775 #endif
776 
777 	s = spltty();
778 #ifdef IOSTATS
779 	dsp->xints++;
780 #endif
781 #ifdef DEBUG
782 	if (dcmdebug & DDB_OUTPUT)
783 		printf("dcmstart(%d): state %x flags %x outcc %d\n",
784 		       UNIT(tp->t_dev), tp->t_state, tp->t_flags,
785 		       tp->t_outq.c_cc);
786 #endif
787 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
788 		goto out;
789 	if (tp->t_outq.c_cc <= tp->t_lowat) {
790 		if (tp->t_state&TS_ASLEEP) {
791 			tp->t_state &= ~TS_ASLEEP;
792 			wakeup((caddr_t)&tp->t_outq);
793 		}
794 		if (tp->t_wsel) {
795 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
796 			tp->t_wsel = 0;
797 			tp->t_state &= ~TS_WCOLL;
798 		}
799 	}
800 	if (tp->t_outq.c_cc == 0) {
801 #ifdef IOSTATS
802 		dsp->xempty++;
803 #endif
804 		goto out;
805 	}
806 
807 	dcm = dcm_addr[BOARD(tp->t_dev)];
808 	port = PORT(tp->t_dev);
809 	pp = dcm_preg(dcm, port);
810 	tail = pp->t_tail & TX_MASK;
811 	next = (tail + 1) & TX_MASK;
812 	head = pp->t_head & TX_MASK;
813 	if (head == next)
814 		goto out;
815 	fifo = &dcm->dcm_tfifos[3-port][tail];
816 again:
817 	nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
818 #ifdef IOSTATS
819 	tch += nch;
820 #endif
821 #ifdef DEBUG
822 	if (dcmdebug & DDB_OUTPUT)
823 		printf("\thead %x tail %x nch %d\n", head, tail, nch);
824 #endif
825 	/*
826 	 * Loop transmitting all the characters we can.
827 	 */
828 	for (bp = buf; --nch >= 0; bp++) {
829 		fifo->data_char = *bp;
830 		pp->t_tail = next;
831 		/*
832 		 * If this is the first character,
833 		 * get the hardware moving right now.
834 		 */
835 		if (bp == buf) {
836 			tp->t_state |= TS_BUSY;
837 			SEM_LOCK(dcm);
838 			dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
839 			dcm->dcm_cr |= (1 << port);
840 			SEM_UNLOCK(dcm);
841 		}
842 		tail = next;
843 		fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
844 		next = (next + 1) & TX_MASK;
845 	}
846 	/*
847 	 * Head changed while we were loading the buffer,
848 	 * go back and load some more if we can.
849 	 */
850 	if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
851 #ifdef IOSTATS
852 		dsp->xrestarts++;
853 #endif
854 		head = pp->t_head & TX_MASK;
855 		goto again;
856 	}
857 	/*
858 	 * Kick it one last time in case it finished while we were
859 	 * loading the last bunch.
860 	 */
861 	if (bp > &buf[1]) {
862 		tp->t_state |= TS_BUSY;
863 		SEM_LOCK(dcm);
864 		dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
865 		dcm->dcm_cr |= (1 << port);
866 		SEM_UNLOCK(dcm);
867 	}
868 #ifdef DEBUG
869 	if (dcmdebug & DDB_INTR)
870 		printf("dcmstart(%d): head %x tail %x outqcc %d\n",
871 		       UNIT(tp->t_dev), head, tail, tp->t_outq.c_cc);
872 #endif
873 out:
874 #ifdef IOSTATS
875 	dsp->xchars += tch;
876 	if (tch <= DCMXBSIZE)
877 		dsp->xsilo[tch]++;
878 	else
879 		dsp->xsilo[DCMXBSIZE+1]++;
880 #endif
881 	splx(s);
882 }
883 
884 /*
885  * Stop output on a line.
886  */
887 dcmstop(tp, flag)
888 	register struct tty *tp;
889 {
890 	int s;
891 
892 	s = spltty();
893 	if (tp->t_state & TS_BUSY) {
894 		/* XXX is there some way to safely stop transmission? */
895 		if ((tp->t_state&TS_TTSTOP) == 0)
896 			tp->t_state |= TS_FLUSH;
897 	}
898 	splx(s);
899 }
900 
901 /* Modem control */
902 
903 dcmmctl(dev, bits, how)
904 	dev_t dev;
905 	int bits, how;
906 {
907 	register struct dcmdevice *dcm;
908 	int s, hit = 0;
909 
910 	/*
911 	 * Only port 0 has modem control lines.
912 	 * XXX ok for now but needs to changed for the 8 port board.
913 	 */
914 	if (PORT(UNIT(dev)) != 0)
915 		return(bits);
916 
917 	dcm = dcm_addr[BOARD(UNIT(dev))];
918 	s = spltty();
919 	switch (how) {
920 
921 	case DMSET:
922 		dcm->dcm_mdmout = bits;
923 		hit++;
924 		break;
925 
926 	case DMBIS:
927 		dcm->dcm_mdmout |= bits;
928 		hit++;
929 		break;
930 
931 	case DMBIC:
932 		dcm->dcm_mdmout &= ~bits;
933 		hit++;
934 		break;
935 
936 	case DMGET:
937 		bits = dcm->dcm_mdmin;
938 		break;
939 	}
940 	if (hit) {
941 		SEM_LOCK(dcm);
942 		dcm->dcm_cr |= CR_MODM;
943 		SEM_UNLOCK(dcm);
944 		DELAY(10); /* delay until done */
945 		(void) splx(s);
946 	}
947 	return(bits);
948 }
949 
950 /*
951  * Set board to either interrupt per-character or at a fixed interval.
952  */
953 dcmsetischeme(brd, flags)
954 	int brd, flags;
955 {
956 	register struct dcmdevice *dcm = dcm_addr[brd];
957 	register struct dcmischeme *dis = &dcmischeme[brd];
958 	register int i;
959 	u_char mask;
960 	int perchar = flags & DIS_PERCHAR;
961 
962 #ifdef DEBUG
963 	if (dcmdebug & DDB_INTSCHM)
964 		printf("dcmsetischeme(%d, %d): cur %d, ints %d, chars %d\n",
965 		       brd, perchar, dis->dis_perchar,
966 		       dis->dis_intr, dis->dis_char);
967 	if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
968 		printf("dcmsetischeme(%d):  redundent request %d\n",
969 		       brd, perchar);
970 		return;
971 	}
972 #endif
973 	/*
974 	 * If perchar is non-zero, we enable interrupts on all characters
975 	 * otherwise we disable perchar interrupts and use periodic
976 	 * polling interrupts.
977 	 */
978 	dis->dis_perchar = perchar;
979 	mask = perchar ? 0xf : 0x0;
980 	for (i = 0; i < 256; i++)
981 		dcm->dcm_bmap[i].data_data = mask;
982 	/*
983 	 * Don't slow down tandem mode, interrupt on flow control
984 	 * chars for any port on the board.
985 	 */
986 	if (!perchar) {
987 		register struct tty *tp = &dcm_tty[MKUNIT(brd, 0)];
988 		int c;
989 
990 		for (i = 0; i < 4; i++, tp++) {
991 			if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
992 				dcm->dcm_bmap[c].data_data |= (1 << i);
993 			if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
994 				dcm->dcm_bmap[c].data_data |= (1 << i);
995 		}
996 	}
997 	/*
998 	 * Board starts with timer disabled so if first call is to
999 	 * set perchar mode then we don't want to toggle the timer.
1000 	 */
1001 	if (flags == (DIS_RESET|DIS_PERCHAR))
1002 		return;
1003 	/*
1004 	 * Toggle card 16.7ms interrupts (we first make sure that card
1005 	 * has cleared the bit so it will see the toggle).
1006 	 */
1007 	while (dcm->dcm_cr & CR_TIMER)
1008 		;
1009 	SEM_LOCK(dcm);
1010 	dcm->dcm_cr |= CR_TIMER;
1011 	SEM_UNLOCK(dcm);
1012 }
1013 
1014 /*
1015  * Following are all routines needed for DCM to act as console
1016  */
1017 #include "machine/cons.h"
1018 
1019 dcmcnprobe(cp)
1020 	struct consdev *cp;
1021 {
1022 	register struct hp_hw *hw;
1023 	int unit, i;
1024 	extern int dcmopen();
1025 
1026 	/*
1027 	 * Implicitly assigns the lowest select code DCM card found to be
1028 	 * logical unit 0 (actually CONUNIT).  If your config file does
1029 	 * anything different, you're screwed.
1030 	 */
1031 	for (hw = sc_table; hw->hw_type; hw++)
1032 	        if (hw->hw_type == COMMDCM && !badaddr((short *)hw->hw_addr))
1033 			break;
1034 	if (hw->hw_type != COMMDCM) {
1035 		cp->cn_pri = CN_DEAD;
1036 		return;
1037 	}
1038 	unit = CONUNIT;
1039 	dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_addr;
1040 
1041 	/* locate the major number */
1042 	for (i = 0; i < nchrdev; i++)
1043 		if (cdevsw[i].d_open == dcmopen)
1044 			break;
1045 
1046 	/* initialize required fields */
1047 	cp->cn_dev = makedev(i, unit);
1048 	cp->cn_tp = &dcm_tty[unit];
1049 	switch (dcm_addr[BOARD(unit)]->dcm_rsid) {
1050 	case DCMID:
1051 		cp->cn_pri = CN_NORMAL;
1052 		break;
1053 	case DCMID|DCMCON:
1054 		cp->cn_pri = CN_REMOTE;
1055 		break;
1056 	default:
1057 		cp->cn_pri = CN_DEAD;
1058 		break;
1059 	}
1060 }
1061 
1062 dcmcninit(cp)
1063 	struct consdev *cp;
1064 {
1065 	dcminit(cp->cn_dev, dcmdefaultrate);
1066 	dcmconsole = UNIT(cp->cn_dev);
1067 }
1068 
1069 dcminit(dev, rate)
1070 	dev_t dev;
1071 	int rate;
1072 {
1073 	register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
1074 	int s, mode, port;
1075 
1076 	port = PORT(dev);
1077 	mode = LC_8BITS | LC_1STOP;
1078 	s = splhigh();
1079 	/*
1080 	 * Wait for transmitter buffer to empty.
1081 	 */
1082 	while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
1083 		DELAY(DCM_USPERCH(rate));
1084 	/*
1085 	 * Make changes known to hardware.
1086 	 */
1087 	dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
1088 	dcm->dcm_data[port].dcm_conf = mode;
1089 	SEM_LOCK(dcm);
1090 	dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
1091 	dcm->dcm_cr |= (1 << port);
1092 	SEM_UNLOCK(dcm);
1093 	/*
1094 	 * Delay for config change to take place. Weighted by buad.
1095 	 * XXX why do we do this?
1096 	 */
1097 	DELAY(16 * DCM_USPERCH(rate));
1098 	splx(s);
1099 }
1100 
1101 dcmcngetc(dev)
1102 	dev_t dev;
1103 {
1104 	register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
1105 	register struct dcmrfifo *fifo;
1106 	register struct dcmpreg *pp;
1107 	register unsigned head;
1108 	int s, c, stat, port;
1109 
1110 	port = PORT(dev);
1111 	pp = dcm_preg(dcm, port);
1112 	s = splhigh();
1113 	head = pp->r_head & RX_MASK;
1114 	fifo = &dcm->dcm_rfifos[3-port][head>>1];
1115 	while (head == (pp->r_tail & RX_MASK))
1116 		;
1117 	/*
1118 	 * If board interrupts are enabled, just let our received char
1119 	 * interrupt through in case some other port on the board was
1120 	 * busy.  Otherwise we must clear the interrupt.
1121 	 */
1122 	SEM_LOCK(dcm);
1123 	if ((dcm->dcm_ic & IC_IE) == 0)
1124 		stat = dcm->dcm_iir;
1125 	SEM_UNLOCK(dcm);
1126 	c = fifo->data_char;
1127 	stat = fifo->data_stat;
1128 	pp->r_head = (head + 2) & RX_MASK;
1129 	splx(s);
1130 	return(c);
1131 }
1132 
1133 /*
1134  * Console kernel output character routine.
1135  */
1136 dcmcnputc(dev, c)
1137 	dev_t dev;
1138 	int c;
1139 {
1140 	register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
1141 	register struct dcmpreg *pp;
1142 	unsigned tail;
1143 	int s, port, stat;
1144 
1145 	port = PORT(dev);
1146 	pp = dcm_preg(dcm, port);
1147 	s = splhigh();
1148 #ifdef KGDB
1149 	if (dev != kgdb_dev)
1150 #endif
1151 	if (dcmconsole == -1) {
1152 		(void) dcminit(dev, dcmdefaultrate);
1153 		dcmconsole = UNIT(dev);
1154 	}
1155 	tail = pp->t_tail & TX_MASK;
1156 	while (tail != (pp->t_head & TX_MASK))
1157 		;
1158 	dcm->dcm_tfifos[3-port][tail].data_char = c;
1159 	pp->t_tail = tail = (tail + 1) & TX_MASK;
1160 	SEM_LOCK(dcm);
1161 	dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1162 	dcm->dcm_cr |= (1 << port);
1163 	SEM_UNLOCK(dcm);
1164 	while (tail != (pp->t_head & TX_MASK))
1165 		;
1166 	/*
1167 	 * If board interrupts are enabled, just let our completion
1168 	 * interrupt through in case some other port on the board
1169 	 * was busy.  Otherwise we must clear the interrupt.
1170 	 */
1171 	if ((dcm->dcm_ic & IC_IE) == 0) {
1172 		SEM_LOCK(dcm);
1173 		stat = dcm->dcm_iir;
1174 		SEM_UNLOCK(dcm);
1175 	}
1176 	splx(s);
1177 }
1178 #endif
1179