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

  1. /*
  2.  * RL disk driver
  3.  * Reworked to handle RL01/RL02
  4.  *    R.A.Mason    Oct.1980
  5.  * Intended to eventually handle overlapped seeks
  6.  */
  7.  
  8. #include "../h/param.h"
  9. #include "../h/buf.h"
  10. #include "../h/dir.h"
  11. #include "../h/user.h"
  12. #include "../h/systm.h"
  13.  
  14. #define DK_N    1
  15.  
  16. struct device {
  17.     int rlcs;
  18.     int rlba;
  19.     int rlda;
  20.     int rlmp;
  21. };
  22.  
  23. #define    RLADDR    ((struct device *)0174400)
  24. #define    NPDISK    4
  25. #define    NLDISK    1    /* no subdivision into logical disks */
  26. #define RLCYLSZ        10240
  27. #define RLSECSZ        256
  28. #define RL01SIZE    10240
  29. #define RL02SIZE    20480
  30.  
  31. /* rlcs bits */
  32. #define DRDY        0000001
  33. #define GETSTAT        0000004
  34. #define SEEK        0000006
  35. #define RDHDR        0000010
  36. #define WCOM        0000012
  37. #define RCOM        0000014
  38. #define IENABLE        0000100
  39. #define CRDY        0000200
  40. #define DS        0001400
  41. #define OPI        0002000
  42. #define CRC        0004000
  43. #define DLT        0010000
  44. #define NXM        0020000
  45. #define DE        0040000
  46. #define ERROR        0100000
  47. #define ACCESS_ERROR    (NXM|DLT|CRC|OPI)
  48.  
  49. /* rlda bits    - during seek */
  50. #define SEEKLO        0000001
  51. #define SEEKHI        0000005
  52. /*        - during get status */
  53. #define GS        0000002
  54. #define RST        0000010
  55. #define RESET        (RST|GS|01)
  56. #define STAT        (GS|01)
  57.  
  58. /* status bits */
  59. #define HO        0000020
  60. #define DT        0000200
  61. #define VC        0001000
  62. #define WL        0020000
  63.  
  64. struct    buf    rltab;
  65. struct    buf    rrlbuf;
  66.  
  67. struct rl
  68. {
  69.     int    status;        /* drive status */
  70.     int    headp;        /* location of heads */
  71.     struct buf *iop;    /* current transfer on drive */
  72.     int    errcnt;        /* error count on drive    */
  73.     int    com;        /* read or write command word */
  74.     int    chn;        /* cylinder and head number */
  75.     unsigned int    bleft;    /* bytes left to be transferred */
  76.     unsigned int    bpart;    /* number of bytes transferred */
  77.     int    sn;        /* sector number */
  78.     union {
  79.         int    w[2];
  80.         long    l;
  81.     } addr;            /* address of memory for transfer */
  82. } rl[NPDISK];
  83. /* Bit sets for drive status */
  84. #define RL01        01
  85. #define RL02        02
  86. #define HEADKNOWN    010
  87.  
  88. rlopen(dev,rw)
  89. dev_t dev;
  90. {
  91.     register struct rl *rlp;
  92.     register struct device *rp;
  93.     int drive,status;
  94.  
  95.     drive = minor(dev);
  96.     if(drive >= NPDISK) {
  97.         u.u_error = ENXIO;
  98.         return;
  99.     }
  100.     rlp = &rl[drive];
  101.     rp = RLADDR;
  102.     spl5();
  103.     while((rp->rlcs & CRDY) == 0);
  104.     rp->rlda = STAT;
  105.     rp->rlcs = (drive << 8) | GETSTAT;
  106.     while((rp->rlcs & CRDY) == 0);
  107.     status = rp->rlmp;
  108.     rp->rlda = RESET;
  109.     rp->rlcs = (drive << 8) | GETSTAT;
  110.     while((rp->rlcs & CRDY) == 0);
  111.     spl0();
  112.     if((status&HO) == 0) {
  113.         u.u_error = ENXIO;
  114.         return;
  115.     }
  116.     if(rw && (status&WL)) {
  117.         u.u_error = EROFS;
  118.         return;
  119.     }
  120.     if(status&DT)
  121.         rlp->status |= RL02;
  122.     else
  123.         rlp->status |= RL01;
  124. }
  125.  
  126. rlclose(dev)
  127. dev_t dev;
  128. {
  129.     register struct rl *rlp;
  130.  
  131.     rlp = &rl[minor(dev)];
  132.     /* will do something on next rework */
  133. }
  134.  
  135. rlstrategy(bp)
  136. register struct buf *bp;
  137. {
  138.     register struct rl *rlp;
  139.     int drive,dsize;
  140.  
  141. #ifdef UNIBMAP
  142.     if(bp->b_flags&B_PHYS)
  143.         mapalloc(bp);
  144. #endif UNIBMAP
  145.     drive = minor(bp->b_dev);
  146.     rlp = &rl[drive];
  147.     dsize = 0;
  148.     if(rlp->status&RL01)
  149.         dsize = RL01SIZE;
  150.     else
  151.     if(rlp->status&RL02)
  152.         dsize = RL02SIZE;
  153.     if(bp->b_blkno >= dsize) {
  154.         if((bp->b_blkno == dsize) && (bp->b_flags&B_READ))
  155.             bp->b_resid = bp->b_bcount;
  156.         else {
  157.             bp->b_flags |= B_ERROR;
  158.             bp->b_error = ENXIO;
  159.         }
  160.         iodone(bp);
  161.         return;
  162.     }
  163.     bp->av_forw = NULL;
  164.     spl5();
  165.     if(rltab.b_actf == NULL)
  166.         rltab.b_actf = bp;
  167.     else
  168.         rltab.b_actl->av_forw = bp;
  169.     rltab.b_actl = bp;
  170.     if(rltab.b_active == NULL)
  171.         rlstart();
  172.     spl0();
  173. }
  174.  
  175. rlstart()
  176. {
  177.     register struct buf *bp;
  178.     register struct rl *rlp;
  179.     int drive;
  180.  
  181.     if((bp = rltab.b_actf) == NULL)
  182.         return;
  183.     rltab.b_active++;
  184.     drive = minor(bp->b_dev);
  185.     rlp = &rl[drive];
  186.     rlp->iop = bp;
  187.     rlp->chn = bp->b_blkno/20;
  188.     rlp->sn = (bp->b_blkno%20) << 1;
  189.     rlp->bleft = bp->b_bcount;
  190.     rlp->addr.w[0] = bp->b_xmem & 3;
  191.     rlp->addr.w[1] = (int)bp->b_un.b_addr;
  192.     rlp->com = (drive << 8) | IENABLE;
  193.     if(bp->b_flags & B_READ)
  194.         rlp->com |= RCOM;
  195.     else
  196.         rlp->com |= WCOM;
  197.     rlio(drive);
  198. }
  199.  
  200. rlintr()
  201. {
  202.     register struct buf *bp;
  203.     register struct device *rp;
  204.     register struct rl *rlp;
  205.     int drive,status;
  206.  
  207.     rp = RLADDR;
  208.     drive = (rp->rlcs&DS) >> 8;
  209.     rlp = &rl[drive];
  210.     if(rlp->iop == NULL) {
  211. /*        logstray(rp); */
  212.         return;
  213.     }
  214.     bp = rlp->iop;
  215. #ifdef INSTRM
  216.     dk_busy &= ~(1<<DK_N);
  217. #endif INSTRM
  218.     if(rp->rlcs&ERROR) {
  219.         if(rp->rlcs&ACCESS_ERROR) {
  220.             if(rlp->errcnt > 2)
  221.                 deverror(bp, rp->rlcs, rp->rlda);
  222.         }
  223.         if(rp->rlcs&DE) {
  224.             rp->rlda = STAT;
  225.             rp->rlcs = (drive << 8) | GETSTAT;
  226.             while((rp->rlcs & CRDY) == 0);
  227.             status = rp->rlmp;
  228.             if(rlp->errcnt > 2)
  229.                 deverror(bp, status, rp->rlda);
  230.             rp->rlda = RESET;
  231.             rp->rlcs = (drive << 8) | GETSTAT;
  232.             while((rp->rlcs & CRDY) == 0);
  233.             if(status&DT)        /* drive type */
  234.                 rlp->status |= RL02;
  235.             else
  236.                 rlp->status |= RL01;
  237.             if(status&VC) {        /* volume check */
  238.                 rlstart();
  239.                 return;
  240.             }
  241.         }
  242.         if(++rlp->errcnt <= 10) {
  243.             rlp->status &= ~HEADKNOWN;
  244.             rlstart();
  245.             return;
  246.         }
  247.         else {
  248.             bp->b_flags |= B_ERROR;
  249.             rlp->bpart = rlp->bleft;
  250.         }
  251.     }
  252.     if((rlp->bleft -= rlp->bpart) > 0) {
  253.         rlp->addr.l += rlp->bpart;
  254.         rlp->sn = 0;
  255.         rlp->chn++;
  256.         rlio(drive);
  257.         return;
  258.     }
  259.     rlp->iop = NULL;
  260.     rlp->errcnt = 0;
  261.     rltab.b_active = NULL;
  262.     rltab.b_actf = bp->av_forw;
  263.     bp->b_resid = 0;
  264.     iodone(bp);
  265.     rlstart();
  266. }
  267.  
  268. rlio(dn)
  269. int dn;
  270. {
  271.     register struct device *rp;
  272.     register struct rl *rlp;
  273.     int dif,head;
  274.  
  275.     rp = RLADDR;
  276.     rlp = &rl[dn];
  277. #ifdef INSTRM
  278.     dk_busy |= 1<<DK_N;
  279.     dk_numb[DK_N] += 1;
  280.     dk_wds[DK_N] += (rlp->bpart>>6);
  281. #endif INSTRM
  282.     if((rlp->status&HEADKNOWN) == 0) {
  283.         rp->rlcs = (dn << 8) | RDHDR;
  284.         while((rp->rlcs&CRDY) == 0);
  285.         rlp->headp = ((unsigned)(rp->rlmp&0177700)) >> 6;
  286.         rlp->status |= HEADKNOWN;
  287.     }
  288.     dif = (rlp->headp >> 1) - (rlp->chn >>1);
  289.     head = (rlp->chn & 1) << 4;
  290.     if(dif < 0)
  291.         rp->rlda = (-dif<<7) | SEEKHI | head;
  292.     else
  293.         rp->rlda = (dif<< 7) | SEEKLO | head;
  294.     rp->rlcs = (dn << 8) | SEEK;
  295.     rlp->headp = rlp->chn;
  296.     if(rlp->bleft < (rlp->bpart = RLCYLSZ - (rlp->sn * RLSECSZ)))
  297.         rlp->bpart = rlp->bleft;
  298.     while((rp->rlcs&CRDY) == 0);
  299.     rp->rlda = (rlp->chn << 6) | rlp->sn;
  300.     rp->rlba = rlp->addr.w[1];
  301.     rp->rlmp = -(rlp->bpart >> 1);
  302.     rp->rlcs = rlp->com | rlp->addr.w[0] << 4;
  303. }
  304.  
  305. rlread(dev)
  306. {
  307.     physio(rlstrategy, &rrlbuf, dev, B_READ);
  308. }
  309.  
  310. rlwrite(dev)
  311. {
  312.     physio(rlstrategy, &rrlbuf, dev, B_WRITE);
  313. }
  314.