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:  *	@(#)rx.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "rx.h"
  10: #if NFX > 0
  11: /*
  12:  * RX02 floppy disk device driver
  13:  *
  14:  */
  15: 
  16: /*
  17:  * TODO:
  18:  *	- clean up the code for multisector transfers using
  19:  *	  a 'transfer in progress' flag
  20:  *	- Test Deleted Data read/write
  21:  *	- Test error handling/reporting and 'volume valid' stuff
  22:  *
  23:  * 	Note: If the drive subsystem is
  24:  * 	powered off at boot time, the controller won't interrupt!
  25:  */
  26: 
  27: #include "../machine/pte.h"
  28: 
  29: #include "param.h"
  30: #include "buf.h"
  31: #include "systm.h"
  32: #include "conf.h"
  33: #include "errno.h"
  34: #include "time.h"
  35: #include "kernel.h"
  36: #include "uio.h"
  37: #include "file.h"
  38: 
  39: #include "../vax/cpu.h"
  40: #include "../vax/nexus.h"
  41: 
  42: #include "ubavar.h"
  43: #include "ubareg.h"
  44: #include "rxreg.h"
  45: 
  46: #define b_cylin b_resid
  47: 
  48: /* per-controller data */
  49: struct  rx_ctlr {
  50:     int rxc_state;  /* controller state */
  51: #define RXS_READ    1   /* read started	*/
  52: #define RXS_EMPTY   2   /* empty started */
  53: #define RXS_FILL    3   /* fill started	*/
  54: #define RXS_WRITE   4   /* write started */
  55: #define RXS_FORMAT  5   /* format started */
  56: #define RXS_RDSTAT  6   /* status read started */
  57: #define RXS_RDERR   7   /* error read started */
  58: #define RXS_IDLE    8   /* device is idle */
  59:     u_short rxc_rxcs;   /* extended error status */
  60:     u_short rxc_rxdb;
  61:     u_short rxc_rxxt[4];
  62:     int rxc_tocnt;  /* for watchdog routine */
  63: #define RX_MAXTIMEOUT   30  /* # seconds to wait before giving up */
  64: } rx_ctlr[NFX];
  65: 
  66: /* per-drive buffers */
  67: struct buf  rrxbuf[NRX];    /* buffers for raw I/O */
  68: struct buf  erxbuf[NRX];    /* buffers for reading error status */
  69: struct buf  rxutab[NRX];    /* per drive buffers */
  70: 
  71: /* per-drive data */
  72: struct rx_softc {
  73:     int sc_flags;   /* drive status flags */
  74: #define RXF_DIRECT  0x01    /* if set: use direct sector mapping */
  75: #define RXF_TRKONE  0x02    /* if set: start mapping on track 1 */
  76: #define RXF_DBLDEN  0x04    /* use double density */
  77: #define RXF_DEVTYPE 0x07    /* mapping flags */
  78: #define RXF_LOCK    0x10    /* exclusive use */
  79: #define RXF_DDMK    0x20    /* deleted-data mark detected */
  80: #define RXF_USEWDDS 0x40    /* write deleted-data sector */
  81: #define RXF_FORMAT  0x80    /* format in progress */
  82: #define RXF_BAD     0x100   /* drive bad, cannot be used */
  83:     int sc_csbits;  /* constant bits for CS register */
  84:     int sc_open;    /* count number of opens */
  85:     int sc_offset;  /* raw mode kludge to avoid restricting */
  86:                 /* single sector transfers to start on */
  87:                 /* DEV_BSIZE boundaries */
  88:     /*
  89: 	 * The rest of this structure is used to
  90: 	 * store temporaries while simulating multi
  91: 	 * sector transfers
  92: 	 */
  93:     caddr_t sc_uaddr;   /* unibus base address */
  94:     long    sc_bcnt;    /* total transfer count */
  95:     long    sc_resid;   /* no. of bytes left to transfer */
  96: } rx_softc[NRX];
  97: 
  98: struct rxerr {
  99:     short   rxcs;
 100:     short   rxdb;
 101:     short   rxxt[4];    /* error code dump from controller */
 102: } rxerr[NRX];
 103: /* End of per-drive data */
 104: 
 105: struct  uba_device *rxdinfo[NRX];
 106: struct  uba_ctlr *rxminfo[NFX];
 107: 
 108: struct buf *savebp;
 109: 
 110: int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(), rxwatch(), rxphys();
 111: u_short rxstd[] = { 0177170, 0177150, 0 };
 112: struct uba_driver fxdriver =
 113:   { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo };
 114: 
 115: int rxwstart;
 116: #define RXUNIT(dev) (minor(dev)>>3)
 117: #define MASKREG(reg)    (reg&0xffff)
 118: 
 119: /* constants related to floppy data capacity */
 120: #define RXSECS  2002                /* # sectors on a floppy */
 121: #define DDSTATE (sc->sc_csbits&RX_DDEN)
 122: #define NBPS    (DDSTATE ? 256 : 128)       /* # bytes per sector */
 123: #define RXSIZE  (DDSTATE ? 512512 : 256256) /* # bytes per disk */
 124: #define SECMASK (DDSTATE ? 0xff : 0x7f)     /* shifted-out bits of offset */
 125: 
 126: #define B_CTRL      0x80000000      /* control (format) request */
 127: #define B_RDSTAT    0x40000000      /* read drive status (open) */
 128: 
 129: /*ARGSUSED*/
 130: rxprobe (reg)
 131:     caddr_t reg;
 132: {
 133:     register int br, cvec;          /* value-result */
 134:     struct rxdevice *rxaddr = (struct rxdevice *)reg;
 135: 
 136: #ifdef lint
 137:     br = 0; cvec = br; br = cvec;
 138:     rxintr(0);
 139: #endif lint
 140:     rxaddr->rxcs = RX_INTR;
 141:     DELAY(10);
 142:     rxaddr->rxcs = 0;
 143:     return (sizeof (*rxaddr));
 144: }
 145: 
 146: rxslave(ui, reg)
 147:     struct uba_device *ui;
 148:     caddr_t reg;
 149: {
 150: 
 151:     ui->ui_dk = 1;
 152:     return (ui->ui_slave == 0 || ui->ui_slave == 1);
 153: }
 154: 
 155: /*ARGSUSED*/
 156: rxattach(ui)
 157:     struct uba_device *ui;
 158: {
 159: 
 160: }
 161: 
 162: /*ARGSUSED1*/
 163: rxopen(dev, flag)
 164:     dev_t dev;
 165: {
 166:     register int unit = RXUNIT(dev);
 167:     register struct rx_softc *sc;
 168:     register struct uba_device *ui;
 169:     struct rx_ctlr *rxc;
 170: 
 171:     if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
 172:         return (ENXIO);
 173:     sc = &rx_softc[unit];
 174:     if (sc->sc_open == 0 && sc->sc_csbits == 0) {
 175:         struct buf *bp = &erxbuf[unit];
 176:         /*
 177: 		 * lock the device while an open
 178: 		 * is in progress
 179: 		 */
 180:         sc->sc_flags = (minor(dev) & RXF_DEVTYPE) | RXF_LOCK;
 181:         sc->sc_csbits = RX_INTR;
 182:         sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
 183: 
 184:         bp->b_dev = dev;
 185:         bp->b_flags = B_RDSTAT | B_BUSY;
 186:         bp->b_error = 0;
 187:         bp->b_blkno = 0;
 188:         sc->sc_offset = 0;
 189:         sc->sc_resid  = 0;
 190:         /*
 191: 		 * read device status to determine if
 192: 		 * a floppy is present in the drive and
 193: 		 * what density it is
 194: 		 */
 195:         rxstrategy(bp);
 196:         iowait(bp);
 197:         if (bp->b_flags & B_ERROR) {
 198:             sc->sc_csbits = 0;
 199:             sc->sc_flags &= ~RXF_LOCK;
 200:             return (bp->b_error);
 201:         }
 202:         if (rxwstart++ == 0) {
 203:             rxc = &rx_ctlr[ui->ui_mi->um_ctlr];
 204:             rxc->rxc_tocnt = 0;
 205:             timeout(rxwatch, (caddr_t)0, hz);  /* start watchdog */
 206:         }
 207: #ifdef RXDEBUG
 208:         printf("rxopen: csbits=0x%x\n", sc->sc_csbits);
 209: #endif
 210:         sc->sc_flags &= ~RXF_LOCK;
 211:     } else  {
 212:         if (sc->sc_flags & RXF_LOCK)
 213:             return(EBUSY);
 214:     }
 215:     sc->sc_open = 1;
 216:     return (0);
 217: }
 218: 
 219: /*ARGSUSED1*/
 220: rxclose(dev, flag)
 221:     dev_t dev;
 222: {
 223:     register struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
 224: 
 225:     sc->sc_open = 0;
 226: #ifdef RXDEBUG
 227:     printf("rxclose: dev=0x%x, sc_open=%d\n", dev, sc->sc_open);
 228: #endif
 229: }
 230: 
 231: rxstrategy(bp)
 232:     register struct buf *bp;
 233: {
 234:     struct uba_device *ui;
 235:     register struct buf *dp;
 236:     struct rx_softc *sc;
 237:     int s, unit = RXUNIT(bp->b_dev);
 238: 
 239:     if (unit >= NRX)
 240:         goto bad;
 241:     ui = rxdinfo[unit];
 242:     if (ui == 0 || ui->ui_alive == 0)
 243:         goto bad;
 244:     sc = &rx_softc[unit];
 245:     if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)
 246:         goto bad;
 247:     if (sc->sc_flags & RXF_BAD) {
 248:         bp->b_error = EIO;
 249:         goto dbad;
 250:     }
 251:     s = spl5();
 252: #ifdef RXDEBUG
 253:     printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n",
 254:         bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);
 255: #endif
 256:     bp->b_cylin = bp->b_blkno;  /* don't care to calculate trackno */
 257:     dp = &rxutab[unit];
 258:     disksort(dp, bp);
 259:     if (dp->b_active == 0) {
 260:         rxustart(ui);
 261:         bp = &ui->ui_mi->um_tab;
 262:         if (bp->b_actf && bp->b_active == 0)
 263:             rxstart(ui->ui_mi);
 264:     }
 265:     splx(s);
 266:     return;
 267: 
 268: bad:
 269:     bp->b_error = ENXIO;
 270: dbad:
 271:     bp->b_flags |= B_ERROR;
 272:     iodone(bp);
 273:     return;
 274: }
 275: 
 276: /*
 277:  * Unit start routine.
 278:  * Put this unit on the ready queue for the controller
 279:  */
 280: rxustart(ui)
 281:     register struct uba_device *ui;
 282: {
 283:     struct buf *dp = &rxutab[ui->ui_unit];
 284:     struct uba_ctlr *um = ui->ui_mi;
 285: 
 286:     dp->b_forw = NULL;
 287:     if (um->um_tab.b_actf == NULL)
 288:         um->um_tab.b_actf = dp;
 289:     else
 290:         um->um_tab.b_actl->b_forw = dp;
 291:     um->um_tab.b_actl = dp;
 292:     dp->b_active++;
 293: }
 294: /*
 295:  * Sector mapping routine.
 296:  * Two independent sets of choices are available:
 297:  *
 298:  * (a) The first logical sector may either be on track 1 or track 0.
 299:  * (b) The sectors on a track may either be taken in 2-for-1 interleaved
 300:  *	 fashion or directly.
 301:  * This gives a total of four possible mapping schemes.
 302:  *
 303:  * Physical tracks on the RX02 are numbered 0-76.  Physical sectors on
 304:  * each track are numbered 1-26.
 305:  *
 306:  * When interleaving is used, sectors on the first logical track are
 307:  * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26.  A skew of
 308:  * six sectors per track is also used (to allow time for the heads to
 309:  * move); hence, the sectors on the second logical track are taken in
 310:  * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6;
 311:  * the third logical track starts with sector 13; and so on.
 312:  *
 313:  * When the mapping starts with track 1, track 0 is the last logical
 314:  * track, and this track is always handled directly (without inter-
 315:  * leaving), even when the rest of the disk is interleaved.  (This is
 316:  * still compatible with DEC RT-11, which does not use track 0 at all.)
 317:  */
 318: rxmap(bp, psector, ptrack)
 319:     struct buf *bp;
 320:     int *psector, *ptrack;
 321: {
 322:     register int lt, ls, ptoff;
 323:     struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
 324: 
 325:     ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;
 326:     lt = ls / 26;
 327:     ls %= 26;
 328:     /*
 329: 	 * The "physical track offset" (ptoff) takes the
 330: 	 * starting physical track (0 or 1) and the desired
 331: 	 * interleaving into account.  If lt+ptoff >= 77,
 332: 	 * then interleaving is not performed.
 333: 	 */
 334:     ptoff = 0;
 335:     if (sc->sc_flags & RXF_DIRECT)
 336:         ptoff = 77;
 337:     if (sc->sc_flags & RXF_TRKONE)
 338:         ptoff++;
 339:     if (lt + ptoff < 77)
 340:         ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
 341:     *ptrack = (lt + ptoff) % 77;
 342:     *psector = ls + 1;
 343: }
 344: 
 345: /*
 346:  * Controller start routine.
 347:  * Start a new transfer or continue a multisector
 348:  * transfer. If this is a new transfer (dp->b_active == 1)
 349:  * save the start address of the data buffer and the total
 350:  * byte count in the soft control structure. These are
 351:  * restored into the buffer structure when the transfer has
 352:  * been completed, before calling 'iodone'.
 353:  */
 354: rxstart(um)
 355:     register struct uba_ctlr *um;
 356: {
 357:     register struct rxdevice *rxaddr;
 358:     register struct rx_ctlr *rxc;
 359:     register struct rx_softc *sc;
 360:     struct buf *dp, *bp;
 361:     int unit, sector, track;
 362: 
 363:     if (um->um_tab.b_active)
 364:         return;
 365: loop:
 366:     if ((dp = um->um_tab.b_actf) == NULL)
 367:         return;
 368:     if ((bp = dp->b_actf) == NULL) {
 369:         um->um_tab.b_actf = dp->b_forw;
 370:         goto loop;
 371:     }
 372:     um->um_tab.b_active++;
 373:     unit = RXUNIT(bp->b_dev);
 374:     sc = &rx_softc[unit];
 375:     if (sc->sc_flags & RXF_BAD) {
 376:         rxpurge(um);
 377:         return;
 378:     }
 379:     if (dp->b_active == 1) {
 380:         sc->sc_resid = bp->b_bcount;
 381:         sc->sc_uaddr = bp->b_un.b_addr;
 382:         sc->sc_bcnt = bp->b_bcount;
 383:         sc->sc_offset += sc->sc_bcnt;
 384:         dp->b_active++;
 385:     }
 386:     rxaddr = (struct rxdevice *)um->um_addr;
 387:     rxc = &rx_ctlr[um->um_ctlr];
 388:     bp->b_bcount = sc->sc_resid;
 389:     if (bp->b_bcount > NBPS)
 390:         bp->b_bcount = NBPS;
 391:     rxc->rxc_tocnt = 0;
 392: #ifdef RXDEBUG
 393:     printf("rxstart: ");
 394: #endif
 395:     if (rxaddr->rxcs == 0x800) {
 396:         /*
 397: 		 * 'Volume valid'? (check if the
 398: 		 * drive unit has been powered down)
 399: 		 */
 400:         rxaddr->rxcs = RX_INIT;
 401:         while((rxaddr->rxcs&RX_DONE) == 0)
 402:             ;
 403:     }
 404:     if (bp->b_flags & B_CTRL) {             /* format */
 405:         rxc->rxc_state = RXS_FORMAT;
 406:         rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;
 407:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 408:             ;
 409:         rxaddr->rxdb = 'I';
 410:         return;
 411:     }
 412:     if (bp->b_flags & B_RDSTAT) {           /* read drive status */
 413:         rxc->rxc_state = RXS_RDSTAT;
 414:         rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
 415:         return;
 416:     }
 417: 
 418:     if (bp->b_flags & B_READ) {
 419:         rxmap(bp, &sector, &track);         /* read */
 420: #ifdef RXDEBUG
 421:         printf("read tr=%d, sc=%d", track, sector);
 422: #endif
 423:         rxc->rxc_state = RXS_READ;
 424:         rxaddr->rxcs = RX_READ | sc->sc_csbits;
 425:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 426:             ;
 427:         rxaddr->rxdb = (u_short)sector;
 428:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 429:             ;
 430:         rxaddr->rxdb = (u_short)track;
 431:     } else {
 432: #ifdef RXDEBUG
 433:         printf("write");
 434: #endif
 435:         rxc->rxc_state = RXS_FILL;          /* write */
 436:         um->um_cmd = RX_FILL;
 437:         (void) ubago(rxdinfo[unit]);
 438:     }
 439: #ifdef RXDEBUG
 440:     printf("\n");
 441: #endif
 442: }
 443: 
 444: rxdgo(um)
 445:     struct uba_ctlr *um;
 446: {
 447:     register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
 448:     int ubinfo = um->um_ubinfo;
 449:     struct buf *bp = um->um_tab.b_actf->b_actf;
 450:     struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
 451:     struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
 452: 
 453:     rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
 454:     if (rxc->rxc_state != RXS_RDERR) {
 455:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 456:             ;
 457:         rxaddr->rxdb = (u_short) bp->b_bcount >> 1;
 458:     }
 459:     while ((rxaddr->rxcs&RX_TREQ) == 0)
 460:         ;
 461:     rxaddr->rxdb = (u_short) ubinfo;
 462: }
 463: 
 464: rxintr(ctlr)
 465:     int ctlr;
 466: {
 467:     int unit, sector, track;
 468:     struct uba_ctlr *um = rxminfo[ctlr];
 469:     register struct rxdevice *rxaddr;
 470:     register struct buf *bp, *dp;
 471:     register struct rx_softc *sc;
 472:     struct uba_device *ui;
 473:     struct rxerr *er;
 474:     struct rx_ctlr *rxc;
 475: 
 476:     if (!um->um_tab.b_active)
 477:         return;
 478:     dp = um->um_tab.b_actf;
 479:     if (!dp->b_active)
 480:         return;
 481:     bp = dp->b_actf;
 482:     unit = RXUNIT(bp->b_dev);
 483:     sc = &rx_softc[unit];
 484:     ui = rxdinfo[unit];
 485:     rxaddr = (struct rxdevice *)um->um_addr;
 486:     rxc = &rx_ctlr[um->um_ctlr];
 487:     rxc->rxc_tocnt = 0;
 488:     er = &rxerr[unit];
 489: #ifdef RXDEBUG
 490:     printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n",
 491:         bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);
 492: #endif
 493:     if ((rxaddr->rxcs & RX_ERR) &&
 494:         (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR))
 495:         goto error;
 496:     switch (rxc->rxc_state) {
 497: 
 498:     /*
 499: 	 * Incomplete commands.  Perform next step
 500: 	 * and return.  Note that b_active is set on
 501: 	 * entrance and, therefore, also on exit.
 502: 	 */
 503:     case RXS_READ:
 504:         if (rxaddr->rxdb & RXES_DDMARK)
 505:             sc->sc_flags |= RXF_DDMK;
 506:         else
 507:             sc->sc_flags &= ~RXF_DDMK;
 508:         rxc->rxc_state = RXS_EMPTY;
 509:         um->um_cmd = RX_EMPTY;
 510:         (void) ubago(ui);
 511:         return;
 512: 
 513:     case RXS_FILL:
 514:         rxc->rxc_state = RXS_WRITE;
 515:         if (sc->sc_flags & RXF_USEWDDS) {
 516:             rxaddr->rxcs = RX_WDDS | sc->sc_csbits;
 517:             sc->sc_flags &= ~RXF_USEWDDS;
 518:         } else
 519:             rxaddr->rxcs = RX_WRITE | sc->sc_csbits;
 520:         rxmap(bp, &sector, &track);
 521:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 522:             ;
 523:         rxaddr->rxdb = sector;
 524:         while ((rxaddr->rxcs&RX_TREQ) == 0)
 525:             ;
 526:         rxaddr->rxdb = track;
 527:         return;
 528: 
 529:     /*
 530: 	 * Possibly completed command.
 531: 	 */
 532:     case RXS_RDSTAT:
 533:         if (bp->b_flags & B_RDSTAT) {
 534:             if ((rxaddr->rxdb&RXES_READY) == 0) {
 535:                 bp->b_flags |= B_ERROR;
 536:                 bp->b_error = ENODEV;
 537:             } else {
 538:                 sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ?
 539:                     RX_DDEN : RX_SDEN;
 540:             }
 541:             goto rdone;
 542:         }
 543:         if (rxaddr->rxdb&RXES_READY)
 544:             goto rderr;
 545:         bp->b_error = ENODEV;
 546:         bp->b_flags |= B_ERROR;
 547:         goto done;
 548: 
 549:     /*
 550: 	 * Command completed.
 551: 	 */
 552:     case RXS_EMPTY:
 553:     case RXS_WRITE:
 554:         goto done;
 555: 
 556:     case RXS_FORMAT:
 557:         goto rdone;
 558: 
 559:     case RXS_RDERR:
 560:         bp = savebp;
 561:         rxmap(bp, &sector, &track);
 562:         printf("rx%d: hard error, trk %d psec %d ",
 563:             unit, track, sector);
 564:         printf("cs=%b, db=%b, err=", MASKREG(er->rxcs),
 565:             RXCS_BITS, MASKREG(er->rxdb), RXES_BITS);
 566:         printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]),
 567:             MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]),
 568:             MASKREG(er->rxxt[3]));
 569:         goto done;
 570: 
 571:     default:
 572:         printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
 573:         rxreset(um->um_ubanum);
 574:         return;
 575:     }
 576: error:
 577:     /*
 578: 	 * In case of an error:
 579: 	 *  (a) Give up now if a format (ioctl) was in progress, if a
 580: 	 *	  density error was detected, or if the drive went offline
 581: 	 *  (b) Retry up to nine times if a CRC (data) error was detected,
 582: 	 *	  then give up if the error persists.
 583: 	 *  (c) In all other cases, reinitialize the drive and try the
 584: 	 *	  operation once more before giving up.
 585: 	 */
 586:     if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR))
 587:         goto giveup;
 588:     if (rxaddr->rxdb & RXES_CRCERR) {
 589:         if (++um->um_tab.b_errcnt >= 10)
 590:             goto giveup;
 591:         goto retry;
 592:     }
 593:     um->um_tab.b_errcnt += 9;
 594:     if (um->um_tab.b_errcnt >= 10)
 595:         goto giveup;
 596:     rxaddr->rxcs = RX_INIT;
 597:     /* no way to get an interrupt for "init done", so just wait */
 598:     while ((rxaddr->rxcs&RX_DONE) == 0)
 599:         ;
 600:     /* if someone opened the drive: give up */
 601:     if ((rxaddr->rxdb&RXES_READY) == 0)
 602:         goto giveup;
 603: retry:
 604:     /*
 605: 	 * In case we already have UNIBUS resources, give
 606: 	 * them back since we reallocate things in rxstart.
 607: 	 */
 608:     if (um->um_ubinfo)
 609:         ubadone(um);
 610:     um->um_tab.b_active = 0;
 611:     rxstart(um);
 612:     return;
 613: 
 614: giveup:
 615:     /*
 616: 	 * Hard I/O error --
 617: 	 * ALL errors are considered fatal and will abort the
 618: 	 * transfer and purge the i/o request queue
 619: 	 */
 620:     sc->sc_flags |= RXF_BAD;
 621:     sc->sc_resid = 0;   /* make sure the transfer is terminated */
 622:     rxc->rxc_state = RXS_RDSTAT;
 623:     rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
 624:     return;
 625: 
 626: rderr:
 627:     /*
 628: 	 * A hard error (other than not ready) has occurred.
 629: 	 * Read the extended error status information.
 630: 	 * Before doing this, save the current CS and DB register values,
 631: 	 * because the read error status operation may modify them.
 632: 	 * Insert buffer with request at the head of the queue.
 633: 	 */
 634:     bp->b_error = EIO;
 635:     bp->b_flags |= B_ERROR;
 636:     if (um->um_ubinfo)
 637:         ubadone(um);
 638:     savebp = bp;
 639:     er->rxcs = rxaddr->rxcs;
 640:     er->rxdb = rxaddr->rxdb;
 641:     bp = &erxbuf[unit];
 642:     bp->b_un.b_addr = (caddr_t)er->rxxt;
 643:     bp->b_bcount = sizeof (er->rxxt);
 644:     bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
 645:     if (dp->b_actf == NULL)
 646:         dp->b_actl = bp;
 647:     bp->b_forw = dp->b_actf;
 648:     dp->b_actf = bp;
 649:     rxc->rxc_state = RXS_RDERR;
 650:     um->um_cmd = RX_RDERR;
 651:     (void) ubago(ui);
 652:     return;
 653: 
 654: done:
 655:     ubadone(um);
 656: rdone:
 657:     um->um_tab.b_active = 0;
 658:     um->um_tab.b_errcnt = 0;
 659:     if ((sc->sc_resid -= NBPS) > 0) {
 660:         bp->b_un.b_addr += NBPS;
 661:         rxstart(um);
 662:         return;
 663:     }
 664:     bp->b_un.b_addr = sc->sc_uaddr;
 665:     bp->b_resid = 0;
 666:     bp->b_bcount = sc->sc_bcnt;
 667:     dp->b_actf = bp->av_forw;
 668:     iodone(bp);
 669:     sc->sc_offset = 0;
 670:     rxc->rxc_state = RXS_IDLE;
 671:     um->um_tab.b_actf = dp->b_forw;
 672:     dp->b_active = 0;
 673:     dp->b_errcnt = 0;
 674: #ifdef RXDEBUG
 675:     printf(".. bp=%x, new=%x\n", bp, dp->b_actf);
 676: #endif
 677:     /*
 678: 	 * If this unit has more work to do,
 679: 	 * start it up right away
 680: 	 */
 681:     if (dp->b_actf)
 682:         rxustart(ui);
 683: 
 684:     rxstart(um);
 685: }
 686: 
 687: /*ARGSUSED*/
 688: 
 689: rxwatch()
 690: {
 691:     register struct uba_device *ui;
 692:     register struct uba_ctlr *um;
 693:     register struct rx_softc *sc;
 694:     struct rx_ctlr *rxc;
 695:     int i, dopen = 0;
 696: 
 697:     for (i=0; i<NRX; i++) {
 698:         ui = rxdinfo[i];
 699:         if (ui == 0 || ui->ui_alive == 0)
 700:             continue;
 701:         sc = &rx_softc[i];
 702:         if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) {
 703:             sc->sc_csbits = 0;
 704:             continue;
 705:         }
 706:         dopen++;
 707:         um = ui->ui_mi;
 708:         rxc = &rx_ctlr[um->um_ctlr];
 709:         if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) {
 710:             rxc->rxc_tocnt = 0;
 711:             if (um->um_tab.b_active) {
 712:                 printf("rx%d: timeout\n", i);/* for debugging */
 713:                 rxintr(um->um_ctlr);
 714:             }
 715:         }
 716:     }
 717:     if (dopen)
 718:         timeout(rxwatch, (caddr_t)0, hz);
 719:     else
 720:         rxwstart = 0;
 721: }
 722: 
 723: rxreset(uban)
 724:     int uban;
 725: {
 726:     register struct uba_ctlr *um;
 727:     register struct rxdevice *rxaddr;
 728:     register int ctlr;
 729: 
 730:     for (ctlr = 0; ctlr < NFX; ctlr++) {
 731:         if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
 732:             um->um_alive == 0)
 733:             continue;
 734:         if (um->um_ubinfo)
 735:             um->um_ubinfo = 0;
 736:         rx_ctlr[ctlr].rxc_state = RXS_IDLE;
 737:         rxaddr = (struct rxdevice *)um->um_addr;
 738:         rxaddr->rxcs = RX_INIT;
 739:         while ((rxaddr->rxcs&RX_DONE) == 0)
 740:             ;
 741:         rxstart(um);
 742:     }
 743: }
 744: 
 745: rxread(dev, uio)
 746:     dev_t dev;
 747:     struct uio *uio;
 748: {
 749:     int unit = RXUNIT(dev);
 750:     struct rx_softc *sc = &rx_softc[unit];
 751: 
 752:     if (uio->uio_offset + uio->uio_resid > RXSIZE)
 753:         return (ENXIO);
 754:     if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
 755:         return (ENXIO);
 756:     sc->sc_offset = uio->uio_offset % DEV_BSIZE;
 757:     return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
 758: }
 759: 
 760: rxwrite(dev, uio)
 761:     dev_t dev;
 762:     struct uio *uio;
 763: {
 764:     int unit = RXUNIT(dev);
 765:     struct rx_softc *sc = &rx_softc[unit];
 766: 
 767:     if (uio->uio_offset + uio->uio_resid > RXSIZE)
 768:         return (ENXIO);
 769:     if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
 770:         return (ENXIO);
 771:     sc->sc_offset = uio->uio_offset % DEV_BSIZE;
 772:     return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
 773: }
 774: 
 775: /*
 776:  * Control routine:
 777:  * processes four kinds of requests:
 778:  *
 779:  *	(1) Set density (i.e., format the diskette) according to
 780:  *		  that specified data parameter
 781:  *	(2) Arrange for the next sector to be written with a deleted-
 782:  *		  data mark.
 783:  *	(3) Report whether the last sector read had a deleted-data mark
 784:  *	(4) Report the density of the diskette in the indicated drive
 785:  *	    (since the density it automatically determined by the driver,
 786:  *	     this is the only way to let an application program know the
 787:  *	     density)
 788:  *
 789:  * Requests relating to deleted-data marks can be handled right here.
 790:  * A "set density" (format) request, however, must additionally be
 791:  * processed through "rxstart", just like a read or write request.
 792:  */
 793: 
 794: /*ARGSUSED3*/
 795: rxioctl(dev, cmd, data, flag)
 796:     dev_t dev;
 797:     caddr_t data;
 798: {
 799:     int unit = RXUNIT(dev);
 800:     struct rx_softc *sc = &rx_softc[unit];
 801: 
 802:     switch (cmd) {
 803: 
 804:     case RXIOC_FORMAT:
 805:         if ((flag&FWRITE) == 0)
 806:             return (EBADF);
 807:         if (sc->sc_open > 1)
 808:             return (EBUSY);
 809:         if (*(int *)data)
 810:             sc->sc_csbits |= RX_DDEN;
 811:         else
 812:             sc->sc_csbits &= ~RX_DDEN;
 813:         return (rxformat(dev));
 814: 
 815:     case RXIOC_WDDS:
 816:         sc->sc_flags |= RXF_USEWDDS;
 817:         return (0);
 818: 
 819:     case RXIOC_RDDSMK:
 820:         *(int *)data = sc->sc_flags & RXF_DDMK;
 821:         return (0);
 822: 
 823:     case RXIOC_GDENS:
 824:         *(int *)data = sc->sc_csbits & RX_DDEN;
 825:         return (0);
 826:     }
 827:     return (ENXIO);
 828: }
 829: 
 830: /*
 831:  * Initiate a format command.
 832:  */
 833: rxformat(dev)
 834:     dev_t dev;
 835: {
 836:     int unit = RXUNIT(dev);
 837:     struct buf *bp;
 838:     struct rx_softc *sc = &rx_softc[unit];
 839:     int s, error = 0;
 840: 
 841:     bp = &rrxbuf[unit];
 842:     bp->b_flags = B_BUSY | B_CTRL;
 843:     sc->sc_flags = RXF_FORMAT | RXF_LOCK;
 844:     bp->b_dev = dev;
 845:     bp->b_error = 0;
 846:     bp->b_blkno = 0;
 847:     rxstrategy(bp);
 848:     iowait(bp);
 849:     if (bp->b_flags & B_ERROR)
 850:         error = bp->b_error;
 851:     bp->b_flags &= ~B_BUSY;
 852:     sc->sc_flags &= ~RXF_LOCK;
 853:     return (error);
 854: }
 855: 
 856: /*
 857:  * A permanent hard error condition has occured,
 858:  * purge the buffer queue
 859:  */
 860: rxpurge(um)
 861:     register struct uba_ctlr *um;
 862: {
 863:     register struct buf *bp, *dp;
 864: 
 865:     dp = um->um_tab.b_actf;
 866:     while (dp->b_actf) {
 867:         dp->b_errcnt++;
 868:         bp = dp->b_actf;
 869:         bp->b_error = EIO;
 870:         bp->b_flags |= B_ERROR;
 871:         iodone(bp);
 872:         dp->b_actf = bp->av_forw;
 873:     }
 874: }
 875: #endif

