1*35045Skarels /* 2*35045Skarels * Copyright (c) 1988 Regents of the University of California. 3*35045Skarels * All rights reserved. 4*35045Skarels * 5*35045Skarels * This code is derived from software contributed to Berkeley by 6*35045Skarels * Chris Torek. 7*35045Skarels * 8*35045Skarels * Redistribution and use in source and binary forms are permitted 9*35045Skarels * provided that the above copyright notice and this paragraph are 10*35045Skarels * duplicated in all such forms and that any documentation, 11*35045Skarels * advertising materials, and other materials related to such 12*35045Skarels * distribution and use acknowledge that the software was developed 13*35045Skarels * by the University of California, Berkeley. The name of the 14*35045Skarels * University may not be used to endorse or promote products derived 15*35045Skarels * from this software without specific prior written permission. 16*35045Skarels * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*35045Skarels * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*35045Skarels * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19*35045Skarels * 20*35045Skarels * @(#)rx50.c 7.1 (Berkeley) 07/09/88 21*35045Skarels */ 22*35045Skarels 23*35045Skarels #if VAX8200 24*35045Skarels 25*35045Skarels /* 26*35045Skarels * Routines to handle the console RX50. 27*35045Skarels */ 28*35045Skarels 29*35045Skarels #include "param.h" 30*35045Skarels #include "time.h" 31*35045Skarels #include "kernel.h" 32*35045Skarels #include "vmmac.h" 33*35045Skarels #include "buf.h" 34*35045Skarels #include "errno.h" 35*35045Skarels #include "uio.h" 36*35045Skarels 37*35045Skarels #include "cpu.h" 38*35045Skarels #include "rx50reg.h" 39*35045Skarels 40*35045Skarels struct rx50device rx50device; 41*35045Skarels 42*35045Skarels #define rx50unit(dev) minor(dev) 43*35045Skarels 44*35045Skarels struct rx50state { 45*35045Skarels short rs_flags; /* see below */ 46*35045Skarels short rs_drive; /* current drive number */ 47*35045Skarels u_int rs_blkno; /* current block number */ 48*35045Skarels } rx50state; 49*35045Skarels 50*35045Skarels /* flags */ 51*35045Skarels #define RS_0OPEN 0x01 /* drive 0 open -- must be first */ 52*35045Skarels #define RS_1OPEN 0x02 /* drive 1 open -- must be second */ 53*35045Skarels #define RS_BUSY 0x04 /* operation in progress */ 54*35045Skarels #define RS_WANT 0x08 /* wakeup when done */ 55*35045Skarels #define RS_DONE 0x20 /* I/O operation done */ 56*35045Skarels #define RS_ERROR 0x40 /* error bit set at interrupt */ 57*35045Skarels 58*35045Skarels /* 59*35045Skarels * Open a console RX50. 60*35045Skarels */ 61*35045Skarels /*ARGSUSED*/ 62*35045Skarels rx50open(dev, flags) 63*35045Skarels dev_t dev; 64*35045Skarels int flags; 65*35045Skarels { 66*35045Skarels int unit; 67*35045Skarels 68*35045Skarels /* only on 8200 (yet) */ 69*35045Skarels if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2) 70*35045Skarels return (ENXIO); 71*35045Skarels 72*35045Skarels /* enforce exclusive access */ 73*35045Skarels if (rx50state.rs_flags & (1 << unit)) 74*35045Skarels return (EBUSY); 75*35045Skarels rx50state.rs_flags |= 1 << unit; 76*35045Skarels return (0); 77*35045Skarels } 78*35045Skarels 79*35045Skarels /* 80*35045Skarels * Close a console RX50. 81*35045Skarels */ 82*35045Skarels /*ARGSUSED*/ 83*35045Skarels rx50close(dev, flags) 84*35045Skarels dev_t dev; 85*35045Skarels int flags; 86*35045Skarels { 87*35045Skarels 88*35045Skarels rx50state.rs_flags &= ~(1 << dev); /* atomic */ 89*35045Skarels } 90*35045Skarels 91*35045Skarels /* 92*35045Skarels * Perform a read (rw==UIO_READ) or write (rw==UIO_WRITE). 93*35045Skarels */ 94*35045Skarels rx50operation(dev, rw, uio) 95*35045Skarels dev_t dev; 96*35045Skarels enum uio_rw rw; 97*35045Skarels register struct uio *uio; 98*35045Skarels { 99*35045Skarels register struct rx50device *rxaddr; 100*35045Skarels register struct rx50state *rs; 101*35045Skarels register char *cp; 102*35045Skarels register int error, i, t; 103*35045Skarels char secbuf[512]; 104*35045Skarels static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 }; 105*35045Skarels 106*35045Skarels /* enforce whole-sector I/O */ 107*35045Skarels if ((uio->uio_offset & 511) || (uio->uio_resid & 511)) 108*35045Skarels return (EINVAL); 109*35045Skarels 110*35045Skarels rs = &rx50state; 111*35045Skarels 112*35045Skarels /* lock out others */ 113*35045Skarels i = spl4(); 114*35045Skarels while (rs->rs_flags & RS_BUSY) { 115*35045Skarels rs->rs_flags |= RS_WANT; 116*35045Skarels sleep((caddr_t) &rx50state, PZERO - 1); 117*35045Skarels } 118*35045Skarels rs->rs_flags |= RS_BUSY; 119*35045Skarels rs->rs_drive = rx50unit(dev); 120*35045Skarels splx(i); 121*35045Skarels 122*35045Skarels rxaddr = &rx50device; 123*35045Skarels error = 0; 124*35045Skarels 125*35045Skarels while (uio->uio_resid) { 126*35045Skarels rs->rs_blkno = uio->uio_offset >> 9; 127*35045Skarels if (rs->rs_blkno >= RX50MAXSEC) { 128*35045Skarels if (rs->rs_blkno > RX50MAXSEC) 129*35045Skarels error = EINVAL; 130*35045Skarels else if (rw == UIO_WRITE) 131*35045Skarels error = ENOSPC; 132*35045Skarels /* else ``eof'' */ 133*35045Skarels break; 134*35045Skarels } 135*35045Skarels rs->rs_flags &= ~(RS_ERROR | RS_DONE); 136*35045Skarels if (rw == UIO_WRITE) { 137*35045Skarels /* copy the data to the RX50 silo */ 138*35045Skarels error = uiomove(secbuf, 512, UIO_WRITE, uio); 139*35045Skarels if (error) 140*35045Skarels break; 141*35045Skarels i = rxaddr->rxrda; 142*35045Skarels for (cp = secbuf, i = 512; --i >= 0;) 143*35045Skarels rxaddr->rxfdb = *cp++; 144*35045Skarels i = RXCMD_WRITE; 145*35045Skarels } else 146*35045Skarels i = RXCMD_READ; 147*35045Skarels rxaddr->rxcmd = i | driveselect[rs->rs_drive]; 148*35045Skarels i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC); 149*35045Skarels rxaddr->rxtrk = t == 79 ? 0 : t + 1; 150*35045Skarels #ifdef notdef 151*35045Skarels rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4); 152*35045Skarels #else 153*35045Skarels rxaddr->rxsec = RX50SKEW(i, t); 154*35045Skarels #endif 155*35045Skarels i = rxaddr->rxgo; /* start it up */ 156*35045Skarels i = spl4(); 157*35045Skarels while ((rs->rs_flags & RS_DONE) == 0) 158*35045Skarels sleep((caddr_t) &rs->rs_blkno, PRIBIO); 159*35045Skarels splx(i); 160*35045Skarels if (rs->rs_flags & RS_ERROR) { 161*35045Skarels error = EIO; 162*35045Skarels break; 163*35045Skarels } 164*35045Skarels if (rw == UIO_READ) { 165*35045Skarels /* copy the data out of the silo */ 166*35045Skarels i = rxaddr->rxrda; 167*35045Skarels for (cp = secbuf, i = 512; --i >= 0;) 168*35045Skarels *cp++ = rxaddr->rxedb; 169*35045Skarels error = uiomove(secbuf, 512, UIO_READ, uio); 170*35045Skarels if (error) 171*35045Skarels break; 172*35045Skarels } 173*35045Skarels } 174*35045Skarels 175*35045Skarels /* let others in */ 176*35045Skarels rs->rs_flags &= ~RS_BUSY; 177*35045Skarels if (rs->rs_flags & RS_WANT) 178*35045Skarels wakeup((caddr_t) rs); 179*35045Skarels 180*35045Skarels return (error); 181*35045Skarels } 182*35045Skarels 183*35045Skarels rx50read(dev, uio) 184*35045Skarels dev_t dev; 185*35045Skarels struct uio *uio; 186*35045Skarels { 187*35045Skarels 188*35045Skarels return (rx50operation(dev, UIO_READ, uio)); 189*35045Skarels } 190*35045Skarels 191*35045Skarels rx50write(dev, uio) 192*35045Skarels dev_t dev; 193*35045Skarels struct uio *uio; 194*35045Skarels { 195*35045Skarels 196*35045Skarels return (rx50operation(dev, UIO_WRITE, uio)); 197*35045Skarels } 198*35045Skarels 199*35045Skarels rx50intr() 200*35045Skarels { 201*35045Skarels register struct rx50device *rxaddr = &rx50device; 202*35045Skarels register struct rx50state *rs = &rx50state; 203*35045Skarels int i; 204*35045Skarels 205*35045Skarels #ifdef lint 206*35045Skarels i = 0; i = i; 207*35045Skarels #endif 208*35045Skarels 209*35045Skarels /* ignore spurious interrupts */ 210*35045Skarels if ((rxaddr->rxcmd & RXCMD_DONE) == 0) 211*35045Skarels return; 212*35045Skarels if ((rs->rs_flags & RS_BUSY) == 0) { 213*35045Skarels printf("stray rx50 interrupt ignored\n"); 214*35045Skarels return; 215*35045Skarels } 216*35045Skarels if (rxaddr->rxcmd & RXCMD_ERROR) { 217*35045Skarels printf( 218*35045Skarels "csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n", 219*35045Skarels rs->rs_drive + 1, rs->rs_blkno, 220*35045Skarels rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec, 221*35045Skarels rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext); 222*35045Skarels rxaddr->rxcmd = RXCMD_RESET; 223*35045Skarels i = rxaddr->rxgo; 224*35045Skarels rs->rs_flags |= RS_ERROR; 225*35045Skarels } 226*35045Skarels rs->rs_flags |= RS_DONE; 227*35045Skarels wakeup((caddr_t) &rs->rs_blkno); 228*35045Skarels } 229*35045Skarels #endif 230