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