fix to reeves fix of dgo handling (reset b_active to 1)
[unix-history] / usr / src / sys / vax / uba / rk.c
CommitLineData
b818ad5f 1/* rk.c 4.41 82/05/19 */
d483c58c 2
66b4fb09 3#include "rk.h"
872b4e09 4#if NHK > 0
a0eab615
BJ
5int rkpip; /* DEBUG */
6int rknosval; /* DEBUG */
b4208137 7#ifdef RKDEBUG
535f6684 8int rkdebug;
b4208137
BJ
9#endif
10#ifdef RKBDEBUG
11int rkbdebug;
12#endif
d483c58c 13/*
535f6684 14 * RK611/RK0[67] disk driver
9037157b
BJ
15 *
16 * This driver mimics up.c; see it for an explanation of common code.
ed687006 17 *
c9e9b65b 18 * TODO:
777e0613 19 * Learn why we lose an interrupt sometime when spinning drives down
d483c58c 20 */
d483c58c
BJ
21#include "../h/param.h"
22#include "../h/systm.h"
23#include "../h/buf.h"
24#include "../h/conf.h"
25#include "../h/dir.h"
26#include "../h/user.h"
27#include "../h/pte.h"
28#include "../h/map.h"
0801d37f 29#include "../h/vm.h"
89bd2f01
BJ
30#include "../h/ubareg.h"
31#include "../h/ubavar.h"
d483c58c 32#include "../h/dk.h"
0801d37f
BJ
33#include "../h/cpu.h"
34#include "../h/cmap.h"
b4208137 35#include "../h/dkbad.h"
0801d37f
BJ
36
37#include "../h/rkreg.h"
d483c58c 38
0801d37f
BJ
39struct rk_softc {
40 int sc_softas;
41 int sc_ndrive;
42 int sc_wticks;
43 int sc_recal;
872b4e09 44} rk_softc[NHK];
0801d37f
BJ
45
46/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
c84ff1f9 47struct size {
0801d37f 48 daddr_t nblocks;
d483c58c 49 int cyloff;
b4208137 50} rk7_sizes[8] ={
0801d37f 51 15884, 0, /* A=cyl 0 thru 240 */
22717fbb
BJ
52 10032, 241, /* B=cyl 241 thru 392 */
53 53790, 0, /* C=cyl 0 thru 814 */
d483c58c
BJ
54 0, 0,
55 0, 0,
56 0, 0,
0801d37f 57 27786, 393, /* G=cyl 393 thru 813 */
d483c58c 58 0, 0,
b4208137
BJ
59}, rk6_sizes[8] ={
60 15884, 0, /* A=cyl 0 thru 240 */
61 11154, 241, /* B=cyl 241 thru 409 */
62 27126, 0, /* C=cyl 0 thru 410 */
63 0, 0,
64 0, 0,
65 0, 0,
66 0, 0,
67 0, 0,
d483c58c 68};
0801d37f
BJ
69/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
70
b4208137
BJ
71short rktypes[] = { RK_CDT, 0 };
72
0801d37f 73int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr();
89bd2f01
BJ
74struct uba_ctlr *rkminfo[NHK];
75struct uba_device *rkdinfo[NRK];
76struct uba_device *rkip[NHK][4];
0801d37f
BJ
77
78u_short rkstd[] = { 0777440, 0 };
79struct uba_driver hkdriver =
9037157b 80 { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 };
872b4e09
BJ
81struct buf rkutab[NRK];
82short rkcyl[NRK];
616c2a83 83#ifndef NOBADSECT
b4208137
BJ
84struct dkbad rkbad[NRK];
85struct buf brkbuf[NRK];
86#endif
0801d37f
BJ
87
88struct rkst {
89 short nsect;
90 short ntrak;
91 short nspc;
92 short ncyl;
93 struct size *sizes;
94} rkst[] = {
95 NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes,
b4208137 96 NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes,
0801d37f
BJ
97};
98
99u_char rk_offset[16] =
535f6684
BJ
100 { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800,
101 RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0
102 };
0801d37f 103
872b4e09 104struct buf rrkbuf[NRK];
0801d37f
BJ
105
106#define b_cylin b_resid
107
108#ifdef INTRLVE
109daddr_t dkblock();
110#endif
111
112int rkwstart, rkwatch();
113
114rkprobe(reg)
115 caddr_t reg;
116{
117 register int br, cvec;
118
119#ifdef lint
120 br = 0; cvec = br; br = cvec;
89b8a44c 121 rkintr(0);
0801d37f
BJ
122#endif
123 ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY;
124 DELAY(10);
125 ((struct rkdevice *)reg)->rkcs1 = RK_CDT;
126 return (1);
127}
128
129rkslave(ui, reg)
89bd2f01 130 struct uba_device *ui;
0801d37f
BJ
131 caddr_t reg;
132{
133 register struct rkdevice *rkaddr = (struct rkdevice *)reg;
134
b4208137
BJ
135 ui->ui_type = 0;
136 rkaddr->rkcs1 = RK_CCLR;
0801d37f 137 rkaddr->rkcs2 = ui->ui_slave;
29a0409f 138 rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
9037157b 139 rkwait(rkaddr);
28de6ed0 140 DELAY(50);
535f6684 141 if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) {
b4208137 142 rkaddr->rkcs1 = RK_CCLR;
0801d37f
BJ
143 return (0);
144 }
b4208137
BJ
145 if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) {
146 ui->ui_type = 1;
147 rkaddr->rkcs1 = RK_CCLR;
148 }
0801d37f
BJ
149 return (1);
150}
d483c58c 151
0801d37f 152rkattach(ui)
89bd2f01 153 register struct uba_device *ui;
0801d37f
BJ
154{
155
156 if (rkwstart == 0) {
7780575a 157 timeout(rkwatch, (caddr_t)0, hz);
0801d37f
BJ
158 rkwstart++;
159 }
160 if (ui->ui_dk >= 0)
7780575a 161 dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256);
0801d37f
BJ
162 rkip[ui->ui_ctlr][ui->ui_slave] = ui;
163 rk_softc[ui->ui_ctlr].sc_ndrive++;
164 rkcyl[ui->ui_unit] = -1;
b4208137 165 ui->ui_flags = 0;
0801d37f
BJ
166}
167
d483c58c 168rkstrategy(bp)
0801d37f 169 register struct buf *bp;
d483c58c 170{
89bd2f01 171 register struct uba_device *ui;
0801d37f
BJ
172 register struct rkst *st;
173 register int unit;
174 register struct buf *dp;
175 int xunit = minor(bp->b_dev) & 07;
176 long bn, sz;
530d0032 177 int s;
0801d37f
BJ
178
179 sz = (bp->b_bcount+511) >> 9;
180 unit = dkunit(bp);
872b4e09 181 if (unit >= NRK)
0801d37f
BJ
182 goto bad;
183 ui = rkdinfo[unit];
184 if (ui == 0 || ui->ui_alive == 0)
185 goto bad;
186 st = &rkst[ui->ui_type];
187 if (bp->b_blkno < 0 ||
188 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
189 goto bad;
190 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
530d0032 191 s = spl5();
0801d37f
BJ
192 dp = &rkutab[ui->ui_unit];
193 disksort(dp, bp);
194 if (dp->b_active == 0) {
195 (void) rkustart(ui);
196 bp = &ui->ui_mi->um_tab;
197 if (bp->b_actf && bp->b_active == 0)
198 (void) rkstart(ui->ui_mi);
d483c58c 199 }
530d0032 200 splx(s);
0801d37f
BJ
201 return;
202
203bad:
204 bp->b_flags |= B_ERROR;
205 iodone(bp);
206 return;
d483c58c
BJ
207}
208
0801d37f 209rkustart(ui)
89bd2f01 210 register struct uba_device *ui;
0801d37f
BJ
211{
212 register struct buf *bp, *dp;
89bd2f01 213 register struct uba_ctlr *um;
0801d37f 214 register struct rkdevice *rkaddr;
0801d37f
BJ
215
216 if (ui == 0)
cc7ff771 217 return;
0801d37f
BJ
218 dk_busy &= ~(1<<ui->ui_dk);
219 dp = &rkutab[ui->ui_unit];
0801d37f 220 um = ui->ui_mi;
28de6ed0 221 rkaddr = (struct rkdevice *)um->um_addr;
0801d37f
BJ
222 if (um->um_tab.b_active) {
223 rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
cc7ff771 224 return;
0801d37f 225 }
cc7ff771
BJ
226 if ((bp = dp->b_actf) == NULL)
227 return;
b4208137 228 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR;
0801d37f 229 rkaddr->rkcs2 = ui->ui_slave;
b4208137 230 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
0801d37f 231 rkwait(rkaddr);
b4208137 232 if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) {
0801d37f 233 /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
616c2a83 234#ifndef NOBADSECT
b4208137
BJ
235 struct rkst *st = &rkst[ui->ui_type];
236 struct buf *bbp = &brkbuf[ui->ui_unit];
237#endif
238
239 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO;
240 ui->ui_flags = 1;
616c2a83 241#ifndef NOBADSECT
b4208137
BJ
242 bbp->b_flags = B_READ|B_BUSY;
243 bbp->b_dev = bp->b_dev;
244 bbp->b_bcount = 512;
245 bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit];
246 bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
247 bbp->b_cylin = st->ncyl - 1;
248 dp->b_actf = bbp;
249 bbp->av_forw = bp;
250 bp = bbp;
251#endif
0801d37f 252 rkwait(rkaddr);
0801d37f 253 }
736f0c13
BJ
254 if (dp->b_active)
255 goto done;
256 dp->b_active = 1;
535f6684 257 if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY)
28de6ed0 258 goto done;
0801d37f
BJ
259 if (rk_softc[um->um_ctlr].sc_ndrive == 1)
260 goto done;
261 if (bp->b_cylin == rkcyl[ui->ui_unit])
262 goto done;
263 rkaddr->rkcyl = bp->b_cylin;
264 rkcyl[ui->ui_unit] = bp->b_cylin;
b4208137 265 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
0801d37f
BJ
266 if (ui->ui_dk >= 0) {
267 dk_busy |= 1<<ui->ui_dk;
268 dk_seek[ui->ui_dk]++;
269 }
270 goto out;
271done:
272 if (dp->b_active != 2) {
273 dp->b_forw = NULL;
274 if (um->um_tab.b_actf == NULL)
275 um->um_tab.b_actf = dp;
276 else
277 um->um_tab.b_actl->b_forw = dp;
278 um->um_tab.b_actl = dp;
279 dp->b_active = 2;
280 }
281out:
cc7ff771 282 return;
0801d37f 283}
d483c58c 284
0801d37f 285rkstart(um)
89bd2f01 286 register struct uba_ctlr *um;
d483c58c 287{
0801d37f 288 register struct buf *bp, *dp;
89bd2f01 289 register struct uba_device *ui;
0801d37f
BJ
290 register struct rkdevice *rkaddr;
291 struct rkst *st;
d483c58c 292 daddr_t bn;
0801d37f
BJ
293 int sn, tn, cmd;
294
295loop:
296 if ((dp = um->um_tab.b_actf) == NULL)
cc7ff771 297 return;
0801d37f
BJ
298 if ((bp = dp->b_actf) == NULL) {
299 um->um_tab.b_actf = dp->b_forw;
300 goto loop;
d483c58c 301 }
0801d37f
BJ
302 um->um_tab.b_active++;
303 ui = rkdinfo[dkunit(bp)];
304 bn = dkblock(bp);
305 st = &rkst[ui->ui_type];
306 sn = bn%st->nspc;
307 tn = sn/st->nsect;
308 sn %= st->nsect;
309 rkaddr = (struct rkdevice *)ui->ui_addr;
29a0409f 310retry:
b4208137 311 rkaddr->rkcs1 = RK_CCLR;
0801d37f 312 rkaddr->rkcs2 = ui->ui_slave;
b4208137 313 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
0801d37f 314 rkwait(rkaddr);
535f6684 315 if ((rkaddr->rkds&RKDS_SVAL) == 0) {
29a0409f
BJ
316 rknosval++;
317 goto nosval;
318 }
535f6684 319 if (rkaddr->rkds&RKDS_PIP) {
29a0409f
BJ
320 rkpip++;
321 goto retry;
28de6ed0 322 }
535f6684 323 if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
68347e63 324 printf("rk%d: not ready", dkunit(bp));
535f6684 325 if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) {
28de6ed0 326 printf("\n");
b4208137 327 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
28de6ed0 328 rkwait(rkaddr);
b4208137 329 rkaddr->rkcs1 = RK_CCLR;
28de6ed0
BJ
330 rkwait(rkaddr);
331 um->um_tab.b_active = 0;
332 um->um_tab.b_errcnt = 0;
333 dp->b_actf = bp->av_forw;
334 dp->b_active = 0;
335 bp->b_flags |= B_ERROR;
336 iodone(bp);
337 goto loop;
338 }
339 printf(" (came back!)\n");
340 }
29a0409f 341nosval:
0801d37f
BJ
342 rkaddr->rkcyl = bp->b_cylin;
343 rkcyl[ui->ui_unit] = bp->b_cylin;
344 rkaddr->rkda = (tn << 8) + sn;
345 rkaddr->rkwc = -bp->b_bcount / sizeof (short);
346 if (bp->b_flags & B_READ)
b4208137 347 cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO;
0801d37f 348 else
b4208137 349 cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO;
0801d37f 350 um->um_cmd = cmd;
a0eab615 351 (void) ubago(ui);
d483c58c
BJ
352}
353
0801d37f 354rkdgo(um)
89bd2f01 355 register struct uba_ctlr *um;
d483c58c 356{
0801d37f
BJ
357 register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
358
cc7ff771 359 um->um_tab.b_active++; /* should now be 2 */
0801d37f
BJ
360 rkaddr->rkba = um->um_ubinfo;
361 rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
362}
363
443c8066 364rkintr(rk11)
0801d37f
BJ
365 int rk11;
366{
89bd2f01
BJ
367 register struct uba_ctlr *um = rkminfo[rk11];
368 register struct uba_device *ui;
0801d37f
BJ
369 register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr;
370 register struct buf *bp, *dp;
371 int unit;
372 struct rk_softc *sc = &rk_softc[um->um_ctlr];
373 int as = (rkaddr->rkatt >> 8) | sc->sc_softas;
374 int needie = 1;
375
376 sc->sc_wticks = 0;
377 sc->sc_softas = 0;
cc7ff771 378 if (um->um_tab.b_active == 2 || sc->sc_recal) {
0801d37f
BJ
379 dp = um->um_tab.b_actf;
380 bp = dp->b_actf;
381 ui = rkdinfo[dkunit(bp)];
382 dk_busy &= ~(1 << ui->ui_dk);
616c2a83 383#ifndef NOBADSECT
b4208137
BJ
384 if (bp->b_flags&B_BAD)
385 if (rkecc(ui, CONT))
386 return;
387#endif
0801d37f
BJ
388 if (rkaddr->rkcs1 & RK_CERR) {
389 int recal;
390 u_short ds = rkaddr->rkds;
391 u_short cs2 = rkaddr->rkcs2;
392 u_short er = rkaddr->rker;
b4208137 393#ifdef RKDEBUG
535f6684
BJ
394 if (rkdebug) {
395 printf("cs2=%b ds=%b er=%b\n",
396 cs2, RKCS2_BITS, ds,
397 RKDS_BITS, er, RKER_BITS);
398 }
b4208137 399#endif
535f6684 400 if (er & RKER_WLE) {
68347e63 401 printf("rk%d: write locked\n", dkunit(bp));
ed687006
BJ
402 bp->b_flags |= B_ERROR;
403 } else if (++um->um_tab.b_errcnt > 28 ||
736772ef 404 ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) {
b4208137 405hard:
68347e63
BJ
406 harderr(bp, "rk");
407 printf("cs2=%b ds=%b er=%b\n",
28de6ed0 408 cs2, RKCS2_BITS, ds,
736772ef 409 RKDS_BITS, er, RKER_BITS);
a306546d
BJ
410 bp->b_flags |= B_ERROR;
411 sc->sc_recal = 0;
b4208137 412 } else if (er & RKER_BSE) {
616c2a83 413#ifndef NOBADSECT
b4208137
BJ
414 if (rkecc(ui, BSE))
415 return;
416 else
417#endif
418 goto hard;
736772ef 419 } else
0801d37f 420 um->um_tab.b_active = 0;
535f6684
BJ
421 if (cs2&RKCS2_MDS) {
422 rkaddr->rkcs2 = RKCS2_SCLR;
0801d37f
BJ
423 goto retry;
424 }
425 recal = 0;
535f6684 426 if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) ||
0801d37f
BJ
427 (um->um_tab.b_errcnt&07) == 4)
428 recal = 1;
535f6684 429 if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK)
b4208137 430 if (rkecc(ui, ECC))
0801d37f 431 return;
b4208137 432 rkaddr->rkcs1 = RK_CCLR;
0801d37f 433 rkaddr->rkcs2 = ui->ui_slave;
b4208137 434 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
0801d37f
BJ
435 rkwait(rkaddr);
436 if (recal && um->um_tab.b_active == 0) {
b4208137 437 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO;
0801d37f 438 rkcyl[ui->ui_unit] = -1;
29a0409f
BJ
439 sc->sc_recal = 0;
440 goto nextrecal;
d483c58c 441 }
d483c58c 442 }
0801d37f 443retry:
29a0409f
BJ
444 switch (sc->sc_recal) {
445
446 case 1:
447 rkaddr->rkcyl = bp->b_cylin;
448 rkcyl[ui->ui_unit] = bp->b_cylin;
b4208137 449 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO;
29a0409f 450 goto nextrecal;
29a0409f
BJ
451 case 2:
452 if (um->um_tab.b_errcnt < 16 ||
6ac24ecd 453 (bp->b_flags&B_READ) == 0)
a6442a2f 454 goto donerecal;
29a0409f 455 rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017];
b4208137 456 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO;
29a0409f
BJ
457 /* fall into ... */
458 nextrecal:
459 sc->sc_recal++;
460 rkwait(rkaddr);
461 um->um_tab.b_active = 1;
462 return;
a6442a2f 463 donerecal:
29a0409f 464 case 3:
0801d37f
BJ
465 sc->sc_recal = 0;
466 um->um_tab.b_active = 0;
29a0409f 467 break;
d483c58c 468 }
b4208137 469 ubadone(um);
0801d37f
BJ
470 if (um->um_tab.b_active) {
471 um->um_tab.b_active = 0;
472 um->um_tab.b_errcnt = 0;
473 um->um_tab.b_actf = dp->b_forw;
474 dp->b_active = 0;
475 dp->b_errcnt = 0;
476 dp->b_actf = bp->av_forw;
477 bp->b_resid = -rkaddr->rkwc * sizeof(short);
478 iodone(bp);
479 if (dp->b_actf)
cc7ff771 480 rkustart(ui);
d483c58c 481 }
0801d37f 482 as &= ~(1<<ui->ui_slave);
d483c58c 483 }
0801d37f 484 for (unit = 0; as; as >>= 1, unit++)
89bd2f01
BJ
485 if (as & 1) {
486 ui = rkip[rk11][unit];
487 if (ui) {
cc7ff771 488 rkustart(rkip[rk11][unit]);
89bd2f01 489 } else {
b4208137 490 rkaddr->rkcs1 = RK_CCLR;
89bd2f01 491 rkaddr->rkcs2 = unit;
b4208137 492 rkaddr->rkcs1 = RK_DCLR|RK_GO;
89bd2f01 493 rkwait(rkaddr);
b4208137 494 rkaddr->rkcs1 = RK_CCLR;
89bd2f01
BJ
495 }
496 }
0801d37f 497 if (um->um_tab.b_actf && um->um_tab.b_active == 0)
cc7ff771
BJ
498 rkstart(um);
499 if (((needie = rkaddr->rkcs1) & RK_IE) == 0)
b4208137 500 rkaddr->rkcs1 = RK_IE;
d483c58c
BJ
501}
502
0801d37f
BJ
503rkwait(addr)
504 register struct rkdevice *addr;
505{
506
507 while ((addr->rkcs1 & RK_CRDY) == 0)
508 ;
509}
d483c58c 510
0801d37f
BJ
511rkread(dev)
512 dev_t dev;
d483c58c 513{
0801d37f
BJ
514 register int unit = minor(dev) >> 3;
515
872b4e09 516 if (unit >= NRK)
0801d37f
BJ
517 u.u_error = ENXIO;
518 else
519 physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys);
d483c58c
BJ
520}
521
0801d37f
BJ
522rkwrite(dev)
523 dev_t dev;
d483c58c 524{
0801d37f 525 register int unit = minor(dev) >> 3;
d483c58c 526
872b4e09 527 if (unit >= NRK)
0801d37f
BJ
528 u.u_error = ENXIO;
529 else
530 physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys);
d483c58c
BJ
531}
532
b4208137 533rkecc(ui, flag)
89bd2f01 534 register struct uba_device *ui;
d483c58c 535{
0801d37f
BJ
536 register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr;
537 register struct buf *bp = rkutab[ui->ui_unit].b_actf;
89bd2f01 538 register struct uba_ctlr *um = ui->ui_mi;
0801d37f
BJ
539 register struct rkst *st;
540 struct uba_regs *ubp = ui->ui_hd->uh_uba;
0801d37f 541 caddr_t addr;
b4208137 542 int reg, npf, o, cmd, ubaddr;
0801d37f 543 int bn, cn, tn, sn;
d483c58c 544
616c2a83 545#ifndef NOBADSECT
b4208137
BJ
546 if (flag == CONT)
547 npf = bp->b_error;
548 else
549#endif
550 npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount);
0801d37f
BJ
551 reg = btop(um->um_ubinfo&0x3ffff) + npf;
552 o = (int)bp->b_un.b_addr & PGOFSET;
0801d37f
BJ
553 bn = dkblock(bp);
554 st = &rkst[ui->ui_type];
555 cn = bp->b_cylin;
b4208137 556 sn = bn%st->nspc + npf;
0801d37f
BJ
557 tn = sn/st->nsect;
558 sn %= st->nsect;
559 cn += tn/st->ntrak;
560 tn %= st->ntrak;
b4208137 561 ubapurge(um);
cc7ff771 562 um->um_tab.b_active = 2; /* Either complete or continuing... */
b4208137
BJ
563 switch (flag) {
564 case ECC:
565 {
566 register int i;
567 int bit, byte, mask;
568
569 npf--;
570 reg--;
571 printf("rk%d%c: soft ecc sn%d\n", dkunit(bp),
572 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
573 mask = rk->rkec2;
574 i = rk->rkec1 - 1; /* -1 makes 0 origin */
575 bit = i&07;
576 i = (i&~07)>>3;
577 byte = i + o;
578 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
579 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
580 (byte & PGOFSET);
581 putmemc(addr, getmemc(addr)^(mask<<bit));
582 byte++;
583 i++;
584 bit -= 8;
585 }
586 if (rk->rkwc == 0)
587 return (0);
588 npf++;
589 reg++;
590 break;
591 }
592
616c2a83 593#ifndef NOBADSECT
b4208137
BJ
594 case BSE:
595#ifdef RKBDEBUG
596 if (rkbdebug)
597 printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
598#endif
599 if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0)
600 return(0);
601 bp->b_flags |= B_BAD;
602 bp->b_error = npf + 1;
603 bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
604 cn = bn/st->nspc;
605 sn = bn%st->nspc;
606 tn = sn/st->nsect;
607 sn %= st->nsect;
608#ifdef RKBDEBUG
609 if (rkbdebug)
610 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
611#endif
612 rk->rkwc = -(512 / sizeof (short));
613 break;
614
615 case CONT:
616#ifdef RKBDEBUG
617 if (rkbdebug)
618 printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
619#endif
620 bp->b_flags &= ~B_BAD;
621 rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short));
622 if (rk->rkwc == 0)
623 return(0);
624 break;
625#endif
626 }
627 rk->rkcs1 = RK_CCLR;
628 rk->rkcs2 = ui->ui_slave;
629 rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
630 rkwait(rk);
0801d37f
BJ
631 rk->rkcyl = cn;
632 rk->rkda = (tn << 8) | sn;
b4208137 633 ubaddr = (int)ptob(reg) + o;
0801d37f 634 rk->rkba = ubaddr;
b4208137
BJ
635 cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO;
636 cmd |= (ubaddr >> 8) & 0x300;
637 cmd |= rktypes[ui->ui_type];
0801d37f 638 rk->rkcs1 = cmd;
b4208137 639 um->um_tab.b_errcnt = 0; /* error has been corrected */
0801d37f 640 return (1);
d483c58c
BJ
641}
642
0801d37f 643rkreset(uban)
68347e63 644 int uban;
0801d37f 645{
89bd2f01
BJ
646 register struct uba_ctlr *um;
647 register struct uba_device *ui;
0801d37f 648 register rk11, unit;
0801d37f 649
872b4e09 650 for (rk11 = 0; rk11 < NHK; rk11++) {
0801d37f
BJ
651 if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban ||
652 um->um_alive == 0)
653 continue;
68347e63 654 printf(" hk%d", rk11);
0801d37f
BJ
655 um->um_tab.b_active = 0;
656 um->um_tab.b_actf = um->um_tab.b_actl = 0;
657 rk_softc[um->um_ctlr].sc_recal = 0;
cc7ff771 658 rk_softc[um->um_ctlr].sc_wticks = 0;
0801d37f
BJ
659 if (um->um_ubinfo) {
660 printf("<%d>", (um->um_ubinfo>>28)&0xf);
661 ubadone(um);
662 }
e1c5f66d 663 for (unit = 0; unit < NRK; unit++) {
0801d37f
BJ
664 if ((ui = rkdinfo[unit]) == 0)
665 continue;
e1c5f66d 666 if (ui->ui_alive == 0 || ui->ui_mi != um)
0801d37f
BJ
667 continue;
668 rkutab[unit].b_active = 0;
669 (void) rkustart(ui);
670 }
671 (void) rkstart(um);
672 }
673}
674
0801d37f 675rkwatch()
d483c58c 676{
89bd2f01 677 register struct uba_ctlr *um;
0801d37f
BJ
678 register rk11, unit;
679 register struct rk_softc *sc;
d483c58c 680
7780575a 681 timeout(rkwatch, (caddr_t)0, hz);
872b4e09 682 for (rk11 = 0; rk11 < NHK; rk11++) {
0801d37f
BJ
683 um = rkminfo[rk11];
684 if (um == 0 || um->um_alive == 0)
685 continue;
686 sc = &rk_softc[rk11];
687 if (um->um_tab.b_active == 0) {
872b4e09 688 for (unit = 0; unit < NRK; unit++)
9037157b
BJ
689 if (rkutab[unit].b_active &&
690 rkdinfo[unit]->ui_mi == um)
0801d37f
BJ
691 goto active;
692 sc->sc_wticks = 0;
693 continue;
694 }
695active:
696 sc->sc_wticks++;
697 if (sc->sc_wticks >= 20) {
698 sc->sc_wticks = 0;
68347e63 699 printf("hk%d: lost interrupt\n", rk11);
872b4e09 700 ubareset(um->um_ubanum);
0801d37f
BJ
701 }
702 }
d483c58c 703}
0ff318b2 704
0801d37f
BJ
705#define DBSIZE 20
706
707rkdump(dev)
708 dev_t dev;
0ff318b2 709{
0801d37f
BJ
710 struct rkdevice *rkaddr;
711 char *start;
712 int num, blk, unit;
713 struct size *sizes;
714 register struct uba_regs *uba;
89bd2f01 715 register struct uba_device *ui;
0801d37f
BJ
716 register short *rp;
717 struct rkst *st;
718
719 unit = minor(dev) >> 3;
c9e9b65b
BJ
720 if (unit >= NRK)
721 return (ENXIO);
0801d37f 722#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
89bd2f01 723 ui = phys(struct uba_device *, rkdinfo[unit]);
c9e9b65b
BJ
724 if (ui->ui_alive == 0)
725 return (ENXIO);
0801d37f 726 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
a53e803c 727 ubainit(uba);
0801d37f
BJ
728 rkaddr = (struct rkdevice *)ui->ui_physaddr;
729 num = maxfree;
730 start = 0;
b4208137 731 rkaddr->rkcs1 = RK_CCLR;
0801d37f 732 rkaddr->rkcs2 = unit;
b4208137 733 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO;
0801d37f 734 rkwait(rkaddr);
535f6684 735 if ((rkaddr->rkds & RKDS_VV) == 0) {
b4208137 736 rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO;
0801d37f
BJ
737 rkwait(rkaddr);
738 }
739 st = &rkst[ui->ui_type];
740 sizes = phys(struct size *, st->sizes);
c9e9b65b
BJ
741 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
742 return (EINVAL);
0801d37f
BJ
743 while (num > 0) {
744 register struct pte *io;
745 register int i;
746 int cn, sn, tn;
747 daddr_t bn;
0ff318b2 748
0801d37f
BJ
749 blk = num > DBSIZE ? DBSIZE : num;
750 io = uba->uba_map;
751 for (i = 0; i < blk; i++)
89bd2f01 752 *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
0801d37f
BJ
753 *(int *)io = 0;
754 bn = dumplo + btop(start);
755 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
756 sn = bn%st->nspc;
757 tn = sn/st->nsect;
758 sn = sn%st->nsect;
759 rkaddr->rkcyl = cn;
760 rp = (short *) &rkaddr->rkda;
761 *rp = (tn << 8) + sn;
762 *--rp = 0;
763 *--rp = -blk*NBPG / sizeof (short);
b4208137 764 *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE;
0801d37f 765 rkwait(rkaddr);
c9e9b65b
BJ
766 if (rkaddr->rkcs1 & RK_CERR)
767 return (EIO);
0801d37f
BJ
768 start += blk*NBPG;
769 num -= blk;
770 }
771 return (0);
0ff318b2 772}
d483c58c 773#endif