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