135045Skarels /* 235045Skarels * Copyright (c) 1988 Regents of the University of California. 335045Skarels * All rights reserved. 435045Skarels * 535045Skarels * This code is derived from software contributed to Berkeley by 635045Skarels * Chris Torek. 735045Skarels * 8*44541Sbostic * %sccs.include.redist.c% 935045Skarels * 10*44541Sbostic * @(#)rx50.c 7.4 (Berkeley) 06/28/90 1135045Skarels */ 1235045Skarels 1335045Skarels #if VAX8200 1435045Skarels 1535045Skarels /* 1635045Skarels * Routines to handle the console RX50. 1735045Skarels */ 1835045Skarels 1935045Skarels #include "param.h" 2035045Skarels #include "time.h" 2135045Skarels #include "kernel.h" 2235045Skarels #include "vmmac.h" 2335045Skarels #include "buf.h" 2435045Skarels #include "errno.h" 2535045Skarels #include "uio.h" 2635045Skarels 2735045Skarels #include "cpu.h" 2835045Skarels #include "rx50reg.h" 2935045Skarels 3035045Skarels struct rx50device rx50device; 3135045Skarels 3235045Skarels #define rx50unit(dev) minor(dev) 3335045Skarels 3435045Skarels struct rx50state { 3535045Skarels short rs_flags; /* see below */ 3635045Skarels short rs_drive; /* current drive number */ 3735045Skarels u_int rs_blkno; /* current block number */ 3835045Skarels } rx50state; 3935045Skarels 4035045Skarels /* flags */ 4135045Skarels #define RS_0OPEN 0x01 /* drive 0 open -- must be first */ 4235045Skarels #define RS_1OPEN 0x02 /* drive 1 open -- must be second */ 4335045Skarels #define RS_BUSY 0x04 /* operation in progress */ 4435045Skarels #define RS_WANT 0x08 /* wakeup when done */ 4535045Skarels #define RS_DONE 0x20 /* I/O operation done */ 4635045Skarels #define RS_ERROR 0x40 /* error bit set at interrupt */ 4735045Skarels 4835045Skarels /* 4935045Skarels * Open a console RX50. 5035045Skarels */ 5135045Skarels /*ARGSUSED*/ 5235045Skarels rx50open(dev, flags) 5335045Skarels dev_t dev; 5435045Skarels int flags; 5535045Skarels { 5635045Skarels int unit; 5735045Skarels 5835045Skarels /* only on 8200 (yet) */ 5935045Skarels if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2) 6035045Skarels return (ENXIO); 6135045Skarels 6235045Skarels /* enforce exclusive access */ 6335045Skarels if (rx50state.rs_flags & (1 << unit)) 6435045Skarels return (EBUSY); 6535045Skarels rx50state.rs_flags |= 1 << unit; 6635045Skarels return (0); 6735045Skarels } 6835045Skarels 6935045Skarels /* 7035045Skarels * Close a console RX50. 7135045Skarels */ 7235045Skarels /*ARGSUSED*/ 7335045Skarels rx50close(dev, flags) 7435045Skarels dev_t dev; 7535045Skarels int flags; 7635045Skarels { 7735045Skarels 7835045Skarels rx50state.rs_flags &= ~(1 << dev); /* atomic */ 7935045Skarels } 8035045Skarels 8135045Skarels /* 8237759Smckusick * Perform a read (uio->uio_rw==UIO_READ) or write (uio->uio_rw==UIO_WRITE). 8335045Skarels */ 8440912Ssklower rx50rw(dev, uio, flags) 8535045Skarels dev_t dev; 8635045Skarels register struct uio *uio; 8737759Smckusick int flags; 8835045Skarels { 8935045Skarels register struct rx50device *rxaddr; 9035045Skarels register struct rx50state *rs; 9135045Skarels register char *cp; 9235045Skarels register int error, i, t; 9335045Skarels char secbuf[512]; 9435045Skarels static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 }; 9535045Skarels 9635045Skarels /* enforce whole-sector I/O */ 9735045Skarels if ((uio->uio_offset & 511) || (uio->uio_resid & 511)) 9835045Skarels return (EINVAL); 9935045Skarels 10035045Skarels rs = &rx50state; 10135045Skarels 10235045Skarels /* lock out others */ 10335045Skarels i = spl4(); 10435045Skarels while (rs->rs_flags & RS_BUSY) { 10535045Skarels rs->rs_flags |= RS_WANT; 10635045Skarels sleep((caddr_t) &rx50state, PZERO - 1); 10735045Skarels } 10835045Skarels rs->rs_flags |= RS_BUSY; 10935045Skarels rs->rs_drive = rx50unit(dev); 11035045Skarels splx(i); 11135045Skarels 11235045Skarels rxaddr = &rx50device; 11335045Skarels error = 0; 11435045Skarels 11535045Skarels while (uio->uio_resid) { 11635045Skarels rs->rs_blkno = uio->uio_offset >> 9; 11735045Skarels if (rs->rs_blkno >= RX50MAXSEC) { 11835045Skarels if (rs->rs_blkno > RX50MAXSEC) 11935045Skarels error = EINVAL; 12037759Smckusick else if (uio->uio_rw == UIO_WRITE) 12135045Skarels error = ENOSPC; 12235045Skarels /* else ``eof'' */ 12335045Skarels break; 12435045Skarels } 12535045Skarels rs->rs_flags &= ~(RS_ERROR | RS_DONE); 12637759Smckusick if (uio->uio_rw == UIO_WRITE) { 12735045Skarels /* copy the data to the RX50 silo */ 12837759Smckusick error = uiomove(secbuf, 512, uio); 12935045Skarels if (error) 13035045Skarels break; 13135045Skarels i = rxaddr->rxrda; 13235045Skarels for (cp = secbuf, i = 512; --i >= 0;) 13335045Skarels rxaddr->rxfdb = *cp++; 13435045Skarels i = RXCMD_WRITE; 13535045Skarels } else 13635045Skarels i = RXCMD_READ; 13735045Skarels rxaddr->rxcmd = i | driveselect[rs->rs_drive]; 13835045Skarels i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC); 13935045Skarels rxaddr->rxtrk = t == 79 ? 0 : t + 1; 14035045Skarels #ifdef notdef 14135045Skarels rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4); 14235045Skarels #else 14335045Skarels rxaddr->rxsec = RX50SKEW(i, t); 14435045Skarels #endif 14535045Skarels i = rxaddr->rxgo; /* start it up */ 14635045Skarels i = spl4(); 14735045Skarels while ((rs->rs_flags & RS_DONE) == 0) 14835045Skarels sleep((caddr_t) &rs->rs_blkno, PRIBIO); 14935045Skarels splx(i); 15035045Skarels if (rs->rs_flags & RS_ERROR) { 15135045Skarels error = EIO; 15235045Skarels break; 15335045Skarels } 15437759Smckusick if (uio->uio_rw == UIO_READ) { 15535045Skarels /* copy the data out of the silo */ 15635045Skarels i = rxaddr->rxrda; 15735045Skarels for (cp = secbuf, i = 512; --i >= 0;) 15835045Skarels *cp++ = rxaddr->rxedb; 15937759Smckusick error = uiomove(secbuf, 512, uio); 16035045Skarels if (error) 16135045Skarels break; 16235045Skarels } 16335045Skarels } 16435045Skarels 16535045Skarels /* let others in */ 16635045Skarels rs->rs_flags &= ~RS_BUSY; 16735045Skarels if (rs->rs_flags & RS_WANT) 16835045Skarels wakeup((caddr_t) rs); 16935045Skarels 17035045Skarels return (error); 17135045Skarels } 17235045Skarels 17335045Skarels rx50intr() 17435045Skarels { 17535045Skarels register struct rx50device *rxaddr = &rx50device; 17635045Skarels register struct rx50state *rs = &rx50state; 17735045Skarels int i; 17835045Skarels 17935045Skarels #ifdef lint 18035045Skarels i = 0; i = i; 18135045Skarels #endif 18235045Skarels 18335045Skarels /* ignore spurious interrupts */ 18435045Skarels if ((rxaddr->rxcmd & RXCMD_DONE) == 0) 18535045Skarels return; 18635045Skarels if ((rs->rs_flags & RS_BUSY) == 0) { 18735045Skarels printf("stray rx50 interrupt ignored\n"); 18835045Skarels return; 18935045Skarels } 19035045Skarels if (rxaddr->rxcmd & RXCMD_ERROR) { 19135045Skarels printf( 19235045Skarels "csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n", 19335045Skarels rs->rs_drive + 1, rs->rs_blkno, 19435045Skarels rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec, 19535045Skarels rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext); 19635045Skarels rxaddr->rxcmd = RXCMD_RESET; 19735045Skarels i = rxaddr->rxgo; 19835045Skarels rs->rs_flags |= RS_ERROR; 19935045Skarels } 20035045Skarels rs->rs_flags |= RS_DONE; 20135045Skarels wakeup((caddr_t) &rs->rs_blkno); 20235045Skarels } 20335045Skarels #endif 204