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

Defined functions

upattach defined in line 191; used 2 times
updgo defined in line 529; used 2 times
updump defined in line 998; never used
upecc defined in line 771; used 4 times
upintr defined in line 542; used 3 times
upmaptype defined in line 206; used 1 times
upopen defined in line 232; never used
upprobe defined in line 161; used 2 times
upread defined in line 743; never used
upreset defined in line 927; never used
upsize defined in line 1087; never used
upslave defined in line 175; used 2 times
upstart defined in line 444; used 3 times
upstrategy defined in line 243; used 2 times
upustart defined in line 307; used 4 times
upwatch defined in line 966; used 3 times
upwrite defined in line 754; never used

Defined variables

bupbuf defined in line 151; used 1 times
rupbuf defined in line 150; used 2 times
scdriver defined in line 120; used 6 times
up9300_sizes defined in line 56; used 1 times
up_offset defined in line 143; used 1 times
up_softc defined in line 48; used 7 times
upbad defined in line 152; used 2 times
updinfo defined in line 115; used 9 times
upinit defined in line 123; used 2 times
upip defined in line 117; used 2 times
upminfo defined in line 114; used 4 times
upseek defined in line 157; used 2 times
upst defined in line 133; used 9 times
upstd defined in line 119; used 1 times
uputab defined in line 122; used 5 times
upwaitdry defined in line 158; used 2 times
upwstart defined in line 156; used 2 times

Defined struct's

size defined in line 53; used 6 times
up_softc defined in line 43; used 4 times
upst defined in line 125; used 14 times

Defined macros

DBSIZE defined in line 996; used 2 times
UPIPUNITS defined in line 116; used 2 times
b_cylin defined in line 154; used 7 times
phys defined in line 1014; used 3 times
upunit defined in line 50; used 12 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3177
Valid CSS Valid XHTML 1.0 Strict