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