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