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