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