1: /* 2: * RX02 Standalone disk driver. 3: * 96/3/8, Steve Schultz (sms@moe.2bsd.com) 4: * 95/12/02, Tim Shoppa (shoppa@altair.krl.caltech.edu) 5: * 6: * Layout of logical devices: 7: * 8: * name min dev unit density 9: * ---- ------- ---- ------- 10: * rx0a 0 0 single 11: * rx1a 1 1 single 12: * rx0b 2 0 double 13: * rx1b 3 1 double 14: * 15: * the following defines use some fundamental 16: * constants of the RX02. 17: */ 18: 19: #define NSPB (4-2*(pn)) /* sectors per block */ 20: #define NRXBLKS (1001-501*(pn)) /* blocks on device */ 21: #define NBPS (128+128*(pn)) /* bytes per sector */ 22: #define DENSITY ((pn)) /* Density: 0 = single, 1 = double */ 23: #define UNIT ((dn)) /* Unit Number: 0 = left, 1 = right */ 24: #define RXGD (RX_GO | (DENSITY << 8)) 25: 26: #define rxwait() while (((rxaddr->rxcs) & RX_XREQ) == 0) 27: #define rxdone() while (((rxaddr->rxcs) & RX_DONE) == 0) 28: 29: #include "../h/param.h" 30: #include "../pdpuba/rxreg.h" 31: #include "saio.h" 32: 33: #define NRX 2 34: 35: struct rxdevice *RXcsr[NRX+1]= 36: { 37: (struct rxdevice *)0177170, 38: (struct rxdevice *)0, 39: (struct rxdevice *)-1 40: }; 41: 42: rxstrategy(io, func) 43: register struct iob *io; 44: { 45: register struct rxdevice *rxaddr; 46: daddr_t bn; 47: unsigned int sectno,sector,track,dn,pn,bae,lo16,lotemp,cc; 48: unsigned int bc,bs,retry; 49: 50: rxaddr = RXcsr[io->i_ctlr]; 51: bn = io->i_bn; 52: dn = io->i_unit; 53: pn = io->i_part; 54: cc = io->i_cc; 55: iomapadr(io->i_ma, &bae, &lo16); 56: bc=0; 57: 58: for (sectno=0; bc<cc; sectno++) { 59: rxfactr((int)bn*NSPB+sectno,§or,&track); 60: if (func == READ) { 61: retry=0; 62: rxretry: rxaddr->rxcs=RX_RSECT|RXGD|(UNIT<<4); 63: rxwait(); 64: rxaddr->rxsa=sector; 65: rxwait(); 66: rxaddr->rxta=track; 67: rxdone(); 68: if (rxaddr->rxcs & RX_ERR) { 69: if ((retry++) < 10) goto rxretry; 70: goto rxerr; 71: } 72: } 73: bs = ((cc-bc<NBPS) ? (cc-bc) : (NBPS)); 74: rxaddr->rxcs=((func==READ)?RX_EMPTY:RX_FILL)|RXGD|(bae<<12); 75: rxwait(); 76: rxaddr->rxwc=bs/2; 77: rxwait(); 78: rxaddr->rxba=lo16; 79: rxdone(); 80: if (rxaddr->rxcs & RX_ERR) goto rxerr; 81: if (func==WRITE) { 82: rxaddr->rxcs=RX_WSECT|RXGD|(UNIT<<4); 83: rxwait(); 84: rxaddr->rxsa=sector; 85: rxwait(); 86: rxaddr->rxta=track; 87: rxdone(); 88: if (rxaddr->rxcs & RX_ERR) goto rxerr; 89: } 90: lotemp=lo16; 91: lo16=lo16+NBPS; 92: if (lo16 < lotemp) 93: bae=bae+1; 94: bc=bc+bs; 95: } 96: return(io->i_cc); 97: 98: rxerr: printf("%s rxcs %o rxes %o\n",devname(io), rxaddr->rxcs,rxaddr->rxes); 99: return(-1); 100: } 101: 102: 103: rxopen(io) 104: struct iob *io; 105: { 106: return(genopen(NRX, io)); 107: } 108: 109: /* 110: * rxfactr -- calculates the physical sector and physical 111: * track on the disk for a given logical sector. 112: * call: 113: * rxfactr(logical_sector,&p_sector,&p_track); 114: * the logical sector number (0 - 2001) is converted 115: * to a physical sector number (1 - 26) and a physical 116: * track number (0 - 76). 117: * the logical sectors specify physical sectors that 118: * are interleaved with a factor of 2. thus the sectors 119: * are read in the following order for increasing 120: * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) 121: * There is also a 6 sector slew between tracks. 122: * Logical sectors start at track 1, sector 1; go to 123: * track 76 and then to track 0. Thus, for example, unix block number 124: * 498 starts at track 0, sector 25 and runs thru track 0, sector 2 125: * (or 6 depending on density). 126: */ 127: static 128: rxfactr(sectr, psectr, ptrck) 129: register int sectr; 130: int *psectr, *ptrck; 131: { 132: register int p1, p2; 133: 134: p1 = sectr / 26; 135: p2 = sectr % 26; 136: /* 2 to 1 interleave */ 137: p2 = (2 * p2 + (p2 >= 13 ? 1 : 0)) % 26; 138: /* 6 sector per track slew */ 139: *psectr = 1 + (p2 + 6 * p1) % 26; 140: if (++p1 >= 77) 141: p1 = 0; 142: *ptrck = p1; 143: }