]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/rp/rp.c
This commit was generated by cvs2svn to compensate for changes in r146901,
[FreeBSD/FreeBSD.git] / sys / dev / rp / rp.c
1 /*-
2  * Copyright (c) Comtrol Corporation <support@comtrol.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted prodived that the follwoing conditions
7  * are met.
8  * 1. Redistributions of source code must retain the above copyright 
9  *    notive, this list of conditions and the following disclainer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials prodided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *       This product includes software developed by Comtrol Corporation.
16  * 4. The name of Comtrol Corporation may not be used to endorse or 
17  *    promote products derived from this software without specific 
18  *    prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 /* 
38  * rp.c - for RocketPort FreeBSD
39  */
40
41 #include "opt_compat.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/fcntl.h>
46 #include <sys/malloc.h>
47 #include <sys/serial.h>
48 #include <sys/tty.h>
49 #include <sys/conf.h>
50 #include <sys/kernel.h>
51 #include <machine/resource.h>
52 #include <machine/bus.h>
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55
56 #define ROCKET_C
57 #include <dev/rp/rpreg.h>
58 #include <dev/rp/rpvar.h>
59
60 static const char RocketPortVersion[] = "3.02";
61
62 static Byte_t RData[RDATASIZE] =
63 {
64    0x00, 0x09, 0xf6, 0x82,
65    0x02, 0x09, 0x86, 0xfb,
66    0x04, 0x09, 0x00, 0x0a,
67    0x06, 0x09, 0x01, 0x0a,
68    0x08, 0x09, 0x8a, 0x13,
69    0x0a, 0x09, 0xc5, 0x11,
70    0x0c, 0x09, 0x86, 0x85,
71    0x0e, 0x09, 0x20, 0x0a,
72    0x10, 0x09, 0x21, 0x0a,
73    0x12, 0x09, 0x41, 0xff,
74    0x14, 0x09, 0x82, 0x00,
75    0x16, 0x09, 0x82, 0x7b,
76    0x18, 0x09, 0x8a, 0x7d,
77    0x1a, 0x09, 0x88, 0x81,
78    0x1c, 0x09, 0x86, 0x7a,
79    0x1e, 0x09, 0x84, 0x81,
80    0x20, 0x09, 0x82, 0x7c,
81    0x22, 0x09, 0x0a, 0x0a
82 };
83
84 static Byte_t RRegData[RREGDATASIZE]=
85 {
86    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
87    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
88    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
89    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
90    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
91    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
92    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
93    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
94    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
95    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
96    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
97    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
98    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
99 };
100
101 #if 0
102 /* IRQ number to MUDBAC register 2 mapping */
103 Byte_t sIRQMap[16] =
104 {
105    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
106 };
107 #endif
108
109 Byte_t rp_sBitMapClrTbl[8] =
110 {
111    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
112 };
113
114 Byte_t rp_sBitMapSetTbl[8] =
115 {
116    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
117 };
118
119 /***************************************************************************
120 Function: sReadAiopID
121 Purpose:  Read the AIOP idenfication number directly from an AIOP.
122 Call:     sReadAiopID(CtlP, aiop)
123           CONTROLLER_T *CtlP; Ptr to controller structure
124           int aiop: AIOP index
125 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
126                  is replace by an identifying number.
127           Flag AIOPID_NULL if no valid AIOP is found
128 Warnings: No context switches are allowed while executing this function.
129
130 */
131 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
132 {
133    Byte_t AiopID;               /* ID byte from AIOP */
134
135    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
136    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
137    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
138    if(AiopID == 0x06)
139       return(1);
140    else                                /* AIOP does not exist */
141       return(-1);
142 }
143
144 /***************************************************************************
145 Function: sReadAiopNumChan
146 Purpose:  Read the number of channels available in an AIOP directly from
147           an AIOP.
148 Call:     sReadAiopNumChan(CtlP, aiop)
149           CONTROLLER_T *CtlP; Ptr to controller structure
150           int aiop: AIOP index
151 Return:   int: The number of channels available
152 Comments: The number of channels is determined by write/reads from identical
153           offsets within the SRAM address spaces for channels 0 and 4.
154           If the channel 4 space is mirrored to channel 0 it is a 4 channel
155           AIOP, otherwise it is an 8 channel.
156 Warnings: No context switches are allowed while executing this function.
157 */
158 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
159 {
160    Word_t x, y;
161
162    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
163    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
164    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
165    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
166    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
167    if(x != y)  /* if different must be 8 chan */
168       return(8);
169    else
170       return(4);
171 }
172
173 /***************************************************************************
174 Function: sInitChan
175 Purpose:  Initialization of a channel and channel structure
176 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
177           CONTROLLER_T *CtlP; Ptr to controller structure
178           CHANNEL_T *ChP; Ptr to channel structure
179           int AiopNum; AIOP number within controller
180           int ChanNum; Channel number within AIOP
181 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
182                number exceeds number of channels available in AIOP.
183 Comments: This function must be called before a channel can be used.
184 Warnings: No range checking on any of the parameters is done.
185
186           No context switches are allowed while executing this function.
187 */
188 int sInitChan(  CONTROLLER_T *CtlP,
189                 CHANNEL_T *ChP,
190                 int AiopNum,
191                 int ChanNum)
192 {
193    int i, ChOff;
194    Byte_t *ChR;
195    static Byte_t R[4];
196
197    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
198       return(FALSE);                   /* exceeds num chans in AIOP */
199
200    /* Channel, AIOP, and controller identifiers */
201    ChP->CtlP = CtlP;
202    ChP->ChanID = CtlP->AiopID[AiopNum];
203    ChP->AiopNum = AiopNum;
204    ChP->ChanNum = ChanNum;
205
206    /* Initialize the channel from the RData array */
207    for(i=0; i < RDATASIZE; i+=4)
208    {
209       R[0] = RData[i];
210       R[1] = RData[i+1] + 0x10 * ChanNum;
211       R[2] = RData[i+2];
212       R[3] = RData[i+3];
213       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
214    }
215
216    ChR = ChP->R;
217    for(i=0; i < RREGDATASIZE; i+=4)
218    {
219       ChR[i] = RRegData[i];
220       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
221       ChR[i+2] = RRegData[i+2];
222       ChR[i+3] = RRegData[i+3];
223    }
224
225    /* Indexed registers */
226    ChOff = (Word_t)ChanNum * 0x1000;
227
228    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
229    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
230    ChP->BaudDiv[2] = (Byte_t)BRD9600;
231    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
232    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
233
234    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
235    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
236    ChP->TxControl[2] = 0;
237    ChP->TxControl[3] = 0;
238    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
239
240    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
241    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
242    ChP->RxControl[2] = 0;
243    ChP->RxControl[3] = 0;
244    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
245
246    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
247    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
248    ChP->TxEnables[2] = 0;
249    ChP->TxEnables[3] = 0;
250    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
251
252    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
253    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
254    ChP->TxCompare[2] = 0;
255    ChP->TxCompare[3] = 0;
256    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
257
258    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
259    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
260    ChP->TxReplace1[2] = 0;
261    ChP->TxReplace1[3] = 0;
262    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
263
264    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
265    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
266    ChP->TxReplace2[2] = 0;
267    ChP->TxReplace2[3] = 0;
268    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
269
270    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
271    ChP->TxFIFO = ChOff + _TX_FIFO;
272
273    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
274    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
275    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
276    rp_writech2(ChP,_INDX_DATA,0);
277    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
278    ChP->RxFIFO = ChOff + _RX_FIFO;
279
280    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
281    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
282    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
283    rp_writech2(ChP,_INDX_DATA,0);
284    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
285    rp_writech2(ChP,_INDX_DATA,0);
286    ChP->TxPrioCnt = ChOff + _TXP_CNT;
287    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
288    rp_writech1(ChP,_INDX_DATA,0);
289    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
290    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
291    rp_writech1(ChP,_INDX_DATA,0);
292    ChP->TxPrioBuf = ChOff + _TXP_BUF;
293    sEnRxProcessor(ChP);                /* start the Rx processor */
294
295    return(TRUE);
296 }
297
298 /***************************************************************************
299 Function: sStopRxProcessor
300 Purpose:  Stop the receive processor from processing a channel.
301 Call:     sStopRxProcessor(ChP)
302           CHANNEL_T *ChP; Ptr to channel structure
303
304 Comments: The receive processor can be started again with sStartRxProcessor().
305           This function causes the receive processor to skip over the
306           stopped channel.  It does not stop it from processing other channels.
307
308 Warnings: No context switches are allowed while executing this function.
309
310           Do not leave the receive processor stopped for more than one
311           character time.
312
313           After calling this function a delay of 4 uS is required to ensure
314           that the receive processor is no longer processing this channel.
315 */
316 void sStopRxProcessor(CHANNEL_T *ChP)
317 {
318    Byte_t R[4];
319
320    R[0] = ChP->R[0];
321    R[1] = ChP->R[1];
322    R[2] = 0x0a;
323    R[3] = ChP->R[3];
324    rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
325 }
326
327 /***************************************************************************
328 Function: sFlushRxFIFO
329 Purpose:  Flush the Rx FIFO
330 Call:     sFlushRxFIFO(ChP)
331           CHANNEL_T *ChP; Ptr to channel structure
332 Return:   void
333 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
334           while it is being flushed the receive processor is stopped
335           and the transmitter is disabled.  After these operations a
336           4 uS delay is done before clearing the pointers to allow
337           the receive processor to stop.  These items are handled inside
338           this function.
339 Warnings: No context switches are allowed while executing this function.
340 */
341 void sFlushRxFIFO(CHANNEL_T *ChP)
342 {
343    int i;
344    Byte_t Ch;                   /* channel number within AIOP */
345    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
346
347    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
348       return;                          /* don't need to flush */
349
350    RxFIFOEnabled = FALSE;
351    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
352    {
353       RxFIFOEnabled = TRUE;
354       sDisRxFIFO(ChP);                 /* disable it */
355       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
356          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
357    }
358    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
359    Ch = (Byte_t)sGetChanNum(ChP);
360    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
361    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
362    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
363    rp_writech2(ChP,_INDX_DATA,0);
364    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
365    rp_writech2(ChP,_INDX_DATA,0);
366    if(RxFIFOEnabled)
367       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
368 }
369
370 /***************************************************************************
371 Function: sFlushTxFIFO
372 Purpose:  Flush the Tx FIFO
373 Call:     sFlushTxFIFO(ChP)
374           CHANNEL_T *ChP; Ptr to channel structure
375 Return:   void
376 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
377           while it is being flushed the receive processor is stopped
378           and the transmitter is disabled.  After these operations a
379           4 uS delay is done before clearing the pointers to allow
380           the receive processor to stop.  These items are handled inside
381           this function.
382 Warnings: No context switches are allowed while executing this function.
383 */
384 void sFlushTxFIFO(CHANNEL_T *ChP)
385 {
386    int i;
387    Byte_t Ch;                   /* channel number within AIOP */
388    int TxEnabled;                      /* TRUE if transmitter enabled */
389
390    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
391       return;                          /* don't need to flush */
392
393    TxEnabled = FALSE;
394    if(ChP->TxControl[3] & TX_ENABLE)
395    {
396       TxEnabled = TRUE;
397       sDisTransmit(ChP);               /* disable transmitter */
398    }
399    sStopRxProcessor(ChP);              /* stop Rx processor */
400    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
401       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
402    Ch = (Byte_t)sGetChanNum(ChP);
403    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
404    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
405    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
406    rp_writech2(ChP,_INDX_DATA,0);
407    if(TxEnabled)
408       sEnTransmit(ChP);                /* enable transmitter */
409    sStartRxProcessor(ChP);             /* restart Rx processor */
410 }
411
412 /***************************************************************************
413 Function: sWriteTxPrioByte
414 Purpose:  Write a byte of priority transmit data to a channel
415 Call:     sWriteTxPrioByte(ChP,Data)
416           CHANNEL_T *ChP; Ptr to channel structure
417           Byte_t Data; The transmit data byte
418
419 Return:   int: 1 if the bytes is successfully written, otherwise 0.
420
421 Comments: The priority byte is transmitted before any data in the Tx FIFO.
422
423 Warnings: No context switches are allowed while executing this function.
424 */
425 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
426 {
427    Byte_t DWBuf[4];             /* buffer for double word writes */
428    Word_t *WordPtr;          /* must be far because Win SS != DS */
429
430    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
431    {
432       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
433       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
434          return(0);                    /* nothing sent */
435
436       WordPtr = (Word_t *)(&DWBuf[0]);
437       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
438
439       DWBuf[2] = Data;                 /* data byte value */
440       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
441
442       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
443
444       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
445       DWBuf[3] = 0;                    /* priority buffer pointer */
446       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
447    }
448    else                                /* write it to Tx FIFO */
449    {
450       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
451    }
452    return(1);                          /* 1 byte sent */
453 }
454
455 /***************************************************************************
456 Function: sEnInterrupts
457 Purpose:  Enable one or more interrupts for a channel
458 Call:     sEnInterrupts(ChP,Flags)
459           CHANNEL_T *ChP; Ptr to channel structure
460           Word_t Flags: Interrupt enable flags, can be any combination
461              of the following flags:
462                 TXINT_EN:   Interrupt on Tx FIFO empty
463                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
464                             sSetRxTrigger())
465                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
466                 MCINT_EN:   Interrupt on modem input change
467                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
468                             Interrupt Channel Register.
469 Return:   void
470 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
471           enabled.  If an interrupt enable flag is not set in Flags, that
472           interrupt will not be changed.  Interrupts can be disabled with
473           function sDisInterrupts().
474
475           This function sets the appropriate bit for the channel in the AIOP's
476           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
477           this channel's bit to be set in the AIOP's Interrupt Channel Register.
478
479           Interrupts must also be globally enabled before channel interrupts
480           will be passed on to the host.  This is done with function
481           sEnGlobalInt().
482
483           In some cases it may be desirable to disable interrupts globally but
484           enable channel interrupts.  This would allow the global interrupt
485           status register to be used to determine which AIOPs need service.
486 */
487 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
488 {
489    Byte_t Mask;                 /* Interrupt Mask Register */
490
491    ChP->RxControl[2] |=
492       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
493
494    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
495
496    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
497
498    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
499
500    if(Flags & CHANINT_EN)
501    {
502       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
503       rp_writech1(ChP,_INT_MASK,Mask);
504    }
505 }
506
507 /***************************************************************************
508 Function: sDisInterrupts
509 Purpose:  Disable one or more interrupts for a channel
510 Call:     sDisInterrupts(ChP,Flags)
511           CHANNEL_T *ChP; Ptr to channel structure
512           Word_t Flags: Interrupt flags, can be any combination
513              of the following flags:
514                 TXINT_EN:   Interrupt on Tx FIFO empty
515                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
516                             sSetRxTrigger())
517                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
518                 MCINT_EN:   Interrupt on modem input change
519                 CHANINT_EN: Disable channel interrupt signal to the
520                             AIOP's Interrupt Channel Register.
521 Return:   void
522 Comments: If an interrupt flag is set in Flags, that interrupt will be
523           disabled.  If an interrupt flag is not set in Flags, that
524           interrupt will not be changed.  Interrupts can be enabled with
525           function sEnInterrupts().
526
527           This function clears the appropriate bit for the channel in the AIOP's
528           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
529           this channel's bit from being set in the AIOP's Interrupt Channel
530           Register.
531 */
532 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
533 {
534    Byte_t Mask;                 /* Interrupt Mask Register */
535
536    ChP->RxControl[2] &=
537          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
538    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
539    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
540    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
541
542    if(Flags & CHANINT_EN)
543    {
544       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
545       rp_writech1(ChP,_INT_MASK,Mask);
546    }
547 }
548
549 /*********************************************************************
550   Begin FreeBsd-specific driver code
551 **********************************************************************/
552
553 struct callout_handle rp_callout_handle;
554
555 static int      rp_num_ports_open = 0;
556 static int      rp_ndevs = 0;
557
558 static int rp_num_ports[4];     /* Number of ports on each controller */
559
560 #define POLL_INTERVAL 1
561
562 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
563 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
564 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
565
566 static  struct  rp_port *p_rp_addr[4];
567 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
568 #define rp_addr(unit)   (p_rp_addr[unit])
569 #define rp_table(port)  (p_rp_table[port])
570
571 /*
572  * The top-level routines begin here
573  */
574
575 static  void    rpbreak(struct tty *, int);
576 static  void    rpclose(struct tty *tp);
577 static  int     rpmodem(struct tty *, int, int);
578 static  int     rpparam(struct tty *, struct termios *);
579 static  void    rpstart(struct tty *);
580 static  void    rpstop(struct tty *, int);
581 static  t_open_t        rpopen;
582
583 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
584                         CHANNEL_t *cp, unsigned int ChanStatus)
585 {
586         int     spl;
587         unsigned        int     CharNStat;
588         int     ToRecv, wRecv, ch, ttynocopy;
589
590         ToRecv = sGetRxCnt(cp);
591         if(ToRecv == 0)
592                 return;
593
594 /*      If status indicates there are errored characters in the
595         FIFO, then enter status mode (a word in FIFO holds
596         characters and status)
597 */
598
599         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
600                 if(!(ChanStatus & STATMODE)) {
601                         ChanStatus |= STATMODE;
602                         sEnRxStatusMode(cp);
603                 }
604         }
605 /*
606         if we previously entered status mode then read down the
607         FIFO one word at a time, pulling apart the character and
608         the status. Update error counters depending on status.
609 */
610         if(ChanStatus & STATMODE) {
611                 while(ToRecv) {
612                         if(tp->t_state & TS_TBLOCK) {
613                                 break;
614                         }
615                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
616                         ch = CharNStat & 0xff;
617
618                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
619                                 ch |= TTY_FE;
620                         else if (CharNStat & STMPARITYH)
621                                 ch |= TTY_PE;
622                         else if (CharNStat & STMRCVROVRH)
623                                 rp->rp_overflows++;
624
625                         ttyld_rint(tp, ch);
626                         ToRecv--;
627                 }
628 /*
629         After emtying FIFO in status mode, turn off status mode
630 */
631
632                 if(sGetRxCnt(cp) == 0) {
633                         sDisRxStatusMode(cp);
634                 }
635         } else {
636                 /*
637                  * Avoid the grotesquely inefficient lineswitch routine
638                  * (ttyinput) in "raw" mode.  It usually takes about 450
639                  * instructions (that's without canonical processing or echo!).
640                  * slinput is reasonably fast (usually 40 instructions plus
641                  * call overhead).
642                  */
643                 ToRecv = sGetRxCnt(cp);
644                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
645                         if ( ToRecv > RXFIFO_SIZE ) {
646                                 ToRecv = RXFIFO_SIZE;
647                         }
648                         wRecv = ToRecv >> 1;
649                         if ( wRecv ) {
650                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
651                         }
652                         if ( ToRecv & 1 ) {
653                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
654                         }
655                         tk_nin += ToRecv;
656                         tk_rawcc += ToRecv;
657                         tp->t_rawcc += ToRecv;
658                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
659                         ttwakeup(tp);
660                 } else {
661                         while (ToRecv) {
662                                 if(tp->t_state & TS_TBLOCK) {
663                                         break;
664                                 }
665                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
666                                 spl = spltty();
667                                 ttyld_rint(tp, ch);
668                                 splx(spl);
669                                 ToRecv--;
670                         }
671                 }
672         }
673 }
674
675 static void rp_handle_port(struct rp_port *rp)
676 {
677         CHANNEL_t       *cp;
678         struct  tty     *tp;
679         unsigned        int     IntMask, ChanStatus;
680
681         if(!rp)
682                 return;
683
684         cp = &rp->rp_channel;
685         tp = rp->rp_tty;
686         IntMask = sGetChanIntID(cp);
687         IntMask = IntMask & rp->rp_intmask;
688         ChanStatus = sGetChanStatus(cp);
689         if(IntMask & RXF_TRIG)
690                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
691                         rp_do_receive(rp, tp, cp, ChanStatus);
692                 }
693         if(IntMask & DELTA_CD) {
694                 if(ChanStatus & CD_ACT) {
695                         if(!(tp->t_state & TS_CARR_ON) ) {
696                                 (void)ttyld_modem(tp, 1);
697                         }
698                 } else {
699                         if((tp->t_state & TS_CARR_ON)) {
700                                 (void)ttyld_modem(tp, 0);
701                                 if(ttyld_modem(tp, 0) == 0) {
702                                         tp->t_close(tp);
703                                 }
704                         }
705                 }
706         }
707 /*      oldcts = rp->rp_cts;
708         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
709         if(oldcts != rp->rp_cts) {
710                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
711         }
712 */
713 }
714
715 static void rp_do_poll(void *not_used)
716 {
717         CONTROLLER_t    *ctl;
718         struct rp_port  *rp;
719         struct tty      *tp;
720         int     unit, aiop, ch, line, count;
721         unsigned char   CtlMask, AiopMask;
722
723         for(unit = 0; unit < rp_ndevs; unit++) {
724         rp = rp_addr(unit);
725         ctl = rp->rp_ctlp;
726         CtlMask = ctl->ctlmask(ctl);
727         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
728                 if(CtlMask & 1) {
729                         AiopMask = sGetAiopIntStatus(ctl, aiop);
730                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
731                                 if(AiopMask & 1) {
732                                         line = (unit << 5) | (aiop << 3) | ch;
733                                         rp = rp_table(line);
734                                         rp_handle_port(rp);
735                                 }
736                         }
737                 }
738         }
739
740         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
741                         line++, rp++) {
742                 tp = rp->rp_tty;
743                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
744                         count = sGetTxCnt(&rp->rp_channel);
745                         if(count == 0)
746                                 tp->t_state &= ~(TS_BUSY);
747                         if(!(tp->t_state & TS_TTSTOP) &&
748                                 (count <= rp->rp_restart)) {
749                                 ttyld_start(tp);
750                         }
751                 }
752         }
753         }
754         if(rp_num_ports_open)
755                 rp_callout_handle = timeout(rp_do_poll, 
756                                             (void *)NULL, POLL_INTERVAL);
757 }
758
759 int
760 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
761 {
762         int     oldspl, unit;
763         int     num_chan;
764         int     aiop, chan, port;
765         int     ChanStatus, line, count;
766         int     retval;
767         struct  rp_port *rp;
768         struct tty *tp;
769
770         unit = device_get_unit(ctlp->dev);
771
772         printf("RocketPort%d (Version %s) %d ports.\n", unit,
773                 RocketPortVersion, num_ports);
774         rp_num_ports[unit] = num_ports;
775         callout_handle_init(&rp_callout_handle);
776
777         ctlp->rp = rp = (struct rp_port *)
778                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
779         if (rp == NULL) {
780                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
781                 retval = ENOMEM;
782                 goto nogo;
783         }
784
785         count = unit * 32;      /* board times max ports per card SG */
786
787         bzero(rp, sizeof(struct rp_port) * num_ports);
788         oldspl = spltty();
789         rp_addr(unit) = rp;
790         splx(oldspl);
791
792         port = 0;
793         for(aiop=0; aiop < num_aiops; aiop++) {
794                 num_chan = sGetAiopNumChan(ctlp, aiop);
795                 for(chan=0; chan < num_chan; chan++, port++, rp++) {
796                         tp = rp->rp_tty = ttyalloc();
797                         tp->t_sc = rp;
798                         tp->t_param = rpparam;
799                         tp->t_oproc = rpstart;
800                         tp->t_stop = rpstop;
801                         tp->t_break = rpbreak;
802                         tp->t_modem = rpmodem;
803                         tp->t_close = rpclose;
804                         tp->t_open = rpopen;
805                         tp->t_ififosize = 512;
806                         tp->t_ispeedwat = (speed_t)-1;
807                         tp->t_ospeedwat = (speed_t)-1;
808                         rp->rp_port = port;
809                         rp->rp_ctlp = ctlp;
810                         rp->rp_unit = unit;
811                         rp->rp_chan = chan;
812                         rp->rp_aiop = aiop;
813
814                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
815                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
816 #if notdef
817                         ChanStatus = sGetChanStatus(&rp->rp_channel);
818 #endif /* notdef */
819                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
820                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
821                                               unit, aiop, chan);
822                                 retval = ENXIO;
823                                 goto nogo;
824                         }
825                         ChanStatus = sGetChanStatus(&rp->rp_channel);
826                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
827                         line = (unit << 5) | (aiop << 3) | chan;
828                         rp_table(line) = rp;
829                         ttycreate(tp, NULL, 0, MINOR_CALLOUT, "R%r", port);
830                 }
831         }
832
833         rp_ndevs++;
834         return (0);
835
836 nogo:
837         rp_releaseresource(ctlp);
838
839         return (retval);
840 }
841
842 void
843 rp_releaseresource(CONTROLLER_t *ctlp)
844 {
845         int i, s, unit;
846         struct  rp_port *rp;
847
848
849         unit = device_get_unit(ctlp->dev);
850         if (rp_addr(unit) != NULL) {
851                 for (i = 0; i < rp_num_ports[unit]; i++) {
852                         rp = rp_addr(unit) + i;
853                         ttyfree(rp->rp_tty);
854                 }
855         }
856
857         if (ctlp->rp != NULL) {
858                 s = spltty();
859                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
860                         if (p_rp_addr[i] == ctlp->rp)
861                                 p_rp_addr[i] = NULL;
862                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
863                         if (p_rp_table[i] == ctlp->rp)
864                                 p_rp_table[i] = NULL;
865                 splx(s);
866                 free(ctlp->rp, M_DEVBUF);
867                 ctlp->rp = NULL;
868         }
869 }
870
871 void
872 rp_untimeout(void)
873 {
874         untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
875 }
876
877 static int
878 rpopen(struct tty *tp, struct cdev *dev)
879 {
880         struct  rp_port *rp;
881         int     oldspl, flags;
882         unsigned int    IntMask, ChanStatus;
883
884         rp = dev->si_drv1;
885
886         oldspl = spltty();
887
888         flags = 0;
889         flags |= SET_RTS;
890         flags |= SET_DTR;
891         rp->rp_channel.TxControl[3] =
892                 ((rp->rp_channel.TxControl[3]
893                 & ~(SET_RTS | SET_DTR)) | flags);
894         rp_writech4(&rp->rp_channel,_INDX_ADDR,
895                 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
896         sSetRxTrigger(&rp->rp_channel, TRIG_1);
897         sDisRxStatusMode(&rp->rp_channel);
898         sFlushRxFIFO(&rp->rp_channel);
899         sFlushTxFIFO(&rp->rp_channel);
900
901         sEnInterrupts(&rp->rp_channel,
902                 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
903         sSetRxTrigger(&rp->rp_channel, TRIG_1);
904
905         sDisRxStatusMode(&rp->rp_channel);
906         sClrTxXOFF(&rp->rp_channel);
907
908 /*      sDisRTSFlowCtl(&rp->rp_channel);
909         sDisCTSFlowCtl(&rp->rp_channel);
910 */
911         sDisTxSoftFlowCtl(&rp->rp_channel);
912
913         sStartRxProcessor(&rp->rp_channel);
914
915         sEnRxFIFO(&rp->rp_channel);
916         sEnTransmit(&rp->rp_channel);
917
918 /*      sSetDTR(&rp->rp_channel);
919         sSetRTS(&rp->rp_channel);
920 */
921
922         rp_num_ports_open++;
923
924         IntMask = sGetChanIntID(&rp->rp_channel);
925         IntMask = IntMask & rp->rp_intmask;
926         ChanStatus = sGetChanStatus(&rp->rp_channel);
927
928         if(rp_num_ports_open == 1)
929                 rp_callout_handle = timeout(rp_do_poll, 
930                                             (void *)NULL, POLL_INTERVAL);
931
932         device_busy(rp->rp_ctlp->dev);
933         return(0);
934 }
935
936 static void
937 rpclose(struct tty *tp)
938 {
939         struct  rp_port *rp;
940         CHANNEL_t       *cp;
941
942         rp = tp->t_sc;
943         cp = &rp->rp_channel;
944
945         sFlushRxFIFO(cp);
946         sFlushTxFIFO(cp);
947         sDisTransmit(cp);
948         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
949         sDisRTSFlowCtl(cp);
950         sDisCTSFlowCtl(cp);
951         sDisTxSoftFlowCtl(cp);
952         sClrTxXOFF(cp);
953
954         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) {
955                 sClrDTR(cp);
956         }
957         if(ISCALLOUT(tp->t_dev)) {
958                 sClrDTR(cp);
959         }
960         tp->t_actout = FALSE;
961         wakeup(&tp->t_actout);
962         wakeup(TSA_CARR_ON(tp));
963         device_unbusy(rp->rp_ctlp->dev);
964 }
965
966 static void
967 rpbreak(struct tty *tp, int sig)
968 {
969         struct rp_port  *rp;
970
971         rp = tp->t_sc;
972         if (sig) {
973                 sSendBreak(&rp->rp_channel);
974         } else {
975                 sClrBreak(&rp->rp_channel);
976         }
977 }
978
979 static int
980 rpmodem(struct tty *tp, int sigon, int sigoff)
981 {
982         struct rp_port  *rp;
983         int i, j, k;
984
985         rp = tp->t_sc;
986         if (sigon != 0 || sigoff != 0) {
987                 i = j = 0;
988                 if (sigon & SER_DTR)
989                         i = SET_DTR;
990                 if (sigoff & SER_DTR)
991                         j = SET_DTR;
992                 if (sigon & SER_RTS)
993                         i = SET_RTS;
994                 if (sigoff & SER_RTS)
995                         j = SET_RTS;
996                 rp->rp_channel.TxControl[3] &= ~i;
997                 rp->rp_channel.TxControl[3] |= j;
998                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
999                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1000         } else {
1001                 i = sGetChanStatusLo(&rp->rp_channel);
1002                 j = rp->rp_channel.TxControl[3];
1003                 k = 0;
1004                 if (j & SET_DTR)
1005                         k |= SER_DTR;
1006                 if (j & SET_RTS)
1007                         k |= SER_RTS;
1008                 if (i & CD_ACT)
1009                         k |= SER_DCD;
1010                 if (i & DSR_ACT)
1011                         k |= SER_DSR;
1012                 if (i & CTS_ACT)
1013                         k |= SER_CTS;
1014                 return(k);
1015         }
1016         return (0);
1017 }
1018
1019 static struct speedtab baud_table[] = {
1020         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
1021         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
1022         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
1023         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
1024         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
1025         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
1026                                 {B57600, BRD57600},     {B76800, BRD76800},
1027         {B115200, BRD115200},   {B230400, BRD230400},
1028         {-1,    -1}
1029 };
1030
1031 static int
1032 rpparam(tp, t)
1033         struct tty *tp;
1034         struct termios *t;
1035 {
1036         struct rp_port  *rp;
1037         CHANNEL_t       *cp;
1038         int     oldspl, cflag, iflag, oflag, lflag;
1039         int     ospeed;
1040 #ifdef RPCLOCAL
1041         int     devshift;
1042 #endif
1043
1044
1045         rp = tp->t_sc;
1046         cp = &rp->rp_channel;
1047         oldspl = spltty();
1048
1049         cflag = t->c_cflag;
1050 #ifdef RPCLOCAL
1051         devshift = umynor / 32;
1052         devshift = 1 << devshift;
1053         if ( devshift & RPCLOCAL ) {
1054                 cflag |= CLOCAL;
1055         }
1056 #endif
1057         iflag = t->c_iflag;
1058         oflag = t->c_oflag;
1059         lflag = t->c_lflag;
1060
1061         ospeed = ttspeedtab(t->c_ispeed, baud_table);
1062         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1063                 return(EINVAL);
1064
1065         tp->t_ispeed = t->c_ispeed;
1066         tp->t_ospeed = t->c_ospeed;
1067         tp->t_cflag = cflag;
1068         tp->t_iflag = iflag;
1069         tp->t_oflag = oflag;
1070         tp->t_lflag = lflag;
1071
1072         if(t->c_ospeed == 0) {
1073                 sClrDTR(cp);
1074                 return(0);
1075         }
1076         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1077
1078         /* Set baud rate ----- we only pay attention to ispeed */
1079         sSetDTR(cp);
1080         sSetRTS(cp);
1081         sSetBaud(cp, ospeed);
1082
1083         if(cflag & CSTOPB) {
1084                 sSetStop2(cp);
1085         } else {
1086                 sSetStop1(cp);
1087         }
1088
1089         if(cflag & PARENB) {
1090                 sEnParity(cp);
1091                 if(cflag & PARODD) {
1092                         sSetOddParity(cp);
1093                 } else {
1094                         sSetEvenParity(cp);
1095                 }
1096         }
1097         else {
1098                 sDisParity(cp);
1099         }
1100         if((cflag & CSIZE) == CS8) {
1101                 sSetData8(cp);
1102                 rp->rp_imask = 0xFF;
1103         } else {
1104                 sSetData7(cp);
1105                 rp->rp_imask = 0x7F;
1106         }
1107
1108         if(iflag & ISTRIP) {
1109                 rp->rp_imask &= 0x7F;
1110         }
1111
1112         if(cflag & CLOCAL) {
1113                 rp->rp_intmask &= ~DELTA_CD;
1114         } else {
1115                 rp->rp_intmask |= DELTA_CD;
1116         }
1117
1118         /* Put flow control stuff here */
1119
1120         if(cflag & CCTS_OFLOW) {
1121                 sEnCTSFlowCtl(cp);
1122         } else {
1123                 sDisCTSFlowCtl(cp);
1124         }
1125
1126         if(cflag & CRTS_IFLOW) {
1127                 rp->rp_rts_iflow = 1;
1128         } else {
1129                 rp->rp_rts_iflow = 0;
1130         }
1131
1132         if(cflag & CRTS_IFLOW) {
1133                 sEnRTSFlowCtl(cp);
1134         } else {
1135                 sDisRTSFlowCtl(cp);
1136         }
1137         ttyldoptim(tp);
1138
1139         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1140                 tp->t_state |= TS_CARR_ON;
1141                 wakeup(TSA_CARR_ON(tp));
1142         }
1143
1144 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
1145         flags = rp->rp_channel.TxControl[3];
1146         if(flags & SET_DTR)
1147         else
1148         if(flags & SET_RTS)
1149         else
1150 */
1151         splx(oldspl);
1152
1153         return(0);
1154 }
1155
1156 static void
1157 rpstart(tp)
1158         struct tty *tp;
1159 {
1160         struct rp_port  *rp;
1161         CHANNEL_t       *cp;
1162         struct  clist   *qp;
1163         char    flags;
1164         int     spl, xmit_fifo_room;
1165         int     count, wcount;
1166
1167
1168         rp = tp->t_sc;
1169         cp = &rp->rp_channel;
1170         flags = rp->rp_channel.TxControl[3];
1171         spl = spltty();
1172
1173         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1174                 ttwwakeup(tp);
1175                 splx(spl);
1176                 return;
1177         }
1178         if(rp->rp_xmit_stopped) {
1179                 sEnTransmit(cp);
1180                 rp->rp_xmit_stopped = 0;
1181         }
1182         count = sGetTxCnt(cp);
1183
1184         if(tp->t_outq.c_cc == 0) {
1185                 if((tp->t_state & TS_BUSY) && (count == 0)) {
1186                         tp->t_state &= ~TS_BUSY;
1187                 }
1188                 ttwwakeup(tp);
1189                 splx(spl);
1190                 return;
1191         }
1192         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1193         qp = &tp->t_outq;
1194         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1195                 tp->t_state |= TS_BUSY;
1196                 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1197                 wcount = count >> 1;
1198                 if ( wcount ) {
1199                         rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1200                 }
1201                 if ( count & 1 ) {
1202                         rp_writech1(cp, sGetTxRxDataIO(cp),
1203                                     ((unsigned char *)(rp->TxBuf))[(count-1)]);
1204                 }
1205         }
1206         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1207
1208         ttwwakeup(tp);
1209         splx(spl);
1210 }
1211
1212 static
1213 void
1214 rpstop(tp, flag)
1215         register struct tty *tp;
1216         int     flag;
1217 {
1218         struct rp_port  *rp;
1219         CHANNEL_t       *cp;
1220         int     spl;
1221
1222         rp = tp->t_sc;
1223         cp = &rp->rp_channel;
1224
1225         spl = spltty();
1226
1227         if(tp->t_state & TS_BUSY) {
1228                 if((tp->t_state&TS_TTSTOP) == 0) {
1229                         sFlushTxFIFO(cp);
1230                 } else {
1231                         if(rp->rp_xmit_stopped == 0) {
1232                                 sDisTransmit(cp);
1233                                 rp->rp_xmit_stopped = 1;
1234                         }
1235                 }
1236         }
1237         splx(spl);
1238         rpstart(tp);
1239 }