xref: /csrg-svn/sys/vax/uba/rl.c (revision 34218)
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  *	@(#)rl.c	7.3 (Berkeley) 05/06/88
7  */
8 
9 #include "rl.h"
10 #if NRL > 0
11 /*
12  * UNIBUS RL02 disk driver
13  */
14 #include "../machine/pte.h"
15 
16 #include "param.h"
17 #include "systm.h"
18 #include "dkstat.h"
19 #include "dkbad.h"
20 #include "buf.h"
21 #include "conf.h"
22 #include "dir.h"
23 #include "user.h"
24 #include "map.h"
25 #include "vm.h"
26 #include "cmap.h"
27 #include "uio.h"
28 #include "kernel.h"
29 
30 #include "../vax/cpu.h"
31 #include "../vax/nexus.h"
32 #include "ubavar.h"
33 #include "ubareg.h"
34 #include "rlreg.h"
35 
36 /* Pending Controller items and statistics */
37 struct	rl_softc {
38 	int	rl_softas;	/* Attention sumary, (seeks pending) */
39 	int	rl_ndrive;	/* Number of drives on controller */
40 	int	rl_wticks;	/* Monitor time for function */
41 } rl_softc[NHL];
42 
43 /*
44  * State of controller from last transfer.
45  * Since only one transfer can be done at a time per
46  * controller, only allocate one for each controller.
47  */
48 struct	rl_stat {
49 	short	rl_cyl[4];	/* Current cylinder for each drive */
50 	short	rl_dn;		/* drive number currently transferring */
51 	short	rl_cylnhd;	/* current cylinder and head of transfer */
52 	u_short	rl_bleft;	/* bytes left to transfer */
53 	u_short	rl_bpart;	/* bytes transferred */
54 } rl_stat[NHL];
55 
56 #define rlunit(dev)	(minor(dev) >> 3)
57 
58 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
59 /* Last cylinder not used. Saved for Bad Sector File */
60 struct	size {
61 	daddr_t	nblocks;
62 	int	cyloff;
63 } rl02_sizes[8] = {
64 	15884,		0,		/* A=cyl   0 thru 397 */
65 	 4520,		398,		/* B=cyl 398 thru 510 */
66 	   -1,		0,		/* C=cyl   0 thru 511 */
67 	 4520,		398,		/* D=cyl 398 thru 510 */
68 	    0,          0,		/* E= Not Defined     */
69 	    0,          0,		/* F= Not Defined     */
70 	20440,	        0,		/* G=cyl   0 thru 510 */
71 	    0,          0,		/* H= Not Defined     */
72 };
73 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
74 
75 int	rlprobe(), rlslave(), rlattach(), rldgo(), rlintr();
76 struct	uba_ctlr	*rlminfo[NHL];
77 struct	uba_device	*rldinfo[NRL];
78 struct	uba_device	*rlip[NHL][4];
79 
80 /* RL02 driver structure */
81 u_short	rlstd[] = { 0174400, 0 };
82 struct	uba_driver hldriver =
83     { rlprobe, rlslave, rlattach, rldgo, rlstd, "rl", rldinfo, "hl", rlminfo };
84 
85 /* User table per controller */
86 struct	buf	rlutab[NRL];
87 
88 /* RL02 drive structure */
89 struct	RL02 {
90 	short	nbpt;		/* Number of 512 byte blocks/track */
91 	short	ntrak;
92 	short	nbpc;		/* Number of 512 byte blocks/cylinder */
93 	short	ncyl;
94 	short	btrak;		/* Number of bytes/track */
95 	struct	size *sizes;
96 } rl02 = {
97 	20,	2,	40,	512,	20*512,	rl02_sizes /* rl02/DEC*/
98 };
99 
100 #define	b_cylin b_resid		/* Last seek as CYL<<1 | HD */
101 
102 int	rlwstart, rlwatch();		/* Have started guardian */
103 
104 /* Check that controller exists */
105 /*ARGSUSED*/
106 rlprobe(reg)
107 	caddr_t reg;
108 {
109 	register int br, cvec;
110 
111 #ifdef lint
112 	br = 0; cvec = br; br = cvec;
113 	rlintr(0);
114 #endif
115 	((struct rldevice *)reg)->rlcs = RL_IE | RL_NOOP;
116 	DELAY(10);
117 	((struct rldevice *)reg)->rlcs &= ~RL_IE;
118 	return (sizeof (struct rldevice));
119 }
120 
121 rlslave(ui, reg)
122 	struct uba_device *ui;
123 	caddr_t reg;
124 {
125 	register struct rldevice *rladdr = (struct rldevice *)reg;
126 	short ctr = 0;
127 
128 	/*
129 	 * DEC reports that:
130 	 * For some unknown reason the RL02 (seems to be only drive 1)
131 	 * does not return a valid drive status the first time that a
132 	 * GET STATUS request is issued for the drive, in fact it can
133 	 * take up to three or more GET STATUS requests to obtain the
134 	 * correct status.
135 	 * In order to overcome this, the driver has been modified to
136 	 * issue a GET STATUS request and validate the drive status
137 	 * returned.  If a valid status is not returned after eight
138 	 * attempts, then an error message is printed.
139 	 */
140 	do {
141 		rladdr->rlda.getstat = RL_RESET;
142 		rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/
143 		rlwait(rladdr);
144 	} while ((rladdr->rlcs & (RL_CRDY|RL_ERR)) != RL_CRDY && ++ctr < 8);
145 
146 	if ((rladdr->rlcs & RL_DE) || (ctr >= 8))
147 		return (0);
148 	if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) {
149 		printf("rl%d: rl01's not supported\n", ui->ui_slave);
150 		return(0);
151 	}
152 	return (1);
153 }
154 
155 rlattach(ui)
156 	register struct uba_device *ui;
157 {
158 	register struct rldevice *rladdr;
159 
160 	if (rlwstart == 0) {
161 		timeout(rlwatch, (caddr_t)0, hz);
162 		rlwstart++;
163 	}
164 	/* Initialize iostat values */
165 	if (ui->ui_dk >= 0)
166 		dk_mspw[ui->ui_dk] = .000003906;   /* 16bit transfer time? */
167 	rlip[ui->ui_ctlr][ui->ui_slave] = ui;
168 	rl_softc[ui->ui_ctlr].rl_ndrive++;
169 	rladdr = (struct rldevice *)ui->ui_addr;
170 	/* reset controller */
171 	rladdr->rlda.getstat = RL_RESET;	/* SHOULD BE REPEATED? */
172 	rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT; /* Reset DE bit */
173 	rlwait(rladdr);
174 	/* determine disk posistion */
175 	rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR;
176 	rlwait(rladdr);
177 	/* save disk drive posistion */
178 	rl_stat[ui->ui_ctlr].rl_cyl[ui->ui_slave] =
179 	     (rladdr->rlmp.readhdr & 0177700) >> 6;
180 	rl_stat[ui->ui_ctlr].rl_dn = -1;
181 }
182 
183 rlopen(dev)
184 	dev_t dev;
185 {
186 	register int unit = rlunit(dev);
187 	register struct uba_device *ui;
188 
189 	if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0)
190 		return (ENXIO);
191 	return (0);
192 }
193 
194 rlstrategy(bp)
195 	register struct buf *bp;
196 {
197 	register struct uba_device *ui;
198 	register int drive;
199 	register struct buf *dp;
200 	int partition = minor(bp->b_dev) & 07, s;
201 	long bn, sz;
202 
203 	sz = (bp->b_bcount+511) >> 9;
204 	drive = rlunit(bp->b_dev);
205 	if (drive >= NRL) {
206 		bp->b_error = ENXIO;
207 		goto bad;
208 	}
209 	ui = rldinfo[drive];
210 	if (ui == 0 || ui->ui_alive == 0) {
211 		bp->b_error = ENXIO;
212 		goto bad;
213 	}
214 	if (bp->b_blkno < 0 ||
215 	    (bn = bp->b_blkno)+sz > rl02.sizes[partition].nblocks) {
216 		if (bp->b_blkno == rl02.sizes[partition].nblocks) {
217 		    bp->b_resid = bp->b_bcount;
218 		    goto done;
219 		}
220 		bp->b_error = EINVAL;
221 		goto bad;
222 	}
223 	/* bn is in 512 byte block size */
224 	bp->b_cylin = bn/rl02.nbpc + rl02.sizes[partition].cyloff;
225 	s = spl5();
226 	dp = &rlutab[ui->ui_unit];
227 	disksort(dp, bp);
228 	if (dp->b_active == 0) {
229 		rlustart(ui);
230 		bp = &ui->ui_mi->um_tab;
231 		if (bp->b_actf && bp->b_active == 0)
232 			rlstart(ui->ui_mi);
233 	}
234 	splx(s);
235 	return;
236 
237 bad:
238 	bp->b_flags |= B_ERROR;
239 done:
240 	iodone(bp);
241 	return;
242 }
243 
244 /*
245  * Unit start routine.
246  * Seek the drive to be where the data is
247  * and then generate another interrupt
248  * to actually start the transfer.
249  */
250 rlustart(ui)
251 	register struct uba_device *ui;
252 {
253 	register struct buf *bp, *dp;
254 	register struct uba_ctlr *um;
255 	register struct rldevice *rladdr;
256 	daddr_t bn;
257 	short hd, diff;
258 
259 	if (ui == 0)
260 		return;
261 	um = ui->ui_mi;
262 	dk_busy &= ~(1 << ui->ui_dk);
263 	dp = &rlutab[ui->ui_unit];
264 	if ((bp = dp->b_actf) == NULL)
265 		return;
266 	/*
267 	 * If the controller is active, just remember
268 	 * that this device has to be positioned...
269 	 */
270 	if (um->um_tab.b_active) {
271 		rl_softc[um->um_ctlr].rl_softas |=  1<<ui->ui_slave;
272 		return;
273 	}
274 	/*
275 	 * If we have already positioned this drive,
276 	 * then just put it on the ready queue.
277 	 */
278 	if (dp->b_active)
279 		goto done;
280 	dp->b_active = 1;	/* positioning drive */
281 	rladdr = (struct rldevice *)um->um_addr;
282 
283 	/*
284 	 * Figure out where this transfer is going to
285 	 * and see if we are seeked correctly.
286 	 */
287 	bn = bp->b_blkno;		/* Block # desired */
288 	/*
289 	 * Map 512 byte logical disk blocks
290 	 * to 256 byte sectors (rl02's are stupid).
291 	 */
292 	hd = (bn / rl02.nbpt) & 1;	/* Get head required */
293 	diff = (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] >> 1) - bp->b_cylin;
294 	if ( diff == 0 && (rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] & 1) == hd)
295 		goto done;		/* on cylinder and head */
296 	/*
297 	 * Not at correct position.
298 	 */
299 	rl_stat[um->um_ctlr].rl_cyl[ui->ui_slave] = (bp->b_cylin << 1) | hd;
300 	if (diff < 0)
301 		rladdr->rlda.seek = -diff << 7 | RLDA_HGH | hd << 4;
302 	else
303 		rladdr->rlda.seek = diff << 7 | RLDA_LOW | hd << 4;
304 	rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK;
305 
306 	/*
307 	 * Mark unit busy for iostat.
308 	 */
309 	if (ui->ui_dk >= 0) {
310 		dk_busy |= 1<<ui->ui_dk;
311 		dk_seek[ui->ui_dk]++;
312 	}
313 	rlwait(rladdr);
314 done:
315 	/*
316 	 * Device is ready to go.
317 	 * Put it on the ready queue for the controller
318 	 * (unless its already there.)
319 	 */
320 	if (dp->b_active != 2) {
321 		dp->b_forw = NULL;
322 		if (um->um_tab.b_actf == NULL)
323 			um->um_tab.b_actf = dp;
324 		else
325 			um->um_tab.b_actl->b_forw = dp;
326 		um->um_tab.b_actl = dp;
327 		dp->b_active = 2;	/* Request on ready queue */
328 	}
329 }
330 
331 /*
332  * Start up a transfer on a drive.
333  */
334 rlstart(um)
335 	register struct uba_ctlr *um;
336 {
337 	register struct buf *bp, *dp;
338 	register struct uba_device *ui;
339 	register struct rldevice *rladdr;
340 	register struct rl_stat *st = &rl_stat[um->um_ctlr];
341 	daddr_t bn;
342 	short sn, cyl, cmd;
343 
344 loop:
345 	if ((dp = um->um_tab.b_actf) == NULL) {
346 		st->rl_dn = -1;
347 		st->rl_cylnhd = 0;
348 		st->rl_bleft = 0;
349 		st->rl_bpart = 0;
350 		return;
351 	}
352 	if ((bp = dp->b_actf) == NULL) {
353 		um->um_tab.b_actf = dp->b_forw;
354 		goto loop;
355 	}
356 	/*
357 	 * Mark controller busy, and
358 	 * determine destination.
359 	 */
360 	um->um_tab.b_active++;
361 	ui = rldinfo[rlunit(bp->b_dev)];	/* Controller */
362 	bn = bp->b_blkno;			/* 512 byte Block number */
363 	cyl = bp->b_cylin << 1;			/* Cylinder */
364 	cyl |= (bn / rl02.nbpt) & 1;		/* Get head required */
365 	sn = (bn % rl02.nbpt) << 1;		/* Sector number */
366 	rladdr = (struct rldevice *)ui->ui_addr;
367 	rlwait(rladdr);
368 	rladdr->rlda.rw = cyl<<6 | sn;
369 	/* save away current transfers drive status */
370 	st->rl_dn = ui->ui_slave;
371 	st->rl_cylnhd = cyl;
372 	st->rl_bleft = bp->b_bcount;
373 	st->rl_bpart = rl02.btrak - (sn * NRLBPSC);
374 	/*
375 	 * RL02 must seek between cylinders and between tracks,
376 	 * determine maximum data transfer at this time.
377 	 */
378 	if (st->rl_bleft < st->rl_bpart)
379 		st->rl_bpart = st->rl_bleft;
380 	rladdr->rlmp.rw = -(st->rl_bpart >> 1);
381 	if (bp->b_flags & B_READ)
382 		cmd = RL_IE | RL_READ | (ui->ui_slave << 8);
383 	else
384 		cmd = RL_IE | RL_WRITE | (ui->ui_slave << 8);
385 	um->um_cmd = cmd;
386 	(void) ubago(ui);
387 }
388 
389 rldgo(um)
390 	register struct uba_ctlr *um;
391 {
392 	register struct rldevice *rladdr = (struct rldevice *)um->um_addr;
393 
394 	rladdr->rlba = um->um_ubinfo;
395 	rladdr->rlcs = um->um_cmd|((um->um_ubinfo>>12)&RL_BAE);
396 }
397 
398 /*
399  * Handle a disk interrupt.
400  */
401 rlintr(rl21)
402 	register rl21;
403 {
404 	register struct buf *bp, *dp;
405 	register struct uba_ctlr *um = rlminfo[rl21];
406 	register struct uba_device *ui;
407 	register struct rldevice *rladdr = (struct rldevice *)um->um_addr;
408 	register unit;
409 	struct rl_softc *rl = &rl_softc[um->um_ctlr];
410 	struct rl_stat *st = &rl_stat[um->um_ctlr];
411 	int as = rl->rl_softas, status;
412 
413 	rl->rl_wticks = 0;
414 	rl->rl_softas = 0;
415 	dp = um->um_tab.b_actf;
416 	bp = dp->b_actf;
417 	ui = rldinfo[rlunit(bp->b_dev)];
418 	dk_busy &= ~(1 << ui->ui_dk);
419 
420 	/*
421 	 * Check for and process errors on
422 	 * either the drive or the controller.
423 	 */
424 	if (rladdr->rlcs & RL_ERR) {
425 		u_short err;
426 		rlwait(rladdr);
427 		err = rladdr->rlcs;
428 		/* get staus and reset controller */
429 		rladdr->rlda.getstat = RL_GSTAT;
430 		rladdr->rlcs = (ui->ui_slave << 8) | RL_GETSTAT;
431 		rlwait(rladdr);
432 		status = rladdr->rlmp.getstat;
433 		/* reset drive */
434 		rladdr->rlda.getstat = RL_RESET;
435 		rladdr->rlcs = (ui->ui_slave <<8) | RL_GETSTAT; /* Get status*/
436 		rlwait(rladdr);
437 		if ((status & RLMP_WL) == RLMP_WL) {
438 			/*
439 			 * Give up on write protected devices
440 			 * immediately.
441 			 */
442 			printf("rl%d: write protected\n", rlunit(bp->b_dev));
443 			bp->b_flags |= B_ERROR;
444 		} else if (++um->um_tab.b_errcnt > 10) {
445 			/*
446 			 * After 10 retries give up.
447 			 */
448 			harderr(bp, "rl");
449 			printf("cs=%b mp=%b\n", err, RLCS_BITS,
450 			    status, RLER_BITS);
451 			bp->b_flags |= B_ERROR;
452 		} else
453 			um->um_tab.b_active = 0;	 /* force retry */
454 		/* determine disk position */
455 		rladdr->rlcs = (ui->ui_slave << 8) | RL_RHDR;
456 		rlwait(rladdr);
457 		/* save disk drive position */
458 		st->rl_cyl[ui->ui_slave] =
459 		    (rladdr->rlmp.readhdr & 0177700) >> 6;
460 	}
461 	/*
462 	 * If still ``active'', then don't need any more retries.
463 	 */
464 	if (um->um_tab.b_active) {
465 		/* RL02 check if more data from previous request */
466 		if ((bp->b_flags & B_ERROR) == 0 &&
467 		     (int)(st->rl_bleft -= st->rl_bpart) > 0) {
468 			/*
469 			 * The following code was modeled from the rk07
470 			 * driver when an ECC error occured.  It has to
471 			 * fix the bits then restart the transfer which is
472 			 * what we have to do (restart transfer).
473 			 */
474 			int reg, npf, o, cmd, ubaddr, diff, head;
475 
476 			/* seek to next head/track */
477 			/* increment head and/or cylinder */
478 			st->rl_cylnhd++;
479 			diff = (st->rl_cyl[ui->ui_slave] >> 1) -
480 				(st->rl_cylnhd >> 1);
481 			st->rl_cyl[ui->ui_slave] = st->rl_cylnhd;
482 			head = st->rl_cylnhd & 1;
483 			rlwait(rladdr);
484 			if (diff < 0)
485 				rladdr->rlda.seek =
486 				    -diff << 7 | RLDA_HGH | head << 4;
487 			else
488 				rladdr->rlda.seek =
489 				    diff << 7 | RLDA_LOW | head << 4;
490 			rladdr->rlcs = (ui->ui_slave << 8) | RL_SEEK;
491 			npf = btop( bp->b_bcount - st->rl_bleft );
492 			reg = btop(um->um_ubinfo&0x3ffff) + npf;
493 			o = (int)bp->b_un.b_addr & PGOFSET;
494 			ubapurge(um);
495 			um->um_tab.b_active++;
496 			rlwait(rladdr);
497 			rladdr->rlda.rw = st->rl_cylnhd << 6;
498 			if (st->rl_bleft < (st->rl_bpart = rl02.btrak))
499 				st->rl_bpart = st->rl_bleft;
500 			rladdr->rlmp.rw = -(st->rl_bpart >> 1);
501 			cmd = (bp->b_flags&B_READ ? RL_READ : RL_WRITE) |
502 			    RL_IE | (ui->ui_slave << 8);
503 			ubaddr = (int)ptob(reg) + o;
504 			cmd |= ((ubaddr >> 12) & RL_BAE);
505 			rladdr->rlba = ubaddr;
506 			rladdr->rlcs = cmd;
507 			return;
508 		}
509 		um->um_tab.b_active = 0;
510 		um->um_tab.b_errcnt = 0;
511 		dp->b_active = 0;
512 		dp->b_errcnt = 0;
513 		/* "b_resid" words remaining after error */
514 		bp->b_resid = st->rl_bleft;
515 		um->um_tab.b_actf = dp->b_forw;
516 		dp->b_actf = bp->av_forw;
517 		st->rl_dn = -1;
518 		st->rl_bpart = st->rl_bleft = 0;
519 		iodone(bp);
520 		/*
521 		 * If this unit has more work to do,
522 		 * then start it up right away.
523 		 */
524 		if (dp->b_actf)
525 			rlustart(ui);
526 		as &= ~(1<<ui->ui_slave);
527 	} else
528 		as |= (1<<ui->ui_slave);
529 	ubadone(um);
530 	/* reset state info */
531 	st->rl_dn = -1;
532 	st->rl_cylnhd = st->rl_bpart = st->rl_bleft = 0;
533 	/*
534 	 * Process other units which need attention.
535 	 * For each unit which needs attention, call
536 	 * the unit start routine to place the slave
537 	 * on the controller device queue.
538 	 */
539 	while (unit = ffs((long)as)) {
540 		unit--;		/* was 1 origin */
541 		as &= ~(1<<unit);
542 		rlustart(rlip[rl21][unit]);
543 	}
544 	/*
545 	 * If the controller is not transferring, but
546 	 * there are devices ready to transfer, start
547 	 * the controller.
548 	 */
549 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
550 		rlstart(um);
551 }
552 
553 rlwait(rladdr)
554 	register struct rldevice *rladdr;
555 {
556 
557 	while ((rladdr->rlcs & RL_CRDY) == 0)
558 		;
559 }
560 
561 /*
562  * Reset driver after UBA init.
563  * Cancel software state of all pending transfers
564  * and restart all units and the controller.
565  */
566 rlreset(uban)
567 	int uban;
568 {
569 	register struct uba_ctlr *um;
570 	register struct uba_device *ui;
571 	register struct rldevice *rladdr;
572 	register struct rl_stat *st;
573 	register int rl21, unit;
574 
575 	for (rl21 = 0; rl21 < NHL; rl21++) {
576 		if ((um = rlminfo[rl21]) == 0 || um->um_ubanum != uban ||
577 		    um->um_alive == 0)
578 			continue;
579 		printf(" hl%d", rl21);
580 		rladdr = (struct rldevice *)um->um_addr;
581 		st = &rl_stat[rl21];
582 		um->um_tab.b_active = 0;
583 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
584 		if (um->um_ubinfo) {
585 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
586 			um->um_ubinfo = 0;
587 		}
588 		/* reset controller */
589 		st->rl_dn = -1;
590 		st->rl_cylnhd = 0;
591 		st->rl_bleft = 0;
592 		st->rl_bpart = 0;
593 		rlwait(rladdr);
594 		for (unit = 0; unit < NRL; unit++) {
595 			rladdr->rlcs = (unit << 8) | RL_GETSTAT;
596 			rlwait(rladdr);
597 			/* Determine disk posistion */
598 			rladdr->rlcs = (unit << 8) | RL_RHDR;
599 			rlwait(rladdr);
600 			/* save disk drive posistion */
601 			st->rl_cyl[unit] =
602 				(rladdr->rlmp.readhdr & 0177700) >> 6;
603 			if ((ui = rldinfo[unit]) == 0)
604 				continue;
605 			if (ui->ui_alive == 0 || ui->ui_mi != um)
606 				continue;
607 			rlutab[unit].b_active = 0;
608 			rlustart(ui);
609 		}
610 		rlstart(um);
611 	}
612 }
613 
614 /*
615  * Wake up every second and if an interrupt is pending
616  * but nothing has happened increment a counter.
617  * If nothing happens for 20 seconds, reset the UNIBUS
618  * and begin anew.
619  */
620 rlwatch()
621 {
622 	register struct uba_ctlr *um;
623 	register rl21, unit;
624 	register struct rl_softc *rl;
625 
626 	timeout(rlwatch, (caddr_t)0, hz);
627 	for (rl21 = 0; rl21 < NHL; rl21++) {
628 		um = rlminfo[rl21];
629 		if (um == 0 || um->um_alive == 0)
630 			continue;
631 		rl = &rl_softc[rl21];
632 		if (um->um_tab.b_active == 0) {
633 			for (unit = 0; unit < NRL; unit++)
634 				if (rlutab[unit].b_active &&
635 				    rldinfo[unit]->ui_mi == um)
636 					goto active;
637 			rl->rl_wticks = 0;
638 			continue;
639 		}
640 active:
641 		rl->rl_wticks++;
642 		if (rl->rl_wticks >= 20) {
643 			rl->rl_wticks = 0;
644 			printf("hl%d: lost interrupt\n", rl21);
645 			ubareset(um->um_ubanum);
646 		}
647 	}
648 }
649 
650 /*ARGSUSED*/
651 rldump(dev)
652 	dev_t dev;
653 {
654 
655 	/* don't think there is room on swap for it anyway. */
656 }
657 
658 rlsize(dev)
659 	dev_t dev;
660 {
661 	register int unit = rlunit(dev);
662 	register struct uba_device *ui;
663 
664 	if (unit >= NRL || (ui = rldinfo[unit]) == 0 || ui->ui_alive == 0)
665 		return (-1);
666 	return (rl02.sizes[minor(dev) & 07].nblocks);
667 }
668 #endif
669