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