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