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