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