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

Cache object: 1d57a853f7cd786ce4b4b110c85fb8f3


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