home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / sys / dev / tm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-03  |  5.1 KB  |  301 lines

  1. #
  2.  
  3. /*
  4.  * TM tape driver
  5.  */
  6.  
  7. #include "../h/param.h"
  8. #include "../h/buf.h"
  9. #include "../h/dir.h"
  10. #include "../h/conf.h"
  11. #include "../h/file.h"
  12. #include "../h/user.h"
  13.  
  14. struct device {
  15.     int    tmer;
  16.     int    tmcs;
  17.     int    tmbc;
  18.     char    *tmba;
  19.     int    tmdb;
  20.     int    tmrd;
  21. };
  22.  
  23. struct    buf    tmtab;
  24. struct    buf    ctmbuf;
  25. struct    buf    rtmbuf;
  26.  
  27. char    t_flags[8];
  28. char    t_openf[8];
  29. daddr_t    t_blkno[8];
  30. daddr_t    t_nxrec[8];
  31.  
  32. #define    TMADDR ((struct device *)0172520)
  33.  
  34. #define    GO    01
  35. #define    RCOM    02
  36. #define    WCOM    04
  37. #define    WEOF    06
  38. #define    NOP    0100
  39. #define    SFORW    010
  40. #define    SREV    012
  41. #define    WIRG    014
  42. #define    REW    016
  43. #define    DENS    060000        /* 9-channel */
  44. #define    IENABLE    0100
  45. #define    CRDY    0200
  46. #define GAPSD    010000
  47. #define    TUR    1
  48. #define    HARD    0102200    /* ILC, EOT, NXM */
  49. #define RLE    0100
  50. #define    EOF    0040000
  51. #define    WL    04
  52.  
  53. #define    SSEEK    1
  54. #define    SIO    2
  55. #define    SCOM    3
  56.  
  57. #define T_WRITTEN 1
  58.  
  59. tmopen(dev, flag)
  60. {
  61.     register unit, ds;
  62.  
  63.     unit = minor(dev) & 0177;
  64.     if (t_openf[unit]) {
  65.         u.u_error = ENXIO;
  66.         return;
  67.     }
  68.     t_blkno[unit] = 0;
  69.     t_nxrec[unit] = 65535;
  70.     t_flags[unit] = 0;
  71.  
  72.     tmtab.b_flags |= B_TAPE;
  73.     ds = tcommand(dev, NOP);
  74.     if ((ds&TUR)==0) {
  75.         printf("mt%d off line\n",unit);
  76.         u.u_error = ENXIO;
  77.     }
  78.     if (flag && ds&WL) {
  79.         printf("mt%d needs write ring\n",unit);
  80.         u.u_error = ENXIO;
  81.     }
  82.     if (u.u_error==0)
  83.         t_openf[unit]++;
  84. }
  85.  
  86. tmclose(dev, flag)
  87. dev_t dev;
  88. int flag;
  89. {
  90.  
  91.     if ( flag == FWRITE ||
  92.     ((flag&FWRITE) && (t_flags[minor(dev)&0177]&T_WRITTEN))) {
  93.         tcommand(dev, WEOF);
  94.         tcommand(dev, WEOF);
  95.         tcommand(dev, SREV);
  96.     }
  97.     if ((minor(dev)&0200) == 0)
  98.         tcommand(dev, REW);
  99.     t_openf[minor(dev)&077] = 0;
  100. }
  101.  
  102. tcommand(dev, com)
  103. {
  104.     register struct buf *bp;
  105.  
  106.     bp = &ctmbuf;
  107.     spl5();
  108.     while (bp->b_flags&B_BUSY) {
  109.         bp->b_flags |= B_WANTED;
  110.         sleep((caddr_t)bp, PRIBIO);
  111.     }
  112.     bp->b_flags = B_BUSY|B_READ;
  113.     spl0();
  114.     bp->b_dev = dev;
  115.     bp->b_resid = com;
  116.     bp->b_blkno = 0;
  117.     tmstrategy(bp);
  118.     iowait(bp);
  119.     if (bp->b_flags&B_WANTED)
  120.         wakeup((caddr_t)bp);
  121.     bp->b_flags = 0;
  122.     return(bp->b_resid);
  123. }
  124.  
  125. tmstrategy(bp)
  126. register struct buf *bp;
  127. {
  128.     register daddr_t *p;
  129.  
  130.     if(bp->b_flags&B_PHYS)
  131.         mapalloc(bp);
  132.     if (bp != &ctmbuf) {
  133.         p = &t_nxrec[minor(bp->b_dev)&0177];
  134.         if (*p <= bp->b_blkno) {
  135.             if (*p < bp->b_blkno) {
  136.                 bp->b_flags |= B_ERROR;
  137.                 iodone(bp);
  138.                 return;
  139.             }
  140.             if (bp->b_flags&B_READ) {
  141.                 clrbuf(bp);
  142.                 bp->b_resid = 0;
  143.                 iodone(bp);
  144.                 return;
  145.             }
  146.         }
  147.         if ((bp->b_flags&B_READ) == 0) {
  148.             t_flags[minor(bp->b_dev)&0177] |= T_WRITTEN;
  149.             *p = bp->b_blkno+1;
  150.         }
  151.     }
  152.     bp->av_forw = 0;
  153.     spl5();
  154.     if (tmtab.b_actf == NULL)
  155.         tmtab.b_actf = bp;
  156.     else
  157.         tmtab.b_actl->av_forw = bp;
  158.     tmtab.b_actl = bp;
  159.     if (tmtab.b_active == NULL)
  160.         tmstart();
  161.     spl0();
  162. }
  163.  
  164. tmstart()
  165. {
  166.     register struct buf *bp;
  167.     register int com;
  168.     int unit;
  169.     register daddr_t *blkno;
  170.  
  171.     loop:
  172.     if ((bp = tmtab.b_actf) == 0)
  173.         return;
  174.     unit = minor(bp->b_dev)&0177;
  175.     blkno = &t_blkno[unit];
  176.     if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY) == NULL) {
  177.         bp->b_flags |= B_ERROR;
  178.         goto next;
  179.     }
  180.     if (bp == &ctmbuf) {
  181.         if (bp->b_resid == NOP) {
  182.             bp->b_resid = TMADDR->tmer;
  183.             goto next;
  184.         }
  185.         tmtab.b_active = SCOM;
  186.         TMADDR->tmcs = DENS|bp->b_resid|GO| (unit<<8) | IENABLE;
  187.         return;
  188.     }
  189.     com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS;
  190.     if (*blkno != bp->b_blkno) {
  191.         tmtab.b_active = SSEEK;
  192.         if (*blkno < bp->b_blkno) {
  193.             com |= SFORW|GO;
  194.             TMADDR->tmbc = *blkno - bp->b_blkno;
  195.         } else {
  196.             if (bp->b_blkno == 0)
  197.                 com |= REW|GO;
  198.             else {
  199.                 com |= SREV|GO;
  200.                 TMADDR->tmbc = bp->b_blkno - *blkno;
  201.             }
  202.         }
  203.         TMADDR->tmcs = com;
  204.         return;
  205.     }
  206.     tmtab.b_active = SIO;
  207.     TMADDR->tmbc = -bp->b_bcount;
  208.     TMADDR->tmba = bp->b_un.b_addr;
  209.     TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO:
  210.         ((tmtab.b_errcnt)? WIRG|GO: WCOM|GO));
  211.     return;
  212.  
  213. next:
  214.     tmtab.b_actf = bp->av_forw;
  215.     iodone(bp);
  216.     goto loop;
  217. }
  218.  
  219. tmintr()
  220. {
  221.     register struct buf *bp;
  222.     register int unit;
  223.     int    state;
  224.  
  225.     if ((bp = tmtab.b_actf) == NULL)
  226.         return;
  227.     unit = minor(bp->b_dev)&0177;
  228.     state = tmtab.b_active;
  229.     tmtab.b_active = 0;
  230.     if (TMADDR->tmcs < 0) {        /* error bit */
  231.         while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
  232.         if (TMADDR->tmer&EOF) {
  233.             t_nxrec[unit] = bp->b_blkno;
  234.             state = SCOM;
  235.             TMADDR->tmbc = -bp->b_bcount;
  236.             goto out;
  237.         }
  238.         if ((TMADDR->tmer&HARD) == 0 && TMADDR->tmer&RLE) {
  239.             state = SIO;
  240.             goto out;
  241.         }
  242.         if ((TMADDR->tmer&(HARD|EOF)) == NULL && state==SIO) {
  243.             if (++tmtab.b_errcnt < 2) {
  244.                 t_blkno[unit]++;
  245.                 tmtab.b_active = 0;
  246.                 tmstart();
  247.                 return;
  248.             }
  249.         } else
  250.             if (t_openf[unit]>0 && bp!=&rtmbuf &&
  251.                 (TMADDR->tmer&EOF)==0 ) {
  252.                 t_openf[unit] = -1;
  253.                 deverror(bp, TMADDR->tmer, 0);
  254.             }
  255.         bp->b_flags |= B_ERROR;
  256.         state = SIO;
  257.     }
  258. out:
  259.     switch ( state ) {
  260.     case SIO:
  261.         t_blkno[unit] += (bp->b_bcount>>BSHIFT);
  262.     case SCOM:
  263.         tmtab.b_errcnt = 0;
  264.         tmtab.b_actf = bp->av_forw;
  265.         bp->b_resid = -TMADDR->tmbc;
  266.         iodone(bp);
  267.         break;
  268.     case SSEEK:
  269.         t_blkno[unit] = bp->b_blkno;
  270.         break;
  271.     default:
  272.         return;
  273.     }
  274.     tmstart();
  275. }
  276.  
  277. tmread(dev)
  278. {
  279.     tmphys(dev);
  280.     physio(tmstrategy, &rtmbuf, dev, B_READ);
  281. }
  282.  
  283. tmwrite(dev)
  284. {
  285.     tmphys(dev);
  286.     physio(tmstrategy, &rtmbuf, dev, B_WRITE);
  287. }
  288.  
  289. tmphys(dev)
  290. {
  291.     register unit;
  292.     daddr_t a;
  293.  
  294.     unit = minor(dev) & 0177;
  295.     if(unit < 8) {
  296.         a = u.u_offset >> 9;
  297.         t_blkno[unit] = a;
  298.         t_nxrec[unit] = a+1;
  299.     }
  300. }
  301.