📄 rx2.c
字号:
#/* * RX02 floppy disk device driver * * Bill Shannon CWRU 05/29/79 * * Modified for Version 7 - 08/13/79 - Bill Shannon * * * Layout of logical devices: * * name min dev unit density * ---- ------- ---- ------- * rx0 0 0 single * rx1 1 1 single * rx2 2 0 double * rx3 3 1 double * * * Stty function call may be used to format a disk. * To enable this feature, define CTRL in this module. */#include "../h/param.h"#include "../h/buf.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/conf.h"#include "../h/tty.h"/* The following structure is used to access av_back as an integer */struct { int dummy0; struct buf *dummy1; struct buf *dummy2; struct buf *dummy3; int seccnt;};struct device { int rx2cs; int rx2db;};/* * the following defines use some fundamental * constants of the RX02. */#define RXADDR ((struct device *) 0177170)#define NSPB ((minor(bp->b_dev)&2) ? 2 : 4) /* Number of floppy sectors per unix block */#define NBPS ((minor(bp->b_dev)&2) ? 256 : 128) /* Number of bytes per floppy sector */#define NRXBLKS ((minor(bp->b_dev)&2) ? 1001 : 500) /* Number of unix blocks on a floppy */#define DENSITY (minor(bp->b_dev)&2) /* Density: 0 = single, 2 = double */#define UNIT (minor(bp->b_dev)&1) /* Unit Number: 0 = left, 1 = right */#define CTRL CTRL /* define for control functions (formatting) */#ifdef CTRL#define B_CTRL 020000#endif#define TRWAIT while (ptcs->lobyte >= 0)struct { char lobyte; char hibyte;};struct buf rx2tab;struct buf rrx2buf;#ifdef CTRLstruct buf crx2buf; /* buffer header for control functions */#endif#define GO 0000001 /* execute command function */#define UNIT1 0000020 /* unit select (drive 0=0, 1=1) */#define RXDONE 0000040 /* function complete */#define INTENB 0000100 /* interrupt enable */#define TRANREQ 0000200 /* transfer request (data only) */#define RXINIT 0040000 /* rx211 initialize */#define RXERROR 0100000 /* general error bit *//* * rx211 control function bits 1-3 of rx2cs */#define FILL 0000000 /* fill buffer */#define EMPTY 0000002 /* empty buffer */#define WRITE 0000004 /* write buffer to disk */#define READ 0000006 /* read disk sector to buffer */#define FORMAT 0000010 /* set media density (format) */#define RSTAT 0000012 /* read disk status */#define WSDD 0000014 /* write sector deleted data */#define RDERR 0000016 /* read error register function *//* * states of driver, kept in b_active */#define SREAD 1 /* read started */#define SEMPTY 2 /* empty started */#define SFILL 3 /* fill started */#define SWRITE 4 /* write started */#define SINIT 5 /* init started */#define SFORMAT 6 /* format started */rx2open(dev, flag){ if(minor(dev) >= 4) u.u_error = ENXIO;}rx2strategy(bp)register struct buf *bp;{ if(bp->b_flags & B_PHYS) mapalloc(bp); if(bp->b_blkno >= NRXBLKS) { if(bp->b_flags&B_READ) bp->b_resid = bp->b_bcount; else { bp->b_flags =| B_ERROR; bp->b_error = ENXIO; } iodone(bp); return; } bp->av_forw = (struct buf *) NULL; /* * seccnt is actually the number of floppy sectors transferred, * incremented by one after each successful transfer of a sector. */ bp->seccnt = 0; /* * We'll modify b_resid as each piece of the transfer * successfully completes. It will also tell us when * the transfer is complete. */ bp->b_resid = bp->b_bcount; spl5(); if(rx2tab.b_actf == NULL) rx2tab.b_actf = bp; else rx2tab.b_actl->av_forw = bp; rx2tab.b_actl = bp; if(rx2tab.b_active == NULL) rx2start(); spl0();}rx2start(){ register int *ptcs, *ptdb; register struct buf *bp; int sector, track; char *addr, *xmem; if((bp = rx2tab.b_actf) == NULL) { rx2tab.b_active = NULL; return; } ptcs = &RXADDR->rx2cs; ptdb = &RXADDR->rx2db;#ifdef CTRL if (bp->b_flags&B_CTRL) { /* is it a control request ? */ rx2tab.b_active = SFORMAT; *ptcs = FORMAT | GO | INTENB | (UNIT << 4) | (DENSITY << 7); TRWAIT; *ptdb = 'I'; } else#endif if(bp->b_flags&B_READ) { rx2tab.b_active = SREAD; rx2factr((int)bp->b_blkno * NSPB + bp->seccnt, §or, &track); *ptcs = READ | GO | INTENB | (UNIT << 4) | (DENSITY << 7); TRWAIT; *ptdb = sector; TRWAIT; *ptdb = track; } else { rx2tab.b_active = SFILL; rx2addr(bp, &addr, &xmem); *ptcs = FILL | GO | INTENB | (xmem << 12) | (DENSITY << 7); TRWAIT; *ptdb = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1; TRWAIT; *ptdb = addr; }}rx2intr() { register int *ptcs, *ptdb; register struct buf *bp; int sector, track; char *addr, *xmem; /* fix for error recovery by duke!phs!dennis */ if (rx2tab.b_active == SINIT) { rx2start(); return; } if((bp = rx2tab.b_actf) == NULL) return; ptcs = &RXADDR->rx2cs; ptdb = &RXADDR->rx2db; if(*ptcs < 0) { if(rx2tab.b_errcnt++ > 10 || rx2tab.b_active == SFORMAT) { bp->b_flags =| B_ERROR; deverror(bp, *ptcs, *ptdb); rx2tab.b_errcnt = 0; rx2tab.b_actf = bp->av_forw; iodone(bp); } *ptcs = RXINIT; *ptcs = INTENB; rx2tab.b_active = SINIT; return; } switch (rx2tab.b_active) { case SREAD: /* read done, start empty */ rx2tab.b_active = SEMPTY; rx2addr(bp, &addr, &xmem); *ptcs = EMPTY | GO | INTENB | (xmem << 12) | (DENSITY << 7); TRWAIT; *ptdb = (bp->b_resid >= NBPS ? NBPS : bp->b_resid) >> 1; TRWAIT; *ptdb = addr; return; case SFILL: /* fill done, start write */ rx2tab.b_active = SWRITE; rx2factr((int)bp->b_blkno * NSPB + bp->seccnt, §or, &track); *ptcs = WRITE | GO | INTENB | (UNIT << 4) | (DENSITY << 7); TRWAIT; *ptdb = sector; TRWAIT; *ptdb = track; return; case SWRITE: /* write done, start next fill */ case SEMPTY: /* empty done, start next read */ /* * increment amount remaining to be transferred. * if it becomes positive, last transfer was a * partial sector and we're done, so set remaining * to zero. */ if (bp->b_resid <= NBPS) {done: bp->b_resid = 0; rx2tab.b_errcnt = 0; rx2tab.b_actf = bp->av_forw; iodone(bp); break; } bp->b_resid -= NBPS; bp->seccnt++; break;#ifdef CTRL case SFORMAT: /* format done (whew!!!) */ goto done; /* driver's getting too big... */#endif } /* end up here from states SWRITE, SEMPTY, and SINIT */ rx2start();}/* * rx2factr -- calculates the physical sector and physical * track on the disk for a given logical sector. * call: * rx2factr(logical_sector,&p_sector,&p_track); * the logical sector number (0 - 2001) is converted * to a physical sector number (1 - 26) and a physical * track number (0 - 76). * the logical sectors specify physical sectors that * are interleaved with a factor of 2. thus the sectors * are read in the following order for increasing * logical sector numbers (1,3, ... 23,25,2,4, ... 24,26) * There is also a 6 sector slew between tracks. * Logical sectors start at track 1, sector 1; go to * track 76 and then to track 0. Thus, for example, unix block number * 498 starts at track 0, sector 21 and runs thru track 0, sector 2. */rx2factr(sectr, psectr, ptrck)register int sectr;int *psectr, *ptrck;{ register int p1, p2; p1 = sectr/26; p2 = sectr%26; /* 2 to 1 interleave */ p2 = (2*p2 + (p2 >= 13 ? 1 : 0)) % 26; /* 6 sector per track slew */ *psectr = 1 + (p2 + 6*p1) % 26; if (++p1 >= 77) p1 = 0; *ptrck = p1;}/* * rx2addr -- compute core address where next sector * goes to / comes from based on bp->b_un.b_addr, bp->b_xmem, * and bp->seccnt. */rx2addr(bp, addr, xmem)register struct buf *bp;register char **addr, **xmem;{ *addr = bp->b_un.b_addr + bp->seccnt * NBPS; *xmem = bp->b_xmem; if (*addr < bp->b_un.b_addr) /* overflow, bump xmem */ (*xmem)++;}rx2read(dev){ physio(rx2strategy, &rrx2buf, dev, B_READ, minor(dev)&2 ? 1001 : 500);}rx2write(dev){ physio(rx2strategy, &rrx2buf, dev, B_WRITE, minor(dev)&2 ? 1001 : 500);}#ifdef CTRL/* * rx2sgtty -- format RX02 disk, single or double density. * stty with word 0 == 010 does format. density determined * by device opened. */rx2ioctl(dev, cmd, addr, flag){ register struct buf *bp; struct rx2iocb { int ioc_cmd; /* command */ int ioc_res1; /* reserved */ int ioc_res2; /* reserved */ } iocb; if (cmd != TIOCSETP) {err: u.u_error = ENXIO; return(0); } if (copyin(addr, (caddr_t)&iocb, sizeof (iocb))) { u.u_error = EFAULT; return(1); } if (iocb.ioc_cmd != FORMAT) goto err; bp = &crx2buf; spl6(); while (bp->b_flags & B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO); } bp->b_flags = B_BUSY | B_CTRL; bp->b_dev = dev; bp->b_error = 0; rx2strategy(bp); iowait(bp); bp->b_flags = 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -