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