BSD 4_1_snap development
[unix-history] / sys / dev / vp.c
CommitLineData
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
24unsigned minvpph();
25
26#define VPPRI (PZERO-1)
27
28struct 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
51struct 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
68struct uba_device *vpdinfo[NVP];
69
70#define VPUNIT(dev) (minor(dev))
71
72struct buf rvpbuf[NVP];
73
74int vpprobe(), vpattach();
75struct uba_device *vpdinfo[NVP];
76u_short vpstd[] = { 0777500, 0 };
77struct uba_driver vpdriver =
78 { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
79
80vpprobe(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*/
102vpattach(ui)
103 struct uba_device *ui;
104{
105
106 ui->ui_addr -= 010;
107 ui->ui_physaddr -= 010;
108}
109
110vpopen(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
140vpstrategy(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();
164brkout:
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
174int vpblock = 16384;
175
176unsigned
177minvpph(bp)
178 struct buf *bp;
179{
180
181 if (bp->b_bcount > vpblock)
182 bp->b_bcount = vpblock;
183}
184
185/*ARGSUSED*/
186vpwrite(dev)
187 dev_t dev;
188{
189
190 physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph);
191}
192
193vpwait(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
211vpstart(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*/
237vpioctl(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
282vptimo(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*/
293vpintr(dev)
294 dev_t dev;
295{
296 register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
297
298 wakeup((caddr_t)sc);
299}
300
301vpclose(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
313vpreset(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