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