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 / r5.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-02-26  |  7.0 KB  |  369 lines

  1. /*
  2.  * This driver handles the RX50 controller on the pro3xx. It should be
  3.  * noted that track 0 is never used, just to be consistent with good ole
  4.  * dec software. The reading of foreign diskettes has not been thoroughly
  5.  * tested, but seems to work. Anyone keen enough could implement an ms-dos
  6.  * or cp/m file system handling utility. Its handy to modify dump/restor so
  7.  * that a version knows about RX50's at 790 sectors each.
  8.  */
  9.  
  10. #include "r5.h"
  11. #if NR5 > 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. #include <sys/r5reg.h>
  23. #include <sys/r5io.h>
  24. #include <sys/ivecpos.h>
  25.  
  26.  
  27. #define    OPEN    1
  28. #define    VOLCHNGE 2
  29. #define DISMNT    4
  30.  
  31. /* These are the diskette type parameters handled by the rx50 controller.
  32.  * See the Professional 300 Series Technical Manual for more details.
  33.  */
  34. struct r5parm {
  35.     int    trks;
  36.     int    sectrfm;
  37.     int    dens;
  38.     int    sectrk;
  39.     int    bytesec;
  40. } r5parm[4] = {
  41.     0120,    0152,    0132,    10,    512,
  42.     050,    0152,    0131,    10,    512,
  43.     050,    0151,    0131,    9,    512,
  44.     050,    0120,    0131,    16,    256,
  45. };
  46.  
  47. extern struct r5device *R5ADDR;
  48.  
  49. struct    buf    r5tab;
  50. struct    buf    rr5buf;
  51.  
  52. struct r5_softc {
  53.     char    sc_stat;
  54.     char    sc_type;
  55.     char    sc_dstat[NR5];
  56. } r5_softc;
  57.  
  58. void r5root()
  59. {
  60.     r5attach(R5ADDR, 0);
  61. }
  62.  
  63. r5attach(addr, unit)
  64. struct r5device *addr;
  65. {
  66.     if (unit == 0) {
  67.         R5ADDR = addr;
  68.         return(1);
  69.     }
  70.     return(0);
  71. }
  72.  
  73. r5open(dev)
  74. dev_t dev;
  75. {
  76.     register int i;
  77.     int s;
  78.  
  79.     if (minor(dev) >= NR5 || (R5ADDR == (struct r5device *) NULL)) {
  80.         u.u_error = ENXIO;
  81.         return;
  82.     }
  83.     if ((r5_softc.sc_stat & OPEN) == 0) {
  84.         (void) _spl4();
  85.         r5_softc.sc_stat |= OPEN;
  86.         r5rstat(0);
  87.         ienable(IVEC(R5ADDR, BPOS));
  88.         for(i = 0; i < NR5; i++) {
  89.             if (i == minor(dev))
  90.                 r5_softc.sc_dstat[i] |= OPEN;
  91.             else
  92.                 r5_softc.sc_dstat[i] = 0;
  93.         }
  94.         (void) _spl0();
  95.     } else {
  96.         r5_softc.sc_dstat[minor(dev)] |= OPEN;
  97.     }
  98. }
  99.  
  100. r5close(dev)
  101. dev_t dev;
  102. {
  103.     r5_softc.sc_dstat[minor(dev)] = 0;
  104. }
  105. r5strategy(bp)
  106. register struct buf *bp;
  107. {
  108.     register struct buf *dp;
  109.     long sz, bn;
  110.     int s;
  111.  
  112.     sz = bp->b_bcount;
  113.     sz = (sz+511)>>9;
  114.     if (bp->b_blkno < 0 || (bn = dkblock(bp))+sz > R5_SIZE) {
  115.         bp->b_error = EINVAL;
  116.         bp->b_flags |= B_ERROR;
  117.         iodone(bp);
  118.         return;
  119.     }
  120.     bp->b_cylin = bn/10;
  121.     dp = &r5tab;
  122.     (void) _spl4();
  123.     disksort(dp, bp);
  124.     if (dp->b_active == NULL)
  125.         r5start();
  126.     (void) _spl0();
  127. }
  128.  
  129. r5start()
  130. {
  131.     register struct buf *bp;
  132.     register int unit;
  133.  
  134.     if ((bp = r5tab.b_actf) == NULL)
  135.         return;
  136.     bp->b_resid = bp->b_bcount;
  137.     r5strt((dkblock(bp)*(512/r5parm[r5_softc.sc_type].bytesec)), bp);
  138. #ifdef R5_DKN
  139.     dk_busy |= 1<<R5_DKN;
  140.     dk_numb[R5_DKN] += 1;
  141. #endif R5_DKN
  142. }
  143.  
  144. r5strt(bn, bp)
  145. daddr_t bn;
  146. register struct buf *bp;
  147. {
  148.     register char *ptr;
  149.     register u_short cnt;
  150.     u_short tn, sn;
  151.     int unit;
  152.     long taddr;
  153.     u_short xfer;
  154.  
  155.     if (r5_softc.sc_stat & VOLCHNGE) {
  156.         r5rstat(1);
  157.         r5_softc.sc_stat &= ~VOLCHNGE;
  158.     }
  159.     r5tab.b_active++;
  160.     unit = minor(bp->b_dev);
  161.     tn = bn/r5parm[r5_softc.sc_type].sectrk;
  162.     sn = bn % r5parm[r5_softc.sc_type].sectrk;
  163.     if (r5_softc.sc_type == 0)  {
  164.         sn = ((sn<<1)%10 + (sn<<1)/10 + (tn<<1))%10;
  165.         tn = (tn+1) % 80;
  166.     }
  167.     R5ADDR->cs1 = tn;
  168.     R5ADDR->cs2 = sn+1;
  169.     if (bp->b_flags & B_READ) {
  170.         R5ADDR->cs0 = R5_READCOM|((unit&03)<<1);
  171.         ienable(IVEC(R5ADDR, APOS));
  172.         R5ADDR->sc = 0;
  173.     } else {
  174.         segm save;
  175.         if (r5_softc.sc_type)
  176.             r5param(r5_softc.sc_type = 0);
  177.         xfer = (bp->b_resid < 01000)?bp->b_resid:01000;
  178.         R5ADDR->cs0 = R5_WRITECOM|((unit&03)<<1);
  179.         R5ADDR->ca = 0;
  180.         taddr = (((((long)bp->b_xmem)<<16)&0x3f0000l)|
  181.             (((long)bp->b_un.b_addr)&0xffff))+
  182.             (bp->b_bcount-bp->b_resid);
  183.         ptr = (char *)((taddr & 077)+SEG5);
  184.         saveseg5(save);
  185.         mapseg5(((caddr_t)(taddr>>6)), 04406);
  186.         for (cnt = 0; cnt < xfer; cnt++) {
  187.             R5ADDR->dbi = *ptr++;
  188.         }
  189.         restorseg5(save);
  190.         ienable(IVEC(R5ADDR, APOS));
  191.         R5ADDR->sc = 0;
  192.     }
  193. }
  194.  
  195. r5aint()
  196. {
  197.     register struct buf *bp;
  198.     register char *ptr;
  199.     register u_short cnt;
  200.     int err;
  201.     long taddr;
  202.     daddr_t bn;
  203.     u_short xfer;
  204.  
  205.     if (r5tab.b_active == NULL) {
  206.         idisable(IVEC(R5ADDR, APOS));
  207.         return;
  208.     }
  209.     r5tab.b_active = NULL;
  210. #ifdef R5_DKN
  211.     dk_busy &= ~(1<<R5_DKN);
  212. #endif R5_DKN
  213.     bp = r5tab.b_actf;
  214.     while ((R5ADDR->cs0 & R5_BUSY) == 0)
  215.         ;
  216.     if (R5ADDR->cs0 & R5_ERROR) {
  217.         if (++r5tab.b_errcnt <= 10) {
  218.             r5init();
  219.             r5rstat(0);
  220.             bn = dkblock(bp)*(512/r5parm[r5_softc.sc_type].bytesec)+
  221.                 ((bp->b_bcount-bp->b_resid)/
  222.                 r5parm[r5_softc.sc_type].bytesec);
  223.             idisable(IVEC(R5ADDR, APOS));
  224.             r5strt(bn, bp);
  225.             return;
  226.         }
  227. #ifdef UCB_DEVERR
  228.         harderr(bp, "r5");
  229.         printf("cs0=%o cs1=%o\n",R5ADDR->cs0,R5ADDR->cs1);
  230. #else
  231.         deverror(bp, R5ADDR->cs0, R5ADDR->cs1);
  232. #endif
  233.         r5init();
  234.         r5rstat(0);
  235.         bp->b_flags |= B_ERROR;
  236.         r5tab.b_errcnt = 0;
  237.         r5tab.b_actf = bp->av_forw;
  238.         bp->b_resid = 0;
  239.         iodone(bp);
  240.         idisable(IVEC(R5ADDR, APOS));
  241.         r5start();
  242.         return;
  243.     }
  244.     xfer = (bp->b_resid < r5parm[r5_softc.sc_type].bytesec)?bp->b_resid:
  245.         r5parm[r5_softc.sc_type].bytesec;
  246.     if (bp->b_flags & B_READ) {
  247.         segm save;
  248.         R5ADDR->ca = 0;
  249.         taddr = (((((long)bp->b_xmem)<<16)&0x3f0000l)|
  250.             (((long)bp->b_un.b_addr)&0xffff))+
  251.             (bp->b_bcount-bp->b_resid);
  252.         ptr = (char *)((taddr & 077)+SEG5);
  253.         saveseg5(save);
  254.         mapseg5(((caddr_t)(taddr>>6)), 04406);
  255.         for (cnt = 0; cnt < xfer; cnt++) {
  256.             *ptr++ = R5ADDR->dbo;
  257.         }
  258.         restorseg5(save);
  259.     }
  260.     r5tab.b_errcnt = 0;
  261.     bp->b_resid -= xfer;
  262.     if (bp->b_resid == 0) {
  263.         r5tab.b_actf = bp->av_forw;
  264.         iodone(bp);
  265.         idisable(IVEC(R5ADDR, APOS));
  266.         r5start();
  267.         return;
  268.     }
  269.     bn = dkblock(bp)*(512/r5parm[r5_softc.sc_type].bytesec)+
  270.          ((bp->b_bcount-bp->b_resid)/r5parm[r5_softc.sc_type].bytesec);
  271.     idisable(IVEC(R5ADDR, APOS));
  272.     r5strt(bn, bp);
  273. }
  274.  
  275. r5init()
  276. {
  277.     R5ADDR->cs0 = R5_INIT;
  278.     R5ADDR->sc = 0;
  279.     while ((R5ADDR->cs0 & R5_BUSY) == 0)
  280.         ;
  281. }
  282.  
  283. r5read(dev)
  284. {
  285.  
  286.     physio(r5strategy, &rr5buf, dev, B_READ);
  287. }
  288.  
  289. r5write(dev)
  290. {
  291.  
  292.     physio(r5strategy, &rr5buf, dev, B_WRITE);
  293. }
  294.  
  295. r5ioctl(dev, cmd, addr, flag)
  296. dev_t dev;
  297. int cmd;
  298. caddr_t addr;
  299. int flag;
  300. {
  301.     int parmvl;
  302.  
  303.     switch(cmd) {
  304.     case R5IOCSETP:
  305.         if (copyin(addr, (caddr_t)&parmvl, sizeof(parmvl)) ||
  306.             (parmvl < 0 || parmvl > 3)) {
  307.             u.u_error = EFAULT;
  308.             return;
  309.         }
  310.         r5param(r5_softc.sc_type = parmvl);
  311.         break;
  312.     case R5IOCGETP:
  313.         parmvl = r5_softc.sc_type;
  314.         if (copyout((caddr_t)&parmvl, addr, sizeof(parmvl))) {
  315.             u.u_error = EFAULT;
  316.             return;
  317.         }
  318.         break;
  319.     };
  320. }
  321.  
  322. r5rstat(flag)
  323. int flag;
  324. {
  325.     register int tmp, i;
  326.  
  327.     R5ADDR->cs0 = R5_STATUS;
  328.     R5ADDR->sc = 0;
  329.     while ((R5ADDR->cs0 & R5_BUSY) == 0)
  330.         ;
  331.     tmp = R5ADDR->cs3 >> 4;
  332.     for (i = 0; i < NR5; i++) {
  333.         if (tmp & 01) {
  334.             if (r5_softc.sc_dstat[i] & OPEN)
  335.                if (flag && !(r5_softc.sc_dstat[i] & DISMNT)) {
  336.                 printf("Umount floppy %d before removing\n",i);
  337.                 r5_softc.sc_dstat[i] |= DISMNT;
  338.                } else {
  339.                 r5_softc.sc_dstat[i] &= ~DISMNT;
  340.                }
  341.             if (r5_softc.sc_type)
  342.                 r5param(r5_softc.sc_type = 0);
  343.         }
  344.         tmp >>= 1;
  345.     }
  346. }
  347.  
  348. r5bint()
  349. {
  350.     if (r5tab.b_active == NULL)
  351.         r5rstat(1);
  352.     else
  353.         r5_softc.sc_stat |= VOLCHNGE;
  354. }
  355.  
  356. r5param(num)
  357. int num;
  358. {
  359.     R5ADDR->cs1 = r5parm[num].trks;
  360.     R5ADDR->cs2 = r5parm[num].sectrfm;
  361.     R5ADDR->cs3 = r5parm[num].dens;
  362.     R5ADDR->cs5 = R5_SPARM;
  363.     R5ADDR->cs0 = R5_EXTCOM;
  364.     R5ADDR->sc = 0;
  365.     while ((R5ADDR->cs0 & R5_BUSY) == 0)
  366.         ;
  367. }
  368. #endif
  369.