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

Cache object: 16e905e93ad92c180bf4f0eef5258bc1


[ 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.