xref: /csrg-svn/sys/vax/uba/ct.c (revision 29208)
123319Smckusick /*
2*29208Smckusick  * 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*29208Smckusick  *	@(#)ct.c	7.1 (Berkeley) 06/05/86
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  */
149771Ssam #include "../machine/pte.h"
152621Swnj 
1617073Sbloom #include "param.h"
1717073Sbloom #include "systm.h"
1828330Smckusick #include "ioctl.h"
1917073Sbloom #include "tty.h"
2017073Sbloom #include "map.h"
2117073Sbloom #include "buf.h"
2217073Sbloom #include "conf.h"
2317073Sbloom #include "dir.h"
2417073Sbloom #include "user.h"
2527234Skarels #include "kernel.h"
262621Swnj 
2717073Sbloom #include "ubareg.h"
2817073Sbloom #include "ubavar.h"
298472Sroot 
302621Swnj #define	PCAT	(PZERO+9)
312621Swnj #define	CATHIWAT	100
322621Swnj #define	CATLOWAT	30
332621Swnj 
3427234Skarels #define	REQUEST_B	0x8000
3527234Skarels #define REQUEST_A	0x80
3627234Skarels #define	INT_ENB_A	0x40
3727234Skarels #define	INT_ENB_B	0x20
3827234Skarels #define	CSR1		0x2
3927234Skarels #define	CSR0		0x1
4027234Skarels 
413201Swnj struct ct_softc {
4227234Skarels 	int	sc_state;
433201Swnj 	struct	clist sc_oq;
443201Swnj } ct_softc[NCT];
452621Swnj 
4627234Skarels #define	CT_OPEN		0x1
4727234Skarels #define	CT_RUNNING	0x2
4827234Skarels 
493201Swnj struct ctdevice {
5027234Skarels 	u_short	ctcsr;
5127234Skarels 	u_short	ctobuf;
5227234Skarels 	u_short ctibuf;
532621Swnj };
542621Swnj 
553201Swnj int	ctprobe(), ctattach(), ctintr();
563201Swnj struct	uba_device *ctdinfo[NCT];
5727234Skarels u_short	ctstd[] = { 0167770, 0 };
583201Swnj struct	uba_driver ctdriver =
593201Swnj     { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo };
602621Swnj 
613217Swnj #define	CTUNIT(dev)	(minor(dev))
623217Swnj 
6327234Skarels int	ct_init	= 0;	/* set to CSR1 for testing loopback on controller */
6427234Skarels 
653201Swnj ctprobe(reg)
663201Swnj 	caddr_t reg;
673201Swnj {
683936Sbugs 	register int br, cvec;		/* value-result */
693201Swnj 	register struct ctdevice *ctaddr = (struct ctdevice *)reg;
703201Swnj 
714932Swnj #ifdef lint
724932Swnj 	br = 0; cvec = br; br = cvec;
734932Swnj 	ctintr(0);
744932Swnj #endif
7527234Skarels 	/*
7627234Skarels 	 * There is no way to make a DR11c interrupt without some
7727234Skarels 	 * external support. We can't always trust that the typesetter
7827234Skarels 	 * will be online and ready so we've made other provisions.
7927234Skarels 	 * This probe assumes setting the B Int Enb will generate
8027234Skarels 	 * an interrupt. To do this, we set CSR0 and loop this back
8127234Skarels 	 * to REQUEST_B in the second plug on the controller.
8227234Skarels 	 * Then, we reset the vector to be that for the "real" device.
8327234Skarels 	 */
8427234Skarels 	ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */
8527234Skarels 	DELAY(1000);
8627234Skarels 	ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */
8727234Skarels 	if (cvec & 04) {
8827234Skarels 		printf("ct: resetting vector %o to %o\n", cvec, cvec&0773);
8927234Skarels 		cvec &= 0773;
9027234Skarels 	}
917409Skre 	return (sizeof (struct ctdevice));
923201Swnj }
933201Swnj 
943217Swnj /*ARGSUSED*/
953217Swnj ctattach(ui)
9628955Skarels 	struct uba_device *ui;
973217Swnj {
983217Swnj }
993217Swnj 
1002621Swnj ctopen(dev)
1013201Swnj 	dev_t dev;
1022621Swnj {
1033201Swnj 	register struct ct_softc *sc;
1043201Swnj 	register struct uba_device *ui;
1053201Swnj 	register struct ctdevice *ctaddr;
1063201Swnj 
1073201Swnj 	if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 ||
10827234Skarels 	    ui->ui_alive == 0)
10927234Skarels 		return (ENODEV);
11027234Skarels 	if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN)
11127234Skarels 		return (EBUSY);
11227234Skarels 	sc->sc_state = CT_OPEN;
11327234Skarels 	ctaddr = (struct ctdevice *)ui->ui_addr;
11427234Skarels 	ctaddr->ctcsr |= INT_ENB_A;
1158566Sroot 	return (0);
1162621Swnj }
1172621Swnj 
1183201Swnj ctclose(dev)
1193201Swnj 	dev_t dev;
1202621Swnj {
12127234Skarels 	ct_softc[CTUNIT(dev)].sc_state = 0;
1223201Swnj 	ctintr(dev);
12327234Skarels 	return (0);
1242621Swnj }
1252621Swnj 
1267831Sroot ctwrite(dev, uio)
1273201Swnj 	dev_t dev;
1287831Sroot 	struct uio *uio;
1292621Swnj {
1303201Swnj 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1313201Swnj 	register int c;
13227234Skarels 	int s;
1332621Swnj 
13427234Skarels 	while ((c = uwritec(uio)) >= 0) {
13527234Skarels 		s = spl5();
1363201Swnj 		while (sc->sc_oq.c_cc > CATHIWAT)
1373201Swnj 			sleep((caddr_t)&sc->sc_oq, PCAT);
1383201Swnj 		while (putc(c, &sc->sc_oq) < 0)
1392621Swnj 			sleep((caddr_t)&lbolt, PCAT);
14027234Skarels 		if ( ! (sc->sc_state & CT_RUNNING) )
14127234Skarels 			ctintr(dev);
14227234Skarels 		splx(s);
1432621Swnj 	}
14427234Skarels 	return (0);
1452621Swnj }
1462621Swnj 
14727234Skarels /*
14827234Skarels  * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe.
14927234Skarels  * If you use this with a C/A/T you can remove the lines with "APSu5" below.
15027234Skarels  * This is way out of spec for the Autologic APS micro-5 which requires
15127234Skarels  * at least a 40 microsec strobe. We therefore use CSR1 output as the
15227234Skarels  * "strobe". It is set after data is loaded and reset only in the
15327234Skarels  * interrupt routine. Therefore, the "strobe" is high for adequate time.
15427234Skarels  * The constant "ctdelay" determines the "low" time for the strobe
15527234Skarels  * and may have to be larger on a 780. "2" gives about 10us on a 750.
15627234Skarels  */
15727234Skarels int	ctdelay	= 2;	/* here so it's visible & changeable */
15827234Skarels 
1593201Swnj ctintr(dev)
1603201Swnj 	dev_t dev;
1612621Swnj {
1622621Swnj 	register int c;
1633201Swnj 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
1643201Swnj 	register struct ctdevice *ctaddr =
1653201Swnj 	    (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr;
1662621Swnj 
16727234Skarels 	if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) {
16827234Skarels 		ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B);	/* set in ctprobe */
16927234Skarels 	}
17027234Skarels 	if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) {
1713201Swnj 		if ((c = getc(&sc->sc_oq)) >= 0) {
17227234Skarels 			ctaddr->ctcsr &= ~CSR1;	/* APSu5 - drop strobe */
17327234Skarels 			ctaddr->ctobuf = c;
17427234Skarels 			DELAY(ctdelay);		/* APSu5 - pause a bit */
17527234Skarels 			ctaddr->ctcsr |= CSR1;	/* APSu5 - raise strobe */
17627234Skarels 			sc->sc_state |= CT_RUNNING;
1773201Swnj 			if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT)
17828955Skarels 				wakeup((caddr_t)&sc->sc_oq);
17927234Skarels 		} else if (sc->sc_state == 0) {
1803201Swnj 				ctaddr->ctcsr = 0;
18127234Skarels 		} else
18227234Skarels 			sc->sc_state &= ~CT_RUNNING;
1832621Swnj 	}
1842621Swnj }
1852621Swnj #endif
186