xref: /csrg-svn/sys/vax/uba/ct.c (revision 27234)
1 /*
2  * Copyright (c) 1982 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	6.4 (Berkeley) 04/21/86
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 "tty.h"
19 #include "map.h"
20 #include "buf.h"
21 #include "conf.h"
22 #include "dir.h"
23 #include "user.h"
24 #include "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 	register 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;
132 
133 	while ((c = uwritec(uio)) >= 0) {
134 		s = spl5();
135 		while (sc->sc_oq.c_cc > CATHIWAT)
136 			sleep((caddr_t)&sc->sc_oq, PCAT);
137 		while (putc(c, &sc->sc_oq) < 0)
138 			sleep((caddr_t)&lbolt, PCAT);
139 		if ( ! (sc->sc_state & CT_RUNNING) )
140 			ctintr(dev);
141 		splx(s);
142 	}
143 	return (0);
144 }
145 
146 /*
147  * The C/A/T is usually wired to accept data on the .5us DATA_AVAIL strobe.
148  * If you use this with a C/A/T you can remove the lines with "APSu5" below.
149  * This is way out of spec for the Autologic APS micro-5 which requires
150  * at least a 40 microsec strobe. We therefore use CSR1 output as the
151  * "strobe". It is set after data is loaded and reset only in the
152  * interrupt routine. Therefore, the "strobe" is high for adequate time.
153  * The constant "ctdelay" determines the "low" time for the strobe
154  * and may have to be larger on a 780. "2" gives about 10us on a 750.
155  */
156 int	ctdelay	= 2;	/* here so it's visible & changeable */
157 
158 ctintr(dev)
159 	dev_t dev;
160 {
161 	register int c;
162 	register struct ct_softc *sc = &ct_softc[CTUNIT(dev)];
163 	register struct ctdevice *ctaddr =
164 	    (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr;
165 
166 	if ((ctaddr->ctcsr&(INT_ENB_B|REQUEST_B)) == (INT_ENB_B|REQUEST_B)) {
167 		ctaddr->ctcsr &= ~(CSR0 | INT_ENB_B);	/* set in ctprobe */
168 	}
169 	if ((ctaddr->ctcsr&(INT_ENB_A|REQUEST_A)) == (INT_ENB_A|REQUEST_A)) {
170 		if ((c = getc(&sc->sc_oq)) >= 0) {
171 			ctaddr->ctcsr &= ~CSR1;	/* APSu5 - drop strobe */
172 			ctaddr->ctobuf = c;
173 			DELAY(ctdelay);		/* APSu5 - pause a bit */
174 			ctaddr->ctcsr |= CSR1;	/* APSu5 - raise strobe */
175 			sc->sc_state |= CT_RUNNING;
176 			if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT)
177 				wakeup(&sc->sc_oq);
178 		} else if (sc->sc_state == 0) {
179 				ctaddr->ctcsr = 0;
180 		} else
181 			sc->sc_state &= ~CT_RUNNING;
182 	}
183 }
184 #endif
185