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: * @(#)flp.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #if VAX780 10: #include "param.h" 11: #include "systm.h" 12: #include "conf.h" 13: #include "dir.h" 14: #include "user.h" 15: #include "buf.h" 16: #include "uio.h" 17: 18: #include "cons.h" 19: #include "cpu.h" 20: #include "flp.h" 21: #include "mtpr.h" 22: 23: struct { 24: short fl_state; /* open and busy flags */ 25: short fl_active; /* driver state flag */ 26: struct buf *fl_buf; /* buffer we're using */ 27: unsigned char *fl_xaddr; /* transfer address */ 28: short fl_errcnt; 29: } fltab; 30: 31: /*ARGSUSED*/ 32: flopen(dev, flag) 33: dev_t dev; 34: int flag; 35: { 36: struct buf *geteblk(); 37: 38: if (cpu != VAX_780) 39: return (ENXIO); 40: if (fltab.fl_state != 0) 41: return (ENXIO); 42: fltab.fl_state = FL_OPEN; 43: fltab.fl_buf = geteblk(512); 44: fltab.fl_active = FL_IDLE; 45: return (0); 46: } 47: 48: /*ARGSUSED*/ 49: flclose(dev, flag) 50: dev_t dev; 51: int flag; 52: { 53: 54: brelse(fltab.fl_buf); 55: fltab.fl_state = 0; 56: } 57: 58: floperation(rw, uio) 59: enum uio_rw rw; 60: struct uio *uio; 61: { 62: register struct buf *bp; 63: register int i; 64: int error; 65: 66: /* 67: * Assume one block read/written for each call - 68: * and enforce this by checking for block size of 128. 69: * Use the b_blkno field to address 70: * physical, 128-byte blocks (u.u_offset/128). 71: * This is checked for validity, and is further interpreted as: 72: * 73: * track# * (sectors/track) + sector # 74: */ 75: if (uio->uio_resid == 0) 76: return (0); 77: (void) spl4(); 78: while (fltab.fl_state & FL_BUSY) 79: sleep((caddr_t)&fltab, PRIBIO); 80: fltab.fl_state |= FL_BUSY; 81: (void) spl0(); 82: 83: bp = fltab.fl_buf; 84: error = 0; 85: while ((i = imin(RXBYSEC, uio->uio_resid)) > 0) { 86: bp->b_blkno = uio->uio_offset>>7; 87: if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0177) != 0) { 88: error = ENXIO; 89: break; 90: } 91: if (rw == UIO_WRITE) { 92: error = uiomove(bp->b_un.b_addr, i, UIO_WRITE, uio); 93: if (error) 94: break; 95: } 96: bp->b_flags = rw == UIO_WRITE ? B_WRITE : B_READ; 97: (void) spl4(); 98: flstart(); 99: while ((bp->b_flags & B_DONE) == 0) 100: sleep((caddr_t)bp, PRIBIO); 101: (void) spl0(); 102: if (bp->b_flags & B_ERROR) { 103: error = EIO; 104: break; 105: } 106: if (rw == UIO_READ) { 107: error = uiomove(bp->b_un.b_addr, i, UIO_READ, uio); 108: if (error) 109: break; 110: } 111: } 112: fltab.fl_state &= ~FL_BUSY; 113: wakeup((caddr_t)&fltab); 114: return (error); 115: } 116: 117: /*ARGSUSED*/ 118: flread(dev, uio) 119: dev_t dev; 120: struct uio *uio; 121: { 122: 123: return (floperation(UIO_READ, uio)); 124: } 125: 126: /*ARGSUSED*/ 127: flwrite(dev, uio) 128: dev_t dev; 129: struct uio *uio; 130: { 131: 132: return (floperation(UIO_WRITE, uio)); 133: } 134: 135: flstart() 136: { 137: register struct buf *bp; 138: 139: bp = fltab.fl_buf; 140: fltab.fl_active = FL_MAND; 141: fltab.fl_errcnt = 0; 142: fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; 143: bp->b_resid = 0; 144: bp->b_bcount = RXBYSEC; /* always transfer a full sector */ 145: 146: if ((mfpr(TXCS) & TXCS_RDY) == 0) 147: /* not ready to receive order */ 148: return; 149: /* 150: * Wake up floppy LSI software with command 151: */ 152: fltab.fl_active = FL_SEC; 153: if ((bp->b_flags&B_READ) == B_READ) 154: mtpr(TXDB, FL_RS); 155: else 156: mtpr(TXDB, FL_WS); 157: } 158: 159: /* 160: * See if we want to transmit something 161: * to the floppy - and do it 162: */ 163: conxfl() 164: { 165: register int databyte; 166: register struct buf *bp; 167: 168: bp = fltab.fl_buf; 169: switch (fltab.fl_active) { 170: 171: case FL_MAND: /* send command */ 172: if ((bp->b_flags&B_READ) == B_READ) 173: mtpr(TXDB,FL_RS); 174: else 175: mtpr(TXDB, FL_WS); 176: fltab.fl_active = FL_SEC; 177: break; 178: 179: case FL_SEC: /* send sector address */ 180: databyte = (int)bp->b_blkno % RXSTRK + 1; 181: mtpr(TXDB, FL_DATA | databyte); 182: fltab.fl_active = FL_TRACK; 183: break; 184: 185: case FL_TRACK: /* send track address */ 186: databyte = (int)bp->b_blkno / RXSTRK; 187: mtpr(TXDB , FL_DATA | databyte); 188: if ((bp->b_flags&B_READ) == B_READ) 189: /* prepare to receive complete */ 190: fltab.fl_active = FL_COM; 191: else 192: /* prepare to send data */ 193: fltab.fl_active = FL_DAX; 194: break; 195: 196: case FL_DAX: 197: databyte = *(fltab.fl_xaddr++); 198: mtpr(TXDB, FL_DATA | databyte); 199: if (--bp->b_bcount == 0) 200: fltab.fl_active = FL_COM; 201: break; 202: 203: case FL_CAN: /* give cancel order */ 204: mtpr(TXDB, FL_CANCEL); 205: if (++fltab.fl_errcnt <= FLERRS) { 206: /* If error count permits, retry order */ 207: fltab.fl_active = FL_MAND; 208: bp->b_bcount = RXBYSEC; 209: fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; 210: } else { 211: /* 212: * We're really stupid today - call it an 213: * error and give up 214: */ 215: bp->b_flags |= B_ERROR | B_DONE; 216: bp->b_resid = -RXBYSEC; 217: fltab.fl_active = FL_IDLE; 218: wakeup((caddr_t)bp); 219: } 220: } 221: } 222: 223: cnrfl(c) 224: int c; 225: { 226: register int datum; 227: register struct buf *bp; 228: 229: datum = c; 230: bp = fltab.fl_buf; 231: if (datum == FL_PERR) { 232: /* 233: * Got a protocol error - cancel the 234: * current function and try again if error count isn't 235: * too great. First, though, make sure that an actual 236: * transaction is in progress (so a spurious error from 237: * the LSI won't screw us up too much! 238: */ 239: if (fltab.fl_active != FL_IDLE) 240: fltab.fl_active = FL_CAN; 241: } else switch(fltab.fl_active ) { 242: 243: case FL_DAR: /* expecting a datum */ 244: if ((c&RXDB_ID) != FL_DATA) 245: goto error; 246: *(fltab.fl_xaddr++) = (c & RXDB_DATA); 247: if (--bp->b_bcount==0) { 248: fltab.fl_active = FL_IDLE; 249: bp->b_flags |= B_DONE; 250: wakeup((caddr_t)bp); 251: } 252: break; 253: 254: case FL_COM: /* expecting a "function complete" */ 255: if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){ 256: error: 257: bp->b_flags |= B_ERROR | B_DONE; 258: bp->b_resid = -bp->b_bcount; 259: fltab.fl_active = FL_IDLE; 260: wakeup((caddr_t)bp); 261: } else if ((bp->b_flags&B_READ) == B_READ) 262: /* got function complete, now get data */ 263: fltab.fl_active = FL_DAR; 264: else { 265: /* got function complete on write - finish up */ 266: fltab.fl_active = FL_IDLE; 267: bp->b_flags |= B_DONE; 268: wakeup((caddr_t)bp); 269: } 270: break; 271: } 272: } 273: #endif