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