Defined functions

rxattach defined in line 156; used 2 times
rxclose defined in line 220; never used
rxdgo defined in line 444; used 2 times
rxformat defined in line 833; used 1 times
rxintr defined in line 464; used 3 times
rxioctl defined in line 795; never used
rxmap defined in line 318; used 3 times
rxopen defined in line 163; never used
rxprobe defined in line 130; used 2 times
rxpurge defined in line 860; used 1 times
rxread defined in line 745; never used
rxreset defined in line 723; used 1 times
rxslave defined in line 146; used 2 times
rxstart defined in line 354; used 5 times
rxstrategy defined in line 231; used 4 times
rxustart defined in line 280; used 2 times
rxwatch defined in line 689; used 3 times
rxwrite defined in line 760; never used

Defined variables

erxbuf defined in line 68; used 2 times
fxdriver defined in line 112; never used
rrxbuf defined in line 67; used 3 times
rx_ctlr defined in line 64; used 6 times
rx_softc defined in line 96; used 12 times
rxdinfo defined in line 105; used 6 times
rxerr defined in line 102; used 1 times
rxminfo defined in line 106; used 3 times
rxstd defined in line 111; used 1 times
rxutab defined in line 69; used 3 times
rxwstart defined in line 115; used 2 times
savebp defined in line 108; used 2 times

