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:  *	@(#)idc.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "rb.h"
  10: #if NIDC > 0
  11: int idcdebug = 0;
  12: #define printd if(idcdebug)printf
  13: int idctrb[1000];
  14: int *trp = idctrb;
  15: #define trace(a,b) {*trp++ = *(int*)a; *trp++ = (int)b; if(trp>&idctrb[998])trp=idctrb;}
  16: /*
  17:  * IDC (RB730) disk driver
  18:  *
  19:  * There can only ever be one IDC on a machine,
  20:  * and only on a VAX-11/730.  We take advantage
  21:  * of that to simplify the driver.
  22:  *
  23:  * TODO:
  24:  *	ecc
  25:  */
  26: #include "../machine/pte.h"
  27: 
  28: #include "param.h"
  29: #include "systm.h"
  30: #include "buf.h"
  31: #include "conf.h"
  32: #include "dir.h"
  33: #include "user.h"
  34: #include "map.h"
  35: #include "vm.h"
  36: #include "dk.h"
  37: #include "cmap.h"
  38: #include "dkbad.h"
  39: #include "uio.h"
  40: #include "kernel.h"
  41: #include "syslog.h"
  42: 
  43: #include "../vax/cpu.h"
  44: #include "ubareg.h"
  45: #include "ubavar.h"
  46: #include "idcreg.h"
  47: 
  48: struct idc_softc {
  49:     int sc_bcnt;    /* number of bytes to transfer */
  50:     int sc_resid;   /* total number of bytes to transfer */
  51:     int sc_ubaddr;  /* Unibus address of data */
  52:     short   sc_unit;    /* unit doing transfer */
  53:     short   sc_softas;  /* software attention summary bits */
  54:     union idc_dar {
  55:         long    dar_l;
  56:         u_short dar_w[2];
  57:         u_char  dar_b[4];
  58:     } sc_un;        /* prototype disk address register */
  59: } idc_softc;
  60: 
  61: #define dar_dar     dar_l       /* the whole disk address */
  62: #define dar_cyl     dar_w[1]    /* cylinder address */
  63: #define dar_trk     dar_b[1]    /* track */
  64: #define dar_sect    dar_b[0]    /* sector */
  65: #define sc_dar      sc_un.dar_dar
  66: #define sc_cyl      sc_un.dar_cyl
  67: #define sc_trk      sc_un.dar_trk
  68: #define sc_sect     sc_un.dar_sect
  69: 
  70: #define idcunit(dev)    (minor(dev) >> 3)
  71: 
  72: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
  73: struct size {
  74:     daddr_t nblocks;
  75:     int cyloff;
  76: } rb02_sizes[8] ={
  77:     15884,  0,      /* A=cyl 0 thru 399 */
  78:     4480,   400,        /* B=cyl 400 thru 510 */
  79:     20480,  0,      /* C=cyl 0 thru 511 */
  80:     0,  0,
  81:     0,  0,
  82:     0,  0,
  83:     0,  0,
  84:     0,  0,
  85: }, rb80_sizes[8] ={
  86:     15884,  0,      /* A=cyl 0 thru 36 */
  87:     33440,  37,     /* B=cyl 37 thru 114 */
  88:     242606, 0,      /* C=cyl 0 thru 558 */
  89:     0,  0,
  90:     0,  0,
  91:     0,  0,
  92:     82080,  115,        /* G=cyl 115 thru 304 */
  93:     110143, 305,        /* H=cyl 305 thru 558 */
  94: };
  95: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
  96: 
  97: int idcprobe(), idcslave(), idcattach(), idcdgo(), idcintr();
  98: struct  uba_ctlr *idcminfo[NIDC];
  99: struct  uba_device *idcdinfo[NRB];
 100: 
 101: u_short idcstd[] = { 0174400, 0};
 102: struct  uba_driver idcdriver =
 103:  { idcprobe, idcslave, idcattach, idcdgo, idcstd, "rb", idcdinfo, "idc", idcminfo, 0 };
 104: struct  buf idcutab[NRB];
 105: union   idc_dar idccyl[NRB];
 106: 
 107: struct  idcst {
 108:     short   nbps;
 109:     short   nsect;
 110:     short   ntrak;
 111:     short   nspc;
 112:     short   ncyl;
 113:     struct  size *sizes;
 114: } idcst[] = {
 115:     256, NRB02SECT, NRB02TRK, NRB02SECT*NRB02TRK, NRB02CYL, rb02_sizes,
 116:     512, NRB80SECT, NRB80TRK, NRB80SECT*NRB80TRK, NRB80CYL, rb80_sizes,
 117: };
 118: 
 119: struct  buf ridcbuf[NRB];
 120: 
 121: #define b_cylin b_resid
 122: 
 123: int idcwstart, idcwticks, idcwatch();
 124: 
 125: /*ARGSUSED*/
 126: idcprobe(reg)
 127:     caddr_t reg;
 128: {
 129:     register int br, cvec;
 130:     register struct idcdevice *idcaddr;
 131: 
 132: #ifdef lint
 133:     br = 0; cvec = br; br = cvec;
 134: #endif
 135:     idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
 136:     idcaddr->idccsr = IDC_ATTN|IDC_IE;
 137:     while ((idcaddr->idccsr & IDC_CRDY) == 0)
 138:         ;
 139:     idcaddr->idccsr = IDC_ATTN|IDC_CRDY;
 140:     return (sizeof (struct idcdevice));
 141: }
 142: 
 143: /*ARGSUSED*/
 144: idcslave(ui, reg)
 145:     struct uba_device *ui;
 146:     caddr_t reg;
 147: {
 148:     register struct idcdevice *idcaddr;
 149:     register int i;
 150: 
 151:     idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
 152:     ui->ui_type = 0;
 153:     idcaddr->idcmpr = IDCGS_GETSTAT;
 154:     idcaddr->idccsr = IDC_GETSTAT|(ui->ui_slave<<8);
 155:     (void) idcwait(idcaddr, 0);
 156:     i = idcaddr->idcmpr;
 157:     idcaddr->idccsr = IDC_CRDY|(1<<(ui->ui_slave+16));
 158:     (void) idcwait(idcaddr, 0);
 159:     /* read header to synchronize microcode */
 160:     idcaddr->idccsr = (ui->ui_slave<<8)|IDC_RHDR;
 161:     (void) idcwait(idcaddr, 0);
 162:     i = idcaddr->idcmpr;        /* read header word 1 */
 163:     i = idcaddr->idcmpr;        /* read header word 2 */
 164: #ifdef lint
 165:     i = i;
 166: #endif
 167:     if ((idcaddr->idccsr & (IDC_ERR|IDC_R80)) == IDC_R80)
 168:         ui->ui_type = 1;
 169:     else if ((idcaddr->idccsr & (IDC_DE|IDC_R80)) == 0)
 170:         /*
 171: 		 * RB02 may not have pack spun up, just look for drive error.
 172: 		 */
 173:         ui->ui_type = 0;
 174:     else
 175:         return (0);
 176:     return (1);
 177: }
 178: 
 179: idcattach(ui)
 180:     register struct uba_device *ui;
 181: {
 182: 
 183:     /*
 184: 	 * Fix all addresses to correspond
 185: 	 * to the "real" IDC address.
 186: 	 */
 187:     ui->ui_mi->um_addr = ui->ui_addr = (caddr_t)uba_hd[0].uh_uba + 0x200;
 188:     ui->ui_physaddr = (caddr_t)uba_hd[0].uh_physuba + 0x200;
 189:     if (idcwstart == 0) {
 190:         timeout(idcwatch, (caddr_t)0, hz);
 191:         idcwstart++;
 192:     }
 193:     if (ui->ui_dk >= 0)
 194:         if (ui->ui_type)
 195:             dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB80SECT * 256);
 196:         else
 197:             dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB02SECT * 128);
 198:     idccyl[ui->ui_unit].dar_dar = -1;
 199:     ui->ui_flags = 0;
 200: }
 201: 
 202: idcopen(dev)
 203:     dev_t dev;
 204: {
 205:     register int unit = idcunit(dev);
 206:     register struct uba_device *ui;
 207: 
 208:     if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
 209:         return (ENXIO);
 210:     return (0);
 211: }
 212: 
 213: idcstrategy(bp)
 214:     register struct buf *bp;
 215: {
 216:     register struct uba_device *ui;
 217:     register struct idcst *st;
 218:     register int unit;
 219:     register struct buf *dp;
 220:     int xunit = minor(bp->b_dev) & 07;
 221:     long bn, sz;
 222: 
 223:     sz = (bp->b_bcount+511) >> 9;
 224:     unit = idcunit(bp->b_dev);
 225:     if (unit >= NRB) {
 226:         bp->b_error = ENXIO;
 227:         goto bad;
 228:     }
 229:     ui = idcdinfo[unit];
 230:     if (ui == 0 || ui->ui_alive == 0) {
 231:         bp->b_error = ENXIO;
 232:         goto bad;
 233:     }
 234:     st = &idcst[ui->ui_type];
 235:     if (bp->b_blkno < 0 ||
 236:         (bn = bp->b_blkno)+sz > st->sizes[xunit].nblocks) {
 237:         if (bp->b_blkno == st->sizes[xunit].nblocks) {
 238:             bp->b_resid = bp->b_bcount;
 239:             goto done;
 240:         }
 241:         bp->b_error = EINVAL;
 242:         goto bad;
 243:     }
 244:     if (ui->ui_type == 0)
 245:         bn *= 2;
 246:     bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
 247:     (void) spl5();
 248:     trace("strt",bp);
 249:     dp = &idcutab[ui->ui_unit];
 250:     disksort(dp, bp);
 251:     if (dp->b_active == 0) {
 252:         trace("!act",dp);
 253:         (void) idcustart(ui);
 254:         bp = &ui->ui_mi->um_tab;
 255:         if (bp->b_actf && bp->b_active == 0)
 256:             (void) idcstart(ui->ui_mi);
 257:     }
 258:     (void) spl0();
 259:     return;
 260: 
 261: bad:
 262:     bp->b_flags |= B_ERROR;
 263: done:
 264:     iodone(bp);
 265:     return;
 266: }
 267: 
 268: idcustart(ui)
 269:     register struct uba_device *ui;
 270: {
 271:     register struct buf *bp, *dp;
 272:     register struct uba_ctlr *um;
 273:     register struct idcdevice *idcaddr;
 274:     register struct idcst *st;
 275:     union idc_dar cyltrk;
 276:     daddr_t bn;
 277:     int unit;
 278: 
 279:     if (ui == 0)
 280:         return (0);
 281:     dk_busy &= ~(1<<ui->ui_dk);
 282:     dp = &idcutab[ui->ui_unit];
 283:     um = ui->ui_mi;
 284:     unit = ui->ui_slave;
 285:     trace("ust", dp);
 286:     idcaddr = (struct idcdevice *)um->um_addr;
 287:     if (um->um_tab.b_active) {
 288:         idc_softc.sc_softas |= 1<<unit;
 289:         trace("umac",idc_softc.sc_softas);
 290:         return (0);
 291:     }
 292:     if ((bp = dp->b_actf) == NULL) {
 293:         trace("!bp",0);
 294:         return (0);
 295:     }
 296:     if (dp->b_active) {
 297:         trace("dpac",dp->b_active);
 298:         goto done;
 299:     }
 300:     dp->b_active = 1;
 301:     /* CHECK DRIVE READY? */
 302:     bn = bp->b_blkno;
 303:     trace("seek", bn);
 304:     if (ui->ui_type == 0)
 305:         bn *= 2;
 306:     st = &idcst[ui->ui_type];
 307:     cyltrk.dar_cyl = bp->b_cylin;
 308:     cyltrk.dar_trk = (bn / st->nsect) % st->ntrak;
 309:     cyltrk.dar_sect = 0;
 310:     printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar);
 311:     /*
 312: 	 * If on cylinder, no need to seek.
 313: 	 */
 314:     if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar)
 315:         goto done;
 316:     /*
 317: 	 * RB80 can change heads (tracks) just by loading
 318: 	 * the disk address register, perform optimization
 319: 	 * here instead of doing a full seek.
 320: 	 */
 321:     if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) {
 322:         idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8);
 323:         idcaddr->idcdar = cyltrk.dar_dar;
 324:         idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
 325:         goto done;
 326:     }
 327:     /*
 328: 	 * Need to do a full seek.  Select the unit, clear
 329: 	 * its attention bit, set the command, load the
 330: 	 * disk address register, and then go.
 331: 	 */
 332:     idcaddr->idccsr =
 333:         IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
 334:     idcaddr->idcdar = cyltrk.dar_dar;
 335:     idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
 336:     printd("  seek");
 337:     idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8);
 338:     if (ui->ui_dk >= 0) {
 339:         dk_busy |= 1<<ui->ui_dk;
 340:         dk_seek[ui->ui_dk]++;
 341:     }
 342:     /*
 343: 	 * RB80's initiate seeks very quickly.  Wait for it
 344: 	 * to come ready rather than taking the interrupt.
 345: 	 */
 346:     if (ui->ui_type) {
 347:         if (idcwait(idcaddr, 10) == 0)
 348:             return (1);
 349:         idcaddr->idccsr &= ~IDC_ATTN;
 350:         /* has the seek completed? */
 351:         if (idcaddr->idccsr & IDC_DRDY) {
 352:             printd(", drdy");
 353:             idcaddr->idccsr =
 354:                 IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
 355:             goto done;
 356:         }
 357:     }
 358:     printd(", idccsr = 0x%x\n", idcaddr->idccsr);
 359:     return (1);
 360: done:
 361:     if (dp->b_active != 2) {
 362:         trace("!=2",dp->b_active);
 363:         dp->b_forw = NULL;
 364:         if (um->um_tab.b_actf == NULL)
 365:             um->um_tab.b_actf = dp;
 366:         else {
 367:             trace("!NUL",um->um_tab.b_actl);
 368:             um->um_tab.b_actl->b_forw = dp;
 369:         }
 370:         um->um_tab.b_actl = dp;
 371:         dp->b_active = 2;
 372:     }
 373:     return (0);
 374: }
 375: 
 376: idcstart(um)
 377:     register struct uba_ctlr *um;
 378: {
 379:     register struct buf *bp, *dp;
 380:     register struct uba_device *ui;
 381:     register struct idcdevice *idcaddr;
 382:     register struct idc_softc *sc;
 383:     struct idcst *st;
 384:     daddr_t bn;
 385:     int sn, tn, cmd;
 386: 
 387: loop:
 388:     if ((dp = um->um_tab.b_actf) == NULL) {
 389:         trace("nodp",um);
 390:         return (0);
 391:     }
 392:     if ((bp = dp->b_actf) == NULL) {
 393:         trace("nobp", dp);
 394:         um->um_tab.b_actf = dp->b_forw;
 395:         goto loop;
 396:     }
 397:     um->um_tab.b_active = 1;
 398:     ui = idcdinfo[idcunit(bp->b_dev)];
 399:     bn = bp->b_blkno;
 400:     trace("star",bp);
 401:     if (ui->ui_type == 0)
 402:         bn *= 2;
 403:     sc = &idc_softc;
 404:     st = &idcst[ui->ui_type];
 405:     sn = bn%st->nspc;
 406:     tn = sn/st->nsect;
 407:     sn %= st->nsect;
 408:     sc->sc_sect = sn;
 409:     sc->sc_trk = tn;
 410:     sc->sc_cyl = bp->b_cylin;
 411:     idcaddr = (struct idcdevice *)ui->ui_addr;
 412:     printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar);
 413:     if (bp->b_flags & B_READ)
 414:         cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8);
 415:     else
 416:         cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8);
 417:     idcaddr->idccsr = IDC_CRDY|cmd;
 418:     if ((idcaddr->idccsr&IDC_DRDY) == 0) {
 419:         printf("rb%d: not ready\n", idcunit(bp->b_dev));
 420:         um->um_tab.b_active = 0;
 421:         um->um_tab.b_errcnt = 0;
 422:         dp->b_actf = bp->av_forw;
 423:         dp->b_active = 0;
 424:         bp->b_flags |= B_ERROR;
 425:         iodone(bp);
 426:         goto loop;
 427:     }
 428:     idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
 429:     idccyl[ui->ui_unit].dar_sect = 0;
 430:     sn = (st->nsect - sn) * st->nbps;
 431:     if (sn > bp->b_bcount)
 432:         sn = bp->b_bcount;
 433:     sc->sc_bcnt = sn;
 434:     sc->sc_resid = bp->b_bcount;
 435:     sc->sc_unit = ui->ui_slave;
 436:     printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd);
 437:     um->um_cmd = cmd;
 438:     (void) ubago(ui);
 439:     return (1);
 440: }
 441: 
 442: idcdgo(um)
 443:     register struct uba_ctlr *um;
 444: {
 445:     register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
 446:     register struct idc_softc *sc = &idc_softc;
 447: 
 448:     /*
 449: 	 * VERY IMPORTANT: must load registers in this order.
 450: 	 */
 451:     idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff;
 452:     idcaddr->idcbcr = -sc->sc_bcnt;
 453:     idcaddr->idcdar = sc->sc_dar;
 454:     printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd);
 455:     idcaddr->idccsr = um->um_cmd;
 456:     trace("go", um);
 457:     um->um_tab.b_active = 2;
 458:     /*** CLEAR SPURIOUS ATTN ON R80? ***/
 459: }
 460: 
 461: idcintr(idc)
 462:     int idc;
 463: {
 464:     register struct uba_ctlr *um = idcminfo[idc];
 465:     register struct uba_device *ui;
 466:     register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
 467:     register struct idc_softc *sc = &idc_softc;
 468:     register struct buf *bp, *dp;
 469:     struct idcst *st;
 470:     int unit, as, er, cmd, ds = 0;
 471: 
 472:     printd("idcintr, idccsr 0x%x", idcaddr->idccsr);
 473: top:
 474:     idcwticks = 0;
 475:     trace("intr", um->um_tab.b_active);
 476:     if (um->um_tab.b_active == 2) {
 477:         /*
 478: 		 * Process a data transfer complete interrupt.
 479: 		 */
 480:         um->um_tab.b_active = 1;
 481:         dp = um->um_tab.b_actf;
 482:         bp = dp->b_actf;
 483:         ui = idcdinfo[idcunit(bp->b_dev)];
 484:         unit = ui->ui_slave;
 485:         st = &idcst[ui->ui_type];
 486:         idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
 487:         if ((er = idcaddr->idccsr) & IDC_ERR) {
 488:             if (er & IDC_DE) {
 489:                 idcaddr->idcmpr = IDCGS_GETSTAT;
 490:                 idcaddr->idccsr = IDC_GETSTAT|(unit<<8);
 491:                 (void) idcwait(idcaddr, 0);
 492:                 ds = idcaddr->idcmpr;
 493:                 idcaddr->idccsr =
 494:                     IDC_IE|IDC_CRDY|(1<<(unit+16));
 495:             }
 496:             printd(", er 0x%x, ds 0x%x", er, ds);
 497:             if (ds & IDCDS_WL) {
 498:                 printf("rb%d: write locked\n",
 499:                     idcunit(bp->b_dev));
 500:                 bp->b_flags |= B_ERROR;
 501:             } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) {
 502: hard:
 503:                 harderr(bp, "rb");
 504:                 printf("csr=%b ds=%b\n", er, IDCCSR_BITS, ds,
 505:                     ui->ui_type?IDCRB80DS_BITS:IDCRB02DS_BITS);
 506:                 bp->b_flags |= B_ERROR;
 507:             } else if (er & IDC_DCK) {
 508:                 switch ((int)(er & IDC_ECS)) {
 509:                 case IDC_ECS_NONE:
 510:                     break;
 511:                 case IDC_ECS_SOFT:
 512:                     idcecc(ui);
 513:                     break;
 514:                 case IDC_ECS_HARD:
 515:                 default:
 516:                     goto hard;
 517:                 }
 518:             } else
 519:                 /* recoverable error, set up for retry */
 520:                 goto seek;
 521:         }
 522:         if ((sc->sc_resid -= sc->sc_bcnt) != 0) {
 523:             sc->sc_ubaddr += sc->sc_bcnt;
 524:             /*
 525: 			 * Current transfer is complete, have
 526: 			 * we overflowed to the next track?
 527: 			 */
 528:             if ((sc->sc_sect += sc->sc_bcnt/st->nbps) == st->nsect) {
 529:                 sc->sc_sect = 0;
 530:                 if (++sc->sc_trk == st->ntrak) {
 531:                     sc->sc_trk = 0;
 532:                     sc->sc_cyl++;
 533:                 } else if (ui->ui_type) {
 534:                     /*
 535: 					 * RB80 can change heads just by
 536: 					 * loading the disk address register.
 537: 					 */
 538:                     idcaddr->idccsr = IDC_SEEK|IDC_CRDY|
 539:                         IDC_IE|(unit<<8);
 540:                     printd(", change to track 0x%x", sc->sc_dar);
 541:                     idcaddr->idcdar = sc->sc_dar;
 542:                     idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
 543:                     idccyl[ui->ui_unit].dar_sect = 0;
 544:                     goto cont;
 545:                 }
 546:                 /*
 547: 				 * Changing tracks on RB02 or cylinders
 548: 				 * on RB80, start a seek.
 549: 				 */
 550: seek:
 551:                 cmd = IDC_IE|IDC_SEEK|(unit<<8);
 552:                 idcaddr->idccsr = cmd|IDC_CRDY;
 553:                 idcaddr->idcdar = sc->sc_dar;
 554:                 printd(", seek to 0x%x\n", sc->sc_dar);
 555:                 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
 556:                 idccyl[ui->ui_unit].dar_sect = 0;
 557:                 sc->sc_bcnt = 0;
 558:                 idcaddr->idccsr = cmd;
 559:                 if (ui->ui_type) {
 560:                     if (idcwait(idcaddr, 10) == 0)
 561:                         return;
 562:                     idcaddr->idccsr &= ~IDC_ATTN;
 563:                     if (idcaddr->idccsr & IDC_DRDY)
 564:                         goto top;
 565:                 }
 566:             } else {
 567:                 /*
 568: 				 * Continue transfer on current track.
 569: 				 */
 570: cont:
 571:                 sc->sc_bcnt = (st->nsect-sc->sc_sect)*st->nbps;
 572:                 if (sc->sc_bcnt > sc->sc_resid)
 573:                     sc->sc_bcnt = sc->sc_resid;
 574:                 if (bp->b_flags & B_READ)
 575:                     cmd = IDC_IE|IDC_READ|(unit<<8);
 576:                 else
 577:                     cmd = IDC_IE|IDC_WRITE|(unit<<8);
 578:                 idcaddr->idccsr = cmd|IDC_CRDY;
 579:                 idcaddr->idcbar = sc->sc_ubaddr;
 580:                 idcaddr->idcbcr = -sc->sc_bcnt;
 581:                 idcaddr->idcdar = sc->sc_dar;
 582:                 printd(", continue I/O 0x%x, 0x%x\n", sc->sc_dar, sc->sc_bcnt);
 583:                 idcaddr->idccsr = cmd;
 584:                 um->um_tab.b_active = 2;
 585:             }
 586:             return;
 587:         }
 588:         /*
 589: 		 * Entire transfer is done, clean up.
 590: 		 */
 591:         ubadone(um);
 592:         dk_busy &= ~(1 << ui->ui_dk);
 593:         um->um_tab.b_active = 0;
 594:         um->um_tab.b_errcnt = 0;
 595:         um->um_tab.b_actf = dp->b_forw;
 596:         dp->b_active = 0;
 597:         dp->b_errcnt = 0;
 598:         dp->b_actf = bp->av_forw;
 599:         trace("done", dp); trace(&um->um_tab.b_actf, dp->b_actf);
 600:         bp->b_resid = sc->sc_resid;
 601:         printd(", iodone, resid 0x%x\n", bp->b_resid);
 602:         iodone(bp);
 603:         if (dp->b_actf)
 604:             if (idcustart(ui))
 605:                 return;
 606:     } else if (um->um_tab.b_active == 1) {
 607:         /*
 608: 		 * Got an interrupt while setting up for a command
 609: 		 * or doing a mid-transfer seek.  Save any attentions
 610: 		 * for later and process a mid-transfer seek complete.
 611: 		 */
 612:         as = idcaddr->idccsr;
 613:         idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
 614:         as = (as >> 16) & 0xf;
 615:         unit = sc->sc_unit;
 616:         sc->sc_softas |= as & ~(1<<unit);
 617:         if (as & (1<<unit)) {
 618:             printd(", seek1 complete");
 619:             um->um_tab.b_active = 2;
 620:             goto top;
 621:         }
 622:         printd(", as1 %o\n", as);
 623:         return;
 624:     }
 625:     /*
 626: 	 * Process any seek initiated or complete interrupts.
 627: 	 */
 628:     as = idcaddr->idccsr;
 629:     idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
 630:     as = ((as >> 16) & 0xf) | sc->sc_softas;
 631:     sc->sc_softas = 0;
 632:     trace("as", as);
 633:     printd(", as %o", as);
 634:     for (unit = 0; unit < NRB; unit++)
 635:         if (as & (1<<unit)) {
 636:             as &= ~(1<<unit);
 637:             idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
 638:             ui = idcdinfo[unit];
 639:             if (ui) {
 640:                 printd(", attn unit %d", unit);
 641:                 if (idcaddr->idccsr & IDC_DRDY)
 642:                     if (idcustart(ui)) {
 643:                         sc->sc_softas = as;
 644:                         return;
 645:                     }
 646:             } else {
 647:                 printd(", unsol. intr. unit %d", unit);
 648:             }
 649:         }
 650:     printd("\n");
 651:     if (um->um_tab.b_actf && um->um_tab.b_active == 0) {
 652:         trace("stum",um->um_tab.b_actf);
 653:         (void) idcstart(um);
 654:     }
 655: }
 656: 
 657: idcwait(addr, n)
 658:     register struct idcdevice *addr;
 659:     register int n;
 660: {
 661:     register int i;
 662: 
 663:     while (--n && (addr->idccsr & IDC_CRDY) == 0)
 664:         for (i = 10; i; i--)
 665:             ;
 666:     return (n);
 667: }
 668: 
 669: idcread(dev, uio)
 670:     dev_t dev;
 671:     struct uio *uio;
 672: {
 673:     register int unit = idcunit(dev);
 674: 
 675:     if (unit >= NRB)
 676:         return (ENXIO);
 677:     return (physio(idcstrategy, &ridcbuf[unit], dev, B_READ, minphys, uio));
 678: }
 679: 
 680: idcwrite(dev, uio)
 681:     dev_t dev;
 682:     struct uio *uio;
 683: {
 684:     register int unit = idcunit(dev);
 685: 
 686:     if (unit >= NRB)
 687:         return (ENXIO);
 688:     return (physio(idcstrategy, &ridcbuf[unit], dev, B_WRITE, minphys, uio));
 689: }
 690: 
 691: idcecc(ui)
 692:     register struct uba_device *ui;
 693: {
 694:     register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr;
 695:     register struct buf *bp = idcutab[ui->ui_unit].b_actf;
 696:     register struct uba_ctlr *um = ui->ui_mi;
 697:     register struct idcst *st;
 698:     register int i;
 699:     struct uba_regs *ubp = ui->ui_hd->uh_uba;
 700:     int bit, byte, mask;
 701:     caddr_t addr;
 702:     int reg, npf, o;
 703:     int cn, tn, sn;
 704: 
 705:     npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;;
 706:     reg = btop(idc_softc.sc_ubaddr) + npf;
 707:     o = (int)bp->b_un.b_addr & PGOFSET;
 708:     st = &idcst[ui->ui_type];
 709:     cn = idc_softc.sc_cyl;
 710:     tn = idc_softc.sc_trk;
 711:     sn = idc_softc.sc_sect;
 712:     um->um_tab.b_active = 1;    /* Either complete or continuing... */
 713:     log(LOG_WARNING, "rb%d%c: soft ecc sn%d\n", idcunit(bp->b_dev),
 714:         'a'+(minor(bp->b_dev)&07),
 715:         (cn*st->ntrak + tn) * st->nsect + sn + npf);
 716:     mask = idc->idceccpat;
 717:     i = idc->idceccpos - 1;     /* -1 makes 0 origin */
 718:     bit = i&07;
 719:     i = (i&~07)>>3;
 720:     byte = i + o;
 721:     while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) {
 722:         /*
 723: 		 * should be:
 724: 		 *	addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
 725: 		 *		(byte & PGOFSET);
 726: 		 * but this generates an extzv which hangs the UNIBUS.
 727: 		 */
 728:         addr = ptob(*(int *)&ubp->uba_map[reg+btop(byte)]&0x1fffff)+
 729:             (byte & PGOFSET);
 730:         putmemc(addr, getmemc(addr)^(mask<<bit));
 731:         byte++;
 732:         i++;
 733:         bit -= 8;
 734:     }
 735:     idc_softc.sc_bcnt += idc->idcbcr;
 736:     um->um_tab.b_errcnt = 0;    /* error has been corrected */
 737:     return;
 738: }
 739: 
 740: idcreset(uban)
 741:     int uban;
 742: {
 743:     register struct uba_ctlr *um;
 744:     register struct uba_device *ui;
 745:     register unit;
 746: 
 747:     if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban ||
 748:         um->um_alive == 0)
 749:         return;
 750:     printf(" idc0");
 751:     um->um_tab.b_active = 0;
 752:     um->um_tab.b_actf = um->um_tab.b_actl = 0;
 753:     if (um->um_ubinfo) {
 754:         printf("<%d>", (um->um_ubinfo>>28)&0xf);
 755:         um->um_ubinfo = 0;
 756:     }
 757:     for (unit = 0; unit < NRB; unit++) {
 758:         if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
 759:             continue;
 760:         idcutab[unit].b_active = 0;
 761:         (void) idcustart(ui);
 762:     }
 763:     (void) idcstart(um);
 764: }
 765: 
 766: idcwatch()
 767: {
 768:     register struct uba_ctlr *um;
 769:     register unit;
 770: 
 771:     timeout(idcwatch, (caddr_t)0, hz);
 772:     um = idcminfo[0];
 773:     if (um == 0 || um->um_alive == 0)
 774:         return;
 775:     if (um->um_tab.b_active == 0) {
 776:         for (unit = 0; unit < NRB; unit++)
 777:             if (idcutab[unit].b_active)
 778:                 goto active;
 779:         idcwticks = 0;
 780:         return;
 781:     }
 782: active:
 783:     idcwticks++;
 784:     if (idcwticks >= 20) {
 785:         idcwticks = 0;
 786:         printf("idc0: lost interrupt\n");
 787:         idcintr(0);
 788:     }
 789: }
 790: 
 791: /*ARGSUSED*/
 792: idcdump(dev)
 793:     dev_t dev;
 794: {
 795:     struct idcdevice *idcaddr;
 796:     char *start;
 797:     int num, blk, unit;
 798:     struct size *sizes;
 799:     register struct uba_regs *uba;
 800:     register struct uba_device *ui;
 801:     struct idcst *st;
 802:     union idc_dar dar;
 803:     int nspg;
 804: 
 805:     unit = idcunit(dev);
 806:     if (unit >= NRB)
 807:         return (ENXIO);
 808: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
 809:     ui = phys(struct uba_device *, idcdinfo[unit]);
 810:     if (ui->ui_alive == 0)
 811:         return (ENXIO);
 812:     uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
 813:     ubainit(uba);
 814:     idcaddr = (struct idcdevice *)ui->ui_physaddr;
 815:     if (idcwait(idcaddr, 100) == 0)
 816:         return (EFAULT);
 817:     /*
 818: 	 * Since we can only transfer one track at a time, and
 819: 	 * the rl02 has 256 byte sectors, all the calculations
 820: 	 * are done in terms of physical sectors (i.e. num and blk
 821: 	 * are in sectors not NBPG blocks.
 822: 	 */
 823:     st = phys(struct idcst *, &idcst[ui->ui_type]);
 824:     sizes = phys(struct size *, st->sizes);
 825:     if (dumplo < 0)
 826:         return (EINVAL);
 827:     if (dumplo + maxfree >= sizes[minor(dev)&07].nblocks)
 828:         num = sizes[minor(dev)&07].nblocks - dumplo;
 829:     nspg = NBPG / st->nbps;
 830:     num = num * nspg;
 831:     start = 0;
 832: 
 833:     while (num > 0) {
 834:         register struct pte *io;
 835:         register int i;
 836:         daddr_t bn;
 837: 
 838:         bn = (dumplo + btop(start)) * nspg;
 839:         dar.dar_cyl = bn / st->nspc + sizes[minor(dev)&07].cyloff;
 840:         bn %= st->nspc;
 841:         dar.dar_trk = bn / st->nsect;
 842:         dar.dar_sect = bn % st->nsect;
 843:         blk = st->nsect - dar.dar_sect;
 844:         if (num < blk)
 845:             blk = num;
 846: 
 847:         io = uba->uba_map;
 848:         for (i = 0; i < (blk + nspg - 1) / nspg; i++)
 849:             *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
 850:         *(int *)io = 0;
 851: 
 852:         idcaddr->idccsr = IDC_CRDY | IDC_SEEK | unit<<8;
 853:         if ((idcaddr->idccsr&IDC_DRDY) == 0)
 854:             return (EFAULT);
 855:         idcaddr->idcdar = dar.dar_dar;
 856:         idcaddr->idccsr = IDC_SEEK | unit << 8;
 857:         while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
 858:             != (IDC_CRDY|IDC_DRDY))
 859:             ;
 860:         if (idcaddr->idccsr & IDC_ERR) {
 861:             printf("rb%d: seek, csr=%b\n",
 862:                 unit, idcaddr->idccsr, IDCCSR_BITS);
 863:             return (EIO);
 864:         }
 865: 
 866:         idcaddr->idccsr = IDC_CRDY | IDC_WRITE | unit<<8;
 867:         if ((idcaddr->idccsr&IDC_DRDY) == 0)
 868:             return (EFAULT);
 869:         idcaddr->idcbar = 0;            /* start addr 0 */
 870:         idcaddr->idcbcr = - (blk * st->nbps);
 871:         idcaddr->idcdar = dar.dar_dar;
 872:         idcaddr->idccsr = IDC_WRITE | unit << 8;
 873:         while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
 874:             != (IDC_CRDY|IDC_DRDY))
 875:             ;
 876:         if (idcaddr->idccsr & IDC_ERR) {
 877:             printf("rb%d: write, csr=%b\n",
 878:                 unit, idcaddr->idccsr, IDCCSR_BITS);
 879:             return (EIO);
 880:         }
 881: 
 882:         start += blk * st->nbps;
 883:         num -= blk;
 884:     }
 885:     return (0);
 886: }
 887: 
 888: idcsize(dev)
 889:     dev_t dev;
 890: {
 891:     int unit = idcunit(dev);
 892:     struct uba_device *ui;
 893:     struct idcst *st;
 894: 
 895:     if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
 896:         return (-1);
 897:     st = &idcst[ui->ui_type];
 898:     return (st->sizes[minor(dev) & 07].nblocks);
 899: }
 900: #endif

