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