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

  1. /*
  2.  *    DH-11 driver
  3.  *    This driver calls on the DHDM driver.
  4.  *    If the DH has no DM11-BB, then the latter will
  5.  *    be fake. To insure loading of the correct DM code,
  6.  *    lib2 should have dhdm.o, dh.o and dhfdm.o in that order.
  7.  */
  8.  
  9. #include "../h/param.h"
  10. #include "../h/conf.h"
  11. #include "../h/dir.h"
  12. #include "../h/user.h"
  13. #include "../h/tty.h"
  14.  
  15. #define    q3    tp->t_outq
  16. #define    DHADDR    ((struct device *)0160020)
  17. #define    NDH11    16    /* number of lines */
  18.  
  19. struct    tty dh11[NDH11];
  20. char    dhcc[NDH11];
  21. int    dhchars[(NDH11+15)/16];
  22. int    ndh11    = NDH11;
  23. int    dhstart();
  24. int    ttrstrt();
  25.  
  26. /*
  27.  * Hardware control bits
  28.  */
  29. #define    BITS6    01
  30. #define    BITS7    02
  31. #define    BITS8    03
  32. #define    TWOSB    04
  33. #define    PENABLE    020
  34. /* DEC manuals incorrectly say this bit causes generation of even parity. */
  35. #define    OPAR    040
  36. #define    HDUPLX    040000
  37.  
  38. #define    IENAB    030100
  39. #define    PERROR    010000
  40. #define    FRERROR    020000
  41. #define    OVERRUN    040000
  42. #define    XINT    0100000
  43. #define    SSPEED    7    /* standard speed: 300 baud */
  44. #define    NSILO    16
  45. #define    DHTIME    6
  46. extern int dhtimer();
  47.  
  48. /*
  49.  * DM control bits
  50.  */
  51. #define    TURNON    03    /* CD lead + line enable */
  52. #define    TURNOFF    01    /* line enable */
  53. #define    RQS    04    /* request to send */
  54.  
  55. /*
  56.  * Software copy of last dhbar
  57.  */
  58. int    dhsar[(NDH11+15)/16];
  59.  
  60. struct device
  61. {
  62.     union {
  63.         int    dhcsr;
  64.         char    dhcsrl;
  65.     } un;
  66.     int    dhnxch;
  67.     int    dhlpr;
  68.     char    *dhcar;
  69.     int    dhbcr;
  70.     int    dhbar;
  71.     int    dhbreak;
  72.     int    dhsilo;
  73. };
  74.  
  75. /*
  76.  * Open a DH11 line.
  77.  */
  78. dhopen(dev, flag)
  79. {
  80.     register struct tty *tp;
  81.     register d;
  82.     register struct device *addr;
  83.     static    timer_on;
  84.     int s;
  85.  
  86.     d = minor(dev);
  87.     if (d >= NDH11) {
  88.         u.u_error = ENXIO;
  89.         return;
  90.     }
  91.     tp = &dh11[d];
  92.     addr = DHADDR;
  93.     addr += d>>4;
  94.     tp->t_addr = (caddr_t)addr;
  95.     tp->t_oproc = dhstart;
  96.     tp->t_iproc = NULL;
  97.     tp->t_state |= WOPEN;
  98.     s = spl6();
  99.     if (!timer_on) {
  100.         timer_on++;
  101.         timeout(dhtimer, (caddr_t)0, DHTIME);
  102.     }
  103.     splx(s);
  104.     addr->un.dhcsr |= IENAB;
  105.     if ((tp->t_state&ISOPEN) == 0) {
  106.         ttychars(tp);
  107.         tp->t_ispeed = SSPEED;
  108.         tp->t_ospeed = SSPEED;
  109.         tp->t_flags = ODDP|EVENP|ECHO;
  110.         dhparam(d);
  111.     }
  112.     if (tp->t_state&XCLUDE && u.u_uid!=0) {
  113.         u.u_error = EBUSY;
  114.         return;
  115.     }
  116.     dmopen(d);
  117.     (*linesw[tp->t_line].l_open)(dev,tp);
  118. }
  119.  
  120. /*
  121.  * Close a DH11 line.
  122.  */
  123. dhclose(dev, flag)
  124. dev_t dev;
  125. int  flag;
  126. {
  127.     register struct tty *tp;
  128.     register d;
  129.  
  130.     d = minor(dev);
  131.     tp = &dh11[d];
  132.     (*linesw[tp->t_line].l_close)(tp);
  133.     if (tp->t_state&HUPCLS)
  134.         dmctl(d, TURNOFF);
  135.     ttyclose(tp);
  136. }
  137.  
  138. /*
  139.  * Read from a DH11 line.
  140.  */
  141. dhread(dev)
  142. {
  143. register struct tty *tp;
  144.  
  145.     tp = &dh11[minor(dev)];
  146.     (*linesw[tp->t_line].l_read)(tp);
  147. }
  148.  
  149. /*
  150.  * write on a DH11 line
  151.  */
  152. dhwrite(dev)
  153. {
  154. register struct tty *tp;
  155.  
  156.     tp = &dh11[minor(dev)];
  157.     (*linesw[tp->t_line].l_write)(tp);
  158. }
  159.  
  160. /*
  161.  * DH11 receiver interrupt.
  162.  */
  163. dhrint(dev)
  164. {
  165.     register struct tty *tp;
  166.     register int c;
  167.     register struct device *addr;
  168.  
  169.     addr = DHADDR;
  170.     addr += minor(dev);
  171.     while ((c = addr->dhnxch) < 0) {    /* char. present */
  172.         tp = &dh11[(minor(dev)<<4) + ((c>>8)&017)];
  173.         dhchars[minor(dev)]++;
  174.         if (tp >= &dh11[NDH11])
  175.             continue;
  176.         if((tp->t_state&ISOPEN)==0) {
  177.             wakeup((caddr_t)tp);
  178.             continue;
  179.         }
  180.         if (c&PERROR)
  181.             if ((tp->t_flags&(EVENP|ODDP))==EVENP
  182.              || (tp->t_flags&(EVENP|ODDP))==ODDP )
  183.                 continue;
  184.         if (c&FRERROR)        /* break */
  185.             if (tp->t_flags&RAW)
  186.                 c = 0;    /* null (for getty) */
  187.             else
  188.                 c = 0177;    /* DEL (intr) */
  189.         (*linesw[tp->t_line].l_rint)(c,tp);
  190.     }
  191. }
  192.  
  193. /*
  194.  * stty/gtty for DH11
  195.  */
  196. dhioctl(dev, cmd, addr, flag)
  197. caddr_t addr;
  198. {
  199.     register struct tty *tp;
  200.  
  201.     tp = &dh11[minor(dev)];
  202.     if (ttioccomm(cmd, tp, addr, dev)) {
  203.         if (cmd==TIOCSETP||cmd==TIOCSETN)
  204.             dhparam(dev);
  205.     } else
  206.         u.u_error = ENOTTY;
  207. }
  208.  
  209. /*
  210.  * Set parameters from open or stty into the DH hardware
  211.  * registers.
  212.  */
  213. dhparam(dev)
  214. {
  215.     register struct tty *tp;
  216.     register struct device *addr;
  217.     register d;
  218.  
  219.     d = minor(dev);
  220.     tp = &dh11[d];
  221.     addr = (struct device *)tp->t_addr;
  222.     spl5();
  223.     addr->un.dhcsrl = (d&017) | IENAB;
  224.     /*
  225.      * Hang up line?
  226.      */
  227.     if ((tp->t_ispeed)==0) {
  228.         tp->t_state |= HUPCLS;
  229.         dmctl(d, TURNOFF);
  230.         return;
  231.     }
  232.     d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
  233.     if ((tp->t_ispeed) == 4)        /* 134.5 baud */
  234.         d |= BITS6|PENABLE|HDUPLX;
  235.     else if (tp->t_flags&RAW)
  236.         d |= BITS8;
  237.     else
  238.         d |= BITS7|PENABLE;
  239.     if ((tp->t_flags&EVENP) == 0)
  240.         d |= OPAR;
  241.     if ((tp->t_ospeed) == 3)    /* 110 baud */
  242.         d |= TWOSB;
  243.     addr->dhlpr = d;
  244.     spl0();
  245. }
  246.  
  247. /*
  248.  * DH11 transmitter interrupt.
  249.  * Restart each line which used to be active but has
  250.  * terminated transmission since the last interrupt.
  251.  */
  252. dhxint(dev)
  253. {
  254.     register struct tty *tp;
  255.     register struct device *addr;
  256.     register d;
  257.     int ttybit, bar, *sbar;
  258.  
  259.     d = minor(dev);
  260.     addr = DHADDR + d;
  261.     addr->un.dhcsr &= ~XINT;
  262.     sbar = &dhsar[d];
  263.     bar = *sbar & ~addr->dhbar;
  264.     d <<= 4; ttybit = 1;
  265.  
  266.     for(; bar; d++, ttybit <<= 1) {
  267.         if(bar&ttybit) {
  268.             *sbar &= ~ttybit;
  269.             bar &= ~ttybit;
  270.             tp = &dh11[d];
  271.             if (tp->t_line) {
  272.                 (*linesw[tp->t_line].l_start)(tp);
  273.             } else {
  274.                 addr->un.dhcsrl = (d&017)|IENAB;
  275.                 if (tp->t_state&FLUSH)
  276.                     tp->t_state &= ~FLUSH;
  277.                 else {
  278.                     ndflush(&q3, addr->dhcar-q3.c_cf);
  279.                 }
  280.                 tp->t_state &= ~BUSY;
  281.                 dhstart(tp);
  282.             }
  283.         }
  284.     }
  285. }
  286.  
  287. /*
  288.  * Start (restart) transmission on the given DH11 line.
  289.  */
  290. dhstart(tp)
  291. register struct tty *tp;
  292. {
  293.     register struct device *addr;
  294.     register nch;
  295.     int s, d;
  296.  
  297.     /*
  298.      * If it's currently active, or delaying,
  299.      * no need to do anything.
  300.      */
  301.     s = spl5();
  302.     d = tp-dh11;
  303.     addr = (struct device *)tp->t_addr;
  304.     if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
  305.         goto out;
  306.  
  307.  
  308.     /*
  309.      * If the writer was sleeping on output overflow,
  310.      * wake him when low tide is reached.
  311.      */
  312.     if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT) {
  313.         tp->t_state &= ~ASLEEP;
  314.         if (tp->t_chan)
  315.             mcstart(tp->t_chan, (caddr_t)&tp->t_outq); else
  316.             wakeup((caddr_t)&tp->t_outq);
  317.     }
  318.  
  319.     if (tp->t_outq.c_cc == 0)
  320.         goto out;
  321.  
  322.  
  323.  
  324.     /*
  325.      * Find number of characters to transfer.
  326.      */
  327.     if (tp->t_flags & RAW) {
  328.         nch = ndqb(&tp->t_outq, 0);
  329.     } else {
  330.         nch = ndqb(&tp->t_outq, 0200);
  331.         if (nch == 0) {
  332.             nch = getc(&tp->t_outq);
  333.             timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
  334.             tp->t_state |= TIMEOUT;
  335.             goto out;
  336.         }
  337.     }
  338.     /*
  339.      * If any characters were set up, start transmission;
  340.      */
  341.     if (nch) {
  342.         addr->un.dhcsrl = (d&017)|IENAB;
  343.         addr->dhcar = tp->t_outq.c_cf;
  344.         addr->dhbcr = -nch;
  345.         dhcc[d] = nch;
  346.         nch = 1<<(d&017);
  347.         addr->dhbar |= nch;
  348.         dhsar[d>>4] |= nch;
  349.         tp->t_state |= BUSY;
  350.     }
  351.     out:
  352.     splx(s);
  353. }
  354.  
  355.  
  356. /*
  357.  * Stop output on a line.
  358.  */
  359. dhstop(tp, flag)
  360. register struct tty *tp;
  361. {
  362.     register struct device *addr;
  363.     register d, s;
  364.  
  365.     addr = (struct device *)tp->t_addr;
  366.     s = spl6();
  367.     if (tp->t_state & BUSY) {
  368.         d = minor(tp->t_dev);
  369.         addr->un.dhcsrl = (d&017) | IENAB;
  370.         if ((tp->t_state&TTSTOP)==0) {
  371.             tp->t_state |= FLUSH;
  372.         }
  373.         addr->dhbcr = -1;
  374.     }
  375.     splx(s);
  376. }
  377.  
  378. dhtimer(dev)
  379. {
  380. register d,cc;
  381. register struct device *addr;
  382.  
  383.     addr = DHADDR; d = 0;
  384.     do {
  385.         cc = dhchars[d];
  386.         dhchars[d] = 0;
  387.         if (cc > 50)
  388.             cc = 32; else
  389.             if (cc > 16)
  390.                 cc = 16; else
  391.                 cc = 0;
  392.         addr->dhsilo = cc;
  393.         addr += 1;
  394.         dhrint(d++);
  395.     } while (d < (NDH11+15)/16);
  396.     timeout(dhtimer, (caddr_t)0, DHTIME);
  397. }
  398.  
  399.