rp.c revision 50254
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 *	$Id: rp.c,v 1.28 1999/05/31 11:26:24 phk Exp $
33 */
34
35/*
36 * rp.c - for RocketPort FreeBSD
37 */
38
39#include "opt_compat.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/fcntl.h>
44#include <sys/malloc.h>
45#include <sys/tty.h>
46#include <sys/proc.h>
47#include <sys/conf.h>
48#include <sys/kernel.h>
49
50#include <i386/isa/isa_device.h>
51
52#include <pci/pcivar.h>
53
54#define ROCKET_C
55#include <i386/isa/rpreg.h>
56#include <i386/isa/rpvar.h>
57
58#ifndef TRUE
59#define TRUE 1
60#endif
61
62#ifndef FALSE
63#define FALSE 0
64#endif
65
66static Byte_t RData[RDATASIZE] =
67{
68   0x00, 0x09, 0xf6, 0x82,
69   0x02, 0x09, 0x86, 0xfb,
70   0x04, 0x09, 0x00, 0x0a,
71   0x06, 0x09, 0x01, 0x0a,
72   0x08, 0x09, 0x8a, 0x13,
73   0x0a, 0x09, 0xc5, 0x11,
74   0x0c, 0x09, 0x86, 0x85,
75   0x0e, 0x09, 0x20, 0x0a,
76   0x10, 0x09, 0x21, 0x0a,
77   0x12, 0x09, 0x41, 0xff,
78   0x14, 0x09, 0x82, 0x00,
79   0x16, 0x09, 0x82, 0x7b,
80   0x18, 0x09, 0x8a, 0x7d,
81   0x1a, 0x09, 0x88, 0x81,
82   0x1c, 0x09, 0x86, 0x7a,
83   0x1e, 0x09, 0x84, 0x81,
84   0x20, 0x09, 0x82, 0x7c,
85   0x22, 0x09, 0x0a, 0x0a
86};
87
88static Byte_t RRegData[RREGDATASIZE]=
89{
90   0x00, 0x09, 0xf6, 0x82,	       /* 00: Stop Rx processor */
91   0x08, 0x09, 0x8a, 0x13,	       /* 04: Tx software flow control */
92   0x0a, 0x09, 0xc5, 0x11,	       /* 08: XON char */
93   0x0c, 0x09, 0x86, 0x85,	       /* 0c: XANY */
94   0x12, 0x09, 0x41, 0xff,	       /* 10: Rx mask char */
95   0x14, 0x09, 0x82, 0x00,	       /* 14: Compare/Ignore #0 */
96   0x16, 0x09, 0x82, 0x7b,	       /* 18: Compare #1 */
97   0x18, 0x09, 0x8a, 0x7d,	       /* 1c: Compare #2 */
98   0x1a, 0x09, 0x88, 0x81,	       /* 20: Interrupt #1 */
99   0x1c, 0x09, 0x86, 0x7a,	       /* 24: Ignore/Replace #1 */
100   0x1e, 0x09, 0x84, 0x81,	       /* 28: Interrupt #2 */
101   0x20, 0x09, 0x82, 0x7c,	       /* 2c: Ignore/Replace #2 */
102   0x22, 0x09, 0x0a, 0x0a	       /* 30: Rx FIFO Enable */
103};
104
105static CONTROLLER_T sController[CTL_SIZE] =
106{
107   {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
108   {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
109   {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
110   {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
111};
112
113#if 0
114/* IRQ number to MUDBAC register 2 mapping */
115Byte_t sIRQMap[16] =
116{
117   0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
118};
119#endif
120
121static Byte_t sBitMapClrTbl[8] =
122{
123   0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
124};
125
126static Byte_t sBitMapSetTbl[8] =
127{
128   0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
129};
130
131/***************************************************************************
132Function: sInitController
133Purpose:  Initialization of controller global registers and controller
134	  structure.
135Call:	  sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
136			  IRQNum,Frequency,PeriodicOnly)
137	  CONTROLLER_T *CtlP; Ptr to controller structure
138	  int CtlNum; Controller number
139	  ByteIO_t MudbacIO; Mudbac base I/O address.
140	  ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
141	     This list must be in the order the AIOPs will be found on the
142	     controller.  Once an AIOP in the list is not found, it is
143	     assumed that there are no more AIOPs on the controller.
144	  int AiopIOListSize; Number of addresses in AiopIOList
145	  int IRQNum; Interrupt Request number.  Can be any of the following:
146			 0: Disable global interrupts
147			 3: IRQ 3
148			 4: IRQ 4
149			 5: IRQ 5
150			 9: IRQ 9
151			 10: IRQ 10
152			 11: IRQ 11
153			 12: IRQ 12
154			 15: IRQ 15
155	  Byte_t Frequency: A flag identifying the frequency
156		   of the periodic interrupt, can be any one of the following:
157		      FREQ_DIS - periodic interrupt disabled
158		      FREQ_137HZ - 137 Hertz
159		      FREQ_69HZ - 69 Hertz
160		      FREQ_34HZ - 34 Hertz
161		      FREQ_17HZ - 17 Hertz
162		      FREQ_9HZ - 9 Hertz
163		      FREQ_4HZ - 4 Hertz
164		   If IRQNum is set to 0 the Frequency parameter is
165		   overidden, it is forced to a value of FREQ_DIS.
166	  int PeriodicOnly: TRUE if all interrupts except the periodic
167			       interrupt are to be blocked.
168			    FALSE is both the periodic interrupt and
169			       other channel interrupts are allowed.
170			    If IRQNum is set to 0 the PeriodicOnly parameter is
171			       overidden, it is forced to a value of FALSE.
172Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
173	       initialization failed.
174
175Comments:
176	  If periodic interrupts are to be disabled but AIOP interrupts
177	  are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
178
179	  If interrupts are to be completely disabled set IRQNum to 0.
180
181	  Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
182	  invalid combination.
183
184	  This function performs initialization of global interrupt modes,
185	  but it does not actually enable global interrupts.  To enable
186	  and disable global interrupts use functions sEnGlobalInt() and
187	  sDisGlobalInt().  Enabling of global interrupts is normally not
188	  done until all other initializations are complete.
189
190	  Even if interrupts are globally enabled, they must also be
191	  individually enabled for each channel that is to generate
192	  interrupts.
193
194Warnings: No range checking on any of the parameters is done.
195
196	  No context switches are allowed while executing this function.
197
198	  After this function all AIOPs on the controller are disabled,
199	  they can be enabled with sEnAiop().
200*/
201int sInitController(	CONTROLLER_T *CtlP,
202			int CtlNum,
203			ByteIO_t MudbacIO,
204			ByteIO_t *AiopIOList,
205			int AiopIOListSize,
206			int IRQNum,
207			Byte_t Frequency,
208			int PeriodicOnly)
209{
210	int		i;
211	ByteIO_t	io;
212
213   CtlP->CtlNum = CtlNum;
214   CtlP->BusType = isISA;
215   CtlP->CtlID = CTLID_0001;	    /* controller release 1 */
216
217   CtlP->MBaseIO = MudbacIO;
218   CtlP->MReg1IO = MudbacIO + 1;
219   CtlP->MReg2IO = MudbacIO + 2;
220   CtlP->MReg3IO = MudbacIO + 3;
221#if 1
222   CtlP->MReg2 = 0;		    /* interrupt disable */
223   CtlP->MReg3 = 0;		    /* no periodic interrupts */
224#else
225   if(sIRQMap[IRQNum] == 0)	       /* interrupts globally disabled */
226   {
227      CtlP->MReg2 = 0;		       /* interrupt disable */
228      CtlP->MReg3 = 0;		       /* no periodic interrupts */
229   }
230   else
231   {
232      CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
233      CtlP->MReg3 = Frequency;	       /* set frequency */
234      if(PeriodicOnly)		       /* periodic interrupt only */
235      {
236	 CtlP->MReg3 |= PERIODIC_ONLY;
237      }
238   }
239#endif
240   sOutB(CtlP->MReg2IO,CtlP->MReg2);
241   sOutB(CtlP->MReg3IO,CtlP->MReg3);
242   sControllerEOI(CtlP);	       /* clear EOI if warm init */
243
244   /* Init AIOPs */
245   CtlP->NumAiop = 0;
246   for(i=0; i < AiopIOListSize; i++)
247   {
248      io = AiopIOList[i];
249      CtlP->AiopIO[i] = (WordIO_t)io;
250      CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
251      sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
252      sOutB(MudbacIO,(Byte_t)(io >> 6));	/* set up AIOP I/O in MUDBAC */
253      sEnAiop(CtlP,i);			       /* enable the AIOP */
254
255      CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
256      if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
257      {
258	 sDisAiop(CtlP,i);		       /* disable AIOP */
259	 break; 			       /* done looking for AIOPs */
260      }
261
262      CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
263      sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
264      sOutB(io + _INDX_DATA,CLOCK_PRESC);
265      CtlP->NumAiop++;			       /* bump count of AIOPs */
266      sDisAiop(CtlP,i); 		       /* disable AIOP */
267   }
268
269   if(CtlP->NumAiop == 0)
270      return(-1);
271   else
272      return(CtlP->NumAiop);
273}
274
275int sPCIInitController( CONTROLLER_T *CtlP,
276			int CtlNum,
277			ByteIO_t *AiopIOList,
278			int AiopIOListSize,
279			int IRQNum,
280			Byte_t Frequency,
281			int PeriodicOnly)
282{
283	int		i;
284	ByteIO_t	io;
285
286   CtlP->CtlNum = CtlNum;
287   CtlP->BusType = isPCI;
288   CtlP->CtlID = CTLID_0001;	    /* controller release 1 */
289   CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
290
291   sPCIControllerEOI(CtlP);
292
293   /* Init AIOPs */
294   CtlP->NumAiop = 0;
295   for(i=0; i < AiopIOListSize; i++)
296   {
297      io = AiopIOList[i];
298      CtlP->AiopIO[i] = (WordIO_t)io;
299      CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
300
301      CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
302      if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
303      {
304	 break; 			       /* done looking for AIOPs */
305      }
306
307      CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
308      sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
309      sOutB(io + _INDX_DATA,CLOCK_PRESC);
310      CtlP->NumAiop++;			       /* bump count of AIOPs */
311   }
312
313   if(CtlP->NumAiop == 0)
314      return(-1);
315   else
316      return(CtlP->NumAiop);
317}
318
319/***************************************************************************
320Function: sReadAiopID
321Purpose:  Read the AIOP idenfication number directly from an AIOP.
322Call:	  sReadAiopID(io)
323	  ByteIO_t io: AIOP base I/O address
324Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
325		 is replace by an identifying number.
326	  Flag AIOPID_NULL if no valid AIOP is found
327Warnings: No context switches are allowed while executing this function.
328
329*/
330int sReadAiopID(ByteIO_t io)
331{
332   Byte_t AiopID;		/* ID byte from AIOP */
333
334   sOutB(io + _CMD_REG,RESET_ALL);     /* reset AIOP */
335   sOutB(io + _CMD_REG,0x0);
336   AiopID = sInB(io + _CHN_STAT0) & 0x07;
337   if(AiopID == 0x06)
338      return(1);
339   else 			       /* AIOP does not exist */
340      return(-1);
341}
342
343/***************************************************************************
344Function: sReadAiopNumChan
345Purpose:  Read the number of channels available in an AIOP directly from
346	  an AIOP.
347Call:	  sReadAiopNumChan(io)
348	  WordIO_t io: AIOP base I/O address
349Return:   int: The number of channels available
350Comments: The number of channels is determined by write/reads from identical
351	  offsets within the SRAM address spaces for channels 0 and 4.
352	  If the channel 4 space is mirrored to channel 0 it is a 4 channel
353	  AIOP, otherwise it is an 8 channel.
354Warnings: No context switches are allowed while executing this function.
355*/
356int sReadAiopNumChan(WordIO_t io)
357{
358   Word_t x;
359
360   sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
361   sOutW(io + _INDX_ADDR,0);	   /* read from SRAM, chan 0 */
362   x = sInW(io + _INDX_DATA);
363   sOutW(io + _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
364   if(x != sInW(io + _INDX_DATA))  /* if different must be 8 chan */
365      return(8);
366   else
367      return(4);
368}
369
370/***************************************************************************
371Function: sInitChan
372Purpose:  Initialization of a channel and channel structure
373Call:	  sInitChan(CtlP,ChP,AiopNum,ChanNum)
374	  CONTROLLER_T *CtlP; Ptr to controller structure
375	  CHANNEL_T *ChP; Ptr to channel structure
376	  int AiopNum; AIOP number within controller
377	  int ChanNum; Channel number within AIOP
378Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
379	       number exceeds number of channels available in AIOP.
380Comments: This function must be called before a channel can be used.
381Warnings: No range checking on any of the parameters is done.
382
383	  No context switches are allowed while executing this function.
384*/
385int sInitChan(	CONTROLLER_T *CtlP,
386		CHANNEL_T *ChP,
387		int AiopNum,
388		int ChanNum)
389{
390   int i;
391   WordIO_t AiopIO;
392   WordIO_t ChIOOff;
393   Byte_t *ChR;
394   Word_t ChOff;
395   static Byte_t R[4];
396
397   if(ChanNum >= CtlP->AiopNumChan[AiopNum])
398      return(FALSE);		       /* exceeds num chans in AIOP */
399
400   /* Channel, AIOP, and controller identifiers */
401   ChP->CtlP = CtlP;
402   ChP->ChanID = CtlP->AiopID[AiopNum];
403   ChP->AiopNum = AiopNum;
404   ChP->ChanNum = ChanNum;
405
406   /* Global direct addresses */
407   AiopIO = CtlP->AiopIO[AiopNum];
408   ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
409   ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
410   ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
411   ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
412   ChP->IndexData = AiopIO + _INDX_DATA;
413
414   /* Channel direct addresses */
415   ChIOOff = AiopIO + ChP->ChanNum * 2;
416   ChP->TxRxData = ChIOOff + _TD0;
417   ChP->ChanStat = ChIOOff + _CHN_STAT0;
418   ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
419   ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
420
421   /* Initialize the channel from the RData array */
422   for(i=0; i < RDATASIZE; i+=4)
423   {
424      R[0] = RData[i];
425      R[1] = RData[i+1] + 0x10 * ChanNum;
426      R[2] = RData[i+2];
427      R[3] = RData[i+3];
428      sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
429   }
430
431   ChR = ChP->R;
432   for(i=0; i < RREGDATASIZE; i+=4)
433   {
434      ChR[i] = RRegData[i];
435      ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
436      ChR[i+2] = RRegData[i+2];
437      ChR[i+3] = RRegData[i+3];
438   }
439
440   /* Indexed registers */
441   ChOff = (Word_t)ChanNum * 0x1000;
442
443   ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
444   ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
445   ChP->BaudDiv[2] = (Byte_t)BRD9600;
446   ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
447   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
448
449   ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
450   ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
451   ChP->TxControl[2] = 0;
452   ChP->TxControl[3] = 0;
453   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
454
455   ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
456   ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
457   ChP->RxControl[2] = 0;
458   ChP->RxControl[3] = 0;
459   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
460
461   ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
462   ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
463   ChP->TxEnables[2] = 0;
464   ChP->TxEnables[3] = 0;
465   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
466
467   ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
468   ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
469   ChP->TxCompare[2] = 0;
470   ChP->TxCompare[3] = 0;
471   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
472
473   ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
474   ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
475   ChP->TxReplace1[2] = 0;
476   ChP->TxReplace1[3] = 0;
477   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
478
479   ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
480   ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
481   ChP->TxReplace2[2] = 0;
482   ChP->TxReplace2[3] = 0;
483   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
484
485   ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
486   ChP->TxFIFO = ChOff + _TX_FIFO;
487
488   sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
489   sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
490   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
491   sOutW(ChP->IndexData,0);
492   ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
493   ChP->RxFIFO = ChOff + _RX_FIFO;
494
495   sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
496   sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
497   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
498   sOutW(ChP->IndexData,0);
499   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
500   sOutW(ChP->IndexData,0);
501   ChP->TxPrioCnt = ChOff + _TXP_CNT;
502   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
503   sOutB(ChP->IndexData,0);
504   ChP->TxPrioPtr = ChOff + _TXP_PNTR;
505   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
506   sOutB(ChP->IndexData,0);
507   ChP->TxPrioBuf = ChOff + _TXP_BUF;
508   sEnRxProcessor(ChP); 	       /* start the Rx processor */
509
510   return(TRUE);
511}
512
513/***************************************************************************
514Function: sStopRxProcessor
515Purpose:  Stop the receive processor from processing a channel.
516Call:	  sStopRxProcessor(ChP)
517	  CHANNEL_T *ChP; Ptr to channel structure
518
519Comments: The receive processor can be started again with sStartRxProcessor().
520	  This function causes the receive processor to skip over the
521	  stopped channel.  It does not stop it from processing other channels.
522
523Warnings: No context switches are allowed while executing this function.
524
525	  Do not leave the receive processor stopped for more than one
526	  character time.
527
528	  After calling this function a delay of 4 uS is required to ensure
529	  that the receive processor is no longer processing this channel.
530*/
531void sStopRxProcessor(CHANNEL_T *ChP)
532{
533   Byte_t R[4];
534
535   R[0] = ChP->R[0];
536   R[1] = ChP->R[1];
537   R[2] = 0x0a;
538   R[3] = ChP->R[3];
539   sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
540}
541
542/***************************************************************************
543Function: sFlushRxFIFO
544Purpose:  Flush the Rx FIFO
545Call:	  sFlushRxFIFO(ChP)
546	  CHANNEL_T *ChP; Ptr to channel structure
547Return:   void
548Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
549	  while it is being flushed the receive processor is stopped
550	  and the transmitter is disabled.  After these operations a
551	  4 uS delay is done before clearing the pointers to allow
552	  the receive processor to stop.  These items are handled inside
553	  this function.
554Warnings: No context switches are allowed while executing this function.
555*/
556void sFlushRxFIFO(CHANNEL_T *ChP)
557{
558   int i;
559   Byte_t Ch;			/* channel number within AIOP */
560   int RxFIFOEnabled;		       /* TRUE if Rx FIFO enabled */
561
562   if(sGetRxCnt(ChP) == 0)	       /* Rx FIFO empty */
563      return;			       /* don't need to flush */
564
565   RxFIFOEnabled = FALSE;
566   if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
567   {
568      RxFIFOEnabled = TRUE;
569      sDisRxFIFO(ChP);		       /* disable it */
570      for(i=0; i < 2000/200; i++)	/* delay 2 uS to allow proc to disable FIFO*/
571	 sInB(ChP->IntChan);		/* depends on bus i/o timing */
572   }
573   sGetChanStatus(ChP); 	 /* clear any pending Rx errors in chan stat */
574   Ch = (Byte_t)sGetChanNum(ChP);
575   sOutB(ChP->Cmd,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
576   sOutB(ChP->Cmd,Ch);		       /* remove reset Rx FIFO count */
577   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
578   sOutW(ChP->IndexData,0);
579   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
580   sOutW(ChP->IndexData,0);
581   if(RxFIFOEnabled)
582      sEnRxFIFO(ChP);		       /* enable Rx FIFO */
583}
584
585/***************************************************************************
586Function: sFlushTxFIFO
587Purpose:  Flush the Tx FIFO
588Call:	  sFlushTxFIFO(ChP)
589	  CHANNEL_T *ChP; Ptr to channel structure
590Return:   void
591Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
592	  while it is being flushed the receive processor is stopped
593	  and the transmitter is disabled.  After these operations a
594	  4 uS delay is done before clearing the pointers to allow
595	  the receive processor to stop.  These items are handled inside
596	  this function.
597Warnings: No context switches are allowed while executing this function.
598*/
599void sFlushTxFIFO(CHANNEL_T *ChP)
600{
601   int i;
602   Byte_t Ch;			/* channel number within AIOP */
603   int TxEnabled;		       /* TRUE if transmitter enabled */
604
605   if(sGetTxCnt(ChP) == 0)	       /* Tx FIFO empty */
606      return;			       /* don't need to flush */
607
608   TxEnabled = FALSE;
609   if(ChP->TxControl[3] & TX_ENABLE)
610   {
611      TxEnabled = TRUE;
612      sDisTransmit(ChP);	       /* disable transmitter */
613   }
614   sStopRxProcessor(ChP);	       /* stop Rx processor */
615   for(i = 0; i < 4000/200; i++)	 /* delay 4 uS to allow proc to stop */
616      sInB(ChP->IntChan);	/* depends on bus i/o timing */
617   Ch = (Byte_t)sGetChanNum(ChP);
618   sOutB(ChP->Cmd,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
619   sOutB(ChP->Cmd,Ch);		       /* remove reset Tx FIFO count */
620   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
621   sOutW(ChP->IndexData,0);
622   if(TxEnabled)
623      sEnTransmit(ChP); 	       /* enable transmitter */
624   sStartRxProcessor(ChP);	       /* restart Rx processor */
625}
626
627/***************************************************************************
628Function: sWriteTxPrioByte
629Purpose:  Write a byte of priority transmit data to a channel
630Call:	  sWriteTxPrioByte(ChP,Data)
631	  CHANNEL_T *ChP; Ptr to channel structure
632	  Byte_t Data; The transmit data byte
633
634Return:   int: 1 if the bytes is successfully written, otherwise 0.
635
636Comments: The priority byte is transmitted before any data in the Tx FIFO.
637
638Warnings: No context switches are allowed while executing this function.
639*/
640int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
641{
642   Byte_t DWBuf[4];		/* buffer for double word writes */
643   Word_t *WordPtr;	     /* must be far because Win SS != DS */
644   register DWordIO_t IndexAddr;
645
646   if(sGetTxCnt(ChP) > 1)	       /* write it to Tx priority buffer */
647   {
648      IndexAddr = ChP->IndexAddr;
649      sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
650      if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
651	 return(0);		       /* nothing sent */
652
653      WordPtr = (Word_t *)(&DWBuf[0]);
654      *WordPtr = ChP->TxPrioBuf;       /* data byte address */
655
656      DWBuf[2] = Data;		       /* data byte value */
657      sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
658
659      *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
660
661      DWBuf[2] = PRI_PEND + 1;	       /* indicate 1 byte pending */
662      DWBuf[3] = 0;		       /* priority buffer pointer */
663      sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
664   }
665   else 			       /* write it to Tx FIFO */
666   {
667      sWriteTxByte(sGetTxRxDataIO(ChP),Data);
668   }
669   return(1);			       /* 1 byte sent */
670}
671
672/***************************************************************************
673Function: sEnInterrupts
674Purpose:  Enable one or more interrupts for a channel
675Call:	  sEnInterrupts(ChP,Flags)
676	  CHANNEL_T *ChP; Ptr to channel structure
677	  Word_t Flags: Interrupt enable flags, can be any combination
678	     of the following flags:
679		TXINT_EN:   Interrupt on Tx FIFO empty
680		RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
681			    sSetRxTrigger())
682		SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
683		MCINT_EN:   Interrupt on modem input change
684		CHANINT_EN: Allow channel interrupt signal to the AIOP's
685			    Interrupt Channel Register.
686Return:   void
687Comments: If an interrupt enable flag is set in Flags, that interrupt will be
688	  enabled.  If an interrupt enable flag is not set in Flags, that
689	  interrupt will not be changed.  Interrupts can be disabled with
690	  function sDisInterrupts().
691
692	  This function sets the appropriate bit for the channel in the AIOP's
693	  Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
694	  this channel's bit to be set in the AIOP's Interrupt Channel Register.
695
696	  Interrupts must also be globally enabled before channel interrupts
697	  will be passed on to the host.  This is done with function
698	  sEnGlobalInt().
699
700	  In some cases it may be desirable to disable interrupts globally but
701	  enable channel interrupts.  This would allow the global interrupt
702	  status register to be used to determine which AIOPs need service.
703*/
704void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
705{
706   Byte_t Mask; 		/* Interrupt Mask Register */
707
708   ChP->RxControl[2] |=
709      ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
710
711   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
712
713   ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
714
715   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
716
717   if(Flags & CHANINT_EN)
718   {
719      Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
720      sOutB(ChP->IntMask,Mask);
721   }
722}
723
724/***************************************************************************
725Function: sDisInterrupts
726Purpose:  Disable one or more interrupts for a channel
727Call:	  sDisInterrupts(ChP,Flags)
728	  CHANNEL_T *ChP; Ptr to channel structure
729	  Word_t Flags: Interrupt flags, can be any combination
730	     of the following flags:
731		TXINT_EN:   Interrupt on Tx FIFO empty
732		RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
733			    sSetRxTrigger())
734		SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
735		MCINT_EN:   Interrupt on modem input change
736		CHANINT_EN: Disable channel interrupt signal to the
737			    AIOP's Interrupt Channel Register.
738Return:   void
739Comments: If an interrupt flag is set in Flags, that interrupt will be
740	  disabled.  If an interrupt flag is not set in Flags, that
741	  interrupt will not be changed.  Interrupts can be enabled with
742	  function sEnInterrupts().
743
744	  This function clears the appropriate bit for the channel in the AIOP's
745	  Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
746	  this channel's bit from being set in the AIOP's Interrupt Channel
747	  Register.
748*/
749void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
750{
751   Byte_t Mask; 		/* Interrupt Mask Register */
752
753   ChP->RxControl[2] &=
754	 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
755   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
756   ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
757   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
758
759   if(Flags & CHANINT_EN)
760   {
761      Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
762      sOutB(ChP->IntMask,Mask);
763   }
764}
765
766/*********************************************************************
767  Begin FreeBsd-specific driver code
768**********************************************************************/
769
770static int rpprobe __P((struct isa_device *));
771static int rpattach __P((struct isa_device *));
772
773static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
774static void rp_pciattach(pcici_t tag, int unit);
775static u_long	rp_pcicount;
776
777static struct pci_device rp_pcidevice = {
778	"rp",
779	rp_pciprobe,
780	rp_pciattach,
781	&rp_pcicount,
782	NULL
783};
784
785COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
786
787static timeout_t rpdtrwakeup;
788
789struct isa_driver rpdriver = {
790	rpprobe, rpattach, "rp"
791     };
792
793static	char	driver_name[] = "rp";
794
795static	d_open_t	rpopen;
796static	d_close_t	rpclose;
797static	d_read_t	rpread;
798static	d_write_t	rpwrite;
799static	d_ioctl_t	rpioctl;
800static	d_stop_t	rpstop;
801static	d_devtotty_t	rpdevtotty;
802
803#define	CDEV_MAJOR	81
804static struct cdevsw rp_cdevsw = {
805	/* open */	rpopen,
806	/* close */	rpclose,
807	/* read */	rpread,
808	/* write */	rpwrite,
809	/* ioctl */	rpioctl,
810	/* stop */	rpstop,
811	/* reset */	noreset,
812	/* devtotty */	rpdevtotty,
813	/* poll */	ttpoll,
814	/* mmap */	nommap,
815	/* strategy */	nostrategy,
816	/* name */	driver_name,
817	/* parms */	noparms,
818	/* maj */	CDEV_MAJOR,
819	/* dump */	nodump,
820	/* psize */	nopsize,
821	/* flags */	D_TTY,
822	/* maxio */	0,
823	/* bmaj */	-1
824};
825
826static int rp_controller_port = 0;
827static int rp_num_ports_open = 0;
828static int	ndevs = 0;
829static int	minor_to_unit[128];
830#if 0
831static	struct	tty	rp_tty[128];
832#endif
833
834static int rp_num_ports[4];	/* Number of ports on each controller */
835
836#define _INLINE_ __inline
837#define POLL_INTERVAL 1
838
839#define CALLOUT_MASK		0x80
840#define CONTROL_MASK		0x60
841#define CONTROL_INIT_STATE	0x20
842#define CONTROL_LOCK_STATE	0x40
843#define DEV_UNIT(dev)	(MINOR_TO_UNIT(minor(dev))
844#define MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
845#define MINOR_MAGIC(dev)	((minor(dev)) & ~MINOR_MAGIC_MASK)
846#define IS_CALLOUT(dev) 	(minor(dev) & CALLOUT_MASK)
847#define IS_CONTROL(dev) 	(minor(dev) & CONTROL_MASK)
848
849#define RP_ISMULTIPORT(dev)	((dev)->id_flags & 0x1)
850#define RP_MPMASTER(dev)	(((dev)->id_flags >> 8) & 0xff)
851#define RP_NOTAST4(dev) 	((dev)->id_flags & 0x04)
852
853static	struct	rp_port *p_rp_addr[4];
854static	struct	rp_port *p_rp_table[MAX_RP_PORTS];
855#define rp_addr(unit)	(p_rp_addr[unit])
856#define rp_table(port)	(p_rp_table[port])
857
858/*
859 * The top-level routines begin here
860 */
861
862int	rpselect __P((dev_t, int, struct proc *));
863
864static	int	rpparam __P((struct tty *, struct termios *));
865static	void	rpstart __P((struct tty *));
866static	void	rphardclose	__P((struct rp_port *));
867#define rpmap	nomap
868#define rpreset noreset
869#define rpstrategy	nostrategy
870static	void	rp_disc_optim	__P((struct tty *tp, struct termios *t,
871						struct rp_port	*rp));
872
873static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
874			CHANNEL_t *cp, unsigned int ChanStatus)
875{
876	int	spl;
877	unsigned	int	CharNStat;
878	int	ToRecv, ch;
879
880	ToRecv = sGetRxCnt(cp);
881	if(ToRecv == 0)
882		return;
883
884/*	If status indicates there are errored characters in the
885	FIFO, then enter status mode (a word in FIFO holds
886	characters and status)
887*/
888
889	if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
890		if(!(ChanStatus & STATMODE)) {
891			ChanStatus |= STATMODE;
892			sEnRxStatusMode(cp);
893		}
894	}
895/*
896	if we previously entered status mode then read down the
897	FIFO one word at a time, pulling apart the character and
898	the status. Update error counters depending on status.
899*/
900	if(ChanStatus & STATMODE) {
901		while(ToRecv) {
902			if(tp->t_state & TS_TBLOCK) {
903				break;
904			}
905			CharNStat = sInW(sGetTxRxDataIO(cp));
906			ch = CharNStat & 0xff;
907
908			if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
909				ch |= TTY_FE;
910			else if (CharNStat & STMPARITYH)
911				ch |= TTY_PE;
912			else if (CharNStat & STMRCVROVRH)
913				rp->rp_overflows++;
914
915			(*linesw[tp->t_line].l_rint)(ch, tp);
916			ToRecv--;
917		}
918/*
919	After emtying FIFO in status mode, turn off status mode
920*/
921
922	if(sGetRxCnt(cp) == 0)
923		sDisRxStatusMode(cp);
924	}
925	else {
926		while (ToRecv) {
927			if(tp->t_state & TS_TBLOCK) {
928				break;
929			}
930			ch = (u_char) sInB(sGetTxRxDataIO(cp));
931			spl = spltty();
932			(*linesw[tp->t_line].l_rint)(ch, tp);
933			splx(spl);
934			ToRecv--;
935		}
936	}
937}
938
939static _INLINE_ void rp_handle_port(struct rp_port *rp)
940{
941	CHANNEL_t	*cp;
942	struct	tty	*tp;
943	unsigned	int	IntMask, ChanStatus;
944     /*	int	oldcts; */
945
946	if(!rp)
947		return;
948
949	cp = &rp->rp_channel;
950	tp = rp->rp_tty;
951	IntMask = sGetChanIntID(cp);
952	IntMask = IntMask & rp->rp_intmask;
953	ChanStatus = sGetChanStatus(cp);
954	if(IntMask & RXF_TRIG)
955		if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
956			rp_do_receive(rp, tp, cp, ChanStatus);
957		}
958	if(IntMask & DELTA_CD) {
959		if(ChanStatus & CD_ACT) {
960			if(!(tp->t_state & TS_CARR_ON) ) {
961				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
962			}
963		} else {
964			if((tp->t_state & TS_CARR_ON)) {
965				(void)(*linesw[tp->t_line].l_modem)(tp, 0);
966				if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
967					rphardclose(rp);
968				}
969			}
970		}
971	}
972/*	oldcts = rp->rp_cts;
973	rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
974	if(oldcts != rp->rp_cts) {
975		printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
976	}
977*/
978}
979
980static void rp_do_poll(void *not_used)
981{
982	CONTROLLER_t	*ctl;
983	struct rp_port	*rp;
984	struct tty	*tp;
985	int	unit, aiop, ch, line, count;
986	unsigned char	CtlMask, AiopMask;
987
988	for(unit = 0; unit <= ndevs; unit++) {
989	rp = rp_addr(unit);
990	ctl = rp->rp_ctlp;
991	if(ctl->BusType == isPCI)
992		CtlMask = sPCIGetControllerIntStatus(ctl);
993	else
994		CtlMask = sGetControllerIntStatus(ctl);
995	for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
996		if(CtlMask & 1) {
997			AiopMask = sGetAiopIntStatus(ctl, aiop);
998			for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
999				if(AiopMask & 1) {
1000					line = (unit << 5) | (aiop << 3) | ch;
1001					rp = rp_table(line);
1002					rp_handle_port(rp);
1003				}
1004			}
1005		}
1006	}
1007
1008	for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
1009			line++, rp++) {
1010		tp = rp->rp_tty;
1011		if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1012			count = sGetTxCnt(&rp->rp_channel);
1013			if(count == 0)
1014				tp->t_state &= ~(TS_BUSY);
1015			if(!(tp->t_state & TS_TTSTOP) &&
1016				(count <= rp->rp_restart)) {
1017				(*linesw[tp->t_line].l_start)(tp);
1018			}
1019		}
1020	}
1021	}
1022	if(rp_num_ports_open)
1023		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1024}
1025
1026static const char*
1027rp_pciprobe(pcici_t tag, pcidi_t type)
1028{
1029	int	vendor_id;
1030
1031	vendor_id = type & 0xffff;
1032	switch(vendor_id)
1033	case 0x11fe:
1034		return("rp");
1035	return(NULL);
1036}
1037
1038static
1039int
1040rpprobe(dev)
1041struct isa_device *dev;
1042{
1043	int controller, unit;
1044	int aiop, num_aiops;
1045	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1046	CONTROLLER_t *ctlp;
1047
1048	unit = dev->id_unit;
1049	if (dev->id_unit >= 4) {
1050		printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1051		return 1;
1052	}
1053	printf("probing for RocketPort(ISA) unit %d\n", unit);
1054	if (rp_controller_port)
1055		controller = rp_controller_port;
1056	else {
1057		controller = dev->id_iobase + 0x40;
1058	}
1059
1060	for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1061		aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1062
1063	ctlp = sCtlNumToCtlPtr(dev->id_unit);
1064	num_aiops = sInitController(ctlp, dev->id_unit,
1065				controller + ((unit-rp_pcicount)*0x400),
1066				aiopio, MAX_AIOPS_PER_BOARD, 0,
1067				FREQ_DIS, 0);
1068	if (num_aiops <= 0) {
1069		printf("board%d init failed\n", unit);
1070		return 0;
1071	}
1072
1073	if (rp_controller_port) {
1074		dev->id_msize = 64;
1075	} else {
1076		dev->id_msize = 68;
1077		rp_controller_port = controller;
1078	}
1079
1080	dev->id_irq = 0;
1081
1082	return 1;
1083}
1084
1085static void
1086rp_pciattach(pcici_t tag, int unit)
1087{
1088	int	success, oldspl;
1089	u_short iobase;
1090	int	num_ports, num_chan, num_aiops;
1091	int	aiop, chan, port;
1092	int	ChanStatus, line, i, count;
1093	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1094	struct	rp_port *rp;
1095	struct	tty	*tty;
1096	CONTROLLER_t	*ctlp;
1097
1098	success = pci_map_port(tag, 0x10, &iobase);
1099	if(!success)
1100		printf("ioaddr mapping failed for RocketPort(PCI)\n");
1101
1102	for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1103		aiopio[aiop] = iobase + (aiop * 0x40);
1104
1105	ctlp = sCtlNumToCtlPtr(unit);
1106	num_aiops = sPCIInitController(ctlp, unit,
1107				aiopio, MAX_AIOPS_PER_BOARD, 0,
1108				FREQ_DIS, 0);
1109
1110	num_ports = 0;
1111	for(aiop=0; aiop < num_aiops; aiop++) {
1112		sResetAiopByNum(ctlp, aiop);
1113		num_ports += sGetAiopNumChan(ctlp, aiop);
1114	}
1115	printf("RocketPort%d = %d ports\n", unit, num_ports);
1116	rp_num_ports[unit] = num_ports;
1117
1118	rp = (struct rp_port *)
1119		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1120	if(rp == 0) {
1121		printf("rp_attach: Could not malloc rp_ports structures\n");
1122		return;
1123	}
1124
1125	count = unit * 32;      /* board times max ports per card SG */
1126	for(i=count;i < (count + rp_num_ports[unit]);i++)
1127		minor_to_unit[i] = unit;
1128
1129	bzero(rp, sizeof(struct rp_port) * num_ports);
1130	tty = (struct tty *)
1131		malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1132	if(tty == 0) {
1133		printf("rp_attach: Could not malloc tty structures\n");
1134		return;
1135	}
1136	bzero(tty, sizeof(struct tty) * num_ports);
1137
1138	oldspl = spltty();
1139	rp_addr(unit) = rp;
1140	splx(oldspl);
1141
1142	cdevsw_add(&rp_cdevsw);
1143
1144	port = 0;
1145	for(aiop=0; aiop < num_aiops; aiop++) {
1146		num_chan = sGetAiopNumChan(ctlp, aiop);
1147		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1148			rp->rp_tty = tty;
1149			rp->rp_port = port;
1150			rp->rp_ctlp = ctlp;
1151			rp->rp_unit = unit;
1152			rp->rp_chan = chan;
1153			rp->rp_aiop = aiop;
1154
1155			tty->t_line = 0;
1156	/*		tty->t_termios = deftermios;
1157	*/
1158			rp->dtr_wait = 3 * hz;
1159			rp->it_in.c_iflag = 0;
1160			rp->it_in.c_oflag = 0;
1161			rp->it_in.c_cflag = TTYDEF_CFLAG;
1162			rp->it_in.c_lflag = 0;
1163			termioschars(&rp->it_in);
1164	/*		termioschars(&tty->t_termios);
1165	*/
1166			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1167			rp->it_out = rp->it_in;
1168
1169			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1170				DELTA_CD | DELTA_CTS | DELTA_DSR;
1171			ChanStatus = sGetChanStatus(&rp->rp_channel);
1172			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1173				printf("RocketPort sInitChan(%d, %d, %d) failed
1174					\n", unit, aiop, chan);
1175				return;
1176			}
1177			ChanStatus = sGetChanStatus(&rp->rp_channel);
1178			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1179			line = (unit << 5) | (aiop << 3) | chan;
1180			rp_table(line) = rp;
1181		}
1182	}
1183}
1184
1185static
1186int
1187rpattach(dev)
1188struct	isa_device	*dev;
1189{
1190	int	iobase, unit, /*rpmajor,*/ oldspl;
1191	int	num_ports, num_chan, num_aiops;
1192	int	aiop, chan, port;
1193	int	ChanStatus, line, i, count;
1194	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1195	struct	rp_port *rp;
1196	struct	tty	*tty;
1197	CONTROLLER_t	*ctlp;
1198
1199	iobase = dev->id_iobase;
1200	unit = dev->id_unit;
1201	ndevs = unit;
1202
1203	for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1204		aiopio[aiop] = iobase + (aiop * 0x400);
1205
1206	ctlp = sCtlNumToCtlPtr(unit);
1207	num_aiops = sInitController(ctlp, unit,
1208				rp_controller_port + ((unit-rp_pcicount) * 0x400),
1209				aiopio, MAX_AIOPS_PER_BOARD, 0,
1210				FREQ_DIS, 0);
1211
1212	num_ports = 0;
1213	for(aiop=0; aiop < num_aiops; aiop++) {
1214		sResetAiopByNum(ctlp, aiop);
1215		sEnAiop(ctlp, aiop);
1216		num_ports += sGetAiopNumChan(ctlp, aiop);
1217	}
1218	printf("RocketPort%d = %d ports\n", unit, num_ports);
1219	rp_num_ports[unit] = num_ports;
1220
1221	rp = (struct rp_port *)
1222		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1223	if(rp == 0) {
1224		printf("rp_attach: Could not malloc rp_ports structures\n");
1225		return(0);
1226	}
1227
1228	count = unit * 32;    /* board # times max ports per card  SG */
1229	for(i=count;i < (count + rp_num_ports[unit]);i++)
1230		minor_to_unit[i] = unit;
1231
1232	bzero(rp, sizeof(struct rp_port) * num_ports);
1233	tty = (struct tty *)
1234		malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1235	if(tty == 0) {
1236		printf("rp_attach: Could not malloc tty structures\n");
1237		return(0);
1238	}
1239	bzero(tty, sizeof(struct tty) * num_ports);
1240
1241	oldspl = spltty();
1242	rp_addr(unit) = rp;
1243	splx(oldspl);
1244
1245	cdevsw_add(&rp_cdevsw);
1246
1247	port = 0;
1248	for(aiop=0; aiop < num_aiops; aiop++) {
1249		num_chan = sGetAiopNumChan(ctlp, aiop);
1250		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1251			rp->rp_tty = tty;
1252			rp->rp_port = port;
1253			rp->rp_ctlp = ctlp;
1254			rp->rp_unit = unit;
1255			rp->rp_chan = chan;
1256			rp->rp_aiop = aiop;
1257
1258			tty->t_line = 0;
1259	/*		tty->t_termios = deftermios;
1260	*/
1261			rp->dtr_wait = 3 * hz;
1262			rp->it_in.c_iflag = 0;
1263			rp->it_in.c_oflag = 0;
1264			rp->it_in.c_cflag = TTYDEF_CFLAG;
1265			rp->it_in.c_lflag = 0;
1266			termioschars(&rp->it_in);
1267	/*		termioschars(&tty->t_termios);
1268	*/
1269			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1270			rp->it_out = rp->it_in;
1271
1272			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1273				DELTA_CD | DELTA_CTS | DELTA_DSR;
1274			ChanStatus = sGetChanStatus(&rp->rp_channel);
1275			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1276				printf("RocketPort sInitChan(%d, %d, %d) failed
1277					\n", unit, aiop, chan);
1278				return(0);
1279			}
1280			ChanStatus = sGetChanStatus(&rp->rp_channel);
1281			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1282			line = (unit << 5) | (aiop << 3) | chan;
1283			rp_table(line) = rp;
1284		}
1285	}
1286
1287	return(1);
1288}
1289
1290int
1291rpopen(dev, flag, mode, p)
1292	dev_t	dev;
1293	int	flag, mode;
1294	struct	proc	*p;
1295{
1296	struct	rp_port *rp;
1297	int	unit, port, mynor, umynor, flags;  /* SG */
1298	struct	tty	*tp;
1299	int	oldspl, error;
1300	unsigned int	IntMask, ChanStatus;
1301
1302
1303   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1304	port  = (minor(dev) & 0x1f);                /* SG */
1305	mynor = (port + umynor);                    /* SG */
1306	unit = minor_to_unit[mynor];
1307	if(IS_CONTROL(dev))
1308		return(0);
1309	rp = rp_addr(unit) + port;
1310/*	rp->rp_tty = &rp_tty[rp->rp_port];
1311*/
1312	tp = rp->rp_tty;
1313
1314	oldspl = spltty();
1315
1316open_top:
1317	while(rp->state & ~SET_DTR) {
1318		error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1319		if(error != 0)
1320			goto out;
1321	}
1322
1323	if(tp->t_state & TS_ISOPEN) {
1324		if(IS_CALLOUT(dev)) {
1325			if(!rp->active_out) {
1326				error = EBUSY;
1327				goto out;
1328			}
1329		} else {
1330			if(rp->active_out) {
1331				if(flag & O_NONBLOCK) {
1332					error = EBUSY;
1333					goto out;
1334				}
1335				error = tsleep(&rp->active_out,
1336					TTIPRI | PCATCH, "rpbi", 0);
1337				if(error != 0)
1338					goto out;
1339				goto open_top;
1340			}
1341		}
1342		if(tp->t_state & TS_XCLUDE &&
1343		    suser(p)) {
1344			splx(oldspl);
1345			return(EBUSY);
1346		}
1347	}
1348	else {
1349		tp->t_dev = dev;
1350		tp->t_param = rpparam;
1351		tp->t_oproc = rpstart;
1352		tp->t_line = 0;
1353		tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1354		flags = 0;
1355		flags |= SET_RTS;
1356		flags |= SET_DTR;
1357		rp->rp_channel.TxControl[3] =
1358			((rp->rp_channel.TxControl[3]
1359			& ~(SET_RTS | SET_DTR)) | flags);
1360		sOutDW(rp->rp_channel.IndexAddr,
1361			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1362		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1363		sDisRxStatusMode(&rp->rp_channel);
1364		sFlushRxFIFO(&rp->rp_channel);
1365		sFlushTxFIFO(&rp->rp_channel);
1366
1367		sEnInterrupts(&rp->rp_channel,
1368			(TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1369		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1370
1371		sDisRxStatusMode(&rp->rp_channel);
1372		sClrTxXOFF(&rp->rp_channel);
1373
1374/*		sDisRTSFlowCtl(&rp->rp_channel);
1375		sDisCTSFlowCtl(&rp->rp_channel);
1376*/
1377		sDisTxSoftFlowCtl(&rp->rp_channel);
1378
1379		sStartRxProcessor(&rp->rp_channel);
1380
1381		sEnRxFIFO(&rp->rp_channel);
1382		sEnTransmit(&rp->rp_channel);
1383
1384/*		sSetDTR(&rp->rp_channel);
1385		sSetRTS(&rp->rp_channel);
1386*/
1387
1388		++rp->wopeners;
1389		error = rpparam(tp, &tp->t_termios);
1390		--rp->wopeners;
1391		if(error != 0) {
1392			splx(oldspl);
1393			return(error);
1394		}
1395
1396		rp_num_ports_open++;
1397
1398		IntMask = sGetChanIntID(&rp->rp_channel);
1399		IntMask = IntMask & rp->rp_intmask;
1400		ChanStatus = sGetChanStatus(&rp->rp_channel);
1401		if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1402			if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1403					(void)(*linesw[tp->t_line].l_modem)(tp, 1);
1404			}
1405		}
1406
1407	if(rp_num_ports_open == 1)
1408		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1409
1410	}
1411
1412	if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1413		!(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1414		++rp->wopeners;
1415		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1416				"rpdcd", 0);
1417		--rp->wopeners;
1418		if(error != 0)
1419			goto out;
1420		goto open_top;
1421	}
1422	error = (*linesw[tp->t_line].l_open)(dev, tp);
1423
1424	rp_disc_optim(tp, &tp->t_termios, rp);
1425	if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1426		rp->active_out = TRUE;
1427
1428/*	if(rp_num_ports_open == 1)
1429		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1430*/
1431out:
1432	splx(oldspl);
1433	if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1434		rphardclose(rp);
1435	}
1436	return(error);
1437}
1438
1439int
1440rpclose(dev, flag, mode, p)
1441	dev_t	dev;
1442	int	flag, mode;
1443	struct	proc	*p;
1444{
1445	int	oldspl, unit, mynor, umynor, port; /* SG */
1446	struct	rp_port *rp;
1447	struct	tty	*tp;
1448	CHANNEL_t	*cp;
1449
1450   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1451	port  = (minor(dev) & 0x1f);                /* SG */
1452	mynor = (port + umynor);                    /* SG */
1453   unit = minor_to_unit[mynor];                /* SG */
1454
1455	if(IS_CONTROL(dev))
1456		return(0);
1457	rp = rp_addr(unit) + port;
1458	cp = &rp->rp_channel;
1459	tp = rp->rp_tty;
1460
1461	oldspl = spltty();
1462	(*linesw[tp->t_line].l_close)(tp, flag);
1463	rp_disc_optim(tp, &tp->t_termios, rp);
1464	rpstop(tp, FREAD | FWRITE);
1465	rphardclose(rp);
1466
1467	tp->t_state &= ~TS_BUSY;
1468	ttyclose(tp);
1469
1470	splx(oldspl);
1471
1472	return(0);
1473}
1474
1475static void
1476rphardclose(struct rp_port *rp)
1477{
1478	int	mynor;
1479	struct	tty	*tp;
1480	CHANNEL_t	*cp;
1481
1482	cp = &rp->rp_channel;
1483	tp = rp->rp_tty;
1484	mynor = MINOR_MAGIC(tp->t_dev);
1485
1486	sFlushRxFIFO(cp);
1487	sFlushTxFIFO(cp);
1488	sDisTransmit(cp);
1489	sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1490	sDisRTSFlowCtl(cp);
1491	sDisCTSFlowCtl(cp);
1492	sDisTxSoftFlowCtl(cp);
1493	sClrTxXOFF(cp);
1494
1495	if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1496		sClrDTR(cp);
1497	}
1498	if(IS_CALLOUT(tp->t_dev)) {
1499		sClrDTR(cp);
1500	}
1501	if(rp->dtr_wait != 0) {
1502		timeout(rpdtrwakeup, rp, rp->dtr_wait);
1503		rp->state |= ~SET_DTR;
1504	}
1505
1506	rp->active_out = FALSE;
1507	wakeup(&rp->active_out);
1508	wakeup(TSA_CARR_ON(tp));
1509}
1510
1511static
1512int
1513rpread(dev, uio, flag)
1514	dev_t	dev;
1515	struct	uio	*uio;
1516	int	flag;
1517{
1518	struct	rp_port *rp;
1519	struct	tty	*tp;
1520	int	unit, mynor, umynor, port, error = 0; /* SG */
1521
1522   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1523	port  = (minor(dev) & 0x1f);                /* SG */
1524	mynor = (port + umynor);                    /* SG */
1525   unit = minor_to_unit[mynor];                /* SG */
1526
1527	if(IS_CONTROL(dev))
1528		return(ENODEV);
1529	rp = rp_addr(unit) + port;
1530	tp = rp->rp_tty;
1531	error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
1532	return(error);
1533}
1534
1535static
1536int
1537rpwrite(dev, uio, flag)
1538	dev_t	dev;
1539	struct	uio	*uio;
1540	int	flag;
1541{
1542	struct	rp_port *rp;
1543	struct	tty	*tp;
1544	int	unit, mynor, port, umynor, error = 0; /* SG */
1545
1546   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1547	port  = (minor(dev) & 0x1f);                /* SG */
1548	mynor = (port + umynor);                    /* SG */
1549   unit = minor_to_unit[mynor];                /* SG */
1550
1551	if(IS_CONTROL(dev))
1552		return(ENODEV);
1553	rp = rp_addr(unit) + port;
1554	tp = rp->rp_tty;
1555	while(rp->rp_disable_writes) {
1556		rp->rp_waiting = 1;
1557		error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1558		if (error)
1559			return(error);
1560	}
1561
1562	error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1563	return error;
1564}
1565
1566static void
1567rpdtrwakeup(void *chan)
1568{
1569	struct	rp_port *rp;
1570
1571	rp = (struct rp_port *)chan;
1572	rp->state &= SET_DTR;
1573	wakeup(&rp->dtr_wait);
1574}
1575
1576int
1577rpioctl(dev, cmd, data, flag, p)
1578	dev_t	dev;
1579	u_long	cmd;
1580	caddr_t data;
1581	int	flag;
1582	struct	proc	*p;
1583{
1584	struct rp_port	*rp;
1585	CHANNEL_t	*cp;
1586	struct tty	*tp;
1587	int	unit, mynor, port, umynor;            /* SG */
1588	int	oldspl;
1589	int	error = 0;
1590	int	arg, flags, result, ChanStatus;
1591	int	oldcmd;
1592	struct	termios term, *t;
1593
1594   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1595	port  = (minor(dev) & 0x1f);                /* SG */
1596	mynor = (port + umynor);                    /* SG */
1597	unit = minor_to_unit[mynor];
1598	rp = rp_addr(unit) + port;
1599
1600	if(IS_CONTROL(dev)) {
1601		struct	termios *ct;
1602
1603		switch (IS_CONTROL(dev)) {
1604		case CONTROL_INIT_STATE:
1605			ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1606			break;
1607		case CONTROL_LOCK_STATE:
1608			ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1609			break;
1610		default:
1611			return(ENODEV); 	/* /dev/nodev */
1612		}
1613		switch (cmd) {
1614		case TIOCSETA:
1615			error = suser(p);
1616			if(error != 0)
1617				return(error);
1618			*ct = *(struct termios *)data;
1619			return(0);
1620		case TIOCGETA:
1621			*(struct termios *)data = *ct;
1622			return(0);
1623		case TIOCGETD:
1624			*(int *)data = TTYDISC;
1625			return(0);
1626		case TIOCGWINSZ:
1627			bzero(data, sizeof(struct winsize));
1628			return(0);
1629		default:
1630			return(ENOTTY);
1631		}
1632	}
1633
1634	tp = rp->rp_tty;
1635	cp = &rp->rp_channel;
1636
1637#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1638	term = tp->t_termios;
1639	oldcmd = cmd;
1640	error = ttsetcompat(tp, &cmd, data, &term);
1641	if(error != 0)
1642		return(error);
1643	if(cmd != oldcmd) {
1644		data = (caddr_t)&term;
1645	}
1646#endif
1647	if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1648		int	cc;
1649		struct	termios *dt = (struct termios *)data;
1650		struct	termios *lt = IS_CALLOUT(dev)
1651					? &rp->lt_out : &rp->lt_in;
1652
1653		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1654				| (dt->c_iflag & ~lt->c_iflag);
1655		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1656				| (dt->c_oflag & ~lt->c_oflag);
1657		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1658				| (dt->c_cflag & ~lt->c_cflag);
1659		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1660				| (dt->c_lflag & ~lt->c_lflag);
1661		for(cc = 0; cc < NCCS; ++cc)
1662			if((lt->c_cc[cc] = tp->t_cc[cc]) != 0)
1663				dt->c_cc[cc] = tp->t_cc[cc];
1664		if(lt->c_ispeed != 0)
1665			dt->c_ispeed = tp->t_ispeed;
1666		if(lt->c_ospeed != 0)
1667			dt->c_ospeed = tp->t_ospeed;
1668	}
1669
1670	t = &tp->t_termios;
1671
1672	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1673	if(error != ENOIOCTL) {
1674		return(error);
1675	}
1676	oldspl = spltty();
1677
1678	flags = rp->rp_channel.TxControl[3];
1679
1680	error = ttioctl(tp, cmd, data, flag);
1681	flags = rp->rp_channel.TxControl[3];
1682	rp_disc_optim(tp, &tp->t_termios, rp);
1683	if(error != ENOIOCTL) {
1684		splx(oldspl);
1685		return(error);
1686	}
1687	switch(cmd) {
1688	case TIOCSBRK:
1689		sSendBreak(&rp->rp_channel);
1690		break;
1691
1692	case TIOCCBRK:
1693		sClrBreak(&rp->rp_channel);
1694		break;
1695
1696	case TIOCSDTR:
1697		sSetDTR(&rp->rp_channel);
1698		sSetRTS(&rp->rp_channel);
1699		break;
1700
1701	case TIOCCDTR:
1702		sClrDTR(&rp->rp_channel);
1703		break;
1704
1705	case TIOCMSET:
1706		arg = *(int *) data;
1707		flags = 0;
1708		if(arg & TIOCM_RTS)
1709			flags |= SET_RTS;
1710		if(arg & TIOCM_DTR)
1711			flags |= SET_DTR;
1712		rp->rp_channel.TxControl[3] =
1713			((rp->rp_channel.TxControl[3]
1714			& ~(SET_RTS | SET_DTR)) | flags);
1715		sOutDW(rp->rp_channel.IndexAddr,
1716			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1717		break;
1718	case TIOCMBIS:
1719		arg = *(int *) data;
1720		flags = 0;
1721		if(arg & TIOCM_RTS)
1722			flags |= SET_RTS;
1723		if(arg & TIOCM_DTR)
1724			flags |= SET_DTR;
1725			rp->rp_channel.TxControl[3] |= flags;
1726		sOutDW(rp->rp_channel.IndexAddr,
1727			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1728		break;
1729	case TIOCMBIC:
1730		arg = *(int *) data;
1731		flags = 0;
1732		if(arg & TIOCM_RTS)
1733			flags |= SET_RTS;
1734		if(arg & TIOCM_DTR)
1735			flags |= SET_DTR;
1736		rp->rp_channel.TxControl[3] &= ~flags;
1737		sOutDW(rp->rp_channel.IndexAddr,
1738			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1739		break;
1740
1741
1742	case TIOCMGET:
1743		ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1744		flags = rp->rp_channel.TxControl[3];
1745		result = TIOCM_LE; /* always on while open for some reason */
1746		result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1747			| ((flags & SET_RTS) ? TIOCM_RTS : 0)
1748			| ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1749			| ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1750			| ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1751
1752		if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1753		{
1754			result |= TIOCM_RTS;
1755		}
1756
1757		*(int *)data = result;
1758		break;
1759	case TIOCMSDTRWAIT:
1760		error = suser(p);
1761		if(error != 0) {
1762			splx(oldspl);
1763			return(error);
1764		}
1765		rp->dtr_wait = *(int *)data * hz/100;
1766		break;
1767	case TIOCMGDTRWAIT:
1768		*(int *)data = rp->dtr_wait * 100/hz;
1769		break;
1770	default:
1771		splx(oldspl);
1772		return ENOTTY;
1773	}
1774	splx(oldspl);
1775	return(0);
1776}
1777
1778static struct speedtab baud_table[] = {
1779	B0,	0,		B50,	BRD50,		B75,	BRD75,
1780	B110,	BRD110, 	B134,	BRD134, 	B150,	BRD150,
1781	B200,	BRD200, 	B300,	BRD300, 	B600,	BRD600,
1782	B1200,	BRD1200,	B1800,	BRD1800,	B2400,	BRD2400,
1783	B4800,	BRD4800,	B9600,	BRD9600,	B19200, BRD19200,
1784	B38400, BRD38400,	B7200,	BRD7200,	B14400, BRD14400,
1785				B57600, BRD57600,	B76800, BRD76800,
1786	B115200, BRD115200,	B230400, BRD230400,
1787	-1,	-1
1788};
1789
1790static int
1791rpparam(tp, t)
1792	struct tty *tp;
1793	struct termios *t;
1794{
1795	struct rp_port	*rp;
1796	CHANNEL_t	*cp;
1797	int	unit, mynor, port, umynor;               /* SG */
1798	int	oldspl, cflag, iflag, oflag, lflag;
1799	int	ospeed;
1800
1801
1802   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1803	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1804	mynor = (port + umynor);                          /* SG */
1805
1806	unit = minor_to_unit[mynor];
1807	rp = rp_addr(unit) + port;
1808	cp = &rp->rp_channel;
1809	oldspl = spltty();
1810
1811	cflag = t->c_cflag;
1812	iflag = t->c_iflag;
1813	oflag = t->c_oflag;
1814	lflag = t->c_lflag;
1815
1816	ospeed = ttspeedtab(t->c_ispeed, baud_table);
1817	if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1818		return(EINVAL);
1819
1820	tp->t_ispeed = t->c_ispeed;
1821	tp->t_ospeed = t->c_ospeed;
1822	tp->t_cflag = cflag;
1823	tp->t_iflag = iflag;
1824	tp->t_oflag = oflag;
1825	tp->t_lflag = lflag;
1826
1827	if(t->c_ospeed == 0) {
1828		sClrDTR(cp);
1829		return(0);
1830	}
1831	rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1832
1833	/* Set baud rate ----- we only pay attention to ispeed */
1834	sSetDTR(cp);
1835	sSetRTS(cp);
1836	sSetBaud(cp, ospeed);
1837
1838	if(cflag & CSTOPB) {
1839		sSetStop2(cp);
1840	} else {
1841		sSetStop1(cp);
1842	}
1843
1844	if(cflag & PARENB) {
1845		sEnParity(cp);
1846		if(cflag & PARODD) {
1847			sSetOddParity(cp);
1848		} else {
1849			sSetEvenParity(cp);
1850		}
1851	}
1852	else {
1853		sDisParity(cp);
1854	}
1855	if((cflag & CSIZE) == CS8) {
1856		sSetData8(cp);
1857		rp->rp_imask = 0xFF;
1858	} else {
1859		sSetData7(cp);
1860		rp->rp_imask = 0x7F;
1861	}
1862
1863	if(iflag & ISTRIP) {
1864		rp->rp_imask &= 0x7F;
1865	}
1866
1867	if(cflag & CLOCAL) {
1868		rp->rp_intmask &= ~DELTA_CD;
1869	} else {
1870		rp->rp_intmask |= DELTA_CD;
1871	}
1872
1873	/* Put flow control stuff here */
1874
1875	if(cflag & CCTS_OFLOW) {
1876		sEnCTSFlowCtl(cp);
1877	} else {
1878		sDisCTSFlowCtl(cp);
1879	}
1880
1881	if(cflag & CRTS_IFLOW) {
1882		rp->rp_rts_iflow = 1;
1883	} else {
1884		rp->rp_rts_iflow = 0;
1885	}
1886
1887	if(cflag & CRTS_IFLOW) {
1888		sEnRTSFlowCtl(cp);
1889	} else {
1890		sDisRTSFlowCtl(cp);
1891	}
1892	rp_disc_optim(tp, t, rp);
1893
1894	if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1895		tp->t_state |= TS_CARR_ON;
1896		wakeup(TSA_CARR_ON(tp));
1897	}
1898
1899/*	tp->t_state |= TS_CAN_BYPASS_L_RINT;
1900	flags = rp->rp_channel.TxControl[3];
1901	if(flags & SET_DTR)
1902	else
1903	if(flags & SET_RTS)
1904	else
1905*/
1906	splx(oldspl);
1907
1908	return(0);
1909}
1910
1911static void
1912rp_disc_optim(tp, t, rp)
1913struct	tty	*tp;
1914struct	termios *t;
1915struct	rp_port *rp;
1916{
1917	if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1918		&&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1919		&&(!(t->c_iflag & PARMRK)
1920		  ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1921		&& !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1922		&& linesw[tp->t_line].l_rint == ttyinput)
1923		tp->t_state |= TS_CAN_BYPASS_L_RINT;
1924	else
1925		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1926}
1927
1928static void
1929rpstart(tp)
1930	struct tty *tp;
1931{
1932	struct rp_port	*rp;
1933	CHANNEL_t	*cp;
1934	struct	clist	*qp;
1935	int	unit, mynor, port, umynor;               /* SG */
1936	char	ch, flags;
1937	int	spl, xmit_fifo_room;
1938	int	count;
1939
1940
1941   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1942	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1943	mynor = (port + umynor);                          /* SG */
1944	unit = minor_to_unit[mynor];
1945	rp = rp_addr(unit) + port;
1946	cp = &rp->rp_channel;
1947	flags = rp->rp_channel.TxControl[3];
1948	spl = spltty();
1949
1950	if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1951		ttwwakeup(tp);
1952		splx(spl);
1953		return;
1954	}
1955	if(rp->rp_xmit_stopped) {
1956		sEnTransmit(cp);
1957		rp->rp_xmit_stopped = 0;
1958	}
1959	count = sGetTxCnt(cp);
1960
1961	if(tp->t_outq.c_cc == 0) {
1962		if((tp->t_state & TS_BUSY) && (count == 0)) {
1963			tp->t_state &= ~TS_BUSY;
1964		}
1965		ttwwakeup(tp);
1966		splx(spl);
1967		return;
1968	}
1969	xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1970	qp = &tp->t_outq;
1971	count = 0;
1972	if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1973		tp->t_state |= TS_BUSY;
1974	}
1975	while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1976		ch = getc(qp);
1977		sOutB(sGetTxRxDataIO(cp), ch);
1978		xmit_fifo_room--;
1979		count++;
1980	}
1981	rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1982
1983	ttwwakeup(tp);
1984	splx(spl);
1985}
1986
1987static
1988void
1989rpstop(tp, flag)
1990	register struct tty *tp;
1991	int	flag;
1992{
1993	struct rp_port	*rp;
1994	CHANNEL_t	*cp;
1995	int	unit, mynor, port, umynor;                  /* SG */
1996	int	spl;
1997
1998   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1999	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
2000	mynor = (port + umynor);                          /* SG */
2001	unit = minor_to_unit[mynor];
2002	rp = rp_addr(unit) + port;
2003	cp = &rp->rp_channel;
2004
2005	spl = spltty();
2006
2007	if(tp->t_state & TS_BUSY) {
2008		if((tp->t_state&TS_TTSTOP) == 0) {
2009			sFlushTxFIFO(cp);
2010		} else {
2011			if(rp->rp_xmit_stopped == 0) {
2012				sDisTransmit(cp);
2013				rp->rp_xmit_stopped = 1;
2014			}
2015		}
2016	}
2017	splx(spl);
2018	rpstart(tp);
2019}
2020
2021int
2022rpselect(dev, flag, p)
2023	dev_t dev;
2024	int flag;
2025	struct proc *p;
2026{
2027	return(0);
2028}
2029
2030struct tty *
2031rpdevtotty(dev_t dev)
2032{
2033	struct	rp_port *rp;
2034	int	unit, port, mynor, umynor;         /* SG */
2035
2036   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
2037	port  = (minor(dev) & 0x1f);                /* SG */
2038	mynor = (port + umynor);                    /* SG */
2039   unit = minor_to_unit[mynor];                /* SG */
2040
2041	if(IS_CONTROL(dev))
2042		return(NULL);
2043	rp = rp_addr(unit) + port;
2044	return(rp->rp_tty);
2045}
2046