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