Defined struct's

rx_ctlr defined in line 49; used 10 times
rx_softc defined in line 72; used 24 times
rxerr defined in line 98; used 2 times
  • in line 473(2)

Defined macros

B_CTRL defined in line 126; used 2 times
B_RDSTAT defined in line 127; used 3 times
DDSTATE defined in line 121; used 3 times
MASKREG defined in line 117; used 6 times
NBPS defined in line 122; used 5 times
RXF_BAD defined in line 82; used 3 times
RXF_DBLDEN defined in line 76; never used
RXF_DDMK defined in line 79; used 3 times
RXF_DEVTYPE defined in line 77; used 1 times
RXF_DIRECT defined in line 74; used 1 times
RXF_FORMAT defined in line 81; used 1 times
RXF_LOCK defined in line 78; used 6 times
RXF_TRKONE defined in line 75; used 1 times
RXF_USEWDDS defined in line 80; used 3 times
RXSECS defined in line 120; never used
RXSIZE defined in line 123; used 3 times
RXS_EMPTY defined in line 52; used 1 times
RXS_FILL defined in line 53; used 1 times
RXS_FORMAT defined in line 55; used 2 times
RXS_IDLE defined in line 58; used 2 times
RXS_RDERR defined in line 57; used 3 times
RXS_RDSTAT defined in line 56; used 3 times
RXS_READ defined in line 51; used 1 times
RXS_WRITE defined in line 54; used 1 times
RXUNIT defined in line 116; used 11 times
RX_MAXTIMEOUT defined in line 63; used 1 times
SECMASK defined in line 124; used 2 times
b_cylin defined in line 46; used 1 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2770
Valid CSS Valid XHTML 1.0 Strict