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), &sector, &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), &sector, &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

Defined functions

rx2addr defined in line 291; used 2 times
rx2factr defined in line 268; used 2 times
rx2intr defined in line 164; never used
rx2ioctl defined in line 323; never used
rx2open defined in line 77; never used
rx2read defined in line 302; never used
rx2start defined in line 126; used 3 times
rx2strategy defined in line 84; used 3 times
rx2write defined in line 309; never used

Defined variables

crx2buf defined in line 63; used 2 times
rrx2buf defined in line 61; used 2 times
rx2tab defined in line 60; used 22 times

Defined struct's

rx2iocb defined in line 328; never used

Defined macros

DENSITY defined in line 53; used 5 times
NBPS defined in line 52; used 7 times
NRXBLKS defined in line 49; used 1 times
  • in line 91
NSPB defined in line 48; used 2 times
SEMPTY defined in line 70; used 1 times
SFILL defined in line 71; used 1 times
SFORMAT defined in line 74; used 2 times
SINIT defined in line 73; used 2 times
SREAD defined in line 69; used 1 times
SWRITE defined in line 72; used 1 times
UNIT defined in line 54; used 3 times
b_seccnt defined in line 57; used 1 times
  • in line 58
rx2wait defined in line 56; used 9 times
seccnt defined in line 58; used 5 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1279
Valid CSS Valid XHTML 1.0 Strict