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) 06/05/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 274