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