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