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