|
|
1.1 root 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.5 (Berkeley) 4/3/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 "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 "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: 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.