xref: /csrg-svn/sys/hp/dev/dca.c (revision 49130)
1 /*
2  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)dca.c	7.9 (Berkeley) 05/04/91
8  */
9 
10 #include "dca.h"
11 #if NDCA > 0
12 /*
13  *  98626/98644/internal serial interface
14  */
15 #include "sys/param.h"
16 #include "sys/systm.h"
17 #include "sys/ioctl.h"
18 #include "sys/tty.h"
19 #include "sys/proc.h"
20 #include "sys/conf.h"
21 #include "sys/file.h"
22 #include "sys/uio.h"
23 #include "sys/kernel.h"
24 #include "sys/syslog.h"
25 
26 #include "device.h"
27 #include "dcareg.h"
28 #include "machine/cpu.h"
29 #include "../hp300/isr.h"
30 
31 int	dcaprobe();
32 struct	driver dcadriver = {
33 	dcaprobe, "dca",
34 };
35 
36 int	dcastart(), dcaparam(), dcaintr();
37 int	dcasoftCAR;
38 int	dca_active;
39 int	ndca = NDCA;
40 #ifdef DCACONSOLE
41 int	dcaconsole = DCACONSOLE;
42 #else
43 int	dcaconsole = -1;
44 #endif
45 int	dcaconsinit;
46 int	dcadefaultrate = TTYDEF_SPEED;
47 int	dcamajor;
48 struct	dcadevice *dca_addr[NDCA];
49 struct	tty dca_tty[NDCA];
50 struct	isr dcaisr[NDCA];
51 
52 struct speedtab dcaspeedtab[] = {
53 	0,	0,
54 	50,	DCABRD(50),
55 	75,	DCABRD(75),
56 	110,	DCABRD(110),
57 	134,	DCABRD(134),
58 	150,	DCABRD(150),
59 	200,	DCABRD(200),
60 	300,	DCABRD(300),
61 	600,	DCABRD(600),
62 	1200,	DCABRD(1200),
63 	1800,	DCABRD(1800),
64 	2400,	DCABRD(2400),
65 	4800,	DCABRD(4800),
66 	9600,	DCABRD(9600),
67 	19200,	DCABRD(19200),
68 	38400,	DCABRD(38400),
69 	-1,	-1
70 };
71 
72 extern	struct tty *constty;
73 #ifdef KGDB
74 #include "machine/remote-sl.h"
75 
76 extern int kgdb_dev;
77 extern int kgdb_rate;
78 extern int kgdb_debug_init;
79 #endif
80 
81 #define	UNIT(x)		minor(x)
82 
83 dcaprobe(hd)
84 	register struct hp_device *hd;
85 {
86 	register struct dcadevice *dca;
87 	register int unit;
88 
89 	dca = (struct dcadevice *)hd->hp_addr;
90 	if (dca->dca_irid != DCAID0 &&
91 	    dca->dca_irid != DCAREMID0 &&
92 	    dca->dca_irid != DCAID1 &&
93 	    dca->dca_irid != DCAREMID1)
94 		return (0);
95 	unit = hd->hp_unit;
96 	if (unit == dcaconsole)
97 		DELAY(100000);
98 	dca->dca_irid = 0xFF;
99 	DELAY(100);
100 
101 	hd->hp_ipl = DCAIPL(dca->dca_ic);
102 	dcaisr[unit].isr_ipl = hd->hp_ipl;
103 	dcaisr[unit].isr_arg = unit;
104 	dcaisr[unit].isr_intr = dcaintr;
105 	dca_addr[unit] = dca;
106 	dca_active |= 1 << unit;
107 	dcasoftCAR = hd->hp_flags;
108 	isrlink(&dcaisr[unit]);
109 #ifdef KGDB
110 	if (kgdb_dev == makedev(dcamajor, unit)) {
111 		if (dcaconsole == unit)
112 			kgdb_dev = -1;	/* can't debug over console port */
113 		else {
114 			(void) dcainit(unit, kgdb_rate);
115 			if (kgdb_debug_init) {
116 				/*
117 				 * Print prefix of device name,
118 				 * let kgdb_connect print the rest.
119 				 */
120 				printf("dca%d: ", unit);
121 				kgdb_connect(1);
122 			} else
123 				printf("dca%d: kgdb enabled\n", unit);
124 		}
125 	}
126 #endif
127 	dca->dca_ic = IC_IE;
128 	/*
129 	 * Need to reset baud rate, etc. of next print so reset dcaconsinit.
130 	 * Also make sure console is always "hardwired."
131 	 */
132 	if (unit == dcaconsole) {
133 		dcaconsinit = 0;
134 		dcasoftCAR |= (1 << unit);
135 	}
136 	return (1);
137 }
138 
139 /* ARGSUSED */
140 #ifdef __STDC__
141 dcaopen(dev_t dev, int flag, int mode, struct proc *p)
142 #else
143 dcaopen(dev, flag, mode, p)
144 	dev_t dev;
145 	int flag, mode;
146 	struct proc *p;
147 #endif
148 {
149 	register struct tty *tp;
150 	register int unit;
151 	int error = 0;
152 
153 	unit = UNIT(dev);
154 	if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
155 		return (ENXIO);
156 	tp = &dca_tty[unit];
157 	tp->t_oproc = dcastart;
158 	tp->t_param = dcaparam;
159 	tp->t_dev = dev;
160 	if ((tp->t_state & TS_ISOPEN) == 0) {
161 		tp->t_state |= TS_WOPEN;
162 		ttychars(tp);
163 		if (tp->t_ispeed == 0) {
164 			tp->t_iflag = TTYDEF_IFLAG;
165 			tp->t_oflag = TTYDEF_OFLAG;
166 			tp->t_cflag = TTYDEF_CFLAG;
167 			tp->t_lflag = TTYDEF_LFLAG;
168 			tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
169 		}
170 		dcaparam(tp, &tp->t_termios);
171 		ttsetwater(tp);
172 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
173 		return (EBUSY);
174 	(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
175 	if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
176 		tp->t_state |= TS_CARR_ON;
177 	(void) spltty();
178 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
179 	       (tp->t_state & TS_CARR_ON) == 0) {
180 		tp->t_state |= TS_WOPEN;
181 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
182 		    ttopen, 0))
183 			break;
184 	}
185 	(void) spl0();
186 	if (error == 0)
187 		error = (*linesw[tp->t_line].l_open)(dev, tp);
188 	return (error);
189 }
190 
191 /*ARGSUSED*/
192 dcaclose(dev, flag)
193 	dev_t dev;
194 {
195 	register struct tty *tp;
196 	register struct dcadevice *dca;
197 	register int unit;
198 
199 	unit = UNIT(dev);
200 	dca = dca_addr[unit];
201 	tp = &dca_tty[unit];
202 	(*linesw[tp->t_line].l_close)(tp);
203 	dca->dca_cfcr &= ~CFCR_SBREAK;
204 #ifdef KGDB
205 	/* do not disable interrupts if debugging */
206 	if (dev != kgdb_dev)
207 #endif
208 	dca->dca_ier = 0;
209 	(void) dcamctl(dev, 0, DMSET);
210 	if (tp->t_state & TS_HUPCLS)
211 		(*linesw[tp->t_line].l_modem)(tp, 0);
212 	ttyclose(tp);
213 	return(0);
214 }
215 
216 dcaread(dev, uio, flag)
217 	dev_t dev;
218 	struct uio *uio;
219 {
220 	register struct tty *tp = &dca_tty[UNIT(dev)];
221 
222 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
223 }
224 
225 dcawrite(dev, uio, flag)
226 	dev_t dev;
227 	struct uio *uio;
228 {
229 	int unit = UNIT(dev);
230 	register struct tty *tp = &dca_tty[unit];
231 
232 	/*
233 	 * (XXX) We disallow virtual consoles if the physical console is
234 	 * a serial port.  This is in case there is a display attached that
235 	 * is not the console.  In that situation we don't need/want the X
236 	 * server taking over the console.
237 	 */
238 	if (constty && unit == dcaconsole)
239 		constty = NULL;
240 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
241 }
242 
243 dcaintr(unit)
244 	register int unit;
245 {
246 	register struct dcadevice *dca;
247 	register u_char code;
248 	register struct tty *tp;
249 
250 	dca = dca_addr[unit];
251 	if ((dca->dca_ic & IC_IR) == 0)
252 		return(0);
253 	while (1) {
254 		code = dca->dca_iir;
255 		switch (code) {
256 		case IIR_NOPEND:
257 			return (1);
258 		case IIR_RXRDY:
259 			/* do time-critical read in-line */
260 			tp = &dca_tty[unit];
261 			code = dca->dca_data;
262 			if ((tp->t_state & TS_ISOPEN) == 0) {
263 #ifdef KGDB
264 				if (kgdb_dev == makedev(dcamajor, unit) &&
265 				    code == FRAME_END)
266 					kgdb_connect(0); /* trap into kgdb */
267 #endif
268 			} else
269 				(*linesw[tp->t_line].l_rint)(code, tp);
270 			break;
271 		case IIR_TXRDY:
272 			tp = &dca_tty[unit];
273 			tp->t_state &=~ (TS_BUSY|TS_FLUSH);
274 			if (tp->t_line)
275 				(*linesw[tp->t_line].l_start)(tp);
276 			else
277 				dcastart(tp);
278 			break;
279 		case IIR_RLS:
280 			dcaeint(unit, dca);
281 			break;
282 		default:
283 			if (code & IIR_NOPEND)
284 				return (1);
285 			log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n",
286 			    unit, code);
287 			/* fall through */
288 		case IIR_MLSC:
289 			dcamint(unit, dca);
290 			break;
291 		}
292 	}
293 }
294 
295 dcaeint(unit, dca)
296 	register int unit;
297 	register struct dcadevice *dca;
298 {
299 	register struct tty *tp;
300 	register int stat, c;
301 
302 	tp = &dca_tty[unit];
303 	stat = dca->dca_lsr;
304 	c = dca->dca_data;
305 	if ((tp->t_state & TS_ISOPEN) == 0) {
306 #ifdef KGDB
307 		/* we don't care about parity errors */
308 		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
309 		    kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END)
310 			kgdb_connect(0); /* trap into kgdb */
311 #endif
312 		return;
313 	}
314 	if (stat & (LSR_BI | LSR_FE))
315 		c |= TTY_FE;
316 	else if (stat & LSR_PE)
317 		c |= TTY_PE;
318 	else if (stat & LSR_OE)
319 		log(LOG_WARNING, "dca%d: silo overflow\n", unit);
320 	(*linesw[tp->t_line].l_rint)(c, tp);
321 }
322 
323 dcamint(unit, dca)
324 	register int unit;
325 	register struct dcadevice *dca;
326 {
327 	register struct tty *tp;
328 	register int stat;
329 
330 	tp = &dca_tty[unit];
331 	stat = dca->dca_msr;
332 	if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) {
333 		if (stat & MSR_DCD)
334 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
335 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
336 			dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
337 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
338 		   (tp->t_flags & CRTSCTS)) {
339 		/* the line is up and we want to do rts/cts flow control */
340 		if (stat & MSR_CTS) {
341 			tp->t_state &=~ TS_TTSTOP;
342 			ttstart(tp);
343 		} else
344 			tp->t_state |= TS_TTSTOP;
345 	}
346 }
347 
348 dcaioctl(dev, cmd, data, flag)
349 	dev_t dev;
350 	caddr_t data;
351 {
352 	register struct tty *tp;
353 	register int unit = UNIT(dev);
354 	register struct dcadevice *dca;
355 	register int error;
356 
357 	tp = &dca_tty[unit];
358 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
359 	if (error >= 0)
360 		return (error);
361 	error = ttioctl(tp, cmd, data, flag);
362 	if (error >= 0)
363 		return (error);
364 
365 	dca = dca_addr[unit];
366 	switch (cmd) {
367 
368 	case TIOCSBRK:
369 		dca->dca_cfcr |= CFCR_SBREAK;
370 		break;
371 
372 	case TIOCCBRK:
373 		dca->dca_cfcr &= ~CFCR_SBREAK;
374 		break;
375 
376 	case TIOCSDTR:
377 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
378 		break;
379 
380 	case TIOCCDTR:
381 		(void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
382 		break;
383 
384 	case TIOCMSET:
385 		(void) dcamctl(dev, *(int *)data, DMSET);
386 		break;
387 
388 	case TIOCMBIS:
389 		(void) dcamctl(dev, *(int *)data, DMBIS);
390 		break;
391 
392 	case TIOCMBIC:
393 		(void) dcamctl(dev, *(int *)data, DMBIC);
394 		break;
395 
396 	case TIOCMGET:
397 		*(int *)data = dcamctl(dev, 0, DMGET);
398 		break;
399 
400 	default:
401 		return (ENOTTY);
402 	}
403 	return (0);
404 }
405 
406 dcaparam(tp, t)
407 	register struct tty *tp;
408 	register struct termios *t;
409 {
410 	register struct dcadevice *dca;
411 	register int cfcr, cflag = t->c_cflag;
412 	int unit = UNIT(tp->t_dev);
413 	int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
414 
415 	/* check requested parameters */
416         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
417                 return(EINVAL);
418         /* and copy to tty */
419         tp->t_ispeed = t->c_ispeed;
420         tp->t_ospeed = t->c_ospeed;
421         tp->t_cflag = cflag;
422 
423 	dca = dca_addr[unit];
424 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
425 	if (ospeed == 0) {
426 		(void) dcamctl(unit, 0, DMSET);	/* hang up line */
427 		return(0);
428 	}
429 	dca->dca_cfcr |= CFCR_DLAB;
430 	dca->dca_data = ospeed & 0xFF;
431 	dca->dca_ier = ospeed >> 8;
432 	switch (cflag&CSIZE) {
433 	case CS5:
434 		cfcr = CFCR_5BITS; break;
435 	case CS6:
436 		cfcr = CFCR_6BITS; break;
437 	case CS7:
438 		cfcr = CFCR_7BITS; break;
439 	case CS8:
440 		cfcr = CFCR_8BITS; break;
441 	}
442 	if (cflag&PARENB) {
443 		cfcr |= CFCR_PENAB;
444 		if ((cflag&PARODD) == 0)
445 			cfcr |= CFCR_PEVEN;
446 	}
447 	if (cflag&CSTOPB)
448 		cfcr |= CFCR_STOPB;
449 	dca->dca_cfcr = cfcr;
450 	return(0);
451 }
452 
453 dcastart(tp)
454 	register struct tty *tp;
455 {
456 	register struct dcadevice *dca;
457 	int s, unit, c;
458 
459 	unit = UNIT(tp->t_dev);
460 	dca = dca_addr[unit];
461 	s = spltty();
462 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
463 		goto out;
464 	if (tp->t_outq.c_cc <= tp->t_lowat) {
465 		if (tp->t_state&TS_ASLEEP) {
466 			tp->t_state &= ~TS_ASLEEP;
467 			wakeup((caddr_t)&tp->t_outq);
468 		}
469 		if (tp->t_wsel) {
470 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
471 			tp->t_wsel = 0;
472 			tp->t_state &= ~TS_WCOLL;
473 		}
474 	}
475 	if (tp->t_outq.c_cc == 0)
476 		goto out;
477 	if (dca->dca_lsr & LSR_TXRDY) {
478 		c = getc(&tp->t_outq);
479 		tp->t_state |= TS_BUSY;
480 		dca->dca_data = c;
481 	}
482 out:
483 	splx(s);
484 }
485 
486 /*
487  * Stop output on a line.
488  */
489 /*ARGSUSED*/
490 dcastop(tp, flag)
491 	register struct tty *tp;
492 {
493 	register int s;
494 
495 	s = spltty();
496 	if (tp->t_state & TS_BUSY) {
497 		if ((tp->t_state&TS_TTSTOP)==0)
498 			tp->t_state |= TS_FLUSH;
499 	}
500 	splx(s);
501 }
502 
503 dcamctl(dev, bits, how)
504 	dev_t dev;
505 	int bits, how;
506 {
507 	register struct dcadevice *dca;
508 	register int unit;
509 	int s;
510 
511 	unit = UNIT(dev);
512 	dca = dca_addr[unit];
513 	s = spltty();
514 	switch (how) {
515 
516 	case DMSET:
517 		dca->dca_mcr = bits;
518 		break;
519 
520 	case DMBIS:
521 		dca->dca_mcr |= bits;
522 		break;
523 
524 	case DMBIC:
525 		dca->dca_mcr &= ~bits;
526 		break;
527 
528 	case DMGET:
529 		bits = dca->dca_msr;
530 		break;
531 	}
532 	(void) splx(s);
533 	return(bits);
534 }
535 
536 /*
537  * Following are all routines needed for DCA to act as console
538  */
539 #include "../hp300/cons.h"
540 
541 dcacnprobe(cp)
542 	struct consdev *cp;
543 {
544 	int unit, i;
545 
546 	/* locate the major number */
547 	for (dcamajor = 0; dcamajor < nchrdev; dcamajor++)
548 		if (cdevsw[dcamajor].d_open == dcaopen)
549 			break;
550 
551 	/* XXX: ick */
552 	unit = CONUNIT;
553 	dca_addr[CONUNIT] = CONADDR;
554 
555 	/* make sure hardware exists */
556 	if (badaddr((short *)dca_addr[unit])) {
557 		cp->cn_pri = CN_DEAD;
558 		return;
559 	}
560 
561 	/* initialize required fields */
562 	cp->cn_dev = makedev(dcamajor, unit);
563 	cp->cn_tp = &dca_tty[unit];
564 	switch (dca_addr[unit]->dca_irid) {
565 	case DCAID0:
566 	case DCAID1:
567 		cp->cn_pri = CN_NORMAL;
568 		break;
569 	case DCAREMID0:
570 	case DCAREMID1:
571 		cp->cn_pri = CN_REMOTE;
572 		break;
573 	default:
574 		cp->cn_pri = CN_DEAD;
575 		break;
576 	}
577 	/*
578 	 * If dcmconsole is initialized, raise our priority.
579 	 */
580 	if (dcaconsole == unit)
581 		cp->cn_pri = CN_REMOTE;
582 	if (major(kgdb_dev) == 1)			/* XXX */
583 		kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
584 }
585 
586 dcacninit(cp)
587 	struct consdev *cp;
588 {
589 	int unit = UNIT(cp->cn_dev);
590 
591 	dcainit(unit, dcadefaultrate);
592 	dcaconsole = unit;
593 	dcaconsinit = 1;
594 }
595 
596 dcainit(unit, rate)
597 	int unit, rate;
598 {
599 	register struct dcadevice *dca;
600 	int s;
601 	short stat;
602 
603 #ifdef lint
604 	stat = unit; if (stat) return;
605 #endif
606 	dca = dca_addr[unit];
607 	s = splhigh();
608 	dca->dca_irid = 0xFF;
609 	DELAY(100);
610 	dca->dca_ic = IC_IE;
611 	dca->dca_cfcr = CFCR_DLAB;
612 	rate = ttspeedtab(rate, dcaspeedtab);
613 	dca->dca_data = rate & 0xFF;
614 	dca->dca_ier = rate >> 8;
615 	dca->dca_cfcr = CFCR_8BITS;
616 	dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
617 	stat = dca->dca_iir;
618 	splx(s);
619 }
620 
621 dcacngetc(dev)
622 {
623 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
624 	short stat;
625 	int c, s;
626 
627 #ifdef lint
628 	stat = dev; if (stat) return(0);
629 #endif
630 	s = splhigh();
631 	while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
632 		;
633 	c = dca->dca_data;
634 	stat = dca->dca_iir;
635 	splx(s);
636 	return(c);
637 }
638 
639 /*
640  * Console kernel output character routine.
641  */
642 dcacnputc(dev, c)
643 	dev_t dev;
644 	register int c;
645 {
646 	register struct dcadevice *dca = dca_addr[UNIT(dev)];
647 	register int timo;
648 	short stat;
649 	int s = splhigh();
650 
651 #ifdef lint
652 	stat = dev; if (stat) return;
653 #endif
654 #ifdef KGDB
655 	if (dev != kgdb_dev)
656 #endif
657 	if (dcaconsinit == 0) {
658 		(void) dcainit(UNIT(dev), dcadefaultrate);
659 		dcaconsinit = 1;
660 	}
661 	/* wait for any pending transmission to finish */
662 	timo = 50000;
663 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
664 		;
665 	dca->dca_data = c;
666 	/* wait for this transmission to complete */
667 	timo = 1500000;
668 	while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
669 		;
670 	/* clear any interrupts generated by this transmission */
671 	stat = dca->dca_iir;
672 	splx(s);
673 }
674 #endif
675