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