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

  1. /*
  2.  * This driver handles the two serial ports on the back of the
  3.  * pro3xx system unit. Although not software compatible, they
  4.  * are handled as minor device 0 & 1 respectively, for the printer
  5.  * and communication port. Modem control is included but no sync
  6.  * serial support for the com. port.
  7.  * NOTE: The DSR line in the printer port is used for carrier
  8.  * detect so terminals or modems should be cabled accordingly.
  9.  * Local terminal cables should jumper DTR-CDT so that the carrier
  10.  * will appear to be up or PC_SOFTCAR defined and devs or'd with 0200.
  11.  * NOTE2: The interrupt service routines are as follows:
  12.  *    plrint - printer port receive
  13.  *    plxint - printer port transmit
  14.  *    cmintr - communication port com. interrupt
  15.  * Modem transition interrupts are NOT used.
  16.  */
  17.  
  18. #include "pc.h"
  19. #if NPC > 0
  20. #include <sys/param.h>
  21. #include <sys/dir.h>
  22. #include <sys/user.h>
  23. #include <sys/tty.h>
  24. #include <sys/file.h>
  25. #include <sys/conf.h>
  26. #include <sys/ivecpos.h>
  27. #include <sys/pcreg.h>
  28.  
  29. #ifdef PC_SOFTCAR
  30. #define PCLINE(d)    (minor(d) & 0177)
  31. #else
  32. #define PCLINE        minor
  33. #endif
  34.  
  35. extern struct pcdevice *PCADDR;
  36. int    npctty    = NPC;        /* Only for pstat */
  37. struct    tty    pc11[NPC];
  38. char    pc_stat;
  39. int    pcstart();
  40.  
  41. char    pc_speeds[] = {
  42.     0, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 10,
  43.     12, 14, 15, 15,
  44. };
  45.  
  46. pcattach(addr, unit)
  47. struct pcdevice *addr;
  48. {
  49.     if ((unsigned)unit < NPC) {
  50.         PCADDR = addr;
  51.         return(1);
  52.     }
  53.     return(0);
  54. }
  55.  
  56. pcopen(dev, flag) {
  57.     register struct tty *tp;
  58.     register int d;
  59.     int s;
  60.  
  61.     d = PCLINE(dev);
  62.     if (d >= NPC) {
  63.         u.u_error = EINVAL;
  64.         return;
  65.     }
  66.     if (PCADDR == (struct pcdevice *)NULL) {
  67.         u.u_error = ENXIO;
  68.         return;
  69.     }
  70.     tp = &pc11[d];
  71.     if ((tp->t_state&(ISOPEN|WOPEN)) == 0) {
  72.         tp->t_oproc = pcstart;
  73.         tp->t_ispeed = B9600;
  74.         tp->t_ospeed = B9600;
  75.         tp->t_flags = ODDP|EVENP|ECHO|CRMOD;
  76.         tp->t_line = DFLT_LDISC;
  77.         ttychars(tp);
  78.         pcparam(d);
  79.     } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
  80.         u.u_error = EBUSY;
  81.         return;
  82.     }
  83.     pcmodem(d, ON);
  84. #ifdef PC_SOFTCAR
  85.     if (dev & 0200)
  86.         tp->t_state |= CARR_ON;
  87.     else
  88. #endif
  89.     {
  90.     (void) _spl4();
  91.     while ((tp->t_state&CARR_ON)==0) {
  92.         tp->t_state |= WOPEN;
  93.         sleep((caddr_t)&tp->t_rawq, TTIPRI);
  94.     }
  95.     (void) _spl0();
  96.     }
  97.     tp->t_state = (tp->t_state & ~WOPEN)|ISOPEN;
  98.     ttyopen(dev, tp);
  99. }
  100.  
  101. pcclose(dev)
  102. dev_t dev;
  103. {
  104.     register struct tty *tp;
  105.     register d;
  106.  
  107.     d = PCLINE(dev);
  108.     tp = &pc11[d];
  109.     if (tp->t_state&HUPCLS)
  110.         pcmodem(d, OFF);
  111.     ttyclose(tp);
  112. }
  113.  
  114. pcread(dev)
  115. dev_t dev;
  116. {
  117.     register struct tty *tp;
  118.  
  119.     tp = &pc11[PCLINE(dev)];
  120.     (*linesw[tp->t_line].l_read)(tp);
  121. }
  122.  
  123. pcwrite(dev)
  124. dev_t dev;
  125. {
  126.     register struct tty *tp;
  127.  
  128.     tp = &pc11[PCLINE(dev)];
  129.     (*linesw[tp->t_line].l_write)(tp);
  130. }
  131.  
  132. pcioctl(dev, cmd, addr, flag)
  133. dev_t    dev;
  134. int    cmd;
  135. caddr_t    addr;
  136. int    flag;
  137. {
  138.     register struct tty *tp;
  139.     register int d;
  140.  
  141.     d = PCLINE(dev);
  142.     switch(ttioctl(&pc11[d], cmd, addr, flag)) {
  143.     case TIOCSETN:
  144.     case TIOCSETP:
  145.         pcparam(d);
  146.     case 0:
  147.         break;
  148.     default:
  149.         u.u_error = ENOTTY;
  150.     }
  151. }
  152.  
  153. pcparam(dev)
  154. int dev;
  155. {
  156.     register struct tty *tp;
  157.     register lpr, flag;
  158.  
  159.     tp = &pc11[dev];
  160.     if (pc_stat==0) {
  161.         pcscan();
  162.         pc_stat++;
  163.     }
  164.     if (tp->t_ispeed==0) {    /* Hang up line */
  165.         pcmodem(dev, OFF);
  166.         return;
  167.     }
  168.     if (dev == 0) {
  169.         lpr = PCADDR->csr;
  170.         if (tp->t_flags&RAW)
  171.             lpr = BITS8;
  172.         else
  173.             lpr = BITS7|PENABLE;
  174.         if (tp->t_flags&EVENP)
  175.             lpr |= EPAR;
  176.         if (tp->t_ispeed == 3)    /* 110 baud */
  177.             lpr |= TWOSB;
  178.         PCADDR->mode = lpr;
  179.         PCADDR->mode = pc_speeds[tp->t_ispeed]|DIVR;
  180.         ((physadr *) 0173700)->r[0] = 0200;
  181.         ienable(PLRPOS);
  182.         ienable(PLXPOS);
  183.     } else {
  184.         PCADDR->baud = (pc_speeds[tp->t_ospeed]<<4)|
  185.             pc_speeds[tp->t_ispeed];
  186.         PCADDR->csa = 1;
  187.         PCADDR->csa = 022;
  188.         PCADDR->csb = 1;
  189.         PCADDR->csb = 04;
  190.         PCADDR->csb = 2;
  191.         PCADDR->csb = 0;
  192.         if (tp->t_flags&RAW) {
  193.             flag = 03;
  194.             lpr = 0104;
  195.         } else {
  196.             flag = 01;
  197.             lpr = 0105;
  198.         }
  199.         if (tp->t_flags&EVENP)
  200.             lpr |= 02;
  201.         if (tp->t_ispeed == 3)
  202.             lpr |= 010;
  203.         PCADDR->csa = 4;
  204.         PCADDR->csa = lpr;
  205.         PCADDR->csa = 3;
  206.         PCADDR->csa = (flag<<6)|01;
  207.         PCADDR->csa = 5;
  208.         PCADDR->csa = (flag<<5)|010;
  209.         ienable(CMPOS);
  210.     }
  211. }
  212.  
  213. pcrint(dev)
  214. int dev;
  215. {
  216.     register struct tty *tp;
  217.     register c, tmp;
  218.     int tmp1;
  219.  
  220.     if (dev == 0) {
  221.         tmp = PCADDR->stat;
  222.         if (tmp & RXDONE) {
  223.             tp = pc11;
  224.             c = PCADDR->dbuf;
  225.             PCADDR->csr = GOCMD;
  226.             if((tp->t_state&ISOPEN)==0) {
  227.                 wakeup((caddr_t)&tp->t_rawq);
  228.                 return;
  229.             }
  230.             if (tmp&FRERROR) {        /* break */
  231.                 if (tp->t_flags&RAW)
  232.                     c = 0;        /* null (for getty) */
  233.                 else
  234.                     c = tun.t_intrc;
  235.             } else if (tmp&PERROR) {
  236.                 if ((tp->t_flags&(EVENP|ODDP))==EVENP
  237.                  || (tp->t_flags&(EVENP|ODDP))==ODDP )
  238.                     return;
  239.             }
  240.             (*linesw[tp->t_line].l_input)(c, tp);
  241.         }
  242.     } else {
  243.         tmp1 = PCADDR->csa;
  244.         PCADDR->csa = 1;
  245.         tmp = PCADDR->csa;
  246.         PCADDR->csa = ERESET;
  247.         if (tmp1 & RXCA) {
  248.             tp = &pc11[1];
  249.             c = PCADDR->cdb;
  250.             if ((tp->t_state&ISOPEN)==0) {
  251.                 wakeup((caddr_t)&tp->t_rawq);
  252.                 return;
  253.             }
  254.             if (tmp&CFERROR) {
  255.                 if (tp->t_flags&RAW)
  256.                     c = 0;
  257.                 else
  258.                     c = tun.t_intrc;
  259.             } else if (tmp&CPERROR) {
  260.                 if ((tp->t_flags&(EVENP|ODDP))==EVENP
  261.                  || (tp->t_flags&(EVENP|ODDP))==ODDP )
  262.                     return;
  263.             }
  264.             (*linesw[tp->t_line].l_input) (c, tp);
  265.         }
  266.     }
  267. }
  268.  
  269. pcxint(dev)
  270. int dev;
  271. {
  272.     register struct tty *tp;
  273.  
  274.     tp = &pc11[dev];
  275.     ttstart(tp);
  276.     if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT(tp))
  277. #ifdef MPX_FIL
  278.         if (tp->t_chan)
  279.             mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
  280.         else
  281. #endif
  282.             wakeup((caddr_t)&tp->t_outq);
  283. }
  284.  
  285. pcstart(tp)
  286. register struct tty *tp;
  287. {
  288.     register unit, c;
  289.     extern ttrstrt();
  290.  
  291.     unit = tp - pc11;
  292.     if (unit == 0) {
  293.         if ((PCADDR->stat & TXDONE)==0)
  294.             return;
  295.     } else {
  296.         if ((PCADDR->csa & CTXDONE)==0)
  297.             return;
  298.     }
  299.     if ((c = getc(&tp->t_outq)) >= 0) {
  300.         if ((tp->t_flags & RAW) == 0 && c >= 0200) {
  301.             tp->t_state |= TIMEOUT;
  302.             timeout(ttrstrt, (caddr_t)tp, (c&0177)+PCDELAY);
  303.         } else {
  304.             if (unit == 0)
  305.                 PCADDR->dbuf = c;
  306.             else
  307.                 PCADDR->cdb = c;
  308.         }
  309.     } else {
  310.         if (unit == 1)
  311.             PCADDR->csa = RTINTP;
  312.     }
  313. }
  314.  
  315. pcmodem(dev, flag)
  316. int dev, flag;
  317. {
  318.  
  319.     if (dev == 0) {
  320.         if (flag==OFF)
  321.             PCADDR->csr = 0;
  322.         else
  323.             PCADDR->csr = GOCMD;
  324.     } else {
  325.         if (flag==OFF)
  326.             PCADDR->mc0 = 0;
  327.         else
  328.             PCADDR->mc0 = 030;
  329.     }
  330. }
  331.  
  332. pcscan()
  333. {
  334.     register i, flag;
  335.     register struct tty *tp;
  336.  
  337.     for (i=0; i<NPC; i++) {
  338.         if (i == 0) {
  339.             flag = PCADDR->stat & DSRON;
  340.         } else {
  341.             flag = PCADDR->mc1 & CARDTC;
  342.         }
  343.         tp = &pc11[i];
  344.         if (flag) {
  345.             if ((tp->t_state&CARR_ON)==0) {
  346.                 wakeup((caddr_t)&tp->t_rawq);
  347.                 tp->t_state |= CARR_ON;
  348.             }
  349.         } else {
  350.             if ((tp->t_state&CARR_ON)
  351. #ifdef PC_SOFTCAR
  352.                && ((tp->t_dev & 0200) == 0)
  353. #endif
  354. #ifdef UCB_NTTY
  355.                 && ((tp->t_local&LNOHANG)==0)
  356. #endif
  357.             ) {
  358.                 if (tp->t_state&ISOPEN) {
  359.                     gsignal(tp->t_pgrp, SIGHUP);
  360.                     if (i == 0) {
  361.                         PCADDR->csr = 0;
  362.                     } else {
  363.                         PCADDR->mc0 = 0;
  364.                     }
  365.                     flushtty(tp, FREAD|FWRITE);
  366.                 }
  367.                 tp->t_state &= ~CARR_ON;
  368.             }
  369.         }
  370.     }
  371.     timeout(pcscan, (caddr_t)0, 120);
  372. }
  373.  
  374. cmintr(dev)
  375. int dev;
  376. {
  377.     register int tmp;
  378.  
  379.     do {
  380.         PCADDR->csb = 2;
  381.         tmp = (PCADDR->csb>>2)&03;
  382.         switch (tmp) {
  383.         case TRAN:
  384.             pcxint(1);
  385.             break;
  386.         case XTERN:
  387.             break;
  388.         case RCV:
  389.         case SRCV:
  390.             pcrint(1);
  391.         };
  392.         PCADDR->csa = EOFINTR;
  393.     } while (PCADDR->csa & INTRP);
  394.     PCADDR->csa = REXINTR;
  395. }
  396. #endif
  397.