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