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