Research V5 development
authorDennis Ritchie <dmr@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
committerDennis Ritchie <dmr@research.uucp>
Tue, 26 Nov 1974 23:13:21 +0000 (18:13 -0500)
Work on file usr/sys/dmr/tm.c

Synthesized-from: v5

usr/sys/dmr/tm.c [new file with mode: 0644]

diff --git a/usr/sys/dmr/tm.c b/usr/sys/dmr/tm.c
new file mode 100644 (file)
index 0000000..57b12c7
--- /dev/null
@@ -0,0 +1,222 @@
+#
+/*
+ *     Copyright 1973 Bell Telephone Laboratories Inc
+ */
+
+/*
+ * TM tape driver
+ */
+
+#include "../param.h"
+#include "../buf.h"
+#include "../conf.h"
+#include "../user.h"
+
+struct {
+       int tmer;
+       int tmcs;
+       int tmbc;
+       int tmba;
+       int tmdb;
+       int tmrd;
+};
+
+struct devtab  tmtab;
+struct buf     rtmbuf;
+
+char   t_openf[8];
+char   *t_blkno[8];
+char   *t_nxrec[8];
+
+#define        TMADDR  0172520
+
+#define        GO      01
+#define        RCOM    02
+#define        WCOM    04
+#define        WEOF    06
+#define        SFORW   010
+#define        SREV    012
+#define        WIRG    014
+#define        REW     016
+#define        DENS    060000          /* 9-channel */
+#define        IENABLE 0100
+#define        CRDY    0200
+#define GAPSD  010000
+#define        TUR     1
+#define        HARD    0102200 /* ILC, EOT, NXM */
+#define        EOF     0040000
+
+#define        SSEEK   1
+#define        SIO     2
+
+tmopen(dev, flag)
+{
+       register dminor;
+
+       dminor = dev.d_minor;
+       if (t_openf[dminor])
+               u.u_error = ENXIO;
+       else {
+               t_openf[dminor]++;
+               t_blkno[dminor] = 0;
+               t_nxrec[dminor] = 65535;
+       }
+}
+
+tmclose(dev, flag)
+{
+       register int dminor;
+
+       dminor = dev.d_minor;
+       t_openf[dminor] = 0;
+       if (flag)
+               tcommand(dminor, WEOF);
+       tcommand(dminor, REW);
+}
+
+tcommand(unit, com)
+{
+       extern lbolt;
+
+       while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0)
+               sleep(&lbolt, 1);
+       TMADDR->tmcs = DENS|com|GO | (unit<<8);
+}
+
+tmstrategy(abp)
+struct buf *abp;
+{
+       register struct buf *bp;
+       register char **p;
+
+       bp = abp;
+       p = &t_nxrec[bp->b_dev.d_minor];
+       if (*p <= bp->b_blkno) {
+               if (*p < bp->b_blkno) {
+                       bp->b_flags =| B_ERROR;
+                       iodone(bp);
+                       return;
+               }
+               if (bp->b_flags&B_READ) {
+                       clrbuf(bp);
+                       iodone(bp);
+                       return;
+               }
+       }
+       if ((bp->b_flags&B_READ)==0)
+               *p = bp->b_blkno + 1;
+       bp->av_forw = 0;
+       spl5();
+       if (tmtab.d_actf==0)
+               tmtab.d_actf = bp;
+       else
+               tmtab.d_actl->av_forw = bp;
+       tmtab.d_actl = bp;
+       if (tmtab.d_active==0)
+               tmstart();
+       spl0();
+}
+
+tmstart()
+{
+       register struct buf *bp;
+       register int com;
+       int unit;
+       register char *blkno;
+
+    loop:
+       if ((bp = tmtab.d_actf) == 0)
+               return;
+       unit = bp->b_dev.d_minor;
+       blkno = t_blkno[unit];
+       if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) {
+               bp->b_flags =| B_ERROR;
+               tmtab.d_actf = bp->av_forw;
+               iodone(bp);
+               goto loop;
+       }
+       com = (unit<<8) | (bp->b_flags&B_XMEM) | IENABLE|DENS;
+       if (blkno != bp->b_blkno) {
+               tmtab.d_active = SSEEK;
+               if (blkno < bp->b_blkno) {
+                       com =| SFORW|GO;
+                       TMADDR->tmbc = blkno - bp->b_blkno;
+               } else {
+                       if (bp->b_blkno == 0)
+                               com =| REW|GO;
+                       else {
+                               com =| SREV|GO;
+                               TMADDR->tmbc = bp->b_blkno - blkno;
+                       }
+               }
+               TMADDR->tmcs = com;
+               return;
+       }
+       tmtab.d_active = SIO;
+       TMADDR->tmbc = bp->b_wcount << 1;
+       TMADDR->tmba = bp->b_addr;              /* core address */
+       TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO:
+           ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO));
+}
+
+tmintr()
+{
+       register struct buf *bp;
+       register int unit;
+
+       if ((bp = tmtab.d_actf)==0)
+               return;
+       unit = bp->b_dev.d_minor;
+       if (TMADDR->tmcs < 0) {         /* error bit */
+/*
+               deverror(bp, TMADDR->tmer);
+ */
+               while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
+               if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) {
+                       if (++tmtab.d_errcnt < 10) {
+                               t_blkno[unit]++;
+                               tmtab.d_active = 0;
+                               tmstart();
+                               return;
+                       }
+               } else
+                       if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0)
+                               t_openf[unit] = -1;
+               bp->b_flags =| B_ERROR;
+               tmtab.d_active = SIO;
+       }
+       if (tmtab.d_active == SIO) {
+               tmtab.d_errcnt = 0;
+               t_blkno[unit]++;
+               tmtab.d_actf = bp->av_forw;
+               tmtab.d_active = 0;
+               iodone(bp);
+               bp->b_resid = TMADDR->tmbc;
+       } else
+               t_blkno[unit] = bp->b_blkno;
+       tmstart();
+}
+
+tmread(dev)
+{
+       tmphys(dev);
+       physio(tmstrategy, &rtmbuf, dev, B_READ);
+       u.u_count = -rtmbuf.b_resid;
+}
+
+tmwrite(dev)
+{
+       tmphys(dev);
+       physio(tmstrategy, &rtmbuf, dev, B_WRITE);
+       u.u_count = 0;
+}
+
+tmphys(dev)
+{
+       register unit, a;
+
+       unit = dev.d_minor;
+       a = lshift(u.u_offset, -9);
+       t_blkno[unit] = a;
+       t_nxrec[unit] = ++a;
+}