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  * rp.c - for RocketPort FreeBSD
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/fcntl.h>
   43 #include <sys/malloc.h>
   44 #include <sys/tty.h>
   45 #include <sys/proc.h>
   46 #include <sys/dkstat.h>
   47 #include <sys/conf.h>
   48 #include <sys/kernel.h>
   49 #include <machine/resource.h>
   50 #include <machine/bus.h>
   51 #include <sys/bus.h>
   52 #include <sys/rman.h>
   53 
   54 #define ROCKET_C
   55 #include <dev/rp/rpreg.h>
   56 #include <dev/rp/rpvar.h>
   57 
   58 static const char RocketPortVersion[] = "3.02";
   59 
   60 static Byte_t RData[RDATASIZE] =
   61 {
   62    0x00, 0x09, 0xf6, 0x82,
   63    0x02, 0x09, 0x86, 0xfb,
   64    0x04, 0x09, 0x00, 0x0a,
   65    0x06, 0x09, 0x01, 0x0a,
   66    0x08, 0x09, 0x8a, 0x13,
   67    0x0a, 0x09, 0xc5, 0x11,
   68    0x0c, 0x09, 0x86, 0x85,
   69    0x0e, 0x09, 0x20, 0x0a,
   70    0x10, 0x09, 0x21, 0x0a,
   71    0x12, 0x09, 0x41, 0xff,
   72    0x14, 0x09, 0x82, 0x00,
   73    0x16, 0x09, 0x82, 0x7b,
   74    0x18, 0x09, 0x8a, 0x7d,
   75    0x1a, 0x09, 0x88, 0x81,
   76    0x1c, 0x09, 0x86, 0x7a,
   77    0x1e, 0x09, 0x84, 0x81,
   78    0x20, 0x09, 0x82, 0x7c,
   79    0x22, 0x09, 0x0a, 0x0a
   80 };
   81 
   82 static Byte_t RRegData[RREGDATASIZE]=
   83 {
   84    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
   85    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
   86    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
   87    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
   88    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
   89    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
   90    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
   91    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
   92    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
   93    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
   94    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
   95    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
   96    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
   97 };
   98 
   99 #if 0
  100 /* IRQ number to MUDBAC register 2 mapping */
  101 Byte_t sIRQMap[16] =
  102 {
  103    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  104 };
  105 #endif
  106 
  107 Byte_t rp_sBitMapClrTbl[8] =
  108 {
  109    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  110 };
  111 
  112 Byte_t rp_sBitMapSetTbl[8] =
  113 {
  114    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  115 };
  116 
  117 /* Actually not used */
  118 #if notdef
  119 struct termios deftermios = {
  120         TTYDEF_IFLAG,
  121         TTYDEF_OFLAG,
  122         TTYDEF_CFLAG,
  123         TTYDEF_LFLAG,
  124         { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
  125         _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
  126         CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
  127         TTYDEF_SPEED,
  128         TTYDEF_SPEED
  129 };
  130 #endif
  131 
  132 /***************************************************************************
  133 Function: sReadAiopID
  134 Purpose:  Read the AIOP idenfication number directly from an AIOP.
  135 Call:     sReadAiopID(CtlP, aiop)
  136           CONTROLLER_T *CtlP; Ptr to controller structure
  137           int aiop: AIOP index
  138 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  139                  is replace by an identifying number.
  140           Flag AIOPID_NULL if no valid AIOP is found
  141 Warnings: No context switches are allowed while executing this function.
  142 
  143 */
  144 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
  145 {
  146    Byte_t AiopID;               /* ID byte from AIOP */
  147 
  148    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
  149    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
  150    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
  151    if(AiopID == 0x06)
  152       return(1);
  153    else                                /* AIOP does not exist */
  154       return(-1);
  155 }
  156 
  157 /***************************************************************************
  158 Function: sReadAiopNumChan
  159 Purpose:  Read the number of channels available in an AIOP directly from
  160           an AIOP.
  161 Call:     sReadAiopNumChan(CtlP, aiop)
  162           CONTROLLER_T *CtlP; Ptr to controller structure
  163           int aiop: AIOP index
  164 Return:   int: The number of channels available
  165 Comments: The number of channels is determined by write/reads from identical
  166           offsets within the SRAM address spaces for channels 0 and 4.
  167           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  168           AIOP, otherwise it is an 8 channel.
  169 Warnings: No context switches are allowed while executing this function.
  170 */
  171 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
  172 {
  173    Word_t x, y;
  174 
  175    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  176    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
  177    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  178    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  179    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  180    if(x != y)  /* if different must be 8 chan */
  181       return(8);
  182    else
  183       return(4);
  184 }
  185 
  186 /***************************************************************************
  187 Function: sInitChan
  188 Purpose:  Initialization of a channel and channel structure
  189 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  190           CONTROLLER_T *CtlP; Ptr to controller structure
  191           CHANNEL_T *ChP; Ptr to channel structure
  192           int AiopNum; AIOP number within controller
  193           int ChanNum; Channel number within AIOP
  194 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  195                number exceeds number of channels available in AIOP.
  196 Comments: This function must be called before a channel can be used.
  197 Warnings: No range checking on any of the parameters is done.
  198 
  199           No context switches are allowed while executing this function.
  200 */
  201 int sInitChan(  CONTROLLER_T *CtlP,
  202                 CHANNEL_T *ChP,
  203                 int AiopNum,
  204                 int ChanNum)
  205 {
  206    int i, ChOff;
  207    Byte_t *ChR;
  208    static Byte_t R[4];
  209 
  210    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  211       return(FALSE);                   /* exceeds num chans in AIOP */
  212 
  213    /* Channel, AIOP, and controller identifiers */
  214    ChP->CtlP = CtlP;
  215    ChP->ChanID = CtlP->AiopID[AiopNum];
  216    ChP->AiopNum = AiopNum;
  217    ChP->ChanNum = ChanNum;
  218 
  219    /* Initialize the channel from the RData array */
  220    for(i=0; i < RDATASIZE; i+=4)
  221    {
  222       R[0] = RData[i];
  223       R[1] = RData[i+1] + 0x10 * ChanNum;
  224       R[2] = RData[i+2];
  225       R[3] = RData[i+3];
  226       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
  227    }
  228 
  229    ChR = ChP->R;
  230    for(i=0; i < RREGDATASIZE; i+=4)
  231    {
  232       ChR[i] = RRegData[i];
  233       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  234       ChR[i+2] = RRegData[i+2];
  235       ChR[i+3] = RRegData[i+3];
  236    }
  237 
  238    /* Indexed registers */
  239    ChOff = (Word_t)ChanNum * 0x1000;
  240 
  241    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  242    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  243    ChP->BaudDiv[2] = (Byte_t)BRD9600;
  244    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
  245    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
  246 
  247    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  248    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  249    ChP->TxControl[2] = 0;
  250    ChP->TxControl[3] = 0;
  251    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  252 
  253    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  254    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  255    ChP->RxControl[2] = 0;
  256    ChP->RxControl[3] = 0;
  257    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  258 
  259    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  260    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  261    ChP->TxEnables[2] = 0;
  262    ChP->TxEnables[3] = 0;
  263    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
  264 
  265    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  266    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  267    ChP->TxCompare[2] = 0;
  268    ChP->TxCompare[3] = 0;
  269    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
  270 
  271    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  272    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  273    ChP->TxReplace1[2] = 0;
  274    ChP->TxReplace1[3] = 0;
  275    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
  276 
  277    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  278    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  279    ChP->TxReplace2[2] = 0;
  280    ChP->TxReplace2[3] = 0;
  281    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
  282 
  283    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  284    ChP->TxFIFO = ChOff + _TX_FIFO;
  285 
  286    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  287    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  288    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  289    rp_writech2(ChP,_INDX_DATA,0);
  290    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  291    ChP->RxFIFO = ChOff + _RX_FIFO;
  292 
  293    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  294    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  295    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  296    rp_writech2(ChP,_INDX_DATA,0);
  297    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  298    rp_writech2(ChP,_INDX_DATA,0);
  299    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  300    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
  301    rp_writech1(ChP,_INDX_DATA,0);
  302    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  303    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
  304    rp_writech1(ChP,_INDX_DATA,0);
  305    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  306    sEnRxProcessor(ChP);                /* start the Rx processor */
  307 
  308    return(TRUE);
  309 }
  310 
  311 /***************************************************************************
  312 Function: sStopRxProcessor
  313 Purpose:  Stop the receive processor from processing a channel.
  314 Call:     sStopRxProcessor(ChP)
  315           CHANNEL_T *ChP; Ptr to channel structure
  316 
  317 Comments: The receive processor can be started again with sStartRxProcessor().
  318           This function causes the receive processor to skip over the
  319           stopped channel.  It does not stop it from processing other channels.
  320 
  321 Warnings: No context switches are allowed while executing this function.
  322 
  323           Do not leave the receive processor stopped for more than one
  324           character time.
  325 
  326           After calling this function a delay of 4 uS is required to ensure
  327           that the receive processor is no longer processing this channel.
  328 */
  329 void sStopRxProcessor(CHANNEL_T *ChP)
  330 {
  331    Byte_t R[4];
  332 
  333    R[0] = ChP->R[0];
  334    R[1] = ChP->R[1];
  335    R[2] = 0x0a;
  336    R[3] = ChP->R[3];
  337    rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
  338 }
  339 
  340 /***************************************************************************
  341 Function: sFlushRxFIFO
  342 Purpose:  Flush the Rx FIFO
  343 Call:     sFlushRxFIFO(ChP)
  344           CHANNEL_T *ChP; Ptr to channel structure
  345 Return:   void
  346 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  347           while it is being flushed the receive processor is stopped
  348           and the transmitter is disabled.  After these operations a
  349           4 uS delay is done before clearing the pointers to allow
  350           the receive processor to stop.  These items are handled inside
  351           this function.
  352 Warnings: No context switches are allowed while executing this function.
  353 */
  354 void sFlushRxFIFO(CHANNEL_T *ChP)
  355 {
  356    int i;
  357    Byte_t Ch;                   /* channel number within AIOP */
  358    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  359 
  360    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  361       return;                          /* don't need to flush */
  362 
  363    RxFIFOEnabled = FALSE;
  364    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  365    {
  366       RxFIFOEnabled = TRUE;
  367       sDisRxFIFO(ChP);                 /* disable it */
  368       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
  369          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
  370    }
  371    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  372    Ch = (Byte_t)sGetChanNum(ChP);
  373    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  374    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
  375    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  376    rp_writech2(ChP,_INDX_DATA,0);
  377    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  378    rp_writech2(ChP,_INDX_DATA,0);
  379    if(RxFIFOEnabled)
  380       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  381 }
  382 
  383 /***************************************************************************
  384 Function: sFlushTxFIFO
  385 Purpose:  Flush the Tx FIFO
  386 Call:     sFlushTxFIFO(ChP)
  387           CHANNEL_T *ChP; Ptr to channel structure
  388 Return:   void
  389 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  390           while it is being flushed the receive processor is stopped
  391           and the transmitter is disabled.  After these operations a
  392           4 uS delay is done before clearing the pointers to allow
  393           the receive processor to stop.  These items are handled inside
  394           this function.
  395 Warnings: No context switches are allowed while executing this function.
  396 */
  397 void sFlushTxFIFO(CHANNEL_T *ChP)
  398 {
  399    int i;
  400    Byte_t Ch;                   /* channel number within AIOP */
  401    int TxEnabled;                      /* TRUE if transmitter enabled */
  402 
  403    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  404       return;                          /* don't need to flush */
  405 
  406    TxEnabled = FALSE;
  407    if(ChP->TxControl[3] & TX_ENABLE)
  408    {
  409       TxEnabled = TRUE;
  410       sDisTransmit(ChP);               /* disable transmitter */
  411    }
  412    sStopRxProcessor(ChP);              /* stop Rx processor */
  413    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  414       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
  415    Ch = (Byte_t)sGetChanNum(ChP);
  416    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  417    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
  418    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  419    rp_writech2(ChP,_INDX_DATA,0);
  420    if(TxEnabled)
  421       sEnTransmit(ChP);                /* enable transmitter */
  422    sStartRxProcessor(ChP);             /* restart Rx processor */
  423 }
  424 
  425 /***************************************************************************
  426 Function: sWriteTxPrioByte
  427 Purpose:  Write a byte of priority transmit data to a channel
  428 Call:     sWriteTxPrioByte(ChP,Data)
  429           CHANNEL_T *ChP; Ptr to channel structure
  430           Byte_t Data; The transmit data byte
  431 
  432 Return:   int: 1 if the bytes is successfully written, otherwise 0.
  433 
  434 Comments: The priority byte is transmitted before any data in the Tx FIFO.
  435 
  436 Warnings: No context switches are allowed while executing this function.
  437 */
  438 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  439 {
  440    Byte_t DWBuf[4];             /* buffer for double word writes */
  441    Word_t *WordPtr;          /* must be far because Win SS != DS */
  442 
  443    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  444    {
  445       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
  446       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
  447          return(0);                    /* nothing sent */
  448 
  449       WordPtr = (Word_t *)(&DWBuf[0]);
  450       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
  451 
  452       DWBuf[2] = Data;                 /* data byte value */
  453       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  454 
  455       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
  456 
  457       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  458       DWBuf[3] = 0;                    /* priority buffer pointer */
  459       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  460    }
  461    else                                /* write it to Tx FIFO */
  462    {
  463       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
  464    }
  465    return(1);                          /* 1 byte sent */
  466 }
  467 
  468 /***************************************************************************
  469 Function: sEnInterrupts
  470 Purpose:  Enable one or more interrupts for a channel
  471 Call:     sEnInterrupts(ChP,Flags)
  472           CHANNEL_T *ChP; Ptr to channel structure
  473           Word_t Flags: Interrupt enable flags, can be any combination
  474              of the following flags:
  475                 TXINT_EN:   Interrupt on Tx FIFO empty
  476                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  477                             sSetRxTrigger())
  478                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  479                 MCINT_EN:   Interrupt on modem input change
  480                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  481                             Interrupt Channel Register.
  482 Return:   void
  483 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  484           enabled.  If an interrupt enable flag is not set in Flags, that
  485           interrupt will not be changed.  Interrupts can be disabled with
  486           function sDisInterrupts().
  487 
  488           This function sets the appropriate bit for the channel in the AIOP's
  489           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  490           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  491 
  492           Interrupts must also be globally enabled before channel interrupts
  493           will be passed on to the host.  This is done with function
  494           sEnGlobalInt().
  495 
  496           In some cases it may be desirable to disable interrupts globally but
  497           enable channel interrupts.  This would allow the global interrupt
  498           status register to be used to determine which AIOPs need service.
  499 */
  500 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  501 {
  502    Byte_t Mask;                 /* Interrupt Mask Register */
  503 
  504    ChP->RxControl[2] |=
  505       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  506 
  507    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  508 
  509    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  510 
  511    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  512 
  513    if(Flags & CHANINT_EN)
  514    {
  515       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
  516       rp_writech1(ChP,_INT_MASK,Mask);
  517    }
  518 }
  519 
  520 /***************************************************************************
  521 Function: sDisInterrupts
  522 Purpose:  Disable one or more interrupts for a channel
  523 Call:     sDisInterrupts(ChP,Flags)
  524           CHANNEL_T *ChP; Ptr to channel structure
  525           Word_t Flags: Interrupt flags, can be any combination
  526              of the following flags:
  527                 TXINT_EN:   Interrupt on Tx FIFO empty
  528                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  529                             sSetRxTrigger())
  530                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  531                 MCINT_EN:   Interrupt on modem input change
  532                 CHANINT_EN: Disable channel interrupt signal to the
  533                             AIOP's Interrupt Channel Register.
  534 Return:   void
  535 Comments: If an interrupt flag is set in Flags, that interrupt will be
  536           disabled.  If an interrupt flag is not set in Flags, that
  537           interrupt will not be changed.  Interrupts can be enabled with
  538           function sEnInterrupts().
  539 
  540           This function clears the appropriate bit for the channel in the AIOP's
  541           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  542           this channel's bit from being set in the AIOP's Interrupt Channel
  543           Register.
  544 */
  545 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  546 {
  547    Byte_t Mask;                 /* Interrupt Mask Register */
  548 
  549    ChP->RxControl[2] &=
  550          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  551    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  552    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  553    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  554 
  555    if(Flags & CHANINT_EN)
  556    {
  557       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
  558       rp_writech1(ChP,_INT_MASK,Mask);
  559    }
  560 }
  561 
  562 /*********************************************************************
  563   Begin FreeBsd-specific driver code
  564 **********************************************************************/
  565 
  566 static timeout_t rpdtrwakeup;
  567 
  568 static  d_open_t        rpopen;
  569 static  d_close_t       rpclose;
  570 static  d_write_t       rpwrite;
  571 static  d_ioctl_t       rpioctl;
  572 
  573 #define CDEV_MAJOR      81
  574 struct cdevsw rp_cdevsw = {
  575         /* open */      rpopen,
  576         /* close */     rpclose,
  577         /* read */      ttyread,
  578         /* write */     rpwrite,
  579         /* ioctl */     rpioctl,
  580         /* poll */      ttypoll,
  581         /* mmap */      nommap,
  582         /* strategy */  nostrategy,
  583         /* name */      "rp",
  584         /* maj */       CDEV_MAJOR,
  585         /* dump */      nodump,
  586         /* psize */     nopsize,
  587         /* flags */     D_TTY,
  588 };
  589 
  590 static int      rp_num_ports_open = 0;
  591 static int      rp_ndevs = 0;
  592 static int      minor_to_unit[128];
  593 
  594 static int rp_num_ports[4];     /* Number of ports on each controller */
  595 
  596 #define _INLINE_ __inline
  597 #define POLL_INTERVAL 1
  598 
  599 #define CALLOUT_MASK            0x80
  600 #define CONTROL_MASK            0x60
  601 #define CONTROL_INIT_STATE      0x20
  602 #define CONTROL_LOCK_STATE      0x40
  603 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  604 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  605 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  606 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  607 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  608 
  609 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  610 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  611 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  612 
  613 static  struct  rp_port *p_rp_addr[4];
  614 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  615 #define rp_addr(unit)   (p_rp_addr[unit])
  616 #define rp_table(port)  (p_rp_table[port])
  617 
  618 /*
  619  * The top-level routines begin here
  620  */
  621 
  622 static  int     rpparam __P((struct tty *, struct termios *));
  623 static  void    rpstart __P((struct tty *));
  624 static  void    rpstop __P((struct tty *, int));
  625 static  void    rphardclose     __P((struct rp_port *));
  626 static  void    rp_disc_optim   __P((struct tty *tp, struct termios *t));
  627 
  628 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
  629                         CHANNEL_t *cp, unsigned int ChanStatus)
  630 {
  631         int     spl;
  632         unsigned        int     CharNStat;
  633         int     ToRecv, wRecv, ch, ttynocopy;
  634 
  635         ToRecv = sGetRxCnt(cp);
  636         if(ToRecv == 0)
  637                 return;
  638 
  639 /*      If status indicates there are errored characters in the
  640         FIFO, then enter status mode (a word in FIFO holds
  641         characters and status)
  642 */
  643 
  644         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  645                 if(!(ChanStatus & STATMODE)) {
  646                         ChanStatus |= STATMODE;
  647                         sEnRxStatusMode(cp);
  648                 }
  649         }
  650 /*
  651         if we previously entered status mode then read down the
  652         FIFO one word at a time, pulling apart the character and
  653         the status. Update error counters depending on status.
  654 */
  655         if(ChanStatus & STATMODE) {
  656                 while(ToRecv) {
  657                         if(tp->t_state & TS_TBLOCK) {
  658                                 break;
  659                         }
  660                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
  661                         ch = CharNStat & 0xff;
  662 
  663                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  664                                 ch |= TTY_FE;
  665                         else if (CharNStat & STMPARITYH)
  666                                 ch |= TTY_PE;
  667                         else if (CharNStat & STMRCVROVRH)
  668                                 rp->rp_overflows++;
  669 
  670                         (*linesw[tp->t_line].l_rint)(ch, tp);
  671                         ToRecv--;
  672                 }
  673 /*
  674         After emtying FIFO in status mode, turn off status mode
  675 */
  676 
  677                 if(sGetRxCnt(cp) == 0) {
  678                         sDisRxStatusMode(cp);
  679                 }
  680         } else {
  681                 /*
  682                  * Avoid the grotesquely inefficient lineswitch routine
  683                  * (ttyinput) in "raw" mode.  It usually takes about 450
  684                  * instructions (that's without canonical processing or echo!).
  685                  * slinput is reasonably fast (usually 40 instructions plus
  686                  * call overhead).
  687                  */
  688                 ToRecv = sGetRxCnt(cp);
  689                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
  690                         if ( ToRecv > RXFIFO_SIZE ) {
  691                                 ToRecv = RXFIFO_SIZE;
  692                         }
  693                         wRecv = ToRecv >> 1;
  694                         if ( wRecv ) {
  695                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
  696                         }
  697                         if ( ToRecv & 1 ) {
  698                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  699                         }
  700                         tk_nin += ToRecv;
  701                         tk_rawcc += ToRecv;
  702                         tp->t_rawcc += ToRecv;
  703                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
  704                         ttwakeup(tp);
  705                 } else {
  706                         while (ToRecv) {
  707                                 if(tp->t_state & TS_TBLOCK) {
  708                                         break;
  709                                 }
  710                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  711                                 spl = spltty();
  712                                 (*linesw[tp->t_line].l_rint)(ch, tp);
  713                                 splx(spl);
  714                                 ToRecv--;
  715                         }
  716                 }
  717         }
  718 }
  719 
  720 static _INLINE_ void rp_handle_port(struct rp_port *rp)
  721 {
  722         CHANNEL_t       *cp;
  723         struct  tty     *tp;
  724         unsigned        int     IntMask, ChanStatus;
  725 
  726         if(!rp)
  727                 return;
  728 
  729         cp = &rp->rp_channel;
  730         tp = rp->rp_tty;
  731         IntMask = sGetChanIntID(cp);
  732         IntMask = IntMask & rp->rp_intmask;
  733         ChanStatus = sGetChanStatus(cp);
  734         if(IntMask & RXF_TRIG)
  735                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  736                         rp_do_receive(rp, tp, cp, ChanStatus);
  737                 }
  738         if(IntMask & DELTA_CD) {
  739                 if(ChanStatus & CD_ACT) {
  740                         if(!(tp->t_state & TS_CARR_ON) ) {
  741                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  742                         }
  743                 } else {
  744                         if((tp->t_state & TS_CARR_ON)) {
  745                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  746                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
  747                                         rphardclose(rp);
  748                                 }
  749                         }
  750                 }
  751         }
  752 /*      oldcts = rp->rp_cts;
  753         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  754         if(oldcts != rp->rp_cts) {
  755                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  756         }
  757 */
  758 }
  759 
  760 static void rp_do_poll(void *not_used)
  761 {
  762         CONTROLLER_t    *ctl;
  763         struct rp_port  *rp;
  764         struct tty      *tp;
  765         int     unit, aiop, ch, line, count;
  766         unsigned char   CtlMask, AiopMask;
  767 
  768         for(unit = 0; unit < rp_ndevs; unit++) {
  769         rp = rp_addr(unit);
  770         ctl = rp->rp_ctlp;
  771         CtlMask = ctl->ctlmask(ctl);
  772         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  773                 if(CtlMask & 1) {
  774                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  775                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  776                                 if(AiopMask & 1) {
  777                                         line = (unit << 5) | (aiop << 3) | ch;
  778                                         rp = rp_table(line);
  779                                         rp_handle_port(rp);
  780                                 }
  781                         }
  782                 }
  783         }
  784 
  785         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  786                         line++, rp++) {
  787                 tp = rp->rp_tty;
  788                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
  789                         count = sGetTxCnt(&rp->rp_channel);
  790                         if(count == 0)
  791                                 tp->t_state &= ~(TS_BUSY);
  792                         if(!(tp->t_state & TS_TTSTOP) &&
  793                                 (count <= rp->rp_restart)) {
  794                                 (*linesw[tp->t_line].l_start)(tp);
  795                         }
  796                 }
  797         }
  798         }
  799         if(rp_num_ports_open)
  800                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
  801 }
  802 
  803 int
  804 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
  805 {
  806         int     oldspl, unit;
  807         int     num_chan;
  808         int     aiop, chan, port;
  809         int     ChanStatus, line, i, count;
  810         int     retval;
  811         struct  rp_port *rp;
  812         struct  tty     *tty;
  813         dev_t   *dev_nodes;
  814 
  815         unit = device_get_unit(ctlp->dev);
  816 
  817         printf("RocketPort%d (Version %s) %d ports.\n", unit,
  818                 RocketPortVersion, num_ports);
  819         rp_num_ports[unit] = num_ports;
  820 
  821         ctlp->rp = rp = (struct rp_port *)
  822                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
  823         if (rp == NULL) {
  824                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
  825                 retval = ENOMEM;
  826                 goto nogo;
  827         }
  828 
  829         count = unit * 32;      /* board times max ports per card SG */
  830         for(i=count;i < (count + rp_num_ports[unit]);i++)
  831                 minor_to_unit[i] = unit;
  832 
  833         bzero(rp, sizeof(struct rp_port) * num_ports);
  834         ctlp->tty = tty = (struct tty *)
  835                 malloc(sizeof(struct tty) * num_ports, M_TTYS,
  836                         M_NOWAIT | M_ZERO);
  837         if(tty == NULL) {
  838                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
  839                 retval = ENOMEM;
  840                 goto nogo;
  841         }
  842 
  843         oldspl = spltty();
  844         rp_addr(unit) = rp;
  845         splx(oldspl);
  846 
  847         dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
  848         if(ctlp->dev_nodes == NULL) {
  849                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
  850                 retval = ENOMEM;
  851                 goto nogo;
  852         }
  853 
  854         for (i = 0 ; i < rp_num_ports[unit] ; i++) {
  855                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
  856                                           UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
  857                                           i <= 9 ? '' + i : 'a' + i - 10);
  858                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
  859                                           UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
  860                                           i <= 9 ? '' + i : 'a' + i - 10);
  861                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
  862                                           UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
  863                                           i <= 9 ? '' + i : 'a' + i - 10);
  864                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
  865                                           UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
  866                                           i <= 9 ? '' + i : 'a' + i - 10);
  867                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
  868                                           UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
  869                                           i <= 9 ? '' + i : 'a' + i - 10);
  870                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
  871                                           UID_ROOT, GID_WHEEL, 0666, "cualR%c",
  872                                           i <= 9 ? '' + i : 'a' + i - 10);
  873         }
  874 
  875         port = 0;
  876         for(aiop=0; aiop < num_aiops; aiop++) {
  877                 num_chan = sGetAiopNumChan(ctlp, aiop);
  878                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
  879                         rp->rp_tty = tty;
  880                         rp->rp_port = port;
  881                         rp->rp_ctlp = ctlp;
  882                         rp->rp_unit = unit;
  883                         rp->rp_chan = chan;
  884                         rp->rp_aiop = aiop;
  885 
  886                         tty->t_line = 0;
  887         /*              tty->t_termios = deftermios;
  888         */
  889                         rp->dtr_wait = 3 * hz;
  890                         rp->it_in.c_iflag = 0;
  891                         rp->it_in.c_oflag = 0;
  892                         rp->it_in.c_cflag = TTYDEF_CFLAG;
  893                         rp->it_in.c_lflag = 0;
  894                         termioschars(&rp->it_in);
  895         /*              termioschars(&tty->t_termios);
  896         */
  897                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
  898                         rp->it_out = rp->it_in;
  899 
  900                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
  901                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
  902 #if notdef
  903                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  904 #endif /* notdef */
  905                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
  906                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
  907                                               unit, aiop, chan);
  908                                 retval = ENXIO;
  909                                 goto nogo;
  910                         }
  911                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  912                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
  913                         line = (unit << 5) | (aiop << 3) | chan;
  914                         rp_table(line) = rp;
  915                 }
  916         }
  917 
  918         rp_ndevs++;
  919         return (0);
  920 
  921 nogo:
  922         rp_releaseresource(ctlp);
  923 
  924         return (retval);
  925 }
  926 
  927 void
  928 rp_releaseresource(CONTROLLER_t *ctlp)
  929 {
  930         int i, s, unit;
  931 
  932         unit = device_get_unit(ctlp->dev);
  933 
  934         if (ctlp->rp != NULL) {
  935                 s = spltty();
  936                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
  937                         if (p_rp_addr[i] == ctlp->rp)
  938                                 p_rp_addr[i] = NULL;
  939                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
  940                         if (p_rp_table[i] == ctlp->rp)
  941                                 p_rp_table[i] = NULL;
  942                 splx(s);
  943                 free(ctlp->rp, M_DEVBUF);
  944                 ctlp->rp = NULL;
  945         }
  946         if (ctlp->tty != NULL) {
  947                 free(ctlp->tty, M_DEVBUF);
  948                 ctlp->tty = NULL;
  949         }
  950         if (ctlp->dev != NULL) {
  951                 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
  952                         destroy_dev(ctlp->dev_nodes[i]);
  953                 free(ctlp->dev_nodes, M_DEVBUF);
  954                 ctlp->dev = NULL;
  955         }
  956 }
  957 
  958 int
  959 rpopen(dev, flag, mode, p)
  960         dev_t   dev;
  961         int     flag, mode;
  962         struct  proc    *p;
  963 {
  964         struct  rp_port *rp;
  965         int     unit, port, mynor, umynor, flags;  /* SG */
  966         struct  tty     *tp;
  967         int     oldspl, error;
  968         unsigned int    IntMask, ChanStatus;
  969 
  970 
  971    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
  972         port  = (minor(dev) & 0x1f);                /* SG */
  973         mynor = (port + umynor);                    /* SG */
  974         unit = minor_to_unit[mynor];
  975         if (rp_addr(unit) == NULL)
  976                 return (ENXIO);
  977         if(IS_CONTROL(dev))
  978                 return(0);
  979         rp = rp_addr(unit) + port;
  980 /*      rp->rp_tty = &rp_tty[rp->rp_port];
  981 */
  982         tp = rp->rp_tty;
  983         dev->si_tty = tp;
  984 
  985         oldspl = spltty();
  986 
  987 open_top:
  988         while(rp->state & ~SET_DTR) {
  989                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
  990                 if(error != 0)
  991                         goto out;
  992         }
  993 
  994         if(tp->t_state & TS_ISOPEN) {
  995                 if(IS_CALLOUT(dev)) {
  996                         if(!rp->active_out) {
  997                                 error = EBUSY;
  998                                 goto out;
  999                         }
 1000                 } else {
 1001                         if(rp->active_out) {
 1002                                 if(flag & O_NONBLOCK) {
 1003                                         error = EBUSY;
 1004                                         goto out;
 1005                                 }
 1006                                 error = tsleep(&rp->active_out,
 1007                                         TTIPRI | PCATCH, "rpbi", 0);
 1008                                 if(error != 0)
 1009                                         goto out;
 1010                                 goto open_top;
 1011                         }
 1012                 }
 1013                 if(tp->t_state & TS_XCLUDE && suser(p) != 0) {
 1014                         splx(oldspl);
 1015                         error = EBUSY;
 1016                         goto out2;
 1017                 }
 1018         }
 1019         else {
 1020                 tp->t_dev = dev;
 1021                 tp->t_param = rpparam;
 1022                 tp->t_oproc = rpstart;
 1023                 tp->t_stop = rpstop;
 1024                 tp->t_line = 0;
 1025                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
 1026                 tp->t_ififosize = 512;
 1027                 tp->t_ispeedwat = (speed_t)-1;
 1028                 tp->t_ospeedwat = (speed_t)-1;
 1029                 flags = 0;
 1030                 flags |= SET_RTS;
 1031                 flags |= SET_DTR;
 1032                 rp->rp_channel.TxControl[3] =
 1033                         ((rp->rp_channel.TxControl[3]
 1034                         & ~(SET_RTS | SET_DTR)) | flags);
 1035                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1036                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1037                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1038                 sDisRxStatusMode(&rp->rp_channel);
 1039                 sFlushRxFIFO(&rp->rp_channel);
 1040                 sFlushTxFIFO(&rp->rp_channel);
 1041 
 1042                 sEnInterrupts(&rp->rp_channel,
 1043                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
 1044                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1045 
 1046                 sDisRxStatusMode(&rp->rp_channel);
 1047                 sClrTxXOFF(&rp->rp_channel);
 1048 
 1049 /*              sDisRTSFlowCtl(&rp->rp_channel);
 1050                 sDisCTSFlowCtl(&rp->rp_channel);
 1051 */
 1052                 sDisTxSoftFlowCtl(&rp->rp_channel);
 1053 
 1054                 sStartRxProcessor(&rp->rp_channel);
 1055 
 1056                 sEnRxFIFO(&rp->rp_channel);
 1057                 sEnTransmit(&rp->rp_channel);
 1058 
 1059 /*              sSetDTR(&rp->rp_channel);
 1060                 sSetRTS(&rp->rp_channel);
 1061 */
 1062 
 1063                 ++rp->wopeners;
 1064                 error = rpparam(tp, &tp->t_termios);
 1065                 --rp->wopeners;
 1066                 if(error != 0) {
 1067                         splx(oldspl);
 1068                         return(error);
 1069                 }
 1070 
 1071                 rp_num_ports_open++;
 1072 
 1073                 IntMask = sGetChanIntID(&rp->rp_channel);
 1074                 IntMask = IntMask & rp->rp_intmask;
 1075                 ChanStatus = sGetChanStatus(&rp->rp_channel);
 1076                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
 1077                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
 1078                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 1079                         }
 1080                 }
 1081 
 1082         if(rp_num_ports_open == 1)
 1083                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1084 
 1085         }
 1086 
 1087         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
 1088                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
 1089                 ++rp->wopeners;
 1090                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1091                                 "rpdcd", 0);
 1092                 --rp->wopeners;
 1093                 if(error != 0)
 1094                         goto out;
 1095                 goto open_top;
 1096         }
 1097         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1098 
 1099         rp_disc_optim(tp, &tp->t_termios);
 1100         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
 1101                 rp->active_out = TRUE;
 1102 
 1103 /*      if(rp_num_ports_open == 1)
 1104                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1105 */
 1106 out:
 1107         splx(oldspl);
 1108         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
 1109                 rphardclose(rp);
 1110         }
 1111 out2:
 1112         if (error == 0)
 1113                 device_busy(rp->rp_ctlp->dev);
 1114         return(error);
 1115 }
 1116 
 1117 int
 1118 rpclose(dev, flag, mode, p)
 1119         dev_t   dev;
 1120         int     flag, mode;
 1121         struct  proc    *p;
 1122 {
 1123         int     oldspl, unit, mynor, umynor, port; /* SG */
 1124         struct  rp_port *rp;
 1125         struct  tty     *tp;
 1126         CHANNEL_t       *cp;
 1127 
 1128    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1129         port  = (minor(dev) & 0x1f);                /* SG */
 1130         mynor = (port + umynor);                    /* SG */
 1131    unit = minor_to_unit[mynor];                /* SG */
 1132 
 1133         if(IS_CONTROL(dev))
 1134                 return(0);
 1135         rp = rp_addr(unit) + port;
 1136         cp = &rp->rp_channel;
 1137         tp = rp->rp_tty;
 1138 
 1139         oldspl = spltty();
 1140         (*linesw[tp->t_line].l_close)(tp, flag);
 1141         rp_disc_optim(tp, &tp->t_termios);
 1142         rpstop(tp, FREAD | FWRITE);
 1143         rphardclose(rp);
 1144 
 1145         tp->t_state &= ~TS_BUSY;
 1146         ttyclose(tp);
 1147 
 1148         splx(oldspl);
 1149 
 1150         device_unbusy(rp->rp_ctlp->dev);
 1151 
 1152         return(0);
 1153 }
 1154 
 1155 static void
 1156 rphardclose(struct rp_port *rp)
 1157 {
 1158         int     mynor;
 1159         struct  tty     *tp;
 1160         CHANNEL_t       *cp;
 1161 
 1162         cp = &rp->rp_channel;
 1163         tp = rp->rp_tty;
 1164         mynor = MINOR_MAGIC(tp->t_dev);
 1165 
 1166         sFlushRxFIFO(cp);
 1167         sFlushTxFIFO(cp);
 1168         sDisTransmit(cp);
 1169         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1170         sDisRTSFlowCtl(cp);
 1171         sDisCTSFlowCtl(cp);
 1172         sDisTxSoftFlowCtl(cp);
 1173         sClrTxXOFF(cp);
 1174 
 1175         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1176                 sClrDTR(cp);
 1177         }
 1178         if(IS_CALLOUT(tp->t_dev)) {
 1179                 sClrDTR(cp);
 1180         }
 1181         if(rp->dtr_wait != 0) {
 1182                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
 1183                 rp->state |= ~SET_DTR;
 1184         }
 1185 
 1186         rp->active_out = FALSE;
 1187         wakeup(&rp->active_out);
 1188         wakeup(TSA_CARR_ON(tp));
 1189 }
 1190 
 1191 static
 1192 int
 1193 rpwrite(dev, uio, flag)
 1194         dev_t   dev;
 1195         struct  uio     *uio;
 1196         int     flag;
 1197 {
 1198         struct  rp_port *rp;
 1199         struct  tty     *tp;
 1200         int     unit, mynor, port, umynor, error = 0; /* SG */
 1201 
 1202    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1203         port  = (minor(dev) & 0x1f);                /* SG */
 1204         mynor = (port + umynor);                    /* SG */
 1205    unit = minor_to_unit[mynor];                /* SG */
 1206 
 1207         if(IS_CONTROL(dev))
 1208                 return(ENODEV);
 1209         rp = rp_addr(unit) + port;
 1210         tp = rp->rp_tty;
 1211         while(rp->rp_disable_writes) {
 1212                 rp->rp_waiting = 1;
 1213                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
 1214                 if (error)
 1215                         return(error);
 1216         }
 1217 
 1218         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
 1219         return error;
 1220 }
 1221 
 1222 static void
 1223 rpdtrwakeup(void *chan)
 1224 {
 1225         struct  rp_port *rp;
 1226 
 1227         rp = (struct rp_port *)chan;
 1228         rp->state &= SET_DTR;
 1229         wakeup(&rp->dtr_wait);
 1230 }
 1231 
 1232 int
 1233 rpioctl(dev, cmd, data, flag, p)
 1234         dev_t   dev;
 1235         u_long  cmd;
 1236         caddr_t data;
 1237         int     flag;
 1238         struct  proc    *p;
 1239 {
 1240         struct rp_port  *rp;
 1241         CHANNEL_t       *cp;
 1242         struct tty      *tp;
 1243         int     unit, mynor, port, umynor;            /* SG */
 1244         int     oldspl;
 1245         int     error = 0;
 1246         int     arg, flags, result, ChanStatus;
 1247         struct  termios *t;
 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(p);
 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, p);
 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(p);
 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: 4ce1cede1c18a38e8186100e162eba5d


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