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