xref: /original-bsd/sys/vax/uba/ct.c (revision 4e9331e4)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)ct.c	7.2 (Berkeley) 04/25/89
7  */
8 
9 #include "ct.h"
10 #if NCT > 0
11 /*
12  * GP DR11C driver used for C/A/T or Autologic APS micro-5
13  */
14 #include "machine/pte.h"
15 
16 #include "param.h"
17 #include "systm.h"
18 #include "ioctl.h"
19 #include "tty.h"
20 #include "map.h"
21 #include "buf.h"
22 #include "conf.h"
23 #include "dir.h"
24 #include "user.h"
25 #include "kernel.h"
26 
27 #include "ubareg.h"
28 #include "ubavar.h"
29 
30 #define	PCAT	(PZERO+9)
31 #define	CATHIWAT	100
32 #define	CATLOWAT	30
33 
34 #define	REQUEST_B	0x8000
35 #define REQUEST_A	0x80
36 #define	INT_ENB_A	0x40
37 #define	INT_ENB_B	0x20
38 #define	CSR1		0x2
39 #define	CSR0		0x1
40 
41 struct ct_softc {
42 	int	sc_state;
43 	struct	clist sc_oq;
44 } ct_softc[NCT];
45 
46 #define	CT_OPEN		0x1
47 #define	CT_RUNNING	0x2
48 
49 struct ctdevice {
50 	u_short	ctcsr;
51 	u_short	ctobuf;
52 	u_short ctibuf;
53 };
54 
55 int	ctprobe(), ctattach(), ctintr();
56 struct	uba_device *ctdinfo[NCT];
57 u_short	ctstd[] = { 0167770, 0 };
58 struct	uba_driver ctdriver =
59     { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo };
60 
61 #define	CTUNIT(dev)	(minor(dev))
62 
63 int	ct_init	= 0;	/* set to CSR1 for testing loopback on controller */
64 
65 ctprobe(reg)
66 	caddr_t reg;
67 {
68 	register int br, cvec;		/* value-result */
69 	register struct ctdevice *ctaddr = (struct ctdevice *)reg;
70 
71 #ifdef lint
72 	br = 0; cvec = br; br = cvec;
73 	ctintr(0);
74 #endif
75 	/*
76 	 * There is no way to make a DR11c interrupt without some
77 	 * external support. We can't always trust that the typesetter
78 	 * will be online and ready so we've made other provisions.
79 	 * This probe assumes setting the B Int Enb will generate
80 	 * an interrupt. To do this, we set CSR0 and loop this back
81 	 * to REQUEST_B in the second plug on the controller.
82 	 * Then, we reset the vector to be that for the "real" device.
83 	 */
84 	ctaddr->ctcsr = INT_ENB_B | CSR0; /* Assume hardware loopback! */
85 	DELAY(1000);
86 	ctaddr->ctcsr = ct_init; /* should be CSR1 for loopback testing */
87 	if (cvec & 04) {
88 		printf("ct: resetting vector %o to %o\n", cvec, cvec&0773);
89 		cvec &= 0773;
90 	}
91 	return (sizeof (struct ctdevice));
92 }
93 
94 /*ARGSUSED*/
95 ctattach(ui)
96 	struct uba_device *ui;
97 {
98 }
99 
100 ctopen(dev)
101 	dev_t dev;
102 {
103 	register struct ct_softc *sc;
104 	register struct uba_device *ui;
105 	register struct ctdevice *ctaddr;
106 
107 	if (CTUNIT(dev) >= NCT || (ui = ctdinfo[CTUNIT(dev)]) == 0 ||
108 	    ui->ui_alive == 0)
109 		return (ENODEV);
110 	if ((sc = &ct_softc[CTUNIT(dev)])->sc_state&CT_OPEN)
111 		return (EBUSY);
112 	sc->sc_state = CT_OPEN;
113 	ctaddr = (struct ctdevice *)ui->ui_addr;
114 	ctaddr->ctcsr |= INT_ENB_A;
115 	return (0);
116 }
117 
118 ctclose(dev)
119 	dev_t dev;
120 {
121 	ct_softc[CTUNIT(dev)].sc_state = 0;
122 	ctintr(dev);
123 	return (0);
124 }
125 
126 ctwrite(dev, uio)
127 	dev_t dev;
128 	struct uio *uio;
129 {
130 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
131 	register int c;
132 	int s;
133 
134 	while ((c = uwritec(uio)) >= 0) {
135 		s = spl5();
136 		while (sc->sc_oq.c_cc > CATHIWAT)
137 			sleep((caddr_t)&sc->sc_oq, PCAT);
138 		while (putc(c, &sc->sc_oq) < 0)
139 			sleep((caddr_t)&lbolt, PCAT);
140 		if ( ! (sc->sc_state & CT_RUNNING) )
141 			ctintr(dev);
142 		splx(s);
143 	}
144 	return (0);
145 }
146 
147 /*
148  * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe.
149  * If you use this with a C/A/T you can remove the lines with "APSu5" below.
150  * This is way out of spec for the Autologic APS micro-5 which requires
151  * at least a 40 microsec strobe. We therefore use CSR1 output as the
152  * "strobe". It is set after data is loaded and reset only in the
153  * interrupt routine. Therefore, the "strobe" is high for adequate time.
154  * The constant "ctdelay" determines the "low" time for the strobe
155  * and may have to be larger on a 780. "2" gives about 10us on a 750.
156  */
157 int	ctdelay	= 2;	/* here so it's visible & changeable */
158 
159 ctintr(dev)
160 	dev_t dev;
161 {
162 	register int c;
163 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
164 	register struct ctdevice *ctaddr =
165 	    (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr;
166 
167 	if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) {
168 		ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B);	/* set in ctprobe */
169 	}
170 	if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) {
171 		if ((c = getc(&sc->sc_oq)) >= 0) {
172 			ctaddr->ctcsr &= ~CSR1;	/* APSu5 - drop strobe */
173 			ctaddr->ctobuf = c;
174 			DELAY(ctdelay);		/* APSu5 - pause a bit */
175 			ctaddr->ctcsr |= CSR1;	/* APSu5 - raise strobe */
176 			sc->sc_state |= CT_RUNNING;
177 			if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT)
178 				wakeup((caddr_t)&sc->sc_oq);
179 		} else if (sc->sc_state == 0) {
180 				ctaddr->ctcsr = 0;
181 		} else
182 			sc->sc_state &= ~CT_RUNNING;
183 	}
184 }
185 #endif
186