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: src/sys/dev/rp/rp.c,v 1.64.2.2 2005/11/08 15:37:21 jhb Exp $");
   36 
   37 /* 
   38  * rp.c - for RocketPort FreeBSD
   39  */
   40 
   41 #include "opt_compat.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/systm.h>
   45 #include <sys/fcntl.h>
   46 #include <sys/malloc.h>
   47 #include <sys/tty.h>
   48 #include <sys/conf.h>
   49 #include <sys/kernel.h>
   50 #include <machine/resource.h>
   51 #include <machine/bus.h>
   52 #include <sys/bus.h>
   53 #include <sys/rman.h>
   54 
   55 #define ROCKET_C
   56 #include <dev/rp/rpreg.h>
   57 #include <dev/rp/rpvar.h>
   58 
   59 static const char RocketPortVersion[] = "3.02";
   60 
   61 static Byte_t RData[RDATASIZE] =
   62 {
   63    0x00, 0x09, 0xf6, 0x82,
   64    0x02, 0x09, 0x86, 0xfb,
   65    0x04, 0x09, 0x00, 0x0a,
   66    0x06, 0x09, 0x01, 0x0a,
   67    0x08, 0x09, 0x8a, 0x13,
   68    0x0a, 0x09, 0xc5, 0x11,
   69    0x0c, 0x09, 0x86, 0x85,
   70    0x0e, 0x09, 0x20, 0x0a,
   71    0x10, 0x09, 0x21, 0x0a,
   72    0x12, 0x09, 0x41, 0xff,
   73    0x14, 0x09, 0x82, 0x00,
   74    0x16, 0x09, 0x82, 0x7b,
   75    0x18, 0x09, 0x8a, 0x7d,
   76    0x1a, 0x09, 0x88, 0x81,
   77    0x1c, 0x09, 0x86, 0x7a,
   78    0x1e, 0x09, 0x84, 0x81,
   79    0x20, 0x09, 0x82, 0x7c,
   80    0x22, 0x09, 0x0a, 0x0a
   81 };
   82 
   83 static Byte_t RRegData[RREGDATASIZE]=
   84 {
   85    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
   86    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
   87    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
   88    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
   89    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
   90    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
   91    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
   92    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
   93    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
   94    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
   95    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
   96    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
   97    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
   98 };
   99 
  100 #if 0
  101 /* IRQ number to MUDBAC register 2 mapping */
  102 Byte_t sIRQMap[16] =
  103 {
  104    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  105 };
  106 #endif
  107 
  108 Byte_t rp_sBitMapClrTbl[8] =
  109 {
  110    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  111 };
  112 
  113 Byte_t rp_sBitMapSetTbl[8] =
  114 {
  115    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  116 };
  117 
  118 /* Actually not used */
  119 #if notdef
  120 struct termios deftermios = {
  121         TTYDEF_IFLAG,
  122         TTYDEF_OFLAG,
  123         TTYDEF_CFLAG,
  124         TTYDEF_LFLAG,
  125         { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
  126         _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
  127         CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
  128         TTYDEF_SPEED,
  129         TTYDEF_SPEED
  130 };
  131 #endif
  132 
  133 /***************************************************************************
  134 Function: sReadAiopID
  135 Purpose:  Read the AIOP idenfication number directly from an AIOP.
  136 Call:     sReadAiopID(CtlP, aiop)
  137           CONTROLLER_T *CtlP; Ptr to controller structure
  138           int aiop: AIOP index
  139 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  140                  is replace by an identifying number.
  141           Flag AIOPID_NULL if no valid AIOP is found
  142 Warnings: No context switches are allowed while executing this function.
  143 
  144 */
  145 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
  146 {
  147    Byte_t AiopID;               /* ID byte from AIOP */
  148 
  149    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
  150    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
  151    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
  152    if(AiopID == 0x06)
  153       return(1);
  154    else                                /* AIOP does not exist */
  155       return(-1);
  156 }
  157 
  158 /***************************************************************************
  159 Function: sReadAiopNumChan
  160 Purpose:  Read the number of channels available in an AIOP directly from
  161           an AIOP.
  162 Call:     sReadAiopNumChan(CtlP, aiop)
  163           CONTROLLER_T *CtlP; Ptr to controller structure
  164           int aiop: AIOP index
  165 Return:   int: The number of channels available
  166 Comments: The number of channels is determined by write/reads from identical
  167           offsets within the SRAM address spaces for channels 0 and 4.
  168           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  169           AIOP, otherwise it is an 8 channel.
  170 Warnings: No context switches are allowed while executing this function.
  171 */
  172 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
  173 {
  174    Word_t x, y;
  175 
  176    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  177    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
  178    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  179    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  180    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
  181    if(x != y)  /* if different must be 8 chan */
  182       return(8);
  183    else
  184       return(4);
  185 }
  186 
  187 /***************************************************************************
  188 Function: sInitChan
  189 Purpose:  Initialization of a channel and channel structure
  190 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  191           CONTROLLER_T *CtlP; Ptr to controller structure
  192           CHANNEL_T *ChP; Ptr to channel structure
  193           int AiopNum; AIOP number within controller
  194           int ChanNum; Channel number within AIOP
  195 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  196                number exceeds number of channels available in AIOP.
  197 Comments: This function must be called before a channel can be used.
  198 Warnings: No range checking on any of the parameters is done.
  199 
  200           No context switches are allowed while executing this function.
  201 */
  202 int sInitChan(  CONTROLLER_T *CtlP,
  203                 CHANNEL_T *ChP,
  204                 int AiopNum,
  205                 int ChanNum)
  206 {
  207    int i, ChOff;
  208    Byte_t *ChR;
  209    static Byte_t R[4];
  210 
  211    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  212       return(FALSE);                   /* exceeds num chans in AIOP */
  213 
  214    /* Channel, AIOP, and controller identifiers */
  215    ChP->CtlP = CtlP;
  216    ChP->ChanID = CtlP->AiopID[AiopNum];
  217    ChP->AiopNum = AiopNum;
  218    ChP->ChanNum = ChanNum;
  219 
  220    /* Initialize the channel from the RData array */
  221    for(i=0; i < RDATASIZE; i+=4)
  222    {
  223       R[0] = RData[i];
  224       R[1] = RData[i+1] + 0x10 * ChanNum;
  225       R[2] = RData[i+2];
  226       R[3] = RData[i+3];
  227       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
  228    }
  229 
  230    ChR = ChP->R;
  231    for(i=0; i < RREGDATASIZE; i+=4)
  232    {
  233       ChR[i] = RRegData[i];
  234       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  235       ChR[i+2] = RRegData[i+2];
  236       ChR[i+3] = RRegData[i+3];
  237    }
  238 
  239    /* Indexed registers */
  240    ChOff = (Word_t)ChanNum * 0x1000;
  241 
  242    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  243    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  244    ChP->BaudDiv[2] = (Byte_t)BRD9600;
  245    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
  246    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
  247 
  248    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  249    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  250    ChP->TxControl[2] = 0;
  251    ChP->TxControl[3] = 0;
  252    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  253 
  254    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  255    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  256    ChP->RxControl[2] = 0;
  257    ChP->RxControl[3] = 0;
  258    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  259 
  260    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  261    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  262    ChP->TxEnables[2] = 0;
  263    ChP->TxEnables[3] = 0;
  264    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
  265 
  266    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  267    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  268    ChP->TxCompare[2] = 0;
  269    ChP->TxCompare[3] = 0;
  270    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
  271 
  272    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  273    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  274    ChP->TxReplace1[2] = 0;
  275    ChP->TxReplace1[3] = 0;
  276    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
  277 
  278    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  279    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  280    ChP->TxReplace2[2] = 0;
  281    ChP->TxReplace2[3] = 0;
  282    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
  283 
  284    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  285    ChP->TxFIFO = ChOff + _TX_FIFO;
  286 
  287    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  288    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  289    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  290    rp_writech2(ChP,_INDX_DATA,0);
  291    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  292    ChP->RxFIFO = ChOff + _RX_FIFO;
  293 
  294    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  295    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  296    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  297    rp_writech2(ChP,_INDX_DATA,0);
  298    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  299    rp_writech2(ChP,_INDX_DATA,0);
  300    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  301    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
  302    rp_writech1(ChP,_INDX_DATA,0);
  303    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  304    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
  305    rp_writech1(ChP,_INDX_DATA,0);
  306    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  307    sEnRxProcessor(ChP);                /* start the Rx processor */
  308 
  309    return(TRUE);
  310 }
  311 
  312 /***************************************************************************
  313 Function: sStopRxProcessor
  314 Purpose:  Stop the receive processor from processing a channel.
  315 Call:     sStopRxProcessor(ChP)
  316           CHANNEL_T *ChP; Ptr to channel structure
  317 
  318 Comments: The receive processor can be started again with sStartRxProcessor().
  319           This function causes the receive processor to skip over the
  320           stopped channel.  It does not stop it from processing other channels.
  321 
  322 Warnings: No context switches are allowed while executing this function.
  323 
  324           Do not leave the receive processor stopped for more than one
  325           character time.
  326 
  327           After calling this function a delay of 4 uS is required to ensure
  328           that the receive processor is no longer processing this channel.
  329 */
  330 void sStopRxProcessor(CHANNEL_T *ChP)
  331 {
  332    Byte_t R[4];
  333 
  334    R[0] = ChP->R[0];
  335    R[1] = ChP->R[1];
  336    R[2] = 0x0a;
  337    R[3] = ChP->R[3];
  338    rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
  339 }
  340 
  341 /***************************************************************************
  342 Function: sFlushRxFIFO
  343 Purpose:  Flush the Rx FIFO
  344 Call:     sFlushRxFIFO(ChP)
  345           CHANNEL_T *ChP; Ptr to channel structure
  346 Return:   void
  347 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  348           while it is being flushed the receive processor is stopped
  349           and the transmitter is disabled.  After these operations a
  350           4 uS delay is done before clearing the pointers to allow
  351           the receive processor to stop.  These items are handled inside
  352           this function.
  353 Warnings: No context switches are allowed while executing this function.
  354 */
  355 void sFlushRxFIFO(CHANNEL_T *ChP)
  356 {
  357    int i;
  358    Byte_t Ch;                   /* channel number within AIOP */
  359    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  360 
  361    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  362       return;                          /* don't need to flush */
  363 
  364    RxFIFOEnabled = FALSE;
  365    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  366    {
  367       RxFIFOEnabled = TRUE;
  368       sDisRxFIFO(ChP);                 /* disable it */
  369       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
  370          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
  371    }
  372    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  373    Ch = (Byte_t)sGetChanNum(ChP);
  374    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  375    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
  376    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  377    rp_writech2(ChP,_INDX_DATA,0);
  378    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  379    rp_writech2(ChP,_INDX_DATA,0);
  380    if(RxFIFOEnabled)
  381       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  382 }
  383 
  384 /***************************************************************************
  385 Function: sFlushTxFIFO
  386 Purpose:  Flush the Tx FIFO
  387 Call:     sFlushTxFIFO(ChP)
  388           CHANNEL_T *ChP; Ptr to channel structure
  389 Return:   void
  390 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  391           while it is being flushed the receive processor is stopped
  392           and the transmitter is disabled.  After these operations a
  393           4 uS delay is done before clearing the pointers to allow
  394           the receive processor to stop.  These items are handled inside
  395           this function.
  396 Warnings: No context switches are allowed while executing this function.
  397 */
  398 void sFlushTxFIFO(CHANNEL_T *ChP)
  399 {
  400    int i;
  401    Byte_t Ch;                   /* channel number within AIOP */
  402    int TxEnabled;                      /* TRUE if transmitter enabled */
  403 
  404    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  405       return;                          /* don't need to flush */
  406 
  407    TxEnabled = FALSE;
  408    if(ChP->TxControl[3] & TX_ENABLE)
  409    {
  410       TxEnabled = TRUE;
  411       sDisTransmit(ChP);               /* disable transmitter */
  412    }
  413    sStopRxProcessor(ChP);              /* stop Rx processor */
  414    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  415       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
  416    Ch = (Byte_t)sGetChanNum(ChP);
  417    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  418    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
  419    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  420    rp_writech2(ChP,_INDX_DATA,0);
  421    if(TxEnabled)
  422       sEnTransmit(ChP);                /* enable transmitter */
  423    sStartRxProcessor(ChP);             /* restart Rx processor */
  424 }
  425 
  426 /***************************************************************************
  427 Function: sWriteTxPrioByte
  428 Purpose:  Write a byte of priority transmit data to a channel
  429 Call:     sWriteTxPrioByte(ChP,Data)
  430           CHANNEL_T *ChP; Ptr to channel structure
  431           Byte_t Data; The transmit data byte
  432 
  433 Return:   int: 1 if the bytes is successfully written, otherwise 0.
  434 
  435 Comments: The priority byte is transmitted before any data in the Tx FIFO.
  436 
  437 Warnings: No context switches are allowed while executing this function.
  438 */
  439 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  440 {
  441    Byte_t DWBuf[4];             /* buffer for double word writes */
  442    Word_t *WordPtr;          /* must be far because Win SS != DS */
  443 
  444    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  445    {
  446       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
  447       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
  448          return(0);                    /* nothing sent */
  449 
  450       WordPtr = (Word_t *)(&DWBuf[0]);
  451       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
  452 
  453       DWBuf[2] = Data;                 /* data byte value */
  454       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  455 
  456       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
  457 
  458       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  459       DWBuf[3] = 0;                    /* priority buffer pointer */
  460       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  461    }
  462    else                                /* write it to Tx FIFO */
  463    {
  464       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
  465    }
  466    return(1);                          /* 1 byte sent */
  467 }
  468 
  469 /***************************************************************************
  470 Function: sEnInterrupts
  471 Purpose:  Enable one or more interrupts for a channel
  472 Call:     sEnInterrupts(ChP,Flags)
  473           CHANNEL_T *ChP; Ptr to channel structure
  474           Word_t Flags: Interrupt enable flags, can be any combination
  475              of the following flags:
  476                 TXINT_EN:   Interrupt on Tx FIFO empty
  477                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  478                             sSetRxTrigger())
  479                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  480                 MCINT_EN:   Interrupt on modem input change
  481                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  482                             Interrupt Channel Register.
  483 Return:   void
  484 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  485           enabled.  If an interrupt enable flag is not set in Flags, that
  486           interrupt will not be changed.  Interrupts can be disabled with
  487           function sDisInterrupts().
  488 
  489           This function sets the appropriate bit for the channel in the AIOP's
  490           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  491           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  492 
  493           Interrupts must also be globally enabled before channel interrupts
  494           will be passed on to the host.  This is done with function
  495           sEnGlobalInt().
  496 
  497           In some cases it may be desirable to disable interrupts globally but
  498           enable channel interrupts.  This would allow the global interrupt
  499           status register to be used to determine which AIOPs need service.
  500 */
  501 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  502 {
  503    Byte_t Mask;                 /* Interrupt Mask Register */
  504 
  505    ChP->RxControl[2] |=
  506       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  507 
  508    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  509 
  510    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  511 
  512    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  513 
  514    if(Flags & CHANINT_EN)
  515    {
  516       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
  517       rp_writech1(ChP,_INT_MASK,Mask);
  518    }
  519 }
  520 
  521 /***************************************************************************
  522 Function: sDisInterrupts
  523 Purpose:  Disable one or more interrupts for a channel
  524 Call:     sDisInterrupts(ChP,Flags)
  525           CHANNEL_T *ChP; Ptr to channel structure
  526           Word_t Flags: Interrupt flags, can be any combination
  527              of the following flags:
  528                 TXINT_EN:   Interrupt on Tx FIFO empty
  529                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  530                             sSetRxTrigger())
  531                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  532                 MCINT_EN:   Interrupt on modem input change
  533                 CHANINT_EN: Disable channel interrupt signal to the
  534                             AIOP's Interrupt Channel Register.
  535 Return:   void
  536 Comments: If an interrupt flag is set in Flags, that interrupt will be
  537           disabled.  If an interrupt flag is not set in Flags, that
  538           interrupt will not be changed.  Interrupts can be enabled with
  539           function sEnInterrupts().
  540 
  541           This function clears the appropriate bit for the channel in the AIOP's
  542           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  543           this channel's bit from being set in the AIOP's Interrupt Channel
  544           Register.
  545 */
  546 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  547 {
  548    Byte_t Mask;                 /* Interrupt Mask Register */
  549 
  550    ChP->RxControl[2] &=
  551          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  552    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
  553    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  554    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
  555 
  556    if(Flags & CHANINT_EN)
  557    {
  558       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
  559       rp_writech1(ChP,_INT_MASK,Mask);
  560    }
  561 }
  562 
  563 /*********************************************************************
  564   Begin FreeBsd-specific driver code
  565 **********************************************************************/
  566 
  567 static timeout_t rpdtrwakeup;
  568 struct callout_handle rp_callout_handle;
  569 
  570 static  d_open_t        rpopen;
  571 static  d_close_t       rpclose;
  572 static  d_write_t       rpwrite;
  573 static  d_ioctl_t       rpioctl;
  574 
  575 struct cdevsw rp_cdevsw = {
  576         .d_version =    D_VERSION,
  577         .d_open =       rpopen,
  578         .d_close =      rpclose,
  579         .d_write =      rpwrite,
  580         .d_ioctl =      rpioctl,
  581         .d_name =       "rp",
  582         .d_flags =      D_TTY | D_NEEDGIANT,
  583 };
  584 
  585 static int      rp_num_ports_open = 0;
  586 static int      rp_ndevs = 0;
  587 static int      minor_to_unit[128];
  588 
  589 static int rp_num_ports[4];     /* Number of ports on each controller */
  590 
  591 #define POLL_INTERVAL 1
  592 
  593 #define CALLOUT_MASK            0x80
  594 #define CONTROL_MASK            0x60
  595 #define CONTROL_INIT_STATE      0x20
  596 #define CONTROL_LOCK_STATE      0x40
  597 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  598 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  599 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  600 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  601 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  602 
  603 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  604 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  605 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  606 
  607 static  struct  rp_port *p_rp_addr[4];
  608 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  609 #define rp_addr(unit)   (p_rp_addr[unit])
  610 #define rp_table(port)  (p_rp_table[port])
  611 
  612 /*
  613  * The top-level routines begin here
  614  */
  615 
  616 static  int     rpparam(struct tty *, struct termios *);
  617 static  void    rpstart(struct tty *);
  618 static  void    rpstop(struct tty *, int);
  619 static  void    rphardclose     (struct rp_port *);
  620 
  621 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
  622                         CHANNEL_t *cp, unsigned int ChanStatus)
  623 {
  624         int     spl;
  625         unsigned        int     CharNStat;
  626         int     ToRecv, wRecv, ch, ttynocopy;
  627 
  628         ToRecv = sGetRxCnt(cp);
  629         if(ToRecv == 0)
  630                 return;
  631 
  632 /*      If status indicates there are errored characters in the
  633         FIFO, then enter status mode (a word in FIFO holds
  634         characters and status)
  635 */
  636 
  637         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  638                 if(!(ChanStatus & STATMODE)) {
  639                         ChanStatus |= STATMODE;
  640                         sEnRxStatusMode(cp);
  641                 }
  642         }
  643 /*
  644         if we previously entered status mode then read down the
  645         FIFO one word at a time, pulling apart the character and
  646         the status. Update error counters depending on status.
  647 */
  648         if(ChanStatus & STATMODE) {
  649                 while(ToRecv) {
  650                         if(tp->t_state & TS_TBLOCK) {
  651                                 break;
  652                         }
  653                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
  654                         ch = CharNStat & 0xff;
  655 
  656                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  657                                 ch |= TTY_FE;
  658                         else if (CharNStat & STMPARITYH)
  659                                 ch |= TTY_PE;
  660                         else if (CharNStat & STMRCVROVRH)
  661                                 rp->rp_overflows++;
  662 
  663                         ttyld_rint(tp, ch);
  664                         ToRecv--;
  665                 }
  666 /*
  667         After emtying FIFO in status mode, turn off status mode
  668 */
  669 
  670                 if(sGetRxCnt(cp) == 0) {
  671                         sDisRxStatusMode(cp);
  672                 }
  673         } else {
  674                 /*
  675                  * Avoid the grotesquely inefficient lineswitch routine
  676                  * (ttyinput) in "raw" mode.  It usually takes about 450
  677                  * instructions (that's without canonical processing or echo!).
  678                  * slinput is reasonably fast (usually 40 instructions plus
  679                  * call overhead).
  680                  */
  681                 ToRecv = sGetRxCnt(cp);
  682                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
  683                         if ( ToRecv > RXFIFO_SIZE ) {
  684                                 ToRecv = RXFIFO_SIZE;
  685                         }
  686                         wRecv = ToRecv >> 1;
  687                         if ( wRecv ) {
  688                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
  689                         }
  690                         if ( ToRecv & 1 ) {
  691                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  692                         }
  693                         tk_nin += ToRecv;
  694                         tk_rawcc += ToRecv;
  695                         tp->t_rawcc += ToRecv;
  696                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
  697                         ttwakeup(tp);
  698                 } else {
  699                         while (ToRecv) {
  700                                 if(tp->t_state & TS_TBLOCK) {
  701                                         break;
  702                                 }
  703                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
  704                                 spl = spltty();
  705                                 ttyld_rint(tp, ch);
  706                                 splx(spl);
  707                                 ToRecv--;
  708                         }
  709                 }
  710         }
  711 }
  712 
  713 static void rp_handle_port(struct rp_port *rp)
  714 {
  715         CHANNEL_t       *cp;
  716         struct  tty     *tp;
  717         unsigned        int     IntMask, ChanStatus;
  718 
  719         if(!rp)
  720                 return;
  721 
  722         cp = &rp->rp_channel;
  723         tp = rp->rp_tty;
  724         IntMask = sGetChanIntID(cp);
  725         IntMask = IntMask & rp->rp_intmask;
  726         ChanStatus = sGetChanStatus(cp);
  727         if(IntMask & RXF_TRIG)
  728                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  729                         rp_do_receive(rp, tp, cp, ChanStatus);
  730                 }
  731         if(IntMask & DELTA_CD) {
  732                 if(ChanStatus & CD_ACT) {
  733                         if(!(tp->t_state & TS_CARR_ON) ) {
  734                                 (void)ttyld_modem(tp, 1);
  735                         }
  736                 } else {
  737                         if((tp->t_state & TS_CARR_ON)) {
  738                                 (void)ttyld_modem(tp, 0);
  739                                 if(ttyld_modem(tp, 0) == 0) {
  740                                         rphardclose(rp);
  741                                 }
  742                         }
  743                 }
  744         }
  745 /*      oldcts = rp->rp_cts;
  746         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  747         if(oldcts != rp->rp_cts) {
  748                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  749         }
  750 */
  751 }
  752 
  753 static void rp_do_poll(void *not_used)
  754 {
  755         CONTROLLER_t    *ctl;
  756         struct rp_port  *rp;
  757         struct tty      *tp;
  758         int     unit, aiop, ch, line, count;
  759         unsigned char   CtlMask, AiopMask;
  760 
  761         for(unit = 0; unit < rp_ndevs; unit++) {
  762         rp = rp_addr(unit);
  763         ctl = rp->rp_ctlp;
  764         CtlMask = ctl->ctlmask(ctl);
  765         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  766                 if(CtlMask & 1) {
  767                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  768                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  769                                 if(AiopMask & 1) {
  770                                         line = (unit << 5) | (aiop << 3) | ch;
  771                                         rp = rp_table(line);
  772                                         rp_handle_port(rp);
  773                                 }
  774                         }
  775                 }
  776         }
  777 
  778         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  779                         line++, rp++) {
  780                 tp = rp->rp_tty;
  781                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
  782                         count = sGetTxCnt(&rp->rp_channel);
  783                         if(count == 0)
  784                                 tp->t_state &= ~(TS_BUSY);
  785                         if(!(tp->t_state & TS_TTSTOP) &&
  786                                 (count <= rp->rp_restart)) {
  787                                 ttyld_start(tp);
  788                         }
  789                 }
  790         }
  791         }
  792         if(rp_num_ports_open)
  793                 rp_callout_handle = timeout(rp_do_poll, 
  794                                             (void *)NULL, POLL_INTERVAL);
  795 }
  796 
  797 int
  798 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
  799 {
  800         int     oldspl, unit;
  801         int     num_chan;
  802         int     aiop, chan, port;
  803         int     ChanStatus, line, i, count;
  804         int     retval;
  805         struct  rp_port *rp;
  806         struct cdev **dev_nodes;
  807 
  808         unit = device_get_unit(ctlp->dev);
  809 
  810         printf("RocketPort%d (Version %s) %d ports.\n", unit,
  811                 RocketPortVersion, num_ports);
  812         rp_num_ports[unit] = num_ports;
  813         callout_handle_init(&rp_callout_handle);
  814 
  815         ctlp->rp = rp = (struct rp_port *)
  816                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
  817         if (rp == NULL) {
  818                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
  819                 retval = ENOMEM;
  820                 goto nogo;
  821         }
  822 
  823         count = unit * 32;      /* board times max ports per card SG */
  824         for(i=count;i < (count + rp_num_ports[unit]);i++)
  825                 minor_to_unit[i] = unit;
  826 
  827         bzero(rp, sizeof(struct rp_port) * num_ports);
  828         oldspl = spltty();
  829         rp_addr(unit) = rp;
  830         splx(oldspl);
  831 
  832         dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
  833         if(ctlp->dev_nodes == NULL) {
  834                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
  835                 retval = ENOMEM;
  836                 goto nogo;
  837         }
  838 
  839         for (i = 0 ; i < rp_num_ports[unit] ; i++) {
  840                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
  841                                           UID_ROOT, GID_WHEEL, 0666, "ttyR%u%c",
  842                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  843                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
  844                                           UID_ROOT, GID_WHEEL, 0666, "ttyiR%u%c",
  845                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  846                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
  847                                           UID_ROOT, GID_WHEEL, 0666, "ttylR%u%c",
  848                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  849                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
  850                                           UID_ROOT, GID_WHEEL, 0666, "cuaR%u%c",
  851                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  852                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
  853                                           UID_ROOT, GID_WHEEL, 0666, "cuaiR%u%c",
  854                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  855                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
  856                                           UID_ROOT, GID_WHEEL, 0666, "cualR%u%c",
  857                                           unit, i <= 9 ? '' + i : 'a' + i - 10);
  858         }
  859 
  860         /* Aliases for compat. */
  861         if (unit == 0) {
  862                 dev_nodes = ctlp->dev_nodes;
  863                 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
  864                         make_dev_alias(*(dev_nodes++), "ttyR%c",
  865                                        i <= 9 ? '' + i : 'a' + i - 10);
  866                         make_dev_alias(*(dev_nodes++), "ttyiR%c",
  867                                        i <= 9 ? '' + i : 'a' + i - 10);
  868                         make_dev_alias(*(dev_nodes++), "ttylR%c",
  869                                        i <= 9 ? '' + i : 'a' + i - 10);
  870                         make_dev_alias(*(dev_nodes++), "cuaR%c",
  871                                        i <= 9 ? '' + i : 'a' + i - 10);
  872                         make_dev_alias(*(dev_nodes++), "cuaiR%c",
  873                                        i <= 9 ? '' + i : 'a' + i - 10);
  874                         make_dev_alias(*(dev_nodes++), "cualR%c",
  875                                        i <= 9 ? '' + i : 'a' + i - 10);
  876                 }
  877         }
  878 
  879         port = 0;
  880         for(aiop=0; aiop < num_aiops; aiop++) {
  881                 num_chan = sGetAiopNumChan(ctlp, aiop);
  882                 for(chan=0; chan < num_chan; chan++, port++, rp++) {
  883                         rp->rp_tty = ttymalloc(NULL);
  884                         rp->rp_port = port;
  885                         rp->rp_ctlp = ctlp;
  886                         rp->rp_unit = unit;
  887                         rp->rp_chan = chan;
  888                         rp->rp_aiop = aiop;
  889 
  890                         rp->rp_tty->t_line = 0;
  891         /*              tty->t_termios = deftermios;
  892         */
  893                         rp->it_in.c_iflag = 0;
  894                         rp->it_in.c_oflag = 0;
  895                         rp->it_in.c_cflag = TTYDEF_CFLAG;
  896                         rp->it_in.c_lflag = 0;
  897                         termioschars(&rp->it_in);
  898         /*              termioschars(&tty->t_termios);
  899         */
  900                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
  901                         rp->it_out = rp->it_in;
  902 
  903                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
  904                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
  905 #if notdef
  906                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  907 #endif /* notdef */
  908                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
  909                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
  910                                               unit, aiop, chan);
  911                                 retval = ENXIO;
  912                                 goto nogo;
  913                         }
  914                         ChanStatus = sGetChanStatus(&rp->rp_channel);
  915                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
  916                         line = (unit << 5) | (aiop << 3) | chan;
  917                         rp_table(line) = rp;
  918                 }
  919         }
  920 
  921         rp_ndevs++;
  922         return (0);
  923 
  924 nogo:
  925         rp_releaseresource(ctlp);
  926 
  927         return (retval);
  928 }
  929 
  930 void
  931 rp_releaseresource(CONTROLLER_t *ctlp)
  932 {
  933         int i, s, unit;
  934         struct  rp_port *rp;
  935 
  936 
  937         unit = device_get_unit(ctlp->dev);
  938         if (rp_addr(unit) != NULL) {
  939                 for (i = 0; i < rp_num_ports[unit]; i++) {
  940                         rp = rp_addr(unit) + i;
  941                         s = ttyrel(rp->rp_tty);
  942                         if (s) {
  943                                 printf("Detaching with active tty (%d refs)!\n", s);
  944                         }
  945                 }
  946         }
  947 
  948         if (ctlp->rp != NULL) {
  949                 s = spltty();
  950                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
  951                         if (p_rp_addr[i] == ctlp->rp)
  952                                 p_rp_addr[i] = NULL;
  953                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
  954                         if (p_rp_table[i] == ctlp->rp)
  955                                 p_rp_table[i] = NULL;
  956                 splx(s);
  957                 free(ctlp->rp, M_DEVBUF);
  958                 ctlp->rp = NULL;
  959         }
  960         if (ctlp->dev != NULL) {
  961                 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
  962                         destroy_dev(ctlp->dev_nodes[i]);
  963                 free(ctlp->dev_nodes, M_DEVBUF);
  964                 ctlp->dev = NULL;
  965         }
  966 }
  967 
  968 void
  969 rp_untimeout(void)
  970 {
  971         untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
  972 }
  973 static int
  974 rpopen(dev, flag, mode, td)
  975         struct cdev *dev;
  976         int     flag, mode;
  977         struct  thread  *td;
  978 {
  979         struct  rp_port *rp;
  980         int     unit, port, mynor, umynor, flags;  /* SG */
  981         struct  tty     *tp;
  982         int     oldspl, error;
  983         unsigned int    IntMask, ChanStatus;
  984 
  985 
  986    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
  987         port  = (minor(dev) & 0x1f);                /* SG */
  988         mynor = (port + umynor);                    /* SG */
  989         unit = minor_to_unit[mynor];
  990         if (rp_addr(unit) == NULL)
  991                 return (ENXIO);
  992         if(IS_CONTROL(dev))
  993                 return(0);
  994         rp = rp_addr(unit) + port;
  995 /*      rp->rp_tty = &rp_tty[rp->rp_port];
  996 */
  997         tp = rp->rp_tty;
  998         dev->si_tty = tp;
  999 
 1000         oldspl = spltty();
 1001 
 1002 open_top:
 1003         while(rp->state & ~SET_DTR) {
 1004                 error = tsleep(&tp->t_dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
 1005                 if(error != 0)
 1006                         goto out;
 1007         }
 1008 
 1009         if(tp->t_state & TS_ISOPEN) {
 1010                 if(IS_CALLOUT(dev)) {
 1011                         if(!rp->active_out) {
 1012                                 error = EBUSY;
 1013                                 goto out;
 1014                         }
 1015                 } else {
 1016                         if(rp->active_out) {
 1017                                 if(flag & O_NONBLOCK) {
 1018                                         error = EBUSY;
 1019                                         goto out;
 1020                                 }
 1021                                 error = tsleep(&rp->active_out,
 1022                                         TTIPRI | PCATCH, "rpbi", 0);
 1023                                 if(error != 0)
 1024                                         goto out;
 1025                                 goto open_top;
 1026                         }
 1027                 }
 1028                 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
 1029                         splx(oldspl);
 1030                         error = EBUSY;
 1031                         goto out2;
 1032                 }
 1033         }
 1034         else {
 1035                 tp->t_dev = dev;
 1036                 tp->t_param = rpparam;
 1037                 tp->t_oproc = rpstart;
 1038                 tp->t_stop = rpstop;
 1039                 tp->t_line = 0;
 1040                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
 1041                 tp->t_ififosize = 512;
 1042                 tp->t_ispeedwat = (speed_t)-1;
 1043                 tp->t_ospeedwat = (speed_t)-1;
 1044                 flags = 0;
 1045                 flags |= SET_RTS;
 1046                 flags |= SET_DTR;
 1047                 rp->rp_channel.TxControl[3] =
 1048                         ((rp->rp_channel.TxControl[3]
 1049                         & ~(SET_RTS | SET_DTR)) | flags);
 1050                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1051                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1052                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1053                 sDisRxStatusMode(&rp->rp_channel);
 1054                 sFlushRxFIFO(&rp->rp_channel);
 1055                 sFlushTxFIFO(&rp->rp_channel);
 1056 
 1057                 sEnInterrupts(&rp->rp_channel,
 1058                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
 1059                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1060 
 1061                 sDisRxStatusMode(&rp->rp_channel);
 1062                 sClrTxXOFF(&rp->rp_channel);
 1063 
 1064 /*              sDisRTSFlowCtl(&rp->rp_channel);
 1065                 sDisCTSFlowCtl(&rp->rp_channel);
 1066 */
 1067                 sDisTxSoftFlowCtl(&rp->rp_channel);
 1068 
 1069                 sStartRxProcessor(&rp->rp_channel);
 1070 
 1071                 sEnRxFIFO(&rp->rp_channel);
 1072                 sEnTransmit(&rp->rp_channel);
 1073 
 1074 /*              sSetDTR(&rp->rp_channel);
 1075                 sSetRTS(&rp->rp_channel);
 1076 */
 1077 
 1078                 ++rp->wopeners;
 1079                 error = rpparam(tp, &tp->t_termios);
 1080                 --rp->wopeners;
 1081                 if(error != 0) {
 1082                         splx(oldspl);
 1083                         return(error);
 1084                 }
 1085 
 1086                 rp_num_ports_open++;
 1087 
 1088                 IntMask = sGetChanIntID(&rp->rp_channel);
 1089                 IntMask = IntMask & rp->rp_intmask;
 1090                 ChanStatus = sGetChanStatus(&rp->rp_channel);
 1091                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
 1092                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
 1093                                         (void)ttyld_modem(tp, 1);
 1094                         }
 1095                 }
 1096 
 1097         if(rp_num_ports_open == 1)
 1098                 rp_callout_handle = timeout(rp_do_poll, 
 1099                                             (void *)NULL, POLL_INTERVAL);
 1100         }
 1101 
 1102         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
 1103                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
 1104                 ++rp->wopeners;
 1105                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1106                                 "rpdcd", 0);
 1107                 --rp->wopeners;
 1108                 if(error != 0)
 1109                         goto out;
 1110                 goto open_top;
 1111         }
 1112         error = ttyld_open(tp, dev);
 1113 
 1114         ttyldoptim(tp);
 1115         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
 1116                 rp->active_out = TRUE;
 1117 
 1118 /*      if(rp_num_ports_open == 1)
 1119                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1120 */
 1121 out:
 1122         splx(oldspl);
 1123         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
 1124                 rphardclose(rp);
 1125         }
 1126 out2:
 1127         if (error == 0)
 1128                 device_busy(rp->rp_ctlp->dev);
 1129         return(error);
 1130 }
 1131 
 1132 static int
 1133 rpclose(dev, flag, mode, td)
 1134         struct cdev *dev;
 1135         int     flag, mode;
 1136         struct  thread  *td;
 1137 {
 1138         int     oldspl, unit, mynor, umynor, port; /* SG */
 1139         struct  rp_port *rp;
 1140         struct  tty     *tp;
 1141         CHANNEL_t       *cp;
 1142 
 1143    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1144         port  = (minor(dev) & 0x1f);                /* SG */
 1145         mynor = (port + umynor);                    /* SG */
 1146    unit = minor_to_unit[mynor];                /* SG */
 1147 
 1148         if(IS_CONTROL(dev))
 1149                 return(0);
 1150         rp = rp_addr(unit) + port;
 1151         cp = &rp->rp_channel;
 1152         tp = rp->rp_tty;
 1153 
 1154         oldspl = spltty();
 1155         ttyld_close(tp, flag);
 1156         ttyldoptim(tp);
 1157         rphardclose(rp);
 1158 
 1159         tp->t_state &= ~TS_BUSY;
 1160         tty_close(tp);
 1161 
 1162         splx(oldspl);
 1163 
 1164         device_unbusy(rp->rp_ctlp->dev);
 1165 
 1166         return(0);
 1167 }
 1168 
 1169 static void
 1170 rphardclose(struct rp_port *rp)
 1171 {
 1172         int     mynor;
 1173         struct  tty     *tp;
 1174         CHANNEL_t       *cp;
 1175 
 1176         cp = &rp->rp_channel;
 1177         tp = rp->rp_tty;
 1178         mynor = MINOR_MAGIC(tp->t_dev);
 1179 
 1180         sFlushRxFIFO(cp);
 1181         sFlushTxFIFO(cp);
 1182         sDisTransmit(cp);
 1183         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1184         sDisRTSFlowCtl(cp);
 1185         sDisCTSFlowCtl(cp);
 1186         sDisTxSoftFlowCtl(cp);
 1187         sClrTxXOFF(cp);
 1188 
 1189         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1190                 sClrDTR(cp);
 1191         }
 1192         if(IS_CALLOUT(tp->t_dev)) {
 1193                 sClrDTR(cp);
 1194         }
 1195         if(tp->t_dtr_wait != 0) {
 1196                 timeout(rpdtrwakeup, rp, tp->t_dtr_wait);
 1197                 rp->state |= ~SET_DTR;
 1198         }
 1199 
 1200         rp->active_out = FALSE;
 1201         wakeup(&rp->active_out);
 1202         wakeup(TSA_CARR_ON(tp));
 1203 }
 1204 
 1205 static
 1206 int
 1207 rpwrite(dev, uio, flag)
 1208         struct cdev *dev;
 1209         struct  uio     *uio;
 1210         int     flag;
 1211 {
 1212         struct  rp_port *rp;
 1213         struct  tty     *tp;
 1214         int     unit, mynor, port, umynor, error = 0; /* SG */
 1215 
 1216    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1217         port  = (minor(dev) & 0x1f);                /* SG */
 1218         mynor = (port + umynor);                    /* SG */
 1219    unit = minor_to_unit[mynor];                /* SG */
 1220 
 1221         if(IS_CONTROL(dev))
 1222                 return(ENODEV);
 1223         rp = rp_addr(unit) + port;
 1224         tp = rp->rp_tty;
 1225         while(rp->rp_disable_writes) {
 1226                 rp->rp_waiting = 1;
 1227                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
 1228                 if (error)
 1229                         return(error);
 1230         }
 1231 
 1232         error = ttyld_write(tp, uio, flag);
 1233         return error;
 1234 }
 1235 
 1236 static void
 1237 rpdtrwakeup(void *chan)
 1238 {
 1239         struct  rp_port *rp;
 1240 
 1241         rp = (struct rp_port *)chan;
 1242         rp->state &= SET_DTR;
 1243         wakeup(&rp->rp_tty->t_dtr_wait);
 1244 }
 1245 
 1246 static int
 1247 rpioctl(dev, cmd, data, flag, td)
 1248         struct cdev *dev;
 1249         u_long  cmd;
 1250         caddr_t data;
 1251         int     flag;
 1252         struct  thread  *td;
 1253 {
 1254         struct rp_port  *rp;
 1255         CHANNEL_t       *cp;
 1256         struct tty      *tp;
 1257         int     unit, mynor, port, umynor;            /* SG */
 1258         int     oldspl;
 1259         int     error = 0;
 1260         int     arg, flags, result, ChanStatus;
 1261         struct  termios *t;
 1262 #ifndef BURN_BRIDGES
 1263 #if defined(COMPAT_43)
 1264         u_long  oldcmd;
 1265         struct  termios term;
 1266 #endif
 1267 #endif
 1268 
 1269    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1270         port  = (minor(dev) & 0x1f);                /* SG */
 1271         mynor = (port + umynor);                    /* SG */
 1272         unit = minor_to_unit[mynor];
 1273         rp = rp_addr(unit) + port;
 1274 
 1275         if(IS_CONTROL(dev)) {
 1276                 struct  termios *ct;
 1277 
 1278                 switch (IS_CONTROL(dev)) {
 1279                 case CONTROL_INIT_STATE:
 1280                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
 1281                         break;
 1282                 case CONTROL_LOCK_STATE:
 1283                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
 1284                         break;
 1285                 default:
 1286                         return(ENODEV);         /* /dev/nodev */
 1287                 }
 1288                 switch (cmd) {
 1289                 case TIOCSETA:
 1290                         error = suser(td);
 1291                         if(error != 0)
 1292                                 return(error);
 1293                         *ct = *(struct termios *)data;
 1294                         return(0);
 1295                 case TIOCGETA:
 1296                         *(struct termios *)data = *ct;
 1297                         return(0);
 1298                 case TIOCGETD:
 1299                         *(int *)data = TTYDISC;
 1300                         return(0);
 1301                 case TIOCGWINSZ:
 1302                         bzero(data, sizeof(struct winsize));
 1303                         return(0);
 1304                 default:
 1305                         return(ENOTTY);
 1306                 }
 1307         }
 1308 
 1309         tp = rp->rp_tty;
 1310         cp = &rp->rp_channel;
 1311 
 1312 #ifndef BURN_BRIDGES
 1313 #if defined(COMPAT_43)
 1314         term = tp->t_termios;
 1315         oldcmd = cmd;
 1316         error = ttsetcompat(tp, &cmd, data, &term);
 1317         if(error != 0)
 1318                 return(error);
 1319         if(cmd != oldcmd) {
 1320                 data = (caddr_t)&term;
 1321         }
 1322 #endif
 1323 #endif
 1324         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1325                 int     cc;
 1326                 struct  termios *dt = (struct termios *)data;
 1327                 struct  termios *lt = IS_CALLOUT(dev)
 1328                                         ? &rp->lt_out : &rp->lt_in;
 1329 
 1330                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1331                                 | (dt->c_iflag & ~lt->c_iflag);
 1332                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1333                                 | (dt->c_oflag & ~lt->c_oflag);
 1334                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1335                                 | (dt->c_cflag & ~lt->c_cflag);
 1336                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1337                                 | (dt->c_lflag & ~lt->c_lflag);
 1338                 for(cc = 0; cc < NCCS; ++cc)
 1339                         if(lt->c_cc[cc] != 0)
 1340                                 dt->c_cc[cc] = tp->t_cc[cc];
 1341                 if(lt->c_ispeed != 0)
 1342                         dt->c_ispeed = tp->t_ispeed;
 1343                 if(lt->c_ospeed != 0)
 1344                         dt->c_ospeed = tp->t_ospeed;
 1345         }
 1346 
 1347         t = &tp->t_termios;
 1348 
 1349         error = ttyioctl(dev, cmd, data, flag, td);
 1350         ttyldoptim(tp);
 1351         if(error != ENOTTY)
 1352                 return(error);
 1353         oldspl = spltty();
 1354 
 1355         flags = rp->rp_channel.TxControl[3];
 1356 
 1357         switch(cmd) {
 1358         case TIOCSBRK:
 1359                 sSendBreak(&rp->rp_channel);
 1360                 break;
 1361 
 1362         case TIOCCBRK:
 1363                 sClrBreak(&rp->rp_channel);
 1364                 break;
 1365 
 1366         case TIOCSDTR:
 1367                 sSetDTR(&rp->rp_channel);
 1368                 sSetRTS(&rp->rp_channel);
 1369                 break;
 1370 
 1371         case TIOCCDTR:
 1372                 sClrDTR(&rp->rp_channel);
 1373                 break;
 1374 
 1375         case TIOCMSET:
 1376                 arg = *(int *) data;
 1377                 flags = 0;
 1378                 if(arg & TIOCM_RTS)
 1379                         flags |= SET_RTS;
 1380                 if(arg & TIOCM_DTR)
 1381                         flags |= SET_DTR;
 1382                 rp->rp_channel.TxControl[3] =
 1383                         ((rp->rp_channel.TxControl[3]
 1384                         & ~(SET_RTS | SET_DTR)) | flags);
 1385                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1386                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1387                 break;
 1388         case TIOCMBIS:
 1389                 arg = *(int *) data;
 1390                 flags = 0;
 1391                 if(arg & TIOCM_RTS)
 1392                         flags |= SET_RTS;
 1393                 if(arg & TIOCM_DTR)
 1394                         flags |= SET_DTR;
 1395                         rp->rp_channel.TxControl[3] |= flags;
 1396                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1397                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1398                 break;
 1399         case TIOCMBIC:
 1400                 arg = *(int *) data;
 1401                 flags = 0;
 1402                 if(arg & TIOCM_RTS)
 1403                         flags |= SET_RTS;
 1404                 if(arg & TIOCM_DTR)
 1405                         flags |= SET_DTR;
 1406                 rp->rp_channel.TxControl[3] &= ~flags;
 1407                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
 1408                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1409                 break;
 1410 
 1411 
 1412         case TIOCMGET:
 1413                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
 1414                 flags = rp->rp_channel.TxControl[3];
 1415                 result = TIOCM_LE; /* always on while open for some reason */
 1416                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
 1417                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
 1418                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
 1419                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
 1420                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
 1421 
 1422                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
 1423                 {
 1424                         result |= TIOCM_RTS;
 1425                 }
 1426 
 1427                 *(int *)data = result;
 1428                 break;
 1429         default:
 1430                 splx(oldspl);
 1431                 return ENOTTY;
 1432         }
 1433         splx(oldspl);
 1434         return(0);
 1435 }
 1436 
 1437 static struct speedtab baud_table[] = {
 1438         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1439         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1440         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1441         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1442         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1443         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1444                                 {B57600, BRD57600},     {B76800, BRD76800},
 1445         {B115200, BRD115200},   {B230400, BRD230400},
 1446         {-1,    -1}
 1447 };
 1448 
 1449 static int
 1450 rpparam(tp, t)
 1451         struct tty *tp;
 1452         struct termios *t;
 1453 {
 1454         struct rp_port  *rp;
 1455         CHANNEL_t       *cp;
 1456         int     unit, mynor, port, umynor;               /* SG */
 1457         int     oldspl, cflag, iflag, oflag, lflag;
 1458         int     ospeed;
 1459 #ifdef RPCLOCAL
 1460         int     devshift;
 1461 #endif
 1462 
 1463 
 1464    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1465         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1466         mynor = (port + umynor);                          /* SG */
 1467 
 1468         unit = minor_to_unit[mynor];
 1469         rp = rp_addr(unit) + port;
 1470         cp = &rp->rp_channel;
 1471         oldspl = spltty();
 1472 
 1473         cflag = t->c_cflag;
 1474 #ifdef RPCLOCAL
 1475         devshift = umynor / 32;
 1476         devshift = 1 << devshift;
 1477         if ( devshift & RPCLOCAL ) {
 1478                 cflag |= CLOCAL;
 1479         }
 1480 #endif
 1481         iflag = t->c_iflag;
 1482         oflag = t->c_oflag;
 1483         lflag = t->c_lflag;
 1484 
 1485         ospeed = ttspeedtab(t->c_ispeed, baud_table);
 1486         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1487                 return(EINVAL);
 1488 
 1489         tp->t_ispeed = t->c_ispeed;
 1490         tp->t_ospeed = t->c_ospeed;
 1491         tp->t_cflag = cflag;
 1492         tp->t_iflag = iflag;
 1493         tp->t_oflag = oflag;
 1494         tp->t_lflag = lflag;
 1495 
 1496         if(t->c_ospeed == 0) {
 1497                 sClrDTR(cp);
 1498                 return(0);
 1499         }
 1500         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1501 
 1502         /* Set baud rate ----- we only pay attention to ispeed */
 1503         sSetDTR(cp);
 1504         sSetRTS(cp);
 1505         sSetBaud(cp, ospeed);
 1506 
 1507         if(cflag & CSTOPB) {
 1508                 sSetStop2(cp);
 1509         } else {
 1510                 sSetStop1(cp);
 1511         }
 1512 
 1513         if(cflag & PARENB) {
 1514                 sEnParity(cp);
 1515                 if(cflag & PARODD) {
 1516                         sSetOddParity(cp);
 1517                 } else {
 1518                         sSetEvenParity(cp);
 1519                 }
 1520         }
 1521         else {
 1522                 sDisParity(cp);
 1523         }
 1524         if((cflag & CSIZE) == CS8) {
 1525                 sSetData8(cp);
 1526                 rp->rp_imask = 0xFF;
 1527         } else {
 1528                 sSetData7(cp);
 1529                 rp->rp_imask = 0x7F;
 1530         }
 1531 
 1532         if(iflag & ISTRIP) {
 1533                 rp->rp_imask &= 0x7F;
 1534         }
 1535 
 1536         if(cflag & CLOCAL) {
 1537                 rp->rp_intmask &= ~DELTA_CD;
 1538         } else {
 1539                 rp->rp_intmask |= DELTA_CD;
 1540         }
 1541 
 1542         /* Put flow control stuff here */
 1543 
 1544         if(cflag & CCTS_OFLOW) {
 1545                 sEnCTSFlowCtl(cp);
 1546         } else {
 1547                 sDisCTSFlowCtl(cp);
 1548         }
 1549 
 1550         if(cflag & CRTS_IFLOW) {
 1551                 rp->rp_rts_iflow = 1;
 1552         } else {
 1553                 rp->rp_rts_iflow = 0;
 1554         }
 1555 
 1556         if(cflag & CRTS_IFLOW) {
 1557                 sEnRTSFlowCtl(cp);
 1558         } else {
 1559                 sDisRTSFlowCtl(cp);
 1560         }
 1561         ttyldoptim(tp);
 1562 
 1563         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
 1564                 tp->t_state |= TS_CARR_ON;
 1565                 wakeup(TSA_CARR_ON(tp));
 1566         }
 1567 
 1568 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1569         flags = rp->rp_channel.TxControl[3];
 1570         if(flags & SET_DTR)
 1571         else
 1572         if(flags & SET_RTS)
 1573         else
 1574 */
 1575         splx(oldspl);
 1576 
 1577         return(0);
 1578 }
 1579 
 1580 static void
 1581 rpstart(tp)
 1582         struct tty *tp;
 1583 {
 1584         struct rp_port  *rp;
 1585         CHANNEL_t       *cp;
 1586         struct  clist   *qp;
 1587         int     unit, mynor, port, umynor;               /* SG */
 1588         char    flags;
 1589         int     spl, xmit_fifo_room;
 1590         int     count, wcount;
 1591 
 1592 
 1593    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1594         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1595         mynor = (port + umynor);                          /* SG */
 1596         unit = minor_to_unit[mynor];
 1597         rp = rp_addr(unit) + port;
 1598         cp = &rp->rp_channel;
 1599         flags = rp->rp_channel.TxControl[3];
 1600         spl = spltty();
 1601 
 1602         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1603                 ttwwakeup(tp);
 1604                 splx(spl);
 1605                 return;
 1606         }
 1607         if(rp->rp_xmit_stopped) {
 1608                 sEnTransmit(cp);
 1609                 rp->rp_xmit_stopped = 0;
 1610         }
 1611         count = sGetTxCnt(cp);
 1612 
 1613         if(tp->t_outq.c_cc == 0) {
 1614                 if((tp->t_state & TS_BUSY) && (count == 0)) {
 1615                         tp->t_state &= ~TS_BUSY;
 1616                 }
 1617                 ttwwakeup(tp);
 1618                 splx(spl);
 1619                 return;
 1620         }
 1621         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1622         qp = &tp->t_outq;
 1623         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1624                 tp->t_state |= TS_BUSY;
 1625                 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
 1626                 wcount = count >> 1;
 1627                 if ( wcount ) {
 1628                         rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
 1629                 }
 1630                 if ( count & 1 ) {
 1631                         rp_writech1(cp, sGetTxRxDataIO(cp),
 1632                                     ((unsigned char *)(rp->TxBuf))[(count-1)]);
 1633                 }
 1634         }
 1635         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
 1636 
 1637         ttwwakeup(tp);
 1638         splx(spl);
 1639 }
 1640 
 1641 static
 1642 void
 1643 rpstop(tp, flag)
 1644         register struct tty *tp;
 1645         int     flag;
 1646 {
 1647         struct rp_port  *rp;
 1648         CHANNEL_t       *cp;
 1649         int     unit, mynor, port, umynor;                  /* SG */
 1650         int     spl;
 1651 
 1652    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1653         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1654         mynor = (port + umynor);                          /* SG */
 1655         unit = minor_to_unit[mynor];
 1656         rp = rp_addr(unit) + port;
 1657         cp = &rp->rp_channel;
 1658 
 1659         spl = spltty();
 1660 
 1661         if(tp->t_state & TS_BUSY) {
 1662                 if((tp->t_state&TS_TTSTOP) == 0) {
 1663                         sFlushTxFIFO(cp);
 1664                 } else {
 1665                         if(rp->rp_xmit_stopped == 0) {
 1666                                 sDisTransmit(cp);
 1667                                 rp->rp_xmit_stopped = 1;
 1668                         }
 1669                 }
 1670         }
 1671         splx(spl);
 1672         rpstart(tp);
 1673 }

Cache object: fe23072c6a41125b972a29ef0ee5d90e


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