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.4 (Berkeley) 12/16/90 7 */ 8 9 #if VAX780 10 #include "sys/param.h" 11 #include "sys/systm.h" 12 #include "sys/conf.h" 13 #include "sys/user.h" 14 #include "sys/buf.h" 15 16 #include "cons.h" 17 #include "../include/cpu.h" 18 #include "flp.h" 19 #include "../include/mtpr.h" 20 21 struct { 22 short fl_state; /* open and busy flags */ 23 short fl_active; /* driver state flag */ 24 struct buf *fl_buf; /* buffer we're using */ 25 unsigned char *fl_xaddr; /* transfer address */ 26 short fl_errcnt; 27 } fltab; 28 29 /*ARGSUSED*/ 30 flopen(dev, flag) 31 dev_t dev; 32 int flag; 33 { 34 struct buf *geteblk(); 35 36 if (cpu != VAX_780) 37 return (ENXIO); 38 if (fltab.fl_state != 0) 39 return (ENXIO); 40 fltab.fl_state = FL_OPEN; 41 fltab.fl_buf = geteblk(512); 42 fltab.fl_active = FL_IDLE; 43 return (0); 44 } 45 46 /*ARGSUSED*/ 47 flclose(dev, flag) 48 dev_t dev; 49 int flag; 50 { 51 52 brelse(fltab.fl_buf); 53 fltab.fl_state = 0; 54 } 55 56 /*ARGSUSED*/ 57 flrw(dev, uio, flag) 58 dev_t dev; 59 struct uio *uio; 60 int flag; 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 (uio->uio_rw == UIO_WRITE) { 92 error = uiomove(bp->b_un.b_addr, i, uio); 93 if (error) 94 break; 95 } 96 bp->b_flags = uio->uio_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 (uio->uio_rw == UIO_READ) { 107 error = uiomove(bp->b_un.b_addr, i, 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 flstart() 118 { 119 register struct buf *bp; 120 121 bp = fltab.fl_buf; 122 fltab.fl_active = FL_MAND; 123 fltab.fl_errcnt = 0; 124 fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; 125 bp->b_resid = 0; 126 bp->b_bcount = RXBYSEC; /* always transfer a full sector */ 127 128 if ((mfpr(TXCS) & TXCS_RDY) == 0) 129 /* not ready to receive order */ 130 return; 131 /* 132 * Wake up floppy LSI software with command 133 */ 134 fltab.fl_active = FL_SEC; 135 if ((bp->b_flags&B_READ) == B_READ) 136 mtpr(TXDB, FL_RS); 137 else 138 mtpr(TXDB, FL_WS); 139 } 140 141 /* 142 * See if we want to transmit something 143 * to the floppy - and do it 144 */ 145 conxfl() 146 { 147 register int databyte; 148 register struct buf *bp; 149 150 bp = fltab.fl_buf; 151 switch (fltab.fl_active) { 152 153 case FL_MAND: /* send command */ 154 if ((bp->b_flags&B_READ) == B_READ) 155 mtpr(TXDB,FL_RS); 156 else 157 mtpr(TXDB, FL_WS); 158 fltab.fl_active = FL_SEC; 159 break; 160 161 case FL_SEC: /* send sector address */ 162 databyte = (int)bp->b_blkno % RXSTRK + 1; 163 mtpr(TXDB, FL_DATA | databyte); 164 fltab.fl_active = FL_TRACK; 165 break; 166 167 case FL_TRACK: /* send track address */ 168 databyte = (int)bp->b_blkno / RXSTRK; 169 mtpr(TXDB , FL_DATA | databyte); 170 if ((bp->b_flags&B_READ) == B_READ) 171 /* prepare to receive complete */ 172 fltab.fl_active = FL_COM; 173 else 174 /* prepare to send data */ 175 fltab.fl_active = FL_DAX; 176 break; 177 178 case FL_DAX: 179 databyte = *(fltab.fl_xaddr++); 180 mtpr(TXDB, FL_DATA | databyte); 181 if (--bp->b_bcount == 0) 182 fltab.fl_active = FL_COM; 183 break; 184 185 case FL_CAN: /* give cancel order */ 186 mtpr(TXDB, FL_CANCEL); 187 if (++fltab.fl_errcnt <= FLERRS) { 188 /* If error count permits, retry order */ 189 fltab.fl_active = FL_MAND; 190 bp->b_bcount = RXBYSEC; 191 fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr; 192 } else { 193 /* 194 * We're really stupid today - call it an 195 * error and give up 196 */ 197 bp->b_flags |= B_ERROR | B_DONE; 198 bp->b_resid = -RXBYSEC; 199 fltab.fl_active = FL_IDLE; 200 wakeup((caddr_t)bp); 201 } 202 } 203 } 204 205 cnrfl(c) 206 int c; 207 { 208 register int datum; 209 register struct buf *bp; 210 211 datum = c; 212 bp = fltab.fl_buf; 213 if (datum == FL_PERR) { 214 /* 215 * Got a protocol error - cancel the 216 * current function and try again if error count isn't 217 * too great. First, though, make sure that an actual 218 * transaction is in progress (so a spurious error from 219 * the LSI won't screw us up too much! 220 */ 221 if (fltab.fl_active != FL_IDLE) 222 fltab.fl_active = FL_CAN; 223 } else switch(fltab.fl_active ) { 224 225 case FL_DAR: /* expecting a datum */ 226 if ((c&RXDB_ID) != FL_DATA) 227 goto error; 228 *(fltab.fl_xaddr++) = (c & RXDB_DATA); 229 if (--bp->b_bcount==0) { 230 fltab.fl_active = FL_IDLE; 231 bp->b_flags |= B_DONE; 232 wakeup((caddr_t)bp); 233 } 234 break; 235 236 case FL_COM: /* expecting a "function complete" */ 237 if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){ 238 error: 239 bp->b_flags |= B_ERROR | B_DONE; 240 bp->b_resid = -bp->b_bcount; 241 fltab.fl_active = FL_IDLE; 242 wakeup((caddr_t)bp); 243 } else if ((bp->b_flags&B_READ) == B_READ) 244 /* got function complete, now get data */ 245 fltab.fl_active = FL_DAR; 246 else { 247 /* got function complete on write - finish up */ 248 fltab.fl_active = FL_IDLE; 249 bp->b_flags |= B_DONE; 250 wakeup((caddr_t)bp); 251 } 252 break; 253 } 254 } 255 #endif 256