xref: /csrg-svn/sys/vax/uba/rk.c (revision 7182)
1 #define	RKDEBUG
2 #define RKBDEBUG
3 /*	rk.c	4.41	82/06/14	*/
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 
39 #include "../h/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 (1);
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 rkstrategy(bp)
171 	register struct buf *bp;
172 {
173 	register struct uba_device *ui;
174 	register struct rkst *st;
175 	register int unit;
176 	register struct buf *dp;
177 	int xunit = minor(bp->b_dev) & 07;
178 	long bn, sz;
179 	int s;
180 
181 	sz = (bp->b_bcount+511) >> 9;
182 	unit = dkunit(bp);
183 	if (unit >= NRK)
184 		goto bad;
185 	ui = rkdinfo[unit];
186 	if (ui == 0 || ui->ui_alive == 0)
187 		goto bad;
188 	st = &rkst[ui->ui_type];
189 	if (bp->b_blkno < 0 ||
190 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
191 		goto bad;
192 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
193 	s = spl5();
194 	dp = &rkutab[ui->ui_unit];
195 	disksort(dp, bp);
196 	if (dp->b_active == 0) {
197 		(void) rkustart(ui);
198 		bp = &ui->ui_mi->um_tab;
199 		if (bp->b_actf && bp->b_active == 0)
200 			(void) rkstart(ui->ui_mi);
201 	}
202 	splx(s);
203 	return;
204 
205 bad:
206 	bp->b_flags |= B_ERROR;
207 	iodone(bp);
208 	return;
209 }
210 
211 rkustart(ui)
212 	register struct uba_device *ui;
213 {
214 	register struct buf *bp, *dp;
215 	register struct uba_ctlr *um;
216 	register struct rkdevice *rkaddr;
217 
218 	if (ui == 0)
219 		return;
220 	dk_busy &= ~(1<<ui->ui_dk);
221 	dp = &rkutab[ui->ui_unit];
222 	um = ui->ui_mi;
223 	rkaddr = (struct rkdevice *)um->um_addr;
224 	if (um->um_tab.b_active) {
225 		rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
226 		return;
227 	}
228 	if ((bp = dp->b_actf) == NULL)
229 		return;
230 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
231 	rkaddr->rkcs2 = ui->ui_slave;
232 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
233 	rkwait(rkaddr);
234 	if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
235 		/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
236 #ifndef NOBADSECT
237 		struct rkst *st = &rkst[ui->ui_type];
238 		struct buf *bbp = &brkbuf[ui->ui_unit];
239 #endif
240 
241 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
242 		ui->ui_flags = 1;
243 #ifndef NOBADSECT
244 		bbp->b_flags = B_READ|B_BUSY;
245 		bbp->b_dev = bp->b_dev;
246 		bbp->b_bcount = 512;
247 		bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
248 		bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
249 		bbp->b_cylin = st->ncyl - 1;
250 		dp->b_actf = bbp;
251 		bbp->av_forw = bp;
252 		bp = bbp;
253 #endif
254 		rkwait(rkaddr);
255 	}
256 	if (dp->b_active)
257 		goto done;
258 	dp->b_active = 1;
259 	if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
260 		goto done;
261 	if (rk_softc[um->um_ctlr].sc_ndrive == 1)
262 		goto done;
263 	if (bp->b_cylin == rkcyl[ui->ui_unit])
264 		goto done;
265 	rkaddr->rkcyl = bp->b_cylin;
266 	rkcyl[ui->ui_unit] = bp->b_cylin;
267 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
268 	if (ui->ui_dk >= 0) {
269 		dk_busy |= 1<<ui->ui_dk;
270 		dk_seek[ui->ui_dk]++;
271 	}
272 	goto out;
273 done:
274 	if (dp->b_active != 2) {
275 		dp->b_forw = NULL;
276 		if (um->um_tab.b_actf == NULL)
277 			um->um_tab.b_actf = dp;
278 		else
279 			um->um_tab.b_actl->b_forw = dp;
280 		um->um_tab.b_actl = dp;
281 		dp->b_active = 2;
282 	}
283 out:
284 	return;
285 }
286 
287 rkstart(um)
288 	register struct uba_ctlr *um;
289 {
290 	register struct buf *bp, *dp;
291 	register struct uba_device *ui;
292 	register struct rkdevice *rkaddr;
293 	struct rkst *st;
294 	daddr_t bn;
295 	int sn, tn, cmd;
296 
297 loop:
298 	if ((dp = um->um_tab.b_actf) == NULL)
299 		return;
300 	if ((bp = dp->b_actf) == NULL) {
301 		um->um_tab.b_actf = dp->b_forw;
302 		goto loop;
303 	}
304 	um->um_tab.b_active++;
305 	ui = rkdinfo[dkunit(bp)];
306 	bn = dkblock(bp);
307 	st = &rkst[ui->ui_type];
308 	sn = bn%st->nspc;
309 	tn = sn/st->nsect;
310 	sn %= st->nsect;
311 	rkaddr = (struct rkdevice *)ui->ui_addr;
312 retry:
313 	rkaddr->rkcs1 = RK_CCLR;
314 	rkaddr->rkcs2 = ui->ui_slave;
315 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
316 	rkwait(rkaddr);
317 	if ((rkaddr->rkds&RKDS_SVAL) == 0) {
318 		rknosval++;
319 		goto nosval;
320 	}
321 	if (rkaddr->rkds&RKDS_PIP) {
322 		rkpip++;
323 		goto retry;
324 	}
325 	if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
326 		printf("rk%d: not ready", dkunit(bp));
327 		if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
328 			printf("\n");
329 			rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
330 			rkwait(rkaddr);
331 			rkaddr->rkcs1 = RK_CCLR;
332 			rkwait(rkaddr);
333 			um->um_tab.b_active = 0;
334 			um->um_tab.b_errcnt = 0;
335 			dp->b_actf = bp->av_forw;
336 			dp->b_active = 0;
337 			bp->b_flags |= B_ERROR;
338 			iodone(bp);
339 			goto loop;
340 		}
341 		printf(" (came back!)\n");
342 	}
343 nosval:
344 	rkaddr->rkcyl = bp->b_cylin;
345 	rkcyl[ui->ui_unit] = bp->b_cylin;
346 	rkaddr->rkda = (tn << 8) + sn;
347 	rkaddr->rkwc = -bp->b_bcount / sizeof (short);
348 	if (bp->b_flags & B_READ)
349 		cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
350 	else
351 		cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
352 	um->um_cmd = cmd;
353 	(void) ubago(ui);
354 }
355 
356 rkdgo(um)
357 	register struct uba_ctlr *um;
358 {
359 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
360 
361 	um->um_tab.b_active = 2;	/* should now be 2 */
362 	rkaddr->rkba = um->um_ubinfo;
363 	rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
364 }
365 
366 rkintr(rk11)
367 	int rk11;
368 {
369 	register struct uba_ctlr *um = rkminfo[rk11];
370 	register struct uba_device *ui;
371 	register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
372 	register struct buf *bp, *dp;
373 	int unit;
374 	struct rk_softc *sc = &rk_softc[um->um_ctlr];
375 	int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
376 	int needie = 1;
377 
378 	sc->sc_wticks = 0;
379 	sc->sc_softas = 0;
380 	if (um->um_tab.b_active == 2 || sc->sc_recal) {
381 		um->um_tab.b_active = 1;
382 		dp = um->um_tab.b_actf;
383 		bp = dp->b_actf;
384 		ui = rkdinfo[dkunit(bp)];
385 		dk_busy &= ~(1 << ui->ui_dk);
386 #ifndef NOBADSECT
387 		if (bp->b_flags&B_BAD)
388 			if (rkecc(ui, CONT))
389 				return;
390 #endif
391 		if (rkaddr->rkcs1 & RK_CERR) {
392 			int recal;
393 			u_short ds = rkaddr->rkds;
394 			u_short cs2 = rkaddr->rkcs2;
395 			u_short er = rkaddr->rker;
396 #ifdef RKDEBUG
397 			if (rkdebug) {
398 				printf("cs2=%b ds=%b er=%b\n",
399 				    cs2, RKCS2_BITS, ds,
400 				    RKDS_BITS, er, RKER_BITS);
401 			}
402 #endif
403 			if (er & RKER_WLE) {
404 				printf("rk%d: write locked\n", dkunit(bp));
405 				bp->b_flags |= B_ERROR;
406 			} else if (++um->um_tab.b_errcnt > 28 ||
407 			    ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
408 hard:
409 				harderr(bp, "rk");
410 				printf("cs2=%b ds=%b er=%b\n",
411 				    cs2, RKCS2_BITS, ds,
412 				    RKDS_BITS, er, RKER_BITS);
413 				bp->b_flags |= B_ERROR;
414 				sc->sc_recal = 0;
415 			} else if (er & RKER_BSE) {
416 #ifndef NOBADSECT
417 				if (rkecc(ui, BSE))
418 					return;
419 				else
420 #endif
421 					goto hard;
422 			} else {
423 				if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) {
424 					if (rkecc(ui, ECC))
425 						return;
426 				} else
427 					um->um_tab.b_active = 0;
428 			}
429 			if (cs2&RKCS2_MDS) {
430 				rkaddr->rkcs2 = RKCS2_SCLR;
431 				goto retry;
432 			}
433 			recal = 0;
434 			if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
435 			    (um->um_tab.b_errcnt&07) == 4)
436 				recal = 1;
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 				rkustart(ui);
486 		}
487 		as &= ~(1<<ui->ui_slave);
488 	}
489 	for (unit = 0; as; as >>= 1, unit++)
490 		if (as & 1) {
491 			ui = rkip[rk11][unit];
492 			if (ui) {
493 				rkustart(rkip[rk11][unit]);
494 			} else {
495 				rkaddr->rkcs1 = RK_CCLR;
496 				rkaddr->rkcs2 = unit;
497 				rkaddr->rkcs1 = RK_DCLR|RK_GO;
498 				rkwait(rkaddr);
499 				rkaddr->rkcs1 = RK_CCLR;
500 			}
501 		}
502 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
503 		rkstart(um);
504 	if (((needie = rkaddr->rkcs1) & RK_IE) == 0)
505 		rkaddr->rkcs1 = RK_IE;
506 }
507 
508 rkwait(addr)
509 	register struct rkdevice *addr;
510 {
511 
512 	while ((addr->rkcs1 & RK_CRDY) == 0)
513 		;
514 }
515 
516 rkread(dev)
517 	dev_t dev;
518 {
519 	register int unit = minor(dev) >> 3;
520 
521 	if (unit >= NRK)
522 		u.u_error = ENXIO;
523 	else
524 		physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys);
525 }
526 
527 rkwrite(dev)
528 	dev_t dev;
529 {
530 	register int unit = minor(dev) >> 3;
531 
532 	if (unit >= NRK)
533 		u.u_error = ENXIO;
534 	else
535 		physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys);
536 }
537 
538 rkecc(ui, flag)
539 	register struct uba_device *ui;
540 {
541 	register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
542 	register struct buf *bp = rkutab[ui->ui_unit].b_actf;
543 	register struct uba_ctlr *um = ui->ui_mi;
544 	register struct rkst *st;
545 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
546 	caddr_t addr;
547 	int reg, npf, o, cmd, ubaddr;
548 	int bn, cn, tn, sn;
549 
550 #ifndef NOBADSECT
551 	if (flag == CONT)
552 		npf = bp->b_error;
553 	else
554 #endif
555 		npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount);
556 	reg = btop(um->um_ubinfo&0x3ffff) + npf;
557 	o = (int)bp->b_un.b_addr & PGOFSET;
558 	bn = dkblock(bp);
559 	st = &rkst[ui->ui_type];
560 	cn = bp->b_cylin;
561 	sn = bn%st->nspc + npf;
562 	tn = sn/st->nsect;
563 	sn %= st->nsect;
564 	cn += tn/st->ntrak;
565 	tn %= st->ntrak;
566 	ubapurge(um);
567 	switch (flag) {
568 	case ECC:
569 		{
570 		register int i;
571 		int bit, byte, mask;
572 
573 		npf--;
574 		reg--;
575 		printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
576 		    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
577 		mask = rk->rkec2;
578 		i = rk->rkec1 - 1;		/* -1 makes 0 origin */
579 		bit = i&07;
580 		i = (i&~07)>>3;
581 		byte = i + o;
582 		while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
583 			addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
584 			    (byte & PGOFSET);
585 			putmemc(addr, getmemc(addr)^(mask<<bit));
586 			byte++;
587 			i++;
588 			bit -= 8;
589 		}
590 		if (rk->rkwc == 0) {
591 			um->um_tab.b_active = 0;
592 			return (0);
593 		}
594 		npf++;
595 		reg++;
596 		break;
597 		}
598 
599 #ifndef NOBADSECT
600 	case BSE:
601 #ifdef RKBDEBUG
602 		if (rkbdebug)
603 	printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
604 #endif
605 		if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
606 			return(0);
607 		bp->b_flags |= B_BAD;
608 		bp->b_error = npf + 1;
609 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
610 		cn = bn/st->nspc;
611 		sn = bn%st->nspc;
612 		tn = sn/st->nsect;
613 		sn %= st->nsect;
614 #ifdef RKBDEBUG
615 		if (rkbdebug)
616 	printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
617 #endif
618 		rk->rkwc = -(512 / sizeof (short));
619 		break;
620 
621 	case CONT:
622 #ifdef RKBDEBUG
623 		if (rkbdebug)
624 	printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
625 #endif
626 		bp->b_flags &= ~B_BAD;
627 		rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short));
628 		if (rk->rkwc == 0) {
629 			um->um_tab.b_active = 0;
630 			return (0);
631 		}
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_active = 2;	/* continuing */
648 	um->um_tab.b_errcnt = 0;	/* error has been corrected */
649 	return (1);
650 }
651 
652 rkreset(uban)
653 	int uban;
654 {
655 	register struct uba_ctlr *um;
656 	register struct uba_device *ui;
657 	register rk11, unit;
658 
659 	for (rk11 = 0; rk11 < NHK; rk11++) {
660 		if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
661 		    um->um_alive == 0)
662 			continue;
663 		printf(" hk%d", rk11);
664 		um->um_tab.b_active = 0;
665 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
666 		rk_softc[um->um_ctlr].sc_recal = 0;
667 		rk_softc[um->um_ctlr].sc_wticks = 0;
668 		if (um->um_ubinfo) {
669 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
670 			ubadone(um);
671 		}
672 		for (unit = 0; unit < NRK; unit++) {
673 			if ((ui = rkdinfo[unit]) == 0)
674 				continue;
675 			if (ui->ui_alive == 0 || ui->ui_mi != um)
676 				continue;
677 			rkutab[unit].b_active = 0;
678 			(void) rkustart(ui);
679 		}
680 		(void) rkstart(um);
681 	}
682 }
683 
684 rkwatch()
685 {
686 	register struct uba_ctlr *um;
687 	register rk11, unit;
688 	register struct rk_softc *sc;
689 
690 	timeout(rkwatch, (caddr_t)0, hz);
691 	for (rk11 = 0; rk11 < NHK; rk11++) {
692 		um = rkminfo[rk11];
693 		if (um == 0 || um->um_alive == 0)
694 			continue;
695 		sc = &rk_softc[rk11];
696 		if (um->um_tab.b_active == 0) {
697 			for (unit = 0; unit < NRK; unit++)
698 				if (rkutab[unit].b_active &&
699 				    rkdinfo[unit]->ui_mi == um)
700 					goto active;
701 			sc->sc_wticks = 0;
702 			continue;
703 		}
704 active:
705 		sc->sc_wticks++;
706 		if (sc->sc_wticks >= 20) {
707 			sc->sc_wticks = 0;
708 			printf("hk%d: lost interrupt\n", rk11);
709 			ubareset(um->um_ubanum);
710 		}
711 	}
712 }
713 
714 #define	DBSIZE	20
715 
716 rkdump(dev)
717 	dev_t dev;
718 {
719 	struct rkdevice *rkaddr;
720 	char *start;
721 	int num, blk, unit;
722 	struct size *sizes;
723 	register struct uba_regs *uba;
724 	register struct uba_device *ui;
725 	register short *rp;
726 	struct rkst *st;
727 
728 	unit = minor(dev) >> 3;
729 	if (unit >= NRK)
730 		return (ENXIO);
731 #define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
732 	ui = phys(struct uba_device *, rkdinfo[unit]);
733 	if (ui->ui_alive == 0)
734 		return (ENXIO);
735 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
736 	ubainit(uba);
737 	rkaddr = (struct rkdevice *)ui->ui_physaddr;
738 	num = maxfree;
739 	start = 0;
740 	rkaddr->rkcs1 = RK_CCLR;
741 	rkaddr->rkcs2 = unit;
742 	rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
743 	rkwait(rkaddr);
744 	if ((rkaddr->rkds & RKDS_VV) == 0) {
745 		rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
746 		rkwait(rkaddr);
747 	}
748 	st = &rkst[ui->ui_type];
749 	sizes = phys(struct size *, st->sizes);
750 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
751 		return (EINVAL);
752 	while (num > 0) {
753 		register struct pte *io;
754 		register int i;
755 		int cn, sn, tn;
756 		daddr_t bn;
757 
758 		blk = num > DBSIZE ? DBSIZE : num;
759 		io = uba->uba_map;
760 		for (i = 0; i < blk; i++)
761 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
762 		*(int *)io = 0;
763 		bn = dumplo + btop(start);
764 		cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
765 		sn = bn%st->nspc;
766 		tn = sn/st->nsect;
767 		sn = sn%st->nsect;
768 		rkaddr->rkcyl = cn;
769 		rp = (short *) &rkaddr->rkda;
770 		*rp = (tn << 8) + sn;
771 		*--rp = 0;
772 		*--rp = -blk*NBPG / sizeof (short);
773 		*--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
774 		rkwait(rkaddr);
775 		if (rkaddr->rkcs1 & RK_CERR)
776 			return (EIO);
777 		start += blk*NBPG;
778 		num -= blk;
779 	}
780 	return (0);
781 }
782 #endif
783