File:  [DragonFly] / src / sys / dev / serial / rp / rp.c
Revision 1.10: download - view: text, annotated - select for diffs
Thu May 13 23:49:20 2004 UTC (10 years, 6 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

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