1: /* 2: * RX02 floppy disk device driver 3: * 4: * This driver was written by Bill Shannon and distributed on the 5: * DEC v7m UNIX tape. It has been modified for 2BSD and has been 6: * included with the permission of the DEC UNIX Engineering Group. 7: * 8: * 9: * Layout of logical devices: 10: * 11: * name min dev unit density 12: * ---- ------- ---- ------- 13: * rx0 0 0 single 14: * rx1 1 1 single 15: * rx2 2 0 double 16: * rx3 3 1 double 17: * 18: * 19: * Stty function call may be used to format a disk. 20: * To enable this feature, define RX2_IOCTL. 21: */ 22: 23: /* 24: * SCCS id @(#)rx2.c 2.1 (Berkeley) 8/5/83 25: */ 26: 27: #include "rx2.h" 28: #if NRX2 > 0 29: #include "param.h" 30: #include <sys/buf.h> 31: #include <sys/dir.h> 32: #include <sys/user.h> 33: #include <sys/conf.h> 34: #include <sys/tty.h> 35: #include <sys/rx2reg.h> 36: 37: extern struct rx2device *RX2ADDR; 38: 39: /* 40: * the following defines use some fundamental 41: * constants of the RX02. 42: */ 43: #if UCB_NKB == 1 44: #define NSPB ((minor(bp->b_dev)&2) ? 4 : 8) /* sectors per block */ 45: #define NRXBLKS ((minor(bp->b_dev)&2) ? 500 : 250) /* blocks on device */ 46: #else 47: #ifndef UCB_NKB 48: #define NSPB ((minor(bp->b_dev)&2) ? 2 : 4) /* sectors per block */ 49: #define NRXBLKS ((minor(bp->b_dev)&2) ? 1001 : 500) /* blocks on device */ 50: #endif 51: #endif UCB_NKB 52: #define NBPS ((minor(bp->b_dev)&2) ? 256 : 128) /* bytes per sector */ 53: #define DENSITY (minor(bp->b_dev)&2) /* Density: 0 = single, 2 = double */ 54: #define UNIT (minor(bp->b_dev)&1) /* Unit Number: 0 = left, 1 = right */ 55: 56: #define rx2wait() while (((RX2ADDR->(rx2cs)) & RX2_XREQ) == 0) 57: #define b_seccnt av_back 58: #define seccnt(bp) ((int) ((bp)->b_seccnt)) 59: 60: struct buf rx2tab; 61: struct buf rrx2buf; 62: #ifdef RX2_IOCTL 63: struct buf crx2buf; /* buffer header for control functions */ 64: #endif 65: 66: /* 67: * states of driver, kept in b_state 68: */ 69: #define SREAD 1 /* read started */ 70: #define SEMPTY 2 /* empty started */ 71: #define SFILL 3 /* fill started */ 72: #define SWRITE 4 /* write started */ 73: #define SINIT 5 /* init started */ 74: #define SFORMAT 6 /* format started */ 75: 76: /*ARGSUSED*/ 77: rx2open(dev, flag) 78: dev_t dev; 79: { 80: if(minor(dev) >= 4) 81: u.u_error = ENXIO; 82: } 83: 84: rx2strategy(bp) 85: register struct buf *bp; 86: { 87: #ifdef UNIBUS_MAP 88: if(bp->b_flags & B_PHYS) 89: mapalloc(bp); 90: #endif 91: if(bp->b_blkno >= NRXBLKS) { 92: if(bp->b_flags&B_READ) 93: bp->b_resid = bp->b_bcount; 94: else { 95: bp->b_flags |= B_ERROR; 96: bp->b_error = ENXIO; 97: } 98: iodone(bp); 99: return; 100: } 101: bp->av_forw = (struct buf *) NULL; 102: 103: /* 104: * seccnt is actually the number of floppy sectors transferred, 105: * incremented by one after each successful transfer of a sector. 106: */ 107: seccnt(bp) = 0; 108: 109: /* 110: * We'll modify b_resid as each piece of the transfer 111: * successfully completes. It will also tell us when 112: * the transfer is complete. 113: */ 114: bp->b_resid = bp->b_bcount; 115: (void) _spl5(); 116: if(rx2tab.b_actf == NULL) 117: rx2tab.b_actf = bp; 118: else 119: rx2tab.b_actl->av_forw = bp; 120: rx2tab.b_actl = bp; 121: if(rx2tab.b_state == NULL) 122: rx2start(); 123: (void) _spl0(); 124: } 125: 126: rx2start() 127: { 128: register struct buf *bp; 129: int sector, track; 130: char *addr, *xmem; 131: 132: if((bp = rx2tab.b_actf) == NULL) { 133: rx2tab.b_state = NULL; 134: return; 135: } 136: 137: #ifdef RX2_IOCTL 138: if (bp == &crx2buf) { /* is it a control request ? */ 139: rx2tab.b_state = SFORMAT; 140: RX2ADDR->rx2cs = RX2_SMD | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); 141: rx2wait(); 142: RX2ADDR->rx2db = 'I'; 143: } else 144: #endif 145: if(bp->b_flags & B_READ) { 146: rx2tab.b_state = SREAD; 147: rx2factr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); 148: RX2ADDR->rx2cs = RX2_RSECT | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); 149: rx2wait(); 150: RX2ADDR->rx2sa = sector; 151: rx2wait(); 152: RX2ADDR->rx2ta = track; 153: } else { 154: rx2tab.b_state = SFILL; 155: rx2addr(bp, &addr, &xmem); 156: RX2ADDR->rx2cs = RX2_FILL | RX2_GO | RX2_IE | (xmem << 12) | (DENSITY << 7); 157: rx2wait(); 158: RX2ADDR->rx2wc = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1; 159: rx2wait(); 160: RX2ADDR->rx2ba = addr; 161: } 162: } 163: 164: rx2intr() 165: { 166: register struct buf *bp; 167: int sector, track; 168: char *addr, *xmem; 169: 170: if (rx2tab.b_state == SINIT) { 171: rx2start(); 172: return; 173: } 174: 175: if((bp = rx2tab.b_actf) == NULL) 176: return; 177: 178: if(RX2ADDR->rx2cs < 0) { 179: if(rx2tab.b_errcnt++ > 10 || rx2tab.b_state == SFORMAT) { 180: bp->b_flags |= B_ERROR; 181: #ifdef UCB_DEVERR 182: harderr(bp, "rx2"); 183: printf("cs=%b er=%b\n", RX2ADDR->rx2cs, RX2_BITS, 184: RX2ADDR->rx2es, RX2ES_BITS); 185: #else 186: deverror(bp, RX2ADDR->rx2cs, RX2ADDR->rx2db); 187: #endif UCB_DEVERR 188: rx2tab.b_errcnt = 0; 189: rx2tab.b_actf = bp->av_forw; 190: iodone(bp); 191: } 192: RX2ADDR->rx2cs = RX2_INIT; 193: RX2ADDR->rx2cs = RX2_IE; 194: rx2tab.b_state = SINIT; 195: return; 196: } 197: switch (rx2tab.b_state) { 198: 199: case SREAD: /* read done, start empty */ 200: rx2tab.b_state = SEMPTY; 201: rx2addr(bp, &addr, &xmem); 202: RX2ADDR->rx2cs = RX2_EMPTY | RX2_GO | RX2_IE | (xmem << 12) | (DENSITY << 7); 203: rx2wait(); 204: RX2ADDR->rx2wc = (bp->b_resid >= NBPS? NBPS : bp->b_resid) >> 1; 205: rx2wait(); 206: RX2ADDR->rx2ba = addr; 207: return; 208: 209: case SFILL: /* fill done, start write */ 210: rx2tab.b_state = SWRITE; 211: rx2factr((int)bp->b_blkno * NSPB + seccnt(bp), §or, &track); 212: RX2ADDR->rx2cs = RX2_WSECT | RX2_GO | RX2_IE | (UNIT << 4) | (DENSITY << 7); 213: rx2wait(); 214: RX2ADDR->rx2sa = sector; 215: rx2wait(); 216: RX2ADDR->rx2ta = track; 217: return; 218: 219: case SWRITE: /* write done, start next fill */ 220: case SEMPTY: /* empty done, start next read */ 221: /* 222: * increment amount remaining to be transferred. 223: * if it becomes positive, last transfer was a 224: * partial sector and we're done, so set remaining 225: * to zero. 226: */ 227: if (bp->b_resid <= NBPS) { 228: done: 229: bp->b_resid = 0; 230: rx2tab.b_errcnt = 0; 231: rx2tab.b_actf = bp->av_forw; 232: iodone(bp); 233: break; 234: } 235: 236: bp->b_resid -= NBPS; 237: seccnt(bp)++; 238: break; 239: 240: #ifdef RX2_IOCTL 241: case SFORMAT: /* format done (whew!!!) */ 242: goto done; /* driver's getting too big... */ 243: #endif 244: } 245: 246: /* end up here from states SWRITE and SEMPTY */ 247: rx2start(); 248: } 249: 250: /* 251: * rx2factr -- calculates the physical sector and physical 252: * track on the disk for a given logical sector. 253: * call: 254: * rx2factr(logical_sector,&p_sector,&p_track); 255: * the logical sector number (0 - 2001) is converted 256: * to a physical sector number (1 - 26) and a physical 257: * track number (0 - 76). 258: * the logical sectors specify physical sectors that 259: * are interleaved with a factor of 2. thus the sectors 260: * are read in the following order for increasing 261: * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) 262: * There is also a 6 sector slew between tracks. 263: * Logical sectors start at track 1, sector 1; go to 264: * track 76 and then to track 0. Thus, for example, unix block number 265: * 498 starts at track 0, sector 25 and runs thru track 0, sector 2 266: * (or 6 depending on density). 267: */ 268: rx2factr(sectr, psectr, ptrck) 269: register int sectr; 270: int *psectr, *ptrck; 271: { 272: register int p1, p2; 273: 274: p1 = sectr / 26; 275: p2 = sectr % 26; 276: /* 2 to 1 interleave */ 277: p2 = (2 * p2 + (p2 >= 13 ? 1 : 0)) % 26; 278: /* 6 sector per track slew */ 279: *psectr = 1 + (p2 + 6 * p1) % 26; 280: if (++p1 >= 77) 281: p1 = 0; 282: *ptrck = p1; 283: } 284: 285: 286: /* 287: * rx2addr -- compute core address where next sector 288: * goes to / comes from based on bp->b_un.b_addr, bp->b_xmem, 289: * and seccnt(bp). 290: */ 291: rx2addr(bp, addr, xmem) 292: register struct buf *bp; 293: register char **addr, **xmem; 294: { 295: *addr = bp->b_un.b_addr + seccnt(bp) * NBPS; 296: *xmem = bp->b_xmem; 297: if (*addr < bp->b_un.b_addr) /* overflow, bump xmem */ 298: (*xmem)++; 299: } 300: 301: 302: rx2read(dev) 303: dev_t dev; 304: { 305: physio(rx2strategy, &rrx2buf, dev, B_READ); 306: } 307: 308: 309: rx2write(dev) 310: dev_t dev; 311: { 312: physio(rx2strategy, &rrx2buf, dev, B_WRITE); 313: } 314: 315: 316: #ifdef RX2_IOCTL 317: /* 318: * rx2sgtty -- format RX02 disk, single or double density. 319: * stty with word 0 == 010 does format. density determined 320: * by device opened. 321: */ 322: /*ARGSUSED*/ 323: rx2ioctl(dev, cmd, addr, flag) 324: dev_t dev; 325: { 326: register s; 327: register struct buf *bp; 328: struct rx2iocb { 329: int ioc_cmd; /* command */ 330: int ioc_res1; /* reserved */ 331: int ioc_res2; /* reserved */ 332: } iocb; 333: 334: if (cmd != TIOCSETP) { 335: err: 336: u.u_error = ENXIO; 337: return(0); 338: } 339: if (copyin(addr, (caddr_t)&iocb, sizeof (iocb))) { 340: u.u_error = EFAULT; 341: return(1); 342: } 343: if (iocb.ioc_cmd != RX2_SMD) 344: goto err; 345: bp = &crx2buf; 346: while (bp->b_flags & B_BUSY) { 347: s = spl6(); 348: bp->b_flags |= B_WANTED; 349: sleep(bp, PRIBIO); 350: } 351: splx(s); 352: bp->b_flags = B_BUSY; 353: bp->b_dev = dev; 354: bp->b_error = 0; 355: rx2strategy(bp); 356: iowait(bp); 357: bp->b_flags = 0; 358: } 359: #endif RX2_IOCTL 360: #endif NRX2