spelling errors and add NEXFLT_BITS and UBASR_BITS
[unix-history] / usr / src / sys / vax / uba / up.c
CommitLineData
f6d201ff 1/* up.c 4.29 81/03/06 */
008c0481 2
66b4fb09 3#include "up.h"
a3cb8f60 4#if NSC > 0
008c0481 5/*
10fb932f 6 * UNIBUS disk driver with overlapped seeks and ECC recovery.
0c48c799
BJ
7 *
8 * TODO:
9 * Check out handling of spun-down drives and write lock
10 * Add reading of bad sector information and disk layout from sector 1
11 * Add bad sector forwarding code
12 * Check multiple drive handling
13 * Check dump code
14 * Check unibus reset code
008c0481 15 */
355250d9 16#define DELAY(N) { register int d; d = N; while (--d > 0); }
008c0481
BJ
17
18#include "../h/param.h"
19#include "../h/systm.h"
3f3a34c3
BJ
20#include "../h/cpu.h"
21#include "../h/nexus.h"
41888f16 22#include "../h/dk.h"
008c0481
BJ
23#include "../h/buf.h"
24#include "../h/conf.h"
25#include "../h/dir.h"
26#include "../h/user.h"
27#include "../h/map.h"
80e7c811 28#include "../h/pte.h"
008c0481 29#include "../h/mtpr.h"
008c0481 30#include "../h/vm.h"
b7333467 31#include "../h/uba.h"
0ff318b2 32#include "../h/cmap.h"
008c0481 33
0ff318b2 34#include "../h/upreg.h"
008c0481 35
3f3a34c3
BJ
36struct up_softc {
37 int sc_softas;
71236e46 38 int sc_ndrive;
3f3a34c3 39 int sc_wticks;
736772ef 40 int sc_recal;
a3cb8f60 41} up_softc[NSC];
008c0481 42
3f3a34c3 43/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
008c0481
BJ
44struct size
45{
46 daddr_t nblocks;
47 int cyloff;
48} up_sizes[8] = {
49 15884, 0, /* A=cyl 0 thru 26 */
50 33440, 27, /* B=cyl 27 thru 81 */
d1778415 51 495520, 0, /* C=cyl 0 thru 814 */
008c0481
BJ
52 15884, 562, /* D=cyl 562 thru 588 */
53 55936, 589, /* E=cyl 589 thru 680 */
54 81472, 681, /* F=cyl 681 thru 814 */
55 153824, 562, /* G=cyl 562 thru 814 */
008c0481 56 291346, 82, /* H=cyl 82 thru 561 */
3f3a34c3
BJ
57}, fj_sizes[8] = {
58 15884, 0, /* A=cyl 0 thru 49 */
59 33440, 50, /* B=cyl 50 thru 154 */
60 263360, 0, /* C=cyl 0 thru 822 */
61 0, 0,
62 0, 0,
63 0, 0,
64 0, 0,
65 213760, 155, /* H=cyl 155 thru 822 */
008c0481 66};
3f3a34c3 67/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
008c0481 68
3f3a34c3
BJ
69#define _upSDIST 2 /* 1.0 msec */
70#define _upRDIST 4 /* 2.0 msec */
71
72int upSDIST = _upSDIST;
73int upRDIST = _upRDIST;
74
71236e46 75int upprobe(), upslave(), upattach(), updgo(), upintr();
a3cb8f60 76struct uba_minfo *upminfo[NSC];
3f3a34c3 77struct uba_dinfo *updinfo[NUP];
a3cb8f60 78struct uba_dinfo *upip[NSC][4];
d763a2b7 79
71236e46 80u_short upstd[] = { 0776700, 0774400, 0776300, 0 };
0801d37f 81struct uba_driver scdriver =
71236e46 82 { upprobe, upslave, upattach, updgo, upstd, "up", updinfo, "sc", upminfo };
3f3a34c3
BJ
83struct buf uputab[NUP];
84
85struct upst {
86 short nsect;
87 short ntrak;
88 short nspc;
89 short ncyl;
90 struct size *sizes;
91} upst[] = {
71236e46
BJ
92 32, 19, 32*19, 823, up_sizes, /* 9300/cdc */
93/* 9300 actually has 815 cylinders... */
3f3a34c3
BJ
94 32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */
95};
008c0481 96
2601dfbd
BJ
97u_char up_offset[16] = {
98 UP_P400, UP_M400, UP_P400, UP_M400, UP_P800, UP_M800, UP_P800, UP_M800,
99 UP_P1200, UP_M1200, UP_P1200, UP_M1200, 0, 0, 0, 0
100};
008c0481 101
0801d37f 102struct buf rupbuf[NUP];
008c0481 103
008c0481
BJ
104#define b_cylin b_resid
105
008c0481
BJ
106#ifdef INTRLVE
107daddr_t dkblock();
108#endif
3f3a34c3
BJ
109
110int upwstart, upwatch(); /* Have started guardian */
7e00c42b 111int upseek;
f88f8fdb 112int upwaitdry;
3f3a34c3
BJ
113
114/*ARGSUSED*/
71236e46 115upprobe(reg)
3f3a34c3 116 caddr_t reg;
008c0481 117{
d763a2b7
BJ
118 register int br, cvec;
119
71236e46
BJ
120#ifdef lint
121 br = 0; cvec = br; br = cvec;
122#endif
2601dfbd 123 ((struct updevice *)reg)->upcs1 = UP_IE|UP_RDY;
71236e46 124 DELAY(10);
2601dfbd 125 ((struct updevice *)reg)->upcs1 = 0;
d763a2b7 126 return (1);
3f3a34c3
BJ
127}
128
71236e46 129upslave(ui, reg)
3f3a34c3
BJ
130 struct uba_dinfo *ui;
131 caddr_t reg;
132{
2601dfbd 133 register struct updevice *upaddr = (struct updevice *)reg;
3f3a34c3
BJ
134
135 upaddr->upcs1 = 0; /* conservative */
71236e46 136 upaddr->upcs2 = ui->ui_slave;
2601dfbd
BJ
137 if (upaddr->upcs2&UP_NED) {
138 upaddr->upcs1 = UP_DCLR|UP_GO;
3f3a34c3
BJ
139 return (0);
140 }
71236e46
BJ
141 return (1);
142}
143
144upattach(ui)
145 register struct uba_dinfo *ui;
146{
2601dfbd
BJ
147#ifdef notdef
148 register struct updevice *upaddr;
149#endif
71236e46 150
6a81870e 151 if (upwstart == 0) {
7780575a 152 timeout(upwatch, (caddr_t)0, hz);
6a81870e
BJ
153 upwstart++;
154 }
b7333467
BJ
155 if (ui->ui_dk >= 0)
156 dk_mspw[ui->ui_dk] = .0000020345;
71236e46
BJ
157 upip[ui->ui_ctlr][ui->ui_slave] = ui;
158 up_softc[ui->ui_ctlr].sc_ndrive++;
2601dfbd
BJ
159#ifdef notdef
160 upaddr = (struct updevice *)ui->ui_addr;
161 upaddr->upcs1 = 0;
162 upaddr->upcs2 = ui->ui_slave;
163 upaddr->uphr = -1;
164 /* ... */
165 if (upaddr-> ... == 10)
166 ui->ui_type = 1;
167#endif
3f3a34c3
BJ
168}
169
3f3a34c3
BJ
170upstrategy(bp)
171 register struct buf *bp;
172{
173 register struct uba_dinfo *ui;
3f3a34c3
BJ
174 register struct upst *st;
175 register int unit;
7e00c42b 176 register struct buf *dp;
3f3a34c3 177 int xunit = minor(bp->b_dev) & 07;
7e00c42b 178 long bn, sz;
3f3a34c3 179
7e00c42b 180 sz = (bp->b_bcount+511) >> 9;
008c0481 181 unit = dkunit(bp);
3f3a34c3
BJ
182 if (unit >= NUP)
183 goto bad;
184 ui = updinfo[unit];
185 if (ui == 0 || ui->ui_alive == 0)
186 goto bad;
187 st = &upst[ui->ui_type];
188 if (bp->b_blkno < 0 ||
189 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
190 goto bad;
191 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
008c0481 192 (void) spl5();
7e00c42b
BJ
193 dp = &uputab[ui->ui_unit];
194 disksort(dp, bp);
195 if (dp->b_active == 0) {
3f3a34c3
BJ
196 (void) upustart(ui);
197 bp = &ui->ui_mi->um_tab;
198 if (bp->b_actf && bp->b_active == 0)
199 (void) upstart(ui->ui_mi);
008c0481
BJ
200 }
201 (void) spl0();
3f3a34c3
BJ
202 return;
203
204bad:
205 bp->b_flags |= B_ERROR;
206 iodone(bp);
207 return;
008c0481
BJ
208}
209
736772ef
BJ
210/*
211 * Unit start routine.
212 * Seek the drive to be where the data is
213 * and then generate another interrupt
214 * to actually start the transfer.
215 * If there is only one drive on the controller,
216 * or we are very close to the data, don't
217 * bother with the search. If called after
218 * searching once, don't bother to look where
219 * we are, just queue for transfer (to avoid
220 * positioning forever without transferrring.)
221 */
3f3a34c3
BJ
222upustart(ui)
223 register struct uba_dinfo *ui;
008c0481
BJ
224{
225 register struct buf *bp, *dp;
736772ef 226 register struct uba_minfo *um = ui->ui_mi;
2601dfbd 227 register struct updevice *upaddr;
3f3a34c3 228 register struct upst *st;
008c0481 229 daddr_t bn;
736772ef 230 int sn, csn;
71236e46
BJ
231 /*
232 * The SC21 cancels commands if you just say
2601dfbd 233 * cs1 = UP_IE
71236e46
BJ
234 * so we are cautious about handling of cs1.
235 * Also don't bother to clear as bits other than in upintr().
236 */
736772ef
BJ
237 int didie = 0;
238
239 if (ui == 0)
240 return (0);
3f3a34c3
BJ
241 dk_busy &= ~(1<<ui->ui_dk);
242 dp = &uputab[ui->ui_unit];
7bc8d985 243 if ((bp = dp->b_actf) == NULL)
eb891eaa 244 goto out;
736772ef
BJ
245 /*
246 * If the controller is active, just remember
247 * that this device would like to be positioned...
248 * if we tried to position now we would confuse the SC21.
249 */
3f3a34c3 250 if (um->um_tab.b_active) {
d763a2b7 251 up_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
2a3b9a7f
BJ
252 return (0);
253 }
736772ef
BJ
254 /*
255 * If we have already positioned this drive,
256 * then just put it on the ready queue.
257 */
a3f430e0
BJ
258 if (dp->b_active)
259 goto done;
260 dp->b_active = 1;
2601dfbd 261 upaddr = (struct updevice *)um->um_addr;
3f3a34c3 262 upaddr->upcs2 = ui->ui_slave;
736772ef
BJ
263 /*
264 * If drive has just come up,
265 * setup the pack.
266 */
2601dfbd 267 if ((upaddr->upds & UP_VV) == 0) {
71236e46 268 /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
2601dfbd
BJ
269 upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO;
270 upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO;
271 upaddr->upof = UP_FMT22;
eb891eaa 272 didie = 1;
008c0481 273 }
736772ef
BJ
274 /*
275 * If drive is offline, forget about positioning.
276 */
2601dfbd 277 if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL))
2a3b9a7f 278 goto done;
736772ef
BJ
279 /*
280 * If there is only one drive,
281 * dont bother searching.
282 */
71236e46
BJ
283 if (up_softc[um->um_ctlr].sc_ndrive == 1)
284 goto done;
736772ef
BJ
285 /*
286 * Figure out where this transfer is going to
287 * and see if we are close enough to justify not searching.
288 */
3f3a34c3 289 st = &upst[ui->ui_type];
008c0481 290 bn = dkblock(bp);
3f3a34c3
BJ
291 sn = bn%st->nspc;
292 sn = (sn + st->nsect - upSDIST) % st->nsect;
736772ef 293 if (bp->b_cylin - upaddr->updc)
7bc8d985 294 goto search; /* Not on-cylinder */
2a3b9a7f
BJ
295 else if (upseek)
296 goto done; /* Ok just to be on-cylinder */
008c0481 297 csn = (upaddr->upla>>6) - sn - 1;
7bc8d985 298 if (csn < 0)
3f3a34c3
BJ
299 csn += st->nsect;
300 if (csn > st->nsect - upRDIST)
008c0481 301 goto done;
008c0481 302search:
736772ef
BJ
303 upaddr->updc = bp->b_cylin;
304 /*
305 * Not on cylinder at correct position,
306 * seek/search.
307 */
2a3b9a7f 308 if (upseek)
2601dfbd 309 upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO;
7e00c42b 310 else {
2a3b9a7f 311 upaddr->upda = sn;
2601dfbd 312 upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO;
2a3b9a7f 313 }
eb891eaa 314 didie = 1;
736772ef
BJ
315 /*
316 * Mark unit busy for iostat.
317 */
3f3a34c3
BJ
318 if (ui->ui_dk >= 0) {
319 dk_busy |= 1<<ui->ui_dk;
320 dk_seek[ui->ui_dk]++;
008c0481 321 }
eb891eaa 322 goto out;
008c0481 323done:
736772ef
BJ
324 /*
325 * Device is ready to go.
326 * Put it on the ready queue for the controller
327 * (unless its already there.)
328 */
2601dfbd
BJ
329 if (dp->b_active != 2) {
330 dp->b_forw = NULL;
331 if (um->um_tab.b_actf == NULL)
332 um->um_tab.b_actf = dp;
333 else
334 um->um_tab.b_actl->b_forw = dp;
335 um->um_tab.b_actl = dp;
336 dp->b_active = 2;
337 }
eb891eaa
BJ
338out:
339 return (didie);
008c0481
BJ
340}
341
736772ef
BJ
342/*
343 * Start up a transfer on a drive.
344 */
3f3a34c3
BJ
345upstart(um)
346 register struct uba_minfo *um;
008c0481
BJ
347{
348 register struct buf *bp, *dp;
3f3a34c3 349 register struct uba_dinfo *ui;
2601dfbd 350 register struct updevice *upaddr;
7e00c42b 351 struct upst *st;
008c0481 352 daddr_t bn;
f88f8fdb 353 int dn, sn, tn, cmd, waitdry;
008c0481 354
008c0481 355loop:
736772ef
BJ
356 /*
357 * Pull a request off the controller queue
358 */
3f3a34c3 359 if ((dp = um->um_tab.b_actf) == NULL)
eb891eaa 360 return (0);
008c0481 361 if ((bp = dp->b_actf) == NULL) {
3f3a34c3 362 um->um_tab.b_actf = dp->b_forw;
008c0481
BJ
363 goto loop;
364 }
736772ef
BJ
365 /*
366 * Mark controller busy, and
367 * determine destination of this request.
368 */
3f3a34c3
BJ
369 um->um_tab.b_active++;
370 ui = updinfo[dkunit(bp)];
008c0481 371 bn = dkblock(bp);
3f3a34c3
BJ
372 dn = ui->ui_slave;
373 st = &upst[ui->ui_type];
374 sn = bn%st->nspc;
375 tn = sn/st->nsect;
376 sn %= st->nsect;
2601dfbd 377 upaddr = (struct updevice *)ui->ui_addr;
736772ef
BJ
378 /*
379 * Select drive if not selected already.
380 */
381 if ((upaddr->upcs2&07) != dn)
382 upaddr->upcs2 = dn;
383 /*
384 * Check that it is ready and online
385 */
f88f8fdb
BJ
386 waitdry = 0;
387 while ((upaddr->upds&UP_DRY) == 0) {
388 if (++waitdry > 512)
389 break;
390 upwaitdry++;
391 }
392 if ((upaddr->upds & UP_DREADY) != UP_DREADY) {
f6d201ff 393 printf("up%d: not ready", dkunit(bp));
f88f8fdb 394 if ((upaddr->upds & UP_DREADY) != UP_DREADY) {
71236e46 395 printf("\n");
3f3a34c3
BJ
396 um->um_tab.b_active = 0;
397 um->um_tab.b_errcnt = 0;
88253fd2
BJ
398 dp->b_actf = bp->av_forw;
399 dp->b_active = 0;
400 bp->b_flags |= B_ERROR;
401 iodone(bp);
88253fd2
BJ
402 goto loop;
403 }
736772ef
BJ
404 /*
405 * Oh, well, sometimes this
406 * happens, for reasons unknown.
407 */
2601dfbd 408 printf(" (flakey)\n");
008c0481 409 }
736772ef
BJ
410 /*
411 * After 16th retry, do offset positioning
412 */
3f3a34c3 413 if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) {
2601dfbd
BJ
414 upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UP_FMT22;
415 upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
416 while (upaddr->upds & UP_PIP)
008c0481
BJ
417 DELAY(25);
418 }
736772ef
BJ
419 /*
420 * Setup for the transfer, and get in the
421 * UNIBUS adaptor queue.
422 */
5aa9d5ea 423 upaddr->updc = bp->b_cylin;
008c0481 424 upaddr->upda = (tn << 8) + sn;
008c0481
BJ
425 upaddr->upwc = -bp->b_bcount / sizeof (short);
426 if (bp->b_flags & B_READ)
2601dfbd 427 cmd = UP_IE|UP_RCOM|UP_GO;
008c0481 428 else
2601dfbd 429 cmd = UP_IE|UP_WCOM|UP_GO;
b7333467
BJ
430 um->um_cmd = cmd;
431 ubago(ui);
eb891eaa 432 return (1);
008c0481
BJ
433}
434
736772ef
BJ
435/*
436 * Now all ready to go, stuff the registers.
437 */
b7333467
BJ
438updgo(um)
439 struct uba_minfo *um;
3f3a34c3 440{
2601dfbd 441 register struct updevice *upaddr = (struct updevice *)um->um_addr;
7e00c42b 442
b7333467
BJ
443 upaddr->upba = um->um_ubinfo;
444 upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
3f3a34c3
BJ
445}
446
736772ef
BJ
447/*
448 * Handle a disk interrupt.
449 */
443c8066 450upintr(sc21)
3f3a34c3 451 register sc21;
008c0481
BJ
452{
453 register struct buf *bp, *dp;
3f3a34c3
BJ
454 register struct uba_minfo *um = upminfo[sc21];
455 register struct uba_dinfo *ui;
2601dfbd 456 register struct updevice *upaddr = (struct updevice *)um->um_addr;
008c0481 457 register unit;
7e00c42b 458 struct up_softc *sc = &up_softc[um->um_ctlr];
71236e46 459 int as = (upaddr->upas & 0377) | sc->sc_softas;
f88f8fdb 460 int needie = 1, waitdry;
008c0481 461
7e00c42b 462 sc->sc_wticks = 0;
71236e46 463 sc->sc_softas = 0;
736772ef
BJ
464 /*
465 * If controller wasn't transferring, then this is an
466 * interrupt for attention status on seeking drives.
467 * Just service them.
468 */
469 if (um->um_tab.b_active == 0) {
470 if (upaddr->upcs1 & UP_TRE)
471 upaddr->upcs1 = UP_TRE;
472 goto doattn;
473 }
736772ef
BJ
474 /*
475 * Get device and block structures, and a pointer
476 * to the uba_dinfo for the drive. Select the drive.
477 */
478 dp = um->um_tab.b_actf;
479 bp = dp->b_actf;
480 ui = updinfo[dkunit(bp)];
481 dk_busy &= ~(1 << ui->ui_dk);
482 if ((upaddr->upcs2&07) != ui->ui_slave)
3f3a34c3 483 upaddr->upcs2 = ui->ui_slave;
736772ef
BJ
484 /*
485 * Check for and process errors on
486 * either the drive or the controller.
487 */
488 if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) {
f88f8fdb
BJ
489 waitdry = 0;
490 while ((upaddr->upds & UP_DRY) == 0) {
491 if (++waitdry > 512)
492 break;
493 upwaitdry++;
494 }
f6d201ff 495 if (upaddr->uper1&UP_WLE) {
736772ef
BJ
496 /*
497 * Give up on write locked devices
498 * immediately.
499 */
f6d201ff 500 printf("up%d: write locked\n", dkunit(bp));
736772ef
BJ
501 bp->b_flags |= B_ERROR;
502 } else if (++um->um_tab.b_errcnt > 27) {
503 /*
504 * After 28 retries (16 without offset, and
505 * 12 with offset positioning) give up.
506 */
f6d201ff
BJ
507 harderr(bp, "up");
508 printf("cs2=%b er1=%b er2=%b\n",
c84ff1f9
BJ
509 upaddr->upcs2, UPCS2_BITS,
510 upaddr->uper1, UPER1_BITS,
511 upaddr->uper2, UPER2_BITS);
736772ef
BJ
512 bp->b_flags |= B_ERROR;
513 } else {
514 /*
515 * Retriable error.
516 * If a soft ecc, correct it (continuing
517 * by returning if necessary.
518 * Otherwise fall through and retry the transfer
519 */
520 um->um_tab.b_active = 0; /* force retry */
2601dfbd
BJ
521 if ((upaddr->uper1&(UP_DCK|UP_ECH))==UP_DCK)
522 if (upecc(ui))
523 return;
736772ef
BJ
524 }
525 /*
526 * Clear drive error and, every eight attempts,
527 * (starting with the fourth)
528 * recalibrate to clear the slate.
529 */
530 upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
531 needie = 0;
532 if ((um->um_tab.b_errcnt&07) == 4) {
533 upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
534 um->um_tab.b_active = 1;
535 sc->sc_recal = 1;
536 return;
537 }
538 }
539 /*
540 * Done retrying transfer... release
541 * resources... if we were recalibrating,
542 * then retry the transfer.
543 * Mathematical note: 28%8 != 4.
544 */
545 ubadone(um);
546 if (sc->sc_recal) {
547 sc->sc_recal = 0;
548 um->um_tab.b_active = 0; /* force retry */
549 }
550 /*
551 * If still ``active'', then don't need any more retries.
552 */
553 if (um->um_tab.b_active) {
554 /*
555 * If we were offset positioning,
556 * return to centerline.
557 */
558 if (um->um_tab.b_errcnt >= 16) {
559 upaddr->upof = UP_FMT22;
560 upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
561 while (upaddr->upds & UP_PIP)
562 DELAY(25);
eb891eaa 563 needie = 0;
008c0481 564 }
736772ef
BJ
565 um->um_tab.b_active = 0;
566 um->um_tab.b_errcnt = 0;
567 um->um_tab.b_actf = dp->b_forw;
568 dp->b_active = 0;
569 dp->b_errcnt = 0;
570 dp->b_actf = bp->av_forw;
571 bp->b_resid = (-upaddr->upwc * sizeof(short));
572 iodone(bp);
573 /*
574 * If this unit has more work to do,
575 * then start it up right away.
576 */
577 if (dp->b_actf)
578 if (upustart(ui))
eb891eaa 579 needie = 0;
008c0481 580 }
736772ef
BJ
581 as &= ~(1<<ui->ui_slave);
582doattn:
583 /*
584 * Process other units which need attention.
585 * For each unit which needs attention, call
586 * the unit start routine to place the slave
587 * on the controller device queue.
588 */
71236e46
BJ
589 for (unit = 0; as; as >>= 1, unit++)
590 if (as & 1) {
7e00c42b 591 upaddr->upas = 1<<unit;
71236e46 592 if (upustart(upip[sc21][unit]))
1f3d30ee
BJ
593 needie = 0;
594 }
736772ef
BJ
595 /*
596 * If the controller is not transferring, but
597 * there are devices ready to transfer, start
598 * the controller.
599 */
3f3a34c3
BJ
600 if (um->um_tab.b_actf && um->um_tab.b_active == 0)
601 if (upstart(um))
eb891eaa 602 needie = 0;
2a3b9a7f 603 if (needie)
2601dfbd 604 upaddr->upcs1 = UP_IE;
008c0481
BJ
605}
606
607upread(dev)
0801d37f 608 dev_t dev;
008c0481 609{
0801d37f 610 register int unit = minor(dev) >> 3;
7e00c42b 611
0801d37f
BJ
612 if (unit >= NUP)
613 u.u_error = ENXIO;
614 else
615 physio(upstrategy, &rupbuf[unit], dev, B_READ, minphys);
008c0481
BJ
616}
617
618upwrite(dev)
0801d37f 619 dev_t dev;
008c0481 620{
0801d37f 621 register int unit = minor(dev) >> 3;
7e00c42b 622
0801d37f
BJ
623 if (unit >= NUP)
624 u.u_error = ENXIO;
625 else
626 physio(upstrategy, &rupbuf[unit], dev, B_WRITE, minphys);
008c0481
BJ
627}
628
7bc8d985
BJ
629/*
630 * Correct an ECC error, and restart the i/o to complete
631 * the transfer if necessary. This is quite complicated because
632 * the transfer may be going to an odd memory address base and/or
633 * across a page boundary.
634 */
3f3a34c3
BJ
635upecc(ui)
636 register struct uba_dinfo *ui;
008c0481 637{
2601dfbd 638 register struct updevice *up = (struct updevice *)ui->ui_addr;
3f3a34c3
BJ
639 register struct buf *bp = uputab[ui->ui_unit].b_actf;
640 register struct uba_minfo *um = ui->ui_mi;
641 register struct upst *st;
642 struct uba_regs *ubp = ui->ui_hd->uh_uba;
7bc8d985 643 register int i;
008c0481 644 caddr_t addr;
7bc8d985 645 int reg, bit, byte, npf, mask, o, cmd, ubaddr;
008c0481
BJ
646 int bn, cn, tn, sn;
647
008c0481 648 /*
7bc8d985
BJ
649 * Npf is the number of sectors transferred before the sector
650 * containing the ECC error, and reg is the UBA register
651 * mapping (the first part of) the transfer.
652 * O is offset within a memory page of the first byte transferred.
008c0481 653 */
7bc8d985 654 npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
b7333467 655 reg = btop(um->um_ubinfo&0x3ffff) + npf;
008c0481 656 o = (int)bp->b_un.b_addr & PGOFSET;
f6d201ff 657 printf("up%d%c: soft ecc bn%d\n", dkunit(bp),
0c48c799 658 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
008c0481 659 mask = up->upec2;
7bc8d985
BJ
660 /*
661 * Flush the buffered data path, and compute the
662 * byte and bit position of the error. The variable i
663 * is the byte offset in the transfer, the variable byte
664 * is the offset from a page boundary in main memory.
665 */
060afaf6 666 ubapurge(um);
7bc8d985
BJ
667 i = up->upec1 - 1; /* -1 makes 0 origin */
668 bit = i&07;
669 i = (i&~07)>>3;
008c0481 670 byte = i + o;
7bc8d985
BJ
671 /*
672 * Correct while possible bits remain of mask. Since mask
673 * contains 11 bits, we continue while the bit offset is > -11.
674 * Also watch out for end of this block and the end of the whole
675 * transfer.
676 */
677 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
678 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
679 (byte & PGOFSET);
680 putmemc(addr, getmemc(addr)^(mask<<bit));
681 byte++;
682 i++;
683 bit -= 8;
008c0481 684 }
3f3a34c3 685 um->um_tab.b_active++; /* Either complete or continuing... */
008c0481
BJ
686 if (up->upwc == 0)
687 return (0);
7bc8d985
BJ
688 /*
689 * Have to continue the transfer... clear the drive,
690 * and compute the position where the transfer is to continue.
691 * We have completed npf+1 sectors of the transfer already;
692 * restart at offset o of next sector (i.e. in UBA register reg+1).
693 */
2601dfbd
BJ
694#ifdef notdef
695 up->uper1 = 0;
696 up->upcs1 |= UP_GO;
697#else
698 up->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
008c0481 699 bn = dkblock(bp);
3f3a34c3 700 st = &upst[ui->ui_type];
008c0481 701 cn = bp->b_cylin;
3f3a34c3
BJ
702 sn = bn%st->nspc + npf + 1;
703 tn = sn/st->nsect;
704 sn %= st->nsect;
705 cn += tn/st->ntrak;
706 tn %= st->ntrak;
008c0481 707 up->updc = cn;
7bc8d985
BJ
708 up->upda = (tn << 8) | sn;
709 ubaddr = (int)ptob(reg+1) + o;
710 up->upba = ubaddr;
711 cmd = (ubaddr >> 8) & 0x300;
2601dfbd 712 cmd |= UP_IE|UP_GO|UP_RCOM;
7bc8d985 713 up->upcs1 = cmd;
2601dfbd 714#endif
008c0481
BJ
715 return (1);
716}
977c2848
BJ
717
718/*
719 * Reset driver after UBA init.
720 * Cancel software state of all pending transfers
721 * and restart all units and the controller.
722 */
3f3a34c3 723upreset(uban)
f6d201ff 724 int uban;
977c2848 725{
3f3a34c3
BJ
726 register struct uba_minfo *um;
727 register struct uba_dinfo *ui;
728 register sc21, unit;
729
a3cb8f60 730 for (sc21 = 0; sc21 < NSC; sc21++) {
7e00c42b
BJ
731 if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||
732 um->um_alive == 0)
3f3a34c3 733 continue;
f6d201ff 734 printf(" sc%d", sc21);
3f3a34c3
BJ
735 um->um_tab.b_active = 0;
736 um->um_tab.b_actf = um->um_tab.b_actl = 0;
f6d201ff 737 up_softc[sc21].sc_recal = 0;
b7333467
BJ
738 if (um->um_ubinfo) {
739 printf("<%d>", (um->um_ubinfo>>28)&0xf);
0801d37f 740 ubadone(um);
3f3a34c3 741 }
2601dfbd 742 ((struct updevice *)(um->um_addr))->upcs2 = UP_CLR;
3f3a34c3
BJ
743 for (unit = 0; unit < NUP; unit++) {
744 if ((ui = updinfo[unit]) == 0)
745 continue;
f6d201ff 746 if (ui->ui_alive == 0 || ui->ui_mi != um)
3f3a34c3
BJ
747 continue;
748 uputab[unit].b_active = 0;
749 (void) upustart(ui);
750 }
751 (void) upstart(um);
977c2848 752 }
977c2848 753}
6a81870e
BJ
754
755/*
756 * Wake up every second and if an interrupt is pending
757 * but nothing has happened increment a counter.
f6d201ff 758 * If nothing happens for 20 seconds, reset the UNIBUS
6a81870e
BJ
759 * and begin anew.
760 */
761upwatch()
762{
3f3a34c3
BJ
763 register struct uba_minfo *um;
764 register sc21, unit;
7e00c42b 765 register struct up_softc *sc;
6a81870e 766
7780575a 767 timeout(upwatch, (caddr_t)0, hz);
a3cb8f60 768 for (sc21 = 0; sc21 < NSC; sc21++) {
3f3a34c3 769 um = upminfo[sc21];
7e00c42b
BJ
770 if (um == 0 || um->um_alive == 0)
771 continue;
772 sc = &up_softc[sc21];
3f3a34c3
BJ
773 if (um->um_tab.b_active == 0) {
774 for (unit = 0; unit < NUP; unit++)
2601dfbd
BJ
775 if (uputab[unit].b_active &&
776 updinfo[unit]->ui_mi == um)
3f3a34c3 777 goto active;
7e00c42b 778 sc->sc_wticks = 0;
3f3a34c3
BJ
779 continue;
780 }
f6d201ff 781active:
7e00c42b
BJ
782 sc->sc_wticks++;
783 if (sc->sc_wticks >= 20) {
784 sc->sc_wticks = 0;
f6d201ff 785 printf("sc%d: lost interrupt\n", sc21);
a3cb8f60 786 ubareset(um->um_ubanum);
3f3a34c3 787 }
6a81870e
BJ
788 }
789}
0ff318b2
BJ
790
791#define DBSIZE 20
792
793updump(dev)
794 dev_t dev;
795{
2601dfbd 796 struct updevice *upaddr;
0ff318b2 797 char *start;
0c48c799 798 int num, blk, unit, i;
0ff318b2 799 struct size *sizes;
3f3a34c3
BJ
800 register struct uba_regs *uba;
801 register struct uba_dinfo *ui;
0ff318b2 802 register short *rp;
3f3a34c3 803 struct upst *st;
0ff318b2 804
0ff318b2 805 unit = minor(dev) >> 3;
0c48c799
BJ
806 if (unit >= NUP)
807 return (ENXIO);
7e00c42b 808#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
3f3a34c3 809 ui = phys(struct uba_dinfo *, updinfo[unit]);
0c48c799
BJ
810 if (ui->ui_alive == 0)
811 return (ENXIO);
3f3a34c3
BJ
812 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
813#if VAX780
7e00c42b
BJ
814 if (cpu == VAX_780)
815 ubainit(uba);
3f3a34c3 816#endif
2601dfbd 817 upaddr = (struct updevice *)ui->ui_physaddr;
0c48c799
BJ
818 if ((upaddr->upcs1&UP_DVA) == 0)
819 return (EFAULT);
3f3a34c3
BJ
820 num = maxfree;
821 start = 0;
0ff318b2 822 upaddr->upcs2 = unit;
2601dfbd
BJ
823 if ((upaddr->upds & UP_VV) == 0) {
824 upaddr->upcs1 = UP_DCLR|UP_GO;
825 upaddr->upcs1 = UP_PRESET|UP_GO;
826 upaddr->upof = UP_FMT22;
0ff318b2 827 }
0c48c799
BJ
828 if ((upaddr->upds & UP_DREADY) != UP_DREADY)
829 return (EFAULT);
7e00c42b 830 st = &upst[ui->ui_type];
3f3a34c3 831 sizes = phys(struct size *, st->sizes);
0c48c799
BJ
832 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
833 return (EINVAL);
0ff318b2
BJ
834 while (num > 0) {
835 register struct pte *io;
836 register int i;
837 int cn, sn, tn;
838 daddr_t bn;
839
840 blk = num > DBSIZE ? DBSIZE : num;
3f3a34c3 841 io = uba->uba_map;
0ff318b2 842 for (i = 0; i < blk; i++)
3f3a34c3 843 *(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV;
0ff318b2
BJ
844 *(int *)io = 0;
845 bn = dumplo + btop(start);
71236e46
BJ
846 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
847 sn = bn%st->nspc;
848 tn = sn/st->nsect;
849 sn = sn%st->nsect;
0ff318b2
BJ
850 upaddr->updc = cn;
851 rp = (short *) &upaddr->upda;
852 *rp = (tn << 8) + sn;
853 *--rp = 0;
854 *--rp = -blk*NBPG / sizeof (short);
2601dfbd 855 *--rp = UP_GO|UP_WCOM;
0ff318b2
BJ
856 do {
857 DELAY(25);
2601dfbd 858 } while ((upaddr->upcs1 & UP_RDY) == 0);
0c48c799
BJ
859 if (upaddr->upcs1&UP_ERR)
860 return (EIO);
0ff318b2
BJ
861 start += blk*NBPG;
862 num -= blk;
863 }
0ff318b2
BJ
864 return (0);
865}
63c35a63 866#endif