home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / 2.9-derivatives / 2.9-pro350 / sys-dev / rd.c < prev   
Encoding:
C/C++ Source or Header  |  1985-02-26  |  8.2 KB  |  399 lines

  1. /*
  2.  * This driver runs the RD50/51 controller on the pro3xx. It
  3.  * expects bad sector forwarding
  4.  * tables to be in a BAD144 style. Bad sectors are marked by writing a nonzero
  5.  * backup revision field in the sector header. The standalone program, "rdfmt"
  6.  * should be run to format and bad scan the disk before this driver is used
  7.  * if BADSECT is enabled.
  8.  */
  9.  
  10. #include "rd.h"
  11. #if NRD > 0
  12. #include <sys/param.h>
  13. #include <sys/systm.h>
  14. #include <sys/buf.h>
  15. #include <sys/dir.h>
  16. #include <sys/conf.h>
  17. #include <sys/user.h>
  18. #include <sys/seg.h>
  19. #ifndef INTRLVE
  20. #include <sys/inline.h>
  21. #endif INTRLVE
  22. #ifdef BADSECT
  23. #include <sys/dkbad.h>
  24. #endif BADSECT
  25. #include <sys/ivecpos.h>
  26. #include <sys/rdreg.h>
  27.  
  28.  
  29. #define    OPEN    1
  30. #define GOTBAD 2
  31.  
  32. extern struct size rd_sizes[];
  33. extern struct rddevice *RDADDR;
  34.  
  35. struct    buf    rdtab;
  36. struct    buf    rrdbuf;
  37. #ifdef BADSECT
  38. struct    dkbad    rdbad;
  39. #endif BADSECT
  40. union    wordval    rdval;
  41. struct rdst rdst[] = {
  42.     16,    4,    16*4,    305,
  43.     16,    4,    16*4,    152,
  44.     0,    0,    0,    0,
  45. };
  46.  
  47. struct rd_softc {
  48.     char    sc_stat;
  49.     char    sc_type;
  50. } rd_softc;
  51.  
  52. void rdroot()
  53. {
  54.     rdattach(RDADDR, 0);
  55. }
  56.  
  57. rdattach(addr, unit)
  58. struct rddevice *addr;
  59. {
  60.     if (unit == 0) {
  61.         RDADDR = addr;
  62.         return(1);
  63.     } 
  64.     return(0);
  65. }
  66.  
  67. rdopen(dev) {
  68.     register int cnt, *ptr, tmp;
  69.  
  70.     if (rd_softc.sc_stat & OPEN)
  71.         return;
  72.     rd_softc.sc_stat |= OPEN;
  73.     rdinit();
  74.     if (!(rd_softc.sc_stat & GOTBAD)) {
  75.         while (1) {
  76.             RDADDR->sec = 0;
  77.             RDADDR->trk = rdst[rd_softc.sc_type].ntrak-1;
  78.             RDADDR->cyl = rdst[rd_softc.sc_type].ncyl;
  79.             RDADDR->csr = RD_READCOM;
  80.             while (RDADDR->st & RD_BUSY) ;
  81.             if (RDADDR->csr & RD_ERROR) {
  82.                 if (RDADDR->err & RD_IDNF)
  83.                     rd_softc.sc_type++;
  84.                 rdinit();
  85.             } else {
  86. #ifdef BADSECT
  87.                 ptr = &rdbad;
  88. #endif BADSECT
  89.                 for (cnt = 0; cnt < 256; cnt++) {
  90.                     while ((RDADDR->st & RD_DRQ) == 0) ;
  91. #ifdef BADSECT
  92.                     if (cnt < ((sizeof rdbad)/2))
  93.                         *ptr++ = RDADDR->db;
  94.                     else
  95. #endif BADSECT
  96.                         tmp = RDADDR->db;
  97.                 }
  98.                 break;
  99.             }
  100.         }
  101.         rd_softc.sc_stat |= GOTBAD;
  102.     }
  103. }
  104.  
  105. rdstrategy(bp)
  106. register struct buf *bp;
  107. {
  108.     register struct buf *dp;
  109.     register struct rdst *st;
  110.     register int unit;
  111.     int s;
  112.     long bn;
  113.     long sz;
  114.  
  115.     unit = minor(bp->b_dev)&07;
  116.     sz = bp->b_bcount;
  117.     sz = (sz+511)>>9;
  118.     st = &rdst[rd_softc.sc_type];
  119.     if (unit >= (NRD<<3) || (RDADDR == (struct rddevice *) NULL)) {
  120.         bp->b_error = ENXIO;
  121.         goto errexit;
  122.     }
  123.     if (bp->b_blkno < 0 || ((bn = dkblock(bp))+sz > rd_sizes[unit].nblocks
  124.        && rd_sizes[unit].nblocks >= 0)) {
  125.         bp->b_error = EINVAL;
  126. errexit:
  127.         bp->b_flags |= B_ERROR;
  128.         iodone(bp);
  129.         return;
  130.     }
  131.     bp->b_cylin = bn/st->nspc+rd_sizes[unit].cyloff;
  132.     dp = &rdtab;
  133.     (void) _spl4();
  134.     disksort(dp, bp);
  135.     if (dp->b_active == NULL)
  136.         rdstart();
  137.     (void) _spl0();
  138. }
  139.  
  140. rdstart()
  141. {
  142.     register struct buf *bp;
  143.     register int unit;
  144.  
  145.     if ((bp = rdtab.b_actf) == NULL)
  146.         return;
  147.     bp->b_resid = bp->b_bcount;
  148.     rdstrt(dkblock(bp), bp);
  149. #ifdef RD_DKN
  150.     dk_busy |= 1<<RD_DKN;
  151.     dk_numb[RD_DKN] += 1;
  152. #endif RD_DKN
  153. }
  154.  
  155. rdstrt(bn, bp)
  156. daddr_t bn;
  157. register struct buf *bp;
  158. {
  159.     register u_short cnt;
  160.     register char *ptr;
  161.     register struct rdst *st;
  162.     long taddr;
  163.     int sn;
  164.     u_short xfer;
  165.  
  166.     rdtab.b_active++;
  167.     st = &rdst[rd_softc.sc_type];
  168.     while (RDADDR->st & RD_BUSY)
  169.         ;
  170.     RDADDR->cyl = bn/(st->nspc)+rd_sizes[minor(bp->b_dev)&07].cyloff;
  171.     sn = bn % st->nspc;
  172.     RDADDR->trk = sn / st->nsect;
  173.     RDADDR->sec = sn % st->nsect;
  174.     if (bp->b_flags & B_READ) {
  175.         ienable(IVEC(RDADDR, APOS));
  176.         ienable(IVEC(RDADDR, BPOS));
  177.         RDADDR->csr = RD_READCOM;
  178.     } else {
  179.         /* Kernel seg. 5 is used to map the i/o buffer into kernel 
  180.          * virtual so that the copy loop can be performed.
  181.          */
  182.         segm save;
  183.         xfer = (bp->b_resid < 01000)?bp->b_resid:01000;
  184.         taddr = (((((long)bp->b_xmem)<<16)&0x3f0000l)|
  185.             (((long)bp->b_un.b_addr)&0xffff))+
  186.             (bp->b_bcount-bp->b_resid);
  187.         ptr = (char *)((taddr & 077)+SEG5);
  188.         ienable(IVEC(RDADDR, APOS));
  189.         RDADDR->csr = RD_WRITECOM;
  190.         saveseg5(save);
  191.         mapseg5(((caddr_t)(taddr>>6)), 04406);
  192.         for (cnt = 0; cnt < 0400; cnt++) {
  193.             while ((RDADDR->st & RD_DRQ) == 0)
  194.                 ;
  195.             if (cnt < (xfer/02)) {
  196.                 rdval.byte[0] = *ptr++;
  197.                 rdval.byte[1] = *ptr++;
  198.             }
  199.             RDADDR->db = rdval.word;
  200.         }
  201.         restorseg5(save);
  202.     }
  203. }
  204.  
  205. /* This interrupt service routine is accessed via. both the A and B vectors */
  206. rdintr()
  207. {
  208.     register struct buf *bp;
  209.     register u_short cnt;
  210.     register char *ptr;
  211.     long taddr;
  212.     daddr_t bn;
  213.     u_short xfer;
  214.  
  215.     if (rdtab.b_active == NULL) {
  216.         idisable(IVEC(RDADDR, APOS));
  217.         idisable(IVEC(RDADDR, BPOS));
  218.         return;
  219.     }
  220. #ifdef RD_DKN
  221.     dk_busy &= ~(1<<RD_DKN);
  222. #endif RD_DKN
  223.     bp = rdtab.b_actf;
  224.     rdtab.b_active = NULL;
  225.     while (RDADDR->st & RD_BUSY)
  226.         ;
  227.     if ((RDADDR->csr & (RD_WFAULT|RD_ERROR))
  228. #ifdef BADSECT
  229.         || (RDADDR->sec & 0177400)
  230. #endif
  231.         ) {
  232. #ifdef BADSECT
  233.         if ((RDADDR->err & (RD_DMNF|RD_IDNF|RD_CRC)) || (RDADDR->sec & 0177400)) {
  234.             idisable(IVEC(RDADDR, APOS));
  235.             idisable(IVEC(RDADDR, BPOS));
  236.             if (baderr(bp)) {
  237.                 return;
  238.             }
  239.         }
  240. #endif
  241.         if (++rdtab.b_errcnt <= 10) {
  242.             rdinit();
  243.             bn = dkblock(bp)+((bp->b_bcount-bp->b_resid)>>9);
  244.             idisable(IVEC(RDADDR, APOS));
  245.             idisable(IVEC(RDADDR, BPOS));
  246.             rdstrt(bn, bp);
  247.             return;
  248.         }
  249. #ifdef UCB_DEVERR
  250.         harderr(bp, "rd");
  251.         printf("cs=%b er=%b\n",RDADDR->csr,RDCS_BITS,RDADDR->err,RDER_BITS);
  252. #else
  253.         deverror(bp, RDADDR->csr, RDADDR->err);
  254. #endif
  255.         rdinit();
  256.         bp->b_flags |= B_ERROR;
  257.         rdtab.b_errcnt = 0;
  258.         rdtab.b_actf = bp->av_forw;
  259.         bp->b_resid = 0;
  260.         iodone(bp);
  261.         idisable(IVEC(RDADDR, APOS));
  262.         idisable(IVEC(RDADDR, BPOS));
  263.         rdstart();
  264.         return;
  265.     }
  266.     xfer = (bp->b_resid < 01000)?bp->b_resid:01000;
  267.     if (bp->b_flags & B_READ) {
  268.         segm save;
  269.         taddr = (((((long)bp->b_xmem)<<16)&0x3f0000l)|
  270.             (((long)bp->b_un.b_addr)&0xffff))+
  271.             (bp->b_bcount-bp->b_resid);
  272.         ptr = (char *)((taddr & 077)+SEG5);
  273.         saveseg5(save);
  274.         mapseg5(((caddr_t)(taddr>>6)), 04406);
  275.         for (cnt = 0; cnt < 0400; cnt++) {
  276.             while ((RDADDR->st & RD_DRQ) == 0)
  277.                 ;
  278.             rdval.word = RDADDR->db;
  279.             if (cnt < (xfer/02)) {
  280.                 *ptr++ = rdval.byte[0];
  281.                 *ptr++ = rdval.byte[1];
  282.             }
  283.         }
  284.         restorseg5(save);
  285.     }
  286.     rdtab.b_errcnt = 0;
  287.     bp->b_resid -= xfer;
  288.     if (bp->b_resid == 0) {
  289.         rdtab.b_actf = bp->av_forw;
  290.         iodone(bp);
  291.         idisable(IVEC(RDADDR, APOS));
  292.         idisable(IVEC(RDADDR, BPOS));
  293.         rdstart();
  294.         return;
  295.     }
  296.     bn = dkblock(bp)+((bp->b_bcount-bp->b_resid)>>9);
  297.     idisable(IVEC(RDADDR, APOS));
  298.     idisable(IVEC(RDADDR, BPOS));
  299.     rdstrt(bn, bp);
  300. }
  301.  
  302. rdinit()
  303. {
  304.     RDADDR->st = RD_INIT;
  305.     while (RDADDR->st & RD_BUSY)
  306.         ;
  307.     RDADDR->csr = RD_RESTORE;
  308.     while ((RDADDR->st & RD_BUSY) || (!(RDADDR->st & RD_OPENDED)))
  309.         ;
  310. }
  311.  
  312. rdread(dev)
  313. {
  314.  
  315.     physio(rdstrategy, &rrdbuf, dev, B_READ);
  316. }
  317.  
  318. rdwrite(dev)
  319. {
  320.  
  321.     physio(rdstrategy, &rrdbuf, dev, B_WRITE);
  322. }
  323. #ifdef BADSECT
  324. baderr(bp)
  325. struct buf *bp;
  326. {
  327.     register int sn,cn;
  328.     register struct rdst *st;
  329.     int tn;
  330.     daddr_t bn, isbad();
  331.  
  332.     st = &rdst[rd_softc.sc_type];
  333.     bn = dkblock(bp) + ((bp->b_bcount-bp->b_resid)>>9)+
  334.         rd_sizes[(minor(bp->b_dev)&07)].cyloff;
  335.     cn = bn/(st->nspc);
  336.     sn = bn%(st->nspc);
  337.     tn = sn/(st->nsect);
  338.     sn %= (st->nsect);
  339.     if ((bn = isbad(&rdbad, cn, tn, sn)) < 0)
  340.         return(0);
  341.     cn = st->ncyl-rd_sizes[(minor(bp->b_dev)&07)].cyloff;
  342.     bn = cn*st->nspc+st->nsect*(st->ntrak-1)-1-bn;
  343.     rdstrt(bn, bp);
  344.     return(1);
  345. }
  346. #endif
  347. #ifdef RD_DUMP
  348. /* This is the RD50/51 dump routine. It uses mapin/mapout to get
  349.  * at all of memory.
  350.  */
  351.  
  352. rddump(dev)
  353.     dev_t dev;
  354. {
  355.     register int *ptr, cnt;
  356.     register struct rdst *st = &rdst[rd_softc.sc_type];
  357.     daddr_t bn, dumpsize;
  358.     long paddr;
  359.     int sn, unit;
  360.     segm save;
  361.  
  362.     unit = minor(dev) >> 3;
  363.     if ((bdevsw[major(dev)].d_strategy != rdstrategy)
  364.         || unit >= NRD)
  365.         return(EINVAL);
  366.     dumpsize = rd_sizes[minor(dev)&07].nblocks;
  367.     if ((dumplo < 0) || (dumplo >= dumpsize))
  368.         return(EINVAL);
  369.     dumpsize -= dumplo;
  370.     /* Initialize the controller/drive */
  371.     rdinit();
  372.     /* Loop until dump complete */
  373.     for (paddr = 0L; dumpsize > 0; dumpsize--) {
  374.         bn = dumplo + (paddr>>PGSHIFT);
  375.         RDADDR->cyl = (bn/st->nspc) + rd_sizes[minor(dev)&07].cyloff;
  376.         sn = bn%st->nspc;
  377.         RDADDR->trk = sn/st->nsect;
  378.         RDADDR->sec = sn%st->nsect;
  379.         RDADDR->csr = RD_WRITECOM;
  380.         ptr = (int *)((paddr & 077)+SEG5);
  381.         saveseg5(save);
  382.         mapseg5(((caddr_t)(paddr>>6)), 04406);
  383.         for (cnt = 0; cnt < 256; cnt++) {
  384.             while ((RDADDR->st & RD_DRQ) == 0)
  385.                 ;
  386.             RDADDR->db = *ptr++;
  387.         }
  388.         restorseg5(save);
  389.         while ((RDADDR->st & RD_BUSY) || (!(RDADDR->st & RD_OPENDED)))
  390.             ;
  391.         if ((RDADDR->csr & (RD_WFAULT|RD_ERROR))
  392.             return(EIO);
  393.         paddr += (1<<PGSHIFT);
  394.     }
  395.     return(0);
  396. }
  397. #endif RD_DUMP
  398. #endif
  399.