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