rp.c revision 41591
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
33/*
34 * rp.c - for RocketPort FreeBSD
35 */
36
37#include "opt_compat.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/fcntl.h>
42#include <sys/malloc.h>
43#include <sys/tty.h>
44#include <sys/proc.h>
45#include <sys/conf.h>
46#include <sys/kernel.h>
47
48#include <i386/isa/isa_device.h>
49
50#include <pci/pcivar.h>
51
52#define ROCKET_C
53#include <i386/isa/rpreg.h>
54#include <i386/isa/rpvar.h>
55
56#ifndef TRUE
57#define TRUE 1
58#endif
59
60#ifndef FALSE
61#define FALSE 0
62#endif
63
64static Byte_t RData[RDATASIZE] =
65{
66   0x00, 0x09, 0xf6, 0x82,
67   0x02, 0x09, 0x86, 0xfb,
68   0x04, 0x09, 0x00, 0x0a,
69   0x06, 0x09, 0x01, 0x0a,
70   0x08, 0x09, 0x8a, 0x13,
71   0x0a, 0x09, 0xc5, 0x11,
72   0x0c, 0x09, 0x86, 0x85,
73   0x0e, 0x09, 0x20, 0x0a,
74   0x10, 0x09, 0x21, 0x0a,
75   0x12, 0x09, 0x41, 0xff,
76   0x14, 0x09, 0x82, 0x00,
77   0x16, 0x09, 0x82, 0x7b,
78   0x18, 0x09, 0x8a, 0x7d,
79   0x1a, 0x09, 0x88, 0x81,
80   0x1c, 0x09, 0x86, 0x7a,
81   0x1e, 0x09, 0x84, 0x81,
82   0x20, 0x09, 0x82, 0x7c,
83   0x22, 0x09, 0x0a, 0x0a
84};
85
86static Byte_t RRegData[RREGDATASIZE]=
87{
88   0x00, 0x09, 0xf6, 0x82,	       /* 00: Stop Rx processor */
89   0x08, 0x09, 0x8a, 0x13,	       /* 04: Tx software flow control */
90   0x0a, 0x09, 0xc5, 0x11,	       /* 08: XON char */
91   0x0c, 0x09, 0x86, 0x85,	       /* 0c: XANY */
92   0x12, 0x09, 0x41, 0xff,	       /* 10: Rx mask char */
93   0x14, 0x09, 0x82, 0x00,	       /* 14: Compare/Ignore #0 */
94   0x16, 0x09, 0x82, 0x7b,	       /* 18: Compare #1 */
95   0x18, 0x09, 0x8a, 0x7d,	       /* 1c: Compare #2 */
96   0x1a, 0x09, 0x88, 0x81,	       /* 20: Interrupt #1 */
97   0x1c, 0x09, 0x86, 0x7a,	       /* 24: Ignore/Replace #1 */
98   0x1e, 0x09, 0x84, 0x81,	       /* 28: Interrupt #2 */
99   0x20, 0x09, 0x82, 0x7c,	       /* 2c: Ignore/Replace #2 */
100   0x22, 0x09, 0x0a, 0x0a	       /* 30: Rx FIFO Enable */
101};
102
103static CONTROLLER_T sController[CTL_SIZE] =
104{
105   {-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}},
106   {-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}},
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};
110
111#if 0
112/* IRQ number to MUDBAC register 2 mapping */
113Byte_t sIRQMap[16] =
114{
115   0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
116};
117#endif
118
119static Byte_t sBitMapClrTbl[8] =
120{
121   0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
122};
123
124static Byte_t sBitMapSetTbl[8] =
125{
126   0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
127};
128
129/***************************************************************************
130Function: sInitController
131Purpose:  Initialization of controller global registers and controller
132	  structure.
133Call:	  sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
134			  IRQNum,Frequency,PeriodicOnly)
135	  CONTROLLER_T *CtlP; Ptr to controller structure
136	  int CtlNum; Controller number
137	  ByteIO_t MudbacIO; Mudbac base I/O address.
138	  ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
139	     This list must be in the order the AIOPs will be found on the
140	     controller.  Once an AIOP in the list is not found, it is
141	     assumed that there are no more AIOPs on the controller.
142	  int AiopIOListSize; Number of addresses in AiopIOList
143	  int IRQNum; Interrupt Request number.  Can be any of the following:
144			 0: Disable global interrupts
145			 3: IRQ 3
146			 4: IRQ 4
147			 5: IRQ 5
148			 9: IRQ 9
149			 10: IRQ 10
150			 11: IRQ 11
151			 12: IRQ 12
152			 15: IRQ 15
153	  Byte_t Frequency: A flag identifying the frequency
154		   of the periodic interrupt, can be any one of the following:
155		      FREQ_DIS - periodic interrupt disabled
156		      FREQ_137HZ - 137 Hertz
157		      FREQ_69HZ - 69 Hertz
158		      FREQ_34HZ - 34 Hertz
159		      FREQ_17HZ - 17 Hertz
160		      FREQ_9HZ - 9 Hertz
161		      FREQ_4HZ - 4 Hertz
162		   If IRQNum is set to 0 the Frequency parameter is
163		   overidden, it is forced to a value of FREQ_DIS.
164	  int PeriodicOnly: TRUE if all interrupts except the periodic
165			       interrupt are to be blocked.
166			    FALSE is both the periodic interrupt and
167			       other channel interrupts are allowed.
168			    If IRQNum is set to 0 the PeriodicOnly parameter is
169			       overidden, it is forced to a value of FALSE.
170Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
171	       initialization failed.
172
173Comments:
174	  If periodic interrupts are to be disabled but AIOP interrupts
175	  are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
176
177	  If interrupts are to be completely disabled set IRQNum to 0.
178
179	  Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
180	  invalid combination.
181
182	  This function performs initialization of global interrupt modes,
183	  but it does not actually enable global interrupts.  To enable
184	  and disable global interrupts use functions sEnGlobalInt() and
185	  sDisGlobalInt().  Enabling of global interrupts is normally not
186	  done until all other initializations are complete.
187
188	  Even if interrupts are globally enabled, they must also be
189	  individually enabled for each channel that is to generate
190	  interrupts.
191
192Warnings: No range checking on any of the parameters is done.
193
194	  No context switches are allowed while executing this function.
195
196	  After this function all AIOPs on the controller are disabled,
197	  they can be enabled with sEnAiop().
198*/
199int sInitController(	CONTROLLER_T *CtlP,
200			int CtlNum,
201			ByteIO_t MudbacIO,
202			ByteIO_t *AiopIOList,
203			int AiopIOListSize,
204			int IRQNum,
205			Byte_t Frequency,
206			int PeriodicOnly)
207{
208	int		i;
209	ByteIO_t	io;
210
211   CtlP->CtlNum = CtlNum;
212   CtlP->BusType = isISA;
213   CtlP->CtlID = CTLID_0001;	    /* controller release 1 */
214
215   CtlP->MBaseIO = MudbacIO;
216   CtlP->MReg1IO = MudbacIO + 1;
217   CtlP->MReg2IO = MudbacIO + 2;
218   CtlP->MReg3IO = MudbacIO + 3;
219#if 1
220   CtlP->MReg2 = 0;		    /* interrupt disable */
221   CtlP->MReg3 = 0;		    /* no periodic interrupts */
222#else
223   if(sIRQMap[IRQNum] == 0)	       /* interrupts globally disabled */
224   {
225      CtlP->MReg2 = 0;		       /* interrupt disable */
226      CtlP->MReg3 = 0;		       /* no periodic interrupts */
227   }
228   else
229   {
230      CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
231      CtlP->MReg3 = Frequency;	       /* set frequency */
232      if(PeriodicOnly)		       /* periodic interrupt only */
233      {
234	 CtlP->MReg3 |= PERIODIC_ONLY;
235      }
236   }
237#endif
238   sOutB(CtlP->MReg2IO,CtlP->MReg2);
239   sOutB(CtlP->MReg3IO,CtlP->MReg3);
240   sControllerEOI(CtlP);	       /* clear EOI if warm init */
241
242   /* Init AIOPs */
243   CtlP->NumAiop = 0;
244   for(i=0; i < AiopIOListSize; i++)
245   {
246      io = AiopIOList[i];
247      CtlP->AiopIO[i] = (WordIO_t)io;
248      CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
249      sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
250      sOutB(MudbacIO,(Byte_t)(io >> 6));	/* set up AIOP I/O in MUDBAC */
251      sEnAiop(CtlP,i);			       /* enable the AIOP */
252
253      CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
254      if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
255      {
256	 sDisAiop(CtlP,i);		       /* disable AIOP */
257	 break; 			       /* done looking for AIOPs */
258      }
259
260      CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
261      sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
262      sOutB(io + _INDX_DATA,CLOCK_PRESC);
263      CtlP->NumAiop++;			       /* bump count of AIOPs */
264      sDisAiop(CtlP,i); 		       /* disable AIOP */
265   }
266
267   if(CtlP->NumAiop == 0)
268      return(-1);
269   else
270      return(CtlP->NumAiop);
271}
272
273int sPCIInitController( CONTROLLER_T *CtlP,
274			int CtlNum,
275			ByteIO_t *AiopIOList,
276			int AiopIOListSize,
277			int IRQNum,
278			Byte_t Frequency,
279			int PeriodicOnly)
280{
281	int		i;
282	ByteIO_t	io;
283
284   CtlP->CtlNum = CtlNum;
285   CtlP->BusType = isPCI;
286   CtlP->CtlID = CTLID_0001;	    /* controller release 1 */
287   CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
288
289   sPCIControllerEOI(CtlP);
290
291   /* Init AIOPs */
292   CtlP->NumAiop = 0;
293   for(i=0; i < AiopIOListSize; i++)
294   {
295      io = AiopIOList[i];
296      CtlP->AiopIO[i] = (WordIO_t)io;
297      CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
298
299      CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
300      if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
301      {
302	 break; 			       /* done looking for AIOPs */
303      }
304
305      CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
306      sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
307      sOutB(io + _INDX_DATA,CLOCK_PRESC);
308      CtlP->NumAiop++;			       /* bump count of AIOPs */
309   }
310
311   if(CtlP->NumAiop == 0)
312      return(-1);
313   else
314      return(CtlP->NumAiop);
315}
316
317/***************************************************************************
318Function: sReadAiopID
319Purpose:  Read the AIOP idenfication number directly from an AIOP.
320Call:	  sReadAiopID(io)
321	  ByteIO_t io: AIOP base I/O address
322Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
323		 is replace by an identifying number.
324	  Flag AIOPID_NULL if no valid AIOP is found
325Warnings: No context switches are allowed while executing this function.
326
327*/
328int sReadAiopID(ByteIO_t io)
329{
330   Byte_t AiopID;		/* ID byte from AIOP */
331
332   sOutB(io + _CMD_REG,RESET_ALL);     /* reset AIOP */
333   sOutB(io + _CMD_REG,0x0);
334   AiopID = sInB(io + _CHN_STAT0) & 0x07;
335   if(AiopID == 0x06)
336      return(1);
337   else 			       /* AIOP does not exist */
338      return(-1);
339}
340
341/***************************************************************************
342Function: sReadAiopNumChan
343Purpose:  Read the number of channels available in an AIOP directly from
344	  an AIOP.
345Call:	  sReadAiopNumChan(io)
346	  WordIO_t io: AIOP base I/O address
347Return:   int: The number of channels available
348Comments: The number of channels is determined by write/reads from identical
349	  offsets within the SRAM address spaces for channels 0 and 4.
350	  If the channel 4 space is mirrored to channel 0 it is a 4 channel
351	  AIOP, otherwise it is an 8 channel.
352Warnings: No context switches are allowed while executing this function.
353*/
354int sReadAiopNumChan(WordIO_t io)
355{
356   Word_t x;
357
358   sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
359   sOutW(io + _INDX_ADDR,0);	   /* read from SRAM, chan 0 */
360   x = sInW(io + _INDX_DATA);
361   sOutW(io + _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
362   if(x != sInW(io + _INDX_DATA))  /* if different must be 8 chan */
363      return(8);
364   else
365      return(4);
366}
367
368/***************************************************************************
369Function: sInitChan
370Purpose:  Initialization of a channel and channel structure
371Call:	  sInitChan(CtlP,ChP,AiopNum,ChanNum)
372	  CONTROLLER_T *CtlP; Ptr to controller structure
373	  CHANNEL_T *ChP; Ptr to channel structure
374	  int AiopNum; AIOP number within controller
375	  int ChanNum; Channel number within AIOP
376Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
377	       number exceeds number of channels available in AIOP.
378Comments: This function must be called before a channel can be used.
379Warnings: No range checking on any of the parameters is done.
380
381	  No context switches are allowed while executing this function.
382*/
383int sInitChan(	CONTROLLER_T *CtlP,
384		CHANNEL_T *ChP,
385		int AiopNum,
386		int ChanNum)
387{
388   int i;
389   WordIO_t AiopIO;
390   WordIO_t ChIOOff;
391   Byte_t *ChR;
392   Word_t ChOff;
393   static Byte_t R[4];
394
395   if(ChanNum >= CtlP->AiopNumChan[AiopNum])
396      return(FALSE);		       /* exceeds num chans in AIOP */
397
398   /* Channel, AIOP, and controller identifiers */
399   ChP->CtlP = CtlP;
400   ChP->ChanID = CtlP->AiopID[AiopNum];
401   ChP->AiopNum = AiopNum;
402   ChP->ChanNum = ChanNum;
403
404   /* Global direct addresses */
405   AiopIO = CtlP->AiopIO[AiopNum];
406   ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
407   ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
408   ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
409   ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
410   ChP->IndexData = AiopIO + _INDX_DATA;
411
412   /* Channel direct addresses */
413   ChIOOff = AiopIO + ChP->ChanNum * 2;
414   ChP->TxRxData = ChIOOff + _TD0;
415   ChP->ChanStat = ChIOOff + _CHN_STAT0;
416   ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
417   ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
418
419   /* Initialize the channel from the RData array */
420   for(i=0; i < RDATASIZE; i+=4)
421   {
422      R[0] = RData[i];
423      R[1] = RData[i+1] + 0x10 * ChanNum;
424      R[2] = RData[i+2];
425      R[3] = RData[i+3];
426      sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
427   }
428
429   ChR = ChP->R;
430   for(i=0; i < RREGDATASIZE; i+=4)
431   {
432      ChR[i] = RRegData[i];
433      ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
434      ChR[i+2] = RRegData[i+2];
435      ChR[i+3] = RRegData[i+3];
436   }
437
438   /* Indexed registers */
439   ChOff = (Word_t)ChanNum * 0x1000;
440
441   ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
442   ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
443   ChP->BaudDiv[2] = (Byte_t)BRD9600;
444   ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
445   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
446
447   ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
448   ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
449   ChP->TxControl[2] = 0;
450   ChP->TxControl[3] = 0;
451   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
452
453   ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
454   ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
455   ChP->RxControl[2] = 0;
456   ChP->RxControl[3] = 0;
457   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
458
459   ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
460   ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
461   ChP->TxEnables[2] = 0;
462   ChP->TxEnables[3] = 0;
463   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
464
465   ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
466   ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
467   ChP->TxCompare[2] = 0;
468   ChP->TxCompare[3] = 0;
469   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
470
471   ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
472   ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
473   ChP->TxReplace1[2] = 0;
474   ChP->TxReplace1[3] = 0;
475   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
476
477   ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
478   ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
479   ChP->TxReplace2[2] = 0;
480   ChP->TxReplace2[3] = 0;
481   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
482
483   ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
484   ChP->TxFIFO = ChOff + _TX_FIFO;
485
486   sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
487   sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
488   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
489   sOutW(ChP->IndexData,0);
490   ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
491   ChP->RxFIFO = ChOff + _RX_FIFO;
492
493   sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
494   sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
495   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
496   sOutW(ChP->IndexData,0);
497   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
498   sOutW(ChP->IndexData,0);
499   ChP->TxPrioCnt = ChOff + _TXP_CNT;
500   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
501   sOutB(ChP->IndexData,0);
502   ChP->TxPrioPtr = ChOff + _TXP_PNTR;
503   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
504   sOutB(ChP->IndexData,0);
505   ChP->TxPrioBuf = ChOff + _TXP_BUF;
506   sEnRxProcessor(ChP); 	       /* start the Rx processor */
507
508   return(TRUE);
509}
510
511/***************************************************************************
512Function: sStopRxProcessor
513Purpose:  Stop the receive processor from processing a channel.
514Call:	  sStopRxProcessor(ChP)
515	  CHANNEL_T *ChP; Ptr to channel structure
516
517Comments: The receive processor can be started again with sStartRxProcessor().
518	  This function causes the receive processor to skip over the
519	  stopped channel.  It does not stop it from processing other channels.
520
521Warnings: No context switches are allowed while executing this function.
522
523	  Do not leave the receive processor stopped for more than one
524	  character time.
525
526	  After calling this function a delay of 4 uS is required to ensure
527	  that the receive processor is no longer processing this channel.
528*/
529void sStopRxProcessor(CHANNEL_T *ChP)
530{
531   Byte_t R[4];
532
533   R[0] = ChP->R[0];
534   R[1] = ChP->R[1];
535   R[2] = 0x0a;
536   R[3] = ChP->R[3];
537   sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
538}
539
540/***************************************************************************
541Function: sFlushRxFIFO
542Purpose:  Flush the Rx FIFO
543Call:	  sFlushRxFIFO(ChP)
544	  CHANNEL_T *ChP; Ptr to channel structure
545Return:   void
546Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
547	  while it is being flushed the receive processor is stopped
548	  and the transmitter is disabled.  After these operations a
549	  4 uS delay is done before clearing the pointers to allow
550	  the receive processor to stop.  These items are handled inside
551	  this function.
552Warnings: No context switches are allowed while executing this function.
553*/
554void sFlushRxFIFO(CHANNEL_T *ChP)
555{
556   int i;
557   Byte_t Ch;			/* channel number within AIOP */
558   int RxFIFOEnabled;		       /* TRUE if Rx FIFO enabled */
559
560   if(sGetRxCnt(ChP) == 0)	       /* Rx FIFO empty */
561      return;			       /* don't need to flush */
562
563   RxFIFOEnabled = FALSE;
564   if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
565   {
566      RxFIFOEnabled = TRUE;
567      sDisRxFIFO(ChP);		       /* disable it */
568      for(i=0; i < 2000/200; i++)	/* delay 2 uS to allow proc to disable FIFO*/
569	 sInB(ChP->IntChan);		/* depends on bus i/o timing */
570   }
571   sGetChanStatus(ChP); 	 /* clear any pending Rx errors in chan stat */
572   Ch = (Byte_t)sGetChanNum(ChP);
573   sOutB(ChP->Cmd,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
574   sOutB(ChP->Cmd,Ch);		       /* remove reset Rx FIFO count */
575   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
576   sOutW(ChP->IndexData,0);
577   sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
578   sOutW(ChP->IndexData,0);
579   if(RxFIFOEnabled)
580      sEnRxFIFO(ChP);		       /* enable Rx FIFO */
581}
582
583/***************************************************************************
584Function: sFlushTxFIFO
585Purpose:  Flush the Tx FIFO
586Call:	  sFlushTxFIFO(ChP)
587	  CHANNEL_T *ChP; Ptr to channel structure
588Return:   void
589Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
590	  while it is being flushed the receive processor is stopped
591	  and the transmitter is disabled.  After these operations a
592	  4 uS delay is done before clearing the pointers to allow
593	  the receive processor to stop.  These items are handled inside
594	  this function.
595Warnings: No context switches are allowed while executing this function.
596*/
597void sFlushTxFIFO(CHANNEL_T *ChP)
598{
599   int i;
600   Byte_t Ch;			/* channel number within AIOP */
601   int TxEnabled;		       /* TRUE if transmitter enabled */
602
603   if(sGetTxCnt(ChP) == 0)	       /* Tx FIFO empty */
604      return;			       /* don't need to flush */
605
606   TxEnabled = FALSE;
607   if(ChP->TxControl[3] & TX_ENABLE)
608   {
609      TxEnabled = TRUE;
610      sDisTransmit(ChP);	       /* disable transmitter */
611   }
612   sStopRxProcessor(ChP);	       /* stop Rx processor */
613   for(i = 0; i < 4000/200; i++)	 /* delay 4 uS to allow proc to stop */
614      sInB(ChP->IntChan);	/* depends on bus i/o timing */
615   Ch = (Byte_t)sGetChanNum(ChP);
616   sOutB(ChP->Cmd,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
617   sOutB(ChP->Cmd,Ch);		       /* remove reset Tx FIFO count */
618   sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
619   sOutW(ChP->IndexData,0);
620   if(TxEnabled)
621      sEnTransmit(ChP); 	       /* enable transmitter */
622   sStartRxProcessor(ChP);	       /* restart Rx processor */
623}
624
625/***************************************************************************
626Function: sWriteTxPrioByte
627Purpose:  Write a byte of priority transmit data to a channel
628Call:	  sWriteTxPrioByte(ChP,Data)
629	  CHANNEL_T *ChP; Ptr to channel structure
630	  Byte_t Data; The transmit data byte
631
632Return:   int: 1 if the bytes is successfully written, otherwise 0.
633
634Comments: The priority byte is transmitted before any data in the Tx FIFO.
635
636Warnings: No context switches are allowed while executing this function.
637*/
638int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
639{
640   Byte_t DWBuf[4];		/* buffer for double word writes */
641   Word_t *WordPtr;	     /* must be far because Win SS != DS */
642   register DWordIO_t IndexAddr;
643
644   if(sGetTxCnt(ChP) > 1)	       /* write it to Tx priority buffer */
645   {
646      IndexAddr = ChP->IndexAddr;
647      sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
648      if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
649	 return(0);		       /* nothing sent */
650
651      WordPtr = (Word_t *)(&DWBuf[0]);
652      *WordPtr = ChP->TxPrioBuf;       /* data byte address */
653
654      DWBuf[2] = Data;		       /* data byte value */
655      sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
656
657      *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
658
659      DWBuf[2] = PRI_PEND + 1;	       /* indicate 1 byte pending */
660      DWBuf[3] = 0;		       /* priority buffer pointer */
661      sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
662   }
663   else 			       /* write it to Tx FIFO */
664   {
665      sWriteTxByte(sGetTxRxDataIO(ChP),Data);
666   }
667   return(1);			       /* 1 byte sent */
668}
669
670/***************************************************************************
671Function: sEnInterrupts
672Purpose:  Enable one or more interrupts for a channel
673Call:	  sEnInterrupts(ChP,Flags)
674	  CHANNEL_T *ChP; Ptr to channel structure
675	  Word_t Flags: Interrupt enable flags, can be any combination
676	     of the following flags:
677		TXINT_EN:   Interrupt on Tx FIFO empty
678		RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
679			    sSetRxTrigger())
680		SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
681		MCINT_EN:   Interrupt on modem input change
682		CHANINT_EN: Allow channel interrupt signal to the AIOP's
683			    Interrupt Channel Register.
684Return:   void
685Comments: If an interrupt enable flag is set in Flags, that interrupt will be
686	  enabled.  If an interrupt enable flag is not set in Flags, that
687	  interrupt will not be changed.  Interrupts can be disabled with
688	  function sDisInterrupts().
689
690	  This function sets the appropriate bit for the channel in the AIOP's
691	  Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
692	  this channel's bit to be set in the AIOP's Interrupt Channel Register.
693
694	  Interrupts must also be globally enabled before channel interrupts
695	  will be passed on to the host.  This is done with function
696	  sEnGlobalInt().
697
698	  In some cases it may be desirable to disable interrupts globally but
699	  enable channel interrupts.  This would allow the global interrupt
700	  status register to be used to determine which AIOPs need service.
701*/
702void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
703{
704   Byte_t Mask; 		/* Interrupt Mask Register */
705
706   ChP->RxControl[2] |=
707      ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
708
709   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
710
711   ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
712
713   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
714
715   if(Flags & CHANINT_EN)
716   {
717      Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
718      sOutB(ChP->IntMask,Mask);
719   }
720}
721
722/***************************************************************************
723Function: sDisInterrupts
724Purpose:  Disable one or more interrupts for a channel
725Call:	  sDisInterrupts(ChP,Flags)
726	  CHANNEL_T *ChP; Ptr to channel structure
727	  Word_t Flags: Interrupt flags, can be any combination
728	     of the following flags:
729		TXINT_EN:   Interrupt on Tx FIFO empty
730		RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
731			    sSetRxTrigger())
732		SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
733		MCINT_EN:   Interrupt on modem input change
734		CHANINT_EN: Disable channel interrupt signal to the
735			    AIOP's Interrupt Channel Register.
736Return:   void
737Comments: If an interrupt flag is set in Flags, that interrupt will be
738	  disabled.  If an interrupt flag is not set in Flags, that
739	  interrupt will not be changed.  Interrupts can be enabled with
740	  function sEnInterrupts().
741
742	  This function clears the appropriate bit for the channel in the AIOP's
743	  Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
744	  this channel's bit from being set in the AIOP's Interrupt Channel
745	  Register.
746*/
747void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
748{
749   Byte_t Mask; 		/* Interrupt Mask Register */
750
751   ChP->RxControl[2] &=
752	 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
753   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
754   ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
755   sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
756
757   if(Flags & CHANINT_EN)
758   {
759      Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
760      sOutB(ChP->IntMask,Mask);
761   }
762}
763
764/*********************************************************************
765  Begin FreeBsd-specific driver code
766**********************************************************************/
767
768static int rpprobe __P((struct isa_device *));
769static int rpattach __P((struct isa_device *));
770
771static char* rp_pciprobe(pcici_t tag, pcidi_t type);
772static void rp_pciattach(pcici_t tag, int unit);
773static u_long	rp_pcicount;
774
775static struct pci_device rp_pcidevice = {
776	"rp",
777	rp_pciprobe,
778	rp_pciattach,
779	&rp_pcicount,
780	NULL
781};
782
783DATA_SET (pcidevice_set, rp_pcidevice);
784
785static timeout_t rpdtrwakeup;
786
787struct isa_driver rpdriver = {
788	rpprobe, rpattach, "rp"
789     };
790
791static	char	driver_name[] = "rp";
792
793static	d_open_t	rpopen;
794static	d_close_t	rpclose;
795static	d_read_t	rpread;
796static	d_write_t	rpwrite;
797static	d_ioctl_t	rpioctl;
798static	d_stop_t	rpstop;
799static	d_devtotty_t	rpdevtotty;
800
801#define	CDEV_MAJOR	81
802static	struct cdevsw	rp_cdevsw = {
803	rpopen,		rpclose,	rpread,		rpwrite,
804	rpioctl,	rpstop,		noreset,	rpdevtotty,
805	ttpoll,		nommap,		NULL,		driver_name,
806	NULL,		-1,		nodump,		nopsize,
807	D_TTY,
808};
809
810static int rp_controller_port = 0;
811static int rp_num_ports_open = 0;
812static int	ndevs = 0;
813static int	minor_to_unit[128];
814#if 0
815static	struct	tty	rp_tty[128];
816#endif
817
818static int rp_num_ports[4];	/* Number of ports on each controller */
819
820#define _INLINE_ __inline
821#define POLL_INTERVAL 1
822
823#define CALLOUT_MASK		0x80
824#define CONTROL_MASK		0x60
825#define CONTROL_INIT_STATE	0x20
826#define CONTROL_LOCK_STATE	0x40
827#define DEV_UNIT(dev)	(MINOR_TO_UNIT(minor(dev))
828#define MINOR_MAGIC_MASK	(CALLOUT_MASK | CONTROL_MASK)
829#define MINOR_MAGIC(dev)	((minor(dev)) & ~MINOR_MAGIC_MASK)
830#define IS_CALLOUT(dev) 	(minor(dev) & CALLOUT_MASK)
831#define IS_CONTROL(dev) 	(minor(dev) & CONTROL_MASK)
832
833#define RP_ISMULTIPORT(dev)	((dev)->id_flags & 0x1)
834#define RP_MPMASTER(dev)	(((dev)->id_flags >> 8) & 0xff)
835#define RP_NOTAST4(dev) 	((dev)->id_flags & 0x04)
836
837static	struct	rp_port *p_rp_addr[4];
838static	struct	rp_port *p_rp_table[MAX_RP_PORTS];
839#define rp_addr(unit)	(p_rp_addr[unit])
840#define rp_table(port)	(p_rp_table[port])
841
842/*
843 * The top-level routines begin here
844 */
845
846int	rpselect __P((dev_t, int, struct proc *));
847
848static	int	rpparam __P((struct tty *, struct termios *));
849static	void	rpstart __P((struct tty *));
850static	void	rphardclose	__P((struct rp_port *));
851#define rpmap	nomap
852#define rpreset noreset
853#define rpstrategy	nostrategy
854static	void	rp_disc_optim	__P((struct tty *tp, struct termios *t,
855						struct rp_port	*rp));
856
857static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
858			CHANNEL_t *cp, unsigned int ChanStatus)
859{
860	int	spl;
861	unsigned	int	CharNStat;
862	int	ToRecv, ch;
863
864	ToRecv = sGetRxCnt(cp);
865	if(ToRecv == 0)
866		return;
867
868/*	If status indicates there are errored characters in the
869	FIFO, then enter status mode (a word in FIFO holds
870	characters and status)
871*/
872
873	if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
874		if(!(ChanStatus & STATMODE)) {
875			ChanStatus |= STATMODE;
876			sEnRxStatusMode(cp);
877		}
878	}
879/*
880	if we previously entered status mode then read down the
881	FIFO one word at a time, pulling apart the character and
882	the status. Update error counters depending on status.
883*/
884	if(ChanStatus & STATMODE) {
885		while(ToRecv) {
886			if(tp->t_state & TS_TBLOCK) {
887				break;
888			}
889			CharNStat = sInW(sGetTxRxDataIO(cp));
890			ch = CharNStat & 0xff;
891
892			if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
893				ch |= TTY_FE;
894			else if (CharNStat & STMPARITYH)
895				ch |= TTY_PE;
896			else if (CharNStat & STMRCVROVRH)
897				rp->rp_overflows++;
898
899			(*linesw[tp->t_line].l_rint)(ch, tp);
900			ToRecv--;
901		}
902/*
903	After emtying FIFO in status mode, turn off status mode
904*/
905
906	if(sGetRxCnt(cp) == 0)
907		sDisRxStatusMode(cp);
908	}
909	else {
910		while (ToRecv) {
911			if(tp->t_state & TS_TBLOCK) {
912				break;
913			}
914			ch = (u_char) sInB(sGetTxRxDataIO(cp));
915			spl = spltty();
916			(*linesw[tp->t_line].l_rint)(ch, tp);
917			splx(spl);
918			ToRecv--;
919		}
920	}
921}
922
923static _INLINE_ void rp_handle_port(struct rp_port *rp)
924{
925	CHANNEL_t	*cp;
926	struct	tty	*tp;
927	unsigned	int	IntMask, ChanStatus;
928     /*	int	oldcts; */
929
930	if(!rp)
931		return;
932
933	cp = &rp->rp_channel;
934	tp = rp->rp_tty;
935	IntMask = sGetChanIntID(cp);
936	IntMask = IntMask & rp->rp_intmask;
937	ChanStatus = sGetChanStatus(cp);
938	if(IntMask & RXF_TRIG)
939		if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
940			rp_do_receive(rp, tp, cp, ChanStatus);
941		}
942	if(IntMask & DELTA_CD) {
943		if(ChanStatus & CD_ACT) {
944			if(!(tp->t_state & TS_CARR_ON) ) {
945				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
946			}
947		} else {
948			if((tp->t_state & TS_CARR_ON)) {
949				(void)(*linesw[tp->t_line].l_modem)(tp, 0);
950				if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
951					rphardclose(rp);
952				}
953			}
954		}
955	}
956/*	oldcts = rp->rp_cts;
957	rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
958	if(oldcts != rp->rp_cts) {
959		printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
960	}
961*/
962}
963
964static void rp_do_poll(void *not_used)
965{
966	CONTROLLER_t	*ctl;
967	struct rp_port	*rp;
968	struct tty	*tp;
969	int	unit, aiop, ch, line, count;
970	unsigned char	CtlMask, AiopMask;
971
972	for(unit = 0; unit <= ndevs; unit++) {
973	rp = rp_addr(unit);
974	ctl = rp->rp_ctlp;
975	if(ctl->BusType == isPCI)
976		CtlMask = sPCIGetControllerIntStatus(ctl);
977	else
978		CtlMask = sGetControllerIntStatus(ctl);
979	for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
980		if(CtlMask & 1) {
981			AiopMask = sGetAiopIntStatus(ctl, aiop);
982			for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
983				if(AiopMask & 1) {
984					line = (unit << 5) | (aiop << 3) | ch;
985					rp = rp_table(line);
986					rp_handle_port(rp);
987				}
988			}
989		}
990	}
991
992	for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
993			line++, rp++) {
994		tp = rp->rp_tty;
995		if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
996			count = sGetTxCnt(&rp->rp_channel);
997			if(count == 0)
998				tp->t_state &= ~(TS_BUSY);
999			if(!(tp->t_state & TS_TTSTOP) &&
1000				(count <= rp->rp_restart)) {
1001				(*linesw[tp->t_line].l_start)(tp);
1002			}
1003		}
1004	}
1005	}
1006	if(rp_num_ports_open)
1007		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1008}
1009
1010static char*
1011rp_pciprobe(pcici_t tag, pcidi_t type)
1012{
1013	int	vendor_id;
1014
1015	vendor_id = type & 0xffff;
1016	switch(vendor_id)
1017	case 0x11fe:
1018		return("rp");
1019	return(NULL);
1020}
1021
1022static
1023int
1024rpprobe(dev)
1025struct isa_device *dev;
1026{
1027	int controller, unit;
1028	int aiop, num_aiops;
1029	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1030	CONTROLLER_t *ctlp;
1031
1032	unit = dev->id_unit;
1033	if (dev->id_unit >= 4) {
1034		printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1035		return 1;
1036	}
1037	printf("probing for RocketPort(ISA) unit %d\n", unit);
1038	if (rp_controller_port)
1039		controller = rp_controller_port;
1040	else {
1041		controller = dev->id_iobase + 0x40;
1042	}
1043
1044	for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1045		aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1046
1047	ctlp = sCtlNumToCtlPtr(dev->id_unit);
1048	num_aiops = sInitController(ctlp, dev->id_unit,
1049				controller + ((unit-rp_pcicount)*0x400),
1050				aiopio, MAX_AIOPS_PER_BOARD, 0,
1051				FREQ_DIS, 0);
1052	if (num_aiops <= 0) {
1053		printf("board%d init failed\n", unit);
1054		return 0;
1055	}
1056
1057	if (rp_controller_port) {
1058		dev->id_msize = 64;
1059	} else {
1060		dev->id_msize = 68;
1061		rp_controller_port = controller;
1062	}
1063
1064	dev->id_irq = 0;
1065
1066	return 1;
1067}
1068
1069static void
1070rp_pciattach(pcici_t tag, int unit)
1071{
1072	dev_t	rp_dev;
1073	int	success, oldspl;
1074	u_short iobase;
1075	int	num_ports, num_chan, num_aiops;
1076	int	aiop, chan, port;
1077	int	ChanStatus, line, i, count;
1078	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1079	struct	rp_port *rp;
1080	struct	tty	*tty;
1081	CONTROLLER_t	*ctlp;
1082
1083	success = pci_map_port(tag, 0x10, &iobase);
1084	if(!success)
1085		printf("ioaddr mapping failed for RocketPort(PCI)\n");
1086
1087	for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1088		aiopio[aiop] = iobase + (aiop * 0x40);
1089
1090	ctlp = sCtlNumToCtlPtr(unit);
1091	num_aiops = sPCIInitController(ctlp, unit,
1092				aiopio, MAX_AIOPS_PER_BOARD, 0,
1093				FREQ_DIS, 0);
1094
1095	num_ports = 0;
1096	for(aiop=0; aiop < num_aiops; aiop++) {
1097		sResetAiopByNum(ctlp, aiop);
1098		num_ports += sGetAiopNumChan(ctlp, aiop);
1099	}
1100	printf("RocketPort%d = %d ports\n", unit, num_ports);
1101	rp_num_ports[unit] = num_ports;
1102
1103	rp = (struct rp_port *)
1104		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1105	if(rp == 0) {
1106		printf("rp_attach: Could not malloc rp_ports structures\n");
1107		return;
1108	}
1109
1110	count = unit * 32;      /* board times max ports per card SG */
1111	for(i=count;i < (count + rp_num_ports[unit]);i++)
1112		minor_to_unit[i] = unit;
1113
1114	bzero(rp, sizeof(struct rp_port) * num_ports);
1115	tty = (struct tty *)
1116		malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1117	if(tty == 0) {
1118		printf("rp_attach: Could not malloc tty structures\n");
1119		return;
1120	}
1121	bzero(tty, sizeof(struct tty) * num_ports);
1122
1123	oldspl = spltty();
1124	rp_addr(unit) = rp;
1125	splx(oldspl);
1126
1127	rp_dev = makedev(CDEV_MAJOR, unit);
1128	cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1129
1130	port = 0;
1131	for(aiop=0; aiop < num_aiops; aiop++) {
1132		num_chan = sGetAiopNumChan(ctlp, aiop);
1133		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1134			rp->rp_tty = tty;
1135			rp->rp_port = port;
1136			rp->rp_ctlp = ctlp;
1137			rp->rp_unit = unit;
1138			rp->rp_chan = chan;
1139			rp->rp_aiop = aiop;
1140
1141			tty->t_line = 0;
1142	/*		tty->t_termios = deftermios;
1143	*/
1144			rp->dtr_wait = 3 * hz;
1145			rp->it_in.c_iflag = 0;
1146			rp->it_in.c_oflag = 0;
1147			rp->it_in.c_cflag = TTYDEF_CFLAG;
1148			rp->it_in.c_lflag = 0;
1149			termioschars(&rp->it_in);
1150	/*		termioschars(&tty->t_termios);
1151	*/
1152			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1153			rp->it_out = rp->it_in;
1154
1155			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1156				DELTA_CD | DELTA_CTS | DELTA_DSR;
1157			ChanStatus = sGetChanStatus(&rp->rp_channel);
1158			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1159				printf("RocketPort sInitChan(%d, %d, %d) failed
1160					\n", unit, aiop, chan);
1161				return;
1162			}
1163			ChanStatus = sGetChanStatus(&rp->rp_channel);
1164			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1165			line = (unit << 5) | (aiop << 3) | chan;
1166			rp_table(line) = rp;
1167/*			devfs_add_devswf(&rp_cdevsw,
1168				port, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
1169				"ttyR%r", port);
1170			devfs_add_devswf(&rp_cdevsw,
1171				port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT,
1172				GID_WHEEL, 0600, "ttyRi%r", port);
1173*/
1174		}
1175	}
1176}
1177
1178static
1179int
1180rpattach(dev)
1181struct	isa_device	*dev;
1182{
1183	struct	isa_device	*idev;
1184	dev_t	rp_dev;
1185	int	iobase, unit, /*rpmajor,*/ oldspl;
1186	int	num_ports, num_chan, num_aiops;
1187	int	aiop, chan, port;
1188	int	ChanStatus, line, i, count;
1189	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];
1190	struct	rp_port *rp;
1191	struct	tty	*tty;
1192	CONTROLLER_t	*ctlp;
1193
1194	iobase = dev->id_iobase;
1195	unit = dev->id_unit;
1196	ndevs = unit;
1197
1198	for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1199		aiopio[aiop] = iobase + (aiop * 0x400);
1200
1201	ctlp = sCtlNumToCtlPtr(unit);
1202	num_aiops = sInitController(ctlp, unit,
1203				rp_controller_port + ((unit-rp_pcicount) * 0x400),
1204				aiopio, MAX_AIOPS_PER_BOARD, 0,
1205				FREQ_DIS, 0);
1206
1207	num_ports = 0;
1208	for(aiop=0; aiop < num_aiops; aiop++) {
1209		sResetAiopByNum(ctlp, aiop);
1210		sEnAiop(ctlp, aiop);
1211		num_ports += sGetAiopNumChan(ctlp, aiop);
1212	}
1213	printf("RocketPort%d = %d ports\n", unit, num_ports);
1214	rp_num_ports[unit] = num_ports;
1215
1216	rp = (struct rp_port *)
1217		malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1218	if(rp == 0) {
1219		printf("rp_attach: Could not malloc rp_ports structures\n");
1220		return(0);
1221	}
1222
1223	count = unit * 32;    /* board # times max ports per card  SG */
1224	for(i=count;i < (count + rp_num_ports[unit]);i++)
1225		minor_to_unit[i] = unit;
1226
1227	bzero(rp, sizeof(struct rp_port) * num_ports);
1228	tty = (struct tty *)
1229		malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1230	if(tty == 0) {
1231		printf("rp_attach: Could not malloc tty structures\n");
1232		return(0);
1233	}
1234	bzero(tty, sizeof(struct tty) * num_ports);
1235
1236	oldspl = spltty();
1237	rp_addr(unit) = rp;
1238	splx(oldspl);
1239
1240	rp_dev = makedev(CDEV_MAJOR, unit);
1241	cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1242
1243	port = 0;
1244	for(aiop=0; aiop < num_aiops; aiop++) {
1245		num_chan = sGetAiopNumChan(ctlp, aiop);
1246		for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1247			rp->rp_tty = tty;
1248			rp->rp_port = port;
1249			rp->rp_ctlp = ctlp;
1250			rp->rp_unit = unit;
1251			rp->rp_chan = chan;
1252			rp->rp_aiop = aiop;
1253
1254			tty->t_line = 0;
1255	/*		tty->t_termios = deftermios;
1256	*/
1257			rp->dtr_wait = 3 * hz;
1258			rp->it_in.c_iflag = 0;
1259			rp->it_in.c_oflag = 0;
1260			rp->it_in.c_cflag = TTYDEF_CFLAG;
1261			rp->it_in.c_lflag = 0;
1262			termioschars(&rp->it_in);
1263	/*		termioschars(&tty->t_termios);
1264	*/
1265			rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1266			rp->it_out = rp->it_in;
1267
1268			rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1269				DELTA_CD | DELTA_CTS | DELTA_DSR;
1270			ChanStatus = sGetChanStatus(&rp->rp_channel);
1271			if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1272				printf("RocketPort sInitChan(%d, %d, %d) failed
1273					\n", unit, aiop, chan);
1274				return(0);
1275			}
1276			ChanStatus = sGetChanStatus(&rp->rp_channel);
1277			rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1278			line = (unit << 5) | (aiop << 3) | chan;
1279			rp_table(line) = rp;
1280		}
1281	}
1282
1283		idev = find_isadev(isa_devtab_tty, &rpdriver,
1284				RP_MPMASTER(dev) + rp_pcicount);
1285		if(idev == NULL) {
1286			printf("rp%d: master device %d not configured\n",
1287				dev->id_unit, RP_MPMASTER(dev));
1288		}
1289/*		printf("COOL!! Device is found!!\n");
1290	for(rpmajor=0;rpmajor<nchrdev;rpmajor++)
1291		if(cdevsw[rpmajor].d_open == rpopen)
1292			printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor);
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 && p->p_ucred->cr_uid != 0) {
1350			splx(oldspl);
1351			return(EBUSY);
1352		}
1353	}
1354	else {
1355		tp->t_dev = dev;
1356		tp->t_param = rpparam;
1357		tp->t_oproc = rpstart;
1358		tp->t_line = 0;
1359		tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1360		flags = 0;
1361		flags |= SET_RTS;
1362		flags |= SET_DTR;
1363		rp->rp_channel.TxControl[3] =
1364			((rp->rp_channel.TxControl[3]
1365			& ~(SET_RTS | SET_DTR)) | flags);
1366		sOutDW(rp->rp_channel.IndexAddr,
1367			*(DWord_t *) &(rp->rp_channel.TxControl[0]));
1368		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1369		sDisRxStatusMode(&rp->rp_channel);
1370		sFlushRxFIFO(&rp->rp_channel);
1371		sFlushTxFIFO(&rp->rp_channel);
1372
1373		sEnInterrupts(&rp->rp_channel,
1374			(TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1375		sSetRxTrigger(&rp->rp_channel, TRIG_1);
1376
1377		sDisRxStatusMode(&rp->rp_channel);
1378		sClrTxXOFF(&rp->rp_channel);
1379
1380/*		sDisRTSFlowCtl(&rp->rp_channel);
1381		sDisCTSFlowCtl(&rp->rp_channel);
1382*/
1383		sDisTxSoftFlowCtl(&rp->rp_channel);
1384
1385		sStartRxProcessor(&rp->rp_channel);
1386
1387		sEnRxFIFO(&rp->rp_channel);
1388		sEnTransmit(&rp->rp_channel);
1389
1390/*		sSetDTR(&rp->rp_channel);
1391		sSetRTS(&rp->rp_channel);
1392*/
1393
1394		++rp->wopeners;
1395		error = rpparam(tp, &tp->t_termios);
1396		--rp->wopeners;
1397		if(error != 0) {
1398			splx(oldspl);
1399			return(error);
1400		}
1401
1402		rp_num_ports_open++;
1403
1404		IntMask = sGetChanIntID(&rp->rp_channel);
1405		IntMask = IntMask & rp->rp_intmask;
1406		ChanStatus = sGetChanStatus(&rp->rp_channel);
1407		if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1408			if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1409					(void)(*linesw[tp->t_line].l_modem)(tp, 1);
1410			}
1411		}
1412
1413	if(rp_num_ports_open == 1)
1414		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1415
1416	}
1417
1418	if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1419		!(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1420		++rp->wopeners;
1421		error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1422				"rpdcd", 0);
1423		--rp->wopeners;
1424		if(error != 0)
1425			goto out;
1426		goto open_top;
1427	}
1428	error = (*linesw[tp->t_line].l_open)(dev, tp);
1429
1430	rp_disc_optim(tp, &tp->t_termios, rp);
1431	if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1432		rp->active_out = TRUE;
1433
1434/*	if(rp_num_ports_open == 1)
1435		timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1436*/
1437out:
1438	splx(oldspl);
1439	if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1440		rphardclose(rp);
1441	}
1442	return(error);
1443}
1444
1445int
1446rpclose(dev, flag, mode, p)
1447	dev_t	dev;
1448	int	flag, mode;
1449	struct	proc	*p;
1450{
1451	int	oldspl, unit, mynor, umynor, port; /* SG */
1452	struct	rp_port *rp;
1453	struct	tty	*tp;
1454	CHANNEL_t	*cp;
1455
1456   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1457	port  = (minor(dev) & 0x1f);                /* SG */
1458	mynor = (port + umynor);                    /* SG */
1459   unit = minor_to_unit[mynor];                /* SG */
1460
1461	if(IS_CONTROL(dev))
1462		return(0);
1463	rp = rp_addr(unit) + port;
1464	cp = &rp->rp_channel;
1465	tp = rp->rp_tty;
1466
1467	oldspl = spltty();
1468	(*linesw[tp->t_line].l_close)(tp, flag);
1469	rp_disc_optim(tp, &tp->t_termios, rp);
1470	rpstop(tp, FREAD | FWRITE);
1471	rphardclose(rp);
1472
1473	tp->t_state &= ~TS_BUSY;
1474	ttyclose(tp);
1475
1476	splx(oldspl);
1477
1478	return(0);
1479}
1480
1481static void
1482rphardclose(struct rp_port *rp)
1483{
1484	int	mynor;
1485	struct	tty	*tp;
1486	CHANNEL_t	*cp;
1487
1488	cp = &rp->rp_channel;
1489	tp = rp->rp_tty;
1490	mynor = MINOR_MAGIC(tp->t_dev);
1491
1492	sFlushRxFIFO(cp);
1493	sFlushTxFIFO(cp);
1494	sDisTransmit(cp);
1495	sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1496	sDisRTSFlowCtl(cp);
1497	sDisCTSFlowCtl(cp);
1498	sDisTxSoftFlowCtl(cp);
1499	sClrTxXOFF(cp);
1500
1501	if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1502		sClrDTR(cp);
1503	}
1504	if(IS_CALLOUT(tp->t_dev)) {
1505		sClrDTR(cp);
1506	}
1507	if(rp->dtr_wait != 0) {
1508		timeout(rpdtrwakeup, rp, rp->dtr_wait);
1509		rp->state |= ~SET_DTR;
1510	}
1511
1512	rp->active_out = FALSE;
1513	wakeup(&rp->active_out);
1514	wakeup(TSA_CARR_ON(tp));
1515}
1516
1517static
1518int
1519rpread(dev, uio, flag)
1520	dev_t	dev;
1521	struct	uio	*uio;
1522	int	flag;
1523{
1524	struct	rp_port *rp;
1525	struct	tty	*tp;
1526	int	unit, mynor, umynor, port, error = 0; /* SG */
1527
1528   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1529	port  = (minor(dev) & 0x1f);                /* SG */
1530	mynor = (port + umynor);                    /* SG */
1531   unit = minor_to_unit[mynor];                /* SG */
1532
1533	if(IS_CONTROL(dev))
1534		return(ENODEV);
1535	rp = rp_addr(unit) + port;
1536	tp = rp->rp_tty;
1537	error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
1538	return(error);
1539}
1540
1541static
1542int
1543rpwrite(dev, uio, flag)
1544	dev_t	dev;
1545	struct	uio	*uio;
1546	int	flag;
1547{
1548	struct	rp_port *rp;
1549	struct	tty	*tp;
1550	int	unit, mynor, port, umynor, error = 0; /* SG */
1551
1552   umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1553	port  = (minor(dev) & 0x1f);                /* SG */
1554	mynor = (port + umynor);                    /* SG */
1555   unit = minor_to_unit[mynor];                /* SG */
1556
1557	if(IS_CONTROL(dev))
1558		return(ENODEV);
1559	rp = rp_addr(unit) + port;
1560	tp = rp->rp_tty;
1561	while(rp->rp_disable_writes) {
1562		rp->rp_waiting = 1;
1563		if(error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH,
1564					"rp_write", 0)) {
1565			return(error);
1566		}
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->p_ucred, &p->p_acflag);
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])
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->p_ucred, &p->p_acflag);
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