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