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/8.2/sys/dev/rp/rp.c 196405 2009-08-20 20:23:28Z jhb $");
   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/endian.h>
   46 #include <sys/fcntl.h>
   47 #include <sys/malloc.h>
   48 #include <sys/serial.h>
   49 #include <sys/tty.h>
   50 #include <sys/conf.h>
   51 #include <sys/kernel.h>
   52 #include <machine/resource.h>
   53 #include <machine/bus.h>
   54 #include <sys/bus.h>
   55 #include <sys/rman.h>
   56 
   57 #define ROCKET_C
   58 #include <dev/rp/rpreg.h>
   59 #include <dev/rp/rpvar.h>
   60 
   61 static const char RocketPortVersion[] = "3.02";
   62 
   63 static Byte_t RData[RDATASIZE] =
   64 {
   65    0x00, 0x09, 0xf6, 0x82,
   66    0x02, 0x09, 0x86, 0xfb,
   67    0x04, 0x09, 0x00, 0x0a,
   68    0x06, 0x09, 0x01, 0x0a,
   69    0x08, 0x09, 0x8a, 0x13,
   70    0x0a, 0x09, 0xc5, 0x11,
   71    0x0c, 0x09, 0x86, 0x85,
   72    0x0e, 0x09, 0x20, 0x0a,
   73    0x10, 0x09, 0x21, 0x0a,
   74    0x12, 0x09, 0x41, 0xff,
   75    0x14, 0x09, 0x82, 0x00,
   76    0x16, 0x09, 0x82, 0x7b,
   77    0x18, 0x09, 0x8a, 0x7d,
   78    0x1a, 0x09, 0x88, 0x81,
   79    0x1c, 0x09, 0x86, 0x7a,
   80    0x1e, 0x09, 0x84, 0x81,
   81    0x20, 0x09, 0x82, 0x7c,
   82    0x22, 0x09, 0x0a, 0x0a
   83 };
   84 
   85 static Byte_t RRegData[RREGDATASIZE]=
   86 {
   87    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
   88    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
   89    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
   90    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
   91    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
   92    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
   93    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
   94    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
   95    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
   96    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
   97    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
   98    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
   99    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
  100 };
  101 
  102 #if 0
  103 /* IRQ number to MUDBAC register 2 mapping */
  104 Byte_t sIRQMap[16] =
  105 {
  106    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  107 };
  108 #endif
  109 
  110 Byte_t rp_sBitMapClrTbl[8] =
  111 {
  112    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  113 };
  114 
  115 Byte_t rp_sBitMapSetTbl[8] =
  116 {
  117    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  118 };
  119 
  120 static void rpfree(void *);
  121 
  122 /***************************************************************************
  123 Function: sReadAiopID
  124 Purpose:  Read the AIOP idenfication number directly from an AIOP.
  125 Call:     sReadAiopID(CtlP, aiop)
  126           CONTROLLER_T *CtlP; Ptr to controller structure
  127           int aiop: AIOP index
  128 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  129                  is replace by an identifying number.
  130           Flag AIOPID_NULL if no valid AIOP is found
  131 Warnings: No context switches are allowed while executing this function.
  132 
  133 */
  134 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
  135 {
  136    Byte_t AiopID;               /* ID byte from AIOP */
  137 
  138    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
  139    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
  140    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
  141    if(AiopID == 0x06)
  142       return(1);
  143    else                                /* AIOP does not exist */
  144       return(-1);
  145 }
  146 
  147 /***************************************************************************
  148 Function: sReadAiopNumChan
  149 Purpose:  Read the number of channels available in an AIOP directly from
  150           an AIOP.
  151 Call:     sReadAiopNumChan(CtlP, aiop)
  152           CONTROLLER_T *CtlP; Ptr to controller structure
  153           int aiop: AIOP index
  154 Return:   int: The number of channels available
  155 Comments: The number of channels is determined by write/reads from identical
  156           offsets within the SRAM address spaces for channels 0 and 4.
  157           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  158           AIOP, otherwise it is an 8 channel.
  159 Warnings: No context switches are allowed while executing this function.
  160 */
  161 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
  162 {
  163    Word_t x, y;
  164 
  165    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  166    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
  167    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  168    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  169    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  170    if(x != y)  /* if different must be 8 chan */
  171       return(8);
  172    else
  173       return(4);
  174 }
  175 
  176 /***************************************************************************
  177 Function: sInitChan
  178 Purpose:  Initialization of a channel and channel structure
  179 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  180           CONTROLLER_T *CtlP; Ptr to controller structure
  181           CHANNEL_T *ChP; Ptr to channel structure
  182           int AiopNum; AIOP number within controller
  183           int ChanNum; Channel number within AIOP
  184 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  185                number exceeds number of channels available in AIOP.
  186 Comments: This function must be called before a channel can be used.
  187 Warnings: No range checking on any of the parameters is done.
  188 
  189           No context switches are allowed while executing this function.
  190 */
  191 int sInitChan(  CONTROLLER_T *CtlP,
  192                 CHANNEL_T *ChP,
  193                 int AiopNum,
  194                 int ChanNum)
  195 {
  196    int i, ChOff;
  197    Byte_t *ChR;
  198    static Byte_t R[4];
  199 
  200    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  201       return(FALSE);                   /* exceeds num chans in AIOP */
  202 
  203    /* Channel, AIOP, and controller identifiers */
  204    ChP->CtlP = CtlP;
  205    ChP->ChanID = CtlP->AiopID[AiopNum];
  206    ChP->AiopNum = AiopNum;
  207    ChP->ChanNum = ChanNum;
  208 
  209    /* Initialize the channel from the RData array */
  210    for(i=0; i < RDATASIZE; i+=4)
  211    {
  212       R[0] = RData[i];
  213       R[1] = RData[i+1] + 0x10 * ChanNum;
  214       R[2] = RData[i+2];
  215       R[3] = RData[i+3];
  216       rp_writech4(ChP,_INDX_ADDR,le32dec(R));
  217    }
  218 
  219    ChR = ChP->R;
  220    for(i=0; i < RREGDATASIZE; i+=4)
  221    {
  222       ChR[i] = RRegData[i];
  223       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  224       ChR[i+2] = RRegData[i+2];
  225       ChR[i+3] = RRegData[i+3];
  226    }
  227 
  228    /* Indexed registers */
  229    ChOff = (Word_t)ChanNum * 0x1000;
  230 
  231    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  232    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  233    ChP->BaudDiv[2] = (Byte_t)BRD9600;
  234    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
  235    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv));
  236 
  237    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  238    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  239    ChP->TxControl[2] = 0;
  240    ChP->TxControl[3] = 0;
  241    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
  242 
  243    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  244    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  245    ChP->RxControl[2] = 0;
  246    ChP->RxControl[3] = 0;
  247    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
  248 
  249    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  250    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  251    ChP->TxEnables[2] = 0;
  252    ChP->TxEnables[3] = 0;
  253    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables));
  254 
  255    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  256    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  257    ChP->TxCompare[2] = 0;
  258    ChP->TxCompare[3] = 0;
  259    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare));
  260 
  261    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  262    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  263    ChP->TxReplace1[2] = 0;
  264    ChP->TxReplace1[3] = 0;
  265    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1));
  266 
  267    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  268    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  269    ChP->TxReplace2[2] = 0;
  270    ChP->TxReplace2[3] = 0;
  271    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2));
  272 
  273    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  274    ChP->TxFIFO = ChOff + _TX_FIFO;
  275 
  276    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  277    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  278    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  279    rp_writech2(ChP,_INDX_DATA,0);
  280    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  281    ChP->RxFIFO = ChOff + _RX_FIFO;
  282 
  283    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  284    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  285    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  286    rp_writech2(ChP,_INDX_DATA,0);
  287    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  288    rp_writech2(ChP,_INDX_DATA,0);
  289    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  290    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
  291    rp_writech1(ChP,_INDX_DATA,0);
  292    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  293    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
  294    rp_writech1(ChP,_INDX_DATA,0);
  295    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  296    sEnRxProcessor(ChP);                /* start the Rx processor */
  297 
  298    return(TRUE);
  299 }
  300 
  301 /***************************************************************************
  302 Function: sStopRxProcessor
  303 Purpose:  Stop the receive processor from processing a channel.
  304 Call:     sStopRxProcessor(ChP)
  305           CHANNEL_T *ChP; Ptr to channel structure
  306 
  307 Comments: The receive processor can be started again with sStartRxProcessor().
  308           This function causes the receive processor to skip over the
  309           stopped channel.  It does not stop it from processing other channels.
  310 
  311 Warnings: No context switches are allowed while executing this function.
  312 
  313           Do not leave the receive processor stopped for more than one
  314           character time.
  315 
  316           After calling this function a delay of 4 uS is required to ensure
  317           that the receive processor is no longer processing this channel.
  318 */
  319 void sStopRxProcessor(CHANNEL_T *ChP)
  320 {
  321    Byte_t R[4];
  322 
  323    R[0] = ChP->R[0];
  324    R[1] = ChP->R[1];
  325    R[2] = 0x0a;
  326    R[3] = ChP->R[3];
  327    rp_writech4(ChP,_INDX_ADDR,le32dec(R));
  328 }
  329 
  330 /***************************************************************************
  331 Function: sFlushRxFIFO
  332 Purpose:  Flush the Rx FIFO
  333 Call:     sFlushRxFIFO(ChP)
  334           CHANNEL_T *ChP; Ptr to channel structure
  335 Return:   void
  336 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  337           while it is being flushed the receive processor is stopped
  338           and the transmitter is disabled.  After these operations a
  339           4 uS delay is done before clearing the pointers to allow
  340           the receive processor to stop.  These items are handled inside
  341           this function.
  342 Warnings: No context switches are allowed while executing this function.
  343 */
  344 void sFlushRxFIFO(CHANNEL_T *ChP)
  345 {
  346    int i;
  347    Byte_t Ch;                   /* channel number within AIOP */
  348    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  349 
  350    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  351       return;                          /* don't need to flush */
  352 
  353    RxFIFOEnabled = FALSE;
  354    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  355    {
  356       RxFIFOEnabled = TRUE;
  357       sDisRxFIFO(ChP);                 /* disable it */
  358       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
  359          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
  360    }
  361    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  362    Ch = (Byte_t)sGetChanNum(ChP);
  363    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  364    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
  365    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  366    rp_writech2(ChP,_INDX_DATA,0);
  367    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  368    rp_writech2(ChP,_INDX_DATA,0);
  369    if(RxFIFOEnabled)
  370       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  371 }
  372 
  373 /***************************************************************************
  374 Function: sFlushTxFIFO
  375 Purpose:  Flush the Tx FIFO
  376 Call:     sFlushTxFIFO(ChP)
  377           CHANNEL_T *ChP; Ptr to channel structure
  378 Return:   void
  379 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  380           while it is being flushed the receive processor is stopped
  381           and the transmitter is disabled.  After these operations a
  382           4 uS delay is done before clearing the pointers to allow
  383           the receive processor to stop.  These items are handled inside
  384           this function.
  385 Warnings: No context switches are allowed while executing this function.
  386 */
  387 void sFlushTxFIFO(CHANNEL_T *ChP)
  388 {
  389    int i;
  390    Byte_t Ch;                   /* channel number within AIOP */
  391    int TxEnabled;                      /* TRUE if transmitter enabled */
  392 
  393    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  394       return;                          /* don't need to flush */
  395 
  396    TxEnabled = FALSE;
  397    if(ChP->TxControl[3] & TX_ENABLE)
  398    {
  399       TxEnabled = TRUE;
  400       sDisTransmit(ChP);               /* disable transmitter */
  401    }
  402    sStopRxProcessor(ChP);              /* stop Rx processor */
  403    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  404       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
  405    Ch = (Byte_t)sGetChanNum(ChP);
  406    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  407    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
  408    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  409    rp_writech2(ChP,_INDX_DATA,0);
  410    if(TxEnabled)
  411       sEnTransmit(ChP);                /* enable transmitter */
  412    sStartRxProcessor(ChP);             /* restart Rx processor */
  413 }
  414 
  415 /***************************************************************************
  416 Function: sWriteTxPrioByte
  417 Purpose:  Write a byte of priority transmit data to a channel
  418 Call:     sWriteTxPrioByte(ChP,Data)
  419           CHANNEL_T *ChP; Ptr to channel structure
  420           Byte_t Data; The transmit data byte
  421 
  422 Return:   int: 1 if the bytes is successfully written, otherwise 0.
  423 
  424 Comments: The priority byte is transmitted before any data in the Tx FIFO.
  425 
  426 Warnings: No context switches are allowed while executing this function.
  427 */
  428 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  429 {
  430    Byte_t DWBuf[4];             /* buffer for double word writes */
  431 
  432    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  433    {
  434       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
  435       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
  436          return(0);                    /* nothing sent */
  437 
  438       le16enc(DWBuf,ChP->TxPrioBuf);   /* data byte address */
  439 
  440       DWBuf[2] = Data;                 /* data byte value */
  441       DWBuf[3] = 0;                    /* priority buffer pointer */
  442       rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
  443 
  444       le16enc(DWBuf,ChP->TxPrioCnt);   /* Tx priority count address */
  445 
  446       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  447       DWBuf[3] = 0;                    /* priority buffer pointer */
  448       rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
  449    }
  450    else                                /* write it to Tx FIFO */
  451    {
  452       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
  453    }
  454    return(1);                          /* 1 byte sent */
  455 }
  456 
  457 /***************************************************************************
  458 Function: sEnInterrupts
  459 Purpose:  Enable one or more interrupts for a channel
  460 Call:     sEnInterrupts(ChP,Flags)
  461           CHANNEL_T *ChP; Ptr to channel structure
  462           Word_t Flags: Interrupt enable flags, can be any combination
  463              of the following flags:
  464                 TXINT_EN:   Interrupt on Tx FIFO empty
  465                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  466                             sSetRxTrigger())
  467                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  468                 MCINT_EN:   Interrupt on modem input change
  469                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  470                             Interrupt Channel Register.
  471 Return:   void
  472 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  473           enabled.  If an interrupt enable flag is not set in Flags, that
  474           interrupt will not be changed.  Interrupts can be disabled with
  475           function sDisInterrupts().
  476 
  477           This function sets the appropriate bit for the channel in the AIOP's
  478           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  479           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  480 
  481           Interrupts must also be globally enabled before channel interrupts
  482           will be passed on to the host.  This is done with function
  483           sEnGlobalInt().
  484 
  485           In some cases it may be desirable to disable interrupts globally but
  486           enable channel interrupts.  This would allow the global interrupt
  487           status register to be used to determine which AIOPs need service.
  488 */
  489 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  490 {
  491    Byte_t Mask;                 /* Interrupt Mask Register */
  492 
  493    ChP->RxControl[2] |=
  494       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  495 
  496    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
  497 
  498    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  499 
  500    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
  501 
  502    if(Flags & CHANINT_EN)
  503    {
  504       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
  505       rp_writech1(ChP,_INT_MASK,Mask);
  506    }
  507 }
  508 
  509 /***************************************************************************
  510 Function: sDisInterrupts
  511 Purpose:  Disable one or more interrupts for a channel
  512 Call:     sDisInterrupts(ChP,Flags)
  513           CHANNEL_T *ChP; Ptr to channel structure
  514           Word_t Flags: Interrupt flags, can be any combination
  515              of the following flags:
  516                 TXINT_EN:   Interrupt on Tx FIFO empty
  517                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  518                             sSetRxTrigger())
  519                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  520                 MCINT_EN:   Interrupt on modem input change
  521                 CHANINT_EN: Disable channel interrupt signal to the
  522                             AIOP's Interrupt Channel Register.
  523 Return:   void
  524 Comments: If an interrupt flag is set in Flags, that interrupt will be
  525           disabled.  If an interrupt flag is not set in Flags, that
  526           interrupt will not be changed.  Interrupts can be enabled with
  527           function sEnInterrupts().
  528 
  529           This function clears the appropriate bit for the channel in the AIOP's
  530           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  531           this channel's bit from being set in the AIOP's Interrupt Channel
  532           Register.
  533 */
  534 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  535 {
  536    Byte_t Mask;                 /* Interrupt Mask Register */
  537 
  538    ChP->RxControl[2] &=
  539          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  540    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
  541    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  542    rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
  543 
  544    if(Flags & CHANINT_EN)
  545    {
  546       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
  547       rp_writech1(ChP,_INT_MASK,Mask);
  548    }
  549 }
  550 
  551 /*********************************************************************
  552   Begin FreeBsd-specific driver code
  553 **********************************************************************/
  554 
  555 struct callout_handle rp_callout_handle;
  556 
  557 static int      rp_num_ports_open = 0;
  558 static int      rp_ndevs = 0;
  559 
  560 static int rp_num_ports[4];     /* Number of ports on each controller */
  561 
  562 #define POLL_INTERVAL 1
  563 
  564 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  565 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  566 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  567 
  568 static  struct  rp_port *p_rp_addr[4];
  569 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  570 #define rp_addr(unit)   (p_rp_addr[unit])
  571 #define rp_table(port)  (p_rp_table[port])
  572 
  573 /*
  574  * The top-level routines begin here
  575  */
  576 
  577 static  void    rpclose(struct tty *tp);
  578 static  void    rphardclose(struct tty *tp);
  579 static  int     rpmodem(struct tty *, int, int);
  580 static  int     rpparam(struct tty *, struct termios *);
  581 static  void    rpstart(struct tty *);
  582 static  int     rpioctl(struct tty *, u_long, caddr_t, struct thread *);
  583 static  int     rpopen(struct tty *);
  584 
  585 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
  586                         CHANNEL_t *cp, unsigned int ChanStatus)
  587 {
  588         unsigned        int     CharNStat;
  589         int     ToRecv, ch, err = 0;
  590 
  591         ToRecv = sGetRxCnt(cp);
  592         if(ToRecv == 0)
  593                 return;
  594 
  595 /*      If status indicates there are errored characters in the
  596         FIFO, then enter status mode (a word in FIFO holds
  597         characters and status)
  598 */
  599 
  600         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  601                 if(!(ChanStatus & STATMODE)) {
  602                         ChanStatus |= STATMODE;
  603                         sEnRxStatusMode(cp);
  604                 }
  605         }
  606 /*
  607         if we previously entered status mode then read down the
  608         FIFO one word at a time, pulling apart the character and
  609         the status. Update error counters depending on status.
  610 */
  611         tty_lock(tp);
  612         if(ChanStatus & STATMODE) {
  613                 while(ToRecv) {
  614                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
  615                         ch = CharNStat & 0xff;
  616 
  617                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  618                                 err |= TRE_FRAMING;
  619                         else if (CharNStat & STMPARITYH)
  620                                 err |= TRE_PARITY;
  621                         else if (CharNStat & STMRCVROVRH) {
  622                                 rp->rp_overflows++;
  623                                 err |= TRE_OVERRUN;
  624                         }
  625 
  626                         ttydisc_rint(tp, ch, err);
  627                         ToRecv--;
  628                 }
  629 /*
  630         After emtying FIFO in status mode, turn off status mode
  631 */
  632 
  633                 if(sGetRxCnt(cp) == 0) {
  634                         sDisRxStatusMode(cp);
  635                 }
  636         } else {
  637                 ToRecv = sGetRxCnt(cp);
  638                 while (ToRecv) {
  639                         ch = rp_readch1(cp,sGetTxRxDataIO(cp));
  640                         ttydisc_rint(tp, ch & 0xff, err);
  641                         ToRecv--;
  642                 }
  643         }
  644         ttydisc_rint_done(tp);
  645         tty_unlock(tp);
  646 }
  647 
  648 static void rp_handle_port(struct rp_port *rp)
  649 {
  650         CHANNEL_t       *cp;
  651         struct  tty     *tp;
  652         unsigned        int     IntMask, ChanStatus;
  653 
  654         if(!rp)
  655                 return;
  656 
  657         cp = &rp->rp_channel;
  658         tp = rp->rp_tty;
  659         IntMask = sGetChanIntID(cp);
  660         IntMask = IntMask & rp->rp_intmask;
  661         ChanStatus = sGetChanStatus(cp);
  662         if(IntMask & RXF_TRIG)
  663                 rp_do_receive(rp, tp, cp, ChanStatus);
  664         if(IntMask & DELTA_CD) {
  665                 if(ChanStatus & CD_ACT) {
  666                         (void)ttydisc_modem(tp, 1);
  667                 } else {
  668                         (void)ttydisc_modem(tp, 0);
  669                 }
  670         }
  671 /*      oldcts = rp->rp_cts;
  672         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  673         if(oldcts != rp->rp_cts) {
  674                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  675         }
  676 */
  677 }
  678 
  679 static void rp_do_poll(void *not_used)
  680 {
  681         CONTROLLER_t    *ctl;
  682         struct rp_port  *rp;
  683         struct tty      *tp;
  684         int     unit, aiop, ch, line, count;
  685         unsigned char   CtlMask, AiopMask;
  686 
  687         for(unit = 0; unit < rp_ndevs; unit++) {
  688         rp = rp_addr(unit);
  689         ctl = rp->rp_ctlp;
  690         CtlMask = ctl->ctlmask(ctl);
  691         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  692                 if(CtlMask & 1) {
  693                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  694                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  695                                 if(AiopMask & 1) {
  696                                         line = (unit << 5) | (aiop << 3) | ch;
  697                                         rp = rp_table(line);
  698                                         rp_handle_port(rp);
  699                                 }
  700                         }
  701                 }
  702         }
  703 
  704         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  705                         line++, rp++) {
  706                 tp = rp->rp_tty;
  707                 tty_lock(tp);
  708                 count = sGetTxCnt(&rp->rp_channel);
  709                 if (count >= 0  &&
  710                     (count <= rp->rp_restart)) {
  711                         rpstart(tp);
  712                 }
  713                 tty_unlock(tp);
  714         }
  715         }
  716         if(rp_num_ports_open)
  717                 rp_callout_handle = timeout(rp_do_poll, 
  718                                             (void *)NULL, POLL_INTERVAL);
  719 }
  720 
  721 static struct ttydevsw rp_tty_class = {
  722         .tsw_flags      = TF_INITLOCK|TF_CALLOUT,
  723         .tsw_open       = rpopen,
  724         .tsw_close      = rpclose,
  725         .tsw_outwakeup  = rpstart,
  726         .tsw_ioctl      = rpioctl,
  727         .tsw_param      = rpparam,
  728         .tsw_modem      = rpmodem,
  729         .tsw_free       = rpfree,
  730 };
  731 
  732 
  733 static void
  734 rpfree(void *softc)
  735 {
  736         struct  rp_port *rp = softc;
  737         CONTROLLER_t *ctlp = rp->rp_ctlp;
  738 
  739         atomic_subtract_32(&ctlp->free, 1);
  740 }
  741 
  742 int
  743 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
  744 {
  745         int     unit;
  746         int     num_chan;
  747         int     aiop, chan, port;
  748         int     ChanStatus, line, count;
  749         int     retval;
  750         struct  rp_port *rp;
  751         struct tty *tp;
  752 
  753         unit = device_get_unit(ctlp->dev);
  754 
  755         printf("RocketPort%d (Version %s) %d ports.\n", unit,
  756                 RocketPortVersion, num_ports);
  757         rp_num_ports[unit] = num_ports;
  758         callout_handle_init(&rp_callout_handle);
  759 
  760         ctlp->rp = rp = (struct rp_port *)
  761                 malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO);
  762         if (rp == NULL) {
  763                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
  764                 retval = ENOMEM;
  765                 goto nogo;
  766         }
  767 
  768         count = unit * 32;      /* board times max ports per card SG */
  769 
  770         bzero(rp, sizeof(struct rp_port) * num_ports);
  771         rp_addr(unit) = rp;
  772 
  773         port = 0;
  774         for(aiop=0; aiop < num_aiops; aiop++) {
  775                 num_chan = sGetAiopNumChan(ctlp, aiop);
  776                 for(chan=0; chan < num_chan; chan++, port++, rp++) {
  777                         rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp);
  778                         rp->rp_port = port;
  779                         rp->rp_ctlp = ctlp;
  780                         rp->rp_unit = unit;
  781                         rp->rp_chan = chan;
  782                         rp->rp_aiop = aiop;
  783 
  784                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
  785                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
  786 #ifdef notdef
  787                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  788 #endif /* notdef */
  789                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
  790                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
  791                                               unit, aiop, chan);
  792                                 retval = ENXIO;
  793                                 goto nogo;
  794                         }
  795                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  796                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
  797                         line = (unit << 5) | (aiop << 3) | chan;
  798                         rp_table(line) = rp;
  799                         tty_makedev(tp, NULL, "R%r%r", unit, port);
  800                 }
  801         }
  802 
  803         rp_ndevs++;
  804         mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF);
  805         ctlp->hwmtx_init = 1;
  806         return (0);
  807 
  808 nogo:
  809         rp_releaseresource(ctlp);
  810 
  811         return (retval);
  812 }
  813 
  814 void
  815 rp_releaseresource(CONTROLLER_t *ctlp)
  816 {
  817         int i, unit;
  818         struct  rp_port *rp;
  819 
  820 
  821         unit = device_get_unit(ctlp->dev);
  822         if (rp_addr(unit) != NULL) {
  823                 for (i = 0; i < rp_num_ports[unit]; i++) {
  824                         rp = rp_addr(unit) + i;
  825                         atomic_add_32(&ctlp->free, 1);
  826                         tty_lock(rp->rp_tty);
  827                         tty_rel_gone(rp->rp_tty);
  828                 }
  829         }
  830 
  831         while (ctlp->free != 0) {
  832                 pause("rpwt", hz / 10);
  833         }
  834 
  835         if (ctlp->rp != NULL) {
  836                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
  837                         if (p_rp_addr[i] == ctlp->rp)
  838                                 p_rp_addr[i] = NULL;
  839                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
  840                         if (p_rp_table[i] == ctlp->rp)
  841                                 p_rp_table[i] = NULL;
  842                 free(ctlp->rp, M_DEVBUF);
  843                 ctlp->rp = NULL;
  844         }
  845 }
  846 
  847 void
  848 rp_untimeout(void)
  849 {
  850         untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
  851 }
  852 
  853 static int
  854 rpopen(struct tty *tp)
  855 {
  856         struct  rp_port *rp;
  857         int     flags;
  858         unsigned int    IntMask, ChanStatus;
  859 
  860         rp = tty_softc(tp);
  861 
  862         flags = 0;
  863         flags |= SET_RTS;
  864         flags |= SET_DTR;
  865         rp->rp_channel.TxControl[3] =
  866                 ((rp->rp_channel.TxControl[3]
  867                 & ~(SET_RTS | SET_DTR)) | flags);
  868         rp_writech4(&rp->rp_channel,_INDX_ADDR,
  869                 le32dec(rp->rp_channel.TxControl));
  870         sSetRxTrigger(&rp->rp_channel, TRIG_1);
  871         sDisRxStatusMode(&rp->rp_channel);
  872         sFlushRxFIFO(&rp->rp_channel);
  873         sFlushTxFIFO(&rp->rp_channel);
  874 
  875         sEnInterrupts(&rp->rp_channel,
  876                 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
  877         sSetRxTrigger(&rp->rp_channel, TRIG_1);
  878 
  879         sDisRxStatusMode(&rp->rp_channel);
  880         sClrTxXOFF(&rp->rp_channel);
  881 
  882 /*      sDisRTSFlowCtl(&rp->rp_channel);
  883         sDisCTSFlowCtl(&rp->rp_channel);
  884 */
  885         sDisTxSoftFlowCtl(&rp->rp_channel);
  886 
  887         sStartRxProcessor(&rp->rp_channel);
  888 
  889         sEnRxFIFO(&rp->rp_channel);
  890         sEnTransmit(&rp->rp_channel);
  891 
  892 /*      sSetDTR(&rp->rp_channel);
  893         sSetRTS(&rp->rp_channel);
  894 */
  895 
  896         rp_num_ports_open++;
  897 
  898         IntMask = sGetChanIntID(&rp->rp_channel);
  899         IntMask = IntMask & rp->rp_intmask;
  900         ChanStatus = sGetChanStatus(&rp->rp_channel);
  901 
  902         if(rp_num_ports_open == 1)
  903                 rp_callout_handle = timeout(rp_do_poll, 
  904                                             (void *)NULL, POLL_INTERVAL);
  905 
  906         device_busy(rp->rp_ctlp->dev);
  907         return(0);
  908 }
  909 
  910 static void
  911 rpclose(struct tty *tp)
  912 {
  913         struct  rp_port *rp;
  914 
  915         rp = tty_softc(tp);
  916         rphardclose(tp);
  917         device_unbusy(rp->rp_ctlp->dev);
  918 }
  919 
  920 static void
  921 rphardclose(struct tty *tp)
  922 {
  923         struct  rp_port *rp;
  924         CHANNEL_t       *cp;
  925 
  926         rp = tty_softc(tp);
  927         cp = &rp->rp_channel;
  928 
  929         sFlushRxFIFO(cp);
  930         sFlushTxFIFO(cp);
  931         sDisTransmit(cp);
  932         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
  933         sDisRTSFlowCtl(cp);
  934         sDisCTSFlowCtl(cp);
  935         sDisTxSoftFlowCtl(cp);
  936         sClrTxXOFF(cp);
  937 
  938 #ifdef DJA
  939         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) {
  940                 sClrDTR(cp);
  941         }
  942         if(ISCALLOUT(tp->t_dev)) {
  943                 sClrDTR(cp);
  944         }
  945         tp->t_actout = FALSE;
  946         wakeup(&tp->t_actout);
  947         wakeup(TSA_CARR_ON(tp));
  948 #endif /* DJA */
  949 }
  950 
  951 static int
  952 rpioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
  953 {
  954         struct rp_port  *rp;
  955 
  956         rp = tty_softc(tp);
  957         switch (cmd) {
  958         case TIOCSBRK:
  959                 sSendBreak(&rp->rp_channel);
  960                 return (0);
  961         case TIOCCBRK:
  962                 sClrBreak(&rp->rp_channel);
  963                 return (0);
  964         default:
  965                 return ENOIOCTL;
  966         }
  967 }
  968 
  969 static int
  970 rpmodem(struct tty *tp, int sigon, int sigoff)
  971 {
  972         struct rp_port  *rp;
  973         int i, j, k;
  974 
  975         rp = tty_softc(tp);
  976         if (sigon != 0 || sigoff != 0) {
  977                 i = j = 0;
  978                 if (sigon & SER_DTR)
  979                         i = SET_DTR;
  980                 if (sigoff & SER_DTR)
  981                         j = SET_DTR;
  982                 if (sigon & SER_RTS)
  983                         i = SET_RTS;
  984                 if (sigoff & SER_RTS)
  985                         j = SET_RTS;
  986                 rp->rp_channel.TxControl[3] &= ~i;
  987                 rp->rp_channel.TxControl[3] |= j;
  988                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
  989                         le32dec(rp->rp_channel.TxControl));
  990         } else {
  991                 i = sGetChanStatusLo(&rp->rp_channel);
  992                 j = rp->rp_channel.TxControl[3];
  993                 k = 0;
  994                 if (j & SET_DTR)
  995                         k |= SER_DTR;
  996                 if (j & SET_RTS)
  997                         k |= SER_RTS;
  998                 if (i & CD_ACT)
  999                         k |= SER_DCD;
 1000                 if (i & DSR_ACT)
 1001                         k |= SER_DSR;
 1002                 if (i & CTS_ACT)
 1003                         k |= SER_CTS;
 1004                 return(k);
 1005         }
 1006         return (0);
 1007 }
 1008 
 1009 static struct
 1010 {
 1011         int baud;
 1012         int conversion;
 1013 } baud_table[] = {
 1014         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1015         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1016         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1017         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1018         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1019         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1020                                 {B57600, BRD57600},     {B76800, BRD76800},
 1021         {B115200, BRD115200},   {B230400, BRD230400},
 1022         {-1,    -1}
 1023 };
 1024 
 1025 static int rp_convert_baud(int baud) {
 1026         int i;
 1027 
 1028         for (i = 0; baud_table[i].baud >= 0; i++) {
 1029                 if (baud_table[i].baud == baud)
 1030                         break;
 1031         }
 1032 
 1033         return baud_table[i].conversion;
 1034 }
 1035 
 1036 static int
 1037 rpparam(tp, t)
 1038         struct tty *tp;
 1039         struct termios *t;
 1040 {
 1041         struct rp_port  *rp;
 1042         CHANNEL_t       *cp;
 1043         int     cflag, iflag, oflag, lflag;
 1044         int     ospeed;
 1045 #ifdef RPCLOCAL
 1046         int     devshift;
 1047 #endif
 1048 
 1049         rp = tty_softc(tp);
 1050         cp = &rp->rp_channel;
 1051 
 1052         cflag = t->c_cflag;
 1053 #ifdef RPCLOCAL
 1054         devshift = umynor / 32;
 1055         devshift = 1 << devshift;
 1056         if ( devshift & RPCLOCAL ) {
 1057                 cflag |= CLOCAL;
 1058         }
 1059 #endif
 1060         iflag = t->c_iflag;
 1061         oflag = t->c_oflag;
 1062         lflag = t->c_lflag;
 1063 
 1064         ospeed = rp_convert_baud(t->c_ispeed);
 1065         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1066                 return(EINVAL);
 1067 
 1068         if(t->c_ospeed == 0) {
 1069                 sClrDTR(cp);
 1070                 return(0);
 1071         }
 1072         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1073 
 1074         /* Set baud rate ----- we only pay attention to ispeed */
 1075         sSetDTR(cp);
 1076         sSetRTS(cp);
 1077         sSetBaud(cp, ospeed);
 1078 
 1079         if(cflag & CSTOPB) {
 1080                 sSetStop2(cp);
 1081         } else {
 1082                 sSetStop1(cp);
 1083         }
 1084 
 1085         if(cflag & PARENB) {
 1086                 sEnParity(cp);
 1087                 if(cflag & PARODD) {
 1088                         sSetOddParity(cp);
 1089                 } else {
 1090                         sSetEvenParity(cp);
 1091                 }
 1092         }
 1093         else {
 1094                 sDisParity(cp);
 1095         }
 1096         if((cflag & CSIZE) == CS8) {
 1097                 sSetData8(cp);
 1098                 rp->rp_imask = 0xFF;
 1099         } else {
 1100                 sSetData7(cp);
 1101                 rp->rp_imask = 0x7F;
 1102         }
 1103 
 1104         if(iflag & ISTRIP) {
 1105                 rp->rp_imask &= 0x7F;
 1106         }
 1107 
 1108         if(cflag & CLOCAL) {
 1109                 rp->rp_intmask &= ~DELTA_CD;
 1110         } else {
 1111                 rp->rp_intmask |= DELTA_CD;
 1112         }
 1113 
 1114         /* Put flow control stuff here */
 1115 
 1116         if(cflag & CCTS_OFLOW) {
 1117                 sEnCTSFlowCtl(cp);
 1118         } else {
 1119                 sDisCTSFlowCtl(cp);
 1120         }
 1121 
 1122         if(cflag & CRTS_IFLOW) {
 1123                 rp->rp_rts_iflow = 1;
 1124         } else {
 1125                 rp->rp_rts_iflow = 0;
 1126         }
 1127 
 1128         if(cflag & CRTS_IFLOW) {
 1129                 sEnRTSFlowCtl(cp);
 1130         } else {
 1131                 sDisRTSFlowCtl(cp);
 1132         }
 1133 
 1134         return(0);
 1135 }
 1136 
 1137 static void
 1138 rpstart(struct tty *tp)
 1139 {
 1140         struct rp_port  *rp;
 1141         CHANNEL_t       *cp;
 1142         char    flags;
 1143         int     xmit_fifo_room;
 1144         int     i, count, wcount;
 1145 
 1146         rp = tty_softc(tp);
 1147         cp = &rp->rp_channel;
 1148         flags = rp->rp_channel.TxControl[3];
 1149 
 1150         if(rp->rp_xmit_stopped) {
 1151                 sEnTransmit(cp);
 1152                 rp->rp_xmit_stopped = 0;
 1153         }
 1154 
 1155         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1156         count = ttydisc_getc(tp, &rp->TxBuf, xmit_fifo_room);
 1157         if(xmit_fifo_room > 0) {
 1158                 for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) {
 1159                         rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(&rp->TxBuf[i]));
 1160                 }
 1161                 if ( count & 1 ) {
 1162                         rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]);
 1163                 }
 1164         }
 1165 }

Cache object: b54fea6acbf60a765762797002e51927


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