xref: /csrg-svn/sys/vax/uba/ct.c (revision 45804)
123319Smckusick /*
229208Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323319Smckusick  * All rights reserved.  The Berkeley software License Agreement
423319Smckusick  * specifies the terms and conditions for redistribution.
523319Smckusick  *
6*45804Sbostic  *	@(#)ct.c	7.6 (Berkeley) 12/16/90
723319Smckusick  */
82621Swnj 
93201Swnj #include "ct.h"
102621Swnj #if NCT > 0
112621Swnj /*
1227234Skarels  * GP DR11C driver used for C/A/T or Autologic APS micro-5
132621Swnj  */
14*45804Sbostic #include "../include/pte.h"
152621Swnj 
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/systm.h"
18*45804Sbostic #include "sys/ioctl.h"
19*45804Sbostic #include "sys/tty.h"
20*45804Sbostic #include "sys/map.h"
21*45804Sbostic #include "sys/buf.h"
22*45804Sbostic #include "sys/conf.h"
23*45804Sbostic #include "sys/user.h"
24*45804Sbostic #include "sys/kernel.h"
252621Swnj 
2617073Sbloom #include "ubareg.h"
2717073Sbloom #include "ubavar.h"
288472Sroot 
292621Swnj #define	PCAT	(PZERO+9)
302621Swnj #define	CATHIWAT	100
312621Swnj #define	CATLOWAT	30
322621Swnj 
3327234Skarels #define	REQUEST_B	0x8000
3427234Skarels #define REQUEST_A	0x80
3527234Skarels #define	INT_ENB_A	0x40
3627234Skarels #define	INT_ENB_B	0x20
3727234Skarels #define	CSR1		0x2
3827234Skarels #define	CSR0		0x1
3927234Skarels 
403201Swnj struct ct_softc {
4127234Skarels 	int	sc_state;
423201Swnj 	struct	clist sc_oq;
433201Swnj } ct_softc[NCT];
442621Swnj 
4527234Skarels #define	CT_OPEN		0x1
4627234Skarels #define	CT_RUNNING	0x2
4727234Skarels 
483201Swnj struct ctdevice {
4927234Skarels 	u_short	ctcsr;
5027234Skarels 	u_short	ctobuf;
5127234Skarels 	u_short ctibuf;
522621Swnj };
532621Swnj 
543201Swnj int	ctprobe(), ctattach(), ctintr();
553201Swnj struct	uba_device *ctdinfo[NCT];
5627234Skarels u_short	ctstd[] = { 0167770, 0 };
573201Swnj struct	uba_driver ctdriver =
583201Swnj     { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo };
592621Swnj 
603217Swnj #define	CTUNIT(dev)	(minor(dev))
613217Swnj 
6227234Skarels int	ct_init	= 0;	/* set to CSR1 for testing loopback on controller */
6327234Skarels 
ctprobe(reg)643201Swnj ctprobe(reg)
653201Swnj 	caddr_t reg;
663201Swnj {
673936Sbugs 	register int br, cvec;		/* value-result */
683201Swnj 	register struct ctdevice *ctaddr = (struct ctdevice *)reg;
693201Swnj 
704932Swnj #ifdef lint
714932Swnj 	br = 0; cvec = br; br = cvec;
724932Swnj 	ctintr(0);
734932Swnj #endif
7427234Skarels 	/*
7527234Skarels 	 * There is no way to make a DR11c interrupt without some
7627234Skarels 	 * external support. We can't always trust that the typesetter
7727234Skarels 	 * will be online and ready so we've made other provisions.
7827234Skarels 	 * This probe assumes setting the B Int Enb will generate
7927234Skarels 	 * an interrupt. To do this, we set CSR0 and loop this back
8027234Skarels 	 * to REQUEST_B in the second plug on the controller.
8127234Skarels 	 * Then, we reset the vector to be that for the "real" device.
8227234Skarels 	 */
8327234Skarels 	ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */
8427234Skarels 	DELAY(1000);
8527234Skarels 	ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */
8627234Skarels 	if (cvec & 04) {
8727234Skarels 		printf("ct: resetting vector %o to %o\n", cvec, cvec&0773);
8827234Skarels 		cvec &= 0773;
8927234Skarels 	}
907409Skre 	return (sizeof (struct ctdevice));
913201Swnj }
923201Swnj 
933217Swnj /*ARGSUSED*/
943217Swnj ctattach(ui)
9528955Skarels 	struct uba_device *ui;
963217Swnj {
973217Swnj }
983217Swnj 
ctopen(dev)992621Swnj ctopen(dev)
1003201Swnj 	dev_t dev;
1012621Swnj {
1023201Swnj 	register struct ct_softc *sc;
1033201Swnj 	register struct uba_device *ui;
1043201Swnj 	register struct ctdevice *ctaddr;
1053201Swnj 
1063201Swnj 	if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 ||
10727234Skarels 	    ui->ui_alive == 0)
10827234Skarels 		return (ENODEV);
10927234Skarels 	if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN)
11027234Skarels 		return (EBUSY);
11127234Skarels 	sc->sc_state = CT_OPEN;
11227234Skarels 	ctaddr = (struct ctdevice *)ui->ui_addr;
11327234Skarels 	ctaddr->ctcsr |= INT_ENB_A;
1148566Sroot 	return (0);
1152621Swnj }
1162621Swnj 
ctclose(dev)1173201Swnj ctclose(dev)
1183201Swnj 	dev_t dev;
1192621Swnj {
12027234Skarels 	ct_softc[CTUNIT(dev)].sc_state = 0;
1213201Swnj 	ctintr(dev);
12227234Skarels 	return (0);
1232621Swnj }
1242621Swnj 
ctwrite(dev,uio)1257831Sroot ctwrite(dev, uio)
1263201Swnj 	dev_t dev;
1277831Sroot 	struct uio *uio;
1282621Swnj {
1293201Swnj 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1303201Swnj 	register int c;
13140728Skarels 	int s, error;
1322621Swnj 
13327234Skarels 	while ((c = uwritec(uio)) >= 0) {
13427234Skarels 		s = spl5();
1353201Swnj 		while (sc->sc_oq.c_cc > CATHIWAT)
13640728Skarels 			if (error = tsleep((caddr_t)&sc->sc_oq, PCAT | PCATCH,
13740728Skarels 			    devout, 0))
13840728Skarels 				goto out;
1393201Swnj 		while (putc(c, &sc->sc_oq) < 0)
14040728Skarels 			if (error = tsleep((caddr_t)&lbolt, PCAT | PCATCH,
14140728Skarels 			    ttybuf, 0))
14240728Skarels 				goto out;
14327234Skarels 		if ( ! (sc->sc_state & CT_RUNNING) )
14427234Skarels 			ctintr(dev);
14527234Skarels 		splx(s);
1462621Swnj 	}
14727234Skarels 	return (0);
14840728Skarels out:
14940728Skarels 	splx(s);
15040728Skarels 	return (error);
1512621Swnj }
1522621Swnj 
15327234Skarels /*
15427234Skarels  * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe.
15527234Skarels  * If you use this with a C/A/T you can remove the lines with "APSu5" below.
15627234Skarels  * This is way out of spec for the Autologic APS micro-5 which requires
15727234Skarels  * at least a 40 microsec strobe. We therefore use CSR1 output as the
15827234Skarels  * "strobe". It is set after data is loaded and reset only in the
15927234Skarels  * interrupt routine. Therefore, the "strobe" is high for adequate time.
16027234Skarels  * The constant "ctdelay" determines the "low" time for the strobe
16127234Skarels  * and may have to be larger on a 780. "2" gives about 10us on a 750.
16227234Skarels  */
16327234Skarels int	ctdelay	= 2;	/* here so it's visible & changeable */
16427234Skarels 
ctintr(dev)1653201Swnj ctintr(dev)
1663201Swnj 	dev_t dev;
1672621Swnj {
1682621Swnj 	register int c;
1693201Swnj 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1703201Swnj 	register struct ctdevice *ctaddr =
1713201Swnj 	    (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr;
1722621Swnj 
17327234Skarels 	if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) {
17427234Skarels 		ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B);	/* set in ctprobe */
17527234Skarels 	}
17627234Skarels 	if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) {
1773201Swnj 		if ((c = getc(&sc->sc_oq)) >= 0) {
17827234Skarels 			ctaddr->ctcsr &= ~CSR1;	/* APSu5 - drop strobe */
17927234Skarels 			ctaddr->ctobuf = c;
18027234Skarels 			DELAY(ctdelay);		/* APSu5 - pause a bit */
18127234Skarels 			ctaddr->ctcsr |= CSR1;	/* APSu5 - raise strobe */
18227234Skarels 			sc->sc_state |= CT_RUNNING;
1833201Swnj 			if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT)
18428955Skarels 				wakeup((caddr_t)&sc->sc_oq);
18527234Skarels 		} else if (sc->sc_state == 0) {
1863201Swnj 				ctaddr->ctcsr = 0;
18727234Skarels 		} else
18827234Skarels 			sc->sc_state &= ~CT_RUNNING;
1892621Swnj 	}
1902621Swnj }
1912621Swnj #endif
192