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