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