Defined functions

idcattach defined in line 179; used 2 times
idcdgo defined in line 442; used 2 times
idcdump defined in line 792; never used
idcecc defined in line 691; used 1 times
idcintr defined in line 461; used 3 times
idcopen defined in line 202; never used
idcprobe defined in line 126; used 2 times
idcread defined in line 669; never used
idcreset defined in line 740; never used
idcsize defined in line 888; never used
idcslave defined in line 144; used 2 times
idcstart defined in line 376; used 3 times
idcstrategy defined in line 213; used 2 times
idcustart defined in line 268; used 4 times
idcwait defined in line 657; used 7 times
idcwatch defined in line 766; used 3 times
idcwrite defined in line 680; never used

Defined variables

idc_softc defined in line 59; used 12 times
idccyl defined in line 105; used 11 times
idcdebug defined in line 11; used 1 times
  • in line 12
idcdinfo defined in line 99; used 9 times
idcdriver defined in line 102; used 4 times
idcminfo defined in line 98; used 4 times
idcst defined in line 114; used 7 times
idcstd defined in line 101; used 1 times
idctrb defined in line 13; used 3 times
idcutab defined in line 104; used 5 times
idcwstart defined in line 123; used 2 times
idcwticks defined in line 123; used 5 times
rb02_sizes defined in line 76; used 1 times
ridcbuf defined in line 119; used 2 times
trp defined in line 14; used 4 times
  • in line 15(4)

Defined struct's

idc_softc defined in line 48; used 6 times
idcst defined in line 107; used 16 times
size defined in line 73; used 6 times

Defined union's

idc_dar defined in line 54; used 6 times

Defined macros

b_cylin defined in line 121; used 3 times
dar_cyl defined in line 62; used 5 times
dar_dar defined in line 61; used 16 times
dar_sect defined in line 64; used 7 times
dar_trk defined in line 63; used 3 times
idcunit defined in line 70; used 11 times
phys defined in line 808; used 4 times
printd defined in line 12; used 19 times
sc_cyl defined in line 66; used 3 times
sc_dar defined in line 65; used 11 times
sc_sect defined in line 68; used 5 times
sc_trk defined in line 67; used 4 times
trace defined in line 15; used 18 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2799
Valid CSS Valid XHTML 1.0 Strict