home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / standalone / rl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-29  |  5.0 KB  |  182 lines

  1. /*
  2.  *  RL disk driver
  3.  *
  4.  *    RL driver modified for the standalone shell.
  5.  *    Armando P. Stettner  Digital Equipment Corp.  July, 1980
  6.  */
  7.  
  8. #include    <sys/param.h>
  9. #include    <sys/inode.h>
  10. #include    "saio.h"
  11.  
  12. #define    BLKRL1    10240        /* Number of UNIX blocks for an RL01 drive */
  13. #define BLKRL2    20480        /* Number of UNIX blocks for an RL02 drive */
  14. #define RLCYLSZ 10240        /* bytes per cylinder */
  15. #define RLSECSZ 256        /* bytes per sector */
  16.  
  17. #define RESET 013
  18. #define    RL02TYP    0200    /* drive type bit */
  19. #define STAT 03
  20. #define GETSTAT 04
  21. #define WCOM 012
  22. #define RCOM 014
  23. #define SEEK 06
  24. #define SEEKHI 5
  25. #define SEEKLO 1
  26. #define RDHDR 010
  27. #define IENABLE 0100
  28. #define CRDY 0200
  29. #define OPI 02000
  30. #define CRCERR 04000
  31. #define TIMOUT 010000
  32. #define NXM 020000
  33. #define DE  040000
  34.  
  35. struct device
  36. {
  37.     int rlcs ,
  38.     rlba ,
  39.     rlda ,
  40.     rlmp ;
  41. } ;
  42.  
  43. #define RLADDR    ((struct device *)0174400)
  44. #define RL_CNT 1
  45.  
  46. struct 
  47. {
  48.     int    cn[4] ;        /* location of heads for each drive */
  49.     int    type[4] ;    /* parameter dependent upon drive type  (RL01/02) */
  50.     int    com ;        /* read or write command word */
  51.     int    chn ;        /* cylinder and head number */
  52.     unsigned int    bleft ;    /* bytes left to be transferred */
  53.     unsigned int    bpart ;    /* number of bytes transferred */
  54.     int    sn ;        /* sector number */
  55.     union {
  56.         int    w[2] ;
  57.         long    l ;
  58.     } addr ;            /* address of memory for transfer */
  59.  
  60. }    rl = {-1,-1,-1,-1, -1,-1,-1,-1} ;    /* initialize cn[] and type[] */
  61.  
  62. rlstrategy(io, func)
  63. register struct iob *io ;
  64. int func ;
  65. {
  66.     int nblocks ;    /* number of UNIX blocks for the drive in question */
  67.     int drive ;
  68.     int dif ;
  69.     int head ;
  70.     int ctr ;
  71.  
  72.  
  73.     /*
  74.      * We must determine what type of drive we are talking to in order 
  75.      * to determine how many blocks are on the device.  The rl.type[]
  76.      * array has been initialized with -1's so that we may test first
  77.      * contact with a particular drive and do this determination only once.
  78.      * Sorry tjk for this hack.
  79.      *
  80.      * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80
  81.      *
  82.      * For some unknown reason the RL02 (seems to be
  83.      * only drive 1) does not return a valid drive status
  84.      * the first time that a GET STATUS request is issued
  85.      * for the drive, in fact it can take up to three or more
  86.      * GET STATUS requests to obtain the correct status.
  87.      * In order to overcome this "HACK" the driver has been
  88.      * modified to issue a GET STATUS request, validate the
  89.      * drive status returned, and then use it to determine the
  90.      * drive type. If a valid status is not returned after eight
  91.      * attempts, then an error message is printed.
  92.      */
  93.     drive = io->i_unit ;
  94.     if (rl.type[drive] < 0)
  95.         {
  96.         ctr = 0;
  97.         do {
  98.         RLADDR->rlda = RESET ;    /* load this register; what a dumb controller */
  99.         RLADDR->rlcs = (drive << 8) | GETSTAT ;    /* set up csr */
  100.         while ((RLADDR->rlcs & CRDY) == 0)    /* wait for it */
  101.             ;
  102.         } while (((RLADDR->rlmp & 0177477) != 035) && (++ctr < 8)) ;
  103.         if (ctr >= 8)
  104.             printf("\nCan't get status of RL unit %d\n",drive) ;
  105.         if (RLADDR->rlmp & RL02TYP) 
  106.             rl.type[drive] = BLKRL2 ;    /* drive is RL02 */
  107.         else
  108.             rl.type[drive] = BLKRL1 ;    /* drive RL01 */
  109.         /*
  110.          * When the device is first touched, find out where the heads are.
  111.          */
  112.         /* find where the heads are */
  113.         RLADDR->rlcs = (drive << 8) | RDHDR;
  114.         while ((RLADDR->rlcs&CRDY) == 0)
  115.             ;
  116.         /*rl.cn[drive] = (RLADDR->rlmp&0177700) >> 6;*/
  117.         rl.cn[drive] = ((RLADDR->rlmp) >> 6) & 01777; /* fix sign bug */
  118.         }
  119.     nblocks = rl.type[drive] ;    /* how many blocks on this drive */
  120.     if(io->i_bn >= nblocks)
  121.         return -1 ;
  122.     rl.chn = io->i_bn/20;
  123.     rl.sn = (io->i_bn%20) << 1;
  124.     rl.bleft = io->i_cc;
  125.     rl.addr.w[0] = segflag & 3;
  126.     rl.addr.w[1] = (int)io->i_ma ;
  127.     rl.com = (drive << 8) ;
  128.     if (func == READ)
  129.         rl.com |= RCOM;
  130.     else
  131.         rl.com |= WCOM;
  132. reading:
  133.     /*
  134.      * One has to seek an RL head, relativily.
  135.      */
  136.     dif =(rl.cn[drive] >> 1) - (rl.chn >>1);
  137.     head = (rl.chn & 1) << 4;
  138.     if (dif < 0)
  139.         RLADDR->rlda = (-dif <<7) | SEEKHI | head;
  140.     else
  141.         RLADDR->rlda = (dif << 7) | SEEKLO | head;
  142.     RLADDR->rlcs = (drive << 8) | SEEK;
  143.     rl.cn[drive] = rl.chn;     /* keep current, our notion of where the heads are */
  144.     if (rl.bleft < (rl.bpart = RLCYLSZ - (rl.sn * RLSECSZ)))
  145.         rl.bpart = rl.bleft;
  146.     while ((RLADDR->rlcs&CRDY) == 0) ;
  147.     RLADDR->rlda = (rl.chn << 6) | rl.sn;
  148.     RLADDR->rlba = rl.addr.w[1];
  149.     RLADDR->rlmp = -(rl.bpart >> 1);
  150.     RLADDR->rlcs = rl.com | rl.addr.w[0] << 4;
  151.     while ((RLADDR->rlcs & CRDY) == 0)    /* wait for completion */
  152.         ;
  153.     if (RLADDR->rlcs < 0)    /* check error bit */
  154.         {
  155.         if (RLADDR->rlcs & 040000)    /* Drive error */
  156.             {
  157.             /*
  158.              * get status from drive
  159.              */
  160.             RLADDR->rlda = STAT;
  161.             RLADDR->rlcs = (drive << 8) | GETSTAT;
  162.             while ((RLADDR->rlcs & CRDY) == 0)    /* wait for controller */
  163.                 ;
  164.             }
  165.         printf("Rl disk error: cyl=%d, head=%d, sector=%d, rlcs=%o, rlmp=%o\n",
  166.             rl.chn>>01, rl.chn&01, rl.sn, RLADDR->rlcs, RLADDR->rlmp) ;
  167.         return -1 ;
  168.         }
  169.     /*
  170.      * Determine if there is more to read to satisfy this request.
  171.      * This is to compensate for the lacl of spiraling reads.
  172.      */
  173.     if ((rl.bleft -= rl.bpart) > 0)
  174.         {
  175.         rl.addr.l += rl.bpart ;
  176.         rl.sn = 0 ;
  177.         rl.chn++ ;
  178.         goto reading ;    /* read some more */
  179.         }
  180.     return io->i_cc ;
  181. }
  182.