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

  1. /*
  2.  * RP04/RP06 disk driver
  3.  */
  4.  
  5. #include "../h/param.h"
  6. #include "../h/systm.h"
  7. #include "../h/buf.h"
  8. #include "../h/conf.h"
  9. #include "../h/dir.h"
  10. #include "../h/user.h"
  11.  
  12. #define    DK_N    0
  13.  
  14. struct    device
  15. {
  16.     union {
  17.         int    w;
  18.         char    c[2];
  19.     } hpcs1;        /* Control and Status register 1 */
  20.     int    hpwc;        /* Word count register */
  21.     caddr_t    hpba;        /* UNIBUS address register */
  22.     int    hpda;        /* Desired address register */
  23.     union {
  24.         int    w;
  25.         char    c[2];
  26.     } hpcs2;        /* Control and Status register 2*/
  27.     int    hpds;        /* Drive Status */
  28.     int    hper1;        /* Error register 1 */
  29.     int    hpas;        /* Attention Summary */
  30.     int    hpla;        /* Look ahead */
  31.     int    hpdb;        /* Data buffer */
  32.     int    hpmr;        /* Maintenance register */
  33.     int    hpdt;        /* Drive type */
  34.     int    hpsn;        /* Serial number */
  35.     int    hpof;        /* Offset register */
  36.     int    hpdc;        /* Desired Cylinder address register*/
  37.     int    hpcc;        /* Current Cylinder */
  38.     int    hper2;        /* Error register 2 */
  39.     int    hper3;        /* Error register 3 */
  40.     int    hpec1;        /* Burst error bit position */
  41.     int    hpec2;        /* Burst error bit pattern */
  42.     int    hpbae;        /* 11/70 bus extension */
  43.     int    hpcs3;
  44. };
  45.  
  46. #define    HPADDR    ((struct device *)0176700)
  47. #define    NHP    2
  48. #define    NSECT    22
  49. #define    NTRAC    19
  50. #define    SDIST    2
  51. #define    RDIST    6
  52.  
  53. struct    size
  54. {
  55.     daddr_t    nblocks;
  56.     int    cyloff;
  57. } hp_sizes[8] =
  58. {
  59.     9614,    0,        /* cyl 0 thru 22 */
  60.     8778,    23,        /* cyl 23 thru 43 */
  61.     0,    0,
  62.     0,    0,
  63.     161348,    44,        /* cyl 44 thru 429 */
  64.     160930, 430,        /* cyl 430 thru 814 */
  65.     153406,    44,        /* cyl 44 thru 410 (rp04, rp05) */
  66.     322278,    44,        /* cyl 44 thru 814 (rp06) */
  67. };
  68.  
  69. #define    P400    020
  70. #define    M400    0220
  71. #define    P800    040
  72. #define    M800    0240
  73. #define    P1200    060
  74. #define    M1200    0260
  75. int    hp_offset[16] =
  76. {
  77.     P400, M400, P400, M400,
  78.     P800, M800, P800, M800,
  79.     P1200, M1200, P1200, M1200,
  80.     0, 0, 0, 0,
  81. };
  82.  
  83. struct    buf    hptab;
  84. struct    buf    rhpbuf;
  85. struct    buf    hputab[NHP];
  86.  
  87. #define    GO    01
  88. #define    PRESET    020
  89. #define    RTC    016
  90. #define    OFFSET    014
  91. #define    SEARCH    030
  92. #define    RECAL    06
  93. #define DCLR    010
  94. #define    WCOM    060
  95. #define    RCOM    070
  96.  
  97. #define    IE    0100
  98. #define    PIP    020000
  99. #define    DRY    0200
  100. #define    ERR    040000
  101. #define    TRE    040000
  102. #define    DCK    0100000
  103. #define    WLE    04000
  104. #define    ECH    0100
  105. #define VV    0100
  106. #define    DPR    0400
  107. #define    MOL    010000
  108. #define FMT22    010000
  109.  
  110. #define    b_cylin    b_resid
  111.  
  112. daddr_t dkblock();
  113.  
  114. hpstrategy(bp)
  115. register struct buf *bp;
  116. {
  117.     register struct buf *dp;
  118.     register unit;
  119.     long sz, bn;
  120.  
  121.     unit = minor(bp->b_dev) & 077;
  122.     sz = bp->b_bcount;
  123.     sz = (sz+511) >> 9;
  124.     if (unit >= (NHP<<3) ||
  125.         bp->b_blkno < 0 ||
  126.         (bn = dkblock(bp))+sz > hp_sizes[unit&07].nblocks) {
  127.         bp->b_flags |= B_ERROR;
  128.         iodone(bp);
  129.         return;
  130.     }
  131.     bp->b_cylin = bn/(NSECT*NTRAC) + hp_sizes[unit&07].cyloff;
  132.     unit = dkunit(bp);
  133.     dp = &hputab[unit];
  134.     spl5();
  135.     disksort(dp, bp);
  136.     if (dp->b_active == 0) {
  137.         hpustart(unit);
  138.         if(hptab.b_active == 0)
  139.             hpstart();
  140.     }
  141.     spl0();
  142. }
  143.  
  144. hpustart(unit)
  145. register unit;
  146. {
  147.     register struct buf *bp, *dp;
  148.     daddr_t bn;
  149.     int sn, cn, csn;
  150.  
  151.     HPADDR->hpcs2.w = unit;
  152.     HPADDR->hpcs1.c[0] = IE;
  153.     HPADDR->hpas = 1<<unit;
  154.  
  155.     if(unit >= NHP)
  156.         return;
  157.     dk_busy &= ~(1<<(unit+DK_N));
  158.     dp = &hputab[unit];
  159.     if((bp=dp->b_actf) == NULL)
  160.         return;
  161.     if((HPADDR->hpds & VV) == 0) {
  162.         HPADDR->hpcs1.c[0] = IE|PRESET|GO;
  163.         HPADDR->hpof = FMT22;
  164.     }
  165.     if(dp->b_active)
  166.         goto done;
  167.     dp->b_active++;
  168.     if ((HPADDR->hpds & (DPR|MOL)) != (DPR|MOL))
  169.         goto done;
  170.  
  171.     bn = dkblock(bp);
  172.     cn = bp->b_cylin;
  173.     sn = bn%(NSECT*NTRAC);
  174.     sn = (sn+NSECT-SDIST)%NSECT;
  175.  
  176.     if(HPADDR->hpcc != cn)
  177.         goto search;
  178.     csn = (HPADDR->hpla>>6) - sn + SDIST - 1;
  179.     if(csn < 0)
  180.         csn += NSECT;
  181.     if(csn > NSECT-RDIST)
  182.         goto done;
  183.  
  184. search:
  185.     HPADDR->hpdc = cn;
  186.     HPADDR->hpda = sn;
  187.     HPADDR->hpcs1.c[0] = IE|SEARCH|GO;
  188.     unit += DK_N;
  189.     dk_busy |= 1<<unit;
  190.     dk_numb[unit] += 1;
  191.     return;
  192.  
  193. done:
  194.     dp->b_forw = NULL;
  195.     if(hptab.b_actf == NULL)
  196.         hptab.b_actf = dp; else
  197.         hptab.b_actl->b_forw = dp;
  198.     hptab.b_actl = dp;
  199. }
  200.  
  201. hpstart()
  202. {
  203.     register struct buf *bp, *dp;
  204.     register unit;
  205.     daddr_t bn;
  206.     int dn, sn, tn, cn;
  207.  
  208. loop:
  209.     if ((dp = hptab.b_actf) == NULL)
  210.         return;
  211.     if ((bp = dp->b_actf) == NULL) {
  212.         hptab.b_actf = dp->b_forw;
  213.         goto loop;
  214.     }
  215.     hptab.b_active++;
  216.     unit = minor(bp->b_dev) & 077;
  217.     dn = dkunit(bp);
  218.     bn = dkblock(bp);
  219.     cn = bn/(NSECT*NTRAC) + hp_sizes[unit&07].cyloff;
  220.     sn = bn%(NSECT*NTRAC);
  221.     tn = sn/NSECT;
  222.     sn = sn%NSECT;
  223.  
  224.     HPADDR->hpcs2.w = dn;
  225.     if ((HPADDR->hpds & (DPR|MOL)) != (DPR|MOL)) {
  226.         hptab.b_active = 0;
  227.         hptab.b_errcnt = 0;
  228.         dp->b_actf = bp->av_forw;
  229.         bp->b_flags |= B_ERROR;
  230.         iodone(bp);
  231.         goto loop;
  232.     }
  233.     if(hptab.b_errcnt >= 16) {
  234.         HPADDR->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
  235.         HPADDR->hpcs1.w = OFFSET|GO;
  236.         while(HPADDR->hpds & PIP)
  237.             ;
  238.     }
  239.     HPADDR->hpdc = cn;
  240.     HPADDR->hpda = (tn << 8) + sn;
  241.     HPADDR->hpba = bp->b_un.b_addr;
  242.     if(cputype == 70)
  243.         HPADDR->hpbae = bp->b_xmem;
  244.     HPADDR->hpwc = -(bp->b_bcount>>1);
  245.     unit = ((bp->b_xmem&3) << 8) | IE | GO;
  246.     if(bp->b_flags & B_READ)
  247.         unit |= RCOM; else
  248.         unit |= WCOM;
  249.     HPADDR->hpcs1.w = unit;
  250.  
  251.     dk_busy |= 1<<(DK_N+NHP);
  252.     dk_numb[DK_N+NHP] += 1;
  253.     unit = bp->b_bcount>>6;
  254.     dk_wds[DK_N+NHP] += unit;
  255. }
  256.  
  257. hpintr()
  258. {
  259.     register struct buf *bp, *dp;
  260.     register unit;
  261.     int as, i, j;
  262.  
  263.     as = HPADDR->hpas & 0377;
  264.     if(hptab.b_active) {
  265.         dk_busy &= ~(1<<(DK_N+NHP));
  266.         dp = hptab.b_actf;
  267.         bp = dp->b_actf;
  268.         unit = dkunit(bp);
  269.         HPADDR->hpcs2.c[0] = unit;
  270.         if (HPADDR->hpcs1.w & TRE) {        /* error bit */
  271.             while((HPADDR->hpds & DRY) == 0)
  272.                 ;
  273.             if(++hptab.b_errcnt > 28 || HPADDR->hper1&WLE)
  274.                 bp->b_flags |= B_ERROR; else
  275.                 hptab.b_active = 0;
  276.             if(hptab.b_errcnt > 27)
  277.                 deverror(bp, HPADDR->hpcs2.w, HPADDR->hper1);
  278.             if((bp->b_flags&B_PHYS) == 0 &&
  279.                (HPADDR->hper1 & (DCK|ECH)) == DCK) {
  280.                 i = HPADDR->hpec1 - 1;
  281.                 j = i&017;
  282.                 i >>= 4;
  283.                 if(i >= 0 && i <256) {
  284.                     bp->b_un.b_words[i] ^= HPADDR->hpec2 << j;
  285.                     bp->b_un.b_words[i+1] ^= HPADDR->hpec2 >> (16-j);
  286.                 }
  287.                 hptab.b_active++;
  288.                 printf("%D ", bp->b_blkno);
  289.                 prdev("ECC", bp->b_dev);
  290.             }
  291.             HPADDR->hpcs1.w = TRE|IE|DCLR|GO;
  292.             if((hptab.b_errcnt&07) == 4) {
  293.                 HPADDR->hpcs1.w = RECAL|IE|GO;
  294.                 while(HPADDR->hpds & PIP)
  295.                     ;
  296.             }
  297.         }
  298.         if(hptab.b_active) {
  299.             if(hptab.b_errcnt) {
  300.                 HPADDR->hpcs1.w = RTC|GO;
  301.                 while(HPADDR->hpds & PIP)
  302.                     ;
  303.             }
  304.             hptab.b_active = 0;
  305.             hptab.b_errcnt = 0;
  306.             hptab.b_actf = dp->b_forw;
  307.             dp->b_active = 0;
  308.             dp->b_errcnt = 0;
  309.             dp->b_actf = bp->av_forw;
  310.             bp->b_resid = -(HPADDR->hpwc<<1);
  311.             iodone(bp);
  312.             HPADDR->hpcs1.w = IE;
  313.             if(dp->b_actf)
  314.                 hpustart(unit);
  315.         }
  316.         as &= ~(1<<unit);
  317.     } else {
  318.         if(as == 0)
  319.             HPADDR->hpcs1.w = IE;
  320.         HPADDR->hpcs1.c[1] = TRE>>8;
  321.     }
  322.     for(unit=0; unit<NHP; unit++)
  323.         if(as & (1<<unit))
  324.             hpustart(unit);
  325.     hpstart();
  326. }
  327.  
  328. hpread(dev)
  329. {
  330.  
  331.     physio(hpstrategy, &rhpbuf, dev, B_READ);
  332. }
  333.  
  334. hpwrite(dev)
  335. {
  336.  
  337.     physio(hpstrategy, &rhpbuf, dev, B_WRITE);
  338. }
  339.