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/i386/isa/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  * $FreeBSD$
   33  */
   34 
   35 /* 
   36  * rp.c - for RocketPort FreeBSD
   37  */
   38 
   39 #include "opt_compat.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/tty.h>
   46 #include <sys/proc.h>
   47 #include <sys/conf.h>
   48 #include <sys/kernel.h>
   49 
   50 #include <i386/isa/isa_device.h>
   51 
   52 #include <pci/pcivar.h>
   53 
   54 #define ROCKET_C
   55 #include <i386/isa/rpreg.h>
   56 #include <i386/isa/rpvar.h>
   57 
   58 #ifndef TRUE
   59 #define TRUE 1
   60 #endif
   61 
   62 #ifndef FALSE
   63 #define FALSE 0
   64 #endif
   65 
   66 static Byte_t RData[RDATASIZE] =
   67 {
   68    0x00, 0x09, 0xf6, 0x82,
   69    0x02, 0x09, 0x86, 0xfb,
   70    0x04, 0x09, 0x00, 0x0a,
   71    0x06, 0x09, 0x01, 0x0a,
   72    0x08, 0x09, 0x8a, 0x13,
   73    0x0a, 0x09, 0xc5, 0x11,
   74    0x0c, 0x09, 0x86, 0x85,
   75    0x0e, 0x09, 0x20, 0x0a,
   76    0x10, 0x09, 0x21, 0x0a,
   77    0x12, 0x09, 0x41, 0xff,
   78    0x14, 0x09, 0x82, 0x00,
   79    0x16, 0x09, 0x82, 0x7b,
   80    0x18, 0x09, 0x8a, 0x7d,
   81    0x1a, 0x09, 0x88, 0x81,
   82    0x1c, 0x09, 0x86, 0x7a,
   83    0x1e, 0x09, 0x84, 0x81,
   84    0x20, 0x09, 0x82, 0x7c,
   85    0x22, 0x09, 0x0a, 0x0a
   86 };
   87 
   88 static Byte_t RRegData[RREGDATASIZE]=
   89 {
   90    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
   91    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
   92    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
   93    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
   94    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
   95    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
   96    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
   97    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
   98    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
   99    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
  100    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
  101    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
  102    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
  103 };
  104 
  105 static CONTROLLER_T sController[CTL_SIZE] =
  106 {
  107    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  108    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  109    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  110    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
  111 };
  112 
  113 #if 0
  114 /* IRQ number to MUDBAC register 2 mapping */
  115 Byte_t sIRQMap[16] =
  116 {
  117    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  118 };
  119 #endif
  120 
  121 static Byte_t sBitMapClrTbl[8] =
  122 {
  123    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  124 };
  125 
  126 static Byte_t sBitMapSetTbl[8] =
  127 {
  128    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  129 };
  130 
  131 /***************************************************************************
  132 Function: sInitController
  133 Purpose:  Initialization of controller global registers and controller
  134           structure.
  135 Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
  136                           IRQNum,Frequency,PeriodicOnly)
  137           CONTROLLER_T *CtlP; Ptr to controller structure
  138           int CtlNum; Controller number
  139           ByteIO_t MudbacIO; Mudbac base I/O address.
  140           ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
  141              This list must be in the order the AIOPs will be found on the
  142              controller.  Once an AIOP in the list is not found, it is
  143              assumed that there are no more AIOPs on the controller.
  144           int AiopIOListSize; Number of addresses in AiopIOList
  145           int IRQNum; Interrupt Request number.  Can be any of the following:
  146                          0: Disable global interrupts
  147                          3: IRQ 3
  148                          4: IRQ 4
  149                          5: IRQ 5
  150                          9: IRQ 9
  151                          10: IRQ 10
  152                          11: IRQ 11
  153                          12: IRQ 12
  154                          15: IRQ 15
  155           Byte_t Frequency: A flag identifying the frequency
  156                    of the periodic interrupt, can be any one of the following:
  157                       FREQ_DIS - periodic interrupt disabled
  158                       FREQ_137HZ - 137 Hertz
  159                       FREQ_69HZ - 69 Hertz
  160                       FREQ_34HZ - 34 Hertz
  161                       FREQ_17HZ - 17 Hertz
  162                       FREQ_9HZ - 9 Hertz
  163                       FREQ_4HZ - 4 Hertz
  164                    If IRQNum is set to 0 the Frequency parameter is
  165                    overidden, it is forced to a value of FREQ_DIS.
  166           int PeriodicOnly: TRUE if all interrupts except the periodic
  167                                interrupt are to be blocked.
  168                             FALSE is both the periodic interrupt and
  169                                other channel interrupts are allowed.
  170                             If IRQNum is set to 0 the PeriodicOnly parameter is
  171                                overidden, it is forced to a value of FALSE.
  172 Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
  173                initialization failed.
  174 
  175 Comments:
  176           If periodic interrupts are to be disabled but AIOP interrupts
  177           are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
  178 
  179           If interrupts are to be completely disabled set IRQNum to 0.
  180 
  181           Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
  182           invalid combination.
  183 
  184           This function performs initialization of global interrupt modes,
  185           but it does not actually enable global interrupts.  To enable
  186           and disable global interrupts use functions sEnGlobalInt() and
  187           sDisGlobalInt().  Enabling of global interrupts is normally not
  188           done until all other initializations are complete.
  189 
  190           Even if interrupts are globally enabled, they must also be
  191           individually enabled for each channel that is to generate
  192           interrupts.
  193 
  194 Warnings: No range checking on any of the parameters is done.
  195 
  196           No context switches are allowed while executing this function.
  197 
  198           After this function all AIOPs on the controller are disabled,
  199           they can be enabled with sEnAiop().
  200 */
  201 int sInitController(    CONTROLLER_T *CtlP,
  202                         int CtlNum,
  203                         ByteIO_t MudbacIO,
  204                         ByteIO_t *AiopIOList,
  205                         int AiopIOListSize,
  206                         int IRQNum,
  207                         Byte_t Frequency,
  208                         int PeriodicOnly)
  209 {
  210         int             i;
  211         ByteIO_t        io;
  212 
  213    CtlP->CtlNum = CtlNum;
  214    CtlP->BusType = isISA;
  215    CtlP->CtlID = CTLID_0001;        /* controller release 1 */
  216 
  217    CtlP->MBaseIO = MudbacIO;
  218    CtlP->MReg1IO = MudbacIO + 1;
  219    CtlP->MReg2IO = MudbacIO + 2;
  220    CtlP->MReg3IO = MudbacIO + 3;
  221 #if 1
  222    CtlP->MReg2 = 0;                 /* interrupt disable */
  223    CtlP->MReg3 = 0;                 /* no periodic interrupts */
  224 #else
  225    if(sIRQMap[IRQNum] == 0)            /* interrupts globally disabled */
  226    {
  227       CtlP->MReg2 = 0;                 /* interrupt disable */
  228       CtlP->MReg3 = 0;                 /* no periodic interrupts */
  229    }
  230    else
  231    {
  232       CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
  233       CtlP->MReg3 = Frequency;         /* set frequency */
  234       if(PeriodicOnly)                 /* periodic interrupt only */
  235       {
  236          CtlP->MReg3 |= PERIODIC_ONLY;
  237       }
  238    }
  239 #endif
  240    sOutB(CtlP->MReg2IO,CtlP->MReg2);
  241    sOutB(CtlP->MReg3IO,CtlP->MReg3);
  242    sControllerEOI(CtlP);               /* clear EOI if warm init */
  243 
  244    /* Init AIOPs */
  245    CtlP->NumAiop = 0;
  246    for(i=0; i < AiopIOListSize; i++)
  247    {
  248       io = AiopIOList[i];
  249       CtlP->AiopIO[i] = (WordIO_t)io;
  250       CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
  251       sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
  252       sOutB(MudbacIO,(Byte_t)(io >> 6));        /* set up AIOP I/O in MUDBAC */
  253       sEnAiop(CtlP,i);                         /* enable the AIOP */
  254 
  255       CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
  256       if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
  257       {
  258          sDisAiop(CtlP,i);                     /* disable AIOP */
  259          break;                                /* done looking for AIOPs */
  260       }
  261 
  262       CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
  263       sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
  264       sOutB(io + _INDX_DATA,CLOCK_PRESC);
  265       CtlP->NumAiop++;                         /* bump count of AIOPs */
  266       sDisAiop(CtlP,i);                        /* disable AIOP */
  267    }
  268 
  269    if(CtlP->NumAiop == 0)
  270       return(-1);
  271    else
  272       return(CtlP->NumAiop);
  273 }
  274 
  275 int sPCIInitController( CONTROLLER_T *CtlP,
  276                         int CtlNum,
  277                         ByteIO_t *AiopIOList,
  278                         int AiopIOListSize,
  279                         int IRQNum,
  280                         Byte_t Frequency,
  281                         int PeriodicOnly)
  282 {
  283         int             i;
  284         ByteIO_t        io;
  285 
  286    CtlP->CtlNum = CtlNum;
  287    CtlP->BusType = isPCI;
  288    CtlP->CtlID = CTLID_0001;        /* controller release 1 */
  289    CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
  290 
  291    sPCIControllerEOI(CtlP);
  292 
  293    /* Init AIOPs */
  294    CtlP->NumAiop = 0;
  295    for(i=0; i < AiopIOListSize; i++)
  296    {
  297       io = AiopIOList[i];
  298       CtlP->AiopIO[i] = (WordIO_t)io;
  299       CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
  300 
  301       CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
  302       if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
  303       {
  304          break;                                /* done looking for AIOPs */
  305       }
  306 
  307       CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
  308       sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
  309       sOutB(io + _INDX_DATA,CLOCK_PRESC);
  310       CtlP->NumAiop++;                         /* bump count of AIOPs */
  311    }
  312 
  313    if(CtlP->NumAiop == 0)
  314       return(-1);
  315    else
  316       return(CtlP->NumAiop);
  317 }
  318 
  319 /***************************************************************************
  320 Function: sReadAiopID
  321 Purpose:  Read the AIOP idenfication number directly from an AIOP.
  322 Call:     sReadAiopID(io)
  323           ByteIO_t io: AIOP base I/O address
  324 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  325                  is replace by an identifying number.
  326           Flag AIOPID_NULL if no valid AIOP is found
  327 Warnings: No context switches are allowed while executing this function.
  328 
  329 */
  330 int sReadAiopID(ByteIO_t io)
  331 {
  332    Byte_t AiopID;               /* ID byte from AIOP */
  333 
  334    sOutB(io + _CMD_REG,RESET_ALL);     /* reset AIOP */
  335    sOutB(io + _CMD_REG,0x0);
  336    AiopID = sInB(io + _CHN_STAT0) & 0x07;
  337    if(AiopID == 0x06)
  338       return(1);
  339    else                                /* AIOP does not exist */
  340       return(-1);
  341 }
  342 
  343 /***************************************************************************
  344 Function: sReadAiopNumChan
  345 Purpose:  Read the number of channels available in an AIOP directly from
  346           an AIOP.
  347 Call:     sReadAiopNumChan(io)
  348           WordIO_t io: AIOP base I/O address
  349 Return:   int: The number of channels available
  350 Comments: The number of channels is determined by write/reads from identical
  351           offsets within the SRAM address spaces for channels 0 and 4.
  352           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  353           AIOP, otherwise it is an 8 channel.
  354 Warnings: No context switches are allowed while executing this function.
  355 */
  356 int sReadAiopNumChan(WordIO_t io)
  357 {
  358    Word_t x;
  359 
  360    sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  361    sOutW(io + _INDX_ADDR,0);       /* read from SRAM, chan 0 */
  362    x = sInW(io + _INDX_DATA);
  363    sOutW(io + _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  364    if(x != sInW(io + _INDX_DATA))  /* if different must be 8 chan */
  365       return(8);
  366    else
  367       return(4);
  368 }
  369 
  370 /***************************************************************************
  371 Function: sInitChan
  372 Purpose:  Initialization of a channel and channel structure
  373 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  374           CONTROLLER_T *CtlP; Ptr to controller structure
  375           CHANNEL_T *ChP; Ptr to channel structure
  376           int AiopNum; AIOP number within controller
  377           int ChanNum; Channel number within AIOP
  378 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  379                number exceeds number of channels available in AIOP.
  380 Comments: This function must be called before a channel can be used.
  381 Warnings: No range checking on any of the parameters is done.
  382 
  383           No context switches are allowed while executing this function.
  384 */
  385 int sInitChan(  CONTROLLER_T *CtlP,
  386                 CHANNEL_T *ChP,
  387                 int AiopNum,
  388                 int ChanNum)
  389 {
  390    int i;
  391    WordIO_t AiopIO;
  392    WordIO_t ChIOOff;
  393    Byte_t *ChR;
  394    Word_t ChOff;
  395    static Byte_t R[4];
  396 
  397    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  398       return(FALSE);                   /* exceeds num chans in AIOP */
  399 
  400    /* Channel, AIOP, and controller identifiers */
  401    ChP->CtlP = CtlP;
  402    ChP->ChanID = CtlP->AiopID[AiopNum];
  403    ChP->AiopNum = AiopNum;
  404    ChP->ChanNum = ChanNum;
  405 
  406    /* Global direct addresses */
  407    AiopIO = CtlP->AiopIO[AiopNum];
  408    ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
  409    ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
  410    ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
  411    ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
  412    ChP->IndexData = AiopIO + _INDX_DATA;
  413 
  414    /* Channel direct addresses */
  415    ChIOOff = AiopIO + ChP->ChanNum * 2;
  416    ChP->TxRxData = ChIOOff + _TD0;
  417    ChP->ChanStat = ChIOOff + _CHN_STAT0;
  418    ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
  419    ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
  420 
  421    /* Initialize the channel from the RData array */
  422    for(i=0; i < RDATASIZE; i+=4)
  423    {
  424       R[0] = RData[i];
  425       R[1] = RData[i+1] + 0x10 * ChanNum;
  426       R[2] = RData[i+2];
  427       R[3] = RData[i+3];
  428       sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
  429    }
  430 
  431    ChR = ChP->R;
  432    for(i=0; i < RREGDATASIZE; i+=4)
  433    {
  434       ChR[i] = RRegData[i];
  435       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  436       ChR[i+2] = RRegData[i+2];
  437       ChR[i+3] = RRegData[i+3];
  438    }
  439 
  440    /* Indexed registers */
  441    ChOff = (Word_t)ChanNum * 0x1000;
  442 
  443    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  444    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  445    ChP->BaudDiv[2] = (Byte_t)BRD9600;
  446    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
  447    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
  448 
  449    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  450    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  451    ChP->TxControl[2] = 0;
  452    ChP->TxControl[3] = 0;
  453    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  454 
  455    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  456    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  457    ChP->RxControl[2] = 0;
  458    ChP->RxControl[3] = 0;
  459    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  460 
  461    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  462    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  463    ChP->TxEnables[2] = 0;
  464    ChP->TxEnables[3] = 0;
  465    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
  466 
  467    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  468    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  469    ChP->TxCompare[2] = 0;
  470    ChP->TxCompare[3] = 0;
  471    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
  472 
  473    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  474    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  475    ChP->TxReplace1[2] = 0;
  476    ChP->TxReplace1[3] = 0;
  477    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
  478 
  479    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  480    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  481    ChP->TxReplace2[2] = 0;
  482    ChP->TxReplace2[3] = 0;
  483    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
  484 
  485    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  486    ChP->TxFIFO = ChOff + _TX_FIFO;
  487 
  488    sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  489    sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  490    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  491    sOutW(ChP->IndexData,0);
  492    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  493    ChP->RxFIFO = ChOff + _RX_FIFO;
  494 
  495    sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  496    sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  497    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  498    sOutW(ChP->IndexData,0);
  499    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  500    sOutW(ChP->IndexData,0);
  501    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  502    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
  503    sOutB(ChP->IndexData,0);
  504    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  505    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
  506    sOutB(ChP->IndexData,0);
  507    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  508    sEnRxProcessor(ChP);                /* start the Rx processor */
  509 
  510    return(TRUE);
  511 }
  512 
  513 /***************************************************************************
  514 Function: sStopRxProcessor
  515 Purpose:  Stop the receive processor from processing a channel.
  516 Call:     sStopRxProcessor(ChP)
  517           CHANNEL_T *ChP; Ptr to channel structure
  518 
  519 Comments: The receive processor can be started again with sStartRxProcessor().
  520           This function causes the receive processor to skip over the
  521           stopped channel.  It does not stop it from processing other channels.
  522 
  523 Warnings: No context switches are allowed while executing this function.
  524 
  525           Do not leave the receive processor stopped for more than one
  526           character time.
  527 
  528           After calling this function a delay of 4 uS is required to ensure
  529           that the receive processor is no longer processing this channel.
  530 */
  531 void sStopRxProcessor(CHANNEL_T *ChP)
  532 {
  533    Byte_t R[4];
  534 
  535    R[0] = ChP->R[0];
  536    R[1] = ChP->R[1];
  537    R[2] = 0x0a;
  538    R[3] = ChP->R[3];
  539    sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
  540 }
  541 
  542 /***************************************************************************
  543 Function: sFlushRxFIFO
  544 Purpose:  Flush the Rx FIFO
  545 Call:     sFlushRxFIFO(ChP)
  546           CHANNEL_T *ChP; Ptr to channel structure
  547 Return:   void
  548 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  549           while it is being flushed the receive processor is stopped
  550           and the transmitter is disabled.  After these operations a
  551           4 uS delay is done before clearing the pointers to allow
  552           the receive processor to stop.  These items are handled inside
  553           this function.
  554 Warnings: No context switches are allowed while executing this function.
  555 */
  556 void sFlushRxFIFO(CHANNEL_T *ChP)
  557 {
  558    int i;
  559    Byte_t Ch;                   /* channel number within AIOP */
  560    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  561 
  562    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  563       return;                          /* don't need to flush */
  564 
  565    RxFIFOEnabled = FALSE;
  566    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  567    {
  568       RxFIFOEnabled = TRUE;
  569       sDisRxFIFO(ChP);                 /* disable it */
  570       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
  571          sInB(ChP->IntChan);            /* depends on bus i/o timing */
  572    }
  573    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  574    Ch = (Byte_t)sGetChanNum(ChP);
  575    sOutB(ChP->Cmd,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  576    sOutB(ChP->Cmd,Ch);                 /* remove reset Rx FIFO count */
  577    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  578    sOutW(ChP->IndexData,0);
  579    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  580    sOutW(ChP->IndexData,0);
  581    if(RxFIFOEnabled)
  582       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  583 }
  584 
  585 /***************************************************************************
  586 Function: sFlushTxFIFO
  587 Purpose:  Flush the Tx FIFO
  588 Call:     sFlushTxFIFO(ChP)
  589           CHANNEL_T *ChP; Ptr to channel structure
  590 Return:   void
  591 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  592           while it is being flushed the receive processor is stopped
  593           and the transmitter is disabled.  After these operations a
  594           4 uS delay is done before clearing the pointers to allow
  595           the receive processor to stop.  These items are handled inside
  596           this function.
  597 Warnings: No context switches are allowed while executing this function.
  598 */
  599 void sFlushTxFIFO(CHANNEL_T *ChP)
  600 {
  601    int i;
  602    Byte_t Ch;                   /* channel number within AIOP */
  603    int TxEnabled;                      /* TRUE if transmitter enabled */
  604 
  605    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  606       return;                          /* don't need to flush */
  607 
  608    TxEnabled = FALSE;
  609    if(ChP->TxControl[3] & TX_ENABLE)
  610    {
  611       TxEnabled = TRUE;
  612       sDisTransmit(ChP);               /* disable transmitter */
  613    }
  614    sStopRxProcessor(ChP);              /* stop Rx processor */
  615    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  616       sInB(ChP->IntChan);       /* depends on bus i/o timing */
  617    Ch = (Byte_t)sGetChanNum(ChP);
  618    sOutB(ChP->Cmd,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  619    sOutB(ChP->Cmd,Ch);                 /* remove reset Tx FIFO count */
  620    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  621    sOutW(ChP->IndexData,0);
  622    if(TxEnabled)
  623       sEnTransmit(ChP);                /* enable transmitter */
  624    sStartRxProcessor(ChP);             /* restart Rx processor */
  625 }
  626 
  627 /***************************************************************************
  628 Function: sWriteTxPrioByte
  629 Purpose:  Write a byte of priority transmit data to a channel
  630 Call:     sWriteTxPrioByte(ChP,Data)
  631           CHANNEL_T *ChP; Ptr to channel structure
  632           Byte_t Data; The transmit data byte
  633 
  634 Return:   int: 1 if the bytes is successfully written, otherwise 0.
  635 
  636 Comments: The priority byte is transmitted before any data in the Tx FIFO.
  637 
  638 Warnings: No context switches are allowed while executing this function.
  639 */
  640 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  641 {
  642    Byte_t DWBuf[4];             /* buffer for double word writes */
  643    Word_t *WordPtr;          /* must be far because Win SS != DS */
  644    register DWordIO_t IndexAddr;
  645 
  646    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  647    {
  648       IndexAddr = ChP->IndexAddr;
  649       sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
  650       if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
  651          return(0);                    /* nothing sent */
  652 
  653       WordPtr = (Word_t *)(&DWBuf[0]);
  654       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
  655 
  656       DWBuf[2] = Data;                 /* data byte value */
  657       sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  658 
  659       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
  660 
  661       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  662       DWBuf[3] = 0;                    /* priority buffer pointer */
  663       sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  664    }
  665    else                                /* write it to Tx FIFO */
  666    {
  667       sWriteTxByte(sGetTxRxDataIO(ChP),Data);
  668    }
  669    return(1);                          /* 1 byte sent */
  670 }
  671 
  672 /***************************************************************************
  673 Function: sEnInterrupts
  674 Purpose:  Enable one or more interrupts for a channel
  675 Call:     sEnInterrupts(ChP,Flags)
  676           CHANNEL_T *ChP; Ptr to channel structure
  677           Word_t Flags: Interrupt enable flags, can be any combination
  678              of the following flags:
  679                 TXINT_EN:   Interrupt on Tx FIFO empty
  680                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  681                             sSetRxTrigger())
  682                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  683                 MCINT_EN:   Interrupt on modem input change
  684                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  685                             Interrupt Channel Register.
  686 Return:   void
  687 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  688           enabled.  If an interrupt enable flag is not set in Flags, that
  689           interrupt will not be changed.  Interrupts can be disabled with
  690           function sDisInterrupts().
  691 
  692           This function sets the appropriate bit for the channel in the AIOP's
  693           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  694           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  695 
  696           Interrupts must also be globally enabled before channel interrupts
  697           will be passed on to the host.  This is done with function
  698           sEnGlobalInt().
  699 
  700           In some cases it may be desirable to disable interrupts globally but
  701           enable channel interrupts.  This would allow the global interrupt
  702           status register to be used to determine which AIOPs need service.
  703 */
  704 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  705 {
  706    Byte_t Mask;                 /* Interrupt Mask Register */
  707 
  708    ChP->RxControl[2] |=
  709       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  710 
  711    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  712 
  713    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  714 
  715    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  716 
  717    if(Flags & CHANINT_EN)
  718    {
  719       Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
  720       sOutB(ChP->IntMask,Mask);
  721    }
  722 }
  723 
  724 /***************************************************************************
  725 Function: sDisInterrupts
  726 Purpose:  Disable one or more interrupts for a channel
  727 Call:     sDisInterrupts(ChP,Flags)
  728           CHANNEL_T *ChP; Ptr to channel structure
  729           Word_t Flags: Interrupt flags, can be any combination
  730              of the following flags:
  731                 TXINT_EN:   Interrupt on Tx FIFO empty
  732                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  733                             sSetRxTrigger())
  734                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  735                 MCINT_EN:   Interrupt on modem input change
  736                 CHANINT_EN: Disable channel interrupt signal to the
  737                             AIOP's Interrupt Channel Register.
  738 Return:   void
  739 Comments: If an interrupt flag is set in Flags, that interrupt will be
  740           disabled.  If an interrupt flag is not set in Flags, that
  741           interrupt will not be changed.  Interrupts can be enabled with
  742           function sEnInterrupts().
  743 
  744           This function clears the appropriate bit for the channel in the AIOP's
  745           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  746           this channel's bit from being set in the AIOP's Interrupt Channel
  747           Register.
  748 */
  749 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  750 {
  751    Byte_t Mask;                 /* Interrupt Mask Register */
  752 
  753    ChP->RxControl[2] &=
  754          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  755    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  756    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  757    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  758 
  759    if(Flags & CHANINT_EN)
  760    {
  761       Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
  762       sOutB(ChP->IntMask,Mask);
  763    }
  764 }
  765 
  766 /*********************************************************************
  767   Begin FreeBsd-specific driver code
  768 **********************************************************************/
  769 
  770 static int rpprobe __P((struct isa_device *));
  771 static int rpattach __P((struct isa_device *));
  772 
  773 static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
  774 static void rp_pciattach(pcici_t tag, int unit);
  775 static u_long   rp_pcicount;
  776 
  777 static struct pci_device rp_pcidevice = {
  778         "rp",
  779         rp_pciprobe,
  780         rp_pciattach,
  781         &rp_pcicount,
  782         NULL
  783 };
  784 
  785 COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
  786 
  787 static timeout_t rpdtrwakeup;
  788 
  789 struct isa_driver rpdriver = {
  790         rpprobe, rpattach, "rp"
  791      };
  792 
  793 static  char    driver_name[] = "rp";
  794 
  795 static  d_open_t        rpopen;
  796 static  d_close_t       rpclose;
  797 static  d_write_t       rpwrite;
  798 static  d_ioctl_t       rpioctl;
  799 
  800 #define CDEV_MAJOR      81
  801 static struct cdevsw rp_cdevsw = {
  802         /* open */      rpopen,
  803         /* close */     rpclose,
  804         /* read */      ttyread,
  805         /* write */     rpwrite,
  806         /* ioctl */     rpioctl,
  807         /* poll */      ttypoll,
  808         /* mmap */      nommap,
  809         /* strategy */  nostrategy,
  810         /* name */      driver_name,
  811         /* maj */       CDEV_MAJOR,
  812         /* dump */      nodump,
  813         /* psize */     nopsize,
  814         /* flags */     D_TTY | D_KQFILTER,
  815         /* bmaj */      -1,
  816         /* kqfilter */  ttykqfilter,
  817 };
  818 
  819 static int rp_controller_port = 0;
  820 static int rp_num_ports_open = 0;
  821 static int      ndevs = 0;
  822 static int      minor_to_unit[128];
  823 #if 0
  824 static  struct  tty     rp_tty[128];
  825 #endif
  826 
  827 static int rp_num_ports[4];     /* Number of ports on each controller */
  828 
  829 #define _INLINE_ __inline
  830 #define POLL_INTERVAL 1
  831 
  832 #define CALLOUT_MASK            0x80
  833 #define CONTROL_MASK            0x60
  834 #define CONTROL_INIT_STATE      0x20
  835 #define CONTROL_LOCK_STATE      0x40
  836 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  837 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  838 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  839 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  840 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  841 
  842 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  843 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  844 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  845 
  846 static  struct  rp_port *p_rp_addr[4];
  847 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  848 #define rp_addr(unit)   (p_rp_addr[unit])
  849 #define rp_table(port)  (p_rp_table[port])
  850 
  851 /*
  852  * The top-level routines begin here
  853  */
  854 
  855 static  int     rpparam __P((struct tty *, struct termios *));
  856 static  void    rpstart __P((struct tty *));
  857 static  void    rpstop __P((struct tty *, int));
  858 static  void    rphardclose     __P((struct rp_port *));
  859 static  void    rp_disc_optim   __P((struct tty *tp, struct termios *t,
  860                                                 struct rp_port  *rp));
  861 
  862 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
  863                         CHANNEL_t *cp, unsigned int ChanStatus)
  864 {
  865         int     spl;
  866         unsigned        int     CharNStat;
  867         int     ToRecv, ch;
  868 
  869         ToRecv = sGetRxCnt(cp);
  870         if(ToRecv == 0)
  871                 return;
  872 
  873 /*      If status indicates there are errored characters in the
  874         FIFO, then enter status mode (a word in FIFO holds
  875         characters and status)
  876 */
  877 
  878         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  879                 if(!(ChanStatus & STATMODE)) {
  880                         ChanStatus |= STATMODE;
  881                         sEnRxStatusMode(cp);
  882                 }
  883         }
  884 /*
  885         if we previously entered status mode then read down the
  886         FIFO one word at a time, pulling apart the character and
  887         the status. Update error counters depending on status.
  888 */
  889         if(ChanStatus & STATMODE) {
  890                 while(ToRecv) {
  891                         if(tp->t_state & TS_TBLOCK) {
  892                                 break;
  893                         }
  894                         CharNStat = sInW(sGetTxRxDataIO(cp));
  895                         ch = CharNStat & 0xff;
  896 
  897                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  898                                 ch |= TTY_FE;
  899                         else if (CharNStat & STMPARITYH)
  900                                 ch |= TTY_PE;
  901                         else if (CharNStat & STMRCVROVRH)
  902                                 rp->rp_overflows++;
  903 
  904                         (*linesw[tp->t_line].l_rint)(ch, tp);
  905                         ToRecv--;
  906                 }
  907 /*
  908         After emtying FIFO in status mode, turn off status mode
  909 */
  910 
  911         if(sGetRxCnt(cp) == 0)
  912                 sDisRxStatusMode(cp);
  913         }
  914         else {
  915                 while (ToRecv) {
  916                         if(tp->t_state & TS_TBLOCK) {
  917                                 break;
  918                         }
  919                         ch = (u_char) sInB(sGetTxRxDataIO(cp));
  920                         spl = spltty();
  921                         (*linesw[tp->t_line].l_rint)(ch, tp);
  922                         splx(spl);
  923                         ToRecv--;
  924                 }
  925         }
  926 }
  927 
  928 static _INLINE_ void rp_handle_port(struct rp_port *rp)
  929 {
  930         CHANNEL_t       *cp;
  931         struct  tty     *tp;
  932         unsigned        int     IntMask, ChanStatus;
  933      /* int     oldcts; */
  934 
  935         if(!rp)
  936                 return;
  937 
  938         cp = &rp->rp_channel;
  939         tp = rp->rp_tty;
  940         IntMask = sGetChanIntID(cp);
  941         IntMask = IntMask & rp->rp_intmask;
  942         ChanStatus = sGetChanStatus(cp);
  943         if(IntMask & RXF_TRIG)
  944                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  945                         rp_do_receive(rp, tp, cp, ChanStatus);
  946                 }
  947         if(IntMask & DELTA_CD) {
  948                 if(ChanStatus & CD_ACT) {
  949                         if(!(tp->t_state & TS_CARR_ON) ) {
  950                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  951                         }
  952                 } else {
  953                         if((tp->t_state & TS_CARR_ON)) {
  954                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  955                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
  956                                         rphardclose(rp);
  957                                 }
  958                         }
  959                 }
  960         }
  961 /*      oldcts = rp->rp_cts;
  962         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  963         if(oldcts != rp->rp_cts) {
  964                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  965         }
  966 */
  967 }
  968 
  969 static void rp_do_poll(void *not_used)
  970 {
  971         CONTROLLER_t    *ctl;
  972         struct rp_port  *rp;
  973         struct tty      *tp;
  974         int     unit, aiop, ch, line, count;
  975         unsigned char   CtlMask, AiopMask;
  976 
  977         for(unit = 0; unit <= ndevs; unit++) {
  978         rp = rp_addr(unit);
  979         ctl = rp->rp_ctlp;
  980         if(ctl->BusType == isPCI)
  981                 CtlMask = sPCIGetControllerIntStatus(ctl);
  982         else
  983                 CtlMask = sGetControllerIntStatus(ctl);
  984         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  985                 if(CtlMask & 1) {
  986                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  987                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  988                                 if(AiopMask & 1) {
  989                                         line = (unit << 5) | (aiop << 3) | ch;
  990                                         rp = rp_table(line);
  991                                         rp_handle_port(rp);
  992                                 }
  993                         }
  994                 }
  995         }
  996 
  997         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  998                         line++, rp++) {
  999                 tp = rp->rp_tty;
 1000                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
 1001                         count = sGetTxCnt(&rp->rp_channel);
 1002                         if(count == 0)
 1003                                 tp->t_state &= ~(TS_BUSY);
 1004                         if(!(tp->t_state & TS_TTSTOP) &&
 1005                                 (count <= rp->rp_restart)) {
 1006                                 (*linesw[tp->t_line].l_start)(tp);
 1007                         }
 1008                 }
 1009         }
 1010         }
 1011         if(rp_num_ports_open)
 1012                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1013 }
 1014 
 1015 static const char*
 1016 rp_pciprobe(pcici_t tag, pcidi_t type)
 1017 {
 1018         int     vendor_id;
 1019 
 1020         vendor_id = type & 0xffff;
 1021         switch(vendor_id)
 1022         case 0x11fe:
 1023                 return("rp");
 1024         return(NULL);
 1025 }
 1026 
 1027 static
 1028 int
 1029 rpprobe(dev)
 1030 struct isa_device *dev;
 1031 {
 1032         int controller, unit;
 1033         int aiop, num_aiops;
 1034         unsigned int aiopio[MAX_AIOPS_PER_BOARD];
 1035         CONTROLLER_t *ctlp;
 1036 
 1037         unit = dev->id_unit;
 1038         if (dev->id_unit >= 4) {
 1039                 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
 1040                 return 1;
 1041         }
 1042         printf("probing for RocketPort(ISA) unit %d\n", unit);
 1043         if (rp_controller_port)
 1044                 controller = rp_controller_port;
 1045         else {
 1046                 controller = dev->id_iobase + 0x40;
 1047         }
 1048 
 1049         for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
 1050                 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
 1051 
 1052         ctlp = sCtlNumToCtlPtr(dev->id_unit);
 1053         num_aiops = sInitController(ctlp, dev->id_unit,
 1054                                 controller + ((unit-rp_pcicount)*0x400),
 1055                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1056                                 FREQ_DIS, 0);
 1057         if (num_aiops <= 0) {
 1058                 printf("board%d init failed\n", unit);
 1059                 return 0;
 1060         }
 1061 
 1062         if (rp_controller_port) {
 1063                 dev->id_msize = 64;
 1064         } else {
 1065                 dev->id_msize = 68;
 1066                 rp_controller_port = controller;
 1067         }
 1068 
 1069         dev->id_irq = 0;
 1070 
 1071         return 1;
 1072 }
 1073 
 1074 static void
 1075 rp_pciattach(pcici_t tag, int unit)
 1076 {
 1077         int     success, oldspl;
 1078         u_short iobase;
 1079         int     num_ports, num_chan, num_aiops;
 1080         int     aiop, chan, port;
 1081         int     ChanStatus, line, i, count;
 1082         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
 1083         struct  rp_port *rp;
 1084         struct  tty     *tty;
 1085         CONTROLLER_t    *ctlp;
 1086 
 1087         success = pci_map_port(tag, 0x10, &iobase);
 1088         if(!success)
 1089                 printf("ioaddr mapping failed for RocketPort(PCI)\n");
 1090 
 1091         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
 1092                 aiopio[aiop] = iobase + (aiop * 0x40);
 1093 
 1094         ctlp = sCtlNumToCtlPtr(unit);
 1095         num_aiops = sPCIInitController(ctlp, unit,
 1096                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1097                                 FREQ_DIS, 0);
 1098 
 1099         num_ports = 0;
 1100         for(aiop=0; aiop < num_aiops; aiop++) {
 1101                 sResetAiopByNum(ctlp, aiop);
 1102                 num_ports += sGetAiopNumChan(ctlp, aiop);
 1103         }
 1104         printf("RocketPort%d = %d ports\n", unit, num_ports);
 1105         rp_num_ports[unit] = num_ports;
 1106 
 1107         rp = (struct rp_port *)
 1108                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
 1109         if(rp == 0) {
 1110                 printf("rp_attach: Could not malloc rp_ports structures\n");
 1111                 return;
 1112         }
 1113 
 1114         count = unit * 32;      /* board times max ports per card SG */
 1115         for(i=count;i < (count + rp_num_ports[unit]);i++)
 1116                 minor_to_unit[i] = unit;
 1117 
 1118         bzero(rp, sizeof(struct rp_port) * num_ports);
 1119         tty = (struct tty *)
 1120                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
 1121         if(tty == 0) {
 1122                 printf("rp_attach: Could not malloc tty structures\n");
 1123                 return;
 1124         }
 1125         bzero(tty, sizeof(struct tty) * num_ports);
 1126 
 1127         oldspl = spltty();
 1128         rp_addr(unit) = rp;
 1129         splx(oldspl);
 1130 
 1131         cdevsw_add(&rp_cdevsw);
 1132 
 1133         port = 0;
 1134         for(aiop=0; aiop < num_aiops; aiop++) {
 1135                 num_chan = sGetAiopNumChan(ctlp, aiop);
 1136                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
 1137                         rp->rp_tty = tty;
 1138                         rp->rp_port = port;
 1139                         rp->rp_ctlp = ctlp;
 1140                         rp->rp_unit = unit;
 1141                         rp->rp_chan = chan;
 1142                         rp->rp_aiop = aiop;
 1143 
 1144                         tty->t_line = 0;
 1145         /*              tty->t_termios = deftermios;
 1146         */
 1147                         rp->dtr_wait = 3 * hz;
 1148                         rp->it_in.c_iflag = 0;
 1149                         rp->it_in.c_oflag = 0;
 1150                         rp->it_in.c_cflag = TTYDEF_CFLAG;
 1151                         rp->it_in.c_lflag = 0;
 1152                         termioschars(&rp->it_in);
 1153         /*              termioschars(&tty->t_termios);
 1154         */
 1155                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
 1156                         rp->it_out = rp->it_in;
 1157 
 1158                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
 1159                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
 1160                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1161                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
 1162                                 printf("RocketPort sInitChan(%d, %d, %d) failed
 1163                                         \n", unit, aiop, chan);
 1164                                 return;
 1165                         }
 1166                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1167                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
 1168                         line = (unit << 5) | (aiop << 3) | chan;
 1169                         rp_table(line) = rp;
 1170                 }
 1171         }
 1172 }
 1173 
 1174 static
 1175 int
 1176 rpattach(dev)
 1177 struct  isa_device      *dev;
 1178 {
 1179         int     iobase, unit, /*rpmajor,*/ oldspl;
 1180         int     num_ports, num_chan, num_aiops;
 1181         int     aiop, chan, port;
 1182         int     ChanStatus, line, i, count;
 1183         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
 1184         struct  rp_port *rp;
 1185         struct  tty     *tty;
 1186         CONTROLLER_t    *ctlp;
 1187 
 1188         iobase = dev->id_iobase;
 1189         unit = dev->id_unit;
 1190         ndevs = unit;
 1191 
 1192         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
 1193                 aiopio[aiop] = iobase + (aiop * 0x400);
 1194 
 1195         ctlp = sCtlNumToCtlPtr(unit);
 1196         num_aiops = sInitController(ctlp, unit,
 1197                                 rp_controller_port + ((unit-rp_pcicount) * 0x400),
 1198                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1199                                 FREQ_DIS, 0);
 1200 
 1201         num_ports = 0;
 1202         for(aiop=0; aiop < num_aiops; aiop++) {
 1203                 sResetAiopByNum(ctlp, aiop);
 1204                 sEnAiop(ctlp, aiop);
 1205                 num_ports += sGetAiopNumChan(ctlp, aiop);
 1206         }
 1207         printf("RocketPort%d = %d ports\n", unit, num_ports);
 1208         rp_num_ports[unit] = num_ports;
 1209 
 1210         rp = (struct rp_port *)
 1211                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
 1212         if(rp == 0) {
 1213                 printf("rp_attach: Could not malloc rp_ports structures\n");
 1214                 return(0);
 1215         }
 1216 
 1217         count = unit * 32;    /* board # times max ports per card  SG */
 1218         for(i=count;i < (count + rp_num_ports[unit]);i++)
 1219                 minor_to_unit[i] = unit;
 1220 
 1221         bzero(rp, sizeof(struct rp_port) * num_ports);
 1222         tty = (struct tty *)
 1223                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
 1224         if(tty == 0) {
 1225                 printf("rp_attach: Could not malloc tty structures\n");
 1226                 return(0);
 1227         }
 1228         bzero(tty, sizeof(struct tty) * num_ports);
 1229 
 1230         oldspl = spltty();
 1231         rp_addr(unit) = rp;
 1232         splx(oldspl);
 1233 
 1234         cdevsw_add(&rp_cdevsw);
 1235 
 1236         port = 0;
 1237         for(aiop=0; aiop < num_aiops; aiop++) {
 1238                 num_chan = sGetAiopNumChan(ctlp, aiop);
 1239                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
 1240                         rp->rp_tty = tty;
 1241                         rp->rp_port = port;
 1242                         rp->rp_ctlp = ctlp;
 1243                         rp->rp_unit = unit;
 1244                         rp->rp_chan = chan;
 1245                         rp->rp_aiop = aiop;
 1246 
 1247                         tty->t_line = 0;
 1248         /*              tty->t_termios = deftermios;
 1249         */
 1250                         rp->dtr_wait = 3 * hz;
 1251                         rp->it_in.c_iflag = 0;
 1252                         rp->it_in.c_oflag = 0;
 1253                         rp->it_in.c_cflag = TTYDEF_CFLAG;
 1254                         rp->it_in.c_lflag = 0;
 1255                         termioschars(&rp->it_in);
 1256         /*              termioschars(&tty->t_termios);
 1257         */
 1258                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
 1259                         rp->it_out = rp->it_in;
 1260 
 1261                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
 1262                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
 1263                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1264                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
 1265                                 printf("RocketPort sInitChan(%d, %d, %d) failed
 1266                                         \n", unit, aiop, chan);
 1267                                 return(0);
 1268                         }
 1269                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1270                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
 1271                         line = (unit << 5) | (aiop << 3) | chan;
 1272                         rp_table(line) = rp;
 1273                 }
 1274         }
 1275 
 1276         return(1);
 1277 }
 1278 
 1279 int
 1280 rpopen(dev, flag, mode, p)
 1281         dev_t   dev;
 1282         int     flag, mode;
 1283         struct  proc    *p;
 1284 {
 1285         struct  rp_port *rp;
 1286         int     unit, port, mynor, umynor, flags;  /* SG */
 1287         struct  tty     *tp;
 1288         int     oldspl, error;
 1289         unsigned int    IntMask, ChanStatus;
 1290 
 1291 
 1292    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1293         port  = (minor(dev) & 0x1f);                /* SG */
 1294         mynor = (port + umynor);                    /* SG */
 1295         unit = minor_to_unit[mynor];
 1296         if (rp_addr(unit) == NULL)
 1297                 return (ENXIO);
 1298         if(IS_CONTROL(dev))
 1299                 return(0);
 1300         rp = rp_addr(unit) + port;
 1301 /*      rp->rp_tty = &rp_tty[rp->rp_port];
 1302 */
 1303         tp = rp->rp_tty;
 1304         dev->si_tty = tp;
 1305 
 1306         oldspl = spltty();
 1307 
 1308 open_top:
 1309         while(rp->state & ~SET_DTR) {
 1310                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
 1311                 if(error != 0)
 1312                         goto out;
 1313         }
 1314 
 1315         if(tp->t_state & TS_ISOPEN) {
 1316                 if(IS_CALLOUT(dev)) {
 1317                         if(!rp->active_out) {
 1318                                 error = EBUSY;
 1319                                 goto out;
 1320                         }
 1321                 } else {
 1322                         if(rp->active_out) {
 1323                                 if(flag & O_NONBLOCK) {
 1324                                         error = EBUSY;
 1325                                         goto out;
 1326                                 }
 1327                                 error = tsleep(&rp->active_out,
 1328                                         TTIPRI | PCATCH, "rpbi", 0);
 1329                                 if(error != 0)
 1330                                         goto out;
 1331                                 goto open_top;
 1332                         }
 1333                 }
 1334                 if(tp->t_state & TS_XCLUDE &&
 1335                     suser(p)) {
 1336                         splx(oldspl);
 1337                         return(EBUSY);
 1338                 }
 1339         }
 1340         else {
 1341                 tp->t_dev = dev;
 1342                 tp->t_param = rpparam;
 1343                 tp->t_oproc = rpstart;
 1344                 tp->t_stop = rpstop;
 1345                 tp->t_line = 0;
 1346                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
 1347                 flags = 0;
 1348                 flags |= SET_RTS;
 1349                 flags |= SET_DTR;
 1350                 rp->rp_channel.TxControl[3] =
 1351                         ((rp->rp_channel.TxControl[3]
 1352                         & ~(SET_RTS | SET_DTR)) | flags);
 1353                 sOutDW(rp->rp_channel.IndexAddr,
 1354                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1355                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1356                 sDisRxStatusMode(&rp->rp_channel);
 1357                 sFlushRxFIFO(&rp->rp_channel);
 1358                 sFlushTxFIFO(&rp->rp_channel);
 1359 
 1360                 sEnInterrupts(&rp->rp_channel,
 1361                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
 1362                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1363 
 1364                 sDisRxStatusMode(&rp->rp_channel);
 1365                 sClrTxXOFF(&rp->rp_channel);
 1366 
 1367 /*              sDisRTSFlowCtl(&rp->rp_channel);
 1368                 sDisCTSFlowCtl(&rp->rp_channel);
 1369 */
 1370                 sDisTxSoftFlowCtl(&rp->rp_channel);
 1371 
 1372                 sStartRxProcessor(&rp->rp_channel);
 1373 
 1374                 sEnRxFIFO(&rp->rp_channel);
 1375                 sEnTransmit(&rp->rp_channel);
 1376 
 1377 /*              sSetDTR(&rp->rp_channel);
 1378                 sSetRTS(&rp->rp_channel);
 1379 */
 1380 
 1381                 ++rp->wopeners;
 1382                 error = rpparam(tp, &tp->t_termios);
 1383                 --rp->wopeners;
 1384                 if(error != 0) {
 1385                         splx(oldspl);
 1386                         return(error);
 1387                 }
 1388 
 1389                 rp_num_ports_open++;
 1390 
 1391                 IntMask = sGetChanIntID(&rp->rp_channel);
 1392                 IntMask = IntMask & rp->rp_intmask;
 1393                 ChanStatus = sGetChanStatus(&rp->rp_channel);
 1394                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
 1395                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
 1396                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 1397                         }
 1398                 }
 1399 
 1400         if(rp_num_ports_open == 1)
 1401                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1402 
 1403         }
 1404 
 1405         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
 1406                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
 1407                 ++rp->wopeners;
 1408                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1409                                 "rpdcd", 0);
 1410                 --rp->wopeners;
 1411                 if(error != 0)
 1412                         goto out;
 1413                 goto open_top;
 1414         }
 1415         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1416 
 1417         rp_disc_optim(tp, &tp->t_termios, rp);
 1418         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
 1419                 rp->active_out = TRUE;
 1420 
 1421 /*      if(rp_num_ports_open == 1)
 1422                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1423 */
 1424 out:
 1425         splx(oldspl);
 1426         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
 1427                 rphardclose(rp);
 1428         }
 1429         return(error);
 1430 }
 1431 
 1432 int
 1433 rpclose(dev, flag, mode, p)
 1434         dev_t   dev;
 1435         int     flag, mode;
 1436         struct  proc    *p;
 1437 {
 1438         int     oldspl, unit, mynor, umynor, port; /* SG */
 1439         struct  rp_port *rp;
 1440         struct  tty     *tp;
 1441         CHANNEL_t       *cp;
 1442 
 1443    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1444         port  = (minor(dev) & 0x1f);                /* SG */
 1445         mynor = (port + umynor);                    /* SG */
 1446    unit = minor_to_unit[mynor];                /* SG */
 1447 
 1448         if(IS_CONTROL(dev))
 1449                 return(0);
 1450         rp = rp_addr(unit) + port;
 1451         cp = &rp->rp_channel;
 1452         tp = rp->rp_tty;
 1453 
 1454         oldspl = spltty();
 1455         (*linesw[tp->t_line].l_close)(tp, flag);
 1456         rp_disc_optim(tp, &tp->t_termios, rp);
 1457         rpstop(tp, FREAD | FWRITE);
 1458         rphardclose(rp);
 1459 
 1460         tp->t_state &= ~TS_BUSY;
 1461         ttyclose(tp);
 1462 
 1463         splx(oldspl);
 1464 
 1465         return(0);
 1466 }
 1467 
 1468 static void
 1469 rphardclose(struct rp_port *rp)
 1470 {
 1471         int     mynor;
 1472         struct  tty     *tp;
 1473         CHANNEL_t       *cp;
 1474 
 1475         cp = &rp->rp_channel;
 1476         tp = rp->rp_tty;
 1477         mynor = MINOR_MAGIC(tp->t_dev);
 1478 
 1479         sFlushRxFIFO(cp);
 1480         sFlushTxFIFO(cp);
 1481         sDisTransmit(cp);
 1482         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1483         sDisRTSFlowCtl(cp);
 1484         sDisCTSFlowCtl(cp);
 1485         sDisTxSoftFlowCtl(cp);
 1486         sClrTxXOFF(cp);
 1487 
 1488         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1489                 sClrDTR(cp);
 1490         }
 1491         if(IS_CALLOUT(tp->t_dev)) {
 1492                 sClrDTR(cp);
 1493         }
 1494         if(rp->dtr_wait != 0) {
 1495                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
 1496                 rp->state |= ~SET_DTR;
 1497         }
 1498 
 1499         rp->active_out = FALSE;
 1500         wakeup(&rp->active_out);
 1501         wakeup(TSA_CARR_ON(tp));
 1502 }
 1503 
 1504 static
 1505 int
 1506 rpwrite(dev, uio, flag)
 1507         dev_t   dev;
 1508         struct  uio     *uio;
 1509         int     flag;
 1510 {
 1511         struct  rp_port *rp;
 1512         struct  tty     *tp;
 1513         int     unit, mynor, port, umynor, error = 0; /* SG */
 1514 
 1515    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1516         port  = (minor(dev) & 0x1f);                /* SG */
 1517         mynor = (port + umynor);                    /* SG */
 1518    unit = minor_to_unit[mynor];                /* SG */
 1519 
 1520         if(IS_CONTROL(dev))
 1521                 return(ENODEV);
 1522         rp = rp_addr(unit) + port;
 1523         tp = rp->rp_tty;
 1524         while(rp->rp_disable_writes) {
 1525                 rp->rp_waiting = 1;
 1526                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
 1527                 if (error)
 1528                         return(error);
 1529         }
 1530 
 1531         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
 1532         return error;
 1533 }
 1534 
 1535 static void
 1536 rpdtrwakeup(void *chan)
 1537 {
 1538         struct  rp_port *rp;
 1539 
 1540         rp = (struct rp_port *)chan;
 1541         rp->state &= SET_DTR;
 1542         wakeup(&rp->dtr_wait);
 1543 }
 1544 
 1545 int
 1546 rpioctl(dev, cmd, data, flag, p)
 1547         dev_t   dev;
 1548         u_long  cmd;
 1549         caddr_t data;
 1550         int     flag;
 1551         struct  proc    *p;
 1552 {
 1553         struct rp_port  *rp;
 1554         CHANNEL_t       *cp;
 1555         struct tty      *tp;
 1556         int     unit, mynor, port, umynor;            /* SG */
 1557         int     oldspl;
 1558         int     error = 0;
 1559         int     arg, flags, result, ChanStatus;
 1560         int     oldcmd;
 1561         struct  termios term, *t;
 1562 
 1563    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1564         port  = (minor(dev) & 0x1f);                /* SG */
 1565         mynor = (port + umynor);                    /* SG */
 1566         unit = minor_to_unit[mynor];
 1567         rp = rp_addr(unit) + port;
 1568 
 1569         if(IS_CONTROL(dev)) {
 1570                 struct  termios *ct;
 1571 
 1572                 switch (IS_CONTROL(dev)) {
 1573                 case CONTROL_INIT_STATE:
 1574                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
 1575                         break;
 1576                 case CONTROL_LOCK_STATE:
 1577                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
 1578                         break;
 1579                 default:
 1580                         return(ENODEV);         /* /dev/nodev */
 1581                 }
 1582                 switch (cmd) {
 1583                 case TIOCSETA:
 1584                         error = suser(p);
 1585                         if(error != 0)
 1586                                 return(error);
 1587                         *ct = *(struct termios *)data;
 1588                         return(0);
 1589                 case TIOCGETA:
 1590                         *(struct termios *)data = *ct;
 1591                         return(0);
 1592                 case TIOCGETD:
 1593                         *(int *)data = TTYDISC;
 1594                         return(0);
 1595                 case TIOCGWINSZ:
 1596                         bzero(data, sizeof(struct winsize));
 1597                         return(0);
 1598                 default:
 1599                         return(ENOTTY);
 1600                 }
 1601         }
 1602 
 1603         tp = rp->rp_tty;
 1604         cp = &rp->rp_channel;
 1605 
 1606 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1607         term = tp->t_termios;
 1608         oldcmd = cmd;
 1609         error = ttsetcompat(tp, &cmd, data, &term);
 1610         if(error != 0)
 1611                 return(error);
 1612         if(cmd != oldcmd) {
 1613                 data = (caddr_t)&term;
 1614         }
 1615 #endif
 1616         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1617                 int     cc;
 1618                 struct  termios *dt = (struct termios *)data;
 1619                 struct  termios *lt = IS_CALLOUT(dev)
 1620                                         ? &rp->lt_out : &rp->lt_in;
 1621 
 1622                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1623                                 | (dt->c_iflag & ~lt->c_iflag);
 1624                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1625                                 | (dt->c_oflag & ~lt->c_oflag);
 1626                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1627                                 | (dt->c_cflag & ~lt->c_cflag);
 1628                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1629                                 | (dt->c_lflag & ~lt->c_lflag);
 1630                 for(cc = 0; cc < NCCS; ++cc)
 1631                         if(lt->c_cc[cc] != 0)
 1632                                 dt->c_cc[cc] = tp->t_cc[cc];
 1633                 if(lt->c_ispeed != 0)
 1634                         dt->c_ispeed = tp->t_ispeed;
 1635                 if(lt->c_ospeed != 0)
 1636                         dt->c_ospeed = tp->t_ospeed;
 1637         }
 1638 
 1639         t = &tp->t_termios;
 1640 
 1641         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 1642         if(error != ENOIOCTL) {
 1643                 return(error);
 1644         }
 1645         oldspl = spltty();
 1646 
 1647         flags = rp->rp_channel.TxControl[3];
 1648 
 1649         error = ttioctl(tp, cmd, data, flag);
 1650         flags = rp->rp_channel.TxControl[3];
 1651         rp_disc_optim(tp, &tp->t_termios, rp);
 1652         if(error != ENOIOCTL) {
 1653                 splx(oldspl);
 1654                 return(error);
 1655         }
 1656         switch(cmd) {
 1657         case TIOCSBRK:
 1658                 sSendBreak(&rp->rp_channel);
 1659                 break;
 1660 
 1661         case TIOCCBRK:
 1662                 sClrBreak(&rp->rp_channel);
 1663                 break;
 1664 
 1665         case TIOCSDTR:
 1666                 sSetDTR(&rp->rp_channel);
 1667                 sSetRTS(&rp->rp_channel);
 1668                 break;
 1669 
 1670         case TIOCCDTR:
 1671                 sClrDTR(&rp->rp_channel);
 1672                 break;
 1673 
 1674         case TIOCMSET:
 1675                 arg = *(int *) data;
 1676                 flags = 0;
 1677                 if(arg & TIOCM_RTS)
 1678                         flags |= SET_RTS;
 1679                 if(arg & TIOCM_DTR)
 1680                         flags |= SET_DTR;
 1681                 rp->rp_channel.TxControl[3] =
 1682                         ((rp->rp_channel.TxControl[3]
 1683                         & ~(SET_RTS | SET_DTR)) | flags);
 1684                 sOutDW(rp->rp_channel.IndexAddr,
 1685                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1686                 break;
 1687         case TIOCMBIS:
 1688                 arg = *(int *) data;
 1689                 flags = 0;
 1690                 if(arg & TIOCM_RTS)
 1691                         flags |= SET_RTS;
 1692                 if(arg & TIOCM_DTR)
 1693                         flags |= SET_DTR;
 1694                         rp->rp_channel.TxControl[3] |= flags;
 1695                 sOutDW(rp->rp_channel.IndexAddr,
 1696                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1697                 break;
 1698         case TIOCMBIC:
 1699                 arg = *(int *) data;
 1700                 flags = 0;
 1701                 if(arg & TIOCM_RTS)
 1702                         flags |= SET_RTS;
 1703                 if(arg & TIOCM_DTR)
 1704                         flags |= SET_DTR;
 1705                 rp->rp_channel.TxControl[3] &= ~flags;
 1706                 sOutDW(rp->rp_channel.IndexAddr,
 1707                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1708                 break;
 1709 
 1710 
 1711         case TIOCMGET:
 1712                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
 1713                 flags = rp->rp_channel.TxControl[3];
 1714                 result = TIOCM_LE; /* always on while open for some reason */
 1715                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
 1716                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
 1717                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
 1718                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
 1719                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
 1720 
 1721                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
 1722                 {
 1723                         result |= TIOCM_RTS;
 1724                 }
 1725 
 1726                 *(int *)data = result;
 1727                 break;
 1728         case TIOCMSDTRWAIT:
 1729                 error = suser(p);
 1730                 if(error != 0) {
 1731                         splx(oldspl);
 1732                         return(error);
 1733                 }
 1734                 rp->dtr_wait = *(int *)data * hz/100;
 1735                 break;
 1736         case TIOCMGDTRWAIT:
 1737                 *(int *)data = rp->dtr_wait * 100/hz;
 1738                 break;
 1739         default:
 1740                 splx(oldspl);
 1741                 return ENOTTY;
 1742         }
 1743         splx(oldspl);
 1744         return(0);
 1745 }
 1746 
 1747 static struct speedtab baud_table[] = {
 1748         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1749         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1750         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1751         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1752         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1753         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1754                                 {B57600, BRD57600},     {B76800, BRD76800},
 1755         {B115200, BRD115200},   {B230400, BRD230400},
 1756         -1,     -1
 1757 };
 1758 
 1759 static int
 1760 rpparam(tp, t)
 1761         struct tty *tp;
 1762         struct termios *t;
 1763 {
 1764         struct rp_port  *rp;
 1765         CHANNEL_t       *cp;
 1766         int     unit, mynor, port, umynor;               /* SG */
 1767         int     oldspl, cflag, iflag, oflag, lflag;
 1768         int     ospeed;
 1769 
 1770 
 1771    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1772         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1773         mynor = (port + umynor);                          /* SG */
 1774 
 1775         unit = minor_to_unit[mynor];
 1776         rp = rp_addr(unit) + port;
 1777         cp = &rp->rp_channel;
 1778         oldspl = spltty();
 1779 
 1780         cflag = t->c_cflag;
 1781         iflag = t->c_iflag;
 1782         oflag = t->c_oflag;
 1783         lflag = t->c_lflag;
 1784 
 1785         ospeed = ttspeedtab(t->c_ispeed, baud_table);
 1786         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1787                 return(EINVAL);
 1788 
 1789         tp->t_ispeed = t->c_ispeed;
 1790         tp->t_ospeed = t->c_ospeed;
 1791         tp->t_cflag = cflag;
 1792         tp->t_iflag = iflag;
 1793         tp->t_oflag = oflag;
 1794         tp->t_lflag = lflag;
 1795 
 1796         if(t->c_ospeed == 0) {
 1797                 sClrDTR(cp);
 1798                 return(0);
 1799         }
 1800         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1801 
 1802         /* Set baud rate ----- we only pay attention to ispeed */
 1803         sSetDTR(cp);
 1804         sSetRTS(cp);
 1805         sSetBaud(cp, ospeed);
 1806 
 1807         if(cflag & CSTOPB) {
 1808                 sSetStop2(cp);
 1809         } else {
 1810                 sSetStop1(cp);
 1811         }
 1812 
 1813         if(cflag & PARENB) {
 1814                 sEnParity(cp);
 1815                 if(cflag & PARODD) {
 1816                         sSetOddParity(cp);
 1817                 } else {
 1818                         sSetEvenParity(cp);
 1819                 }
 1820         }
 1821         else {
 1822                 sDisParity(cp);
 1823         }
 1824         if((cflag & CSIZE) == CS8) {
 1825                 sSetData8(cp);
 1826                 rp->rp_imask = 0xFF;
 1827         } else {
 1828                 sSetData7(cp);
 1829                 rp->rp_imask = 0x7F;
 1830         }
 1831 
 1832         if(iflag & ISTRIP) {
 1833                 rp->rp_imask &= 0x7F;
 1834         }
 1835 
 1836         if(cflag & CLOCAL) {
 1837                 rp->rp_intmask &= ~DELTA_CD;
 1838         } else {
 1839                 rp->rp_intmask |= DELTA_CD;
 1840         }
 1841 
 1842         /* Put flow control stuff here */
 1843 
 1844         if(cflag & CCTS_OFLOW) {
 1845                 sEnCTSFlowCtl(cp);
 1846         } else {
 1847                 sDisCTSFlowCtl(cp);
 1848         }
 1849 
 1850         if(cflag & CRTS_IFLOW) {
 1851                 rp->rp_rts_iflow = 1;
 1852         } else {
 1853                 rp->rp_rts_iflow = 0;
 1854         }
 1855 
 1856         if(cflag & CRTS_IFLOW) {
 1857                 sEnRTSFlowCtl(cp);
 1858         } else {
 1859                 sDisRTSFlowCtl(cp);
 1860         }
 1861         rp_disc_optim(tp, t, rp);
 1862 
 1863         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
 1864                 tp->t_state |= TS_CARR_ON;
 1865                 wakeup(TSA_CARR_ON(tp));
 1866         }
 1867 
 1868 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1869         flags = rp->rp_channel.TxControl[3];
 1870         if(flags & SET_DTR)
 1871         else
 1872         if(flags & SET_RTS)
 1873         else
 1874 */
 1875         splx(oldspl);
 1876 
 1877         return(0);
 1878 }
 1879 
 1880 static void
 1881 rp_disc_optim(tp, t, rp)
 1882 struct  tty     *tp;
 1883 struct  termios *t;
 1884 struct  rp_port *rp;
 1885 {
 1886         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
 1887                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
 1888                 &&(!(t->c_iflag & PARMRK)
 1889                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
 1890                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
 1891                 && linesw[tp->t_line].l_rint == ttyinput)
 1892                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1893         else
 1894                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 1895 }
 1896 
 1897 static void
 1898 rpstart(tp)
 1899         struct tty *tp;
 1900 {
 1901         struct rp_port  *rp;
 1902         CHANNEL_t       *cp;
 1903         struct  clist   *qp;
 1904         int     unit, mynor, port, umynor;               /* SG */
 1905         char    ch, flags;
 1906         int     spl, xmit_fifo_room;
 1907         int     count;
 1908 
 1909 
 1910    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1911         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1912         mynor = (port + umynor);                          /* SG */
 1913         unit = minor_to_unit[mynor];
 1914         rp = rp_addr(unit) + port;
 1915         cp = &rp->rp_channel;
 1916         flags = rp->rp_channel.TxControl[3];
 1917         spl = spltty();
 1918 
 1919         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1920                 ttwwakeup(tp);
 1921                 splx(spl);
 1922                 return;
 1923         }
 1924         if(rp->rp_xmit_stopped) {
 1925                 sEnTransmit(cp);
 1926                 rp->rp_xmit_stopped = 0;
 1927         }
 1928         count = sGetTxCnt(cp);
 1929 
 1930         if(tp->t_outq.c_cc == 0) {
 1931                 if((tp->t_state & TS_BUSY) && (count == 0)) {
 1932                         tp->t_state &= ~TS_BUSY;
 1933                 }
 1934                 ttwwakeup(tp);
 1935                 splx(spl);
 1936                 return;
 1937         }
 1938         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1939         qp = &tp->t_outq;
 1940         count = 0;
 1941         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1942                 tp->t_state |= TS_BUSY;
 1943         }
 1944         while(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1945                 ch = getc(qp);
 1946                 sOutB(sGetTxRxDataIO(cp), ch);
 1947                 xmit_fifo_room--;
 1948                 count++;
 1949         }
 1950         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
 1951 
 1952         ttwwakeup(tp);
 1953         splx(spl);
 1954 }
 1955 
 1956 static
 1957 void
 1958 rpstop(tp, flag)
 1959         register struct tty *tp;
 1960         int     flag;
 1961 {
 1962         struct rp_port  *rp;
 1963         CHANNEL_t       *cp;
 1964         int     unit, mynor, port, umynor;                  /* SG */
 1965         int     spl;
 1966 
 1967    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1968         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1969         mynor = (port + umynor);                          /* SG */
 1970         unit = minor_to_unit[mynor];
 1971         rp = rp_addr(unit) + port;
 1972         cp = &rp->rp_channel;
 1973 
 1974         spl = spltty();
 1975 
 1976         if(tp->t_state & TS_BUSY) {
 1977                 if((tp->t_state&TS_TTSTOP) == 0) {
 1978                         sFlushTxFIFO(cp);
 1979                 } else {
 1980                         if(rp->rp_xmit_stopped == 0) {
 1981                                 sDisTransmit(cp);
 1982                                 rp->rp_xmit_stopped = 1;
 1983                         }
 1984                 }
 1985         }
 1986         splx(spl);
 1987         rpstart(tp);
 1988 }

Cache object: d8a22da392a8b0eda7b508ce7d13c028


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