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