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