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