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