xref: /original-bsd/sys/vax/uba/rk.c (revision f0fd5f8a)
1 /*	rk.c	4.51	82/12/17	*/
2 
3 #include "rk.h"
4 #if NHK > 0
5 int	rkpip;		/* DEBUG */
6 int	rknosval;	/* DEBUG */
7 #ifdef RKDEBUG
8 int	rkdebug;
9 #endif
10 #ifdef RKBDEBUG
11 int	rkbdebug;
12 #endif
13 /*
14  * RK611/RK0[67] disk driver
15  *
16  * This driver mimics up.c; see it for an explanation of common code.
17  *
18  * TODO:
19  *	Learn why we lose an interrupt sometime when spinning drives down
20  */
21 #include "../machine/pte.h"
22 
23 #include "../h/param.h"
24 #include "../h/systm.h"
25 #include "../h/buf.h"
26 #include "../h/conf.h"
27 #include "../h/dir.h"
28 #include "../h/user.h"
29 #include "../h/map.h"
30 #include "../h/vm.h"
31 #include "../h/dk.h"
32 #include "../h/cmap.h"
33 #include "../h/dkbad.h"
34 #include "../h/uio.h"
35 
36 #include "../vax/cpu.h"
37 #include "../vaxuba/ubareg.h"
38 #include "../vaxuba/ubavar.h"
39 #include "../vaxuba/rkreg.h"
40 
41 struct	rk_softc {
42 	int	sc_softas;
43 	int	sc_ndrive;
44 	int	sc_wticks;
45 	int	sc_recal;
46 } rk_softc[NHK];
47 
48 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
49 struct size {
50 	daddr_t	nblocks;
51 	int	cyloff;
52 } rk7_sizes[8] ={
53 	15884,	0,		/* A=cyl 0 thru 240 */
54 	10032,	241,		/* B=cyl 241 thru 392 */
55 	53790,	0,		/* C=cyl 0 thru 814 */
56 	0,	0,
57 	0,	0,
58 	0,	0,
59 	27786,	393,		/* G=cyl 393 thru 813 */
60 	0,	0,
61 }, rk6_sizes[8] ={
62 	15884,	0,		/* A=cyl 0 thru 240 */
63 	11154,	241,		/* B=cyl 241 thru 409 */
64 	27126,	0,		/* C=cyl 0 thru 410 */
65 	0,	0,
66 	0,	0,
67 	0,	0,
68 	0,	0,
69 	0,	0,
70 };
71 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
72 
73 short	rktypes[] = { RK_CDT, 0 };
74 
75 int	rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
76 struct	uba_ctlr *rkminfo[NHK];
77 struct	uba_device *rkdinfo[NRK];
78 struct	uba_device *rkip[NHK][4];
79 
80 u_short	rkstd[] = { 0777440, 0 };
81 struct	uba_driver hkdriver =
82  { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
83 struct	buf rkutab[NRK];
84 short	rkcyl[NRK];
85 #ifndef NOBADSECT
86 struct	dkbad rkbad[NRK];
87 struct	buf brkbuf[NRK];
88 #endif
89 
90 struct	rkst {
91 	short	nsect;
92 	short	ntrak;
93 	short	nspc;
94 	short	ncyl;
95 	struct	size *sizes;
96 } rkst[] = {
97 	NRKSECT, NRKTRK, NRKSECT*NRKTRK,	NRK7CYL,	rk7_sizes,
98 	NRKSECT, NRKTRK, NRKSECT*NRKTRK,	NRK6CYL,	rk6_sizes,
99 };
100 
101 u_char 	rk_offset[16] =
102   { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
103     RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
104   };
105 
106 struct	buf rrkbuf[NRK];
107 
108 #define	b_cylin	b_resid
109 
110 #ifdef INTRLVE
111 daddr_t	dkblock();
112 #endif
113 
114 int	rkwstart, rkwatch();
115 
116 rkprobe(reg)
117 	caddr_t reg;
118 {
119 	register int br, cvec;
120 
121 #ifdef lint
122 	br = 0; cvec = br; br = cvec;
123 	rkintr(0);
124 #endif
125 	((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
126 	DELAY(10);
127 	((struct rkdevice *)reg)->rkcs1 = RK_CDT;
128 	return (sizeof (struct rkdevice));
129 }
130 
131 rkslave(ui, reg)
132 	struct uba_device *ui;
133 	caddr_t reg;
134 {
135 	register struct rkdevice *rkaddr = (struct rkdevice *)reg;
136 
137 	ui->ui_type = 0;
138 	rkaddr->rkcs1 = RK_CCLR;
139 	rkaddr->rkcs2 = ui->ui_slave;
140 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
141 	rkwait(rkaddr);
142 	DELAY(50);
143 	if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
144 		rkaddr->rkcs1 = RK_CCLR;
145 		return (0);
146 	}
147 	if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) {
148 		ui->ui_type = 1;
149 		rkaddr->rkcs1 = RK_CCLR;
150 	}
151 	return (1);
152 }
153 
154 rkattach(ui)
155 	register struct uba_device *ui;
156 {
157 
158 	if (rkwstart == 0) {
159 		timeout(rkwatch, (caddr_t)0, hz);
160 		rkwstart++;
161 	}
162 	if (ui->ui_dk >= 0)
163 		dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256);
164 	rkip[ui->ui_ctlr][ui->ui_slave] = ui;
165 	rk_softc[ui->ui_ctlr].sc_ndrive++;
166 	rkcyl[ui->ui_unit] = -1;
167 	ui->ui_flags = 0;
168 }
169 
170 rkopen(dev)
171 	dev_t dev;
172 {
173 	register int unit = minor(dev) >> 3;
174 	register struct uba_device *ui;
175 
176 	if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0)
177 		return (ENXIO);
178 	return (0);
179 }
180 
181 rkstrategy(bp)
182 	register struct buf *bp;
183 {
184 	register struct uba_device *ui;
185 	register struct rkst *st;
186 	register int unit;
187 	register struct buf *dp;
188 	int xunit = minor(bp->b_dev) & 07;
189 	long bn, sz;
190 	int s;
191 
192 	sz = (bp->b_bcount+511) >> 9;
193 	unit = dkunit(bp);
194 	if (unit >= NRK)
195 		goto bad;
196 	ui = rkdinfo[unit];
197 	if (ui == 0 || ui->ui_alive == 0)
198 		goto bad;
199 	st = &rkst[ui->ui_type];
200 	if (bp->b_blkno < 0 ||
201 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
202 		goto bad;
203 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
204 	s = spl5();
205 	dp = &rkutab[ui->ui_unit];
206 	disksort(dp, bp);
207 	if (dp->b_active == 0) {
208 		(void) rkustart(ui);
209 		bp = &ui->ui_mi->um_tab;
210 		if (bp->b_actf && bp->b_active == 0)
211 			(void) rkstart(ui->ui_mi);
212 	}
213 	splx(s);
214 	return;
215 
216 bad:
217 	bp->b_flags |= B_ERROR;
218 	iodone(bp);
219 	return;
220 }
221 
222 rkustart(ui)
223 	register struct uba_device *ui;
224 {
225 	register struct buf *bp, *dp;
226 	register struct uba_ctlr *um;
227 	register struct rkdevice *rkaddr;
228 
229 	if (ui == 0)
230 		return;
231 	dk_busy &= ~(1<<ui->ui_dk);
232 	dp = &rkutab[ui->ui_unit];
233 	um = ui->ui_mi;
234 	rkaddr = (struct rkdevice *)um->um_addr;
235 	if (um->um_tab.b_active) {
236 		rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
237 		return;
238 	}
239 	if ((bp = dp->b_actf) == NULL)
240 		return;
241 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
242 	rkaddr->rkcs2 = ui->ui_slave;
243 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
244 	rkwait(rkaddr);
245 	if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
246 		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
247 #ifndef NOBADSECT
248 		struct rkst *st = &rkst[ui->ui_type];
249 		struct buf *bbp = &brkbuf[ui->ui_unit];
250 #endif
251 
252 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
253 		ui->ui_flags = 1;
254 #ifndef NOBADSECT
255 		bbp->b_flags = B_READ|B_BUSY;
256 		bbp->b_dev = bp->b_dev;
257 		bbp->b_bcount = 512;
258 		bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
259 		bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
260 		bbp->b_cylin = st->ncyl - 1;
261 		dp->b_actf = bbp;
262 		bbp->av_forw = bp;
263 		bp = bbp;
264 #endif
265 		rkwait(rkaddr);
266 	}
267 	if (dp->b_active)
268 		goto done;
269 	dp->b_active = 1;
270 	if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
271 		goto done;
272 	if (rk_softc[um->um_ctlr].sc_ndrive == 1)
273 		goto done;
274 	if (bp->b_cylin == rkcyl[ui->ui_unit])
275 		goto done;
276 	rkaddr->rkcyl = bp->b_cylin;
277 	rkcyl[ui->ui_unit] = bp->b_cylin;
278 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
279 	if (ui->ui_dk >= 0) {
280 		dk_busy |= 1<<ui->ui_dk;
281 		dk_seek[ui->ui_dk]++;
282 	}
283 	goto out;
284 done:
285 	if (dp->b_active != 2) {
286 		dp->b_forw = NULL;
287 		if (um->um_tab.b_actf == NULL)
288 			um->um_tab.b_actf = dp;
289 		else
290 			um->um_tab.b_actl->b_forw = dp;
291 		um->um_tab.b_actl = dp;
292 		dp->b_active = 2;
293 	}
294 out:
295 	return;
296 }
297 
298 rkstart(um)
299 	register struct uba_ctlr *um;
300 {
301 	register struct buf *bp, *dp;
302 	register struct uba_device *ui;
303 	register struct rkdevice *rkaddr;
304 	struct rkst *st;
305 	daddr_t bn;
306 	int sn, tn, cmd;
307 
308 loop:
309 	if ((dp = um->um_tab.b_actf) == NULL)
310 		return;
311 	if ((bp = dp->b_actf) == NULL) {
312 		um->um_tab.b_actf = dp->b_forw;
313 		goto loop;
314 	}
315 	um->um_tab.b_active++;
316 	ui = rkdinfo[dkunit(bp)];
317 	bn = dkblock(bp);
318 	st = &rkst[ui->ui_type];
319 	sn = bn%st->nspc;
320 	tn = sn/st->nsect;
321 	sn %= st->nsect;
322 	rkaddr = (struct rkdevice *)ui->ui_addr;
323 retry:
324 	rkaddr->rkcs1 = RK_CCLR;
325 	rkaddr->rkcs2 = ui->ui_slave;
326 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
327 	rkwait(rkaddr);
328 	if ((rkaddr->rkds&RKDS_SVAL) == 0) {
329 		rknosval++;
330 		goto nosval;
331 	}
332 	if (rkaddr->rkds&RKDS_PIP) {
333 		rkpip++;
334 		goto retry;
335 	}
336 	if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
337 		printf("rk%d: not ready", dkunit(bp));
338 		if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
339 			printf("\n");
340 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
341 			rkwait(rkaddr);
342 			rkaddr->rkcs1 = RK_CCLR;
343 			rkwait(rkaddr);
344 			um->um_tab.b_active = 0;
345 			um->um_tab.b_errcnt = 0;
346 			dp->b_actf = bp->av_forw;
347 			dp->b_active = 0;
348 			bp->b_flags |= B_ERROR;
349 			iodone(bp);
350 			goto loop;
351 		}
352 		printf(" (came back!)\n");
353 	}
354 nosval:
355 	rkaddr->rkcyl = bp->b_cylin;
356 	rkcyl[ui->ui_unit] = bp->b_cylin;
357 	rkaddr->rkda = (tn << 8) + sn;
358 	rkaddr->rkwc = -bp->b_bcount / sizeof (short);
359 	if (bp->b_flags & B_READ)
360 		cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
361 	else
362 		cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
363 	um->um_cmd = cmd;
364 	(void) ubago(ui);
365 }
366 
367 rkdgo(um)
368 	register struct uba_ctlr *um;
369 {
370 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
371 
372 	um->um_tab.b_active = 2;	/* should now be 2 */
373 	rkaddr->rkba = um->um_ubinfo;
374 	rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
375 }
376 
377 rkintr(rk11)
378 	int rk11;
379 {
380 	register struct uba_ctlr *um = rkminfo[rk11];
381 	register struct uba_device *ui;
382 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
383 	register struct buf *bp, *dp;
384 	int unit;
385 	struct rk_softc *sc = &rk_softc[um->um_ctlr];
386 	int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
387 
388 	sc->sc_wticks = 0;
389 	sc->sc_softas = 0;
390 	if (um->um_tab.b_active == 2 || sc->sc_recal) {
391 		um->um_tab.b_active = 1;
392 		dp = um->um_tab.b_actf;
393 		bp = dp->b_actf;
394 		ui = rkdinfo[dkunit(bp)];
395 		dk_busy &= ~(1 << ui->ui_dk);
396 #ifndef NOBADSECT
397 		if (bp->b_flags&B_BAD)
398 			if (rkecc(ui, CONT))
399 				return;
400 #endif
401 		if (rkaddr->rkcs1 & RK_CERR) {
402 			int recal;
403 			u_short ds = rkaddr->rkds;
404 			u_short cs2 = rkaddr->rkcs2;
405 			u_short er = rkaddr->rker;
406 #ifdef RKDEBUG
407 			if (rkdebug) {
408 				printf("cs2=%b ds=%b er=%b\n",
409 				    cs2, RKCS2_BITS, ds,
410 				    RKDS_BITS, er, RKER_BITS);
411 			}
412 #endif
413 			if (er & RKER_WLE) {
414 				printf("rk%d: write locked\n", dkunit(bp));
415 				bp->b_flags |= B_ERROR;
416 			} else if (++um->um_tab.b_errcnt > 28 ||
417 			    ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
418 hard:
419 				harderr(bp, "rk");
420 				printf("cs2=%b ds=%b er=%b\n",
421 				    cs2, RKCS2_BITS, ds,
422 				    RKDS_BITS, er, RKER_BITS);
423 				bp->b_flags |= B_ERROR;
424 				sc->sc_recal = 0;
425 			} else if (er & RKER_BSE) {
426 #ifndef NOBADSECT
427 				if (rkecc(ui, BSE))
428 					return;
429 				else
430 #endif
431 					goto hard;
432 			} else {
433 				if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) {
434 					if (rkecc(ui, ECC))
435 						return;
436 				} else
437 					um->um_tab.b_active = 0;
438 			}
439 			if (cs2&RKCS2_MDS) {
440 				rkaddr->rkcs2 = RKCS2_SCLR;
441 				goto retry;
442 			}
443 			recal = 0;
444 			if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
445 			    (um->um_tab.b_errcnt&07) == 4)
446 				recal = 1;
447 			rkaddr->rkcs1 = RK_CCLR;
448 			rkaddr->rkcs2 = ui->ui_slave;
449 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
450 			rkwait(rkaddr);
451 			if (recal && um->um_tab.b_active == 0) {
452 				rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO;
453 				rkcyl[ui->ui_unit] = -1;
454 				sc->sc_recal = 0;
455 				goto nextrecal;
456 			}
457 		}
458 retry:
459 		switch (sc->sc_recal) {
460 
461 		case 1:
462 			rkaddr->rkcyl = bp->b_cylin;
463 			rkcyl[ui->ui_unit] = bp->b_cylin;
464 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
465 			goto nextrecal;
466 		case 2:
467 			if (um->um_tab.b_errcnt < 16 ||
468 			    (bp->b_flags&B_READ) == 0)
469 				goto donerecal;
470 			rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
471 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO;
472 			/* fall into ... */
473 		nextrecal:
474 			sc->sc_recal++;
475 			rkwait(rkaddr);
476 			um->um_tab.b_active = 1;
477 			return;
478 		donerecal:
479 		case 3:
480 			sc->sc_recal = 0;
481 			um->um_tab.b_active = 0;
482 			break;
483 		}
484 		ubadone(um);
485 		if (um->um_tab.b_active) {
486 			um->um_tab.b_active = 0;
487 			um->um_tab.b_errcnt = 0;
488 			um->um_tab.b_actf = dp->b_forw;
489 			dp->b_active = 0;
490 			dp->b_errcnt = 0;
491 			dp->b_actf = bp->av_forw;
492 			bp->b_resid = -rkaddr->rkwc * sizeof(short);
493 			iodone(bp);
494 			if (dp->b_actf)
495 				rkustart(ui);
496 		}
497 		as &= ~(1<<ui->ui_slave);
498 	}
499 	for (unit = 0; as; as >>= 1, unit++)
500 		if (as & 1) {
501 			ui = rkip[rk11][unit];
502 			if (ui) {
503 				rkustart(rkip[rk11][unit]);
504 			} else {
505 				rkaddr->rkcs1 = RK_CCLR;
506 				rkaddr->rkcs2 = unit;
507 				rkaddr->rkcs1 = RK_DCLR|RK_GO;
508 				rkwait(rkaddr);
509 				rkaddr->rkcs1 = RK_CCLR;
510 			}
511 		}
512 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
513 		rkstart(um);
514 	if (((rkaddr->rkcs1) & RK_IE) == 0)
515 		rkaddr->rkcs1 = RK_IE;
516 }
517 
518 rkwait(addr)
519 	register struct rkdevice *addr;
520 {
521 
522 	while ((addr->rkcs1 & RK_CRDY) == 0)
523 		;
524 }
525 
526 rkread(dev, uio)
527 	dev_t dev;
528 	struct uio *uio;
529 {
530 	register int unit = minor(dev) >> 3;
531 
532 	if (unit >= NRK)
533 		return (ENXIO);
534 	return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio));
535 }
536 
537 rkwrite(dev, uio)
538 	dev_t dev;
539 	struct uio *uio;
540 {
541 	register int unit = minor(dev) >> 3;
542 
543 	if (unit >= NRK)
544 		return (ENXIO);
545 	return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio));
546 }
547 
548 rkecc(ui, flag)
549 	register struct uba_device *ui;
550 {
551 	register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
552 	register struct buf *bp = rkutab[ui->ui_unit].b_actf;
553 	register struct uba_ctlr *um = ui->ui_mi;
554 	register struct rkst *st;
555 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
556 	caddr_t addr;
557 	int reg, npf, o, cmd, ubaddr;
558 	int bn, cn, tn, sn;
559 
560 #ifndef NOBADSECT
561 	if (flag == CONT)
562 		npf = bp->b_error;
563 	else
564 #endif
565 		npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount);
566 	reg = btop(um->um_ubinfo&0x3ffff) + npf;
567 	o = (int)bp->b_un.b_addr & PGOFSET;
568 	bn = dkblock(bp);
569 	st = &rkst[ui->ui_type];
570 	cn = bp->b_cylin;
571 	sn = bn%st->nspc + npf;
572 	tn = sn/st->nsect;
573 	sn %= st->nsect;
574 	cn += tn/st->ntrak;
575 	tn %= st->ntrak;
576 	ubapurge(um);
577 	switch (flag) {
578 	case ECC:
579 		{
580 		register int i;
581 		int bit, byte, mask;
582 
583 		npf--;
584 		reg--;
585 		printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
586 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
587 		mask = rk->rkec2;
588 		i = rk->rkec1 - 1;		/* -1 makes 0 origin */
589 		bit = i&07;
590 		i = (i&~07)>>3;
591 		byte = i + o;
592 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
593 			addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
594 			    (byte & PGOFSET);
595 			putmemc(addr, getmemc(addr)^(mask<<bit));
596 			byte++;
597 			i++;
598 			bit -= 8;
599 		}
600 		if (rk->rkwc == 0) {
601 			um->um_tab.b_active = 0;
602 			return (0);
603 		}
604 		npf++;
605 		reg++;
606 		break;
607 		}
608 
609 #ifndef NOBADSECT
610 	case BSE:
611 #ifdef RKBDEBUG
612 		if (rkbdebug)
613 	printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
614 #endif
615 		if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
616 			return(0);
617 		bp->b_flags |= B_BAD;
618 		bp->b_error = npf + 1;
619 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
620 		cn = bn/st->nspc;
621 		sn = bn%st->nspc;
622 		tn = sn/st->nsect;
623 		sn %= st->nsect;
624 #ifdef RKBDEBUG
625 		if (rkbdebug)
626 	printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
627 #endif
628 		rk->rkwc = -(512 / sizeof (short));
629 		break;
630 
631 	case CONT:
632 #ifdef RKBDEBUG
633 		if (rkbdebug)
634 	printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
635 #endif
636 		bp->b_flags &= ~B_BAD;
637 		rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short));
638 		if (rk->rkwc == 0) {
639 			um->um_tab.b_active = 0;
640 			return (0);
641 		}
642 		break;
643 #endif
644 	}
645 	rk->rkcs1 = RK_CCLR;
646 	rk->rkcs2 = ui->ui_slave;
647 	rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
648 	rkwait(rk);
649 	rk->rkcyl = cn;
650 	rk->rkda = (tn << 8) | sn;
651 	ubaddr = (int)ptob(reg) + o;
652 	rk->rkba = ubaddr;
653 	cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO;
654 	cmd |= (ubaddr >> 8) & 0x300;
655 	cmd |= rktypes[ui->ui_type];
656 	rk->rkcs1 = cmd;
657 	um->um_tab.b_active = 2;	/* continuing */
658 	um->um_tab.b_errcnt = 0;	/* error has been corrected */
659 	return (1);
660 }
661 
662 rkreset(uban)
663 	int uban;
664 {
665 	register struct uba_ctlr *um;
666 	register struct uba_device *ui;
667 	register rk11, unit;
668 
669 	for (rk11 = 0; rk11 < NHK; rk11++) {
670 		if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
671 		    um->um_alive == 0)
672 			continue;
673 		printf(" hk%d", rk11);
674 		um->um_tab.b_active = 0;
675 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
676 		rk_softc[um->um_ctlr].sc_recal = 0;
677 		rk_softc[um->um_ctlr].sc_wticks = 0;
678 		if (um->um_ubinfo) {
679 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
680 			um->um_ubinfo = 0;
681 		}
682 		for (unit = 0; unit < NRK; unit++) {
683 			if ((ui = rkdinfo[unit]) == 0)
684 				continue;
685 			if (ui->ui_alive == 0 || ui->ui_mi != um)
686 				continue;
687 			rkutab[unit].b_active = 0;
688 			(void) rkustart(ui);
689 		}
690 		(void) rkstart(um);
691 	}
692 }
693 
694 rkwatch()
695 {
696 	register struct uba_ctlr *um;
697 	register rk11, unit;
698 	register struct rk_softc *sc;
699 
700 	timeout(rkwatch, (caddr_t)0, hz);
701 	for (rk11 = 0; rk11 < NHK; rk11++) {
702 		um = rkminfo[rk11];
703 		if (um == 0 || um->um_alive == 0)
704 			continue;
705 		sc = &rk_softc[rk11];
706 		if (um->um_tab.b_active == 0) {
707 			for (unit = 0; unit < NRK; unit++)
708 				if (rkutab[unit].b_active &&
709 				    rkdinfo[unit]->ui_mi == um)
710 					goto active;
711 			sc->sc_wticks = 0;
712 			continue;
713 		}
714 active:
715 		sc->sc_wticks++;
716 		if (sc->sc_wticks >= 20) {
717 			sc->sc_wticks = 0;
718 			printf("hk%d: lost interrupt\n", rk11);
719 			ubareset(um->um_ubanum);
720 		}
721 	}
722 }
723 
724 #define	DBSIZE	20
725 
726 rkdump(dev)
727 	dev_t dev;
728 {
729 	struct rkdevice *rkaddr;
730 	char *start;
731 	int num, blk, unit;
732 	struct size *sizes;
733 	register struct uba_regs *uba;
734 	register struct uba_device *ui;
735 	register short *rp;
736 	struct rkst *st;
737 
738 	unit = minor(dev) >> 3;
739 	if (unit >= NRK)
740 		return (ENXIO);
741 #define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
742 	ui = phys(struct uba_device *, rkdinfo[unit]);
743 	if (ui->ui_alive == 0)
744 		return (ENXIO);
745 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
746 	ubainit(uba);
747 	rkaddr = (struct rkdevice *)ui->ui_physaddr;
748 	num = maxfree;
749 	start = 0;
750 	rkaddr->rkcs1 = RK_CCLR;
751 	rkaddr->rkcs2 = unit;
752 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
753 	rkwait(rkaddr);
754 	if ((rkaddr->rkds & RKDS_VV) == 0) {
755 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
756 		rkwait(rkaddr);
757 	}
758 	st = &rkst[ui->ui_type];
759 	sizes = phys(struct size *, st->sizes);
760 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
761 		return (EINVAL);
762 	while (num > 0) {
763 		register struct pte *io;
764 		register int i;
765 		int cn, sn, tn;
766 		daddr_t bn;
767 
768 		blk = num > DBSIZE ? DBSIZE : num;
769 		io = uba->uba_map;
770 		for (i = 0; i < blk; i++)
771 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
772 		*(int *)io = 0;
773 		bn = dumplo + btop(start);
774 		cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
775 		sn = bn%st->nspc;
776 		tn = sn/st->nsect;
777 		sn = sn%st->nsect;
778 		rkaddr->rkcyl = cn;
779 		rp = (short *) &rkaddr->rkda;
780 		*rp = (tn << 8) + sn;
781 		*--rp = 0;
782 		*--rp = -blk*NBPG / sizeof (short);
783 		*--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
784 		rkwait(rkaddr);
785 		if (rkaddr->rkcs1 & RK_CERR)
786 			return (EIO);
787 		start += blk*NBPG;
788 		num -= blk;
789 	}
790 	return (0);
791 }
792 #endif
793