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