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