The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rp/rp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Copyright (c) Comtrol Corporation <support@comtrol.com>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted prodived that the follwoing conditions
    7  * are met.
    8  * 1. Redistributions of source code must retain the above copyright 
    9  *    notive, this list of conditions and the following disclainer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials prodided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *       This product includes software developed by Comtrol Corporation.
   16  * 4. The name of Comtrol Corporation may not be used to endorse or 
   17  *    promote products derived from this software without specific 
   18  *    prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
   21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
   24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD: releng/5.1/sys/dev/rp/rp.c 111815 2003-03-03 12:15:54Z phk $
   33  */
   34 
   35 /* 
   36  * rp.c - for RocketPort FreeBSD
   37  */
   38 
   39 #include "opt_compat.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/tty.h>
   46 #include <sys/conf.h>
   47 #include <sys/kernel.h>
   48 #include <machine/resource.h>
   49 #include <machine/bus.h>
   50 #include <sys/bus.h>
   51 #include <sys/rman.h>
   52 
   53 #define ROCKET_C
   54 #include <dev/rp/rpreg.h>
   55 #include <dev/rp/rpvar.h>
   56 
   57 static const char RocketPortVersion[] = "3.02";
   58 
   59 static Byte_t RData[RDATASIZE] =
   60 {
   61    0x00, 0x09, 0xf6, 0x82,
   62    0x02, 0x09, 0x86, 0xfb,
   63    0x04, 0x09, 0x00, 0x0a,
   64    0x06, 0x09, 0x01, 0x0a,
   65    0x08, 0x09, 0x8a, 0x13,
   66    0x0a, 0x09, 0xc5, 0x11,
   67    0x0c, 0x09, 0x86, 0x85,
   68    0x0e, 0x09, 0x20, 0x0a,
   69    0x10, 0x09, 0x21, 0x0a,
   70    0x12, 0x09, 0x41, 0xff,
   71    0x14, 0x09, 0x82, 0x00,
   72    0x16, 0x09, 0x82, 0x7b,
   73    0x18, 0x09, 0x8a, 0x7d,
   74    0x1a, 0x09, 0x88, 0x81,
   75    0x1c, 0x09, 0x86, 0x7a,
   76    0x1e, 0x09, 0x84, 0x81,
   77    0x20, 0x09, 0x82, 0x7c,
   78    0x22, 0x09, 0x0a, 0x0a
   79 };
   80 
   81 static Byte_t RRegData[RREGDATASIZE]=
   82 {
   83    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
   84    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
   85    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
   86    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
   87    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
   88    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
   89    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
   90    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
   91    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
   92    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
   93    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
   94    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
   95    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
   96 };
   97 
   98 #if 0
   99 /* IRQ number to MUDBAC register 2 mapping */
  100 Byte_t sIRQMap[16] =
  101 {
  102    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  103 };
  104 #endif
  105 
  106 Byte_t rp_sBitMapClrTbl[8] =
  107 {
  108    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  109 };
  110 
  111 Byte_t rp_sBitMapSetTbl[8] =
  112 {
  113    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  114 };
  115 
  116 /* Actually not used */
  117 #if notdef
  118 struct termios deftermios = {
  119         TTYDEF_IFLAG,
  120         TTYDEF_OFLAG,
  121         TTYDEF_CFLAG,
  122         TTYDEF_LFLAG,
  123         { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
  124         _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
  125         CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
  126         TTYDEF_SPEED,
  127         TTYDEF_SPEED
  128 };
  129 #endif
  130 
  131 /***************************************************************************
  132 Function: sReadAiopID
  133 Purpose:  Read the AIOP idenfication number directly from an AIOP.
  134 Call:     sReadAiopID(CtlP, aiop)
  135           CONTROLLER_T *CtlP; Ptr to controller structure
  136           int aiop: AIOP index
  137 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  138                  is replace by an identifying number.
  139           Flag AIOPID_NULL if no valid AIOP is found
  140 Warnings: No context switches are allowed while executing this function.
  141 
  142 */
  143 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
  144 {
  145    Byte_t AiopID;               /* ID byte from AIOP */
  146 
  147    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
  148    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
  149    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
  150    if(AiopID == 0x06)
  151       return(1);
  152    else                                /* AIOP does not exist */
  153       return(-1);
  154 }
  155 
  156 /***************************************************************************
  157 Function: sReadAiopNumChan
  158 Purpose:  Read the number of channels available in an AIOP directly from
  159           an AIOP.
  160 Call:     sReadAiopNumChan(CtlP, aiop)
  161           CONTROLLER_T *CtlP; Ptr to controller structure
  162           int aiop: AIOP index
  163 Return:   int: The number of channels available
  164 Comments: The number of channels is determined by write/reads from identical
  165           offsets within the SRAM address spaces for channels 0 and 4.
  166           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  167           AIOP, otherwise it is an 8 channel.
  168 Warnings: No context switches are allowed while executing this function.
  169 */
  170 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
  171 {
  172    Word_t x, y;
  173 
  174    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  175    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
  176    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  177    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  178    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  179    if(x != y)  /* if different must be 8 chan */
  180       return(8);
  181    else
  182       return(4);
  183 }
  184 
  185 /***************************************************************************
  186 Function: sInitChan
  187 Purpose:  Initialization of a channel and channel structure
  188 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  189           CONTROLLER_T *CtlP; Ptr to controller structure
  190           CHANNEL_T *ChP; Ptr to channel structure
  191           int AiopNum; AIOP number within controller
  192           int ChanNum; Channel number within AIOP
  193 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  194                number exceeds number of channels available in AIOP.
  195 Comments: This function must be called before a channel can be used.
  196 Warnings: No range checking on any of the parameters is done.
  197 
  198           No context switches are allowed while executing this function.
  199 */
  200 int sInitChan(  CONTROLLER_T *CtlP,
  201                 CHANNEL_T *ChP,
  202                 int AiopNum,
  203                 int ChanNum)
  204 {
  205    int i, ChOff;
  206    Byte_t *ChR;
  207    static Byte_t R[4];
  208 
  209    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  210       return(FALSE);                   /* exceeds num chans in AIOP */
  211 
  212    /* Channel, AIOP, and controller identifiers */
  213    ChP->CtlP = CtlP;
  214    ChP->ChanID = CtlP->AiopID[AiopNum];
  215    ChP->AiopNum = AiopNum;
  216    ChP->ChanNum = ChanNum;
  217 
  218    /* Initialize the channel from the RData array */
  219    for(i=0; i < RDATASIZE; i+=4)
  220    {
  221       R[0] = RData[i];
  222       R[1] = RData[i+1] + 0x10 * ChanNum;
  223       R[2] = RData[i+2];
  224       R[3] = RData[i+3];
  225       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
  226    }
  227 
  228    ChR = ChP->R;
  229    for(i=0; i < RREGDATASIZE; i+=4)
  230    {
  231       ChR[i] = RRegData[i];
  232       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  233       ChR[i+2] = RRegData[i+2];
  234       ChR[i+3] = RRegData[i+3];
  235    }
  236 
  237    /* Indexed registers */
  238    ChOff = (Word_t)ChanNum * 0x1000;
  239 
  240    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  241    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  242    ChP->BaudDiv[2] = (Byte_t)BRD9600;
  243    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
  244    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
  245 
  246    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  247    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  248    ChP->TxControl[2] = 0;
  249    ChP->TxControl[3] = 0;
  250    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  251 
  252    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  253    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  254    ChP->RxControl[2] = 0;
  255    ChP->RxControl[3] = 0;
  256    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  257 
  258    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  259    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  260    ChP->TxEnables[2] = 0;
  261    ChP->TxEnables[3] = 0;
  262    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
  263 
  264    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  265    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  266    ChP->TxCompare[2] = 0;
  267    ChP->TxCompare[3] = 0;
  268    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
  269 
  270    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  271    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  272    ChP->TxReplace1[2] = 0;
  273    ChP->TxReplace1[3] = 0;
  274    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
  275 
  276    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  277    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  278    ChP->TxReplace2[2] = 0;
  279    ChP->TxReplace2[3] = 0;
  280    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
  281 
  282    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  283    ChP->TxFIFO = ChOff + _TX_FIFO;
  284 
  285    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  286    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  287    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  288    rp_writech2(ChP,_INDX_DATA,0);
  289    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  290    ChP->RxFIFO = ChOff + _RX_FIFO;
  291 
  292    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  293    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  294    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  295    rp_writech2(ChP,_INDX_DATA,0);
  296    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  297    rp_writech2(ChP,_INDX_DATA,0);
  298    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  299    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
  300    rp_writech1(ChP,_INDX_DATA,0);
  301    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  302    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
  303    rp_writech1(ChP,_INDX_DATA,0);
  304    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  305    sEnRxProcessor(ChP);                /* start the Rx processor */
  306 
  307    return(TRUE);
  308 }
  309 
  310 /***************************************************************************
  311 Function: sStopRxProcessor
  312 Purpose:  Stop the receive processor from processing a channel.
  313 Call:     sStopRxProcessor(ChP)
  314           CHANNEL_T *ChP; Ptr to channel structure
  315 
  316 Comments: The receive processor can be started again with sStartRxProcessor().
  317           This function causes the receive processor to skip over the
  318           stopped channel.  It does not stop it from processing other channels.
  319 
  320 Warnings: No context switches are allowed while executing this function.
  321 
  322           Do not leave the receive processor stopped for more than one
  323           character time.
  324 
  325           After calling this function a delay of 4 uS is required to ensure
  326           that the receive processor is no longer processing this channel.
  327 */
  328 void sStopRxProcessor(CHANNEL_T *ChP)
  329 {
  330    Byte_t R[4];
  331 
  332    R[0] = ChP->R[0];
  333    R[1] = ChP->R[1];
  334    R[2] = 0x0a;
  335    R[3] = ChP->R[3];
  336    rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
  337 }
  338 
  339 /***************************************************************************
  340 Function: sFlushRxFIFO
  341 Purpose:  Flush the Rx FIFO
  342 Call:     sFlushRxFIFO(ChP)
  343           CHANNEL_T *ChP; Ptr to channel structure
  344 Return:   void
  345 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  346           while it is being flushed the receive processor is stopped
  347           and the transmitter is disabled.  After these operations a
  348           4 uS delay is done before clearing the pointers to allow
  349           the receive processor to stop.  These items are handled inside
  350           this function.
  351 Warnings: No context switches are allowed while executing this function.
  352 */
  353 void sFlushRxFIFO(CHANNEL_T *ChP)
  354 {
  355    int i;
  356    Byte_t Ch;                   /* channel number within AIOP */
  357    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  358 
  359    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  360       return;                          /* don't need to flush */
  361 
  362    RxFIFOEnabled = FALSE;
  363    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  364    {
  365       RxFIFOEnabled = TRUE;
  366       sDisRxFIFO(ChP);                 /* disable it */
  367       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
  368          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
  369    }
  370    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  371    Ch = (Byte_t)sGetChanNum(ChP);
  372    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  373    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
  374    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  375    rp_writech2(ChP,_INDX_DATA,0);
  376    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  377    rp_writech2(ChP,_INDX_DATA,0);
  378    if(RxFIFOEnabled)
  379       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  380 }
  381 
  382 /***************************************************************************
  383 Function: sFlushTxFIFO
  384 Purpose:  Flush the Tx FIFO
  385 Call:     sFlushTxFIFO(ChP)
  386           CHANNEL_T *ChP; Ptr to channel structure
  387 Return:   void
  388 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  389           while it is being flushed the receive processor is stopped
  390           and the transmitter is disabled.  After these operations a
  391           4 uS delay is done before clearing the pointers to allow
  392           the receive processor to stop.  These items are handled inside
  393           this function.
  394 Warnings: No context switches are allowed while executing this function.
  395 */
  396 void sFlushTxFIFO(CHANNEL_T *ChP)
  397 {
  398    int i;
  399    Byte_t Ch;                   /* channel number within AIOP */
  400    int TxEnabled;                      /* TRUE if transmitter enabled */
  401 
  402    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  403       return;                          /* don't need to flush */
  404 
  405    TxEnabled = FALSE;
  406    if(ChP->TxControl[3] & TX_ENABLE)
  407    {
  408       TxEnabled = TRUE;
  409       sDisTransmit(ChP);               /* disable transmitter */
  410    }
  411    sStopRxProcessor(ChP);              /* stop Rx processor */
  412    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  413       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
  414    Ch = (Byte_t)sGetChanNum(ChP);
  415    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  416    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
  417    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  418    rp_writech2(ChP,_INDX_DATA,0);
  419    if(TxEnabled)
  420       sEnTransmit(ChP);                /* enable transmitter */
  421    sStartRxProcessor(ChP);             /* restart Rx processor */
  422 }
  423 
  424 /***************************************************************************
  425 Function: sWriteTxPrioByte
  426 Purpose:  Write a byte of priority transmit data to a channel
  427 Call:     sWriteTxPrioByte(ChP,Data)
  428           CHANNEL_T *ChP; Ptr to channel structure
  429           Byte_t Data; The transmit data byte
  430 
  431 Return:   int: 1 if the bytes is successfully written, otherwise 0.
  432 
  433 Comments: The priority byte is transmitted before any data in the Tx FIFO.
  434 
  435 Warnings: No context switches are allowed while executing this function.
  436 */
  437 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  438 {
  439    Byte_t DWBuf[4];             /* buffer for double word writes */
  440    Word_t *WordPtr;          /* must be far because Win SS != DS */
  441 
  442    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  443    {
  444       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
  445       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
  446          return(0);                    /* nothing sent */
  447 
  448       WordPtr = (Word_t *)(&DWBuf[0]);
  449       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
  450 
  451       DWBuf[2] = Data;                 /* data byte value */
  452       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  453 
  454       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
  455 
  456       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  457       DWBuf[3] = 0;                    /* priority buffer pointer */
  458       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  459    }
  460    else                                /* write it to Tx FIFO */
  461    {
  462       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
  463    }
  464    return(1);                          /* 1 byte sent */
  465 }
  466 
  467 /***************************************************************************
  468 Function: sEnInterrupts
  469 Purpose:  Enable one or more interrupts for a channel
  470 Call:     sEnInterrupts(ChP,Flags)
  471           CHANNEL_T *ChP; Ptr to channel structure
  472           Word_t Flags: Interrupt enable flags, can be any combination
  473              of the following flags:
  474                 TXINT_EN:   Interrupt on Tx FIFO empty
  475                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  476                             sSetRxTrigger())
  477                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  478                 MCINT_EN:   Interrupt on modem input change
  479                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  480                             Interrupt Channel Register.
  481 Return:   void
  482 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  483           enabled.  If an interrupt enable flag is not set in Flags, that
  484           interrupt will not be changed.  Interrupts can be disabled with
  485           function sDisInterrupts().
  486 
  487           This function sets the appropriate bit for the channel in the AIOP's
  488           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  489           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  490 
  491           Interrupts must also be globally enabled before channel interrupts
  492           will be passed on to the host.  This is done with function
  493           sEnGlobalInt().
  494 
  495           In some cases it may be desirable to disable interrupts globally but
  496           enable channel interrupts.  This would allow the global interrupt
  497           status register to be used to determine which AIOPs need service.
  498 */
  499 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  500 {
  501    Byte_t Mask;                 /* Interrupt Mask Register */
  502 
  503    ChP->RxControl[2] |=
  504       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  505 
  506    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  507 
  508    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  509 
  510    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  511 
  512    if(Flags & CHANINT_EN)
  513    {
  514       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
  515       rp_writech1(ChP,_INT_MASK,Mask);
  516    }
  517 }
  518 
  519 /***************************************************************************
  520 Function: sDisInterrupts
  521 Purpose:  Disable one or more interrupts for a channel
  522 Call:     sDisInterrupts(ChP,Flags)
  523           CHANNEL_T *ChP; Ptr to channel structure
  524           Word_t Flags: Interrupt flags, can be any combination
  525              of the following flags:
  526                 TXINT_EN:   Interrupt on Tx FIFO empty
  527                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  528                             sSetRxTrigger())
  529                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  530                 MCINT_EN:   Interrupt on modem input change
  531                 CHANINT_EN: Disable channel interrupt signal to the
  532                             AIOP's Interrupt Channel Register.
  533 Return:   void
  534 Comments: If an interrupt flag is set in Flags, that interrupt will be
  535           disabled.  If an interrupt flag is not set in Flags, that
  536           interrupt will not be changed.  Interrupts can be enabled with
  537           function sEnInterrupts().
  538 
  539           This function clears the appropriate bit for the channel in the AIOP's
  540           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  541           this channel's bit from being set in the AIOP's Interrupt Channel
  542           Register.
  543 */
  544 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  545 {
  546    Byte_t Mask;                 /* Interrupt Mask Register */
  547 
  548    ChP->RxControl[2] &=
  549          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  550    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  551    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  552    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  553 
  554    if(Flags & CHANINT_EN)
  555    {
  556       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
  557       rp_writech1(ChP,_INT_MASK,Mask);
  558    }
  559 }
  560 
  561 /*********************************************************************
  562   Begin FreeBsd-specific driver code
  563 **********************************************************************/
  564 
  565 static timeout_t rpdtrwakeup;
  566 
  567 static  d_open_t        rpopen;
  568 static  d_close_t       rpclose;
  569 static  d_write_t       rpwrite;
  570 static  d_ioctl_t       rpioctl;
  571 
  572 #define CDEV_MAJOR      81
  573 struct cdevsw rp_cdevsw = {
  574         .d_open =       rpopen,
  575         .d_close =      rpclose,
  576         .d_read =       ttyread,
  577         .d_write =      rpwrite,
  578         .d_ioctl =      rpioctl,
  579         .d_poll =       ttypoll,
  580         .d_name =       "rp",
  581         .d_maj =        CDEV_MAJOR,
  582         .d_flags =      D_TTY,
  583 };
  584 
  585 static int      rp_num_ports_open = 0;
  586 static int      rp_ndevs = 0;
  587 static int      minor_to_unit[128];
  588 
  589 static int rp_num_ports[4];     /* Number of ports on each controller */
  590 
  591 #define _INLINE_ __inline
  592 #define POLL_INTERVAL 1
  593 
  594 #define CALLOUT_MASK            0x80
  595 #define CONTROL_MASK            0x60
  596 #define CONTROL_INIT_STATE      0x20
  597 #define CONTROL_LOCK_STATE      0x40
  598 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  599 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  600 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  601 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  602 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  603 
  604 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  605 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  606 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  607 
  608 static  struct  rp_port *p_rp_addr[4];
  609 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  610 #define rp_addr(unit)   (p_rp_addr[unit])
  611 #define rp_table(port)  (p_rp_table[port])
  612 
  613 /*
  614  * The top-level routines begin here
  615  */
  616 
  617 static  int     rpparam(struct tty *, struct termios *);
  618 static  void    rpstart(struct tty *);
  619 static  void    rpstop(struct tty *, int);
  620 static  void    rphardclose     (struct rp_port *);
  621 static  void    rp_disc_optim   (struct tty *tp, struct termios *t);
  622 
  623 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
  624                         CHANNEL_t *cp, unsigned int ChanStatus)
  625 {
  626         int     spl;
  627         unsigned        int     CharNStat;
  628         int     ToRecv, wRecv, ch, ttynocopy;
  629 
  630         ToRecv = sGetRxCnt(cp);
  631         if(ToRecv == 0)
  632                 return;
  633 
  634 /*      If status indicates there are errored characters in the
  635         FIFO, then enter status mode (a word in FIFO holds
  636         characters and status)
  637 */
  638 
  639         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  640                 if(!(ChanStatus & STATMODE)) {
  641                         ChanStatus |= STATMODE;
  642                         sEnRxStatusMode(cp);
  643                 }
  644         }
  645 /*
  646         if we previously entered status mode then read down the
  647         FIFO one word at a time, pulling apart the character and
  648         the status. Update error counters depending on status.
  649 */
  650         if(ChanStatus & STATMODE) {
  651                 while(ToRecv) {
  652                         if(tp->t_state & TS_TBLOCK) {
  653                                 break;
  654                         }
  655                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
  656                         ch = CharNStat & 0xff;
  657 
  658                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  659                                 ch |= TTY_FE;
  660                         else if (CharNStat & STMPARITYH)
  661                                 ch |= TTY_PE;
  662                         else if (CharNStat & STMRCVROVRH)
  663                                 rp->rp_overflows++;
  664 
  665                         (*linesw[tp->t_line].l_rint)(ch, tp);
  666                         ToRecv--;
  667                 }
  668 /*
  669         After emtying FIFO in status mode, turn off status mode
  670 */
  671 
  672                 if(sGetRxCnt(cp) == 0) {
  673                         sDisRxStatusMode(cp);
  674                 }
  675         } else {
  676                 /*
  677                  * Avoid the grotesquely inefficient lineswitch routine
  678                  * (ttyinput) in "raw" mode.  It usually takes about 450
  679                  * instructions (that's without canonical processing or echo!).
  680                  * slinput is reasonably fast (usually 40 instructions plus
  681                  * call overhead).
  682                  */
  683                 ToRecv = sGetRxCnt(cp);
  684                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
  685                         if ( ToRecv > RXFIFO_SIZE ) {
  686                                 ToRecv = RXFIFO_SIZE;
  687                         }
  688                         wRecv = ToRecv >> 1;
  689                         if ( wRecv ) {
  690                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
  691                         }
  692                         if ( ToRecv & 1 ) {
  693                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  694                         }
  695                         tk_nin += ToRecv;
  696                         tk_rawcc += ToRecv;
  697                         tp->t_rawcc += ToRecv;
  698                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
  699                         ttwakeup(tp);
  700                 } else {
  701                         while (ToRecv) {
  702                                 if(tp->t_state & TS_TBLOCK) {
  703                                         break;
  704                                 }
  705                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  706                                 spl = spltty();
  707                                 (*linesw[tp->t_line].l_rint)(ch, tp);
  708                                 splx(spl);
  709                                 ToRecv--;
  710                         }
  711                 }
  712         }
  713 }
  714 
  715 static _INLINE_ void rp_handle_port(struct rp_port *rp)
  716 {
  717         CHANNEL_t       *cp;
  718         struct  tty     *tp;
  719         unsigned        int     IntMask, ChanStatus;
  720 
  721         if(!rp)
  722                 return;
  723 
  724         cp = &rp->rp_channel;
  725         tp = rp->rp_tty;
  726         IntMask = sGetChanIntID(cp);
  727         IntMask = IntMask & rp->rp_intmask;
  728         ChanStatus = sGetChanStatus(cp);
  729         if(IntMask & RXF_TRIG)
  730                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  731                         rp_do_receive(rp, tp, cp, ChanStatus);
  732                 }
  733         if(IntMask & DELTA_CD) {
  734                 if(ChanStatus & CD_ACT) {
  735                         if(!(tp->t_state & TS_CARR_ON) ) {
  736                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  737                         }
  738                 } else {
  739                         if((tp->t_state & TS_CARR_ON)) {
  740                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  741                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
  742                                         rphardclose(rp);
  743                                 }
  744                         }
  745                 }
  746         }
  747 /*      oldcts = rp->rp_cts;
  748         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  749         if(oldcts != rp->rp_cts) {
  750                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  751         }
  752 */
  753 }
  754 
  755 static void rp_do_poll(void *not_used)
  756 {
  757         CONTROLLER_t    *ctl;
  758         struct rp_port  *rp;
  759         struct tty      *tp;
  760         int     unit, aiop, ch, line, count;
  761         unsigned char   CtlMask, AiopMask;
  762 
  763         for(unit = 0; unit < rp_ndevs; unit++) {
  764         rp = rp_addr(unit);
  765         ctl = rp->rp_ctlp;
  766         CtlMask = ctl->ctlmask(ctl);
  767         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  768                 if(CtlMask & 1) {
  769                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  770                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  771                                 if(AiopMask & 1) {
  772                                         line = (unit << 5) | (aiop << 3) | ch;
  773                                         rp = rp_table(line);
  774                                         rp_handle_port(rp);
  775                                 }
  776                         }
  777                 }
  778         }
  779 
  780         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  781                         line++, rp++) {
  782                 tp = rp->rp_tty;
  783                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
  784                         count = sGetTxCnt(&rp->rp_channel);
  785                         if(count == 0)
  786                                 tp->t_state &= ~(TS_BUSY);
  787                         if(!(tp->t_state & TS_TTSTOP) &&
  788                                 (count <= rp->rp_restart)) {
  789                                 (*linesw[tp->t_line].l_start)(tp);
  790                         }
  791                 }
  792         }
  793         }
  794         if(rp_num_ports_open)
  795                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
  796 }
  797 
  798 int
  799 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
  800 {
  801         int     oldspl, unit;
  802         int     num_chan;
  803         int     aiop, chan, port;
  804         int     ChanStatus, line, i, count;
  805         int     retval;
  806         struct  rp_port *rp;
  807         struct  tty     *tty;
  808         dev_t   *dev_nodes;
  809 
  810         unit = device_get_unit(ctlp->dev);
  811 
  812         printf("RocketPort%d (Version %s) %d ports.\n", unit,
  813                 RocketPortVersion, num_ports);
  814         rp_num_ports[unit] = num_ports;
  815 
  816         ctlp->rp = rp = (struct rp_port *)
  817                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
  818         if (rp == NULL) {
  819                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
  820                 retval = ENOMEM;
  821                 goto nogo;
  822         }
  823 
  824         count = unit * 32;      /* board times max ports per card SG */
  825         for(i=count;i < (count + rp_num_ports[unit]);i++)
  826                 minor_to_unit[i] = unit;
  827 
  828         bzero(rp, sizeof(struct rp_port) * num_ports);
  829         ctlp->tty = tty = (struct tty *)
  830                 malloc(sizeof(struct tty) * num_ports, M_TTYS,
  831                         M_NOWAIT | M_ZERO);
  832         if(tty == NULL) {
  833                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
  834                 retval = ENOMEM;
  835                 goto nogo;
  836         }
  837 
  838         oldspl = spltty();
  839         rp_addr(unit) = rp;
  840         splx(oldspl);
  841 
  842         dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
  843         if(ctlp->dev_nodes == NULL) {
  844                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
  845                 retval = ENOMEM;
  846                 goto nogo;
  847         }
  848 
  849         for (i = 0 ; i < rp_num_ports[unit] ; i++) {
  850                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
  851                                           UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
  852                                           i <= 9 ? '' + i : 'a' + i - 10);
  853                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
  854                                           UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
  855                                           i <= 9 ? '' + i : 'a' + i - 10);
  856                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
  857                                           UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
  858                                           i <= 9 ? '' + i : 'a' + i - 10);
  859                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
  860                                           UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
  861                                           i <= 9 ? '' + i : 'a' + i - 10);
  862                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
  863                                           UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
  864                                           i <= 9 ? '' + i : 'a' + i - 10);
  865                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
  866                                           UID_ROOT, GID_WHEEL, 0666, "cualR%c",
  867                                           i <= 9 ? '' + i : 'a' + i - 10);
  868         }
  869 
  870         port = 0;
  871         for(aiop=0; aiop < num_aiops; aiop++) {
  872                 num_chan = sGetAiopNumChan(ctlp, aiop);
  873                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
  874                         rp->rp_tty = tty;
  875                         rp->rp_port = port;
  876                         rp->rp_ctlp = ctlp;
  877                         rp->rp_unit = unit;
  878                         rp->rp_chan = chan;
  879                         rp->rp_aiop = aiop;
  880 
  881                         tty->t_line = 0;
  882         /*              tty->t_termios = deftermios;
  883         */
  884                         rp->dtr_wait = 3 * hz;
  885                         rp->it_in.c_iflag = 0;
  886                         rp->it_in.c_oflag = 0;
  887                         rp->it_in.c_cflag = TTYDEF_CFLAG;
  888                         rp->it_in.c_lflag = 0;
  889                         termioschars(&rp->it_in);
  890         /*              termioschars(&tty->t_termios);
  891         */
  892                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
  893                         rp->it_out = rp->it_in;
  894 
  895                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
  896                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
  897 #if notdef
  898                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  899 #endif /* notdef */
  900                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
  901                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
  902                                               unit, aiop, chan);
  903                                 retval = ENXIO;
  904                                 goto nogo;
  905                         }
  906                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  907                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
  908                         line = (unit << 5) | (aiop << 3) | chan;
  909                         rp_table(line) = rp;
  910                 }
  911         }
  912 
  913         rp_ndevs++;
  914         return (0);
  915 
  916 nogo:
  917         rp_releaseresource(ctlp);
  918 
  919         return (retval);
  920 }
  921 
  922 void
  923 rp_releaseresource(CONTROLLER_t *ctlp)
  924 {
  925         int i, s, unit;
  926 
  927         unit = device_get_unit(ctlp->dev);
  928 
  929         if (ctlp->rp != NULL) {
  930                 s = spltty();
  931                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
  932                         if (p_rp_addr[i] == ctlp->rp)
  933                                 p_rp_addr[i] = NULL;
  934                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
  935                         if (p_rp_table[i] == ctlp->rp)
  936                                 p_rp_table[i] = NULL;
  937                 splx(s);
  938                 free(ctlp->rp, M_DEVBUF);
  939                 ctlp->rp = NULL;
  940         }
  941         if (ctlp->tty != NULL) {
  942                 free(ctlp->tty, M_DEVBUF);
  943                 ctlp->tty = NULL;
  944         }
  945         if (ctlp->dev != NULL) {
  946                 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
  947                         destroy_dev(ctlp->dev_nodes[i]);
  948                 free(ctlp->dev_nodes, M_DEVBUF);
  949                 ctlp->dev = NULL;
  950         }
  951 }
  952 
  953 static int
  954 rpopen(dev, flag, mode, td)
  955         dev_t   dev;
  956         int     flag, mode;
  957         struct  thread  *td;
  958 {
  959         struct  rp_port *rp;
  960         int     unit, port, mynor, umynor, flags;  /* SG */
  961         struct  tty     *tp;
  962         int     oldspl, error;
  963         unsigned int    IntMask, ChanStatus;
  964 
  965 
  966    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
  967         port  = (minor(dev) & 0x1f);                /* SG */
  968         mynor = (port + umynor);                    /* SG */
  969         unit = minor_to_unit[mynor];
  970         if (rp_addr(unit) == NULL)
  971                 return (ENXIO);
  972         if(IS_CONTROL(dev))
  973                 return(0);
  974         rp = rp_addr(unit) + port;
  975 /*      rp->rp_tty = &rp_tty[rp->rp_port];
  976 */
  977         tp = rp->rp_tty;
  978         dev->si_tty = tp;
  979 
  980         oldspl = spltty();
  981 
  982 open_top:
  983         while(rp->state & ~SET_DTR) {
  984                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
  985                 if(error != 0)
  986                         goto out;
  987         }
  988 
  989         if(tp->t_state & TS_ISOPEN) {
  990                 if(IS_CALLOUT(dev)) {
  991                         if(!rp->active_out) {
  992                                 error = EBUSY;
  993                                 goto out;
  994                         }
  995                 } else {
  996                         if(rp->active_out) {
  997                                 if(flag & O_NONBLOCK) {
  998                                         error = EBUSY;
  999                                         goto out;
 1000                                 }
 1001                                 error = tsleep(&rp->active_out,
 1002                                         TTIPRI | PCATCH, "rpbi", 0);
 1003                                 if(error != 0)
 1004                                         goto out;
 1005                                 goto open_top;
 1006                         }
 1007                 }
 1008                 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
 1009                         splx(oldspl);
 1010                         error = EBUSY;
 1011                         goto out2;
 1012                 }
 1013         }
 1014         else {
 1015                 tp->t_dev = dev;
 1016                 tp->t_param = rpparam;
 1017                 tp->t_oproc = rpstart;
 1018                 tp->t_stop = rpstop;
 1019                 tp->t_line = 0;
 1020                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
 1021                 tp->t_ififosize = 512;
 1022                 tp->t_ispeedwat = (speed_t)-1;
 1023                 tp->t_ospeedwat = (speed_t)-1;
 1024                 flags = 0;
 1025                 flags |= SET_RTS;
 1026                 flags |= SET_DTR;
 1027                 rp->rp_channel.TxControl[3] =
 1028                         ((rp->rp_channel.TxControl[3]
 1029                         & ~(SET_RTS | SET_DTR)) | flags);
 1030                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1031                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1032                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1033                 sDisRxStatusMode(&rp->rp_channel);
 1034                 sFlushRxFIFO(&rp->rp_channel);
 1035                 sFlushTxFIFO(&rp->rp_channel);
 1036 
 1037                 sEnInterrupts(&rp->rp_channel,
 1038                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
 1039                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1040 
 1041                 sDisRxStatusMode(&rp->rp_channel);
 1042                 sClrTxXOFF(&rp->rp_channel);
 1043 
 1044 /*              sDisRTSFlowCtl(&rp->rp_channel);
 1045                 sDisCTSFlowCtl(&rp->rp_channel);
 1046 */
 1047                 sDisTxSoftFlowCtl(&rp->rp_channel);
 1048 
 1049                 sStartRxProcessor(&rp->rp_channel);
 1050 
 1051                 sEnRxFIFO(&rp->rp_channel);
 1052                 sEnTransmit(&rp->rp_channel);
 1053 
 1054 /*              sSetDTR(&rp->rp_channel);
 1055                 sSetRTS(&rp->rp_channel);
 1056 */
 1057 
 1058                 ++rp->wopeners;
 1059                 error = rpparam(tp, &tp->t_termios);
 1060                 --rp->wopeners;
 1061                 if(error != 0) {
 1062                         splx(oldspl);
 1063                         return(error);
 1064                 }
 1065 
 1066                 rp_num_ports_open++;
 1067 
 1068                 IntMask = sGetChanIntID(&rp->rp_channel);
 1069                 IntMask = IntMask & rp->rp_intmask;
 1070                 ChanStatus = sGetChanStatus(&rp->rp_channel);
 1071                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
 1072                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
 1073                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 1074                         }
 1075                 }
 1076 
 1077         if(rp_num_ports_open == 1)
 1078                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1079 
 1080         }
 1081 
 1082         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
 1083                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
 1084                 ++rp->wopeners;
 1085                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1086                                 "rpdcd", 0);
 1087                 --rp->wopeners;
 1088                 if(error != 0)
 1089                         goto out;
 1090                 goto open_top;
 1091         }
 1092         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1093 
 1094         rp_disc_optim(tp, &tp->t_termios);
 1095         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
 1096                 rp->active_out = TRUE;
 1097 
 1098 /*      if(rp_num_ports_open == 1)
 1099                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1100 */
 1101 out:
 1102         splx(oldspl);
 1103         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
 1104                 rphardclose(rp);
 1105         }
 1106 out2:
 1107         if (error == 0)
 1108                 device_busy(rp->rp_ctlp->dev);
 1109         return(error);
 1110 }
 1111 
 1112 static int
 1113 rpclose(dev, flag, mode, td)
 1114         dev_t   dev;
 1115         int     flag, mode;
 1116         struct  thread  *td;
 1117 {
 1118         int     oldspl, unit, mynor, umynor, port; /* SG */
 1119         struct  rp_port *rp;
 1120         struct  tty     *tp;
 1121         CHANNEL_t       *cp;
 1122 
 1123    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1124         port  = (minor(dev) & 0x1f);                /* SG */
 1125         mynor = (port + umynor);                    /* SG */
 1126    unit = minor_to_unit[mynor];                /* SG */
 1127 
 1128         if(IS_CONTROL(dev))
 1129                 return(0);
 1130         rp = rp_addr(unit) + port;
 1131         cp = &rp->rp_channel;
 1132         tp = rp->rp_tty;
 1133 
 1134         oldspl = spltty();
 1135         (*linesw[tp->t_line].l_close)(tp, flag);
 1136         rp_disc_optim(tp, &tp->t_termios);
 1137         rpstop(tp, FREAD | FWRITE);
 1138         rphardclose(rp);
 1139 
 1140         tp->t_state &= ~TS_BUSY;
 1141         ttyclose(tp);
 1142 
 1143         splx(oldspl);
 1144 
 1145         device_unbusy(rp->rp_ctlp->dev);
 1146 
 1147         return(0);
 1148 }
 1149 
 1150 static void
 1151 rphardclose(struct rp_port *rp)
 1152 {
 1153         int     mynor;
 1154         struct  tty     *tp;
 1155         CHANNEL_t       *cp;
 1156 
 1157         cp = &rp->rp_channel;
 1158         tp = rp->rp_tty;
 1159         mynor = MINOR_MAGIC(tp->t_dev);
 1160 
 1161         sFlushRxFIFO(cp);
 1162         sFlushTxFIFO(cp);
 1163         sDisTransmit(cp);
 1164         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1165         sDisRTSFlowCtl(cp);
 1166         sDisCTSFlowCtl(cp);
 1167         sDisTxSoftFlowCtl(cp);
 1168         sClrTxXOFF(cp);
 1169 
 1170         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1171                 sClrDTR(cp);
 1172         }
 1173         if(IS_CALLOUT(tp->t_dev)) {
 1174                 sClrDTR(cp);
 1175         }
 1176         if(rp->dtr_wait != 0) {
 1177                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
 1178                 rp->state |= ~SET_DTR;
 1179         }
 1180 
 1181         rp->active_out = FALSE;
 1182         wakeup(&rp->active_out);
 1183         wakeup(TSA_CARR_ON(tp));
 1184 }
 1185 
 1186 static
 1187 int
 1188 rpwrite(dev, uio, flag)
 1189         dev_t   dev;
 1190         struct  uio     *uio;
 1191         int     flag;
 1192 {
 1193         struct  rp_port *rp;
 1194         struct  tty     *tp;
 1195         int     unit, mynor, port, umynor, error = 0; /* SG */
 1196 
 1197    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1198         port  = (minor(dev) & 0x1f);                /* SG */
 1199         mynor = (port + umynor);                    /* SG */
 1200    unit = minor_to_unit[mynor];                /* SG */
 1201 
 1202         if(IS_CONTROL(dev))
 1203                 return(ENODEV);
 1204         rp = rp_addr(unit) + port;
 1205         tp = rp->rp_tty;
 1206         while(rp->rp_disable_writes) {
 1207                 rp->rp_waiting = 1;
 1208                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
 1209                 if (error)
 1210                         return(error);
 1211         }
 1212 
 1213         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
 1214         return error;
 1215 }
 1216 
 1217 static void
 1218 rpdtrwakeup(void *chan)
 1219 {
 1220         struct  rp_port *rp;
 1221 
 1222         rp = (struct rp_port *)chan;
 1223         rp->state &= SET_DTR;
 1224         wakeup(&rp->dtr_wait);
 1225 }
 1226 
 1227 static int
 1228 rpioctl(dev, cmd, data, flag, td)
 1229         dev_t   dev;
 1230         u_long  cmd;
 1231         caddr_t data;
 1232         int     flag;
 1233         struct  thread  *td;
 1234 {
 1235         struct rp_port  *rp;
 1236         CHANNEL_t       *cp;
 1237         struct tty      *tp;
 1238         int     unit, mynor, port, umynor;            /* SG */
 1239         int     oldspl;
 1240         int     error = 0;
 1241         int     arg, flags, result, ChanStatus;
 1242         struct  termios *t;
 1243 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1244         u_long  oldcmd;
 1245         struct  termios term;
 1246 #endif
 1247 
 1248    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1249         port  = (minor(dev) & 0x1f);                /* SG */
 1250         mynor = (port + umynor);                    /* SG */
 1251         unit = minor_to_unit[mynor];
 1252         rp = rp_addr(unit) + port;
 1253 
 1254         if(IS_CONTROL(dev)) {
 1255                 struct  termios *ct;
 1256 
 1257                 switch (IS_CONTROL(dev)) {
 1258                 case CONTROL_INIT_STATE:
 1259                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
 1260                         break;
 1261                 case CONTROL_LOCK_STATE:
 1262                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
 1263                         break;
 1264                 default:
 1265                         return(ENODEV);         /* /dev/nodev */
 1266                 }
 1267                 switch (cmd) {
 1268                 case TIOCSETA:
 1269                         error = suser(td);
 1270                         if(error != 0)
 1271                                 return(error);
 1272                         *ct = *(struct termios *)data;
 1273                         return(0);
 1274                 case TIOCGETA:
 1275                         *(struct termios *)data = *ct;
 1276                         return(0);
 1277                 case TIOCGETD:
 1278                         *(int *)data = TTYDISC;
 1279                         return(0);
 1280                 case TIOCGWINSZ:
 1281                         bzero(data, sizeof(struct winsize));
 1282                         return(0);
 1283                 default:
 1284                         return(ENOTTY);
 1285                 }
 1286         }
 1287 
 1288         tp = rp->rp_tty;
 1289         cp = &rp->rp_channel;
 1290 
 1291 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1292         term = tp->t_termios;
 1293         oldcmd = cmd;
 1294         error = ttsetcompat(tp, &cmd, data, &term);
 1295         if(error != 0)
 1296                 return(error);
 1297         if(cmd != oldcmd) {
 1298                 data = (caddr_t)&term;
 1299         }
 1300 #endif
 1301         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1302                 int     cc;
 1303                 struct  termios *dt = (struct termios *)data;
 1304                 struct  termios *lt = IS_CALLOUT(dev)
 1305                                         ? &rp->lt_out : &rp->lt_in;
 1306 
 1307                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1308                                 | (dt->c_iflag & ~lt->c_iflag);
 1309                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1310                                 | (dt->c_oflag & ~lt->c_oflag);
 1311                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1312                                 | (dt->c_cflag & ~lt->c_cflag);
 1313                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1314                                 | (dt->c_lflag & ~lt->c_lflag);
 1315                 for(cc = 0; cc < NCCS; ++cc)
 1316                         if(lt->c_cc[cc] != 0)
 1317                                 dt->c_cc[cc] = tp->t_cc[cc];
 1318                 if(lt->c_ispeed != 0)
 1319                         dt->c_ispeed = tp->t_ispeed;
 1320                 if(lt->c_ospeed != 0)
 1321                         dt->c_ospeed = tp->t_ospeed;
 1322         }
 1323 
 1324         t = &tp->t_termios;
 1325 
 1326         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
 1327         if(error != ENOIOCTL) {
 1328                 return(error);
 1329         }
 1330         oldspl = spltty();
 1331 
 1332         flags = rp->rp_channel.TxControl[3];
 1333 
 1334         error = ttioctl(tp, cmd, data, flag);
 1335         flags = rp->rp_channel.TxControl[3];
 1336         rp_disc_optim(tp, &tp->t_termios);
 1337         if(error != ENOIOCTL) {
 1338                 splx(oldspl);
 1339                 return(error);
 1340         }
 1341         switch(cmd) {
 1342         case TIOCSBRK:
 1343                 sSendBreak(&rp->rp_channel);
 1344                 break;
 1345 
 1346         case TIOCCBRK:
 1347                 sClrBreak(&rp->rp_channel);
 1348                 break;
 1349 
 1350         case TIOCSDTR:
 1351                 sSetDTR(&rp->rp_channel);
 1352                 sSetRTS(&rp->rp_channel);
 1353                 break;
 1354 
 1355         case TIOCCDTR:
 1356                 sClrDTR(&rp->rp_channel);
 1357                 break;
 1358 
 1359         case TIOCMSET:
 1360                 arg = *(int *) data;
 1361                 flags = 0;
 1362                 if(arg & TIOCM_RTS)
 1363                         flags |= SET_RTS;
 1364                 if(arg & TIOCM_DTR)
 1365                         flags |= SET_DTR;
 1366                 rp->rp_channel.TxControl[3] =
 1367                         ((rp->rp_channel.TxControl[3]
 1368                         & ~(SET_RTS | SET_DTR)) | flags);
 1369                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1370                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1371                 break;
 1372         case TIOCMBIS:
 1373                 arg = *(int *) data;
 1374                 flags = 0;
 1375                 if(arg & TIOCM_RTS)
 1376                         flags |= SET_RTS;
 1377                 if(arg & TIOCM_DTR)
 1378                         flags |= SET_DTR;
 1379                         rp->rp_channel.TxControl[3] |= flags;
 1380                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1381                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1382                 break;
 1383         case TIOCMBIC:
 1384                 arg = *(int *) data;
 1385                 flags = 0;
 1386                 if(arg & TIOCM_RTS)
 1387                         flags |= SET_RTS;
 1388                 if(arg & TIOCM_DTR)
 1389                         flags |= SET_DTR;
 1390                 rp->rp_channel.TxControl[3] &= ~flags;
 1391                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1392                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1393                 break;
 1394 
 1395 
 1396         case TIOCMGET:
 1397                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
 1398                 flags = rp->rp_channel.TxControl[3];
 1399                 result = TIOCM_LE; /* always on while open for some reason */
 1400                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
 1401                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
 1402                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
 1403                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
 1404                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
 1405 
 1406                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
 1407                 {
 1408                         result |= TIOCM_RTS;
 1409                 }
 1410 
 1411                 *(int *)data = result;
 1412                 break;
 1413         case TIOCMSDTRWAIT:
 1414                 error = suser(td);
 1415                 if(error != 0) {
 1416                         splx(oldspl);
 1417                         return(error);
 1418                 }
 1419                 rp->dtr_wait = *(int *)data * hz/100;
 1420                 break;
 1421         case TIOCMGDTRWAIT:
 1422                 *(int *)data = rp->dtr_wait * 100/hz;
 1423                 break;
 1424         default:
 1425                 splx(oldspl);
 1426                 return ENOTTY;
 1427         }
 1428         splx(oldspl);
 1429         return(0);
 1430 }
 1431 
 1432 static struct speedtab baud_table[] = {
 1433         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1434         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1435         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1436         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1437         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1438         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1439                                 {B57600, BRD57600},     {B76800, BRD76800},
 1440         {B115200, BRD115200},   {B230400, BRD230400},
 1441         {-1,    -1}
 1442 };
 1443 
 1444 static int
 1445 rpparam(tp, t)
 1446         struct tty *tp;
 1447         struct termios *t;
 1448 {
 1449         struct rp_port  *rp;
 1450         CHANNEL_t       *cp;
 1451         int     unit, mynor, port, umynor;               /* SG */
 1452         int     oldspl, cflag, iflag, oflag, lflag;
 1453         int     ospeed;
 1454 #ifdef RPCLOCAL
 1455         int     devshift;
 1456 #endif
 1457 
 1458 
 1459    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1460         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1461         mynor = (port + umynor);                          /* SG */
 1462 
 1463         unit = minor_to_unit[mynor];
 1464         rp = rp_addr(unit) + port;
 1465         cp = &rp->rp_channel;
 1466         oldspl = spltty();
 1467 
 1468         cflag = t->c_cflag;
 1469 #ifdef RPCLOCAL
 1470         devshift = umynor / 32;
 1471         devshift = 1 << devshift;
 1472         if ( devshift & RPCLOCAL ) {
 1473                 cflag |= CLOCAL;
 1474         }
 1475 #endif
 1476         iflag = t->c_iflag;
 1477         oflag = t->c_oflag;
 1478         lflag = t->c_lflag;
 1479 
 1480         ospeed = ttspeedtab(t->c_ispeed, baud_table);
 1481         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1482                 return(EINVAL);
 1483 
 1484         tp->t_ispeed = t->c_ispeed;
 1485         tp->t_ospeed = t->c_ospeed;
 1486         tp->t_cflag = cflag;
 1487         tp->t_iflag = iflag;
 1488         tp->t_oflag = oflag;
 1489         tp->t_lflag = lflag;
 1490 
 1491         if(t->c_ospeed == 0) {
 1492                 sClrDTR(cp);
 1493                 return(0);
 1494         }
 1495         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1496 
 1497         /* Set baud rate ----- we only pay attention to ispeed */
 1498         sSetDTR(cp);
 1499         sSetRTS(cp);
 1500         sSetBaud(cp, ospeed);
 1501 
 1502         if(cflag & CSTOPB) {
 1503                 sSetStop2(cp);
 1504         } else {
 1505                 sSetStop1(cp);
 1506         }
 1507 
 1508         if(cflag & PARENB) {
 1509                 sEnParity(cp);
 1510                 if(cflag & PARODD) {
 1511                         sSetOddParity(cp);
 1512                 } else {
 1513                         sSetEvenParity(cp);
 1514                 }
 1515         }
 1516         else {
 1517                 sDisParity(cp);
 1518         }
 1519         if((cflag & CSIZE) == CS8) {
 1520                 sSetData8(cp);
 1521                 rp->rp_imask = 0xFF;
 1522         } else {
 1523                 sSetData7(cp);
 1524                 rp->rp_imask = 0x7F;
 1525         }
 1526 
 1527         if(iflag & ISTRIP) {
 1528                 rp->rp_imask &= 0x7F;
 1529         }
 1530 
 1531         if(cflag & CLOCAL) {
 1532                 rp->rp_intmask &= ~DELTA_CD;
 1533         } else {
 1534                 rp->rp_intmask |= DELTA_CD;
 1535         }
 1536 
 1537         /* Put flow control stuff here */
 1538 
 1539         if(cflag & CCTS_OFLOW) {
 1540                 sEnCTSFlowCtl(cp);
 1541         } else {
 1542                 sDisCTSFlowCtl(cp);
 1543         }
 1544 
 1545         if(cflag & CRTS_IFLOW) {
 1546                 rp->rp_rts_iflow = 1;
 1547         } else {
 1548                 rp->rp_rts_iflow = 0;
 1549         }
 1550 
 1551         if(cflag & CRTS_IFLOW) {
 1552                 sEnRTSFlowCtl(cp);
 1553         } else {
 1554                 sDisRTSFlowCtl(cp);
 1555         }
 1556         rp_disc_optim(tp, t);
 1557 
 1558         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
 1559                 tp->t_state |= TS_CARR_ON;
 1560                 wakeup(TSA_CARR_ON(tp));
 1561         }
 1562 
 1563 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1564         flags = rp->rp_channel.TxControl[3];
 1565         if(flags & SET_DTR)
 1566         else
 1567         if(flags & SET_RTS)
 1568         else
 1569 */
 1570         splx(oldspl);
 1571 
 1572         return(0);
 1573 }
 1574 
 1575 static void
 1576 rp_disc_optim(tp, t)
 1577 struct  tty     *tp;
 1578 struct  termios *t;
 1579 {
 1580         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
 1581                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
 1582                 &&(!(t->c_iflag & PARMRK)
 1583                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
 1584                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
 1585                 && linesw[tp->t_line].l_rint == ttyinput)
 1586                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1587         else
 1588                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 1589 }
 1590 
 1591 static void
 1592 rpstart(tp)
 1593         struct tty *tp;
 1594 {
 1595         struct rp_port  *rp;
 1596         CHANNEL_t       *cp;
 1597         struct  clist   *qp;
 1598         int     unit, mynor, port, umynor;               /* SG */
 1599         char    flags;
 1600         int     spl, xmit_fifo_room;
 1601         int     count, wcount;
 1602 
 1603 
 1604    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1605         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1606         mynor = (port + umynor);                          /* SG */
 1607         unit = minor_to_unit[mynor];
 1608         rp = rp_addr(unit) + port;
 1609         cp = &rp->rp_channel;
 1610         flags = rp->rp_channel.TxControl[3];
 1611         spl = spltty();
 1612 
 1613         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1614                 ttwwakeup(tp);
 1615                 splx(spl);
 1616                 return;
 1617         }
 1618         if(rp->rp_xmit_stopped) {
 1619                 sEnTransmit(cp);
 1620                 rp->rp_xmit_stopped = 0;
 1621         }
 1622         count = sGetTxCnt(cp);
 1623 
 1624         if(tp->t_outq.c_cc == 0) {
 1625                 if((tp->t_state & TS_BUSY) && (count == 0)) {
 1626                         tp->t_state &= ~TS_BUSY;
 1627                 }
 1628                 ttwwakeup(tp);
 1629                 splx(spl);
 1630                 return;
 1631         }
 1632         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1633         qp = &tp->t_outq;
 1634         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1635                 tp->t_state |= TS_BUSY;
 1636                 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
 1637                 wcount = count >> 1;
 1638                 if ( wcount ) {
 1639                         rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
 1640                 }
 1641                 if ( count & 1 ) {
 1642                         rp_writech1(cp, sGetTxRxDataIO(cp),
 1643                                     ((unsigned char *)(rp->TxBuf))[(count-1)]);
 1644                 }
 1645         }
 1646         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
 1647 
 1648         ttwwakeup(tp);
 1649         splx(spl);
 1650 }
 1651 
 1652 static
 1653 void
 1654 rpstop(tp, flag)
 1655         register struct tty *tp;
 1656         int     flag;
 1657 {
 1658         struct rp_port  *rp;
 1659         CHANNEL_t       *cp;
 1660         int     unit, mynor, port, umynor;                  /* SG */
 1661         int     spl;
 1662 
 1663    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1664         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1665         mynor = (port + umynor);                          /* SG */
 1666         unit = minor_to_unit[mynor];
 1667         rp = rp_addr(unit) + port;
 1668         cp = &rp->rp_channel;
 1669 
 1670         spl = spltty();
 1671 
 1672         if(tp->t_state & TS_BUSY) {
 1673                 if((tp->t_state&TS_TTSTOP) == 0) {
 1674                         sFlushTxFIFO(cp);
 1675                 } else {
 1676                         if(rp->rp_xmit_stopped == 0) {
 1677                                 sDisTransmit(cp);
 1678                                 rp->rp_xmit_stopped = 1;
 1679                         }
 1680                 }
 1681         }
 1682         splx(spl);
 1683         rpstart(tp);
 1684 }

Cache object: e594eac8929cc341aecc0523182c9058


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.