rp.c revision 46027
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: $
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
785#ifdef COMPAT_PCI_DRIVER
786COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
787#else
788DATA_SET (pcidevice_set, rp_pcidevice);
789#endif /* COMPAT_PCI_DRIVER */
790
791static timeout_t rpdtrwakeup;
792
793struct isa_driver rpdriver = {
794	rpprobe, rpattach, "rp"
795     };
796
797static	char	driver_name[] = "rp";
798
799static	d_open_t	rpopen;
800static	d_close_t	rpclose;
801static	d_read_t	rpread;
802static	d_write_t	rpwrite;
803static	d_ioctl_t	rpioctl;
804static	d_stop_t	rpstop;
805static	d_devtotty_t	rpdevtotty;
806
807#define	CDEV_MAJOR	81
808static	struct cdevsw	rp_cdevsw = {
809	rpopen,		rpclose,	rpread,		rpwrite,
810	rpioctl,	rpstop,		noreset,	rpdevtotty,
811	ttpoll,		nommap,		NULL,		driver_name,
812	NULL,		-1,		nodump,		nopsize,
813	D_TTY,
814};
815
816static int rp_controller_port = 0;
817static int rp_num_ports_open = 0;
818static int	ndevs = 0;
819static int	minor_to_unit[128];
820#if 0
821static	struct	tty	rp_tty[128];
822#endif
823
824static int rp_num_ports[4];	/* Number of ports on each controller */
825
826#define _INLINE_ __inline
827#define POLL_INTERVAL 1
828
829#define CALLOUT_MASK		0x80
830#define CONTROL_MASK		0x60
831#define CONTROL_INIT_STATE	0x20
832#define CONTROL_LOCK_STATE	0x40
833#define DEV_UNIT(dev)	(MINOR_TO_UNIT(minor(dev))
834#define MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
835#define MINOR_MAGIC(dev)	((minor(dev)) & ~MINOR_MAGIC_MASK)
836#define IS_CALLOUT(dev) 	(minor(dev) & CALLOUT_MASK)
837#define IS_CONTROL(dev) 	(minor(dev) & CONTROL_MASK)
838
839#define RP_ISMULTIPORT(dev)	((dev)->id_flags & 0x1)
840#define RP_MPMASTER(dev)	(((dev)->id_flags >> 8) & 0xff)
841#define RP_NOTAST4(dev) 	((dev)->id_flags & 0x04)
842
843static	struct	rp_port *p_rp_addr[4];
844static	struct	rp_port *p_rp_table[MAX_RP_PORTS];
845#define rp_addr(unit)	(p_rp_addr[unit])
846#define rp_table(port)	(p_rp_table[port])
847
848/*
849 * The top-level routines begin here
850 */
851
852int	rpselect __P((dev_t, int, struct proc *));
853
854static	int	rpparam __P((struct tty *, struct termios *));
855static	void	rpstart __P((struct tty *));
856static	void	rphardclose	__P((struct rp_port *));
857#define rpmap	nomap
858#define rpreset noreset
859#define rpstrategy	nostrategy
860static	void	rp_disc_optim	__P((struct tty *tp, struct termios *t,
861						struct rp_port	*rp));
862
863static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
864			CHANNEL_t *cp, unsigned int ChanStatus)
865{
866	int	spl;
867	unsigned	int	CharNStat;
868	int	ToRecv, ch;
869
870	ToRecv = sGetRxCnt(cp);
871	if(ToRecv == 0)
872		return;
873
874/*	If status indicates there are errored characters in the
875	FIFO, then enter status mode (a word in FIFO holds
876	characters and status)
877*/
878
879	if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
880		if(!(ChanStatus & STATMODE)) {
881			ChanStatus |= STATMODE;
882			sEnRxStatusMode(cp);
883		}
884	}
885/*
886	if we previously entered status mode then read down the
887	FIFO one word at a time, pulling apart the character and
888	the status. Update error counters depending on status.
889*/
890	if(ChanStatus & STATMODE) {
891		while(ToRecv) {
892			if(tp->t_state & TS_TBLOCK) {
893				break;
894			}
895			CharNStat = sInW(sGetTxRxDataIO(cp));
896			ch = CharNStat & 0xff;
897
898			if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
899				ch |= TTY_FE;
900			else if (CharNStat & STMPARITYH)
901				ch |= TTY_PE;
902			else if (CharNStat & STMRCVROVRH)
903				rp->rp_overflows++;
904
905			(*linesw[tp->t_line].l_rint)(ch, tp);
906			ToRecv--;
907		}
908/*
909	After emtying FIFO in status mode, turn off status mode
910*/
911
912	if(sGetRxCnt(cp) == 0)
913		sDisRxStatusMode(cp);
914	}
915	else {
916		while (ToRecv) {
917			if(tp->t_state & TS_TBLOCK) {
918				break;
919			}
920			ch = (u_char) sInB(sGetTxRxDataIO(cp));
921			spl = spltty();
922			(*linesw[tp->t_line].l_rint)(ch, tp);
923			splx(spl);
924			ToRecv--;
925		}
926	}
927}
928
929static _INLINE_ void rp_handle_port(struct rp_port *rp)
930{
931	CHANNEL_t	*cp;
932	struct	tty	*tp;
933	unsigned	int	IntMask, ChanStatus;
934     /*	int	oldcts; */
935
936	if(!rp)
937		return;
938
939	cp = &rp->rp_channel;
940	tp = rp->rp_tty;
941	IntMask = sGetChanIntID(cp);
942	IntMask = IntMask & rp->rp_intmask;
943	ChanStatus = sGetChanStatus(cp);
944	if(IntMask & RXF_TRIG)
945		if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
946			rp_do_receive(rp, tp, cp, ChanStatus);
947		}
948	if(IntMask & DELTA_CD) {
949		if(ChanStatus & CD_ACT) {
950			if(!(tp->t_state & TS_CARR_ON) ) {
951				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
952			}
953		} else {
954			if((tp->t_state & TS_CARR_ON)) {
955				(void)(*linesw[tp->t_line].l_modem)(tp, 0);
956				if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
957					rphardclose(rp);
958				}
959			}
960		}
961	}
962/*	oldcts = rp->rp_cts;
963	rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
964	if(oldcts != rp->rp_cts) {
965		printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
966	}
967*/
968}
969
970static void rp_do_poll(void *not_used)
971{
972	CONTROLLER_t	*ctl;
973	struct rp_port	*rp;
974	struct tty	*tp;
975	int	unit, aiop, ch, line, count;
976	unsigned char	CtlMask, AiopMask;
977
978	for(unit = 0; unit <= ndevs; unit++) {
979	rp = rp_addr(unit);
980	ctl = rp->rp_ctlp;
981	if(ctl->BusType == isPCI)
982		CtlMask = sPCIGetControllerIntStatus(ctl);
983	else
984		CtlMask = sGetControllerIntStatus(ctl);
985	for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
986		if(CtlMask & 1) {
987			AiopMask = sGetAiopIntStatus(ctl, aiop);
988			for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
989				if(AiopMask & 1) {
990					line = (unit << 5) | (aiop << 3) | ch;
991					rp = rp_table(line);
992					rp_handle_port(rp);
993				}
994			}
995		}
996	}
997
998	for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
999			line++, rp++) {
1000		tp = rp->rp_tty;
1001		if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1002			count = sGetTxCnt(&rp->rp_channel);
1003			if(count == 0)
1004				tp->t_state &= ~(TS_BUSY);
1005			if(!(tp->t_state & TS_TTSTOP) &&
1006				(count <= rp->rp_restart)) {
1007				(*linesw[tp->t_line].l_start)(tp);
1008			}
1009		}
1010	}
1011	}
1012	if(rp_num_ports_open)
1013		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1014}
1015
1016static const char*
1017rp_pciprobe(pcici_t tag, pcidi_t type)
1018{
1019	int	vendor_id;
1020
1021	vendor_id = type & 0xffff;
1022	switch(vendor_id)
1023	case 0x11fe:
1024		return("rp");
1025	return(NULL);
1026}
1027
1028static
1029int
1030rpprobe(dev)
1031struct isa_device *dev;
1032{
1033	int controller, unit;
1034	int aiop, num_aiops;
1035	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1036	CONTROLLER_t *ctlp;
1037
1038	unit = dev->id_unit;
1039	if (dev->id_unit >= 4) {
1040		printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1041		return 1;
1042	}
1043	printf("probing for RocketPort(ISA) unit %d\n", unit);
1044	if (rp_controller_port)
1045		controller = rp_controller_port;
1046	else {
1047		controller = dev->id_iobase + 0x40;
1048	}
1049
1050	for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1051		aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1052
1053	ctlp = sCtlNumToCtlPtr(dev->id_unit);
1054	num_aiops = sInitController(ctlp, dev->id_unit,
1055				controller + ((unit-rp_pcicount)*0x400),
1056				aiopio, MAX_AIOPS_PER_BOARD, 0,
1057				FREQ_DIS, 0);
1058	if (num_aiops <= 0) {
1059		printf("board%d init failed\n", unit);
1060		return 0;
1061	}
1062
1063	if (rp_controller_port) {
1064		dev->id_msize = 64;
1065	} else {
1066		dev->id_msize = 68;
1067		rp_controller_port = controller;
1068	}
1069
1070	dev->id_irq = 0;
1071
1072	return 1;
1073}
1074
1075static void
1076rp_pciattach(pcici_t tag, int unit)
1077{
1078	dev_t	rp_dev;
1079	int	success, oldspl;
1080	u_short iobase;
1081	int	num_ports, num_chan, num_aiops;
1082	int	aiop, chan, port;
1083	int	ChanStatus, line, i, count;
1084	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1085	struct	rp_port *rp;
1086	struct	tty	*tty;
1087	CONTROLLER_t	*ctlp;
1088
1089	success = pci_map_port(tag, 0x10, &iobase);
1090	if(!success)
1091		printf("ioaddr mapping failed for RocketPort(PCI)\n");
1092
1093	for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1094		aiopio[aiop] = iobase + (aiop * 0x40);
1095
1096	ctlp = sCtlNumToCtlPtr(unit);
1097	num_aiops = sPCIInitController(ctlp, unit,
1098				aiopio, MAX_AIOPS_PER_BOARD, 0,
1099				FREQ_DIS, 0);
1100
1101	num_ports = 0;
1102	for(aiop=0; aiop < num_aiops; aiop++) {
1103		sResetAiopByNum(ctlp, aiop);
1104		num_ports += sGetAiopNumChan(ctlp, aiop);
1105	}
1106	printf("RocketPort%d = %d ports\n", unit, num_ports);
1107	rp_num_ports[unit] = num_ports;
1108
1109	rp = (struct rp_port *)
1110		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1111	if(rp == 0) {
1112		printf("rp_attach: Could not malloc rp_ports structures\n");
1113		return;
1114	}
1115
1116	count = unit * 32;      /* board times max ports per card SG */
1117	for(i=count;i < (count + rp_num_ports[unit]);i++)
1118		minor_to_unit[i] = unit;
1119
1120	bzero(rp, sizeof(struct rp_port) * num_ports);
1121	tty = (struct tty *)
1122		malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1123	if(tty == 0) {
1124		printf("rp_attach: Could not malloc tty structures\n");
1125		return;
1126	}
1127	bzero(tty, sizeof(struct tty) * num_ports);
1128
1129	oldspl = spltty();
1130	rp_addr(unit) = rp;
1131	splx(oldspl);
1132
1133	rp_dev = makedev(CDEV_MAJOR, unit);
1134	cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1135
1136	port = 0;
1137	for(aiop=0; aiop < num_aiops; aiop++) {
1138		num_chan = sGetAiopNumChan(ctlp, aiop);
1139		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1140			rp->rp_tty = tty;
1141			rp->rp_port = port;
1142			rp->rp_ctlp = ctlp;
1143			rp->rp_unit = unit;
1144			rp->rp_chan = chan;
1145			rp->rp_aiop = aiop;
1146
1147			tty->t_line = 0;
1148	/*		tty->t_termios = deftermios;
1149	*/
1150			rp->dtr_wait = 3 * hz;
1151			rp->it_in.c_iflag = 0;
1152			rp->it_in.c_oflag = 0;
1153			rp->it_in.c_cflag = TTYDEF_CFLAG;
1154			rp->it_in.c_lflag = 0;
1155			termioschars(&rp->it_in);
1156	/*		termioschars(&tty->t_termios);
1157	*/
1158			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1159			rp->it_out = rp->it_in;
1160
1161			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1162				DELTA_CD | DELTA_CTS | DELTA_DSR;
1163			ChanStatus = sGetChanStatus(&rp->rp_channel);
1164			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1165				printf("RocketPort sInitChan(%d, %d, %d) failed
1166					\n", unit, aiop, chan);
1167				return;
1168			}
1169			ChanStatus = sGetChanStatus(&rp->rp_channel);
1170			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1171			line = (unit << 5) | (aiop << 3) | chan;
1172			rp_table(line) = rp;
1173/*			devfs_add_devswf(&rp_cdevsw,
1174				port, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
1175				"ttyR%r", port);
1176			devfs_add_devswf(&rp_cdevsw,
1177				port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT,
1178				GID_WHEEL, 0600, "ttyRi%r", port);
1179*/
1180		}
1181	}
1182}
1183
1184static
1185int
1186rpattach(dev)
1187struct	isa_device	*dev;
1188{
1189	dev_t	rp_dev;
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	rp_dev = makedev(CDEV_MAJOR, unit);
1246	cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1247
1248	port = 0;
1249	for(aiop=0; aiop < num_aiops; aiop++) {
1250		num_chan = sGetAiopNumChan(ctlp, aiop);
1251		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1252			rp->rp_tty = tty;
1253			rp->rp_port = port;
1254			rp->rp_ctlp = ctlp;
1255			rp->rp_unit = unit;
1256			rp->rp_chan = chan;
1257			rp->rp_aiop = aiop;
1258
1259			tty->t_line = 0;
1260	/*		tty->t_termios = deftermios;
1261	*/
1262			rp->dtr_wait = 3 * hz;
1263			rp->it_in.c_iflag = 0;
1264			rp->it_in.c_oflag = 0;
1265			rp->it_in.c_cflag = TTYDEF_CFLAG;
1266			rp->it_in.c_lflag = 0;
1267			termioschars(&rp->it_in);
1268	/*		termioschars(&tty->t_termios);
1269	*/
1270			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1271			rp->it_out = rp->it_in;
1272
1273			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1274				DELTA_CD | DELTA_CTS | DELTA_DSR;
1275			ChanStatus = sGetChanStatus(&rp->rp_channel);
1276			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1277				printf("RocketPort sInitChan(%d, %d, %d) failed
1278					\n", unit, aiop, chan);
1279				return(0);
1280			}
1281			ChanStatus = sGetChanStatus(&rp->rp_channel);
1282			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1283			line = (unit << 5) | (aiop << 3) | chan;
1284			rp_table(line) = rp;
1285		}
1286	}
1287
1288	return(1);
1289}
1290
1291int
1292rpopen(dev, flag, mode, p)
1293	dev_t	dev;
1294	int	flag, mode;
1295	struct	proc	*p;
1296{
1297	struct	rp_port *rp;
1298	int	unit, port, mynor, umynor, flags;  /* SG */
1299	struct	tty	*tp;
1300	int	oldspl, error;
1301	unsigned int	IntMask, ChanStatus;
1302
1303
1304   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1305	port  = (minor(dev) & 0x1f);                /* SG */
1306	mynor = (port + umynor);                    /* SG */
1307	unit = minor_to_unit[mynor];
1308	if(IS_CONTROL(dev))
1309		return(0);
1310	rp = rp_addr(unit) + port;
1311/*	rp->rp_tty = &rp_tty[rp->rp_port];
1312*/
1313	tp = rp->rp_tty;
1314
1315	oldspl = spltty();
1316
1317open_top:
1318	while(rp->state & ~SET_DTR) {
1319		error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1320		if(error != 0)
1321			goto out;
1322	}
1323
1324	if(tp->t_state & TS_ISOPEN) {
1325		if(IS_CALLOUT(dev)) {
1326			if(!rp->active_out) {
1327				error = EBUSY;
1328				goto out;
1329			}
1330		} else {
1331			if(rp->active_out) {
1332				if(flag & O_NONBLOCK) {
1333					error = EBUSY;
1334					goto out;
1335				}
1336				error = tsleep(&rp->active_out,
1337					TTIPRI | PCATCH, "rpbi", 0);
1338				if(error != 0)
1339					goto out;
1340				goto open_top;
1341			}
1342		}
1343		if(tp->t_state & TS_XCLUDE &&
1344		    suser(p->p_ucred, &p->p_acflag)) {
1345			splx(oldspl);
1346			return(EBUSY);
1347		}
1348	}
1349	else {
1350		tp->t_dev = dev;
1351		tp->t_param = rpparam;
1352		tp->t_oproc = rpstart;
1353		tp->t_line = 0;
1354		tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1355		flags = 0;
1356		flags |= SET_RTS;
1357		flags |= SET_DTR;
1358		rp->rp_channel.TxControl[3] =
1359			((rp->rp_channel.TxControl[3]
1360			& ~(SET_RTS | SET_DTR)) | flags);
1361		sOutDW(rp->rp_channel.IndexAddr,
1362			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1363		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1364		sDisRxStatusMode(&rp->rp_channel);
1365		sFlushRxFIFO(&rp->rp_channel);
1366		sFlushTxFIFO(&rp->rp_channel);
1367
1368		sEnInterrupts(&rp->rp_channel,
1369			(TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1370		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1371
1372		sDisRxStatusMode(&rp->rp_channel);
1373		sClrTxXOFF(&rp->rp_channel);
1374
1375/*		sDisRTSFlowCtl(&rp->rp_channel);
1376		sDisCTSFlowCtl(&rp->rp_channel);
1377*/
1378		sDisTxSoftFlowCtl(&rp->rp_channel);
1379
1380		sStartRxProcessor(&rp->rp_channel);
1381
1382		sEnRxFIFO(&rp->rp_channel);
1383		sEnTransmit(&rp->rp_channel);
1384
1385/*		sSetDTR(&rp->rp_channel);
1386		sSetRTS(&rp->rp_channel);
1387*/
1388
1389		++rp->wopeners;
1390		error = rpparam(tp, &tp->t_termios);
1391		--rp->wopeners;
1392		if(error != 0) {
1393			splx(oldspl);
1394			return(error);
1395		}
1396
1397		rp_num_ports_open++;
1398
1399		IntMask = sGetChanIntID(&rp->rp_channel);
1400		IntMask = IntMask & rp->rp_intmask;
1401		ChanStatus = sGetChanStatus(&rp->rp_channel);
1402		if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1403			if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1404					(void)(*linesw[tp->t_line].l_modem)(tp, 1);
1405			}
1406		}
1407
1408	if(rp_num_ports_open == 1)
1409		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1410
1411	}
1412
1413	if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1414		!(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1415		++rp->wopeners;
1416		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1417				"rpdcd", 0);
1418		--rp->wopeners;
1419		if(error != 0)
1420			goto out;
1421		goto open_top;
1422	}
1423	error = (*linesw[tp->t_line].l_open)(dev, tp);
1424
1425	rp_disc_optim(tp, &tp->t_termios, rp);
1426	if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1427		rp->active_out = TRUE;
1428
1429/*	if(rp_num_ports_open == 1)
1430		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1431*/
1432out:
1433	splx(oldspl);
1434	if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1435		rphardclose(rp);
1436	}
1437	return(error);
1438}
1439
1440int
1441rpclose(dev, flag, mode, p)
1442	dev_t	dev;
1443	int	flag, mode;
1444	struct	proc	*p;
1445{
1446	int	oldspl, unit, mynor, umynor, port; /* SG */
1447	struct	rp_port *rp;
1448	struct	tty	*tp;
1449	CHANNEL_t	*cp;
1450
1451   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1452	port  = (minor(dev) & 0x1f);                /* SG */
1453	mynor = (port + umynor);                    /* SG */
1454   unit = minor_to_unit[mynor];                /* SG */
1455
1456	if(IS_CONTROL(dev))
1457		return(0);
1458	rp = rp_addr(unit) + port;
1459	cp = &rp->rp_channel;
1460	tp = rp->rp_tty;
1461
1462	oldspl = spltty();
1463	(*linesw[tp->t_line].l_close)(tp, flag);
1464	rp_disc_optim(tp, &tp->t_termios, rp);
1465	rpstop(tp, FREAD | FWRITE);
1466	rphardclose(rp);
1467
1468	tp->t_state &= ~TS_BUSY;
1469	ttyclose(tp);
1470
1471	splx(oldspl);
1472
1473	return(0);
1474}
1475
1476static void
1477rphardclose(struct rp_port *rp)
1478{
1479	int	mynor;
1480	struct	tty	*tp;
1481	CHANNEL_t	*cp;
1482
1483	cp = &rp->rp_channel;
1484	tp = rp->rp_tty;
1485	mynor = MINOR_MAGIC(tp->t_dev);
1486
1487	sFlushRxFIFO(cp);
1488	sFlushTxFIFO(cp);
1489	sDisTransmit(cp);
1490	sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1491	sDisRTSFlowCtl(cp);
1492	sDisCTSFlowCtl(cp);
1493	sDisTxSoftFlowCtl(cp);
1494	sClrTxXOFF(cp);
1495
1496	if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1497		sClrDTR(cp);
1498	}
1499	if(IS_CALLOUT(tp->t_dev)) {
1500		sClrDTR(cp);
1501	}
1502	if(rp->dtr_wait != 0) {
1503		timeout(rpdtrwakeup, rp, rp->dtr_wait);
1504		rp->state |= ~SET_DTR;
1505	}
1506
1507	rp->active_out = FALSE;
1508	wakeup(&rp->active_out);
1509	wakeup(TSA_CARR_ON(tp));
1510}
1511
1512static
1513int
1514rpread(dev, uio, flag)
1515	dev_t	dev;
1516	struct	uio	*uio;
1517	int	flag;
1518{
1519	struct	rp_port *rp;
1520	struct	tty	*tp;
1521	int	unit, mynor, umynor, port, error = 0; /* SG */
1522
1523   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1524	port  = (minor(dev) & 0x1f);                /* SG */
1525	mynor = (port + umynor);                    /* SG */
1526   unit = minor_to_unit[mynor];                /* SG */
1527
1528	if(IS_CONTROL(dev))
1529		return(ENODEV);
1530	rp = rp_addr(unit) + port;
1531	tp = rp->rp_tty;
1532	error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
1533	return(error);
1534}
1535
1536static
1537int
1538rpwrite(dev, uio, flag)
1539	dev_t	dev;
1540	struct	uio	*uio;
1541	int	flag;
1542{
1543	struct	rp_port *rp;
1544	struct	tty	*tp;
1545	int	unit, mynor, port, umynor, error = 0; /* SG */
1546
1547   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1548	port  = (minor(dev) & 0x1f);                /* SG */
1549	mynor = (port + umynor);                    /* SG */
1550   unit = minor_to_unit[mynor];                /* SG */
1551
1552	if(IS_CONTROL(dev))
1553		return(ENODEV);
1554	rp = rp_addr(unit) + port;
1555	tp = rp->rp_tty;
1556	while(rp->rp_disable_writes) {
1557		rp->rp_waiting = 1;
1558		if(error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH,
1559					"rp_write", 0)) {
1560			return(error);
1561		}
1562	}
1563
1564	error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1565	return error;
1566}
1567
1568static void
1569rpdtrwakeup(void *chan)
1570{
1571	struct	rp_port *rp;
1572
1573	rp = (struct rp_port *)chan;
1574	rp->state &= SET_DTR;
1575	wakeup(&rp->dtr_wait);
1576}
1577
1578int
1579rpioctl(dev, cmd, data, flag, p)
1580	dev_t	dev;
1581	u_long	cmd;
1582	caddr_t data;
1583	int	flag;
1584	struct	proc	*p;
1585{
1586	struct rp_port	*rp;
1587	CHANNEL_t	*cp;
1588	struct tty	*tp;
1589	int	unit, mynor, port, umynor;            /* SG */
1590	int	oldspl;
1591	int	error = 0;
1592	int	arg, flags, result, ChanStatus;
1593	int	oldcmd;
1594	struct	termios term, *t;
1595
1596   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1597	port  = (minor(dev) & 0x1f);                /* SG */
1598	mynor = (port + umynor);                    /* SG */
1599	unit = minor_to_unit[mynor];
1600	rp = rp_addr(unit) + port;
1601
1602	if(IS_CONTROL(dev)) {
1603		struct	termios *ct;
1604
1605		switch (IS_CONTROL(dev)) {
1606		case CONTROL_INIT_STATE:
1607			ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1608			break;
1609		case CONTROL_LOCK_STATE:
1610			ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1611			break;
1612		default:
1613			return(ENODEV); 	/* /dev/nodev */
1614		}
1615		switch (cmd) {
1616		case TIOCSETA:
1617			error = suser(p->p_ucred, &p->p_acflag);
1618			if(error != 0)
1619				return(error);
1620			*ct = *(struct termios *)data;
1621			return(0);
1622		case TIOCGETA:
1623			*(struct termios *)data = *ct;
1624			return(0);
1625		case TIOCGETD:
1626			*(int *)data = TTYDISC;
1627			return(0);
1628		case TIOCGWINSZ:
1629			bzero(data, sizeof(struct winsize));
1630			return(0);
1631		default:
1632			return(ENOTTY);
1633		}
1634	}
1635
1636	tp = rp->rp_tty;
1637	cp = &rp->rp_channel;
1638
1639#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1640	term = tp->t_termios;
1641	oldcmd = cmd;
1642	error = ttsetcompat(tp, &cmd, data, &term);
1643	if(error != 0)
1644		return(error);
1645	if(cmd != oldcmd) {
1646		data = (caddr_t)&term;
1647	}
1648#endif
1649	if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1650		int	cc;
1651		struct	termios *dt = (struct termios *)data;
1652		struct	termios *lt = IS_CALLOUT(dev)
1653					? &rp->lt_out : &rp->lt_in;
1654
1655		dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1656				| (dt->c_iflag & ~lt->c_iflag);
1657		dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1658				| (dt->c_oflag & ~lt->c_oflag);
1659		dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1660				| (dt->c_cflag & ~lt->c_cflag);
1661		dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1662				| (dt->c_lflag & ~lt->c_lflag);
1663		for(cc = 0; cc < NCCS; ++cc)
1664			if(lt->c_cc[cc] = tp->t_cc[cc])
1665				dt->c_cc[cc] = tp->t_cc[cc];
1666		if(lt->c_ispeed != 0)
1667			dt->c_ispeed = tp->t_ispeed;
1668		if(lt->c_ospeed != 0)
1669			dt->c_ospeed = tp->t_ospeed;
1670	}
1671
1672	t = &tp->t_termios;
1673
1674	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1675	if(error != ENOIOCTL) {
1676		return(error);
1677	}
1678	oldspl = spltty();
1679
1680	flags = rp->rp_channel.TxControl[3];
1681
1682	error = ttioctl(tp, cmd, data, flag);
1683	flags = rp->rp_channel.TxControl[3];
1684	rp_disc_optim(tp, &tp->t_termios, rp);
1685	if(error != ENOIOCTL) {
1686		splx(oldspl);
1687		return(error);
1688	}
1689	switch(cmd) {
1690	case TIOCSBRK:
1691		sSendBreak(&rp->rp_channel);
1692		break;
1693
1694	case TIOCCBRK:
1695		sClrBreak(&rp->rp_channel);
1696		break;
1697
1698	case TIOCSDTR:
1699		sSetDTR(&rp->rp_channel);
1700		sSetRTS(&rp->rp_channel);
1701		break;
1702
1703	case TIOCCDTR:
1704		sClrDTR(&rp->rp_channel);
1705		break;
1706
1707	case TIOCMSET:
1708		arg = *(int *) data;
1709		flags = 0;
1710		if(arg & TIOCM_RTS)
1711			flags |= SET_RTS;
1712		if(arg & TIOCM_DTR)
1713			flags |= SET_DTR;
1714		rp->rp_channel.TxControl[3] =
1715			((rp->rp_channel.TxControl[3]
1716			& ~(SET_RTS | SET_DTR)) | flags);
1717		sOutDW(rp->rp_channel.IndexAddr,
1718			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1719		break;
1720	case TIOCMBIS:
1721		arg = *(int *) data;
1722		flags = 0;
1723		if(arg & TIOCM_RTS)
1724			flags |= SET_RTS;
1725		if(arg & TIOCM_DTR)
1726			flags |= SET_DTR;
1727			rp->rp_channel.TxControl[3] |= flags;
1728		sOutDW(rp->rp_channel.IndexAddr,
1729			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1730		break;
1731	case TIOCMBIC:
1732		arg = *(int *) data;
1733		flags = 0;
1734		if(arg & TIOCM_RTS)
1735			flags |= SET_RTS;
1736		if(arg & TIOCM_DTR)
1737			flags |= SET_DTR;
1738		rp->rp_channel.TxControl[3] &= ~flags;
1739		sOutDW(rp->rp_channel.IndexAddr,
1740			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1741		break;
1742
1743
1744	case TIOCMGET:
1745		ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1746		flags = rp->rp_channel.TxControl[3];
1747		result = TIOCM_LE; /* always on while open for some reason */
1748		result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1749			| ((flags & SET_RTS) ? TIOCM_RTS : 0)
1750			| ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1751			| ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1752			| ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1753
1754		if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1755		{
1756			result |= TIOCM_RTS;
1757		}
1758
1759		*(int *)data = result;
1760		break;
1761	case TIOCMSDTRWAIT:
1762		error = suser(p->p_ucred, &p->p_acflag);
1763		if(error != 0) {
1764			splx(oldspl);
1765			return(error);
1766		}
1767		rp->dtr_wait = *(int *)data * hz/100;
1768		break;
1769	case TIOCMGDTRWAIT:
1770		*(int *)data = rp->dtr_wait * 100/hz;
1771		break;
1772	default:
1773		splx(oldspl);
1774		return ENOTTY;
1775	}
1776	splx(oldspl);
1777	return(0);
1778}
1779
1780static struct speedtab baud_table[] = {
1781	B0,	0,		B50,	BRD50,		B75,	BRD75,
1782	B110,	BRD110, 	B134,	BRD134, 	B150,	BRD150,
1783	B200,	BRD200, 	B300,	BRD300, 	B600,	BRD600,
1784	B1200,	BRD1200,	B1800,	BRD1800,	B2400,	BRD2400,
1785	B4800,	BRD4800,	B9600,	BRD9600,	B19200, BRD19200,
1786	B38400, BRD38400,	B7200,	BRD7200,	B14400, BRD14400,
1787				B57600, BRD57600,	B76800, BRD76800,
1788	B115200, BRD115200,	B230400, BRD230400,
1789	-1,	-1
1790};
1791
1792static int
1793rpparam(tp, t)
1794	struct tty *tp;
1795	struct termios *t;
1796{
1797	struct rp_port	*rp;
1798	CHANNEL_t	*cp;
1799	int	unit, mynor, port, umynor;               /* SG */
1800	int	oldspl, cflag, iflag, oflag, lflag;
1801	int	ospeed;
1802
1803
1804   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1805	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1806	mynor = (port + umynor);                          /* SG */
1807
1808	unit = minor_to_unit[mynor];
1809	rp = rp_addr(unit) + port;
1810	cp = &rp->rp_channel;
1811	oldspl = spltty();
1812
1813	cflag = t->c_cflag;
1814	iflag = t->c_iflag;
1815	oflag = t->c_oflag;
1816	lflag = t->c_lflag;
1817
1818	ospeed = ttspeedtab(t->c_ispeed, baud_table);
1819	if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1820		return(EINVAL);
1821
1822	tp->t_ispeed = t->c_ispeed;
1823	tp->t_ospeed = t->c_ospeed;
1824	tp->t_cflag = cflag;
1825	tp->t_iflag = iflag;
1826	tp->t_oflag = oflag;
1827	tp->t_lflag = lflag;
1828
1829	if(t->c_ospeed == 0) {
1830		sClrDTR(cp);
1831		return(0);
1832	}
1833	rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1834
1835	/* Set baud rate ----- we only pay attention to ispeed */
1836	sSetDTR(cp);
1837	sSetRTS(cp);
1838	sSetBaud(cp, ospeed);
1839
1840	if(cflag & CSTOPB) {
1841		sSetStop2(cp);
1842	} else {
1843		sSetStop1(cp);
1844	}
1845
1846	if(cflag & PARENB) {
1847		sEnParity(cp);
1848		if(cflag & PARODD) {
1849			sSetOddParity(cp);
1850		} else {
1851			sSetEvenParity(cp);
1852		}
1853	}
1854	else {
1855		sDisParity(cp);
1856	}
1857	if((cflag & CSIZE) == CS8) {
1858		sSetData8(cp);
1859		rp->rp_imask = 0xFF;
1860	} else {
1861		sSetData7(cp);
1862		rp->rp_imask = 0x7F;
1863	}
1864
1865	if(iflag & ISTRIP) {
1866		rp->rp_imask &= 0x7F;
1867	}
1868
1869	if(cflag & CLOCAL) {
1870		rp->rp_intmask &= ~DELTA_CD;
1871	} else {
1872		rp->rp_intmask |= DELTA_CD;
1873	}
1874
1875	/* Put flow control stuff here */
1876
1877	if(cflag & CCTS_OFLOW) {
1878		sEnCTSFlowCtl(cp);
1879	} else {
1880		sDisCTSFlowCtl(cp);
1881	}
1882
1883	if(cflag & CRTS_IFLOW) {
1884		rp->rp_rts_iflow = 1;
1885	} else {
1886		rp->rp_rts_iflow = 0;
1887	}
1888
1889	if(cflag & CRTS_IFLOW) {
1890		sEnRTSFlowCtl(cp);
1891	} else {
1892		sDisRTSFlowCtl(cp);
1893	}
1894	rp_disc_optim(tp, t, rp);
1895
1896	if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1897		tp->t_state |= TS_CARR_ON;
1898		wakeup(TSA_CARR_ON(tp));
1899	}
1900
1901/*	tp->t_state |= TS_CAN_BYPASS_L_RINT;
1902	flags = rp->rp_channel.TxControl[3];
1903	if(flags & SET_DTR)
1904	else
1905	if(flags & SET_RTS)
1906	else
1907*/
1908	splx(oldspl);
1909
1910	return(0);
1911}
1912
1913static void
1914rp_disc_optim(tp, t, rp)
1915struct	tty	*tp;
1916struct	termios *t;
1917struct	rp_port *rp;
1918{
1919	if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1920		&&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1921		&&(!(t->c_iflag & PARMRK)
1922		  ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1923		&& !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1924		&& linesw[tp->t_line].l_rint == ttyinput)
1925		tp->t_state |= TS_CAN_BYPASS_L_RINT;
1926	else
1927		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1928}
1929
1930static void
1931rpstart(tp)
1932	struct tty *tp;
1933{
1934	struct rp_port	*rp;
1935	CHANNEL_t	*cp;
1936	struct	clist	*qp;
1937	int	unit, mynor, port, umynor;               /* SG */
1938	char	ch, flags;
1939	int	spl, xmit_fifo_room;
1940	int	count;
1941
1942
1943   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1944	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1945	mynor = (port + umynor);                          /* SG */
1946	unit = minor_to_unit[mynor];
1947	rp = rp_addr(unit) + port;
1948	cp = &rp->rp_channel;
1949	flags = rp->rp_channel.TxControl[3];
1950	spl = spltty();
1951
1952	if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1953		ttwwakeup(tp);
1954		splx(spl);
1955		return;
1956	}
1957	if(rp->rp_xmit_stopped) {
1958		sEnTransmit(cp);
1959		rp->rp_xmit_stopped = 0;
1960	}
1961	count = sGetTxCnt(cp);
1962
1963	if(tp->t_outq.c_cc == 0) {
1964		if((tp->t_state & TS_BUSY) && (count == 0)) {
1965			tp->t_state &= ~TS_BUSY;
1966		}
1967		ttwwakeup(tp);
1968		splx(spl);
1969		return;
1970	}
1971	xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1972	qp = &tp->t_outq;
1973	count = 0;
1974	if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1975		tp->t_state |= TS_BUSY;
1976	}
1977	while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1978		ch = getc(qp);
1979		sOutB(sGetTxRxDataIO(cp), ch);
1980		xmit_fifo_room--;
1981		count++;
1982	}
1983	rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1984
1985	ttwwakeup(tp);
1986	splx(spl);
1987}
1988
1989static
1990void
1991rpstop(tp, flag)
1992	register struct tty *tp;
1993	int	flag;
1994{
1995	struct rp_port	*rp;
1996	CHANNEL_t	*cp;
1997	int	unit, mynor, port, umynor;                  /* SG */
1998	int	spl;
1999
2000   umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
2001	port  = (minor(tp->t_dev) & 0x1f);                /* SG */
2002	mynor = (port + umynor);                          /* SG */
2003	unit = minor_to_unit[mynor];
2004	rp = rp_addr(unit) + port;
2005	cp = &rp->rp_channel;
2006
2007	spl = spltty();
2008
2009	if(tp->t_state & TS_BUSY) {
2010		if((tp->t_state&TS_TTSTOP) == 0) {
2011			sFlushTxFIFO(cp);
2012		} else {
2013			if(rp->rp_xmit_stopped == 0) {
2014				sDisTransmit(cp);
2015				rp->rp_xmit_stopped = 1;
2016			}
2017		}
2018	}
2019	splx(spl);
2020	rpstart(tp);
2021}
2022
2023int
2024rpselect(dev, flag, p)
2025	dev_t dev;
2026	int flag;
2027	struct proc *p;
2028{
2029	return(0);
2030}
2031
2032struct tty *
2033rpdevtotty(dev_t dev)
2034{
2035	struct	rp_port *rp;
2036	int	unit, port, mynor, umynor;         /* SG */
2037
2038   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
2039	port  = (minor(dev) & 0x1f);                /* SG */
2040	mynor = (port + umynor);                    /* SG */
2041   unit = minor_to_unit[mynor];                /* SG */
2042
2043	if(IS_CONTROL(dev))
2044		return(NULL);
2045	rp = rp_addr(unit) + port;
2046	return(rp->rp_tty);
2047}
2048