xref: /csrg-svn/sys/vax/uba/rk.c (revision 3129)
1 /*	rk.c	4.26	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 				bp->b_flags |= B_ERROR;
352 				harderr(bp, "rk");
353 				printf("cs2=%b ds=%b er=%b\n",
354 				    cs2, RKCS2_BITS, ds,
355 				    RKDS_BITS, er, RKER_BITS);
356 			} else
357 				um->um_tab.b_active = 0;
358 			if (cs2&RK_MDS) {
359 				rkaddr->rkcs2 = RK_SCLR;
360 				goto retry;
361 			}
362 			recal = 0;
363 			if (ds&RK_DROT || er&(RK_OPI|RK_SKI|RK_UNS) ||
364 			    (um->um_tab.b_errcnt&07) == 4)
365 				recal = 1;
366 			if ((er & (RK_DCK|RK_ECH)) == RK_DCK)
367 				if (rkecc(ui))
368 					return;
369 			rkaddr->rkcs1 = RK_CDT|RK_CCLR;
370 			rkaddr->rkcs2 = ui->ui_slave;
371 			rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
372 			rkwait(rkaddr);
373 			if (recal && um->um_tab.b_active == 0) {
374 				rkaddr->rkcs1 = RK_CDT|RK_IE|RK_RECAL|RK_GO;
375 				rkcyl[ui->ui_unit] = -1;
376 				sc->sc_recal = 0;
377 				goto nextrecal;
378 			}
379 		}
380 retry:
381 		switch (sc->sc_recal) {
382 
383 		case 1:
384 			rkaddr->rkcyl = bp->b_cylin;
385 			rkcyl[ui->ui_unit] = bp->b_cylin;
386 			rkaddr->rkcs1 = RK_CDT|RK_IE|RK_SEEK|RK_GO;
387 			goto nextrecal;
388 
389 		case 2:
390 			if (um->um_tab.b_errcnt < 16 ||
391 			    (bp->b_flags&B_READ) != 0)
392 				break;
393 			rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
394 			rkaddr->rkcs1 = RK_CDT|RK_IE|RK_OFFSET|RK_GO;
395 			/* fall into ... */
396 		nextrecal:
397 			sc->sc_recal++;
398 			rkwait(rkaddr);
399 			um->um_tab.b_active = 1;
400 			return;
401 
402 		case 3:
403 			sc->sc_recal = 0;
404 			um->um_tab.b_active = 0;
405 			break;
406 		}
407 		if (um->um_tab.b_active) {
408 			um->um_tab.b_active = 0;
409 			um->um_tab.b_errcnt = 0;
410 			um->um_tab.b_actf = dp->b_forw;
411 			dp->b_active = 0;
412 			dp->b_errcnt = 0;
413 			dp->b_actf = bp->av_forw;
414 			bp->b_resid = -rkaddr->rkwc * sizeof(short);
415 			iodone(bp);
416 			if (dp->b_actf)
417 				if (rkustart(ui))
418 					needie = 0;
419 		}
420 		as &= ~(1<<ui->ui_slave);
421 	}
422 	for (unit = 0; as; as >>= 1, unit++)
423 		if (as & 1) {
424 			ui = rkip[rk11][unit];
425 			if (ui) {
426 				if (rkustart(rkip[rk11][unit]))
427 					needie = 0;
428 			} else {
429 				rkaddr->rkcs1 = RK_CERR|RK_CDT;
430 				rkaddr->rkcs2 = unit;
431 				rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
432 				rkwait(rkaddr);
433 			}
434 		}
435 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
436 		if (rkstart(um))
437 			needie = 0;
438 	if (needie)
439 		rkaddr->rkcs1 = RK_CDT|RK_IE;
440 }
441 
442 rkwait(addr)
443 	register struct rkdevice *addr;
444 {
445 
446 	while ((addr->rkcs1 & RK_CRDY) == 0)
447 		;
448 }
449 
450 rkread(dev)
451 	dev_t dev;
452 {
453 	register int unit = minor(dev) >> 3;
454 
455 	if (unit >= NRK)
456 		u.u_error = ENXIO;
457 	else
458 		physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys);
459 }
460 
461 rkwrite(dev)
462 	dev_t dev;
463 {
464 	register int unit = minor(dev) >> 3;
465 
466 	if (unit >= NRK)
467 		u.u_error = ENXIO;
468 	else
469 		physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys);
470 }
471 
472 rkecc(ui)
473 	register struct uba_device *ui;
474 {
475 	register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
476 	register struct buf *bp = rkutab[ui->ui_unit].b_actf;
477 	register struct uba_ctlr *um = ui->ui_mi;
478 	register struct rkst *st;
479 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
480 	register int i;
481 	caddr_t addr;
482 	int reg, bit, byte, npf, mask, o, cmd, ubaddr;
483 	int bn, cn, tn, sn;
484 
485 	npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount) - 1;
486 	reg = btop(um->um_ubinfo&0x3ffff) + npf;
487 	o = (int)bp->b_un.b_addr & PGOFSET;
488 	printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
489 	    'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
490 	mask = rk->rkec2;
491 	ubapurge(um);
492 	i = rk->rkec1 - 1;		/* -1 makes 0 origin */
493 	bit = i&07;
494 	i = (i&~07)>>3;
495 	byte = i + o;
496 	while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
497 		addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
498 		    (byte & PGOFSET);
499 		putmemc(addr, getmemc(addr)^(mask<<bit));
500 		byte++;
501 		i++;
502 		bit -= 8;
503 	}
504 	um->um_tab.b_active++;	/* Either complete or continuing... */
505 	if (rk->rkwc == 0)
506 		return (0);
507 #ifdef notdef
508 	rk->rkcs1 |= RK_GO;
509 #else
510 	rk->rkcs1 = RK_CDT|RK_CCLR;
511 	rk->rkcs2 = ui->ui_slave;
512 	rk->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
513 	rkwait(rk);
514 	bn = dkblock(bp);
515 	st = &rkst[ui->ui_type];
516 	cn = bp->b_cylin;
517 	sn = bn%st->nspc + npf + 1;
518 	tn = sn/st->nsect;
519 	sn %= st->nsect;
520 	cn += tn/st->ntrak;
521 	tn %= st->ntrak;
522 	rk->rkcyl = cn;
523 	rk->rkda = (tn << 8) | sn;
524 	ubaddr = (int)ptob(reg+1) + o;
525 	rk->rkba = ubaddr;
526 	cmd = (ubaddr >> 8) & 0x300;
527 	cmd |= RK_CDT|RK_IE|RK_GO|RK_READ;
528 	rk->rkcs1 = cmd;
529 #endif
530 	return (1);
531 }
532 
533 rkreset(uban)
534 	int uban;
535 {
536 	register struct uba_ctlr *um;
537 	register struct uba_device *ui;
538 	register rk11, unit;
539 
540 	for (rk11 = 0; rk11 < NHK; rk11++) {
541 		if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
542 		    um->um_alive == 0)
543 			continue;
544 		printf(" hk%d", rk11);
545 		um->um_tab.b_active = 0;
546 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
547 		rk_softc[um->um_ctlr].sc_recal = 0;
548 		if (um->um_ubinfo) {
549 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
550 			ubadone(um);
551 		}
552 		for (unit = 0; unit < NHK; unit++) {
553 			if ((ui = rkdinfo[unit]) == 0)
554 				continue;
555 			if (ui->ui_alive == 0)
556 				continue;
557 			rkutab[unit].b_active = 0;
558 			(void) rkustart(ui);
559 		}
560 		(void) rkstart(um);
561 	}
562 }
563 
564 rkwatch()
565 {
566 	register struct uba_ctlr *um;
567 	register rk11, unit;
568 	register struct rk_softc *sc;
569 
570 	timeout(rkwatch, (caddr_t)0, hz);
571 	for (rk11 = 0; rk11 < NHK; rk11++) {
572 		um = rkminfo[rk11];
573 		if (um == 0 || um->um_alive == 0)
574 			continue;
575 		sc = &rk_softc[rk11];
576 		if (um->um_tab.b_active == 0) {
577 			for (unit = 0; unit < NRK; unit++)
578 				if (rkutab[unit].b_active &&
579 				    rkdinfo[unit]->ui_mi == um)
580 					goto active;
581 			sc->sc_wticks = 0;
582 			continue;
583 		}
584 active:
585 		sc->sc_wticks++;
586 		if (sc->sc_wticks >= 20) {
587 			sc->sc_wticks = 0;
588 			printf("hk%d: lost interrupt\n", rk11);
589 			ubareset(um->um_ubanum);
590 		}
591 	}
592 }
593 
594 #define	DBSIZE	20
595 
596 rkdump(dev)
597 	dev_t dev;
598 {
599 	struct rkdevice *rkaddr;
600 	char *start;
601 	int num, blk, unit;
602 	struct size *sizes;
603 	register struct uba_regs *uba;
604 	register struct uba_device *ui;
605 	register short *rp;
606 	struct rkst *st;
607 
608 	unit = minor(dev) >> 3;
609 	if (unit >= NRK)
610 		return (ENXIO);
611 #define	phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
612 	ui = phys(struct uba_device *, rkdinfo[unit]);
613 	if (ui->ui_alive == 0)
614 		return (ENXIO);
615 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
616 #if VAX780
617 	if (cpu == VAX_780)
618 		ubainit(uba);
619 #endif
620 	rkaddr = (struct rkdevice *)ui->ui_physaddr;
621 	num = maxfree;
622 	start = 0;
623 	rkaddr->rkcs1 = RK_CDT|RK_CERR;
624 	rkaddr->rkcs2 = unit;
625 	rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
626 	rkwait(rkaddr);
627 	if ((rkaddr->rkds & RK_VV) == 0) {
628 		rkaddr->rkcs1 = RK_CDT|RK_IE|RK_PACK|RK_GO;
629 		rkwait(rkaddr);
630 	}
631 	st = &rkst[ui->ui_type];
632 	sizes = phys(struct size *, st->sizes);
633 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
634 		return (EINVAL);
635 	while (num > 0) {
636 		register struct pte *io;
637 		register int i;
638 		int cn, sn, tn;
639 		daddr_t bn;
640 
641 		blk = num > DBSIZE ? DBSIZE : num;
642 		io = uba->uba_map;
643 		for (i = 0; i < blk; i++)
644 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
645 		*(int *)io = 0;
646 		bn = dumplo + btop(start);
647 		cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
648 		sn = bn%st->nspc;
649 		tn = sn/st->nsect;
650 		sn = sn%st->nsect;
651 		rkaddr->rkcyl = cn;
652 		rp = (short *) &rkaddr->rkda;
653 		*rp = (tn << 8) + sn;
654 		*--rp = 0;
655 		*--rp = -blk*NBPG / sizeof (short);
656 		*--rp = RK_CDT|RK_GO|RK_WRITE;
657 		rkwait(rkaddr);
658 		if (rkaddr->rkcs1 & RK_CERR)
659 			return (EIO);
660 		start += blk*NBPG;
661 		num -= blk;
662 	}
663 	return (0);
664 }
665 #endif
666