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