Commit | Line | Data |
---|---|---|
ac9aa4fd C |
1 | /* vp.c 4.9 81/04/02 */ |
2 | ||
3 | #include "vp.h" | |
4 | #if NVP > 0 | |
5 | /* | |
6 | * Versatec matrix printer/plotter | |
7 | * dma interface driver | |
8 | * | |
9 | * SETUP NOTES: | |
10 | * Set up both print and plot interrupts to go through the same vector | |
11 | * Give the address of the plcsr register in the config specification | |
12 | */ | |
13 | #include "../h/param.h" | |
14 | #include "../h/dir.h" | |
15 | #include "../h/user.h" | |
16 | #include "../h/buf.h" | |
17 | #include "../h/systm.h" | |
18 | #include "../h/map.h" | |
19 | #include "../h/pte.h" | |
20 | #include "../h/ubavar.h" | |
21 | #include "../h/ubareg.h" | |
22 | #include "../h/vcmd.h" | |
23 | ||
24 | unsigned minvpph(); | |
25 | ||
26 | #define VPPRI (PZERO-1) | |
27 | ||
28 | struct vpdevice { | |
29 | short plbcr; | |
30 | short pbxaddr; | |
31 | short prbcr; | |
32 | u_short pbaddr; | |
33 | short plcsr; | |
34 | short plbuf; | |
35 | short prcsr; | |
36 | u_short prbuf; | |
37 | }; | |
38 | ||
39 | #define VP_ERROR 0100000 | |
40 | #define VP_DTCINTR 0040000 | |
41 | #define VP_DMAACT 0020000 | |
42 | #define VP_READY 0000200 | |
43 | #define VP_IENABLE 0000100 | |
44 | #define VP_TERMCOM 0000040 | |
45 | #define VP_FFCOM 0000020 | |
46 | #define VP_EOTCOM 0000010 | |
47 | #define VP_CLRCOM 0000004 | |
48 | #define VP_RESET 0000002 | |
49 | #define VP_SPP 0000001 | |
50 | ||
51 | struct vp_softc { | |
52 | int sc_state; | |
53 | int sc_count; | |
54 | int sc_bufp; | |
55 | struct buf *sc_bp; | |
56 | int sc_ubinfo; | |
57 | } vp_softc[NVP]; | |
58 | ||
59 | /* sc_state bits */ | |
60 | #define VPSC_BUSY 0001000 | |
61 | #define VPSC_MODE 0000700 | |
62 | #define VPSC_SPP 0000400 | |
63 | #define VPSC_PLOT 0000200 | |
64 | #define VPSC_PRINT 0000100 | |
65 | #define VPSC_CMNDS 0000076 | |
66 | #define VPSC_OPEN 0000001 | |
67 | ||
68 | struct uba_device *vpdinfo[NVP]; | |
69 | ||
70 | #define VPUNIT(dev) (minor(dev)) | |
71 | ||
72 | struct buf rvpbuf[NVP]; | |
73 | ||
74 | int vpprobe(), vpattach(); | |
75 | struct uba_device *vpdinfo[NVP]; | |
76 | u_short vpstd[] = { 0777500, 0 }; | |
77 | struct uba_driver vpdriver = | |
78 | { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; | |
79 | ||
80 | vpprobe(reg) | |
81 | caddr_t reg; | |
82 | { | |
83 | register int br, cvec; /* value-result */ | |
84 | register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); | |
85 | ||
86 | vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; | |
87 | vpaddr->pbaddr = 0; | |
88 | vpaddr->pbxaddr = 0; | |
89 | vpaddr->prbcr = 1; | |
90 | DELAY(10000); | |
91 | vpaddr->prcsr = 0; | |
92 | #ifdef ERNIE | |
93 | /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ | |
94 | if (cvec == 0200) { | |
95 | printf("vp reset vec from 200 to 174\n"); | |
96 | cvec = 0174; | |
97 | } | |
98 | #endif | |
99 | } | |
100 | ||
101 | /*ARGSUSED*/ | |
102 | vpattach(ui) | |
103 | struct uba_device *ui; | |
104 | { | |
105 | ||
106 | ui->ui_addr -= 010; | |
107 | ui->ui_physaddr -= 010; | |
108 | } | |
109 | ||
110 | vpopen(dev) | |
111 | dev_t dev; | |
112 | { | |
113 | register struct vp_softc *sc; | |
114 | register struct vpdevice *vpaddr; | |
115 | register struct uba_device *ui; | |
116 | ||
117 | if (VPUNIT(dev) >= NVP || | |
118 | ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || | |
119 | (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { | |
120 | u.u_error = ENXIO; | |
121 | return; | |
122 | } | |
123 | vpaddr = (struct vpdevice *)ui->ui_addr; | |
124 | sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; | |
125 | sc->sc_count = 0; | |
126 | vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; | |
127 | vptimo(dev); | |
128 | while (sc->sc_state & VPSC_CMNDS) { | |
129 | (void) spl4(); | |
130 | if (vpwait(dev)) { | |
131 | vpclose(dev); | |
132 | u.u_error = EIO; | |
133 | return; | |
134 | } | |
135 | vpstart(dev); | |
136 | (void) spl0(); | |
137 | } | |
138 | } | |
139 | ||
140 | vpstrategy(bp) | |
141 | register struct buf *bp; | |
142 | { | |
143 | register int e; | |
144 | register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; | |
145 | register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; | |
146 | register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; | |
147 | ||
148 | (void) spl4(); | |
149 | while (sc->sc_state & VPSC_BUSY) | |
150 | sleep((caddr_t)sc, VPPRI); | |
151 | sc->sc_state |= VPSC_BUSY; | |
152 | sc->sc_bp = bp; | |
153 | sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); | |
154 | if (e = vpwait(bp->b_dev)) | |
155 | goto brkout; | |
156 | sc->sc_count = bp->b_bcount; | |
157 | vpstart(bp->b_dev); | |
158 | while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) | |
159 | sleep((caddr_t)sc, VPPRI); | |
160 | sc->sc_count = 0; | |
161 | if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) | |
162 | sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; | |
163 | (void) spl0(); | |
164 | brkout: | |
165 | ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); | |
166 | sc->sc_state &= ~VPSC_BUSY; | |
167 | sc->sc_bp = 0; | |
168 | iodone(bp); | |
169 | if (e) | |
170 | u.u_error = EIO; | |
171 | wakeup((caddr_t)sc); | |
172 | } | |
173 | ||
174 | int vpblock = 16384; | |
175 | ||
176 | unsigned | |
177 | minvpph(bp) | |
178 | struct buf *bp; | |
179 | { | |
180 | ||
181 | if (bp->b_bcount > vpblock) | |
182 | bp->b_bcount = vpblock; | |
183 | } | |
184 | ||
185 | /*ARGSUSED*/ | |
186 | vpwrite(dev) | |
187 | dev_t dev; | |
188 | { | |
189 | ||
190 | physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); | |
191 | } | |
192 | ||
193 | vpwait(dev) | |
194 | dev_t dev; | |
195 | { | |
196 | register struct vpdevice *vpaddr = | |
197 | (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; | |
198 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
199 | register int e; | |
200 | ||
201 | for (;;) { | |
202 | e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; | |
203 | if (e & (VP_READY|VP_ERROR)) | |
204 | break; | |
205 | sleep((caddr_t)sc, VPPRI); | |
206 | } | |
207 | /* I wish i could tell whether an error indicated an npr timeout */ | |
208 | return (e & VP_ERROR); | |
209 | } | |
210 | ||
211 | vpstart(dev) | |
212 | dev_t; | |
213 | { | |
214 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
215 | register struct vpdevice *vpaddr = | |
216 | (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; | |
217 | short bit; | |
218 | ||
219 | if (sc->sc_count) { | |
220 | vpaddr->pbaddr = sc->sc_ubinfo; | |
221 | vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; | |
222 | if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) | |
223 | vpaddr->prbcr = sc->sc_count; | |
224 | else | |
225 | vpaddr->plbcr = sc->sc_count; | |
226 | return; | |
227 | } | |
228 | for (bit = 1; bit != 0; bit <<= 1) | |
229 | if (sc->sc_state&bit&VPSC_CMNDS) { | |
230 | vpaddr->plcsr |= bit; | |
231 | sc->sc_state &= ~bit; | |
232 | return; | |
233 | } | |
234 | } | |
235 | ||
236 | /*ARGSUSED*/ | |
237 | vpioctl(dev, cmd, addr, flag) | |
238 | dev_t dev; | |
239 | int cmd; | |
240 | register caddr_t addr; | |
241 | int flag; | |
242 | { | |
243 | register int m; | |
244 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
245 | register struct vpdevice *vpaddr = | |
246 | (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; | |
247 | ||
248 | switch (cmd) { | |
249 | ||
250 | case VGETSTATE: | |
251 | (void) suword(addr, sc->sc_state); | |
252 | return; | |
253 | ||
254 | case VSETSTATE: | |
255 | m = fuword(addr); | |
256 | if (m == -1) { | |
257 | u.u_error = EFAULT; | |
258 | return; | |
259 | } | |
260 | sc->sc_state = | |
261 | (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); | |
262 | break; | |
263 | ||
264 | default: | |
265 | u.u_error = ENOTTY; | |
266 | return; | |
267 | } | |
268 | (void) spl4(); | |
269 | (void) vpwait(dev); | |
270 | if (sc->sc_state&VPSC_SPP) | |
271 | vpaddr->plcsr |= VP_SPP; | |
272 | else | |
273 | vpaddr->plcsr &= ~VP_SPP; | |
274 | sc->sc_count = 0; | |
275 | while (sc->sc_state & VPSC_CMNDS) { | |
276 | (void) vpwait(dev); | |
277 | vpstart(dev); | |
278 | } | |
279 | (void) spl0(); | |
280 | } | |
281 | ||
282 | vptimo(dev) | |
283 | dev_t dev; | |
284 | { | |
285 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
286 | ||
287 | if (sc->sc_state&VPSC_OPEN) | |
288 | timeout(vptimo, (caddr_t)dev, hz/10); | |
289 | vpintr(dev); | |
290 | } | |
291 | ||
292 | /*ARGSUSED*/ | |
293 | vpintr(dev) | |
294 | dev_t dev; | |
295 | { | |
296 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
297 | ||
298 | wakeup((caddr_t)sc); | |
299 | } | |
300 | ||
301 | vpclose(dev) | |
302 | dev_t dev; | |
303 | { | |
304 | register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; | |
305 | register struct vpdevice *vpaddr = | |
306 | (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; | |
307 | ||
308 | sc->sc_state = 0; | |
309 | sc->sc_count = 0; | |
310 | vpaddr->plcsr = 0; | |
311 | } | |
312 | ||
313 | vpreset(uban) | |
314 | int uban; | |
315 | { | |
316 | register int vp11; | |
317 | register struct uba_device *ui; | |
318 | register struct vp_softc *sc = vp_softc; | |
319 | register struct vpdevice *vpaddr; | |
320 | ||
321 | for (vp11 = 0; vp11 < NVP; vp11++, sc++) { | |
322 | if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || | |
323 | ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) | |
324 | continue; | |
325 | printf(" vp%d", vp11); | |
326 | vpaddr = (struct vpdevice *)ui->ui_addr; | |
327 | vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; | |
328 | if ((sc->sc_state & VPSC_BUSY) == 0) | |
329 | continue; | |
330 | if (sc->sc_ubinfo) { | |
331 | printf("<%d>", (sc->sc_ubinfo>>28)&0xf); | |
332 | ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); | |
333 | } | |
334 | sc->sc_count = sc->sc_bp->b_bcount; | |
335 | vpstart(sc->sc_bp->b_dev); | |
336 | } | |
337 | } | |
338 | #endif |