home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / unix / amiga / 2370 < prev    next >
Encoding:
Text File  |  1992-11-08  |  41.7 KB  |  2,374 lines

  1. Path: sparky!uunet!ukma!usenet.ins.cwru.edu!agate!cogsci.Berkeley.EDU!ag
  2. From: ag@cogsci.Berkeley.EDU (Keith Gabryelski)
  3. Newsgroups: comp.unix.amiga
  4. Subject: Fixes for /dev/term/ql?? and /dev/term/ser garbage.
  5. Date: 8 Nov 1992 18:14:18 GMT
  6. Organization: Institute of Cognitive Studies, U.C. Berkeley
  7. Lines: 2362
  8. Distribution: usa
  9. Message-ID: <1djldqINNhhf@agate.berkeley.edu>
  10. NNTP-Posting-Host: cogsci.berkeley.edu
  11.  
  12. Included in the shell archive below is a new version of `ql.c'
  13. and `sl.c' which had some bugs in them that would cause garbage
  14. to be sent to user land under some circumstances.
  15.  
  16. To install these new drivers you will need a version of amiga unix
  17. that is greater than 1.1 and the `conf' package installed.
  18.  
  19. These source files should replace /usr/sys/amiga/driver/ql.c and
  20. /usr/sys/amiga/driver/sl.c.  Please remember to back up the old versions
  21. so that if these drivers turn out to be in worse shape you can back
  22. out this change.
  23.  
  24. Make and install a new kernel as described in the release notes
  25. and you should be fine.
  26.  
  27. Thanks to Mike Ditto for bringing the bug to my attention.
  28.  
  29. Thanks to Rich Skrenta for testing the fixed drivers.
  30.  
  31. Pax, Keith
  32.  
  33. # This is a shell archive.  Remove anything before this line,
  34. # then unpack it by saving it in a file and typing "sh file".
  35. #
  36. # This archive contains:
  37. #    ql.c    sl.c    
  38. #
  39.  
  40. echo x - ql.c
  41. cat >ql.c <<'@EOF'
  42. /* mps6551 */
  43. #include "sys/types.h"
  44. #include "sys/param.h"
  45. #include "sys/dir.h"
  46. #include "sys/file.h"
  47. #include "sys/signal.h"
  48. #include "sys/termio.h"
  49. #include "sys/termios.h"
  50. #include "sys/stream.h"
  51. #include "sys/stropts.h"
  52. #include "sys/strtty.h"
  53. #include "sys/errno.h"
  54. #include "sys/conf.h"
  55. #include "sys/sysmacros.h"
  56. #include "sys/inline.h"
  57. #include "sys/systm.h"
  58. #include "sys/cred.h"
  59. #include "ql6502.h"
  60. #include "ql.h"
  61.  
  62. static int qlopen(struct queue *rq, dev_t *devp, int flag, int sflag,
  63.           cred_t *credp);
  64. static int qlclose(struct queue *q, int oflag, cred_t *credp);
  65. static void output(ql_t *ql, mblk_t *bp);
  66. static int getoblk(struct strtty *tp);
  67. static void delay(struct strtty *tp);
  68. static void flush(struct strtty *tp, int cmd);
  69. static int qlwput(struct queue *q, mblk_t *bp);
  70. static void qlproc(struct strtty *tp, int cmd);
  71. static void qlputioc(queue_t *q, mblk_t *bp);
  72. static int qlwsrv();
  73. static void input(ql_t *ql);
  74. static int qlrsrv(queue_t *q);
  75. static void handle_exceptions(ql_t *ql);
  76. static void qlparam(ql_t *ql, xmitter xm);
  77. static void qlsrvioc(queue_t *q, mblk_t *mp);
  78. static void ql_ttrstrt(ql_t *ql);
  79. static void newcard(device_t *dp);
  80. static void startcard(device_t *dp);
  81. static void initialize(void);
  82. void qlintr(void);
  83.  
  84. /*
  85.  * STREAM data structure definitions.
  86.  */
  87.  
  88. static struct module_info ql_minfo =
  89. {
  90.     0x7777, "ql", 0, INFPSZ, 256, 128,
  91. };
  92.  
  93. static struct qinit qlrinit =
  94. {
  95.     NULL, qlrsrv, qlopen, qlclose, NULL, &ql_minfo, NULL,
  96. };
  97.  
  98. static struct qinit qlwinit =
  99. {
  100.     qlwput, qlwsrv, NULL, NULL, NULL, &ql_minfo, NULL,
  101. };
  102.  
  103. struct streamtab qlinfo =
  104. {
  105.     &qlrinit, &qlwinit, NULL, NULL,
  106. };
  107.  
  108. struct strtty ql_tty[NCARD][NLINE];
  109. ql_t ql_board[NCARD][NLINE];
  110. device_t *qladdr[NCARD];
  111.  
  112. static int qlopen(struct queue *rq, dev_t *devp, int flag, int sflag,
  113.           cred_t *credp)
  114. {
  115.     int s, minor_device;
  116.     ql_t *ql;
  117.  
  118.     s = spltty();
  119.  
  120.     initialize();
  121.  
  122.     if (sflag)
  123.     {
  124.     splx(s);
  125.     return EINVAL;
  126.     }
  127.  
  128.     minor_device = getminor(*devp);
  129.  
  130.     if ((qlcard(minor_device) >= NCARD) || (qlline(minor_device) >= NLINE))
  131.     {
  132.     splx(s);
  133.     return ENXIO;
  134.     }
  135.  
  136.     ql = &ql_board[qlcard(minor_device)][qlline(minor_device)];
  137.  
  138.     if (!ql->lp)
  139.     {
  140.     splx(s);
  141.     return ENXIO;
  142.     }
  143.  
  144.     {
  145.     struct stroptions *sop;
  146.     mblk_t *mop = allocb(sizeof (struct stroptions), BPRI_MED);
  147.  
  148.     if (!mop)
  149.     {
  150.         splx(s);
  151.         return EAGAIN;
  152.     }
  153.  
  154.     mop->b_datap->db_type = M_SETOPTS;
  155.     sop = (struct stroptions *)mop->b_wptr;
  156.     mop->b_wptr += sizeof (struct stroptions);
  157.     sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
  158.     sop->so_hiwat = 512;
  159.     sop->so_lowat = 256;
  160.  
  161.     putnext(rq, mop);
  162.     }
  163.  
  164.     WR(rq)->q_ptr = rq->q_ptr = (caddr_t)ql;
  165.  
  166.     if (!(ql->tp->t_state & ISOPEN))
  167.     {
  168.     ql->tp->t_rdqp = rq;
  169.     ql->tp->t_dev = minor_device;
  170.     ql->tp->t_line = 0;
  171.     ql->tp->t_iflag = 0;
  172.     ql->tp->t_oflag = 0;
  173.     ql->tp->t_lflag = 0;
  174.     ql->tp->t_cflag = B9600|SSPEED|CS8|CREAD|HUPCL;
  175.  
  176.     qlparam(ql, OPEN);
  177.     ql->rts = TRUE;
  178.     ql->rsync = FALSE;
  179.     ql->lp->rsync = TRUE;
  180.  
  181.     while (!ql->rsync)
  182.         sleep(ql, TTIPRI);
  183.     }
  184.  
  185.     if ((flag & (FNDELAY|FNONBLOCK)) || ql->carrier)
  186.     {
  187.     ql->tp->t_state |= CARR_ON;
  188.     if (ql->tp->t_state & WOPEN)
  189.     {
  190.         ql->tp->t_state &= ~WOPEN;
  191.         wakeup(ql);
  192.     }
  193.     }
  194.     else
  195.     {
  196.     while (!(ql->tp->t_state & CARR_ON))
  197.     {
  198.         ql->tp->t_state |= WOPEN;
  199.         sleep(ql, TTIPRI);
  200.     }
  201.     }
  202.  
  203.     ql->tp->t_state |= ISOPEN;
  204.  
  205.     splx(s);
  206.  
  207.     return 0;
  208. }
  209.  
  210. static int qlclose(struct queue *q, int oflag, cred_t *credp)
  211. {
  212.     int s = spltty();
  213.     ql_t *ql = (ql_t *)q->q_ptr;
  214.     struct strtty *tp = ql->tp;
  215.  
  216.     if (tp->t_state & ISOPEN)
  217.     {
  218.     int cflag = tp->t_cflag;
  219.  
  220.     if (!(oflag & (FNDELAY|FNONBLOCK)))
  221.     {
  222.         while (WR(q)->q_first || tp->t_state & BUSY)
  223.         {
  224.         (void) getoblk(tp);
  225.  
  226.         if (WR(q)->q_first || tp->t_state & BUSY)
  227.         {
  228.             tp->t_state |= TTIOW;
  229.  
  230.             if (sleep((caddr_t)&tp->t_oflag, PZERO+1 | PCATCH))
  231.             {
  232.             tp->t_state &= ~TTIOW;
  233.             break;
  234.             }
  235.         }
  236.         }
  237.     }
  238.     }
  239.  
  240.     if (ql->tp->t_cflag & HUPCL)
  241.     qlparam(ql, CLOSE);
  242.  
  243.     tp->t_rdqp = NULL;
  244.     tp->t_state = 0;        /* Just to be really sure --ford */
  245.  
  246.     splx(s);
  247. }
  248.  
  249. static void output(ql_t *ql, mblk_t *bp)
  250. {
  251.     struct strtty *tp = ql->tp;
  252.     queue_t *q;
  253.  
  254.     q = WR(tp->t_rdqp);
  255.  
  256.     if (ql->lp->thead == ql->lp->ttail)
  257.     {
  258.     tp->t_state &= ~BUSY;
  259.     
  260.     if (tp->t_state & TTIOW)
  261.     {
  262.         tp->t_state &= ~TTIOW;
  263.         wakeup(&tp->t_oflag);
  264.     }
  265.     }
  266.  
  267. #if 0
  268.     if (tp->t_state & BUSY)
  269.     return;
  270. #endif
  271.  
  272.     if (ql->lp->ttandem)
  273.     {
  274.     putbq(q, bp);
  275.     return;
  276.     }
  277.  
  278.     if (tp->t_state & TTXON)
  279.     {
  280.     tp->t_state &= ~TTXON;
  281.     ql->lp->ttandem = CSTART;
  282.     putbq(q, bp);
  283.     return;
  284.     }
  285.  
  286.     if (tp->t_state & TTXOFF)
  287.     {
  288.     tp->t_state &= ~TTXOFF;
  289.     ql->lp->ttandem = CSTOP;
  290.     putbq(q, bp);
  291.     return;
  292.     }
  293.  
  294.     if ((ql->lp->tflush) || (tp->t_state & TIMEOUT))
  295.     {
  296.     putbq(q, bp);
  297.     return;
  298.     }
  299.  
  300.     do
  301.     {
  302.     while ((ql->lp->thead+1)%BUFSIZE != ql->lp->ttail &&
  303.            (bp->b_rptr < bp->b_wptr))
  304.     {
  305.         ql->tbufp[ql->lp->thead] = *bp->b_rptr++;
  306.         ql->lp->thead = (ql->lp->thead+1) % BUFSIZE;
  307.         tp->t_state |= BUSY;
  308.     }
  309.  
  310.     if (bp->b_rptr < bp->b_wptr)
  311.     {
  312.         putbq(q, bp);        /* ql buffer full--bail */
  313.         return;
  314.     }
  315.     else
  316.     {
  317.         mblk_t *bp1 = bp;
  318.  
  319.         bp = unlinkb(bp1);
  320.         freeb(bp1);
  321.     }
  322.     } while (bp);
  323. }
  324.  
  325. /*
  326.  * Process an output block.
  327.  * Returns nonzero if there was nothing in the queue.
  328.  */
  329.  
  330. static int getoblk(struct strtty *tp)
  331. {
  332.     int s;
  333.     struct queue *q;
  334.     ql_t *ql;
  335.     mblk_t *bp;
  336.  
  337.     s = spltty();
  338.  
  339.     if (!tp->t_rdqp)
  340.     {
  341.     splx(s);
  342.     return 1;
  343.     }
  344.  
  345.     q = WR(tp->t_rdqp);
  346.     ql = (ql_t *)q->q_ptr;
  347.  
  348.     do
  349.     {
  350.     bp = getq(q);
  351.  
  352.     if (!bp)
  353.     {
  354.         /* wakeup close write queue drain */
  355.         if (ql->lp->thead == ql->lp->ttail)
  356.         {
  357.         tp->t_state &= ~BUSY;
  358.  
  359.         if (tp->t_state & TTIOW)
  360.         {
  361.             tp->t_state &= ~TTIOW;
  362.             wakeup(&tp->t_oflag);
  363.         }
  364.         }
  365.         splx(s);
  366.         return 1;
  367.     }
  368.  
  369.     switch (bp->b_datap->db_type)
  370.     {
  371.     case M_DATA:
  372. #if 0
  373.         printf("qlgetoblk 0x%x: got DATA msg, %d bytes (%x %x %x)\n",
  374.            tp, blklen(bp), bp->b_rptr[0], bp->b_rptr[1],
  375.            bp->b_rptr[2]);
  376. #endif
  377.         if (tp->t_state & (TTSTOP | TIMEOUT))
  378.         {
  379.         putbq(q, bp);
  380.         splx(s);
  381.         return 0;
  382.         }
  383.  
  384.         /*
  385.          * queue bytes to be sent out
  386.          */
  387.         output(ql, bp);
  388.         break;
  389.  
  390.     case M_IOCTL:
  391.     case M_IOCDATA:
  392.         qlsrvioc(q, bp);
  393.         break;
  394.  
  395.     default:
  396.         printf("qlgetoblk 0x%x: got an unknown message, type 0x%x\n",
  397.            tp, bp->b_datap->db_type);
  398.         freemsg(bp);
  399.         break;
  400.     }
  401.     } while (!(tp->t_state & BUSY));
  402.  
  403.     splx(s);
  404.     return 0;
  405. }
  406.  
  407. static void delay(struct strtty *tp)
  408. {
  409.     int s = spltty();
  410.  
  411.     tp->t_state &= ~TIMEOUT;
  412.  
  413.     splx(s);
  414.  
  415.     getoblk(tp);
  416. }
  417.  
  418. static void flush(struct strtty *tp, int cmd)
  419. {
  420.     struct queue *q = WR(tp->t_rdqp);
  421.     ql_t *ql = (ql_t *)q->q_ptr;
  422.     int s = spltty();
  423.  
  424.     if (cmd&FWRITE)
  425.     {
  426.     flushq(WR(tp->t_rdqp), FLUSHDATA);
  427.     tp->t_state &= ~(BUSY|TBLOCK);
  428.     if (tp->t_state & TTIOW)
  429.     {
  430.         tp->t_state &= ~TTIOW;
  431.         wakeup(&tp->t_oflag);
  432.     }
  433.  
  434.     qlproc(tp, T_WFLUSH);
  435.     }
  436.  
  437.     if (cmd&FREAD)
  438.     {
  439.     flushq(tp->t_rdqp, FLUSHDATA);
  440.     tp->t_state &= ~(TBLOCK);
  441.  
  442.     qlproc(tp, T_RFLUSH);
  443.     }
  444.  
  445.     splx(s);
  446.  
  447.     getoblk(tp);
  448. }
  449.  
  450. static int qlwput(struct queue *q, mblk_t *bp)
  451. {
  452.     int s;
  453.     ql_t *ql = (ql_t *)q->q_ptr;
  454.     struct strtty *tp = ql->tp;
  455.     mblk_t *bp1;
  456.  
  457.     switch (bp->b_datap->db_type)
  458.     {
  459.     case M_DATA:
  460.     if (!(tp->t_state & CARR_ON))
  461.     {
  462.         putq(q, bp);
  463.         return 0;
  464.     }
  465.  
  466.     s = spltty();
  467.  
  468.     while (bp)
  469.     {
  470.         bp->b_datap->db_type = M_DATA;
  471.         bp1 = unlinkb(bp);
  472.  
  473.         if (blklen(bp) <= 0)
  474.         freeb(bp);
  475.         else
  476.         putq(q, bp);
  477.  
  478.         bp = bp1;
  479.     }
  480.  
  481.     splx(s);
  482.  
  483.     if (q->q_first)
  484.         getoblk(tp);
  485.     break;
  486.  
  487.     case M_IOCTL:
  488.     case M_IOCDATA:
  489.     qlputioc(q, bp);
  490.     if (q->q_first)
  491.         getoblk(tp);
  492.     break;
  493.  
  494.     case M_CTL:
  495.     {
  496.         struct iocblk *iocb = (struct iocblk *)bp->b_rptr;
  497.  
  498.         if ((blklen(bp) == sizeof *iocb) &&
  499.         (iocb->ioc_cmd == MC_CANONQUERY))
  500.         iocb->ioc_cmd = MC_DO_CANON;
  501.         else
  502.         bp->b_datap->db_type = M_IOCNAK;
  503.  
  504.         putnext(RD(q), bp);
  505.     }
  506.     break;
  507.  
  508.     case M_FLUSH:
  509.     s = spltty();
  510.     switch (bp->b_rptr[0])
  511.     {
  512.     case FLUSHRW:
  513.         flush(tp, (FREAD|FWRITE));
  514.         bp->b_rptr[0] = FLUSHR;
  515.         putnext(RD(q), bp);
  516.         break;
  517.  
  518.     case FLUSHR:
  519.         flush(tp, FREAD);
  520.         putnext(RD(q), bp);
  521.         break;
  522.  
  523.     case FLUSHW:
  524.         flush(tp, FWRITE);
  525.         freemsg(bp);
  526.         break;
  527.     }
  528.     splx(s);
  529.     break;
  530.  
  531.     case M_BREAK:
  532.     s = spltty();
  533.     qlparam(ql, SETBREAK);
  534.     tp->t_state |= TIMEOUT;
  535.     splx(s);
  536.     timeout(ql_ttrstrt, ql, HZ/4);
  537.     freemsg(bp);
  538.     break;
  539.  
  540.     case M_START:
  541.     s = spltty();
  542.     qlproc(tp, T_RESUME);
  543.     splx(s);
  544.     freemsg(bp);
  545.     getoblk(tp);
  546.     break;
  547.  
  548.     case M_STOP:
  549.     s = spltty();
  550.     qlproc(tp, T_SUSPEND);
  551.     splx(s);
  552.     freemsg(bp);
  553.     break;
  554.  
  555.     case M_DELAY:
  556.     s = spltty();
  557.     tp->t_state |= TIMEOUT;
  558.     timeout(delay, (caddr_t)tp, bp->b_rptr[0]);
  559.     splx(s);
  560.     freemsg(bp);
  561.     break;
  562.  
  563.     case M_STARTI:
  564.     /* Can't start/stop keyboard */
  565.     freemsg(bp);
  566.     break;
  567.  
  568.     case M_STOPI:
  569.     /* Can't start/stop keyboard */
  570.     freemsg(bp);
  571.     break;
  572.  
  573.     case M_READ:
  574.     /* <EH> Read queue is always up-to-date? */
  575.     freemsg(bp);
  576.     break;
  577.  
  578.     default:
  579.     printf("qlwput: got an unknown message 0x%x\n", bp->b_datap->db_type);
  580.     freemsg(bp);
  581.     break;
  582.     }
  583. }
  584.  
  585. /*
  586.  * This does all the work.
  587.  */
  588.  
  589. static void qlproc(struct strtty *tp, int cmd)
  590. {
  591.     int s;
  592.     ql_t *ql = &ql_board[0][tp-ql_tty[0]];
  593.  
  594.     switch (cmd)
  595.     {
  596.     case T_TIME:
  597.     s = spltty();
  598.     qlparam(ql, OPEN);
  599.     tp->t_state &= ~TIMEOUT;
  600.     splx(s);
  601.     getoblk(tp);
  602.     break;
  603.  
  604.     case T_RESUME:        /* resume output */
  605.     s = spltty();
  606.     tp->t_state &= ~TTSTOP;
  607.     ql->lp->tdisable = FALSE;
  608.     splx(s);
  609.     getoblk(tp);
  610.     break;
  611.  
  612.     case T_SUSPEND:        /* suspend output */
  613.     ql->lp->tdisable = TRUE;
  614.     s = spltty();
  615.     tp->t_state |= TTSTOP;
  616.     splx(s);
  617.     break;
  618.  
  619.     case T_BREAK:
  620.     qlparam(ql, SETBREAK);
  621.     s = spltty();
  622.     tp->t_state |= TIMEOUT;
  623.     splx(s);
  624.     timeout(ql_ttrstrt, ql, HZ/4);
  625.     getoblk(tp);
  626.     break;
  627.  
  628.     case T_OUTPUT:
  629.     break;
  630.  
  631.     case T_BLOCK:
  632.     tp->t_state &= ~TTXON;
  633.     tp->t_state |= TBLOCK | TTXOFF;
  634.     break;
  635.  
  636.     case T_RFLUSH:
  637.     if (!(tp->t_state&TBLOCK))
  638.         break;
  639.     /* Fall through case */
  640.     case T_UNBLOCK:
  641.     tp->t_state &= ~ (TTXOFF|TBLOCK);
  642.     tp->t_state |= TTXON;
  643.     break;
  644.  
  645.     case T_WFLUSH:
  646.     s = spltty();
  647.     ql->lp->tdisable = TRUE;
  648.     ql->lp->tflush = TRUE;
  649.     tp->t_state &= ~TTSTOP;
  650.     splx(s);
  651.     break;
  652.     }
  653. }
  654.  
  655. static void qlputioc(queue_t *q, mblk_t *bp)
  656. {
  657.     ql_t *ql =  (ql_t *)q->q_ptr;
  658.     struct strtty *tp = ql->tp;
  659.     struct iocblk *iocbp = (struct iocblk *)bp->b_rptr;
  660.     mblk_t *bp1;
  661.  
  662.     switch (iocbp->ioc_cmd)
  663.     {
  664.     case TCSETA:
  665.     case TCSETS:
  666.     if (tp->t_state & BUSY)
  667.         putbq(q, bp);        /* queue these for later */
  668.     else
  669.         qlsrvioc(q, bp);
  670.     return;
  671.  
  672.     case TCGETA:
  673.     case TCGETS:            /* immediate parm retrieve */
  674.     qlsrvioc(q, bp);
  675.     return;
  676.  
  677.     default:
  678.     if ((iocbp->ioc_cmd&IOCTYPE) == LDIOC)
  679.     {
  680.         bp->b_datap->db_type = M_IOCACK; /* ignore LDIOC cmds */
  681.         freemsg(unlinkb(bp));
  682.         iocbp->ioc_count = 0;
  683.         putnext(RD(q), bp);
  684.         return;
  685.     }
  686.     break;
  687.     }
  688.  
  689.     /* Other IOCTLs get queued... */
  690.     if (q->q_first || (tp->t_state & BUSY))
  691.     putbq(q, bp);
  692.     else
  693.     qlsrvioc(q, bp);
  694. }
  695.  
  696. static int qlwsrv()
  697. {
  698.     return 0;
  699. }
  700.  
  701. static void input(ql_t *ql)
  702. {
  703.     struct strtty *tp = ql->tp;
  704.     queue_t *q = tp->t_rdqp;
  705.     unsigned int i, c;
  706.     unsigned char *p;
  707.     mblk_t *bp;
  708.  
  709.     if (!(tp->t_state & (WOPEN|ISOPEN)))
  710.     return;
  711.  
  712.     if (tp->t_state & ISOPEN)
  713.     {
  714.     while ((i = ql->lp->rhead - ql->rtail) != 0)
  715.     {
  716.         if (i > BUFSIZE)
  717.         i = BUFSIZE - ql->rtail;
  718.  
  719.         if (canput(q->q_next))
  720.         {
  721.         if (!ql->rts)
  722.         {
  723.             ql->rts = TRUE;
  724.             qlparam(ql, OPEN);
  725.         }
  726.         }
  727.         else
  728.         {
  729.         ql->rts = FALSE;
  730.         qlparam(ql, RESETRTS);
  731.         break;
  732.         }
  733.  
  734.         bp = allocb(i, BPRI_HI);
  735.         if (!bp)
  736.         break;
  737.  
  738.         p = &ql->rbufp[ql->rtail];
  739.         ql->rtail = (ql->rtail+i) % BUFSIZE;
  740.  
  741.         while (i--)
  742.         {
  743.         c = *p++;
  744.  
  745.         if (tp->t_iflag & ISTRIP)
  746.             c &= 0x7F;
  747.  
  748.         if (tp->t_iflag & IXON)
  749.         {
  750.             if (c == CSTART)
  751.             {
  752.             qlproc(tp, T_RESUME);
  753.             continue;
  754.             }
  755.             if (c == CSTOP)
  756.             {
  757.             qlproc(tp, T_SUSPEND);
  758.             continue;
  759.             }
  760.             if ((tp->t_state & TTSTOP) && (tp->t_iflag & IXANY))
  761.             qlproc(tp, T_RESUME);
  762.         }
  763.  
  764.         *bp->b_wptr++ = c;
  765.         }
  766.  
  767.         putnext(q, bp);
  768.     }
  769.     }
  770.     else
  771.     ql->rtail = ql->lp->rhead;
  772. }
  773.  
  774. static int qlrsrv(queue_t *q)
  775. {
  776.     input((ql_t *)q->q_ptr);
  777.     return 0;
  778. }
  779.  
  780. static void handle_exceptions(ql_t *ql)
  781. {
  782.     struct strtty *tp = ql->tp;
  783.     switch (ql->lp->rcondition)
  784.     {
  785.     case BREAK_DETECTED:
  786.     if ((tp->t_state & ISOPEN) && (!(tp->t_iflag&IGNBRK)))
  787.     {
  788.         if (!(tp->t_lflag & NOFLSH))
  789.         flush(tp, (FREAD|FWRITE));
  790.  
  791.         putctl1(tp->t_rdqp->q_next, M_BREAK, 0);
  792.  
  793.         if (tp->t_iflag & BRKINT)
  794.         putctl1(tp->t_rdqp->q_next, M_SIG, SIGINT);
  795.     }
  796.     break;
  797.  
  798.     case CARR_DETECTED:
  799.     ql->carrier = TRUE;
  800.     tp->t_state |= CARR_ON;
  801.     if (tp->t_state & WOPEN)
  802.     {
  803.         tp->t_state &= ~WOPEN;
  804.         wakeup(ql);
  805.     }
  806.     break;
  807.  
  808.     case RECEIVER_SYNC:
  809.     ql->rsync = TRUE;
  810.     wakeup(ql);
  811.     break;
  812.  
  813.     case CARR_DROPPED:
  814.     ql->carrier = FALSE;
  815.  
  816.     if (tp->t_state & ISOPEN)
  817.     {
  818.         if (!(tp->t_cflag & CLOCAL))
  819.         {
  820.         flush(tp, FREAD|FWRITE);
  821.         tp->t_state &= ~CARR_ON;
  822.         putctl1(tp->t_rdqp->q_next, M_HANGUP, 0);
  823.         }
  824.     }
  825.     else
  826.         tp->t_state &= ~CARR_ON;
  827.  
  828.     break;
  829.     }
  830.  
  831.     ql->lp->rcondition = 0;
  832. }
  833.  
  834. static void qlparam(ql_t *ql, xmitter xm)
  835. {
  836.     struct strtty *tp;
  837.     line_t *lp;
  838.     int    b;
  839.     static unsigned char baudtab[] =
  840.     {
  841.     0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x06,
  842.     0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x0F, 0x00,
  843.     };
  844.  
  845.     tp = ql->tp;
  846.     lp = ql->lp;
  847.     b = baudtab[tp->t_cflag&CBAUD];
  848.  
  849.     lp->xon = tp->t_iflag&IXON? TRUE: FALSE;
  850.     lp->control = 0x10 | b;
  851.  
  852.     switch ((int)xm)
  853.     {
  854.     case OPEN:
  855.     if ((tp->t_cflag&CBAUD) != B0)
  856.     {
  857.         lp->command = 0x0B;
  858.         break;
  859.     }
  860.     /* fall through */
  861.     case CLOSE:
  862.     lp->command = 0x00;
  863.     break;
  864.  
  865.     case SETBREAK:
  866.     lp->command = 0x0D;
  867.     break;
  868.  
  869.     case RESETRTS:
  870.     lp->command &= ~0xC;    /* Stop sending */
  871. #if 0                /* just to remind me of states that could be */
  872.     lp->command |= 0x8;    /* rts assert= normal state-- start ending */
  873.     lp->command |= 0x4;    /* illeagal  */
  874.     lp->command |= 0xC;    /* rts asserted and break is in action. */
  875. #endif
  876.     break;
  877.     }
  878.  
  879.     if (tp->t_cflag & PARENB)
  880.     {
  881.     if (tp->t_cflag & PARODD)
  882.         lp->command |= 0x20;
  883.     else
  884.         lp->command |= 0x60;
  885.     }
  886.  
  887.     switch (tp->t_cflag & CSIZE)
  888.     {
  889.     case CS5:
  890.     lp->control |= 0x60;
  891.     break;
  892.     case CS6:
  893.     lp->control |= 0x40;
  894.     break;
  895.     case CS7:
  896.     lp->control |= 0x20;
  897.     }
  898.  
  899.     lp->setparams = TRUE;
  900. }
  901.  
  902. static void qlsrvioc(queue_t *q, mblk_t *mp)
  903. {
  904.     ql_t *ql = (ql_t *)q->q_ptr;
  905.     struct strtty *tp = ql->tp;
  906.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  907.     int error;
  908.     mblk_t *bp1;
  909.  
  910.     if (mp->b_datap->db_type == M_IOCDATA)
  911.     {
  912.     /* For copyin/copyout failures, just free message. */
  913.     if (((struct copyresp *)mp->b_rptr)->cp_rval)
  914.     {
  915.         freemsg(mp);
  916.         return;
  917.     }
  918.  
  919.     if (!((struct copyresp *)mp->b_rptr)->cp_private)
  920.     {
  921.         mp->b_datap->db_type = M_IOCACK;
  922.         freemsg(unlinkb(mp));
  923.         iocbp->ioc_count = 0;
  924.         iocbp->ioc_rval = 0;
  925.         iocbp->ioc_error = 0;
  926.         putnext(RD(q), mp);
  927.         return;
  928.     }
  929.     }
  930.  
  931. #if 0
  932.     printf("qlsrvioc: %s message, command 0x%x\n",
  933.        (mp->b_datap->db_type == M_IOCDATA ? "IOCDATA" :
  934.         mp->b_datap->db_type == M_IOCTL ? "IOCTL" : "??"),
  935.         iocbp->ioc_cmd);
  936. #endif
  937.  
  938.     switch (iocbp->ioc_cmd)
  939.     {
  940.     case TCSETAF:
  941.     {
  942.         struct termio *cb;
  943.  
  944.         flush(tp, FREAD);
  945.  
  946.         if (!mp->b_cont)
  947.         {
  948.         iocbp->ioc_error = EINVAL;
  949.         mp->b_datap->db_type = M_IOCNAK;
  950.         iocbp->ioc_count = 0;
  951.         putnext(RD(q), mp);
  952.         break;
  953.         }
  954.         cb = (struct termio *)mp->b_cont->b_rptr;
  955.  
  956.         tp->t_cflag = (tp->t_cflag & 0xffff0000 | cb->c_cflag);
  957.         tp->t_iflag = (tp->t_iflag & 0xffff0000 | cb->c_iflag);
  958.         tp->t_oflag = (tp->t_oflag & 0xffff0000 | cb->c_oflag);
  959.  
  960.         qlparam(ql, OPEN);
  961.  
  962.         mp->b_datap->db_type = M_IOCACK;
  963.         bp1 = unlinkb(mp);
  964.         if (bp1)
  965.         freeb(bp1);
  966.         iocbp->ioc_count = 0;
  967.         putnext(RD(q), mp);
  968.         break;
  969.     }
  970.  
  971.     case TCSETA:
  972.     case TCSETAW:
  973.     {
  974.         struct termio *cb;
  975.  
  976.         if (!mp->b_cont)
  977.         {
  978.         iocbp->ioc_error = EINVAL;
  979.         mp->b_datap->db_type = M_IOCNAK;
  980.         iocbp->ioc_count = 0;
  981.         putnext(RD(q), mp);
  982.         break;
  983.         }
  984.         cb = (struct termio *)mp->b_cont->b_rptr;
  985.  
  986.         tp->t_cflag = (tp->t_cflag & 0xffff0000 | cb->c_cflag);
  987.         tp->t_iflag = (tp->t_iflag & 0xffff0000 | cb->c_iflag);
  988.         tp->t_oflag = (tp->t_oflag & 0xffff0000 | cb->c_oflag);
  989.  
  990.         qlparam(ql, OPEN);
  991.  
  992.         mp->b_datap->db_type = M_IOCACK;
  993.         bp1 = unlinkb(mp);
  994.         if (bp1)
  995.         freeb(bp1);
  996.         iocbp->ioc_count = 0;
  997.         putnext(RD(q), mp);
  998.         break;
  999.     }
  1000.  
  1001.     case TCSETSF:
  1002.     {
  1003.         struct termios *cb;
  1004.  
  1005.         flush(tp, FREAD);
  1006.  
  1007.         if (!mp->b_cont)
  1008.         {
  1009.         iocbp->ioc_error = EINVAL;
  1010.         mp->b_datap->db_type = M_IOCNAK;
  1011.         iocbp->ioc_count = 0;
  1012.         putnext(RD(q), mp);
  1013.         break;
  1014.         }
  1015.         cb = (struct termios *)mp->b_cont->b_rptr;
  1016.  
  1017.         tp->t_cflag = cb->c_cflag;
  1018.         tp->t_iflag = cb->c_iflag;
  1019.         tp->t_oflag = cb->c_oflag;
  1020.  
  1021.         qlparam(ql, OPEN);
  1022.  
  1023.         mp->b_datap->db_type = M_IOCACK;
  1024.         bp1 = unlinkb(mp);
  1025.         if (bp1)
  1026.         freeb(bp1);
  1027.         iocbp->ioc_count = 0;
  1028.         putnext(RD(q), mp);
  1029.         break;
  1030.     }
  1031.  
  1032.     case TCSETS:
  1033.     case TCSETSW:
  1034.     {
  1035.         struct termios *cb;
  1036.  
  1037.         if (!mp->b_cont)
  1038.         {
  1039.         iocbp->ioc_error = EINVAL;
  1040.         mp->b_datap->db_type = M_IOCNAK;
  1041.         iocbp->ioc_count = 0;
  1042.         putnext(RD(q), mp);
  1043.         break;
  1044.         }
  1045.         cb = (struct termios *)mp->b_cont->b_rptr;
  1046.  
  1047.         tp->t_cflag = cb->c_cflag;
  1048.         tp->t_iflag = cb->c_iflag;
  1049.         tp->t_oflag = cb->c_oflag;
  1050.  
  1051.         qlparam(ql, OPEN);
  1052.  
  1053.         mp->b_datap->db_type = M_IOCACK;
  1054.         bp1 = unlinkb(mp);
  1055.         if (bp1)
  1056.         freeb(bp1);
  1057.         iocbp->ioc_count = 0;
  1058.         putnext(RD(q), mp);
  1059.         break;
  1060.     }
  1061.  
  1062.     case TCGETA:
  1063.     {    /* immediate parm retrieve */
  1064.         struct termio *cb;
  1065.  
  1066.         if (mp->b_cont)        /* Bad user supplied parameter */
  1067.         freemsg(mp->b_cont);
  1068.  
  1069.         if (!(bp1 = allocb(sizeof (struct termio), BPRI_MED)))
  1070.         {
  1071.         putbq(q, mp);
  1072.         bufcall(sizeof (struct termio), BPRI_MED, getoblk, (long)tp);
  1073.         return;
  1074.         }
  1075.  
  1076.         mp->b_cont = bp1;
  1077.         cb = (struct termio *)mp->b_cont->b_rptr;
  1078.  
  1079.         cb->c_iflag = (unsigned short)tp->t_iflag;
  1080.         cb->c_oflag = (unsigned short)tp->t_oflag;
  1081.         cb->c_cflag = (unsigned short)tp->t_cflag;
  1082.  
  1083.         mp->b_cont->b_wptr += sizeof (struct termio);
  1084.         mp->b_datap->db_type = M_IOCACK;
  1085.         iocbp->ioc_count = sizeof (struct termio);
  1086.         putnext(RD(q), mp);
  1087.         break;
  1088.     }
  1089.  
  1090.     case TCGETS:
  1091.     {    /* immediate parm retrieve */
  1092.         struct termios *cb;
  1093.  
  1094.         if (mp->b_cont)        /* Bad user supplied parameter */
  1095.         freemsg(mp->b_cont);
  1096.  
  1097.         if (!(bp1 = allocb(sizeof(struct termios), BPRI_MED)))
  1098.         {
  1099.         putbq(q, mp);
  1100.         bufcall(sizeof(struct termios), BPRI_MED, getoblk, (long)tp);
  1101.         return;
  1102.         }
  1103.         mp->b_cont = bp1;
  1104.         cb = (struct termios *)mp->b_cont->b_rptr;
  1105.  
  1106.         cb->c_iflag = tp->t_iflag;
  1107.         cb->c_oflag = tp->t_oflag;
  1108.         cb->c_cflag = tp->t_cflag;
  1109.  
  1110.         mp->b_cont->b_wptr += sizeof(struct termios);
  1111.         mp->b_datap->db_type = M_IOCACK;
  1112.         iocbp->ioc_count = sizeof(struct termios);
  1113.         putnext(RD(q), mp);
  1114.         break;
  1115.     }
  1116.  
  1117.     case TCSBRK:
  1118.     mp->b_datap->db_type = (mp->b_cont ? M_IOCACK : M_IOCNAK);
  1119.     freemsg(unlinkb(mp));
  1120.     iocbp->ioc_count = 0;
  1121.     iocbp->ioc_rval = 0;
  1122.     iocbp->ioc_error = 0;
  1123.     putnext(RD(q), mp);
  1124.     qlproc(tp, T_BREAK);
  1125.     break;
  1126.  
  1127.     default:
  1128.     /* Unrecognized ioctl command */
  1129.     if (canput(RD(q)->q_next))
  1130.     {
  1131.         mp->b_datap->db_type = M_IOCNAK;
  1132.         putnext(RD(q), mp);
  1133.     }
  1134.     else
  1135.         putbq(q, mp);
  1136.     break;
  1137.     }
  1138. }
  1139.  
  1140. static void ql_ttrstrt(ql_t *ql)
  1141. {
  1142.     qlparam(ql, OPEN);
  1143.     ql->tp->t_state &= ~TIMEOUT;
  1144. }
  1145.  
  1146. static void newcard(device_t *dp)
  1147. {
  1148.     device_t **pp;
  1149.  
  1150.     pp = (device_t **)endof(qladdr) - 1;
  1151.  
  1152.     if (pp[0])
  1153.     {
  1154.     printf("ql: too many cards\n");
  1155.     return;
  1156.     }
  1157.  
  1158.     while ((pp > qladdr) && (! pp[-1] || pp[-1] > dp))
  1159.     {
  1160.     pp[0] = pp[-1];
  1161.     --pp;
  1162.     }
  1163.  
  1164.     pp[0] = dp;
  1165. }
  1166.  
  1167. static void startcard(device_t *dp)
  1168. {
  1169.     unsigned char *ip, *op;
  1170.  
  1171.     ip = ql6502code;
  1172.     op = (unsigned char *)dp;
  1173.  
  1174.     while (ip < (unsigned char *)endof(ql6502code))
  1175.     {
  1176.     short s = *(short *)ip;
  1177.  
  1178.     ip += sizeof(s);
  1179.  
  1180.     if (s < 0)
  1181.     {
  1182.         while (s++)
  1183.         *op++ = '\0';
  1184.     }
  1185.     else
  1186.     {
  1187.         while (s--)
  1188.         *op++ = *ip++;
  1189.     }
  1190.     }
  1191.  
  1192.     dp->start = 0;
  1193. }
  1194.  
  1195. static void initialize(void)
  1196. {
  1197.     device_t *dp;
  1198.     unsigned int c, l;
  1199.     unsigned char *x;
  1200.     int s;
  1201.     static int done;
  1202.  
  1203.     if (done)
  1204.     return;
  1205.  
  1206.     done = TRUE;
  1207.  
  1208.     for (c = 0; autocon(0x02020046, c, &dp, &x); ++c)
  1209.     newcard(dp);
  1210.  
  1211.     for (c = 0; autocon(0x02020045, c, &dp, &x); ++c)
  1212.     newcard(dp);
  1213.  
  1214.     c = 0;
  1215.  
  1216.     while ((c < nel(qladdr)) && (dp = qladdr[c]))
  1217.     {
  1218.     startcard(dp);
  1219.  
  1220.     for (l = 0; l < NLINE; ++l)
  1221.     {
  1222.         ql_board[c][l].tp = &ql_tty[c][l];
  1223.         ql_board[c][l].lp = &dp->line[l];
  1224.         ql_board[c][l].tbufp = dp->tbuf[l];
  1225.         ql_board[c][l].rbufp = dp->rbuf[l];
  1226.     }
  1227.     ++c;
  1228.     }
  1229. }
  1230.  
  1231. void qlintr(void)
  1232. {
  1233.     unsigned int c, l;
  1234.  
  1235.     for (c = 0; (c < NCARD) && (qladdr[c]); ++c)
  1236.     {
  1237.     qladdr[c]->irqack = 0;        /* ... just in case--rico */
  1238.  
  1239.     for (l = 0; l < NLINE; ++l)
  1240.     {
  1241.         handle_exceptions(&ql_board[c][l]);
  1242.         if (ql_board[c][l].tp->t_rdqp)
  1243.         {
  1244.         input(&ql_board[c][l]);
  1245.         (void) getoblk(ql_board[c][l].tp);
  1246.         }
  1247.     }
  1248.     }
  1249. }
  1250. @EOF
  1251.  
  1252. chmod 644 ql.c
  1253.  
  1254. echo x - sl.c
  1255. cat >sl.c <<'@EOF'
  1256. #include "sys/types.h"
  1257. #include "sys/param.h"
  1258. #include "sys/dir.h"
  1259. #include "sys/file.h"
  1260. #include "sys/signal.h"
  1261. #include "sys/termio.h"
  1262. #include "sys/termios.h"
  1263. #include "sys/stream.h"
  1264. #include "sys/stropts.h"
  1265. #include "sys/strtty.h"
  1266. #include "sys/errno.h"
  1267. #include "sys/conf.h"
  1268. #include "sys/sysmacros.h"
  1269. #include "sys/inline.h"
  1270. #include "sys/systm.h"
  1271. #include "sys/cred.h"
  1272. #include "amigahr.h"
  1273. #include "sl.h"
  1274.  
  1275.  
  1276. /* Amiga serdatr register: */
  1277. #define DATABITS 0x0FF
  1278. #define STOPBIT  0x100
  1279. #define DATASTOP 0x1FF
  1280.  
  1281. /* Amiga adkcon register: */
  1282. #define UARTBRK (1<<11)
  1283.  
  1284. void slinit(void);
  1285. static int slopen(struct queue *rq, dev_t *devp, int flag, int sflag,
  1286.           cred_t *credp);
  1287. static int slclose(struct queue *q, int oflag, cred_t *credp);
  1288. static int getoblk(struct strtty *tp);
  1289. static void delay(struct strtty *tp);
  1290. static void flush(struct strtty *tp, int cmd);
  1291. static int slwput(struct queue *q, mblk_t *bp);
  1292. static void slproc(struct strtty *tp, unsigned cmd);
  1293. static void slputioc(queue_t *q, mblk_t *bp);
  1294. static int slwsrv();
  1295. static int slrsrv();
  1296. static void slparam(xmitter xm);
  1297. static void slsrvioc(queue_t *q, mblk_t *mp);
  1298. static void sl_ttrstrt(struct strtty *tp);
  1299. static void checkcarrier(void);
  1300. void slrint(void);
  1301. void slpoll(void);
  1302. void sltint(void);
  1303. static void output(unsigned int ch);
  1304.  
  1305. /*
  1306.  * Local stuff.
  1307.  */
  1308. sl_t sl = { INPUTGLOBSIZE, EVERYSOOFTEN, };
  1309. static int tictoc;
  1310.  
  1311. /*
  1312.  *  stream data structure definitions
  1313.  */
  1314.  
  1315. static struct module_info sl_minfo =
  1316. {
  1317.     0x736c, "sl", 0, INFPSZ, 256, 128,
  1318. };
  1319.  
  1320. static struct qinit slrinit =
  1321. {
  1322.     NULL, slrsrv, slopen, slclose, NULL, &sl_minfo, NULL,
  1323. };
  1324.  
  1325. static struct qinit slwinit =
  1326. {
  1327.     slwput, slwsrv, NULL, NULL, NULL, &sl_minfo, NULL,
  1328. };
  1329.  
  1330. struct streamtab slinfo =
  1331. {
  1332.     &slrinit, &slwinit, NULL, NULL,
  1333. };
  1334.  
  1335. /* One-time initialization */
  1336. static int initflag;
  1337.  
  1338. void slinit(void)
  1339. {
  1340.     ACIAB->ddra |= (DTR|RTS);    /* Outputs */
  1341.     ACIAB->ddra &= ~(CD|CTS);    /* Inputs */
  1342.     idisable(AIESRBF);
  1343.     idisable(AIESTBE);
  1344.     ++initflag;
  1345. }
  1346.  
  1347. static int slopen(struct queue *rq, dev_t *devp, int flag, int sflag,
  1348.           cred_t *credp)
  1349. {
  1350.     int s, minor_device;
  1351.  
  1352.     if (sflag)            /* not a clone */
  1353.     return EINVAL;        /* or module */
  1354.  
  1355.     s = spltty();
  1356.  
  1357.     if (!initflag)
  1358.     slinit();
  1359.  
  1360.     {
  1361.     struct stroptions *sop;
  1362.     mblk_t *mop = allocb(sizeof (struct stroptions), BPRI_MED);
  1363.  
  1364.     if (!mop)
  1365.     {
  1366.         splx(s);
  1367.         return EAGAIN;
  1368.     }
  1369.  
  1370.     mop->b_datap->db_type = M_SETOPTS;
  1371.     sop = (struct stroptions *)mop->b_wptr;
  1372.     mop->b_wptr += sizeof (struct stroptions);
  1373.     sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
  1374.     sop->so_hiwat = 512;
  1375.     sop->so_lowat = 256;
  1376.  
  1377.     putnext(rq, mop);
  1378.     }
  1379.  
  1380.     /*
  1381.      * Hardware flow control on if minor == 0, otherwise don't
  1382.      * do hardware flow control.
  1383.      */
  1384.     if (!(sl.tty.t_state & ISOPEN))
  1385.     {
  1386.     sl.output_mblk = NULL;
  1387.     sl.cts = TRUE;
  1388.     sl.tty.t_rdqp = rq;
  1389.     sl.tty.t_dev = getminor(*devp);    /* needed for hd flow ctl */
  1390.     sl.tty.t_line = 0;
  1391.     sl.tty.t_iflag = 0;
  1392.     sl.tty.t_oflag = 0;
  1393.     sl.tty.t_lflag = 0;
  1394.     sl.tty.t_cflag = B9600|SSPEED|CS8|CREAD|HUPCL;
  1395.  
  1396.     sl.carrier = FALSE;
  1397.  
  1398.     slparam(OPEN);
  1399.     }
  1400.  
  1401.     checkcarrier();
  1402.  
  1403.     if (flag & (FNDELAY|FNONBLOCK))
  1404.     {
  1405.     sl.tty.t_state |= CARR_ON;
  1406.     if (sl.tty.t_state & WOPEN)
  1407.     {
  1408.         sl.tty.t_state &= ~WOPEN;
  1409.         wakeup(&sl.tty);
  1410.     }
  1411.     }
  1412.     else
  1413.     {
  1414.     while (!(sl.tty.t_state & CARR_ON))
  1415.     {
  1416.         sl.tty.t_state |= WOPEN;    /* Sleeping for carrier in open */
  1417.         sleep(&sl.tty, TTIPRI);
  1418.     }
  1419.     }
  1420.  
  1421.     if (!sl.rdq)
  1422.     {
  1423.     sl.rdq = rq;
  1424.     sl.tty.t_state |= ISOPEN; /* In open */
  1425.     ienable(AIESRBF);
  1426.     }
  1427.  
  1428.     splx(s);
  1429.  
  1430.     return 0;
  1431. }
  1432.  
  1433. static int slclose(struct queue *q, int oflag, cred_t *credp)
  1434. {
  1435.     int s = spltty();
  1436.     struct strtty *tp = &sl.tty;
  1437.  
  1438.     if (tp->t_state & ISOPEN)
  1439.     {
  1440.     int cflag = tp->t_cflag;
  1441.  
  1442.     if (!(oflag & (FNDELAY|FNONBLOCK)))
  1443.     {
  1444.         while (WR(q)->q_first || tp->t_state & BUSY)
  1445.         {
  1446.         (void) getoblk(tp);
  1447.  
  1448.         if (WR(q)->q_first || tp->t_state & BUSY)
  1449.         {
  1450.             tp->t_state |= TTIOW;
  1451.             if (sleep((caddr_t)&tp->t_oflag, PZERO + 1| PCATCH))
  1452.             {
  1453.             tp->t_state &= ~TTIOW;
  1454.             break;
  1455.             }
  1456.         }
  1457.         }
  1458.     }
  1459.     }
  1460.  
  1461.     if (sl.tty.t_cflag & HUPCL)
  1462.     slparam(CLOSE);
  1463.  
  1464.     tp->t_state = 0;
  1465.     tp->t_rdqp = NULL;
  1466.     sl.rdq = NULL;
  1467.  
  1468.     idisable(AIESRBF);
  1469.     idisable(AIESTBE);
  1470.  
  1471.     splx(s);
  1472.  
  1473.     return 0;
  1474. }
  1475.  
  1476. /*
  1477.  * Process an output block.
  1478.  * Returns nonzero if there was nothing in the queue.
  1479.  */
  1480.  
  1481. static int getoblk(struct strtty *tp)
  1482. {
  1483.     int s = spltty();
  1484.     struct queue *q;
  1485.     mblk_t *bp;
  1486.  
  1487.     if (!tp->t_rdqp)
  1488.     {
  1489.     splx(s);
  1490.     return 1;
  1491.     }
  1492.     q = WR(tp->t_rdqp);
  1493.  
  1494.     do
  1495.     {
  1496.     bp = getq(q);
  1497.  
  1498.     if (!bp)
  1499.     {
  1500.         /* wakeup close write queue drain */
  1501.         tp->t_state &= ~BUSY;
  1502.  
  1503.         if (tp->t_state & TTIOW)
  1504.         {
  1505.         tp->t_state &= ~TTIOW;
  1506.         wakeup(&tp->t_oflag);
  1507.         }
  1508.  
  1509.         splx(s);
  1510.         return 1;
  1511.     }
  1512.  
  1513.     switch (bp->b_datap->db_type)
  1514.     {
  1515.     case M_DATA:
  1516. #if 0
  1517.         printf("slgetoblk 0x%x: got DATA msg, %d bytes (%x %x %x)\n",
  1518.            tp, blklen(bp), bp->b_rptr[0], bp->b_rptr[1],
  1519.            bp->b_rptr[2]);
  1520. #endif
  1521.         if (tp->t_state & (TTSTOP | TIMEOUT))
  1522.         {
  1523.         putbq(q, bp);
  1524.         splx(s);
  1525.         return 0;
  1526.         }
  1527.  
  1528.         /*
  1529.          * queue bytes to be sent out
  1530.          */
  1531.  
  1532.         if (sl.output_mblk)
  1533.         putbq(q, bp);
  1534.         else
  1535.         sl.output_mblk = bp;
  1536.  
  1537.         if (!(tp->t_state & BUSY))
  1538.         {
  1539.         ienable(AIESTBE);
  1540.  
  1541.         if (sl.output_mblk->b_rptr >= sl.output_mblk->b_wptr)
  1542.             freemsg(sl.output_mblk);
  1543.         else
  1544.             output(*sl.output_mblk->b_rptr++);
  1545.         }
  1546.         break;
  1547.  
  1548.     case M_IOCTL:
  1549.     case M_IOCDATA:
  1550.         slsrvioc(q, bp);
  1551.         break;
  1552.  
  1553.     default:
  1554.         printf("slgetoblk 0x%x: got an unknown message, type 0x%x\n",
  1555.            tp, bp->b_datap->db_type);
  1556.         freemsg(bp);
  1557.         break;
  1558.     }
  1559.     } while (!(tp->t_state & BUSY));
  1560.  
  1561.     splx(s);
  1562.     return 0;
  1563. }
  1564.  
  1565. static void delay(struct strtty *tp)
  1566. {
  1567.     int s = spltty();
  1568.  
  1569.     tp->t_state &= ~TIMEOUT;
  1570.  
  1571.     splx(s);
  1572.  
  1573.     getoblk(tp);
  1574. }
  1575.  
  1576. static void flush(struct strtty *tp, int cmd)
  1577. {
  1578.     int s = spltty();
  1579.  
  1580.     if (cmd&FWRITE)
  1581.     {
  1582.     flushq(WR(tp->t_rdqp), FLUSHDATA);
  1583.     tp->t_state &= ~BUSY;
  1584.  
  1585.     if (tp->t_state & TTIOW)
  1586.     {
  1587.         tp->t_state &= ~TTIOW;
  1588.         wakeup(&tp->t_oflag);
  1589.     }
  1590.  
  1591.     slproc(tp, T_WFLUSH);
  1592.     }
  1593.  
  1594.     if (cmd&FREAD)
  1595.     {
  1596.     flushq(tp->t_rdqp, FLUSHDATA);
  1597.  
  1598.     slproc(tp, T_RFLUSH);
  1599.     }
  1600.  
  1601.     splx(s);
  1602.     getoblk(tp);
  1603. }
  1604.  
  1605. static int slwput(struct queue *q, mblk_t *bp)
  1606. {
  1607.     int s;
  1608.     struct strtty *tp = &sl.tty;
  1609.     mblk_t *bp1;
  1610.  
  1611.     switch (bp->b_datap->db_type)
  1612.     {
  1613.     case M_DATA:
  1614.     if (!(tp->t_state & CARR_ON))
  1615.     {
  1616.         putq(q, bp);
  1617.         return 0;
  1618.     }
  1619.  
  1620.     s = spltty();
  1621.  
  1622.     while (bp)
  1623.     {
  1624.         bp->b_datap->db_type = M_DATA;
  1625.         bp1 = unlinkb(bp);
  1626.  
  1627.         if (blklen(bp) <= 0)
  1628.         freeb(bp);
  1629.         else
  1630.         putq(q, bp);
  1631.  
  1632.         bp = bp1;
  1633.     }
  1634.  
  1635.     splx(s);
  1636.  
  1637.     if (q->q_first)
  1638.         getoblk(tp);
  1639.     break;
  1640.  
  1641.     case M_IOCTL:
  1642.     case M_IOCDATA:
  1643.     slputioc(q, bp);
  1644.     if (q->q_first)
  1645.         getoblk(tp);
  1646.     break;
  1647.  
  1648.     case M_CTL:
  1649.     {
  1650.         struct iocblk *iocb = (struct iocblk *)bp->b_rptr;
  1651.         if ((blklen(bp) == sizeof *iocb) &&
  1652.         (iocb->ioc_cmd == MC_CANONQUERY))
  1653.         iocb->ioc_cmd = MC_DO_CANON;
  1654.         else
  1655.         bp->b_datap->db_type = M_IOCNAK;
  1656.         putnext(RD(q), bp);
  1657.     }
  1658.     break;
  1659.  
  1660.     case M_FLUSH:
  1661.     s = spltty();
  1662.     switch (bp->b_rptr[0])
  1663.     {
  1664.     case FLUSHRW:
  1665.         flush(tp, (FREAD|FWRITE));
  1666.         bp->b_rptr[0] = FLUSHR;
  1667.         putnext(RD(q), bp);
  1668.         break;
  1669.  
  1670.     case FLUSHR:
  1671.         flush(tp, FREAD);
  1672.         putnext(RD(q), bp);
  1673.         break;
  1674.  
  1675.     case FLUSHW:
  1676.         flush(tp, FWRITE);
  1677.         freemsg(bp);
  1678.         break;
  1679.     }
  1680.     splx(s);
  1681.     break;
  1682.  
  1683.     case M_BREAK:
  1684.     s = spltty();
  1685.     slproc(tp, T_BREAK);
  1686.     splx(s);
  1687.     freemsg(bp);
  1688.     break;
  1689.  
  1690.     case M_START:
  1691.     s = spltty();
  1692.     slproc(tp, T_RESUME);
  1693.     splx(s);
  1694.     freemsg(bp);
  1695.     getoblk(tp);
  1696.     break;
  1697.  
  1698.     case M_STOP:
  1699.     s = spltty();
  1700.     slproc(tp, T_SUSPEND);
  1701.     splx(s);
  1702.     freemsg(bp);
  1703.     break;
  1704.  
  1705.     case M_DELAY:
  1706.     s = spltty();
  1707.     tp->t_state |= TIMEOUT;
  1708.     timeout(delay, (caddr_t)tp, bp->b_rptr[0]);
  1709.     splx(s);
  1710.     freemsg(bp);
  1711.     break;
  1712.  
  1713.     case M_STARTI:
  1714.     /* Can't start/stop keyboard */
  1715.     freemsg(bp);
  1716.     break;
  1717.  
  1718.     case M_STOPI:
  1719.     /* Can't start/stop keyboard */
  1720.     freemsg(bp);
  1721.     break;
  1722.  
  1723.     case M_READ:
  1724.     /* <EH> Read queue is always up-to-date? */
  1725.     freemsg(bp);
  1726.     break;
  1727.  
  1728.     default:
  1729.     printf("slwput: got an unknown message 0x%x\n", bp->b_datap->db_type);
  1730.     freemsg(bp);
  1731.     break;
  1732.     }
  1733. }
  1734.  
  1735. /*
  1736.  * This does all the work.
  1737.  */
  1738.  
  1739. static void slproc(struct strtty *tp, unsigned cmd)
  1740. {
  1741.     int s;
  1742.  
  1743.     switch (cmd)
  1744.     {
  1745.     case T_TIME:
  1746.     s = spltty();
  1747.     tp->t_state &= ~TIMEOUT;
  1748.     splx(s);
  1749.     irequest(AIESTBE);
  1750.     getoblk(tp);
  1751.     break;
  1752.  
  1753.     case T_WFLUSH:
  1754.     if (sl.output_mblk)
  1755.     {
  1756.         freemsg(sl.output_mblk);
  1757.         sl.output_mblk = NULL;
  1758.     }
  1759.     /* fall through */
  1760.     case T_RESUME:            /* resume output */
  1761.     s = spltty();
  1762.     tp->t_state &= ~TTSTOP;
  1763.     splx(s);
  1764.     irequest(AIESTBE);
  1765.     getoblk(tp);
  1766.     break;
  1767.  
  1768.     case T_SUSPEND:            /* suspend output */
  1769.     s = spltty();
  1770.     tp->t_state |= TTSTOP;
  1771.     splx(s);
  1772.     break;
  1773.  
  1774.     case T_RFLUSH:
  1775.     break;
  1776.  
  1777.     case T_BREAK:
  1778.     s = spltty();
  1779.     slparam(SETBREAK);
  1780.     tp->t_state |= TIMEOUT;
  1781.     timeout(sl_ttrstrt, tp, HZ/4);
  1782.     splx(s);
  1783.     getoblk(tp);
  1784.     break;
  1785.     }
  1786. }
  1787.  
  1788. static void slputioc(queue_t *q, mblk_t *bp)
  1789. {
  1790.     struct iocblk *iocbp = (struct iocblk *)bp->b_rptr;
  1791.     struct strtty *tp = &sl.tty;
  1792.     mblk_t *bp1;
  1793.  
  1794.     switch (iocbp->ioc_cmd)
  1795.     {
  1796.     case TCSETA:
  1797.     case TCSETS:
  1798.     if (tp->t_state & BUSY)
  1799.         putbq(q, bp);        /* queue these for later */
  1800.     else
  1801.         slsrvioc(q, bp);
  1802.     return;
  1803.  
  1804.     case TCGETA:
  1805.     case TCGETS:            /* immediate parm retrieve */
  1806.     slsrvioc(q, bp);
  1807.     return;
  1808.  
  1809.     default:
  1810.     if ((iocbp->ioc_cmd&IOCTYPE) == LDIOC)
  1811.     {
  1812.         bp->b_datap->db_type = M_IOCACK; /* ignore LDIOC cmds */
  1813.         freemsg(unlinkb(bp));
  1814.         iocbp->ioc_count = 0;
  1815.         putnext(RD(q), bp);
  1816.         return;
  1817.     }
  1818.     break;
  1819.     }
  1820.  
  1821.     /* Other IOCTLs get queued... */
  1822.     if (q->q_first || (tp->t_state & BUSY))
  1823.     putbq(q, bp);
  1824.     else
  1825.     slsrvioc(q, bp);
  1826. }
  1827.  
  1828. static int slwsrv() { return 0; }
  1829.  
  1830. static int slrsrv() { return 0; }
  1831.  
  1832. static void slparam(xmitter xm)
  1833. {
  1834.     unsigned int s;
  1835.     static unsigned short speeds[] =
  1836.     {
  1837.     0,            /* hangup */
  1838.     31 - 1,            /* 115200 for ql (hardware can't do 50) */
  1839.     62 - 1,            /* 57600 is popular (hardware can't do 75) */
  1840.     32542 - 1,        /* 110 */
  1841.     26714 - 1,        /* 134 */
  1842.     23864 - 1,        /* 150 */
  1843.     17898 - 1,        /* 200 */
  1844.     11932 - 1,        /* 300 */
  1845.     5966 - 1,        /* 600 */
  1846.     2983 - 1,        /* 1200 */
  1847.     1989 - 1,        /* 1800 */
  1848.     1492 - 1,        /* 2400 */
  1849.     746 - 1,        /* 4800 */
  1850.     373 - 1,        /* 9600 */
  1851.     186 - 1,        /* 19200 */
  1852.     93 - 1            /* 38400 */
  1853.     };
  1854.  
  1855.     switch ((int)xm)
  1856.     {
  1857.     case OPEN:
  1858.     s = sl.tty.t_cflag & CBAUD;
  1859.  
  1860.     if (s>0 && s < (sizeof(speeds) / sizeof(speeds[0])))
  1861.     {
  1862.         AMIGA->serper = DATA8 | speeds[s];
  1863.         ACIAB->pra &= ~DTR;
  1864.     }
  1865.     else
  1866.         ACIAB->pra |= DTR;
  1867.  
  1868.     AMIGA->adkcon = ADKCLR | UARTBRK;
  1869.  
  1870.     if (!(sl.tty.t_iflag & IXON) && (sl.tty.t_state & TTSTOP))
  1871.         slproc(&sl.tty, T_RESUME);
  1872.     break;
  1873.  
  1874.     case CLOSE:
  1875.     ACIAB->pra |= DTR;
  1876.     break;
  1877.  
  1878.     case SETBREAK:
  1879.     AMIGA->adkcon = ADKSET | UARTBRK;
  1880.     }
  1881. }
  1882.  
  1883. static void slsrvioc(queue_t *q, mblk_t *mp)
  1884. {
  1885.     struct strtty *tp = &sl.tty;
  1886.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  1887.     int error;
  1888.     mblk_t *bp1;
  1889.  
  1890.     if (mp->b_datap->db_type == M_IOCDATA)
  1891.     {
  1892.     /* For copyin/copyout failures, just free message. */
  1893.     if (((struct copyresp *)mp->b_rptr)->cp_rval)
  1894.     {
  1895.         freemsg(mp);
  1896.         return;
  1897.     }
  1898.  
  1899.     if (!((struct copyresp *)mp->b_rptr)->cp_private)
  1900.     {
  1901.         mp->b_datap->db_type = M_IOCACK;
  1902.         freemsg(unlinkb(mp));
  1903.         iocbp->ioc_count = 0;
  1904.         iocbp->ioc_rval = 0;
  1905.         iocbp->ioc_error = 0;
  1906.         putnext(RD(q), mp);
  1907.         return;
  1908.     }
  1909.     }
  1910.  
  1911. #if 0
  1912.     printf("slsrvioc: %s message, command 0x%x %d\n",
  1913.        (mp->b_datap->db_type == M_IOCDATA ? "IOCDATA" :
  1914.         mp->b_datap->db_type == M_IOCTL ? "IOCTL" : "??"),
  1915.         iocbp->ioc_cmd, (sl.tty.t_state & CARR_ON));
  1916. #endif
  1917.  
  1918.     switch (iocbp->ioc_cmd)
  1919.     {
  1920.     case TCSETAF:
  1921.     {
  1922.         struct termio *cb;
  1923.  
  1924.         flush(tp, FREAD);
  1925.  
  1926.         if (!mp->b_cont)
  1927.         {
  1928.         iocbp->ioc_error = EINVAL;
  1929.         mp->b_datap->db_type = M_IOCNAK;
  1930.         iocbp->ioc_count = 0;
  1931.         putnext(RD(q), mp);
  1932.         break;
  1933.         }
  1934.         cb = (struct termio *)mp->b_cont->b_rptr;
  1935.  
  1936.         tp->t_cflag = (tp->t_cflag & 0xffff0000 | cb->c_cflag);
  1937.         tp->t_iflag = (tp->t_iflag & 0xffff0000 | cb->c_iflag);
  1938.         tp->t_oflag = (tp->t_oflag & 0xffff0000 | cb->c_oflag);
  1939.  
  1940.         slparam(OPEN);
  1941.  
  1942.         mp->b_datap->db_type = M_IOCACK;
  1943.         bp1 = unlinkb(mp);
  1944.         if (bp1)
  1945.         freeb(bp1);
  1946.         iocbp->ioc_count = 0;
  1947.         putnext(RD(q), mp);
  1948.         break;
  1949.     }
  1950.  
  1951.     case TCSETA:
  1952.     case TCSETAW:
  1953.     {
  1954.         struct termio *cb;
  1955.  
  1956.         if (!mp->b_cont)
  1957.         {
  1958.         iocbp->ioc_error = EINVAL;
  1959.         mp->b_datap->db_type = M_IOCNAK;
  1960.         iocbp->ioc_count = 0;
  1961.         putnext(RD(q), mp);
  1962.         break;
  1963.         }
  1964.         cb = (struct termio *)mp->b_cont->b_rptr;
  1965.  
  1966.         tp->t_cflag = (tp->t_cflag & 0xffff0000 | cb->c_cflag);
  1967.         tp->t_iflag = (tp->t_iflag & 0xffff0000 | cb->c_iflag);
  1968.         tp->t_oflag = (tp->t_oflag & 0xffff0000 | cb->c_oflag);
  1969.  
  1970.         slparam(OPEN);
  1971.  
  1972.         mp->b_datap->db_type = M_IOCACK;
  1973.         bp1 = unlinkb(mp);
  1974.         if (bp1)
  1975.         freeb(bp1);
  1976.         iocbp->ioc_count = 0;
  1977.         putnext(RD(q), mp);
  1978.         break;
  1979.     }
  1980.  
  1981.     case TCSETSF:
  1982.     {
  1983.         struct termios *cb;
  1984.  
  1985.         flush(tp, FREAD);
  1986.  
  1987.         if (!mp->b_cont)
  1988.         {
  1989.         iocbp->ioc_error = EINVAL;
  1990.         mp->b_datap->db_type = M_IOCNAK;
  1991.         iocbp->ioc_count = 0;
  1992.         putnext(RD(q), mp);
  1993.         break;
  1994.         }
  1995.         cb = (struct termios *)mp->b_cont->b_rptr;
  1996.  
  1997.         tp->t_cflag = cb->c_cflag;
  1998.         tp->t_iflag = cb->c_iflag;
  1999.         tp->t_oflag = cb->c_oflag;
  2000.  
  2001.         slparam(OPEN);
  2002.  
  2003.         mp->b_datap->db_type = M_IOCACK;
  2004.         bp1 = unlinkb(mp);
  2005.         if (bp1)
  2006.         freeb(bp1);
  2007.         iocbp->ioc_count = 0;
  2008.         putnext(RD(q), mp);
  2009.         break;
  2010.     }
  2011.  
  2012.     case TCSETS:
  2013.     case TCSETSW:
  2014.     {
  2015.         struct termios *cb;
  2016.  
  2017.         if (!mp->b_cont)
  2018.         {
  2019.         iocbp->ioc_error = EINVAL;
  2020.         mp->b_datap->db_type = M_IOCNAK;
  2021.         iocbp->ioc_count = 0;
  2022.         putnext(RD(q), mp);
  2023.         break;
  2024.         }
  2025.         cb = (struct termios *)mp->b_cont->b_rptr;
  2026.  
  2027.         tp->t_cflag = cb->c_cflag;
  2028.         tp->t_iflag = cb->c_iflag;
  2029.         tp->t_oflag = cb->c_oflag;
  2030.  
  2031.         slparam(OPEN);
  2032.  
  2033.         mp->b_datap->db_type = M_IOCACK;
  2034.         bp1 = unlinkb(mp);
  2035.         if (bp1)
  2036.         freeb(bp1);
  2037.         iocbp->ioc_count = 0;
  2038.         putnext(RD(q), mp);
  2039.         break;
  2040.     }
  2041.  
  2042.     case TCGETA:
  2043.     {    /* immediate parm retrieve */
  2044.         struct termio *cb;
  2045.  
  2046.         if (mp->b_cont)        /* Bad user supplied parameter */
  2047.         freemsg(mp->b_cont);
  2048.  
  2049.         if (!(bp1 = allocb(sizeof (struct termio), BPRI_MED)))
  2050.         {
  2051.         putbq(q, mp);
  2052.         bufcall(sizeof (struct termio), BPRI_MED, getoblk, (long)tp);
  2053.         return;
  2054.         }
  2055.  
  2056.         mp->b_cont = bp1;
  2057.         cb = (struct termio *)mp->b_cont->b_rptr;
  2058.  
  2059.         cb->c_iflag = (unsigned short)tp->t_iflag;
  2060.         cb->c_oflag = (unsigned short)tp->t_oflag;
  2061.         cb->c_cflag = (unsigned short)tp->t_cflag;
  2062.  
  2063.         mp->b_cont->b_wptr += sizeof (struct termio);
  2064.         mp->b_datap->db_type = M_IOCACK;
  2065.         iocbp->ioc_count = sizeof (struct termio);
  2066.         putnext(RD(q), mp);
  2067.         break;
  2068.     }
  2069.  
  2070.     case TCGETS:
  2071.     {    /* immediate parm retrieve */
  2072.         struct termios *cb;
  2073.  
  2074.         if (mp->b_cont)        /* Bad user supplied parameter */
  2075.         freemsg(mp->b_cont);
  2076.  
  2077.         if (!(bp1 = allocb(sizeof(struct termios), BPRI_MED)))
  2078.         {
  2079.         putbq(q, mp);
  2080.         bufcall(sizeof(struct termios), BPRI_MED, getoblk, (long)tp);
  2081.         return;
  2082.         }
  2083.         mp->b_cont = bp1;
  2084.         cb = (struct termios *)mp->b_cont->b_rptr;
  2085.  
  2086.         cb->c_iflag = tp->t_iflag;
  2087.         cb->c_oflag = tp->t_oflag;
  2088.         cb->c_cflag = tp->t_cflag;
  2089.  
  2090.         mp->b_cont->b_wptr += sizeof(struct termios);
  2091.         mp->b_datap->db_type = M_IOCACK;
  2092.         iocbp->ioc_count = sizeof(struct termios);
  2093.         putnext(RD(q), mp);
  2094.         break;
  2095.     }
  2096.  
  2097.     case TCSBRK:
  2098.     mp->b_datap->db_type = (mp->b_cont ? M_IOCACK : M_IOCNAK);
  2099.     freemsg(unlinkb(mp));
  2100.     iocbp->ioc_count = 0;
  2101.     iocbp->ioc_rval = 0;
  2102.     iocbp->ioc_error = 0;
  2103.     putnext(RD(q), mp);
  2104.     slproc(tp, T_BREAK);
  2105.     break;
  2106.  
  2107.     default:
  2108.     /* Unrecognized ioctl command */
  2109.     if (canput(RD(q)->q_next))
  2110.     {
  2111.         mp->b_datap->db_type = M_IOCNAK;
  2112.         putnext(RD(q), mp);
  2113.     }
  2114.     else
  2115.         putbq(q, mp);
  2116.     break;
  2117.     }
  2118. }
  2119.  
  2120. static void sl_ttrstrt(struct strtty *tp)
  2121. {
  2122.     slparam(OPEN);
  2123.     slproc(tp, T_TIME);
  2124. }
  2125.  
  2126. static void checkcarrier(void)
  2127. {
  2128.     int    s;
  2129.  
  2130.     s = spltty();
  2131.  
  2132.     if ((ACIAB->pra&CD) == 0)
  2133.     {
  2134.     if (!sl.carrier)
  2135.     {
  2136.         sl.carrier = TRUE;
  2137.         sl.tty.t_state |= CARR_ON;
  2138.  
  2139.         if (sl.tty.t_state & WOPEN)
  2140.         {
  2141.         sl.tty.t_state &= ~WOPEN;
  2142.         wakeup(&sl.tty);
  2143.         }
  2144.     }
  2145.     }
  2146.     else
  2147.     {
  2148.     if (sl.carrier)
  2149.     {
  2150.         sl.carrier = FALSE;
  2151.  
  2152.         if (tictoc)
  2153.         untimeout(tictoc);
  2154.  
  2155.         if (!(sl.tty.t_state & ISOPEN))
  2156.         sl.tty.t_state &= ~CARR_ON;
  2157.         else if (!(sl.tty.t_cflag & CLOCAL))
  2158.         {
  2159.         flush(&sl.tty, FREAD|FWRITE);
  2160.         sl.tty.t_state &= ~CARR_ON;
  2161.  
  2162.         if (sl.rdq)
  2163.             putctl1(sl.rdq->q_next, M_HANGUP, 0);
  2164.         }
  2165.     }
  2166.     }
  2167.  
  2168.     splx(s);
  2169. }
  2170.  
  2171. #define BUFsize   256U
  2172. #define HIGHwater 64
  2173. #define LOWwater  32
  2174. static volatile    unsigned int head, tail;
  2175. static unsigned short buff[BUFsize];
  2176.  
  2177. /* slrint runs from level 5 hardware interrupt */
  2178. void slrint(void)
  2179. {
  2180.     unsigned int nbytes = (BUFsize+head-tail)%BUFsize;
  2181.     unsigned short c = AMIGA->serdatr & DATASTOP;
  2182.  
  2183.     if (sl.tty.t_iflag & IXON)
  2184.     {
  2185.     if (c == (CSTART|STOPBIT))
  2186.     {
  2187.         sl.output_xoff = 0;
  2188.         return;
  2189.     }
  2190.     if (c == (CSTOP|STOPBIT))
  2191.     {
  2192.         sl.output_xoff = 1;
  2193.         return;
  2194.     }
  2195.  
  2196.     if (sl.tty.t_iflag & IXANY)
  2197.         sl.output_xoff = 0;
  2198.     }
  2199.  
  2200.     if (nbytes >= BUFsize-1)
  2201.     {
  2202.     idisable(AIESRBF);
  2203.     return;
  2204.     }
  2205.  
  2206.     if (nbytes > BUFsize-LOWwater)
  2207.     ACIAB->pra |= RTS;    /* RTS off */
  2208.  
  2209.     buff[head] = c;
  2210.     head = (head+1) % BUFsize;
  2211. }
  2212.  
  2213. /* slpoll runs at clock priority */
  2214. void slpoll(void)
  2215. {
  2216.     mblk_t *mp;
  2217.  
  2218.     if (hardware_flow_control && sl.tty.t_state&ISOPEN)
  2219.     {
  2220.     if (!sl.output_xoff && (sl.tty.t_state & TTSTOP))
  2221.         slproc(&sl.tty, T_RESUME);
  2222.  
  2223.     if (!sl.cts && !(ACIAB->pra&CTS))
  2224.     {
  2225.         sl.cts = TRUE;
  2226.         irequest(AIESTBE);    /* Try to send another byte */
  2227.     }
  2228.     }
  2229.     if (sl.tty.t_state & (WOPEN|ISOPEN))
  2230.     checkcarrier();
  2231.  
  2232.     mp = 0;
  2233.     while (sl.rdq && tail != head && canput(sl.rdq->q_next))
  2234.     {
  2235.     unsigned short c = buff[tail];
  2236.  
  2237.     if (!(c & DATASTOP))    /* No bits indicates a break */
  2238.     {
  2239.         tail = (tail+1) % BUFsize;
  2240.  
  2241.         if (sl.tty.t_iflag & IGNBRK)
  2242.         continue;
  2243.  
  2244.         if (sl.tty.t_lflag & NOFLSH)
  2245.         {
  2246.         if (mp)
  2247.             putnext(sl.rdq, mp);
  2248.         }
  2249.         else
  2250.         {
  2251.         flush(&sl.tty, (FREAD|FWRITE));
  2252.         freemsg(mp);
  2253.         }
  2254.         mp = 0;
  2255.  
  2256.         putctl1(sl.rdq->q_next, M_BREAK, 0);
  2257.         if (sl.tty.t_iflag & BRKINT)
  2258.         putctl1(sl.rdq->q_next, M_SIG, SIGINT);
  2259.     }
  2260.     else
  2261.     {
  2262.         if (mp && mp->b_wptr >= mp->b_datap->db_lim)
  2263.         {
  2264.         putnext(sl.rdq, mp);
  2265.         mp = 0;
  2266.         }
  2267.  
  2268.         if (!mp)
  2269.         mp = allocb(sl.inputglobsize, BPRI_HI);
  2270.  
  2271.         if (!mp)
  2272.         break;
  2273.  
  2274.         tail = (tail+1) % BUFsize;
  2275.  
  2276.         c &= DATABITS;    /* Get the real character */
  2277.  
  2278.         if ((sl.tty.t_iflag & ISTRIP) || (sl.tty.t_cflag & PARENB))
  2279.         c &= 0x7F;    /* Strip if wanted */
  2280.  
  2281.         *mp->b_wptr++ = c;
  2282.     }
  2283.  
  2284.     ienable(AIESRBF);
  2285.     if ((BUFsize+head-tail)%BUFsize < BUFsize-HIGHwater)
  2286.         ACIAB->pra &= ~RTS;    /* RTS on */
  2287.     }
  2288.  
  2289.     if (mp)
  2290.     putnext(sl.rdq, mp);
  2291. }
  2292.  
  2293. void sltint(void)
  2294. {
  2295.     unsigned int ch = (unsigned int)-1;
  2296.  
  2297.     if (!(AMIGA->serdatr&TBE))
  2298.     return;
  2299.  
  2300.     if (!sl.rdq)
  2301.     return;
  2302.  
  2303.     if (hardware_flow_control)
  2304.     {
  2305.     if (ACIAB->pra&CTS)        /* Not Clear To Send? */
  2306.     {
  2307.         sl.cts = FALSE;
  2308.         sl.tty.t_state |= BUSY;
  2309.         return;
  2310.     }
  2311.     else
  2312.     {
  2313.         sl.tty.t_state &= ~BUSY;
  2314.         
  2315.         if (sl.tty.t_state & TTIOW)
  2316.         {
  2317.         sl.tty.t_state &= ~TTIOW;
  2318.         wakeup(&sl.tty.t_oflag);
  2319.         }
  2320.     }
  2321.     }
  2322.  
  2323.     if (sl.output_xoff && !(sl.tty.t_state & TTSTOP))
  2324.     slproc(&sl.tty, T_SUSPEND);
  2325.  
  2326.     if (sl.tty.t_state & TTXON)
  2327.     {
  2328.     if (sl.tty.t_iflag & IXOFF)
  2329.         ch = CSTART;
  2330.  
  2331.     sl.tty.t_state &= ~TTXON;
  2332.     }
  2333.     else if (sl.tty.t_state & TTXOFF)
  2334.     {
  2335.     if (sl.tty.t_iflag & IXOFF)
  2336.         ch = CSTOP;
  2337.  
  2338.     sl.tty.t_state &= ~TTXOFF;
  2339.     }
  2340.     else if (sl.tty.t_state & TTSTOP)
  2341.     {
  2342.     idisable(AIESTBE);    /* No interrupts for a while */
  2343.     return;
  2344.     }
  2345.  
  2346.     if (ch == (unsigned int)-1)
  2347.     getoblk(&sl.tty);
  2348.     else
  2349.     output(ch);
  2350. }
  2351.  
  2352. static void output(unsigned int ch)
  2353. {
  2354.     if (sl.tty.t_cflag & PARENB)
  2355.     {
  2356.     extern unsigned char partab[];
  2357.  
  2358.     ch &= 0x7F;
  2359.     ch |= partab[ch] & 0x80;
  2360.     if (sl.tty.t_cflag & PARODD)
  2361.         ch ^= 0x80;
  2362.     }
  2363.  
  2364.     AMIGA->serdat = STOPBIT | ch;    /* Or'd stop bit in */
  2365.  
  2366.     sl.tty.t_state |= BUSY;
  2367. }
  2368. @EOF
  2369.  
  2370. chmod 644 sl.c
  2371.  
  2372. exit 0
  2373.  
  2374.