VOID=>void
[unix-history] / usr / src / sys / vax / uba / va.c
CommitLineData
81263dba 1/* va.c 3.2 %H% */
20cc8b5b
BJ
2
3#ifdef ERNIE
4#include "../h/param.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/buf.h"
8#include "../h/systm.h"
9#include "../h/map.h"
10#include "../h/pte.h"
11#include "../h/uba.h"
12#include "../h/vcmd.h"
13
14/*
15 * Benson-Varian matrix printer/plotter. Device "va", for "varian".
16 * dma interface driver
17 */
18int vabdp = 1; /* Used with ubasetup. */
19
20unsigned minvaph(); /* Maximum amount transferred by physio. */
21
22#define VAPRI (PZERO-1)
23
24struct varegs { /* Unibus registers provided by va. */
25 unsigned short vabufaddr; /* DMA buffer address. */
26 short vawcount; /* Negative of number of 16-bit
27 words to transfer by DMA. */
28 union {
29 short vacsrword; /* csr addressed as a word (for R). */
30 struct {
31 char Vacsrlo;
32 char Vacsrhi; /* High byte (command bytes go here). */
33 } vacsrbytes; /* csr addressed as bytes (for W). */
34 } vacsr; /* Control/Status Register (csr). */
35 short vadata;
36};
37
38#define vacsrhi vacsr.vacsrbytes.Vacsrhi
39#define vacsrlo vacsr.vacsrbytes.Vacsrlo
40#define VAADDR ((struct varegs *)(UBA0_DEV + 0164000))
41
42/* vacsr.vacsrword bits: */
43#define ERROR 0100000 /* R Some error has occurred */
44#define NPRTIMO 01000 /* R DMA timeout error */
45#define NOTREADY 0400 /* R Something besides NPRTIMO */
46#define DONE 0200 /* R */
47#define IENABLE 0100 /* R/W Interrupt enable */
48#define SUPPLIESLOW 04 /* R */
49#define BOTOFFORM 02 /* R */
50#define BYTEREVERSE 01 /* R/W Reverse byte order in words */
51
52/* Command bytes sent to vacsrhi */
53#define VAPLOT 0340
54#define VAPRINT 0100
55#define VAPRINTPLOT 0160
56#define VAAUTOSTEP 0244
57/* The following commands are not used in this driver: */
58#define VANOAUTOSTEP 0045
59#define VAFORMFEED 0263
60#define VASLEW 0265
61#define VASTEP 0064
62
63struct {
64 char va_is_open;
65 char va_busy;
66 int va_state; /* State: bits are commands in vcmd.h. */
67 int va_wcount;
68 int va_bufp;
69} vainfo;
70int va_ubinfo;
71
72struct buf rvabuf; /* Used by physio for a buffer. */
73
74vaopen()
75{
76
77 if (vainfo.va_is_open) { /* Can't open if it's already open. */
78 u.u_error = ENXIO;
79 return;
80 }
81 vainfo.va_is_open = 1; /* NOW it's open! */
82 VAADDR->vawcount = 0; /* Clear residual errors */
83 vainfo.va_wcount = 0; /* No DMA to do now. */
84 vainfo.va_state = 0;
85 VAADDR->vacsrlo = IENABLE;
86 /* Enable interrupts. */
87 vatimo();
88
89 vacmd(VPRINT); /* Start in print mode. */
90 if (u.u_error)
91 vaclose();
92}
93
94vastrategy(bp)
95 register struct buf *bp;
96{
97 register int e;
98
81263dba 99 (void) spl4();
20cc8b5b
BJ
100 while (vainfo.va_busy) /* Wait till not busy. */
101 sleep((caddr_t)&vainfo, VAPRI);
102 vainfo.va_busy = 1; /* Grab it. */
81263dba 103 (void) spl0();
20cc8b5b
BJ
104
105 va_ubinfo = ubasetup(bp, vabdp); /* Set up uba mapper. */
106 vainfo.va_bufp = va_ubinfo & 0x3ffff;
107
81263dba 108 (void) spl4();
20cc8b5b
BJ
109 if (e = vaerror(DONE))
110 goto brkout;
111 vainfo.va_wcount = -(bp->b_bcount/2);
112 /* va uses a word count,
113 so user had better supply an even number of bytes. */
114 vastart();
115 e = vaerror(DONE); /* Wait for DMA to complete. */
116 vainfo.va_wcount = 0; /* Reset state info. */
117 vainfo.va_bufp = 0;
118
119 /* After printing a line of characters, VPRINTPLOT mode essentially
120 reverts to VPLOT mode, plotting things until a new mode is set.
121 This change is indicated by sending a VAAUTOSTEP command to
122 the va. We also change va_state to reflect this effective
123 mode change.
124 */
125 if (vainfo.va_state & VPRINTPLOT) {
126 vainfo.va_state = (vainfo.va_state & ~VPRINTPLOT) | VPLOT;
127 VAADDR->vacsrhi = VAAUTOSTEP;
128 e |= vaerror(DONE);
129 }
81263dba 130 (void) spl0();
20cc8b5b
BJ
131brkout:
132 ubafree(va_ubinfo), va_ubinfo = 0;
133 vainfo.va_busy = 0;
134 iodone(bp);
135 if (e)
136 u.u_error = EIO;
137 wakeup((caddr_t)&vainfo);
138}
139
140int vablock = 16384;
141
142unsigned
143minvaph(bp)
144struct buf *bp;
145{
146 if (bp->b_bcount > vablock)
147 bp->b_bcount = vablock;
148}
149
150/*ARGSUSED*/
151vawrite(dev)
152{
153 physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
154}
155
156/*
157 * Vaerror waits until bit or ERROR gets set, then returns non-zero if
158 * if it was ERROR that was set.
159 */
160vaerror(bit)
161{
162 register int e;
163
164 while ((e = VAADDR->vacsr.vacsrword & (bit|ERROR)) == 0)
165 sleep((caddr_t)&vainfo, VAPRI);
166 return (e & ERROR);
167}
168
169/* vastart starts up the DMA by setting the buffer pointer and the word count. */
170vastart()
171{
172 if (vainfo.va_wcount) {
173 VAADDR->vabufaddr = vainfo.va_bufp;
174 VAADDR->vawcount = vainfo.va_wcount;
175 return;
176 }
177}
178
179/*ARGSUSED*/
180vaioctl(dev, cmd, addr, flag)
181 register caddr_t addr;
182{
183 register int vcmd;
184
185 switch (cmd) {
186
187 case VGETSTATE:
81263dba 188 (void) suword(addr, vainfo.va_state);
20cc8b5b
BJ
189 return;
190
191 case VSETSTATE:
192 vcmd = fuword(addr);
193 if (vcmd == -1) {
194 u.u_error = EFAULT;
195 return;
196 }
197 vacmd(vcmd);
198 return;
199
200 default:
201 u.u_error = ENOTTY; /* Not a legal ioctl cmd. */
202 return;
203 }
204}
205
206/* vacmd sends a command code to the va, and waits for it to complete.
207 If an error occurs, u.u_error is set to EIO.
208 vacmd also updates vainfo.va_state.
209 */
210
211vacmd(vcmd)
212{
81263dba
BJ
213 (void) spl4();
214 (void) vaerror(DONE); /* Wait for va to be ready. */
20cc8b5b
BJ
215 switch (vcmd) {
216
217 case VPLOT:
218 /* Must turn on plot AND autostep modes. */
219 VAADDR->vacsrhi = VAPLOT;
220 if (vaerror(DONE))
221 u.u_error = EIO;
222 VAADDR->vacsrhi = VAAUTOSTEP;
223 break;
224
225 case VPRINT:
226 VAADDR->vacsrhi = VAPRINT;
227 break;
228
229 case VPRINTPLOT:
230 VAADDR->vacsrhi = VAPRINTPLOT;
231 break;
232 }
233 vainfo.va_state =
234 (vainfo.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;
235
236 if (vaerror(DONE)) /* Wait for command to complete. */
237 u.u_error = EIO;
81263dba 238 (void) spl0();
20cc8b5b
BJ
239}
240
241vatimo()
242{
243 if (vainfo.va_is_open)
244 timeout(vatimo, (caddr_t)0, HZ/10);
245 vaintr(0);
246}
247
248/*ARGSUSED*/
249vaintr(dev)
250{
251 wakeup((caddr_t)&vainfo);
252}
253
254vaclose()
255{
256
257 vainfo.va_is_open = 0;
258 vainfo.va_busy = 0;
259 vainfo.va_state = 0;
260 vainfo.va_wcount = 0;
261 vainfo.va_bufp = 0;
262 VAADDR->vacsrlo = 0;
263}
264#endif