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