BSD 4_2 release
[unix-history] / usr / src / sys / vax / flp.c
CommitLineData
61c578c4
C
1/* flp.c 6.1 83/07/29 */
2
3#if VAX780
4#include "../h/param.h"
5#include "../h/systm.h"
6#include "../h/conf.h"
7#include "../h/dir.h"
8#include "../h/user.h"
9#include "../h/buf.h"
10#include "../h/uio.h"
11
12#include "../vax/cons.h"
13#include "../vax/cpu.h"
14#include "../vax/flp.h"
15#include "../vax/mtpr.h"
16
17struct {
18 short fl_state; /* open and busy flags */
19 short fl_active; /* driver state flag */
20 struct buf *fl_buf; /* buffer we're using */
21 unsigned char *fl_xaddr; /* transfer address */
22 short fl_errcnt;
23} fltab;
24
25/*ARGSUSED*/
26flopen(dev, flag)
27 dev_t dev;
28 int flag;
29{
30 struct buf *geteblk();
31
32#if VAX750
33 if (cpu != VAX_780)
34 return (ENXIO);
35#endif
36 if (fltab.fl_state != 0)
37 return (ENXIO);
38 fltab.fl_state = FL_OPEN;
39 fltab.fl_buf = geteblk(512);
40 fltab.fl_active = FL_IDLE;
41 return (0);
42}
43
44/*ARGSUSED*/
45flclose(dev, flag)
46 dev_t dev;
47 int flag;
48{
49
50 brelse(fltab.fl_buf);
51 fltab.fl_state = 0;
52}
53
54floperation(rw, uio)
55 enum uio_rw rw;
56 struct uio *uio;
57{
58 register struct buf *bp;
59 register int i;
60 int error;
61
62 /*
63 * Assume one block read/written for each call -
64 * and enforce this by checking for block size of 128.
65 * Use the b_blkno field to address
66 * physical, 128-byte blocks (u.u_offset/128).
67 * This is checked for validity, and is further interpreted as:
68 *
69 * track# * (sectors/track) + sector #
70 */
71 if (uio->uio_resid == 0)
72 return (0);
73 (void) spl4();
74 while (fltab.fl_state & FL_BUSY)
75 sleep((caddr_t)&fltab, PRIBIO);
76 fltab.fl_state |= FL_BUSY;
77 (void) spl0();
78
79 bp = fltab.fl_buf;
80 error = 0;
81 while ((i = imin(RXBYSEC, uio->uio_resid)) > 0) {
82 bp->b_blkno = uio->uio_offset>>7;
83 if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0177) != 0)
84 return (ENXIO);
85 if (rw == UIO_WRITE) {
86 error = uiomove(bp->b_un.b_addr, i, UIO_WRITE, uio);
87 if (error)
88 break;
89 }
90 bp->b_flags = rw == UIO_WRITE ? B_WRITE : B_READ;
91 (void) spl4();
92 flstart();
93 while ((bp->b_flags & B_DONE) == 0)
94 sleep((caddr_t)bp, PRIBIO);
95 (void) spl0();
96 if (bp->b_flags & B_ERROR) {
97 error = EIO;
98 break;
99 }
100 if (rw == UIO_READ) {
101 error = uiomove(bp->b_un.b_addr, i, UIO_READ, uio);
102 if (error)
103 break;
104 }
105 }
106 fltab.fl_state &= ~FL_BUSY;
107 wakeup((caddr_t)&fltab);
108 return (error);
109}
110
111/*ARGSUSED*/
112flread(dev, uio)
113 dev_t dev;
114 struct uio *uio;
115{
116
117 return (floperation(UIO_READ, uio));
118}
119
120/*ARGSUSED*/
121flwrite(dev, uio)
122 dev_t dev;
123 struct uio *uio;
124{
125
126 return (floperation(UIO_WRITE, uio));
127}
128
129flstart()
130{
131 register struct buf *bp;
132
133 bp = fltab.fl_buf;
134 fltab.fl_active = FL_MAND;
135 fltab.fl_errcnt = 0;
136 fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
137 bp->b_resid = 0;
138 bp->b_bcount = RXBYSEC; /* always transfer a full sector */
139
140 if ((mfpr(TXCS) & TXCS_RDY) == 0)
141 /* not ready to receive order */
142 return;
143 /*
144 * Wake up floppy LSI software with command
145 */
146 fltab.fl_active = FL_SEC;
147 if ((bp->b_flags&B_READ) == B_READ)
148 mtpr(TXDB, FL_RS);
149 else
150 mtpr(TXDB, FL_WS);
151}
152
153/*
154 * See if we want to transmit something
155 * to the floppy - and do it
156 */
157conxfl()
158{
159 register int databyte;
160 register struct buf *bp;
161
162 bp = fltab.fl_buf;
163 switch (fltab.fl_active) {
164
165 case FL_MAND: /* send command */
166 if ((bp->b_flags&B_READ) == B_READ)
167 mtpr(TXDB,FL_RS);
168 else
169 mtpr(TXDB, FL_WS);
170 fltab.fl_active = FL_SEC;
171 break;
172
173 case FL_SEC: /* send sector address */
174 databyte = (int)bp->b_blkno % RXSTRK + 1;
175 mtpr(TXDB, FL_DATA | databyte);
176 fltab.fl_active = FL_TRACK;
177 break;
178
179 case FL_TRACK: /* send track address */
180 databyte = (int)bp->b_blkno / RXSTRK;
181 mtpr(TXDB , FL_DATA | databyte);
182 if ((bp->b_flags&B_READ) == B_READ)
183 /* prepare to receive complete */
184 fltab.fl_active = FL_COM;
185 else
186 /* prepare to send data */
187 fltab.fl_active = FL_DAX;
188 break;
189
190 case FL_DAX:
191 databyte = *(fltab.fl_xaddr++);
192 mtpr(TXDB, FL_DATA | databyte);
193 if (--bp->b_bcount == 0)
194 fltab.fl_active = FL_COM;
195 break;
196
197 case FL_CAN: /* give cancel order */
198 mtpr(TXDB, FL_CANCEL);
199 if (++fltab.fl_errcnt <= FLERRS) {
200 /* If error count permits, retry order */
201 fltab.fl_active = FL_MAND;
202 bp->b_bcount = RXBYSEC;
203 fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
204 } else {
205 /*
206 * We're really stupid today - call it an
207 * error and give up
208 */
209 bp->b_flags |= B_ERROR | B_DONE;
210 bp->b_resid = -RXBYSEC;
211 fltab.fl_active = FL_IDLE;
212 wakeup((caddr_t)bp);
213 }
214 }
215}
216
217cnrfl(c)
218 int c;
219{
220 register int datum;
221 register struct buf *bp;
222
223 datum = c;
224 bp = fltab.fl_buf;
225 if (datum == FL_PERR) {
226 /*
227 * Got a protocol error - cancel the
228 * current function and try again if error count isn't
229 * too great. First, though, make sure that an actual
230 * transaction is in progress (so a spurious error from
231 * the LSI won't screw us up too much!
232 */
233 if (fltab.fl_active != FL_IDLE)
234 fltab.fl_active = FL_CAN;
235 } else switch(fltab.fl_active ) {
236
237 case FL_DAR: /* expecting a datum */
238 if ((c&RXDB_ID) != FL_DATA)
239 goto error;
240 *(fltab.fl_xaddr++) = (c & RXDB_DATA);
241 if (--bp->b_bcount==0) {
242 fltab.fl_active = FL_IDLE;
243 bp->b_flags |= B_DONE;
244 wakeup((caddr_t)bp);
245 }
246 break;
247
248 case FL_COM: /* expecting a "function complete" */
249 if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){
250error:
251 bp->b_flags |= B_ERROR | B_DONE;
252 bp->b_resid = -bp->b_bcount;
253 fltab.fl_active = FL_IDLE;
254 wakeup((caddr_t)bp);
255 } else if ((bp->b_flags&B_READ) == B_READ)
256 /* got function complete, now get data */
257 fltab.fl_active = FL_DAR;
258 else {
259 /* got function complete on write - finish up */
260 fltab.fl_active = FL_IDLE;
261 bp->b_flags |= B_DONE;
262 wakeup((caddr_t)bp);
263 }
264 break;
265 }
266}
267#endif