Commit | Line | Data |
---|---|---|
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 | ||
17 | struct { | |
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*/ | |
26 | flopen(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*/ | |
45 | flclose(dev, flag) | |
46 | dev_t dev; | |
47 | int flag; | |
48 | { | |
49 | ||
50 | brelse(fltab.fl_buf); | |
51 | fltab.fl_state = 0; | |
52 | } | |
53 | ||
54 | floperation(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*/ | |
112 | flread(dev, uio) | |
113 | dev_t dev; | |
114 | struct uio *uio; | |
115 | { | |
116 | ||
117 | return (floperation(UIO_READ, uio)); | |
118 | } | |
119 | ||
120 | /*ARGSUSED*/ | |
121 | flwrite(dev, uio) | |
122 | dev_t dev; | |
123 | struct uio *uio; | |
124 | { | |
125 | ||
126 | return (floperation(UIO_WRITE, uio)); | |
127 | } | |
128 | ||
129 | flstart() | |
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 | */ | |
157 | conxfl() | |
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 | ||
217 | cnrfl(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){ | |
250 | error: | |
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 |