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

Cache object: 3d50c09b34a68992ffa28919dd117521


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