Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)ct.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
99aa0ab4 | 8 | |
a53c8506 | 9 | #include "ct.h" |
99aa0ab4 BJ |
10 | #if NCT > 0 |
11 | /* | |
ba80d2df | 12 | * GP DR11C driver used for C/A/T or Autologic APS micro-5 |
99aa0ab4 | 13 | */ |
961945a8 | 14 | #include "../machine/pte.h" |
99aa0ab4 | 15 | |
ff360633 JB |
16 | #include "param.h" |
17 | #include "systm.h" | |
f88025a6 | 18 | #include "ioctl.h" |
ff360633 JB |
19 | #include "tty.h" |
20 | #include "map.h" | |
21 | #include "buf.h" | |
22 | #include "conf.h" | |
23 | #include "dir.h" | |
24 | #include "user.h" | |
ba80d2df | 25 | #include "kernel.h" |
99aa0ab4 | 26 | |
ff360633 JB |
27 | #include "ubareg.h" |
28 | #include "ubavar.h" | |
896962b1 | 29 | |
99aa0ab4 BJ |
30 | #define PCAT (PZERO+9) |
31 | #define CATHIWAT 100 | |
32 | #define CATLOWAT 30 | |
33 | ||
ba80d2df MK |
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 | ||
a53c8506 | 41 | struct ct_softc { |
ba80d2df | 42 | int sc_state; |
a53c8506 BJ |
43 | struct clist sc_oq; |
44 | } ct_softc[NCT]; | |
99aa0ab4 | 45 | |
ba80d2df MK |
46 | #define CT_OPEN 0x1 |
47 | #define CT_RUNNING 0x2 | |
48 | ||
a53c8506 | 49 | struct ctdevice { |
ba80d2df MK |
50 | u_short ctcsr; |
51 | u_short ctobuf; | |
52 | u_short ctibuf; | |
99aa0ab4 BJ |
53 | }; |
54 | ||
a53c8506 BJ |
55 | int ctprobe(), ctattach(), ctintr(); |
56 | struct uba_device *ctdinfo[NCT]; | |
ba80d2df | 57 | u_short ctstd[] = { 0167770, 0 }; |
a53c8506 BJ |
58 | struct uba_driver ctdriver = |
59 | { ctprobe, 0, ctattach, 0, ctstd, "ct", ctdinfo }; | |
60 | ||
042f22be BJ |
61 | #define CTUNIT(dev) (minor(dev)) |
62 | ||
ba80d2df MK |
63 | int ct_init = 0; /* set to CSR1 for testing loopback on controller */ |
64 | ||
a53c8506 BJ |
65 | ctprobe(reg) |
66 | caddr_t reg; | |
67 | { | |
2b50de22 | 68 | register int br, cvec; /* value-result */ |
a53c8506 BJ |
69 | register struct ctdevice *ctaddr = (struct ctdevice *)reg; |
70 | ||
89b8a44c BJ |
71 | #ifdef lint |
72 | br = 0; cvec = br; br = cvec; | |
73 | ctintr(0); | |
74 | #endif | |
ba80d2df MK |
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 | } | |
9c0adba0 | 91 | return (sizeof (struct ctdevice)); |
a53c8506 | 92 | } |
99aa0ab4 | 93 | |
042f22be BJ |
94 | /*ARGSUSED*/ |
95 | ctattach(ui) | |
58bca61d | 96 | struct uba_device *ui; |
042f22be | 97 | { |
042f22be BJ |
98 | } |
99 | ||
99aa0ab4 | 100 | ctopen(dev) |
a53c8506 | 101 | dev_t dev; |
99aa0ab4 | 102 | { |
a53c8506 BJ |
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 || | |
ba80d2df MK |
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; | |
7da157da | 115 | return (0); |
99aa0ab4 BJ |
116 | } |
117 | ||
a53c8506 BJ |
118 | ctclose(dev) |
119 | dev_t dev; | |
99aa0ab4 | 120 | { |
ba80d2df | 121 | ct_softc[CTUNIT(dev)].sc_state = 0; |
a53c8506 | 122 | ctintr(dev); |
ba80d2df | 123 | return (0); |
99aa0ab4 BJ |
124 | } |
125 | ||
406ddcbe | 126 | ctwrite(dev, uio) |
a53c8506 | 127 | dev_t dev; |
406ddcbe | 128 | struct uio *uio; |
99aa0ab4 | 129 | { |
a53c8506 BJ |
130 | register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; |
131 | register int c; | |
ba80d2df | 132 | int s; |
99aa0ab4 | 133 | |
ba80d2df MK |
134 | while ((c = uwritec(uio)) >= 0) { |
135 | s = spl5(); | |
a53c8506 BJ |
136 | while (sc->sc_oq.c_cc > CATHIWAT) |
137 | sleep((caddr_t)&sc->sc_oq, PCAT); | |
138 | while (putc(c, &sc->sc_oq) < 0) | |
99aa0ab4 | 139 | sleep((caddr_t)&lbolt, PCAT); |
ba80d2df MK |
140 | if ( ! (sc->sc_state & CT_RUNNING) ) |
141 | ctintr(dev); | |
142 | splx(s); | |
99aa0ab4 | 143 | } |
ba80d2df | 144 | return (0); |
99aa0ab4 BJ |
145 | } |
146 | ||
ba80d2df MK |
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 | ||
a53c8506 BJ |
159 | ctintr(dev) |
160 | dev_t dev; | |
99aa0ab4 BJ |
161 | { |
162 | register int c; | |
a53c8506 BJ |
163 | register struct ct_softc *sc = &ct_softc[CTUNIT(dev)]; |
164 | register struct ctdevice *ctaddr = | |
165 | (struct ctdevice *)ctdinfo[CTUNIT(dev)]->ui_addr; | |
99aa0ab4 | 166 | |
ba80d2df MK |
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)) { | |
a53c8506 | 171 | if ((c = getc(&sc->sc_oq)) >= 0) { |
ba80d2df MK |
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; | |
a53c8506 | 177 | if (sc->sc_oq.c_cc==0 || sc->sc_oq.c_cc==CATLOWAT) |
58bca61d | 178 | wakeup((caddr_t)&sc->sc_oq); |
ba80d2df | 179 | } else if (sc->sc_state == 0) { |
a53c8506 | 180 | ctaddr->ctcsr = 0; |
ba80d2df MK |
181 | } else |
182 | sc->sc_state &= ~CT_RUNNING; | |
99aa0ab4 | 183 | } |
99aa0ab4 BJ |
184 | } |
185 | #endif |