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