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.3/sys/dev/rp/rp.c 132226 2004-07-15 20:47:41Z phk $");
   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 struct callout_handle rp_callout_handle;
  569 
  570 static  d_open_t        rpopen;
  571 static  d_close_t       rpclose;
  572 static  d_write_t       rpwrite;
  573 static  d_ioctl_t       rpioctl;
  574 
  575 struct cdevsw rp_cdevsw = {
  576         .d_version =    D_VERSION,
  577         .d_open =       rpopen,
  578         .d_close =      rpclose,
  579         .d_write =      rpwrite,
  580         .d_ioctl =      rpioctl,
  581         .d_name =       "rp",
  582         .d_flags =      D_TTY | D_NEEDGIANT,
  583 };
  584 
  585 static int      rp_num_ports_open = 0;
  586 static int      rp_ndevs = 0;
  587 static int      minor_to_unit[128];
  588 
  589 static int rp_num_ports[4];     /* Number of ports on each controller */
  590 
  591 #define POLL_INTERVAL 1
  592 
  593 #define CALLOUT_MASK            0x80
  594 #define CONTROL_MASK            0x60
  595 #define CONTROL_INIT_STATE      0x20
  596 #define CONTROL_LOCK_STATE      0x40
  597 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  598 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  599 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  600 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  601 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  602 
  603 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  604 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  605 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  606 
  607 static  struct  rp_port *p_rp_addr[4];
  608 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  609 #define rp_addr(unit)   (p_rp_addr[unit])
  610 #define rp_table(port)  (p_rp_table[port])
  611 
  612 /*
  613  * The top-level routines begin here
  614  */
  615 
  616 static  int     rpparam(struct tty *, struct termios *);
  617 static  void    rpstart(struct tty *);
  618 static  void    rpstop(struct tty *, int);
  619 static  void    rphardclose     (struct rp_port *);
  620 
  621 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
  622                         CHANNEL_t *cp, unsigned int ChanStatus)
  623 {
  624         int     spl;
  625         unsigned        int     CharNStat;
  626         int     ToRecv, wRecv, ch, ttynocopy;
  627 
  628         ToRecv = sGetRxCnt(cp);
  629         if(ToRecv == 0)
  630                 return;
  631 
  632 /*      If status indicates there are errored characters in the
  633         FIFO, then enter status mode (a word in FIFO holds
  634         characters and status)
  635 */
  636 
  637         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  638                 if(!(ChanStatus & STATMODE)) {
  639                         ChanStatus |= STATMODE;
  640                         sEnRxStatusMode(cp);
  641                 }
  642         }
  643 /*
  644         if we previously entered status mode then read down the
  645         FIFO one word at a time, pulling apart the character and
  646         the status. Update error counters depending on status.
  647 */
  648         if(ChanStatus & STATMODE) {
  649                 while(ToRecv) {
  650                         if(tp->t_state & TS_TBLOCK) {
  651                                 break;
  652                         }
  653                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
  654                         ch = CharNStat & 0xff;
  655 
  656                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  657                                 ch |= TTY_FE;
  658                         else if (CharNStat & STMPARITYH)
  659                                 ch |= TTY_PE;
  660                         else if (CharNStat & STMRCVROVRH)
  661                                 rp->rp_overflows++;
  662 
  663                         ttyld_rint(tp, ch);
  664                         ToRecv--;
  665                 }
  666 /*
  667         After emtying FIFO in status mode, turn off status mode
  668 */
  669 
  670                 if(sGetRxCnt(cp) == 0) {
  671                         sDisRxStatusMode(cp);
  672                 }
  673         } else {
  674                 /*
  675                  * Avoid the grotesquely inefficient lineswitch routine
  676                  * (ttyinput) in "raw" mode.  It usually takes about 450
  677                  * instructions (that's without canonical processing or echo!).
  678                  * slinput is reasonably fast (usually 40 instructions plus
  679                  * call overhead).
  680                  */
  681                 ToRecv = sGetRxCnt(cp);
  682                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
  683                         if ( ToRecv > RXFIFO_SIZE ) {
  684                                 ToRecv = RXFIFO_SIZE;
  685                         }
  686                         wRecv = ToRecv >> 1;
  687                         if ( wRecv ) {
  688                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
  689                         }
  690                         if ( ToRecv & 1 ) {
  691                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  692                         }
  693                         tk_nin += ToRecv;
  694                         tk_rawcc += ToRecv;
  695                         tp->t_rawcc += ToRecv;
  696                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
  697                         ttwakeup(tp);
  698                 } else {
  699                         while (ToRecv) {
  700                                 if(tp->t_state & TS_TBLOCK) {
  701                                         break;
  702                                 }
  703                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  704                                 spl = spltty();
  705                                 ttyld_rint(tp, ch);
  706                                 splx(spl);
  707                                 ToRecv--;
  708                         }
  709                 }
  710         }
  711 }
  712 
  713 static void rp_handle_port(struct rp_port *rp)
  714 {
  715         CHANNEL_t       *cp;
  716         struct  tty     *tp;
  717         unsigned        int     IntMask, ChanStatus;
  718 
  719         if(!rp)
  720                 return;
  721 
  722         cp = &rp->rp_channel;
  723         tp = rp->rp_tty;
  724         IntMask = sGetChanIntID(cp);
  725         IntMask = IntMask & rp->rp_intmask;
  726         ChanStatus = sGetChanStatus(cp);
  727         if(IntMask & RXF_TRIG)
  728                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  729                         rp_do_receive(rp, tp, cp, ChanStatus);
  730                 }
  731         if(IntMask & DELTA_CD) {
  732                 if(ChanStatus & CD_ACT) {
  733                         if(!(tp->t_state & TS_CARR_ON) ) {
  734                                 (void)ttyld_modem(tp, 1);
  735                         }
  736                 } else {
  737                         if((tp->t_state & TS_CARR_ON)) {
  738                                 (void)ttyld_modem(tp, 0);
  739                                 if(ttyld_modem(tp, 0) == 0) {
  740                                         rphardclose(rp);
  741                                 }
  742                         }
  743                 }
  744         }
  745 /*      oldcts = rp->rp_cts;
  746         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  747         if(oldcts != rp->rp_cts) {
  748                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  749         }
  750 */
  751 }
  752 
  753 static void rp_do_poll(void *not_used)
  754 {
  755         CONTROLLER_t    *ctl;
  756         struct rp_port  *rp;
  757         struct tty      *tp;
  758         int     unit, aiop, ch, line, count;
  759         unsigned char   CtlMask, AiopMask;
  760 
  761         for(unit = 0; unit < rp_ndevs; unit++) {
  762         rp = rp_addr(unit);
  763         ctl = rp->rp_ctlp;
  764         CtlMask = ctl->ctlmask(ctl);
  765         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  766                 if(CtlMask & 1) {
  767                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  768                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  769                                 if(AiopMask & 1) {
  770                                         line = (unit << 5) | (aiop << 3) | ch;
  771                                         rp = rp_table(line);
  772                                         rp_handle_port(rp);
  773                                 }
  774                         }
  775                 }
  776         }
  777 
  778         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  779                         line++, rp++) {
  780                 tp = rp->rp_tty;
  781                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
  782                         count = sGetTxCnt(&rp->rp_channel);
  783                         if(count == 0)
  784                                 tp->t_state &= ~(TS_BUSY);
  785                         if(!(tp->t_state & TS_TTSTOP) &&
  786                                 (count <= rp->rp_restart)) {
  787                                 ttyld_start(tp);
  788                         }
  789                 }
  790         }
  791         }
  792         if(rp_num_ports_open)
  793                 rp_callout_handle = timeout(rp_do_poll, 
  794                                             (void *)NULL, POLL_INTERVAL);
  795 }
  796 
  797 int
  798 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
  799 {
  800         int     oldspl, unit;
  801         int     num_chan;
  802         int     aiop, chan, port;
  803         int     ChanStatus, line, i, count;
  804         int     retval;
  805         struct  rp_port *rp;
  806         struct cdev **dev_nodes;
  807 
  808         unit = device_get_unit(ctlp->dev);
  809 
  810         printf("RocketPort%d (Version %s) %d ports.\n", unit,
  811                 RocketPortVersion, num_ports);
  812         rp_num_ports[unit] = num_ports;
  813         callout_handle_init(&rp_callout_handle);
  814 
  815         ctlp->rp = rp = (struct rp_port *)
  816                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
  817         if (rp == NULL) {
  818                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
  819                 retval = ENOMEM;
  820                 goto nogo;
  821         }
  822 
  823         count = unit * 32;      /* board times max ports per card SG */
  824         for(i=count;i < (count + rp_num_ports[unit]);i++)
  825                 minor_to_unit[i] = unit;
  826 
  827         bzero(rp, sizeof(struct rp_port) * num_ports);
  828         oldspl = spltty();
  829         rp_addr(unit) = rp;
  830         splx(oldspl);
  831 
  832         dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
  833         if(ctlp->dev_nodes == NULL) {
  834                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
  835                 retval = ENOMEM;
  836                 goto nogo;
  837         }
  838 
  839         for (i = 0 ; i < rp_num_ports[unit] ; i++) {
  840                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
  841                                           UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
  842                                           i <= 9 ? '' + i : 'a' + i - 10);
  843                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
  844                                           UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
  845                                           i <= 9 ? '' + i : 'a' + i - 10);
  846                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
  847                                           UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
  848                                           i <= 9 ? '' + i : 'a' + i - 10);
  849                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
  850                                           UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
  851                                           i <= 9 ? '' + i : 'a' + i - 10);
  852                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
  853                                           UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
  854                                           i <= 9 ? '' + i : 'a' + i - 10);
  855                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
  856                                           UID_ROOT, GID_WHEEL, 0666, "cualR%c",
  857                                           i <= 9 ? '' + i : 'a' + i - 10);
  858         }
  859 
  860         port = 0;
  861         for(aiop=0; aiop < num_aiops; aiop++) {
  862                 num_chan = sGetAiopNumChan(ctlp, aiop);
  863                 for(chan=0; chan < num_chan; chan++, port++, rp++) {
  864                         rp->rp_tty = ttymalloc(NULL);
  865                         rp->rp_port = port;
  866                         rp->rp_ctlp = ctlp;
  867                         rp->rp_unit = unit;
  868                         rp->rp_chan = chan;
  869                         rp->rp_aiop = aiop;
  870 
  871                         rp->rp_tty->t_line = 0;
  872         /*              tty->t_termios = deftermios;
  873         */
  874                         rp->it_in.c_iflag = 0;
  875                         rp->it_in.c_oflag = 0;
  876                         rp->it_in.c_cflag = TTYDEF_CFLAG;
  877                         rp->it_in.c_lflag = 0;
  878                         termioschars(&rp->it_in);
  879         /*              termioschars(&tty->t_termios);
  880         */
  881                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
  882                         rp->it_out = rp->it_in;
  883 
  884                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
  885                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
  886 #if notdef
  887                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  888 #endif /* notdef */
  889                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
  890                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
  891                                               unit, aiop, chan);
  892                                 retval = ENXIO;
  893                                 goto nogo;
  894                         }
  895                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  896                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
  897                         line = (unit << 5) | (aiop << 3) | chan;
  898                         rp_table(line) = rp;
  899                 }
  900         }
  901 
  902         rp_ndevs++;
  903         return (0);
  904 
  905 nogo:
  906         rp_releaseresource(ctlp);
  907 
  908         return (retval);
  909 }
  910 
  911 void
  912 rp_releaseresource(CONTROLLER_t *ctlp)
  913 {
  914         int i, s, unit;
  915         struct  rp_port *rp;
  916 
  917 
  918         unit = device_get_unit(ctlp->dev);
  919         if (rp_addr(unit) != NULL) {
  920                 for (i = 0; i < rp_num_ports[unit]; i++) {
  921                         rp = rp_addr(unit) + i;
  922                         s = ttyrel(rp->rp_tty);
  923                         if (s) {
  924                                 printf("Detaching with active tty (%d refs)!\n", s);
  925                         }
  926                 }
  927         }
  928 
  929         if (ctlp->rp != NULL) {
  930                 s = spltty();
  931                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
  932                         if (p_rp_addr[i] == ctlp->rp)
  933                                 p_rp_addr[i] = NULL;
  934                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
  935                         if (p_rp_table[i] == ctlp->rp)
  936                                 p_rp_table[i] = NULL;
  937                 splx(s);
  938                 free(ctlp->rp, M_DEVBUF);
  939                 ctlp->rp = NULL;
  940         }
  941         if (ctlp->dev != NULL) {
  942                 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
  943                         destroy_dev(ctlp->dev_nodes[i]);
  944                 free(ctlp->dev_nodes, M_DEVBUF);
  945                 ctlp->dev = NULL;
  946         }
  947 }
  948 
  949 void
  950 rp_untimeout(void)
  951 {
  952         untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
  953 }
  954 static int
  955 rpopen(dev, flag, mode, td)
  956         struct cdev *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(&tp->t_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)ttyld_modem(tp, 1);
 1075                         }
 1076                 }
 1077 
 1078         if(rp_num_ports_open == 1)
 1079                 rp_callout_handle = timeout(rp_do_poll, 
 1080                                             (void *)NULL, POLL_INTERVAL);
 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 = ttyld_open(tp, dev);
 1094 
 1095         ttyldoptim(tp);
 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         struct cdev *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         ttyld_close(tp, flag);
 1137         ttyldoptim(tp);
 1138         rphardclose(rp);
 1139 
 1140         tp->t_state &= ~TS_BUSY;
 1141         tty_close(tp);
 1142 
 1143         splx(oldspl);
 1144 
 1145         device_unbusy(rp->rp_ctlp->dev);
 1146 
 1147         return(0);
 1148 }
 1149 
 1150 static void
 1151 rphardclose(struct rp_port *rp)
 1152 {
 1153         int     mynor;
 1154         struct  tty     *tp;
 1155         CHANNEL_t       *cp;
 1156 
 1157         cp = &rp->rp_channel;
 1158         tp = rp->rp_tty;
 1159         mynor = MINOR_MAGIC(tp->t_dev);
 1160 
 1161         sFlushRxFIFO(cp);
 1162         sFlushTxFIFO(cp);
 1163         sDisTransmit(cp);
 1164         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1165         sDisRTSFlowCtl(cp);
 1166         sDisCTSFlowCtl(cp);
 1167         sDisTxSoftFlowCtl(cp);
 1168         sClrTxXOFF(cp);
 1169 
 1170         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1171                 sClrDTR(cp);
 1172         }
 1173         if(IS_CALLOUT(tp->t_dev)) {
 1174                 sClrDTR(cp);
 1175         }
 1176         if(tp->t_dtr_wait != 0) {
 1177                 timeout(rpdtrwakeup, rp, tp->t_dtr_wait);
 1178                 rp->state |= ~SET_DTR;
 1179         }
 1180 
 1181         rp->active_out = FALSE;
 1182         wakeup(&rp->active_out);
 1183         wakeup(TSA_CARR_ON(tp));
 1184 }
 1185 
 1186 static
 1187 int
 1188 rpwrite(dev, uio, flag)
 1189         struct cdev *dev;
 1190         struct  uio     *uio;
 1191         int     flag;
 1192 {
 1193         struct  rp_port *rp;
 1194         struct  tty     *tp;
 1195         int     unit, mynor, port, umynor, error = 0; /* SG */
 1196 
 1197    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1198         port  = (minor(dev) & 0x1f);                /* SG */
 1199         mynor = (port + umynor);                    /* SG */
 1200    unit = minor_to_unit[mynor];                /* SG */
 1201 
 1202         if(IS_CONTROL(dev))
 1203                 return(ENODEV);
 1204         rp = rp_addr(unit) + port;
 1205         tp = rp->rp_tty;
 1206         while(rp->rp_disable_writes) {
 1207                 rp->rp_waiting = 1;
 1208                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
 1209                 if (error)
 1210                         return(error);
 1211         }
 1212 
 1213         error = ttyld_write(tp, uio, flag);
 1214         return error;
 1215 }
 1216 
 1217 static void
 1218 rpdtrwakeup(void *chan)
 1219 {
 1220         struct  rp_port *rp;
 1221 
 1222         rp = (struct rp_port *)chan;
 1223         rp->state &= SET_DTR;
 1224         wakeup(&rp->rp_tty->t_dtr_wait);
 1225 }
 1226 
 1227 static int
 1228 rpioctl(dev, cmd, data, flag, td)
 1229         struct cdev *dev;
 1230         u_long  cmd;
 1231         caddr_t data;
 1232         int     flag;
 1233         struct  thread  *td;
 1234 {
 1235         struct rp_port  *rp;
 1236         CHANNEL_t       *cp;
 1237         struct tty      *tp;
 1238         int     unit, mynor, port, umynor;            /* SG */
 1239         int     oldspl;
 1240         int     error = 0;
 1241         int     arg, flags, result, ChanStatus;
 1242         struct  termios *t;
 1243 #ifndef BURN_BRIDGES
 1244 #if defined(COMPAT_43)
 1245         u_long  oldcmd;
 1246         struct  termios term;
 1247 #endif
 1248 #endif
 1249 
 1250    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1251         port  = (minor(dev) & 0x1f);                /* SG */
 1252         mynor = (port + umynor);                    /* SG */
 1253         unit = minor_to_unit[mynor];
 1254         rp = rp_addr(unit) + port;
 1255 
 1256         if(IS_CONTROL(dev)) {
 1257                 struct  termios *ct;
 1258 
 1259                 switch (IS_CONTROL(dev)) {
 1260                 case CONTROL_INIT_STATE:
 1261                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
 1262                         break;
 1263                 case CONTROL_LOCK_STATE:
 1264                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
 1265                         break;
 1266                 default:
 1267                         return(ENODEV);         /* /dev/nodev */
 1268                 }
 1269                 switch (cmd) {
 1270                 case TIOCSETA:
 1271                         error = suser(td);
 1272                         if(error != 0)
 1273                                 return(error);
 1274                         *ct = *(struct termios *)data;
 1275                         return(0);
 1276                 case TIOCGETA:
 1277                         *(struct termios *)data = *ct;
 1278                         return(0);
 1279                 case TIOCGETD:
 1280                         *(int *)data = TTYDISC;
 1281                         return(0);
 1282                 case TIOCGWINSZ:
 1283                         bzero(data, sizeof(struct winsize));
 1284                         return(0);
 1285                 default:
 1286                         return(ENOTTY);
 1287                 }
 1288         }
 1289 
 1290         tp = rp->rp_tty;
 1291         cp = &rp->rp_channel;
 1292 
 1293 #ifndef BURN_BRIDGES
 1294 #if defined(COMPAT_43)
 1295         term = tp->t_termios;
 1296         oldcmd = cmd;
 1297         error = ttsetcompat(tp, &cmd, data, &term);
 1298         if(error != 0)
 1299                 return(error);
 1300         if(cmd != oldcmd) {
 1301                 data = (caddr_t)&term;
 1302         }
 1303 #endif
 1304 #endif
 1305         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1306                 int     cc;
 1307                 struct  termios *dt = (struct termios *)data;
 1308                 struct  termios *lt = IS_CALLOUT(dev)
 1309                                         ? &rp->lt_out : &rp->lt_in;
 1310 
 1311                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1312                                 | (dt->c_iflag & ~lt->c_iflag);
 1313                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1314                                 | (dt->c_oflag & ~lt->c_oflag);
 1315                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1316                                 | (dt->c_cflag & ~lt->c_cflag);
 1317                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1318                                 | (dt->c_lflag & ~lt->c_lflag);
 1319                 for(cc = 0; cc < NCCS; ++cc)
 1320                         if(lt->c_cc[cc] != 0)
 1321                                 dt->c_cc[cc] = tp->t_cc[cc];
 1322                 if(lt->c_ispeed != 0)
 1323                         dt->c_ispeed = tp->t_ispeed;
 1324                 if(lt->c_ospeed != 0)
 1325                         dt->c_ospeed = tp->t_ospeed;
 1326         }
 1327 
 1328         t = &tp->t_termios;
 1329 
 1330         error = ttyioctl(dev, cmd, data, flag, td);
 1331         ttyldoptim(tp);
 1332         if(error != ENOTTY)
 1333                 return(error);
 1334         oldspl = spltty();
 1335 
 1336         flags = rp->rp_channel.TxControl[3];
 1337 
 1338         switch(cmd) {
 1339         case TIOCSBRK:
 1340                 sSendBreak(&rp->rp_channel);
 1341                 break;
 1342 
 1343         case TIOCCBRK:
 1344                 sClrBreak(&rp->rp_channel);
 1345                 break;
 1346 
 1347         case TIOCSDTR:
 1348                 sSetDTR(&rp->rp_channel);
 1349                 sSetRTS(&rp->rp_channel);
 1350                 break;
 1351 
 1352         case TIOCCDTR:
 1353                 sClrDTR(&rp->rp_channel);
 1354                 break;
 1355 
 1356         case TIOCMSET:
 1357                 arg = *(int *) data;
 1358                 flags = 0;
 1359                 if(arg & TIOCM_RTS)
 1360                         flags |= SET_RTS;
 1361                 if(arg & TIOCM_DTR)
 1362                         flags |= SET_DTR;
 1363                 rp->rp_channel.TxControl[3] =
 1364                         ((rp->rp_channel.TxControl[3]
 1365                         & ~(SET_RTS | SET_DTR)) | flags);
 1366                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1367                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1368                 break;
 1369         case TIOCMBIS:
 1370                 arg = *(int *) data;
 1371                 flags = 0;
 1372                 if(arg & TIOCM_RTS)
 1373                         flags |= SET_RTS;
 1374                 if(arg & TIOCM_DTR)
 1375                         flags |= SET_DTR;
 1376                         rp->rp_channel.TxControl[3] |= flags;
 1377                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1378                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1379                 break;
 1380         case TIOCMBIC:
 1381                 arg = *(int *) data;
 1382                 flags = 0;
 1383                 if(arg & TIOCM_RTS)
 1384                         flags |= SET_RTS;
 1385                 if(arg & TIOCM_DTR)
 1386                         flags |= SET_DTR;
 1387                 rp->rp_channel.TxControl[3] &= ~flags;
 1388                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1389                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1390                 break;
 1391 
 1392 
 1393         case TIOCMGET:
 1394                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
 1395                 flags = rp->rp_channel.TxControl[3];
 1396                 result = TIOCM_LE; /* always on while open for some reason */
 1397                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
 1398                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
 1399                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
 1400                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
 1401                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
 1402 
 1403                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
 1404                 {
 1405                         result |= TIOCM_RTS;
 1406                 }
 1407 
 1408                 *(int *)data = result;
 1409                 break;
 1410         default:
 1411                 splx(oldspl);
 1412                 return ENOTTY;
 1413         }
 1414         splx(oldspl);
 1415         return(0);
 1416 }
 1417 
 1418 static struct speedtab baud_table[] = {
 1419         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1420         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1421         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1422         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1423         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1424         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1425                                 {B57600, BRD57600},     {B76800, BRD76800},
 1426         {B115200, BRD115200},   {B230400, BRD230400},
 1427         {-1,    -1}
 1428 };
 1429 
 1430 static int
 1431 rpparam(tp, t)
 1432         struct tty *tp;
 1433         struct termios *t;
 1434 {
 1435         struct rp_port  *rp;
 1436         CHANNEL_t       *cp;
 1437         int     unit, mynor, port, umynor;               /* SG */
 1438         int     oldspl, cflag, iflag, oflag, lflag;
 1439         int     ospeed;
 1440 #ifdef RPCLOCAL
 1441         int     devshift;
 1442 #endif
 1443 
 1444 
 1445    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1446         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1447         mynor = (port + umynor);                          /* SG */
 1448 
 1449         unit = minor_to_unit[mynor];
 1450         rp = rp_addr(unit) + port;
 1451         cp = &rp->rp_channel;
 1452         oldspl = spltty();
 1453 
 1454         cflag = t->c_cflag;
 1455 #ifdef RPCLOCAL
 1456         devshift = umynor / 32;
 1457         devshift = 1 << devshift;
 1458         if ( devshift & RPCLOCAL ) {
 1459                 cflag |= CLOCAL;
 1460         }
 1461 #endif
 1462         iflag = t->c_iflag;
 1463         oflag = t->c_oflag;
 1464         lflag = t->c_lflag;
 1465 
 1466         ospeed = ttspeedtab(t->c_ispeed, baud_table);
 1467         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1468                 return(EINVAL);
 1469 
 1470         tp->t_ispeed = t->c_ispeed;
 1471         tp->t_ospeed = t->c_ospeed;
 1472         tp->t_cflag = cflag;
 1473         tp->t_iflag = iflag;
 1474         tp->t_oflag = oflag;
 1475         tp->t_lflag = lflag;
 1476 
 1477         if(t->c_ospeed == 0) {
 1478                 sClrDTR(cp);
 1479                 return(0);
 1480         }
 1481         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1482 
 1483         /* Set baud rate ----- we only pay attention to ispeed */
 1484         sSetDTR(cp);
 1485         sSetRTS(cp);
 1486         sSetBaud(cp, ospeed);
 1487 
 1488         if(cflag & CSTOPB) {
 1489                 sSetStop2(cp);
 1490         } else {
 1491                 sSetStop1(cp);
 1492         }
 1493 
 1494         if(cflag & PARENB) {
 1495                 sEnParity(cp);
 1496                 if(cflag & PARODD) {
 1497                         sSetOddParity(cp);
 1498                 } else {
 1499                         sSetEvenParity(cp);
 1500                 }
 1501         }
 1502         else {
 1503                 sDisParity(cp);
 1504         }
 1505         if((cflag & CSIZE) == CS8) {
 1506                 sSetData8(cp);
 1507                 rp->rp_imask = 0xFF;
 1508         } else {
 1509                 sSetData7(cp);
 1510                 rp->rp_imask = 0x7F;
 1511         }
 1512 
 1513         if(iflag & ISTRIP) {
 1514                 rp->rp_imask &= 0x7F;
 1515         }
 1516 
 1517         if(cflag & CLOCAL) {
 1518                 rp->rp_intmask &= ~DELTA_CD;
 1519         } else {
 1520                 rp->rp_intmask |= DELTA_CD;
 1521         }
 1522 
 1523         /* Put flow control stuff here */
 1524 
 1525         if(cflag & CCTS_OFLOW) {
 1526                 sEnCTSFlowCtl(cp);
 1527         } else {
 1528                 sDisCTSFlowCtl(cp);
 1529         }
 1530 
 1531         if(cflag & CRTS_IFLOW) {
 1532                 rp->rp_rts_iflow = 1;
 1533         } else {
 1534                 rp->rp_rts_iflow = 0;
 1535         }
 1536 
 1537         if(cflag & CRTS_IFLOW) {
 1538                 sEnRTSFlowCtl(cp);
 1539         } else {
 1540                 sDisRTSFlowCtl(cp);
 1541         }
 1542         ttyldoptim(tp);
 1543 
 1544         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
 1545                 tp->t_state |= TS_CARR_ON;
 1546                 wakeup(TSA_CARR_ON(tp));
 1547         }
 1548 
 1549 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1550         flags = rp->rp_channel.TxControl[3];
 1551         if(flags & SET_DTR)
 1552         else
 1553         if(flags & SET_RTS)
 1554         else
 1555 */
 1556         splx(oldspl);
 1557 
 1558         return(0);
 1559 }
 1560 
 1561 static void
 1562 rpstart(tp)
 1563         struct tty *tp;
 1564 {
 1565         struct rp_port  *rp;
 1566         CHANNEL_t       *cp;
 1567         struct  clist   *qp;
 1568         int     unit, mynor, port, umynor;               /* SG */
 1569         char    flags;
 1570         int     spl, xmit_fifo_room;
 1571         int     count, wcount;
 1572 
 1573 
 1574    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1575         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1576         mynor = (port + umynor);                          /* SG */
 1577         unit = minor_to_unit[mynor];
 1578         rp = rp_addr(unit) + port;
 1579         cp = &rp->rp_channel;
 1580         flags = rp->rp_channel.TxControl[3];
 1581         spl = spltty();
 1582 
 1583         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1584                 ttwwakeup(tp);
 1585                 splx(spl);
 1586                 return;
 1587         }
 1588         if(rp->rp_xmit_stopped) {
 1589                 sEnTransmit(cp);
 1590                 rp->rp_xmit_stopped = 0;
 1591         }
 1592         count = sGetTxCnt(cp);
 1593 
 1594         if(tp->t_outq.c_cc == 0) {
 1595                 if((tp->t_state & TS_BUSY) && (count == 0)) {
 1596                         tp->t_state &= ~TS_BUSY;
 1597                 }
 1598                 ttwwakeup(tp);
 1599                 splx(spl);
 1600                 return;
 1601         }
 1602         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1603         qp = &tp->t_outq;
 1604         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1605                 tp->t_state |= TS_BUSY;
 1606                 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
 1607                 wcount = count >> 1;
 1608                 if ( wcount ) {
 1609                         rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
 1610                 }
 1611                 if ( count & 1 ) {
 1612                         rp_writech1(cp, sGetTxRxDataIO(cp),
 1613                                     ((unsigned char *)(rp->TxBuf))[(count-1)]);
 1614                 }
 1615         }
 1616         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
 1617 
 1618         ttwwakeup(tp);
 1619         splx(spl);
 1620 }
 1621 
 1622 static
 1623 void
 1624 rpstop(tp, flag)
 1625         register struct tty *tp;
 1626         int     flag;
 1627 {
 1628         struct rp_port  *rp;
 1629         CHANNEL_t       *cp;
 1630         int     unit, mynor, port, umynor;                  /* SG */
 1631         int     spl;
 1632 
 1633    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1634         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1635         mynor = (port + umynor);                          /* SG */
 1636         unit = minor_to_unit[mynor];
 1637         rp = rp_addr(unit) + port;
 1638         cp = &rp->rp_channel;
 1639 
 1640         spl = spltty();
 1641 
 1642         if(tp->t_state & TS_BUSY) {
 1643                 if((tp->t_state&TS_TTSTOP) == 0) {
 1644                         sFlushTxFIFO(cp);
 1645                 } else {
 1646                         if(rp->rp_xmit_stopped == 0) {
 1647                                 sDisTransmit(cp);
 1648                                 rp->rp_xmit_stopped = 1;
 1649                         }
 1650                 }
 1651         }
 1652         splx(spl);
 1653         rpstart(tp);
 1654 }

Cache object: d71342080312e32a3e63287c10ce84fc


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