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