Commit | Line | Data |
---|---|---|
89435dd5 | 1 | /* rx.c 4.4 83/02/21 */ |
63e51da2 SL |
2 | |
3 | #include "rx.h" | |
4 | #if NFX > 0 | |
5 | /* | |
6 | * RX02 floppy disk device driver | |
7 | * | |
9246378c | 8 | * WARNING, UNTESTED |
63e51da2 | 9 | */ |
9246378c SL |
10 | #include "../machine/pte.h" |
11 | ||
63e51da2 | 12 | #include "../h/param.h" |
63e51da2 | 13 | #include "../h/buf.h" |
9246378c | 14 | #include "../h/systm.h" |
63e51da2 | 15 | #include "../h/conf.h" |
95c06320 HS |
16 | #include "../h/errno.h" |
17 | #include "../h/time.h" | |
9246378c SL |
18 | #include "../h/kernel.h" |
19 | #include "../h/uio.h" | |
95c06320 | 20 | #include "../h/file.h" |
63e51da2 | 21 | |
9246378c | 22 | #include "../vax/cpu.h" |
63e51da2 SL |
23 | #include "../vax/nexus.h" |
24 | #include "../vaxuba/ubavar.h" | |
25 | #include "../vaxuba/ubareg.h" | |
26 | #include "../vaxuba/rxreg.h" | |
27 | ||
28 | /* per-controller data */ | |
29 | struct rx_ctlr { | |
30 | int rxc_state; /* controller state */ | |
31 | #define RXS_READ 1 /* read started */ | |
32 | #define RXS_EMPTY 2 /* empty started */ | |
33 | #define RXS_FILL 3 /* fill started */ | |
34 | #define RXS_WRITE 4 /* write started */ | |
35 | #define RXS_FORMAT 5 /* format started */ | |
36 | #define RXS_RDSTAT 6 /* status read started */ | |
37 | #define RXS_RDERR 7 /* error read started */ | |
9246378c | 38 | #define RXS_IDLE 8 /* device is idle */ |
63e51da2 SL |
39 | u_short rxc_rxcs; /* extended error status */ |
40 | u_short rxc_rxdb; | |
41 | u_short rxc_rxxt[4]; | |
9246378c | 42 | #define RX_MAXTIMEOUT 30 /* # seconds to wait before giving up */ |
63e51da2 SL |
43 | } rx_ctlr[NFX]; |
44 | struct buf rrxbuf[NFX]; /* buffer for I/O */ | |
45 | struct buf erxbuf[NFX]; /* buffer for reading error status */ | |
46 | ||
47 | /* per-drive data */ | |
48 | struct rx_softc { | |
9246378c | 49 | int sc_flags; /* drive status flags */ |
63e51da2 SL |
50 | #define RXF_DBLDEN 0x01 /* use double density */ |
51 | #define RXF_DIRECT 0x02 /* use direct sector mapping */ | |
52 | #define RXF_TRKZERO 0x04 /* start mapping on track 0 */ | |
53 | #define RXF_DEVTYPE 0x07 /* density and mapping flags */ | |
54 | #define RXF_OPEN 0x10 /* open */ | |
55 | #define RXF_DDMK 0x20 /* deleted-data mark detected */ | |
56 | #define RXF_USEWDDS 0x40 /* write deleted-data sector */ | |
9246378c SL |
57 | int sc_csbits; /* constant bits for CS register */ |
58 | int sc_tocnt; /* for watchdog routine */ | |
63e51da2 SL |
59 | } rx_softc[NRX]; |
60 | ||
9246378c SL |
61 | struct rxerr { |
62 | short rxcs; | |
63 | short rxdb; | |
64 | short rxxt[4]; /* error code dump from controller */ | |
65 | } rxerr[NFX]; | |
66 | ||
63e51da2 SL |
67 | struct uba_device *rxdinfo[NRX]; |
68 | struct uba_ctlr *rxminfo[NFX]; | |
69 | int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(); | |
70 | int rxwatch(), rxphys(); | |
71 | u_short rxstd[] = { 0177170, 0177150, 0 }; | |
72 | struct uba_driver fxdriver = | |
73 | { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo }; | |
74 | ||
75 | int rxwstart; | |
76 | #define RXUNIT(dev) (minor(dev)>>4) | |
77 | ||
63e51da2 SL |
78 | /* constants related to floppy data capacity */ |
79 | #define RXSECS 2002 /* # sectors on a floppy */ | |
9246378c | 80 | #define DDSTATE (sc->sc_flags&RXF_DBLDEN) |
63e51da2 SL |
81 | #define NBPS (DDSTATE ? 256 : 128) /* # bytes per sector */ |
82 | #define NWPS (DDSTATE ? 128 : 64) /* # words per sector */ | |
83 | #define RXSIZE (DDSTATE ? 512512 : 256256) /* # bytes per disk */ | |
84 | #define SECSHFT (DDSTATE ? 8 : 7) /* # bits to shift for sctr # */ | |
85 | #define SECMASK (DDSTATE ? 0xff : 0x7f) /* shifted-out bits of offset */ | |
86 | ||
9246378c | 87 | #define B_CTRL 0x80000000 /* control (format) request */ |
63e51da2 SL |
88 | |
89 | /*ARGSUSED*/ | |
90 | rxprobe (reg) | |
91 | caddr_t reg; | |
92 | { | |
9246378c | 93 | register int br, cvec; /* value-result */ |
63e51da2 SL |
94 | struct rxdevice *rxaddr = (struct rxdevice *)reg; |
95 | ||
96 | #ifdef lint | |
97 | br = 0; cvec = br; br = cvec; | |
9246378c | 98 | rxintr(0); |
63e51da2 SL |
99 | #endif lint |
100 | rxaddr->rxcs = RX_INTR; | |
101 | DELAY(10); | |
102 | rxaddr->rxcs = 0; | |
103 | return (sizeof (*rxaddr)); | |
104 | } | |
105 | ||
106 | rxslave(ui,reg) | |
107 | struct uba_device *ui; | |
108 | caddr_t reg; | |
109 | { | |
110 | ||
111 | ui->ui_dk = 1; | |
112 | return (ui->ui_slave == 0 || ui->ui_slave == 1); | |
113 | } | |
114 | ||
115 | /*ARGSUSED*/ | |
116 | rxattach(ui) | |
117 | struct uba_device *ui; | |
118 | { | |
119 | ||
120 | } | |
121 | ||
122 | /*ARGSUSED1*/ | |
123 | rxopen(dev, flag) | |
124 | dev_t dev; | |
125 | int flag; | |
126 | { | |
127 | register int unit = RXUNIT(dev); | |
128 | register struct rx_softc *sc; | |
129 | register struct uba_device *ui; | |
130 | ||
9246378c SL |
131 | if (unit >= NRX || (minor(dev) & 0x8) || |
132 | (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0) | |
133 | return (ENXIO); | |
63e51da2 | 134 | sc = &rx_softc[unit]; |
9246378c SL |
135 | if (sc->sc_flags & RXF_OPEN) |
136 | return (EBUSY); | |
137 | sc->sc_flags = RXF_OPEN | (minor(dev) & RXF_DEVTYPE); | |
138 | sc->sc_csbits = RX_INTR; | |
139 | sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1; | |
140 | sc->sc_csbits |= minor(dev) & RXF_DBLDEN ? RX_DDEN : RX_SDEN; | |
141 | return (0); | |
63e51da2 SL |
142 | } |
143 | ||
144 | /*ARGSUSED1*/ | |
145 | rxclose(dev, flag) | |
146 | dev_t dev; | |
147 | int flag; | |
148 | { | |
149 | register struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; | |
150 | ||
151 | sc->sc_flags &= ~RXF_OPEN; | |
152 | sc->sc_csbits = 0; | |
153 | } | |
154 | ||
155 | rxstrategy(bp) | |
156 | register struct buf *bp; | |
157 | { | |
158 | struct uba_device *ui; | |
159 | register struct rx_softc *sc; | |
160 | register struct uba_ctlr *um; | |
9246378c | 161 | int s; |
63e51da2 SL |
162 | |
163 | ui = rxdinfo[RXUNIT(bp->b_dev)]; | |
164 | if (ui == 0 || ui->ui_alive == 0) { | |
165 | bp->b_flags |= B_ERROR; | |
166 | iodone(bp); | |
167 | return; | |
168 | } | |
63e51da2 SL |
169 | um = ui->ui_mi; |
170 | bp->b_actf = NULL; | |
9246378c | 171 | s = spl5(); |
63e51da2 SL |
172 | if (um->um_tab.b_actf->b_actf == NULL) |
173 | um->um_tab.b_actf->b_actf = bp; | |
174 | else | |
175 | um->um_tab.b_actf->b_actl->b_forw = bp; | |
176 | um->um_tab.b_actf->b_actl = bp; | |
177 | bp = um->um_tab.b_actf; | |
9246378c SL |
178 | if (!um->um_tab.b_active && bp->b_actf) |
179 | rxstart(um); | |
63e51da2 SL |
180 | splx(s); |
181 | } | |
182 | ||
183 | /* | |
184 | * Sector mapping routine. | |
185 | * Two independent sets of choices are available: | |
186 | * | |
187 | * (a) The first logical sector may either be on track 1 or track 0. | |
188 | * (b) The sectors on a track may either be taken in 2-for-1 interleaved | |
189 | * fashion or directly. | |
190 | * This gives a total of four possible mapping schemes. | |
191 | * | |
192 | * Physical tracks on the RX02 are numbered 0-76. Physical sectors on | |
193 | * each track are numbered 1-26. | |
194 | * | |
195 | * When interleaving is used, sectors on the first logical track are | |
196 | * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26. A skew of | |
197 | * six sectors per track is also used (to allow time for the heads to | |
198 | * move); hence, the sectors on the second logical track are taken in | |
199 | * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6; | |
200 | * the third logical track starts with sector 13; and so on. | |
201 | * | |
202 | * When the mapping starts with track 1, track 0 is the last logical | |
203 | * track, and this track is always handled directly (without inter- | |
204 | * leaving), even when the rest of the disk is interleaved. (This is | |
205 | * still compatible with DEC RT-11, which does not use track 0 at all.) | |
206 | */ | |
9246378c SL |
207 | rxmap(bp, psector, ptrack) |
208 | struct buf *bp; | |
209 | int *psector, *ptrack; | |
63e51da2 SL |
210 | { |
211 | register int lt, ls, ptoff; | |
9246378c | 212 | struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; |
63e51da2 | 213 | |
95c06320 | 214 | ls = bp->b_blkno * (NBPS / DEV_BSIZE); |
9246378c SL |
215 | lt = ls / 26; |
216 | ls %= 26; | |
63e51da2 SL |
217 | /* |
218 | * The "physical track offset" (ptoff) takes the | |
219 | * starting physical track (0 or 1) and the desired | |
220 | * interleaving into account. If lt+ptoff >= 77, | |
221 | * then interleaving is not performed. | |
222 | */ | |
223 | ptoff = 0; | |
9246378c SL |
224 | if (sc->sc_flags&RXF_DIRECT) |
225 | ptoff = 77; | |
226 | if (sc->sc_flags&RXF_TRKZERO) | |
63e51da2 SL |
227 | ptoff++; |
228 | if (lt + ptoff < 77) | |
229 | ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26; | |
9246378c SL |
230 | *ptrack = (lt + ptoff) % 77; |
231 | *psector = ls + 1; | |
63e51da2 SL |
232 | } |
233 | ||
234 | rxstart(um) | |
235 | register struct uba_ctlr *um; | |
236 | { | |
237 | register struct rxdevice *rxaddr; | |
238 | register struct rx_ctlr *rxc; | |
239 | register struct rx_softc *sc; | |
240 | struct buf *bp; | |
9246378c | 241 | int unit, sector, track; |
63e51da2 | 242 | |
9246378c | 243 | if (um->um_tab.b_active || (bp = um->um_tab.b_actf->b_actf) == NULL) |
63e51da2 | 244 | return; |
9246378c | 245 | um->um_tab.b_active++; |
63e51da2 SL |
246 | unit = RXUNIT(bp->b_dev); |
247 | sc = &rx_softc[unit]; | |
63e51da2 SL |
248 | rxaddr = (struct rxdevice *)um->um_addr; |
249 | rxc = &rx_ctlr[um->um_ctlr]; | |
9246378c SL |
250 | rxtimo(bp->b_dev); /* start watchdog */ |
251 | if (bp->b_flags&B_CTRL) { /* format */ | |
63e51da2 SL |
252 | rxc->rxc_state = RXS_FORMAT; |
253 | rxaddr->rxcs = RX_FORMAT | sc->sc_csbits; | |
9246378c | 254 | while ((rxaddr->rxcs&RX_TREQ) == 0) |
63e51da2 SL |
255 | ; |
256 | rxaddr->rxdb = 'I'; | |
257 | return; | |
258 | } | |
9246378c SL |
259 | if (bp->b_flags&B_READ) { /* read */ |
260 | rxmap(bp, §or, &track); | |
63e51da2 SL |
261 | rxc->rxc_state = RXS_READ; |
262 | rxaddr->rxcs = RX_READ | sc->sc_csbits; | |
9246378c | 263 | while ((rxaddr->rxcs&RX_TREQ) == 0) |
63e51da2 | 264 | ; |
9246378c SL |
265 | rxaddr->rxdb = (u_short)sector; |
266 | while ((rxaddr->rxcs&RX_TREQ) == 0) | |
63e51da2 | 267 | ; |
9246378c | 268 | rxaddr->rxdb = (u_short)track; |
63e51da2 SL |
269 | return; |
270 | } | |
9246378c | 271 | rxc->rxc_state = RXS_FILL; /* write */ |
63e51da2 SL |
272 | um->um_cmd = RX_FILL; |
273 | (void) ubago(rxdinfo[unit]); | |
274 | } | |
275 | ||
276 | rxdgo(um) | |
277 | struct uba_ctlr *um; | |
278 | { | |
279 | register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr; | |
280 | int ubinfo = um->um_ubinfo; | |
281 | struct buf *bp = &rrxbuf[um->um_ctlr]; | |
282 | struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; | |
283 | struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr]; | |
284 | ||
285 | bp = um->um_tab.b_actf; | |
9246378c | 286 | sc->sc_tocnt = 0; |
63e51da2 | 287 | if (rxc->rxc_state != RXS_RDERR) { |
9246378c | 288 | while ((rxaddr->rxcs&RX_TREQ) == 0) |
63e51da2 | 289 | ; |
9246378c | 290 | rxaddr->rxdb = bp->b_bcount >> 1; |
63e51da2 | 291 | } |
9246378c | 292 | while ((rxaddr->rxcs&RX_TREQ) == 0) |
63e51da2 | 293 | ; |
9246378c | 294 | rxaddr->rxdb = ubinfo; |
63e51da2 SL |
295 | rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits; |
296 | } | |
297 | ||
9246378c SL |
298 | rxintr(dev) |
299 | dev_t dev; | |
63e51da2 | 300 | { |
9246378c SL |
301 | int unit = RXUNIT(dev), sector, track; |
302 | struct uba_ctlr *um = rxminfo[unit]; | |
303 | register struct rxdevice *rxaddr; | |
304 | register struct buf *bp; | |
63e51da2 SL |
305 | register struct rx_softc *sc = &rx_softc[unit]; |
306 | struct uba_device *ui = rxdinfo[unit]; | |
9246378c SL |
307 | struct rxerr *er; |
308 | register struct rx_ctlr *rxc; | |
309 | ||
310 | sc->sc_tocnt = 0; | |
311 | if (!um->um_tab.b_active) | |
63e51da2 | 312 | return; |
9246378c SL |
313 | rxaddr = (struct rxdevice *)um->um_addr; |
314 | rxc = &rx_ctlr[um->um_ctlr]; | |
315 | er = &rxerr[um->um_ctlr]; | |
316 | bp = um->um_tab.b_actf->b_actf; | |
317 | if ((rxaddr->rxcs & RX_ERR) && | |
318 | rxc->rxc_state != RXS_RDSTAT && rxc->rxc_state != RXS_RDERR) | |
319 | goto error; | |
63e51da2 SL |
320 | switch (rxc->rxc_state) { |
321 | ||
9246378c SL |
322 | /* |
323 | * Incomplete commands. Perform next step | |
324 | * and return. Note that b_active is set on | |
325 | * entrance and, therefore, also on exit. | |
326 | */ | |
63e51da2 SL |
327 | case RXS_READ: |
328 | if (rxaddr->rxdb & RXES_DDMARK) | |
329 | sc->sc_flags |= RXF_DDMK; | |
330 | else | |
331 | sc->sc_flags &= ~RXF_DDMK; | |
332 | rxc->rxc_state = RXS_EMPTY; | |
333 | um->um_cmd = RX_EMPTY; | |
334 | (void) ubago(ui); | |
335 | return; | |
336 | ||
337 | case RXS_FILL: | |
338 | rxc->rxc_state = RXS_WRITE; | |
339 | if (sc->sc_flags & RXF_USEWDDS) { | |
340 | rxaddr->rxcs = RX_WDDS | sc->sc_csbits; | |
341 | sc->sc_flags &= ~RXF_USEWDDS; | |
342 | } else | |
343 | rxaddr->rxcs = RX_WRITE | sc->sc_csbits; | |
9246378c | 344 | while ((rxaddr->rxcs&RX_TREQ) == 0) |
63e51da2 | 345 | ; |
9246378c SL |
346 | rxmap(bp, §or, &track); |
347 | rxaddr->rxdb = sector; | |
348 | while ((rxaddr->rxcs&RX_TREQ) == 0) | |
63e51da2 | 349 | ; |
9246378c | 350 | rxaddr->rxdb = track; |
63e51da2 SL |
351 | return; |
352 | ||
9246378c SL |
353 | /* |
354 | * Possibly completed command. | |
355 | */ | |
63e51da2 | 356 | case RXS_RDSTAT: |
9246378c | 357 | if (rxaddr->rxdb&RXES_READY) |
63e51da2 SL |
358 | goto rderr; |
359 | bp->b_error = EBUSY; | |
360 | bp->b_flags |= B_ERROR; | |
9246378c SL |
361 | goto done; |
362 | ||
363 | /* | |
364 | * Command completed. | |
365 | */ | |
366 | case RXS_EMPTY: | |
367 | case RXS_WRITE: | |
368 | case RXS_FORMAT: | |
369 | goto done; | |
63e51da2 SL |
370 | |
371 | case RXS_RDERR: | |
9246378c SL |
372 | rxmap(bp, §or, &track); |
373 | printf("rx%d: hard error, lsn%d (trk %d psec %d) ", | |
95c06320 | 374 | unit, bp->b_blkno * (NBPS / DEV_BSIZE), |
9246378c SL |
375 | track, sector); |
376 | printf("cs=%b, db=%b, err=%x\n", er->rxcs, | |
377 | RXCS_BITS, er->rxdb, RXES_BITS, er->rxxt[0]); | |
378 | goto done; | |
63e51da2 SL |
379 | |
380 | default: | |
9246378c SL |
381 | printf("rx%d: state %d (reset)", unit, rxc->rxc_state); |
382 | rxreset(um->um_ubanum); | |
63e51da2 SL |
383 | printf("\n"); |
384 | return; | |
385 | } | |
63e51da2 SL |
386 | error: |
387 | /* | |
388 | * In case of an error: | |
389 | * (a) Give up now if a format (ioctl) was in progress, or if a | |
390 | * density error was detected. | |
391 | * (b) Retry up to nine times if a CRC (data) error was detected, | |
392 | * then give up if the error persists. | |
393 | * (c) In all other cases, reinitialize the drive and try the | |
394 | * operation once more before giving up. | |
395 | */ | |
9246378c | 396 | if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR)) |
63e51da2 SL |
397 | goto giveup; |
398 | if (rxaddr->rxdb & RXES_CRCERR) { | |
63e51da2 SL |
399 | if (++bp->b_errcnt >= 10) |
400 | goto giveup; | |
401 | goto retry; | |
402 | } | |
403 | bp->b_errcnt += 9; | |
404 | if (bp->b_errcnt >= 10) | |
405 | goto giveup; | |
406 | rxaddr->rxcs = RX_INIT; | |
407 | /* no way to get an interrupt for "init done", so just wait */ | |
9246378c | 408 | while ((rxaddr->rxdb&RX_DONE) == 0) |
63e51da2 SL |
409 | ; |
410 | retry: | |
9246378c SL |
411 | /* |
412 | * In case we already have UNIBUS resources, give | |
413 | * them back since we reallocate things in rxstart. | |
414 | */ | |
415 | if (um->um_ubinfo) | |
416 | ubadone(um); | |
417 | rxstart(um); | |
63e51da2 | 418 | return; |
9246378c | 419 | |
63e51da2 SL |
420 | giveup: |
421 | /* | |
422 | * Hard I/O error -- | |
9246378c SL |
423 | * Density errors are not noted on the console since the |
424 | * only way to determine the density of an unknown disk | |
425 | * is to try one density or the other at random and see | |
426 | * which one doesn't give a density error. | |
63e51da2 SL |
427 | */ |
428 | if (rxaddr->rxdb & RXES_DENERR) { | |
9246378c | 429 | bp->b_error = EIO; |
63e51da2 SL |
430 | bp->b_flags |= B_ERROR; |
431 | goto done; | |
432 | } | |
433 | rxc->rxc_state = RXS_RDSTAT; | |
434 | rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits; | |
435 | return; | |
9246378c | 436 | |
63e51da2 SL |
437 | rderr: |
438 | /* | |
439 | * A hard error (other than not ready or density) has occurred. | |
440 | * Read the extended error status information. | |
441 | * Before doing this, save the current CS and DB register values, | |
442 | * because the read error status operation may modify them. | |
9246378c | 443 | * Insert buffer with request at the head of the queue. |
63e51da2 SL |
444 | */ |
445 | bp->b_error = EIO; | |
446 | bp->b_flags |= B_ERROR; | |
447 | ubadone(um); | |
448 | er->rxcs = rxaddr->rxcs; | |
449 | er->rxdb = rxaddr->rxdb; | |
95c06320 | 450 | bp = &erxbuf[unit]; |
63e51da2 SL |
451 | bp->b_un.b_addr = (caddr_t)er->rxxt; |
452 | bp->b_bcount = sizeof (er->rxxt); | |
453 | bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET); | |
9246378c SL |
454 | if (um->um_tab.b_actf->b_actf == NULL) |
455 | um->um_tab.b_actf->b_actl = bp; | |
456 | bp->b_forw = um->um_tab.b_actf->b_actf; | |
457 | um->um_tab.b_actf->b_actf = bp; | |
63e51da2 SL |
458 | rxc->rxc_state = RXS_RDERR; |
459 | um->um_cmd = RX_RDERR; | |
460 | (void) ubago(ui); | |
9246378c SL |
461 | return; |
462 | done: | |
463 | um->um_tab.b_active = 0; | |
464 | um->um_tab.b_actf->b_actf = bp->b_forw; | |
465 | bp->b_resid = 0; | |
466 | iodone(bp); | |
467 | rxc->rxc_state = RXS_IDLE; | |
468 | ubadone(um); | |
469 | /* | |
470 | * If this unit has more work to do, | |
471 | * start it up right away | |
472 | */ | |
95c06320 HS |
473 | if (um->um_tab.b_actf->b_actf) |
474 | rxstart(um); | |
63e51da2 SL |
475 | } |
476 | ||
477 | /*ARGSUSED*/ | |
478 | minrxphys(bp) | |
479 | struct buf *bp; | |
480 | { | |
95c06320 | 481 | struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; |
63e51da2 SL |
482 | |
483 | if (bp->b_bcount > NBPS) | |
484 | bp->b_bcount = NBPS; | |
485 | } | |
486 | ||
9246378c SL |
487 | rxtimo(dev) |
488 | dev_t dev; | |
63e51da2 SL |
489 | { |
490 | register struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; | |
491 | ||
9246378c SL |
492 | if (sc->sc_flags & RXF_OPEN) |
493 | timeout(rxtimo, (caddr_t)dev, hz); | |
63e51da2 SL |
494 | if (++sc->sc_tocnt < RX_MAXTIMEOUT) |
495 | return; | |
63e51da2 SL |
496 | rxintr(dev); |
497 | } | |
498 | ||
499 | rxreset(uban) | |
500 | int uban; | |
501 | { | |
502 | register struct uba_ctlr *um; | |
503 | register struct rxdevice *rxaddr; | |
504 | register int ctlr; | |
505 | ||
506 | for (ctlr = 0; ctlr < NFX; ctlr++) { | |
507 | if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban || | |
508 | um->um_alive == 0) | |
509 | continue; | |
510 | printf(" fx%d", ctlr); | |
511 | if (um->um_ubinfo) { | |
512 | printf("<%d>", (um->um_ubinfo>>28)&0xf); | |
9246378c | 513 | um->um_ubinfo = 0; |
63e51da2 SL |
514 | } |
515 | rx_ctlr[ctlr].rxc_state = RXS_IDLE; | |
516 | rxaddr = (struct rxdevice *)um->um_addr; | |
9246378c SL |
517 | rxaddr->rxcs = RX_INIT; |
518 | while ((rxaddr->rxdb&RX_DONE) == 0) | |
63e51da2 | 519 | ; |
9246378c | 520 | rxstart(um); |
63e51da2 SL |
521 | } |
522 | } | |
523 | ||
9246378c | 524 | rxread(dev, uio) |
63e51da2 | 525 | dev_t dev; |
9246378c | 526 | struct uio *uio; |
63e51da2 SL |
527 | { |
528 | int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr; | |
95c06320 | 529 | struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; |
63e51da2 | 530 | |
9246378c SL |
531 | if (uio->uio_offset + uio->uio_resid > RXSIZE) |
532 | return (ENXIO); | |
533 | if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) | |
534 | return (EIO); | |
535 | return (physio(rxstrategy, &rrxbuf[ctlr], dev, B_READ, minrxphys)); | |
63e51da2 SL |
536 | } |
537 | ||
9246378c | 538 | rxwrite(dev, uio) |
63e51da2 | 539 | dev_t dev; |
9246378c | 540 | struct uio *uio; |
63e51da2 SL |
541 | { |
542 | int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr; | |
95c06320 | 543 | struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; |
63e51da2 | 544 | |
9246378c SL |
545 | if (uio->uio_offset + uio->uio_resid > RXSIZE) |
546 | return (ENXIO); | |
547 | if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) | |
548 | return (EIO); | |
549 | return (physio(rxstrategy, &rrxbuf[ctlr], dev, B_WRITE, minrxphys)); | |
63e51da2 SL |
550 | } |
551 | ||
552 | /* | |
553 | * Control routine: | |
554 | * processes three kinds of requests: | |
555 | * | |
556 | * (1) Set density according to that specified by the open device. | |
557 | * (2) Arrange for the next sector to be written with a deleted- | |
558 | * data mark. | |
559 | * (3) Report whether the last sector read had a deleted-data mark | |
560 | * (by returning with an EIO error code if it did). | |
561 | * | |
562 | * Requests relating to deleted-data marks can be handled right here. | |
563 | * A "set density" request, however, must additionally be processed | |
564 | * through "rxstart", just like a read or write request. | |
63e51da2 SL |
565 | */ |
566 | /*ARGSUSED3*/ | |
9246378c | 567 | rxioctl(dev, cmd, data, flag) |
63e51da2 SL |
568 | dev_t dev; |
569 | int cmd; | |
9246378c | 570 | caddr_t data; |
63e51da2 SL |
571 | int flag; |
572 | { | |
573 | int unit = RXUNIT(dev); | |
574 | struct rx_softc *sc = &rx_softc[unit]; | |
63e51da2 SL |
575 | |
576 | switch (cmd) { | |
577 | ||
9246378c | 578 | case RXIOC_FORMAT: |
63e51da2 | 579 | if ((flag&FWRITE) == 0) |
9246378c | 580 | return (EBADF); |
95c06320 | 581 | return (rxformat(dev)); |
63e51da2 | 582 | |
9246378c SL |
583 | case RXIOC_WDDS: |
584 | sc->sc_flags |= RXF_USEWDDS; | |
585 | return (0); | |
63e51da2 | 586 | |
9246378c SL |
587 | case RXIOC_RDDSMK: |
588 | *(int *)data = sc->sc_flags & RXF_DDMK; | |
589 | return (0); | |
63e51da2 | 590 | } |
9246378c SL |
591 | return (ENXIO); |
592 | } | |
593 | ||
594 | /* | |
595 | * Initiate a format command. | |
596 | */ | |
95c06320 HS |
597 | rxformat(dev) |
598 | dev_t dev; | |
9246378c | 599 | { |
95c06320 | 600 | int ctlr = rxdinfo[RXUNIT(dev)]->ui_mi->um_ctlr; |
9246378c | 601 | struct buf *bp; |
95c06320 | 602 | struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; |
9246378c | 603 | int s, error = 0; |
63e51da2 | 604 | |
63e51da2 SL |
605 | bp = &rrxbuf[ctlr]; |
606 | s = spl5(); | |
607 | while (bp->b_flags & B_BUSY) | |
608 | sleep(bp, PRIBIO); | |
609 | bp->b_flags = B_BUSY | B_CTRL; | |
610 | splx(s); | |
9246378c | 611 | sc->sc_flags = RXS_FORMAT; |
63e51da2 SL |
612 | bp->b_dev = dev; |
613 | bp->b_error = 0; | |
9246378c | 614 | bp->b_resid = 0; |
63e51da2 SL |
615 | rxstrategy (bp); |
616 | iowait(bp); | |
9246378c SL |
617 | if (bp->b_flags & B_ERROR) |
618 | error = bp->b_error; | |
63e51da2 | 619 | bp->b_flags &= ~B_BUSY; |
9246378c SL |
620 | wakeup((caddr_t)bp); |
621 | return (error); | |
63e51da2 SL |
622 | } |
623 | #endif |