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