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