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