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 DATA_SET (pcidevice_set, 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_read_t        rpread;
  798 static  d_write_t       rpwrite;
  799 static  d_ioctl_t       rpioctl;
  800 static  d_stop_t        rpstop;
  801 static  d_devtotty_t    rpdevtotty;
  802 
  803 #define CDEV_MAJOR      81
  804 static  struct cdevsw   rp_cdevsw = {
  805         rpopen,         rpclose,        rpread,         rpwrite,
  806         rpioctl,        rpstop,         noreset,        rpdevtotty,
  807         ttpoll,         nommap,         NULL,           driver_name,
  808         NULL,           -1,             nodump,         nopsize,
  809         D_TTY,
  810 };
  811 
  812 static int rp_controller_port = 0;
  813 static int rp_num_ports_open = 0;
  814 static int      ndevs = 0;
  815 static int      minor_to_unit[128];
  816 #if 0
  817 static  struct  tty     rp_tty[128];
  818 #endif
  819 
  820 static int rp_num_ports[4];     /* Number of ports on each controller */
  821 
  822 #define _INLINE_ __inline
  823 #define POLL_INTERVAL 1
  824 
  825 #define CALLOUT_MASK            0x80
  826 #define CONTROL_MASK            0x60
  827 #define CONTROL_INIT_STATE      0x20
  828 #define CONTROL_LOCK_STATE      0x40
  829 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
  830 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
  831 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
  832 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
  833 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
  834 
  835 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
  836 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
  837 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
  838 
  839 static  struct  rp_port *p_rp_addr[4];
  840 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
  841 #define rp_addr(unit)   (p_rp_addr[unit])
  842 #define rp_table(port)  (p_rp_table[port])
  843 
  844 /*
  845  * The top-level routines begin here
  846  */
  847 
  848 int     rpselect __P((dev_t, int, struct proc *));
  849 
  850 static  int     rpparam __P((struct tty *, struct termios *));
  851 static  void    rpstart __P((struct tty *));
  852 static  void    rphardclose     __P((struct rp_port *));
  853 #define rpmap   nomap
  854 #define rpreset noreset
  855 #define rpstrategy      nostrategy
  856 static  void    rp_disc_optim   __P((struct tty *tp, struct termios *t,
  857                                                 struct rp_port  *rp));
  858 
  859 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
  860                         CHANNEL_t *cp, unsigned int ChanStatus)
  861 {
  862         int     spl;
  863         unsigned        int     CharNStat;
  864         int     ToRecv, ch;
  865 
  866         ToRecv = sGetRxCnt(cp);
  867         if(ToRecv == 0)
  868                 return;
  869 
  870 /*      If status indicates there are errored characters in the
  871         FIFO, then enter status mode (a word in FIFO holds
  872         characters and status)
  873 */
  874 
  875         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  876                 if(!(ChanStatus & STATMODE)) {
  877                         ChanStatus |= STATMODE;
  878                         sEnRxStatusMode(cp);
  879                 }
  880         }
  881 /*
  882         if we previously entered status mode then read down the
  883         FIFO one word at a time, pulling apart the character and
  884         the status. Update error counters depending on status.
  885 */
  886         if(ChanStatus & STATMODE) {
  887                 while(ToRecv) {
  888                         if(tp->t_state & TS_TBLOCK) {
  889                                 break;
  890                         }
  891                         CharNStat = sInW(sGetTxRxDataIO(cp));
  892                         ch = CharNStat & 0xff;
  893 
  894                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
  895                                 ch |= TTY_FE;
  896                         else if (CharNStat & STMPARITYH)
  897                                 ch |= TTY_PE;
  898                         else if (CharNStat & STMRCVROVRH)
  899                                 rp->rp_overflows++;
  900 
  901                         (*linesw[tp->t_line].l_rint)(ch, tp);
  902                         ToRecv--;
  903                 }
  904 /*
  905         After emtying FIFO in status mode, turn off status mode
  906 */
  907 
  908         if(sGetRxCnt(cp) == 0)
  909                 sDisRxStatusMode(cp);
  910         }
  911         else {
  912                 while (ToRecv) {
  913                         if(tp->t_state & TS_TBLOCK) {
  914                                 break;
  915                         }
  916                         ch = (u_char) sInB(sGetTxRxDataIO(cp));
  917                         spl = spltty();
  918                         (*linesw[tp->t_line].l_rint)(ch, tp);
  919                         splx(spl);
  920                         ToRecv--;
  921                 }
  922         }
  923 }
  924 
  925 static _INLINE_ void rp_handle_port(struct rp_port *rp)
  926 {
  927         CHANNEL_t       *cp;
  928         struct  tty     *tp;
  929         unsigned        int     IntMask, ChanStatus;
  930      /* int     oldcts; */
  931 
  932         if(!rp)
  933                 return;
  934 
  935         cp = &rp->rp_channel;
  936         tp = rp->rp_tty;
  937         IntMask = sGetChanIntID(cp);
  938         IntMask = IntMask & rp->rp_intmask;
  939         ChanStatus = sGetChanStatus(cp);
  940         if(IntMask & RXF_TRIG)
  941                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
  942                         rp_do_receive(rp, tp, cp, ChanStatus);
  943                 }
  944         if(IntMask & DELTA_CD) {
  945                 if(ChanStatus & CD_ACT) {
  946                         if(!(tp->t_state & TS_CARR_ON) ) {
  947                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
  948                         }
  949                 } else {
  950                         if((tp->t_state & TS_CARR_ON)) {
  951                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
  952                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
  953                                         rphardclose(rp);
  954                                 }
  955                         }
  956                 }
  957         }
  958 /*      oldcts = rp->rp_cts;
  959         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
  960         if(oldcts != rp->rp_cts) {
  961                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
  962         }
  963 */
  964 }
  965 
  966 static void rp_do_poll(void *not_used)
  967 {
  968         CONTROLLER_t    *ctl;
  969         struct rp_port  *rp;
  970         struct tty      *tp;
  971         int     unit, aiop, ch, line, count;
  972         unsigned char   CtlMask, AiopMask;
  973 
  974         for(unit = 0; unit <= ndevs; unit++) {
  975         rp = rp_addr(unit);
  976         ctl = rp->rp_ctlp;
  977         if(ctl->BusType == isPCI)
  978                 CtlMask = sPCIGetControllerIntStatus(ctl);
  979         else
  980                 CtlMask = sGetControllerIntStatus(ctl);
  981         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
  982                 if(CtlMask & 1) {
  983                         AiopMask = sGetAiopIntStatus(ctl, aiop);
  984                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
  985                                 if(AiopMask & 1) {
  986                                         line = (unit << 5) | (aiop << 3) | ch;
  987                                         rp = rp_table(line);
  988                                         rp_handle_port(rp);
  989                                 }
  990                         }
  991                 }
  992         }
  993 
  994         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
  995                         line++, rp++) {
  996                 tp = rp->rp_tty;
  997                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
  998                         count = sGetTxCnt(&rp->rp_channel);
  999                         if(count == 0)
 1000                                 tp->t_state &= ~(TS_BUSY);
 1001                         if(!(tp->t_state & TS_TTSTOP) &&
 1002                                 (count <= rp->rp_restart)) {
 1003                                 (*linesw[tp->t_line].l_start)(tp);
 1004                         }
 1005                 }
 1006         }
 1007         }
 1008         if(rp_num_ports_open)
 1009                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1010 }
 1011 
 1012 static const char*
 1013 rp_pciprobe(pcici_t tag, pcidi_t type)
 1014 {
 1015         int     vendor_id;
 1016 
 1017         vendor_id = type & 0xffff;
 1018         switch(vendor_id)
 1019         case 0x11fe:
 1020                 return("rp");
 1021         return(NULL);
 1022 }
 1023 
 1024 static
 1025 int
 1026 rpprobe(dev)
 1027 struct isa_device *dev;
 1028 {
 1029         int controller, unit;
 1030         int aiop, num_aiops;
 1031         unsigned int aiopio[MAX_AIOPS_PER_BOARD];
 1032         CONTROLLER_t *ctlp;
 1033 
 1034         unit = dev->id_unit;
 1035         if (dev->id_unit >= 4) {
 1036                 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
 1037                 return 1;
 1038         }
 1039         printf("probing for RocketPort(ISA) unit %d\n", unit);
 1040         if (rp_controller_port)
 1041                 controller = rp_controller_port;
 1042         else {
 1043                 controller = dev->id_iobase + 0x40;
 1044         }
 1045 
 1046         for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
 1047                 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
 1048 
 1049         ctlp = sCtlNumToCtlPtr(dev->id_unit);
 1050         num_aiops = sInitController(ctlp, dev->id_unit,
 1051                                 controller + ((unit-rp_pcicount)*0x400),
 1052                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1053                                 FREQ_DIS, 0);
 1054         if (num_aiops <= 0) {
 1055                 printf("board%d init failed\n", unit);
 1056                 return 0;
 1057         }
 1058 
 1059         if (rp_controller_port) {
 1060                 dev->id_msize = 64;
 1061         } else {
 1062                 dev->id_msize = 68;
 1063                 rp_controller_port = controller;
 1064         }
 1065 
 1066         dev->id_irq = 0;
 1067 
 1068         return 1;
 1069 }
 1070 
 1071 static void
 1072 rp_pciattach(pcici_t tag, int unit)
 1073 {
 1074         dev_t   rp_dev;
 1075         int     success, oldspl;
 1076         u_short iobase;
 1077         int     num_ports, num_chan, num_aiops;
 1078         int     aiop, chan, port;
 1079         int     ChanStatus, line, i, count;
 1080         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
 1081         struct  rp_port *rp;
 1082         struct  tty     *tty;
 1083         CONTROLLER_t    *ctlp;
 1084 
 1085         success = pci_map_port(tag, 0x10, &iobase);
 1086         if(!success)
 1087                 printf("ioaddr mapping failed for RocketPort(PCI)\n");
 1088 
 1089         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
 1090                 aiopio[aiop] = iobase + (aiop * 0x40);
 1091 
 1092         ctlp = sCtlNumToCtlPtr(unit);
 1093         num_aiops = sPCIInitController(ctlp, unit,
 1094                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1095                                 FREQ_DIS, 0);
 1096 
 1097         num_ports = 0;
 1098         for(aiop=0; aiop < num_aiops; aiop++) {
 1099                 sResetAiopByNum(ctlp, aiop);
 1100                 num_ports += sGetAiopNumChan(ctlp, aiop);
 1101         }
 1102         printf("RocketPort%d = %d ports\n", unit, num_ports);
 1103         rp_num_ports[unit] = num_ports;
 1104 
 1105         rp = (struct rp_port *)
 1106                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
 1107         if(rp == 0) {
 1108                 printf("rp_attach: Could not malloc rp_ports structures\n");
 1109                 return;
 1110         }
 1111 
 1112         count = unit * 32;      /* board times max ports per card SG */
 1113         for(i=count;i < (count + rp_num_ports[unit]);i++)
 1114                 minor_to_unit[i] = unit;
 1115 
 1116         bzero(rp, sizeof(struct rp_port) * num_ports);
 1117         tty = (struct tty *)
 1118                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
 1119         if(tty == 0) {
 1120                 printf("rp_attach: Could not malloc tty structures\n");
 1121                 return;
 1122         }
 1123         bzero(tty, sizeof(struct tty) * num_ports);
 1124 
 1125         oldspl = spltty();
 1126         rp_addr(unit) = rp;
 1127         splx(oldspl);
 1128 
 1129         rp_dev = makedev(CDEV_MAJOR, unit);
 1130         cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
 1131 
 1132         port = 0;
 1133         for(aiop=0; aiop < num_aiops; aiop++) {
 1134                 num_chan = sGetAiopNumChan(ctlp, aiop);
 1135                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
 1136                         rp->rp_tty = tty;
 1137                         rp->rp_port = port;
 1138                         rp->rp_ctlp = ctlp;
 1139                         rp->rp_unit = unit;
 1140                         rp->rp_chan = chan;
 1141                         rp->rp_aiop = aiop;
 1142 
 1143                         tty->t_line = 0;
 1144         /*              tty->t_termios = deftermios;
 1145         */
 1146                         rp->dtr_wait = 3 * hz;
 1147                         rp->it_in.c_iflag = 0;
 1148                         rp->it_in.c_oflag = 0;
 1149                         rp->it_in.c_cflag = TTYDEF_CFLAG;
 1150                         rp->it_in.c_lflag = 0;
 1151                         termioschars(&rp->it_in);
 1152         /*              termioschars(&tty->t_termios);
 1153         */
 1154                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
 1155                         rp->it_out = rp->it_in;
 1156 
 1157                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
 1158                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
 1159                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1160                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
 1161                                 printf("RocketPort sInitChan(%d, %d, %d) failed
 1162                                         \n", unit, aiop, chan);
 1163                                 return;
 1164                         }
 1165                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1166                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
 1167                         line = (unit << 5) | (aiop << 3) | chan;
 1168                         rp_table(line) = rp;
 1169 /*                      devfs_add_devswf(&rp_cdevsw,
 1170                                 port, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
 1171                                 "ttyR%r", port);
 1172                         devfs_add_devswf(&rp_cdevsw,
 1173                                 port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT,
 1174                                 GID_WHEEL, 0600, "ttyRi%r", port);
 1175 */
 1176                 }
 1177         }
 1178 }
 1179 
 1180 static
 1181 int
 1182 rpattach(dev)
 1183 struct  isa_device      *dev;
 1184 {
 1185         struct  isa_device      *idev;
 1186         dev_t   rp_dev;
 1187         int     iobase, unit, /*rpmajor,*/ oldspl;
 1188         int     num_ports, num_chan, num_aiops;
 1189         int     aiop, chan, port;
 1190         int     ChanStatus, line, i, count;
 1191         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
 1192         struct  rp_port *rp;
 1193         struct  tty     *tty;
 1194         CONTROLLER_t    *ctlp;
 1195 
 1196         iobase = dev->id_iobase;
 1197         unit = dev->id_unit;
 1198         ndevs = unit;
 1199 
 1200         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
 1201                 aiopio[aiop] = iobase + (aiop * 0x400);
 1202 
 1203         ctlp = sCtlNumToCtlPtr(unit);
 1204         num_aiops = sInitController(ctlp, unit,
 1205                                 rp_controller_port + ((unit-rp_pcicount) * 0x400),
 1206                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
 1207                                 FREQ_DIS, 0);
 1208 
 1209         num_ports = 0;
 1210         for(aiop=0; aiop < num_aiops; aiop++) {
 1211                 sResetAiopByNum(ctlp, aiop);
 1212                 sEnAiop(ctlp, aiop);
 1213                 num_ports += sGetAiopNumChan(ctlp, aiop);
 1214         }
 1215         printf("RocketPort%d = %d ports\n", unit, num_ports);
 1216         rp_num_ports[unit] = num_ports;
 1217 
 1218         rp = (struct rp_port *)
 1219                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
 1220         if(rp == 0) {
 1221                 printf("rp_attach: Could not malloc rp_ports structures\n");
 1222                 return(0);
 1223         }
 1224 
 1225         count = unit * 32;    /* board # times max ports per card  SG */
 1226         for(i=count;i < (count + rp_num_ports[unit]);i++)
 1227                 minor_to_unit[i] = unit;
 1228 
 1229         bzero(rp, sizeof(struct rp_port) * num_ports);
 1230         tty = (struct tty *)
 1231                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
 1232         if(tty == 0) {
 1233                 printf("rp_attach: Could not malloc tty structures\n");
 1234                 return(0);
 1235         }
 1236         bzero(tty, sizeof(struct tty) * num_ports);
 1237 
 1238         oldspl = spltty();
 1239         rp_addr(unit) = rp;
 1240         splx(oldspl);
 1241 
 1242         rp_dev = makedev(CDEV_MAJOR, unit);
 1243         cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
 1244 
 1245         port = 0;
 1246         for(aiop=0; aiop < num_aiops; aiop++) {
 1247                 num_chan = sGetAiopNumChan(ctlp, aiop);
 1248                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
 1249                         rp->rp_tty = tty;
 1250                         rp->rp_port = port;
 1251                         rp->rp_ctlp = ctlp;
 1252                         rp->rp_unit = unit;
 1253                         rp->rp_chan = chan;
 1254                         rp->rp_aiop = aiop;
 1255 
 1256                         tty->t_line = 0;
 1257         /*              tty->t_termios = deftermios;
 1258         */
 1259                         rp->dtr_wait = 3 * hz;
 1260                         rp->it_in.c_iflag = 0;
 1261                         rp->it_in.c_oflag = 0;
 1262                         rp->it_in.c_cflag = TTYDEF_CFLAG;
 1263                         rp->it_in.c_lflag = 0;
 1264                         termioschars(&rp->it_in);
 1265         /*              termioschars(&tty->t_termios);
 1266         */
 1267                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
 1268                         rp->it_out = rp->it_in;
 1269 
 1270                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
 1271                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
 1272                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1273                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
 1274                                 printf("RocketPort sInitChan(%d, %d, %d) failed
 1275                                         \n", unit, aiop, chan);
 1276                                 return(0);
 1277                         }
 1278                         ChanStatus = sGetChanStatus(&rp->rp_channel);
 1279                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
 1280                         line = (unit << 5) | (aiop << 3) | chan;
 1281                         rp_table(line) = rp;
 1282                 }
 1283         }
 1284 
 1285                 idev = find_isadev(isa_devtab_tty, &rpdriver,
 1286                                 RP_MPMASTER(dev) + rp_pcicount);
 1287                 if(idev == NULL) {
 1288                         printf("rp%d: master device %d not configured\n",
 1289                                 dev->id_unit, RP_MPMASTER(dev));
 1290                 }
 1291 /*              printf("COOL!! Device is found!!\n");
 1292         for(rpmajor=0;rpmajor<nchrdev;rpmajor++)
 1293                 if(cdevsw[rpmajor].d_open == rpopen)
 1294                         printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor);
 1295 */
 1296         return(1);
 1297 }
 1298 
 1299 int
 1300 rpopen(dev, flag, mode, p)
 1301         dev_t   dev;
 1302         int     flag, mode;
 1303         struct  proc    *p;
 1304 {
 1305         struct  rp_port *rp;
 1306         int     unit, port, mynor, umynor, flags;  /* SG */
 1307         struct  tty     *tp;
 1308         int     oldspl, error;
 1309         unsigned int    IntMask, ChanStatus;
 1310 
 1311 
 1312    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1313         port  = (minor(dev) & 0x1f);                /* SG */
 1314         mynor = (port + umynor);                    /* SG */
 1315         unit = minor_to_unit[mynor];
 1316         if (rp_addr(unit) == NULL)
 1317                 return (ENXIO);
 1318         if(IS_CONTROL(dev))
 1319                 return(0);
 1320         rp = rp_addr(unit) + port;
 1321 /*      rp->rp_tty = &rp_tty[rp->rp_port];
 1322 */
 1323         tp = rp->rp_tty;
 1324 
 1325         oldspl = spltty();
 1326 
 1327 open_top:
 1328         while(rp->state & ~SET_DTR) {
 1329                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
 1330                 if(error != 0)
 1331                         goto out;
 1332         }
 1333 
 1334         if(tp->t_state & TS_ISOPEN) {
 1335                 if(IS_CALLOUT(dev)) {
 1336                         if(!rp->active_out) {
 1337                                 error = EBUSY;
 1338                                 goto out;
 1339                         }
 1340                 } else {
 1341                         if(rp->active_out) {
 1342                                 if(flag & O_NONBLOCK) {
 1343                                         error = EBUSY;
 1344                                         goto out;
 1345                                 }
 1346                                 error = tsleep(&rp->active_out,
 1347                                         TTIPRI | PCATCH, "rpbi", 0);
 1348                                 if(error != 0)
 1349                                         goto out;
 1350                                 goto open_top;
 1351                         }
 1352                 }
 1353                 if(tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
 1354                         splx(oldspl);
 1355                         return(EBUSY);
 1356                 }
 1357         }
 1358         else {
 1359                 tp->t_dev = dev;
 1360                 tp->t_param = rpparam;
 1361                 tp->t_oproc = rpstart;
 1362                 tp->t_line = 0;
 1363                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
 1364                 flags = 0;
 1365                 flags |= SET_RTS;
 1366                 flags |= SET_DTR;
 1367                 rp->rp_channel.TxControl[3] =
 1368                         ((rp->rp_channel.TxControl[3]
 1369                         & ~(SET_RTS | SET_DTR)) | flags);
 1370                 sOutDW(rp->rp_channel.IndexAddr,
 1371                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1372                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1373                 sDisRxStatusMode(&rp->rp_channel);
 1374                 sFlushRxFIFO(&rp->rp_channel);
 1375                 sFlushTxFIFO(&rp->rp_channel);
 1376 
 1377                 sEnInterrupts(&rp->rp_channel,
 1378                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
 1379                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
 1380 
 1381                 sDisRxStatusMode(&rp->rp_channel);
 1382                 sClrTxXOFF(&rp->rp_channel);
 1383 
 1384 /*              sDisRTSFlowCtl(&rp->rp_channel);
 1385                 sDisCTSFlowCtl(&rp->rp_channel);
 1386 */
 1387                 sDisTxSoftFlowCtl(&rp->rp_channel);
 1388 
 1389                 sStartRxProcessor(&rp->rp_channel);
 1390 
 1391                 sEnRxFIFO(&rp->rp_channel);
 1392                 sEnTransmit(&rp->rp_channel);
 1393 
 1394 /*              sSetDTR(&rp->rp_channel);
 1395                 sSetRTS(&rp->rp_channel);
 1396 */
 1397 
 1398                 ++rp->wopeners;
 1399                 error = rpparam(tp, &tp->t_termios);
 1400                 --rp->wopeners;
 1401                 if(error != 0) {
 1402                         splx(oldspl);
 1403                         return(error);
 1404                 }
 1405 
 1406                 rp_num_ports_open++;
 1407 
 1408                 IntMask = sGetChanIntID(&rp->rp_channel);
 1409                 IntMask = IntMask & rp->rp_intmask;
 1410                 ChanStatus = sGetChanStatus(&rp->rp_channel);
 1411                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
 1412                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
 1413                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 1414                         }
 1415                 }
 1416 
 1417         if(rp_num_ports_open == 1)
 1418                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1419 
 1420         }
 1421 
 1422         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
 1423                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
 1424                 ++rp->wopeners;
 1425                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1426                                 "rpdcd", 0);
 1427                 --rp->wopeners;
 1428                 if(error != 0)
 1429                         goto out;
 1430                 goto open_top;
 1431         }
 1432         error = (*linesw[tp->t_line].l_open)(dev, tp);
 1433 
 1434         rp_disc_optim(tp, &tp->t_termios, rp);
 1435         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
 1436                 rp->active_out = TRUE;
 1437 
 1438 /*      if(rp_num_ports_open == 1)
 1439                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
 1440 */
 1441 out:
 1442         splx(oldspl);
 1443         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
 1444                 rphardclose(rp);
 1445         }
 1446         return(error);
 1447 }
 1448 
 1449 int
 1450 rpclose(dev, flag, mode, p)
 1451         dev_t   dev;
 1452         int     flag, mode;
 1453         struct  proc    *p;
 1454 {
 1455         int     oldspl, unit, mynor, umynor, port; /* SG */
 1456         struct  rp_port *rp;
 1457         struct  tty     *tp;
 1458         CHANNEL_t       *cp;
 1459 
 1460    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1461         port  = (minor(dev) & 0x1f);                /* SG */
 1462         mynor = (port + umynor);                    /* SG */
 1463    unit = minor_to_unit[mynor];                /* SG */
 1464 
 1465         if(IS_CONTROL(dev))
 1466                 return(0);
 1467         rp = rp_addr(unit) + port;
 1468         cp = &rp->rp_channel;
 1469         tp = rp->rp_tty;
 1470 
 1471         oldspl = spltty();
 1472         (*linesw[tp->t_line].l_close)(tp, flag);
 1473         rp_disc_optim(tp, &tp->t_termios, rp);
 1474         rpstop(tp, FREAD | FWRITE);
 1475         rphardclose(rp);
 1476 
 1477         tp->t_state &= ~TS_BUSY;
 1478         ttyclose(tp);
 1479 
 1480         splx(oldspl);
 1481 
 1482         return(0);
 1483 }
 1484 
 1485 static void
 1486 rphardclose(struct rp_port *rp)
 1487 {
 1488         int     mynor;
 1489         struct  tty     *tp;
 1490         CHANNEL_t       *cp;
 1491 
 1492         cp = &rp->rp_channel;
 1493         tp = rp->rp_tty;
 1494         mynor = MINOR_MAGIC(tp->t_dev);
 1495 
 1496         sFlushRxFIFO(cp);
 1497         sFlushTxFIFO(cp);
 1498         sDisTransmit(cp);
 1499         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
 1500         sDisRTSFlowCtl(cp);
 1501         sDisCTSFlowCtl(cp);
 1502         sDisTxSoftFlowCtl(cp);
 1503         sClrTxXOFF(cp);
 1504 
 1505         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
 1506                 sClrDTR(cp);
 1507         }
 1508         if(IS_CALLOUT(tp->t_dev)) {
 1509                 sClrDTR(cp);
 1510         }
 1511         if(rp->dtr_wait != 0) {
 1512                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
 1513                 rp->state |= ~SET_DTR;
 1514         }
 1515 
 1516         rp->active_out = FALSE;
 1517         wakeup(&rp->active_out);
 1518         wakeup(TSA_CARR_ON(tp));
 1519 }
 1520 
 1521 static
 1522 int
 1523 rpread(dev, uio, flag)
 1524         dev_t   dev;
 1525         struct  uio     *uio;
 1526         int     flag;
 1527 {
 1528         struct  rp_port *rp;
 1529         struct  tty     *tp;
 1530         int     unit, mynor, umynor, port, error = 0; /* SG */
 1531 
 1532    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1533         port  = (minor(dev) & 0x1f);                /* SG */
 1534         mynor = (port + umynor);                    /* SG */
 1535    unit = minor_to_unit[mynor];                /* SG */
 1536 
 1537         if(IS_CONTROL(dev))
 1538                 return(ENODEV);
 1539         rp = rp_addr(unit) + port;
 1540         tp = rp->rp_tty;
 1541         error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
 1542         return(error);
 1543 }
 1544 
 1545 static
 1546 int
 1547 rpwrite(dev, uio, flag)
 1548         dev_t   dev;
 1549         struct  uio     *uio;
 1550         int     flag;
 1551 {
 1552         struct  rp_port *rp;
 1553         struct  tty     *tp;
 1554         int     unit, mynor, port, umynor, error = 0; /* SG */
 1555 
 1556    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1557         port  = (minor(dev) & 0x1f);                /* SG */
 1558         mynor = (port + umynor);                    /* SG */
 1559    unit = minor_to_unit[mynor];                /* SG */
 1560 
 1561         if(IS_CONTROL(dev))
 1562                 return(ENODEV);
 1563         rp = rp_addr(unit) + port;
 1564         tp = rp->rp_tty;
 1565         while(rp->rp_disable_writes) {
 1566                 rp->rp_waiting = 1;
 1567                 if(error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH,
 1568                                         "rp_write", 0)) {
 1569                         return(error);
 1570                 }
 1571         }
 1572 
 1573         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
 1574         return error;
 1575 }
 1576 
 1577 static void
 1578 rpdtrwakeup(void *chan)
 1579 {
 1580         struct  rp_port *rp;
 1581 
 1582         rp = (struct rp_port *)chan;
 1583         rp->state &= SET_DTR;
 1584         wakeup(&rp->dtr_wait);
 1585 }
 1586 
 1587 int
 1588 rpioctl(dev, cmd, data, flag, p)
 1589         dev_t   dev;
 1590         u_long  cmd;
 1591         caddr_t data;
 1592         int     flag;
 1593         struct  proc    *p;
 1594 {
 1595         struct rp_port  *rp;
 1596         CHANNEL_t       *cp;
 1597         struct tty      *tp;
 1598         int     unit, mynor, port, umynor;            /* SG */
 1599         int     oldspl;
 1600         int     error = 0;
 1601         int     arg, flags, result, ChanStatus;
 1602         int     oldcmd;
 1603         struct  termios term, *t;
 1604 
 1605    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 1606         port  = (minor(dev) & 0x1f);                /* SG */
 1607         mynor = (port + umynor);                    /* SG */
 1608         unit = minor_to_unit[mynor];
 1609         rp = rp_addr(unit) + port;
 1610 
 1611         if(IS_CONTROL(dev)) {
 1612                 struct  termios *ct;
 1613 
 1614                 switch (IS_CONTROL(dev)) {
 1615                 case CONTROL_INIT_STATE:
 1616                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
 1617                         break;
 1618                 case CONTROL_LOCK_STATE:
 1619                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
 1620                         break;
 1621                 default:
 1622                         return(ENODEV);         /* /dev/nodev */
 1623                 }
 1624                 switch (cmd) {
 1625                 case TIOCSETA:
 1626                         error = suser(p->p_ucred, &p->p_acflag);
 1627                         if(error != 0)
 1628                                 return(error);
 1629                         *ct = *(struct termios *)data;
 1630                         return(0);
 1631                 case TIOCGETA:
 1632                         *(struct termios *)data = *ct;
 1633                         return(0);
 1634                 case TIOCGETD:
 1635                         *(int *)data = TTYDISC;
 1636                         return(0);
 1637                 case TIOCGWINSZ:
 1638                         bzero(data, sizeof(struct winsize));
 1639                         return(0);
 1640                 default:
 1641                         return(ENOTTY);
 1642                 }
 1643         }
 1644 
 1645         tp = rp->rp_tty;
 1646         cp = &rp->rp_channel;
 1647 
 1648 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1649         term = tp->t_termios;
 1650         oldcmd = cmd;
 1651         error = ttsetcompat(tp, &cmd, data, &term);
 1652         if(error != 0)
 1653                 return(error);
 1654         if(cmd != oldcmd) {
 1655                 data = (caddr_t)&term;
 1656         }
 1657 #endif
 1658         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1659                 int     cc;
 1660                 struct  termios *dt = (struct termios *)data;
 1661                 struct  termios *lt = IS_CALLOUT(dev)
 1662                                         ? &rp->lt_out : &rp->lt_in;
 1663 
 1664                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
 1665                                 | (dt->c_iflag & ~lt->c_iflag);
 1666                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
 1667                                 | (dt->c_oflag & ~lt->c_oflag);
 1668                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
 1669                                 | (dt->c_cflag & ~lt->c_cflag);
 1670                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
 1671                                 | (dt->c_lflag & ~lt->c_lflag);
 1672                 for(cc = 0; cc < NCCS; ++cc)
 1673                         if(lt->c_cc[cc] != 0)
 1674                                 dt->c_cc[cc] = tp->t_cc[cc];
 1675                 if(lt->c_ispeed != 0)
 1676                         dt->c_ispeed = tp->t_ispeed;
 1677                 if(lt->c_ospeed != 0)
 1678                         dt->c_ospeed = tp->t_ospeed;
 1679         }
 1680 
 1681         t = &tp->t_termios;
 1682 
 1683         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 1684         if(error != ENOIOCTL) {
 1685                 return(error);
 1686         }
 1687         oldspl = spltty();
 1688 
 1689         flags = rp->rp_channel.TxControl[3];
 1690 
 1691         error = ttioctl(tp, cmd, data, flag);
 1692         flags = rp->rp_channel.TxControl[3];
 1693         rp_disc_optim(tp, &tp->t_termios, rp);
 1694         if(error != ENOIOCTL) {
 1695                 splx(oldspl);
 1696                 return(error);
 1697         }
 1698         switch(cmd) {
 1699         case TIOCSBRK:
 1700                 sSendBreak(&rp->rp_channel);
 1701                 break;
 1702 
 1703         case TIOCCBRK:
 1704                 sClrBreak(&rp->rp_channel);
 1705                 break;
 1706 
 1707         case TIOCSDTR:
 1708                 sSetDTR(&rp->rp_channel);
 1709                 sSetRTS(&rp->rp_channel);
 1710                 break;
 1711 
 1712         case TIOCCDTR:
 1713                 sClrDTR(&rp->rp_channel);
 1714                 break;
 1715 
 1716         case TIOCMSET:
 1717                 arg = *(int *) data;
 1718                 flags = 0;
 1719                 if(arg & TIOCM_RTS)
 1720                         flags |= SET_RTS;
 1721                 if(arg & TIOCM_DTR)
 1722                         flags |= SET_DTR;
 1723                 rp->rp_channel.TxControl[3] =
 1724                         ((rp->rp_channel.TxControl[3]
 1725                         & ~(SET_RTS | SET_DTR)) | flags);
 1726                 sOutDW(rp->rp_channel.IndexAddr,
 1727                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1728                 break;
 1729         case TIOCMBIS:
 1730                 arg = *(int *) data;
 1731                 flags = 0;
 1732                 if(arg & TIOCM_RTS)
 1733                         flags |= SET_RTS;
 1734                 if(arg & TIOCM_DTR)
 1735                         flags |= SET_DTR;
 1736                         rp->rp_channel.TxControl[3] |= flags;
 1737                 sOutDW(rp->rp_channel.IndexAddr,
 1738                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1739                 break;
 1740         case TIOCMBIC:
 1741                 arg = *(int *) data;
 1742                 flags = 0;
 1743                 if(arg & TIOCM_RTS)
 1744                         flags |= SET_RTS;
 1745                 if(arg & TIOCM_DTR)
 1746                         flags |= SET_DTR;
 1747                 rp->rp_channel.TxControl[3] &= ~flags;
 1748                 sOutDW(rp->rp_channel.IndexAddr,
 1749                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
 1750                 break;
 1751 
 1752 
 1753         case TIOCMGET:
 1754                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
 1755                 flags = rp->rp_channel.TxControl[3];
 1756                 result = TIOCM_LE; /* always on while open for some reason */
 1757                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
 1758                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
 1759                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
 1760                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
 1761                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
 1762 
 1763                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
 1764                 {
 1765                         result |= TIOCM_RTS;
 1766                 }
 1767 
 1768                 *(int *)data = result;
 1769                 break;
 1770         case TIOCMSDTRWAIT:
 1771                 error = suser(p->p_ucred, &p->p_acflag);
 1772                 if(error != 0) {
 1773                         splx(oldspl);
 1774                         return(error);
 1775                 }
 1776                 rp->dtr_wait = *(int *)data * hz/100;
 1777                 break;
 1778         case TIOCMGDTRWAIT:
 1779                 *(int *)data = rp->dtr_wait * 100/hz;
 1780                 break;
 1781         default:
 1782                 splx(oldspl);
 1783                 return ENOTTY;
 1784         }
 1785         splx(oldspl);
 1786         return(0);
 1787 }
 1788 
 1789 static struct speedtab baud_table[] = {
 1790         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
 1791         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
 1792         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
 1793         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
 1794         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
 1795         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
 1796                                 {B57600, BRD57600},     {B76800, BRD76800},
 1797         {B115200, BRD115200},   {B230400, BRD230400},
 1798         -1,     -1
 1799 };
 1800 
 1801 static int
 1802 rpparam(tp, t)
 1803         struct tty *tp;
 1804         struct termios *t;
 1805 {
 1806         struct rp_port  *rp;
 1807         CHANNEL_t       *cp;
 1808         int     unit, mynor, port, umynor;               /* SG */
 1809         int     oldspl, cflag, iflag, oflag, lflag;
 1810         int     ospeed;
 1811 
 1812 
 1813    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1814         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1815         mynor = (port + umynor);                          /* SG */
 1816 
 1817         unit = minor_to_unit[mynor];
 1818         rp = rp_addr(unit) + port;
 1819         cp = &rp->rp_channel;
 1820         oldspl = spltty();
 1821 
 1822         cflag = t->c_cflag;
 1823         iflag = t->c_iflag;
 1824         oflag = t->c_oflag;
 1825         lflag = t->c_lflag;
 1826 
 1827         ospeed = ttspeedtab(t->c_ispeed, baud_table);
 1828         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
 1829                 return(EINVAL);
 1830 
 1831         tp->t_ispeed = t->c_ispeed;
 1832         tp->t_ospeed = t->c_ospeed;
 1833         tp->t_cflag = cflag;
 1834         tp->t_iflag = iflag;
 1835         tp->t_oflag = oflag;
 1836         tp->t_lflag = lflag;
 1837 
 1838         if(t->c_ospeed == 0) {
 1839                 sClrDTR(cp);
 1840                 return(0);
 1841         }
 1842         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
 1843 
 1844         /* Set baud rate ----- we only pay attention to ispeed */
 1845         sSetDTR(cp);
 1846         sSetRTS(cp);
 1847         sSetBaud(cp, ospeed);
 1848 
 1849         if(cflag & CSTOPB) {
 1850                 sSetStop2(cp);
 1851         } else {
 1852                 sSetStop1(cp);
 1853         }
 1854 
 1855         if(cflag & PARENB) {
 1856                 sEnParity(cp);
 1857                 if(cflag & PARODD) {
 1858                         sSetOddParity(cp);
 1859                 } else {
 1860                         sSetEvenParity(cp);
 1861                 }
 1862         }
 1863         else {
 1864                 sDisParity(cp);
 1865         }
 1866         if((cflag & CSIZE) == CS8) {
 1867                 sSetData8(cp);
 1868                 rp->rp_imask = 0xFF;
 1869         } else {
 1870                 sSetData7(cp);
 1871                 rp->rp_imask = 0x7F;
 1872         }
 1873 
 1874         if(iflag & ISTRIP) {
 1875                 rp->rp_imask &= 0x7F;
 1876         }
 1877 
 1878         if(cflag & CLOCAL) {
 1879                 rp->rp_intmask &= ~DELTA_CD;
 1880         } else {
 1881                 rp->rp_intmask |= DELTA_CD;
 1882         }
 1883 
 1884         /* Put flow control stuff here */
 1885 
 1886         if(cflag & CCTS_OFLOW) {
 1887                 sEnCTSFlowCtl(cp);
 1888         } else {
 1889                 sDisCTSFlowCtl(cp);
 1890         }
 1891 
 1892         if(cflag & CRTS_IFLOW) {
 1893                 rp->rp_rts_iflow = 1;
 1894         } else {
 1895                 rp->rp_rts_iflow = 0;
 1896         }
 1897 
 1898         if(cflag & CRTS_IFLOW) {
 1899                 sEnRTSFlowCtl(cp);
 1900         } else {
 1901                 sDisRTSFlowCtl(cp);
 1902         }
 1903         rp_disc_optim(tp, t, rp);
 1904 
 1905         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
 1906                 tp->t_state |= TS_CARR_ON;
 1907                 wakeup(TSA_CARR_ON(tp));
 1908         }
 1909 
 1910 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1911         flags = rp->rp_channel.TxControl[3];
 1912         if(flags & SET_DTR)
 1913         else
 1914         if(flags & SET_RTS)
 1915         else
 1916 */
 1917         splx(oldspl);
 1918 
 1919         return(0);
 1920 }
 1921 
 1922 static void
 1923 rp_disc_optim(tp, t, rp)
 1924 struct  tty     *tp;
 1925 struct  termios *t;
 1926 struct  rp_port *rp;
 1927 {
 1928         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
 1929                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
 1930                 &&(!(t->c_iflag & PARMRK)
 1931                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
 1932                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
 1933                 && linesw[tp->t_line].l_rint == ttyinput)
 1934                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
 1935         else
 1936                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 1937 }
 1938 
 1939 static void
 1940 rpstart(tp)
 1941         struct tty *tp;
 1942 {
 1943         struct rp_port  *rp;
 1944         CHANNEL_t       *cp;
 1945         struct  clist   *qp;
 1946         int     unit, mynor, port, umynor;               /* SG */
 1947         char    ch, flags;
 1948         int     spl, xmit_fifo_room;
 1949         int     count;
 1950 
 1951 
 1952    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 1953         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 1954         mynor = (port + umynor);                          /* SG */
 1955         unit = minor_to_unit[mynor];
 1956         rp = rp_addr(unit) + port;
 1957         cp = &rp->rp_channel;
 1958         flags = rp->rp_channel.TxControl[3];
 1959         spl = spltty();
 1960 
 1961         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1962                 ttwwakeup(tp);
 1963                 splx(spl);
 1964                 return;
 1965         }
 1966         if(rp->rp_xmit_stopped) {
 1967                 sEnTransmit(cp);
 1968                 rp->rp_xmit_stopped = 0;
 1969         }
 1970         count = sGetTxCnt(cp);
 1971 
 1972         if(tp->t_outq.c_cc == 0) {
 1973                 if((tp->t_state & TS_BUSY) && (count == 0)) {
 1974                         tp->t_state &= ~TS_BUSY;
 1975                 }
 1976                 ttwwakeup(tp);
 1977                 splx(spl);
 1978                 return;
 1979         }
 1980         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
 1981         qp = &tp->t_outq;
 1982         count = 0;
 1983         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1984                 tp->t_state |= TS_BUSY;
 1985         }
 1986         while(xmit_fifo_room > 0 && qp->c_cc > 0) {
 1987                 ch = getc(qp);
 1988                 sOutB(sGetTxRxDataIO(cp), ch);
 1989                 xmit_fifo_room--;
 1990                 count++;
 1991         }
 1992         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
 1993 
 1994         ttwwakeup(tp);
 1995         splx(spl);
 1996 }
 1997 
 1998 static
 1999 void
 2000 rpstop(tp, flag)
 2001         register struct tty *tp;
 2002         int     flag;
 2003 {
 2004         struct rp_port  *rp;
 2005         CHANNEL_t       *cp;
 2006         int     unit, mynor, port, umynor;                  /* SG */
 2007         int     spl;
 2008 
 2009    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
 2010         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
 2011         mynor = (port + umynor);                          /* SG */
 2012         unit = minor_to_unit[mynor];
 2013         rp = rp_addr(unit) + port;
 2014         cp = &rp->rp_channel;
 2015 
 2016         spl = spltty();
 2017 
 2018         if(tp->t_state & TS_BUSY) {
 2019                 if((tp->t_state&TS_TTSTOP) == 0) {
 2020                         sFlushTxFIFO(cp);
 2021                 } else {
 2022                         if(rp->rp_xmit_stopped == 0) {
 2023                                 sDisTransmit(cp);
 2024                                 rp->rp_xmit_stopped = 1;
 2025                         }
 2026                 }
 2027         }
 2028         splx(spl);
 2029         rpstart(tp);
 2030 }
 2031 
 2032 int
 2033 rpselect(dev, flag, p)
 2034         dev_t dev;
 2035         int flag;
 2036         struct proc *p;
 2037 {
 2038         return(0);
 2039 }
 2040 
 2041 struct tty *
 2042 rpdevtotty(dev_t dev)
 2043 {
 2044         struct  rp_port *rp;
 2045         int     unit, port, mynor, umynor;         /* SG */
 2046 
 2047    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
 2048         port  = (minor(dev) & 0x1f);                /* SG */
 2049         mynor = (port + umynor);                    /* SG */
 2050    unit = minor_to_unit[mynor];                /* SG */
 2051 
 2052         if(IS_CONTROL(dev))
 2053                 return(NULL);
 2054         rp = rp_addr(unit) + port;
 2055         return(rp->rp_tty);
 2056 }

Cache object: 6b994b00f5d87af4a2b9296c53c518f0


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