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