BSD 4_1_snap development
[unix-history] / sys / dev / flp.c
CommitLineData
01395141
C
1/* flp.c 4.5 81/03/08 */
2
3#if VAX780
4#include "../h/flp.h"
5#include "../h/param.h"
6#include "../h/systm.h"
7#include "../h/conf.h"
8#include "../h/dir.h"
9#include "../h/user.h"
10#include "../h/mtpr.h"
11#include "../h/buf.h"
12#include "../h/cons.h"
13#include "../h/cpu.h"
14
15struct {
16 short fl_state; /* open and busy flags */
17 short fl_active; /* driver state flag */
18 struct buf *fl_buf; /* buffer we're using */
19 unsigned char *fl_xaddr; /* transfer address */
20 short fl_errcnt;
21} fltab;
22
23/*ARGSUSED*/
24flopen(dev, flag)
25 dev_t dev;
26 int flag;
27{
28 struct buf *geteblk();
29
30#if VAX750
31 if (cpu != VAX_780) {
32 u.u_error = ENXIO;
33 return;
34 }
35#endif
36 if (fltab.fl_state != 0) {
37 u.u_error = ENXIO;
38 return;
39 }
40 fltab.fl_state = FL_OPEN;
41 fltab.fl_buf = geteblk();
42 fltab.fl_active = FL_IDLE;
43}
44
45/*ARGSUSED*/
46flclose(dev, flag)
47 dev_t dev;
48 int flag;
49{
50
51 brelse(fltab.fl_buf);
52 fltab.fl_state = 0;
53}
54
55flstrategy(rw)
56 int rw;
57{
58 register struct buf *bp;
59 register unsigned i;
60
61 /*
62 * Assume one block read/written for each call -
63 * and enforce this by checking for block size of 128.
64 * Use the b_blkno field to address
65 * physical, 128-byte blocks (u.u_offset/128).
66 * This is checked for validity, and is further interpreted as:
67 *
68 * track# * (sectors/track) + sector #
69 */
70 if (u.u_count == 0)
71 return;
72 (void) spl4();
73 while (fltab.fl_state & FL_BUSY)
74 sleep((caddr_t)&fltab, PRIBIO);
75 fltab.fl_state |= FL_BUSY;
76 (void) spl0();
77
78 bp = fltab.fl_buf;
79 while ((i = min(RXBYSEC, u.u_count)) != 0) {
80 bp->b_blkno = u.u_offset>>7;
81 if (bp->b_blkno >= MAXSEC || (u.u_offset & 0177) != 0) {
82 /* block number out of range */
83 /* or offset in middle of block */
84 u.u_error = ENXIO;
85 break;
86 }
87 if (rw == B_WRITE) {
88 iomove(bp->b_un.b_addr, i, B_WRITE);
89 if (u.u_error != 0)
90 break;
91 }
92 bp->b_flags = rw;
93 (void) spl4();
94 flstart();
95 while ((bp->b_flags & B_DONE) == 0)
96 sleep((caddr_t)bp, PRIBIO);
97 (void) spl0();
98 if (bp->b_flags & B_ERROR) {
99 u.u_error = EIO;
100 break;
101 }
102 if (rw == B_READ) {
103 iomove(bp->b_un.b_addr, i, B_READ);
104 if (u.u_error != 0)
105 break;
106 }
107 }
108 u.u_count = bp->b_resid;
109 fltab.fl_state &= ~FL_BUSY;
110 wakeup((caddr_t)&fltab);
111}
112
113/*ARGSUSED*/
114flread(dev)
115 dev_t dev;
116{
117
118 flstrategy(B_READ);
119}
120
121/*ARGSUSED*/
122flwrite(dev)
123 dev_t dev;
124{
125
126 flstrategy(B_WRITE);
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