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