lets go ahead and commit this before we hit the network interfaces
[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.9 2003/08/27 06:48:14 rob 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         /* autoq */     0,
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 = (struct rp_port *)
1111                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1112         if(rp == 0) {
1113                 printf("rp_attach: Could not malloc rp_ports structures\n");
1114                 return;
1115         }
1116
1117         count = unit * 32;      /* board times max ports per card SG */
1118         for(i=count;i < (count + rp_num_ports[unit]);i++)
1119                 minor_to_unit[i] = unit;
1120
1121         bzero(rp, sizeof(struct rp_port) * num_ports);
1122         tty = (struct tty *)
1123                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1124         if(tty == 0) {
1125                 printf("rp_attach: Could not malloc tty structures\n");
1126                 return;
1127         }
1128         bzero(tty, sizeof(struct tty) * num_ports);
1129
1130         oldspl = spltty();
1131         rp_addr(unit) = rp;
1132         splx(oldspl);
1133
1134         cdevsw_add(&rp_cdevsw);
1135
1136         port = 0;
1137         for(aiop=0; aiop < num_aiops; aiop++) {
1138                 num_chan = sGetAiopNumChan(ctlp, aiop);
1139                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1140                         rp->rp_tty = tty;
1141                         rp->rp_port = port;
1142                         rp->rp_ctlp = ctlp;
1143                         rp->rp_unit = unit;
1144                         rp->rp_chan = chan;
1145                         rp->rp_aiop = aiop;
1146
1147                         tty->t_line = 0;
1148         /*              tty->t_termios = deftermios;
1149         */
1150                         rp->dtr_wait = 3 * hz;
1151                         rp->it_in.c_iflag = 0;
1152                         rp->it_in.c_oflag = 0;
1153                         rp->it_in.c_cflag = TTYDEF_CFLAG;
1154                         rp->it_in.c_lflag = 0;
1155                         termioschars(&rp->it_in);
1156         /*              termioschars(&tty->t_termios);
1157         */
1158                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1159                         rp->it_out = rp->it_in;
1160
1161                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1162                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
1163                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1164                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1165                                 printf("RocketPort sInitChan(%d, %d, %d) failed
1166                                         \n", unit, aiop, chan);
1167                                 return;
1168                         }
1169                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1170                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1171                         line = (unit << 5) | (aiop << 3) | chan;
1172                         rp_table(line) = rp;
1173                 }
1174         }
1175 }
1176
1177 static
1178 int
1179 rpattach(dev)
1180 struct  isa_device      *dev;
1181 {
1182         int     iobase, unit, /*rpmajor,*/ oldspl;
1183         int     num_ports, num_chan, num_aiops;
1184         int     aiop, chan, port;
1185         int     ChanStatus, line, i, count;
1186         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
1187         struct  rp_port *rp;
1188         struct  tty     *tty;
1189         CONTROLLER_t    *ctlp;
1190
1191         iobase = dev->id_iobase;
1192         unit = dev->id_unit;
1193         ndevs = unit;
1194
1195         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1196                 aiopio[aiop] = iobase + (aiop * 0x400);
1197
1198         ctlp = sCtlNumToCtlPtr(unit);
1199         num_aiops = sInitController(ctlp, unit,
1200                                 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1201                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
1202                                 FREQ_DIS, 0);
1203
1204         num_ports = 0;
1205         for(aiop=0; aiop < num_aiops; aiop++) {
1206                 sResetAiopByNum(ctlp, aiop);
1207                 sEnAiop(ctlp, aiop);
1208                 num_ports += sGetAiopNumChan(ctlp, aiop);
1209         }
1210         printf("RocketPort%d = %d ports\n", unit, num_ports);
1211         rp_num_ports[unit] = num_ports;
1212
1213         rp = (struct rp_port *)
1214                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1215         if(rp == 0) {
1216                 printf("rp_attach: Could not malloc rp_ports structures\n");
1217                 return(0);
1218         }
1219
1220         count = unit * 32;    /* board # times max ports per card  SG */
1221         for(i=count;i < (count + rp_num_ports[unit]);i++)
1222                 minor_to_unit[i] = unit;
1223
1224         bzero(rp, sizeof(struct rp_port) * num_ports);
1225         tty = (struct tty *)
1226                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1227         if(tty == 0) {
1228                 printf("rp_attach: Could not malloc tty structures\n");
1229                 return(0);
1230         }
1231         bzero(tty, sizeof(struct tty) * num_ports);
1232
1233         oldspl = spltty();
1234         rp_addr(unit) = rp;
1235         splx(oldspl);
1236
1237         cdevsw_add(&rp_cdevsw);
1238
1239         port = 0;
1240         for(aiop=0; aiop < num_aiops; aiop++) {
1241                 num_chan = sGetAiopNumChan(ctlp, aiop);
1242                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1243                         rp->rp_tty = tty;
1244                         rp->rp_port = port;
1245                         rp->rp_ctlp = ctlp;
1246                         rp->rp_unit = unit;
1247                         rp->rp_chan = chan;
1248                         rp->rp_aiop = aiop;
1249
1250                         tty->t_line = 0;
1251         /*              tty->t_termios = deftermios;
1252         */
1253                         rp->dtr_wait = 3 * hz;
1254                         rp->it_in.c_iflag = 0;
1255                         rp->it_in.c_oflag = 0;
1256                         rp->it_in.c_cflag = TTYDEF_CFLAG;
1257                         rp->it_in.c_lflag = 0;
1258                         termioschars(&rp->it_in);
1259         /*              termioschars(&tty->t_termios);
1260         */
1261                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1262                         rp->it_out = rp->it_in;
1263
1264                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1265                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
1266                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1267                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1268                                 printf("RocketPort sInitChan(%d, %d, %d) failed
1269                                         \n", unit, aiop, chan);
1270                                 return(0);
1271                         }
1272                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1273                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1274                         line = (unit << 5) | (aiop << 3) | chan;
1275                         rp_table(line) = rp;
1276                 }
1277         }
1278
1279         return(1);
1280 }
1281
1282 int
1283 rpopen(dev, flag, mode, td)
1284         dev_t   dev;
1285         int     flag, mode;
1286         struct thread *td;
1287 {
1288         struct  rp_port *rp;
1289         int     unit, port, mynor, umynor, flags;  /* SG */
1290         struct  tty     *tp;
1291         int     oldspl, error;
1292         unsigned int    IntMask, ChanStatus;
1293
1294
1295    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1296         port  = (minor(dev) & 0x1f);                /* SG */
1297         mynor = (port + umynor);                    /* SG */
1298         unit = minor_to_unit[mynor];
1299         if (rp_addr(unit) == NULL)
1300                 return (ENXIO);
1301         if(IS_CONTROL(dev))
1302                 return(0);
1303         rp = rp_addr(unit) + port;
1304 /*      rp->rp_tty = &rp_tty[rp->rp_port];
1305 */
1306         tp = rp->rp_tty;
1307         dev->si_tty = tp;
1308
1309         oldspl = spltty();
1310
1311 open_top:
1312         while(rp->state & ~SET_DTR) {
1313                 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
1314                 if(error != 0)
1315                         goto out;
1316         }
1317
1318         if(tp->t_state & TS_ISOPEN) {
1319                 if(IS_CALLOUT(dev)) {
1320                         if(!rp->active_out) {
1321                                 error = EBUSY;
1322                                 goto out;
1323                         }
1324                 } else {
1325                         if(rp->active_out) {
1326                                 if(flag & O_NONBLOCK) {
1327                                         error = EBUSY;
1328                                         goto out;
1329                                 }
1330                                 error = tsleep(&rp->active_out,
1331                                             PCATCH, "rpbi", 0);
1332                                 if(error != 0)
1333                                         goto out;
1334                                 goto open_top;
1335                         }
1336                 }
1337                 if(tp->t_state & TS_XCLUDE &&
1338                     suser(td)) {
1339                         splx(oldspl);
1340                         return(EBUSY);
1341                 }
1342         }
1343         else {
1344                 tp->t_dev = dev;
1345                 tp->t_param = rpparam;
1346                 tp->t_oproc = rpstart;
1347                 tp->t_stop = rpstop;
1348                 tp->t_line = 0;
1349                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1350                 flags = 0;
1351                 flags |= SET_RTS;
1352                 flags |= SET_DTR;
1353                 rp->rp_channel.TxControl[3] =
1354                         ((rp->rp_channel.TxControl[3]
1355                         & ~(SET_RTS | SET_DTR)) | flags);
1356                 sOutDW(rp->rp_channel.IndexAddr,
1357                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1358                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1359                 sDisRxStatusMode(&rp->rp_channel);
1360                 sFlushRxFIFO(&rp->rp_channel);
1361                 sFlushTxFIFO(&rp->rp_channel);
1362
1363                 sEnInterrupts(&rp->rp_channel,
1364                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1365                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1366
1367                 sDisRxStatusMode(&rp->rp_channel);
1368                 sClrTxXOFF(&rp->rp_channel);
1369
1370 /*              sDisRTSFlowCtl(&rp->rp_channel);
1371                 sDisCTSFlowCtl(&rp->rp_channel);
1372 */
1373                 sDisTxSoftFlowCtl(&rp->rp_channel);
1374
1375                 sStartRxProcessor(&rp->rp_channel);
1376
1377                 sEnRxFIFO(&rp->rp_channel);
1378                 sEnTransmit(&rp->rp_channel);
1379
1380 /*              sSetDTR(&rp->rp_channel);
1381                 sSetRTS(&rp->rp_channel);
1382 */
1383
1384                 ++rp->wopeners;
1385                 error = rpparam(tp, &tp->t_termios);
1386                 --rp->wopeners;
1387                 if(error != 0) {
1388                         splx(oldspl);
1389                         return(error);
1390                 }
1391
1392                 rp_num_ports_open++;
1393
1394                 IntMask = sGetChanIntID(&rp->rp_channel);
1395                 IntMask = IntMask & rp->rp_intmask;
1396                 ChanStatus = sGetChanStatus(&rp->rp_channel);
1397                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1398                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1399                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1400                         }
1401                 }
1402
1403         if(rp_num_ports_open == 1)
1404                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1405
1406         }
1407
1408         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1409                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1410                 ++rp->wopeners;
1411                 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
1412                 --rp->wopeners;
1413                 if(error != 0)
1414                         goto out;
1415                 goto open_top;
1416         }
1417         error = (*linesw[tp->t_line].l_open)(dev, tp);
1418
1419         rp_disc_optim(tp, &tp->t_termios, rp);
1420         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1421                 rp->active_out = TRUE;
1422
1423 /*      if(rp_num_ports_open == 1)
1424                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1425 */
1426 out:
1427         splx(oldspl);
1428         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1429                 rphardclose(rp);
1430         }
1431         return(error);
1432 }
1433
1434 int
1435 rpclose(dev, flag, mode, td)
1436         dev_t   dev;
1437         int     flag, mode;
1438         struct thread *td;
1439 {
1440         int     oldspl, unit, mynor, umynor, port; /* SG */
1441         struct  rp_port *rp;
1442         struct  tty     *tp;
1443         CHANNEL_t       *cp;
1444
1445    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1446         port  = (minor(dev) & 0x1f);                /* SG */
1447         mynor = (port + umynor);                    /* SG */
1448    unit = minor_to_unit[mynor];                /* SG */
1449
1450         if(IS_CONTROL(dev))
1451                 return(0);
1452         rp = rp_addr(unit) + port;
1453         cp = &rp->rp_channel;
1454         tp = rp->rp_tty;
1455
1456         oldspl = spltty();
1457         (*linesw[tp->t_line].l_close)(tp, flag);
1458         rp_disc_optim(tp, &tp->t_termios, rp);
1459         rpstop(tp, FREAD | FWRITE);
1460         rphardclose(rp);
1461
1462         tp->t_state &= ~TS_BUSY;
1463         ttyclose(tp);
1464
1465         splx(oldspl);
1466
1467         return(0);
1468 }
1469
1470 static void
1471 rphardclose(struct rp_port *rp)
1472 {
1473         int     mynor;
1474         struct  tty     *tp;
1475         CHANNEL_t       *cp;
1476
1477         cp = &rp->rp_channel;
1478         tp = rp->rp_tty;
1479         mynor = MINOR_MAGIC(tp->t_dev);
1480
1481         sFlushRxFIFO(cp);
1482         sFlushTxFIFO(cp);
1483         sDisTransmit(cp);
1484         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1485         sDisRTSFlowCtl(cp);
1486         sDisCTSFlowCtl(cp);
1487         sDisTxSoftFlowCtl(cp);
1488         sClrTxXOFF(cp);
1489
1490         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1491                 sClrDTR(cp);
1492         }
1493         if(IS_CALLOUT(tp->t_dev)) {
1494                 sClrDTR(cp);
1495         }
1496         if(rp->dtr_wait != 0) {
1497                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1498                 rp->state |= ~SET_DTR;
1499         }
1500
1501         rp->active_out = FALSE;
1502         wakeup(&rp->active_out);
1503         wakeup(TSA_CARR_ON(tp));
1504 }
1505
1506 static
1507 int
1508 rpwrite(dev, uio, flag)
1509         dev_t   dev;
1510         struct  uio     *uio;
1511         int     flag;
1512 {
1513         struct  rp_port *rp;
1514         struct  tty     *tp;
1515         int     unit, mynor, port, umynor, error = 0; /* SG */
1516
1517    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1518         port  = (minor(dev) & 0x1f);                /* SG */
1519         mynor = (port + umynor);                    /* SG */
1520    unit = minor_to_unit[mynor];                /* SG */
1521
1522         if(IS_CONTROL(dev))
1523                 return(ENODEV);
1524         rp = rp_addr(unit) + port;
1525         tp = rp->rp_tty;
1526         while(rp->rp_disable_writes) {
1527                 rp->rp_waiting = 1;
1528                 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
1529                 if (error)
1530                         return(error);
1531         }
1532
1533         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1534         return error;
1535 }
1536
1537 static void
1538 rpdtrwakeup(void *chan)
1539 {
1540         struct  rp_port *rp;
1541
1542         rp = (struct rp_port *)chan;
1543         rp->state &= SET_DTR;
1544         wakeup(&rp->dtr_wait);
1545 }
1546
1547 int
1548 rpioctl(dev, cmd, data, flag, td)
1549         dev_t   dev;
1550         u_long  cmd;
1551         caddr_t data;
1552         int     flag;
1553         struct  thread *td;
1554 {
1555         struct rp_port  *rp;
1556         CHANNEL_t       *cp;
1557         struct tty      *tp;
1558         int     unit, mynor, port, umynor;            /* SG */
1559         int     oldspl;
1560         int     error = 0;
1561         int     arg, flags, result, ChanStatus;
1562         int     oldcmd;
1563         struct  termios term, *t;
1564
1565    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1566         port  = (minor(dev) & 0x1f);                /* SG */
1567         mynor = (port + umynor);                    /* SG */
1568         unit = minor_to_unit[mynor];
1569         rp = rp_addr(unit) + port;
1570
1571         if(IS_CONTROL(dev)) {
1572                 struct  termios *ct;
1573
1574                 switch (IS_CONTROL(dev)) {
1575                 case CONTROL_INIT_STATE:
1576                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1577                         break;
1578                 case CONTROL_LOCK_STATE:
1579                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1580                         break;
1581                 default:
1582                         return(ENODEV);         /* /dev/nodev */
1583                 }
1584                 switch (cmd) {
1585                 case TIOCSETA:
1586                         error = suser(td);
1587                         if(error != 0)
1588                                 return(error);
1589                         *ct = *(struct termios *)data;
1590                         return(0);
1591                 case TIOCGETA:
1592                         *(struct termios *)data = *ct;
1593                         return(0);
1594                 case TIOCGETD:
1595                         *(int *)data = TTYDISC;
1596                         return(0);
1597                 case TIOCGWINSZ:
1598                         bzero(data, sizeof(struct winsize));
1599                         return(0);
1600                 default:
1601                         return(ENOTTY);
1602                 }
1603         }
1604
1605         tp = rp->rp_tty;
1606         cp = &rp->rp_channel;
1607
1608 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1609         term = tp->t_termios;
1610         oldcmd = cmd;
1611         error = ttsetcompat(tp, &cmd, data, &term);
1612         if(error != 0)
1613                 return(error);
1614         if(cmd != oldcmd) {
1615                 data = (caddr_t)&term;
1616         }
1617 #endif
1618         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1619                 int     cc;
1620                 struct  termios *dt = (struct termios *)data;
1621                 struct  termios *lt = IS_CALLOUT(dev)
1622                                         ? &rp->lt_out : &rp->lt_in;
1623
1624                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1625                                 | (dt->c_iflag & ~lt->c_iflag);
1626                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1627                                 | (dt->c_oflag & ~lt->c_oflag);
1628                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1629                                 | (dt->c_cflag & ~lt->c_cflag);
1630                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1631                                 | (dt->c_lflag & ~lt->c_lflag);
1632                 for(cc = 0; cc < NCCS; ++cc)
1633                         if(lt->c_cc[cc] != 0)
1634                                 dt->c_cc[cc] = tp->t_cc[cc];
1635                 if(lt->c_ispeed != 0)
1636                         dt->c_ispeed = tp->t_ispeed;
1637                 if(lt->c_ospeed != 0)
1638                         dt->c_ospeed = tp->t_ospeed;
1639         }
1640
1641         t = &tp->t_termios;
1642
1643         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
1644         if(error != ENOIOCTL) {
1645                 return(error);
1646         }
1647         oldspl = spltty();
1648
1649         flags = rp->rp_channel.TxControl[3];
1650
1651         error = ttioctl(tp, cmd, data, flag);
1652         flags = rp->rp_channel.TxControl[3];
1653         rp_disc_optim(tp, &tp->t_termios, rp);
1654         if(error != ENOIOCTL) {
1655                 splx(oldspl);
1656                 return(error);
1657         }
1658         switch(cmd) {
1659         case TIOCSBRK:
1660                 sSendBreak(&rp->rp_channel);
1661                 break;
1662
1663         case TIOCCBRK:
1664                 sClrBreak(&rp->rp_channel);
1665                 break;
1666
1667         case TIOCSDTR:
1668                 sSetDTR(&rp->rp_channel);
1669                 sSetRTS(&rp->rp_channel);
1670                 break;
1671
1672         case TIOCCDTR:
1673                 sClrDTR(&rp->rp_channel);
1674                 break;
1675
1676         case TIOCMSET:
1677                 arg = *(int *) data;
1678                 flags = 0;
1679                 if(arg & TIOCM_RTS)
1680                         flags |= SET_RTS;
1681                 if(arg & TIOCM_DTR)
1682                         flags |= SET_DTR;
1683                 rp->rp_channel.TxControl[3] =
1684                         ((rp->rp_channel.TxControl[3]
1685                         & ~(SET_RTS | SET_DTR)) | flags);
1686                 sOutDW(rp->rp_channel.IndexAddr,
1687                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1688                 break;
1689         case TIOCMBIS:
1690                 arg = *(int *) data;
1691                 flags = 0;
1692                 if(arg & TIOCM_RTS)
1693                         flags |= SET_RTS;
1694                 if(arg & TIOCM_DTR)
1695                         flags |= SET_DTR;
1696                         rp->rp_channel.TxControl[3] |= flags;
1697                 sOutDW(rp->rp_channel.IndexAddr,
1698                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1699                 break;
1700         case TIOCMBIC:
1701                 arg = *(int *) data;
1702                 flags = 0;
1703                 if(arg & TIOCM_RTS)
1704                         flags |= SET_RTS;
1705                 if(arg & TIOCM_DTR)
1706                         flags |= SET_DTR;
1707                 rp->rp_channel.TxControl[3] &= ~flags;
1708                 sOutDW(rp->rp_channel.IndexAddr,
1709                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1710                 break;
1711
1712
1713         case TIOCMGET:
1714                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1715                 flags = rp->rp_channel.TxControl[3];
1716                 result = TIOCM_LE; /* always on while open for some reason */
1717                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1718                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1719                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1720                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1721                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1722
1723                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1724                 {
1725                         result |= TIOCM_RTS;
1726                 }
1727
1728                 *(int *)data = result;
1729                 break;
1730         case TIOCMSDTRWAIT:
1731                 error = suser(td);
1732                 if(error != 0) {
1733                         splx(oldspl);
1734                         return(error);
1735                 }
1736                 rp->dtr_wait = *(int *)data * hz/100;
1737                 break;
1738         case TIOCMGDTRWAIT:
1739                 *(int *)data = rp->dtr_wait * 100/hz;
1740                 break;
1741         default:
1742                 splx(oldspl);
1743                 return ENOTTY;
1744         }
1745         splx(oldspl);
1746         return(0);
1747 }
1748
1749 static struct speedtab baud_table[] = {
1750         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
1751         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
1752         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
1753         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
1754         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
1755         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
1756                                 {B57600, BRD57600},     {B76800, BRD76800},
1757         {B115200, BRD115200},   {B230400, BRD230400},
1758         { -1,   -1 }
1759 };
1760
1761 static int
1762 rpparam(tp, t)
1763         struct tty *tp;
1764         struct termios *t;
1765 {
1766         struct rp_port  *rp;
1767         CHANNEL_t       *cp;
1768         int     unit, mynor, port, umynor;               /* SG */
1769         int     oldspl, cflag, iflag, oflag, lflag;
1770         int     ospeed;
1771
1772
1773    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1774         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1775         mynor = (port + umynor);                          /* SG */
1776
1777         unit = minor_to_unit[mynor];
1778         rp = rp_addr(unit) + port;
1779         cp = &rp->rp_channel;
1780         oldspl = spltty();
1781
1782         cflag = t->c_cflag;
1783         iflag = t->c_iflag;
1784         oflag = t->c_oflag;
1785         lflag = t->c_lflag;
1786
1787         ospeed = ttspeedtab(t->c_ispeed, baud_table);
1788         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1789                 return(EINVAL);
1790
1791         tp->t_ispeed = t->c_ispeed;
1792         tp->t_ospeed = t->c_ospeed;
1793         tp->t_cflag = cflag;
1794         tp->t_iflag = iflag;
1795         tp->t_oflag = oflag;
1796         tp->t_lflag = lflag;
1797
1798         if(t->c_ospeed == 0) {
1799                 sClrDTR(cp);
1800                 return(0);
1801         }
1802         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1803
1804         /* Set baud rate ----- we only pay attention to ispeed */
1805         sSetDTR(cp);
1806         sSetRTS(cp);
1807         sSetBaud(cp, ospeed);
1808
1809         if(cflag & CSTOPB) {
1810                 sSetStop2(cp);
1811         } else {
1812                 sSetStop1(cp);
1813         }
1814
1815         if(cflag & PARENB) {
1816                 sEnParity(cp);
1817                 if(cflag & PARODD) {
1818                         sSetOddParity(cp);
1819                 } else {
1820                         sSetEvenParity(cp);
1821                 }
1822         }
1823         else {
1824                 sDisParity(cp);
1825         }
1826         if((cflag & CSIZE) == CS8) {
1827                 sSetData8(cp);
1828                 rp->rp_imask = 0xFF;
1829         } else {
1830                 sSetData7(cp);
1831                 rp->rp_imask = 0x7F;
1832         }
1833
1834         if(iflag & ISTRIP) {
1835                 rp->rp_imask &= 0x7F;
1836         }
1837
1838         if(cflag & CLOCAL) {
1839                 rp->rp_intmask &= ~DELTA_CD;
1840         } else {
1841                 rp->rp_intmask |= DELTA_CD;
1842         }
1843
1844         /* Put flow control stuff here */
1845
1846         if(cflag & CCTS_OFLOW) {
1847                 sEnCTSFlowCtl(cp);
1848         } else {
1849                 sDisCTSFlowCtl(cp);
1850         }
1851
1852         if(cflag & CRTS_IFLOW) {
1853                 rp->rp_rts_iflow = 1;
1854         } else {
1855                 rp->rp_rts_iflow = 0;
1856         }
1857
1858         if(cflag & CRTS_IFLOW) {
1859                 sEnRTSFlowCtl(cp);
1860         } else {
1861                 sDisRTSFlowCtl(cp);
1862         }
1863         rp_disc_optim(tp, t, rp);
1864
1865         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1866                 tp->t_state |= TS_CARR_ON;
1867                 wakeup(TSA_CARR_ON(tp));
1868         }
1869
1870 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
1871         flags = rp->rp_channel.TxControl[3];
1872         if(flags & SET_DTR)
1873         else
1874         if(flags & SET_RTS)
1875         else
1876 */
1877         splx(oldspl);
1878
1879         return(0);
1880 }
1881
1882 static void
1883 rp_disc_optim(tp, t, rp)
1884 struct  tty     *tp;
1885 struct  termios *t;
1886 struct  rp_port *rp;
1887 {
1888         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1889                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1890                 &&(!(t->c_iflag & PARMRK)
1891                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1892                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1893                 && linesw[tp->t_line].l_rint == ttyinput)
1894                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1895         else
1896                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1897 }
1898
1899 static void
1900 rpstart(tp)
1901         struct tty *tp;
1902 {
1903         struct rp_port  *rp;
1904         CHANNEL_t       *cp;
1905         struct  clist   *qp;
1906         int     unit, mynor, port, umynor;               /* SG */
1907         char    ch, flags;
1908         int     spl, xmit_fifo_room;
1909         int     count;
1910
1911
1912    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1913         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1914         mynor = (port + umynor);                          /* SG */
1915         unit = minor_to_unit[mynor];
1916         rp = rp_addr(unit) + port;
1917         cp = &rp->rp_channel;
1918         flags = rp->rp_channel.TxControl[3];
1919         spl = spltty();
1920
1921         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1922                 ttwwakeup(tp);
1923                 splx(spl);
1924                 return;
1925         }
1926         if(rp->rp_xmit_stopped) {
1927                 sEnTransmit(cp);
1928                 rp->rp_xmit_stopped = 0;
1929         }
1930         count = sGetTxCnt(cp);
1931
1932         if(tp->t_outq.c_cc == 0) {
1933                 if((tp->t_state & TS_BUSY) && (count == 0)) {
1934                         tp->t_state &= ~TS_BUSY;
1935                 }
1936                 ttwwakeup(tp);
1937                 splx(spl);
1938                 return;
1939         }
1940         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1941         qp = &tp->t_outq;
1942         count = 0;
1943         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1944                 tp->t_state |= TS_BUSY;
1945         }
1946         while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1947                 ch = getc(qp);
1948                 sOutB(sGetTxRxDataIO(cp), ch);
1949                 xmit_fifo_room--;
1950                 count++;
1951         }
1952         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1953
1954         ttwwakeup(tp);
1955         splx(spl);
1956 }
1957
1958 static
1959 void
1960 rpstop(tp, flag)
1961         struct tty *tp;
1962         int     flag;
1963 {
1964         struct rp_port  *rp;
1965         CHANNEL_t       *cp;
1966         int     unit, mynor, port, umynor;                  /* SG */
1967         int     spl;
1968
1969    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1970         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1971         mynor = (port + umynor);                          /* SG */
1972         unit = minor_to_unit[mynor];
1973         rp = rp_addr(unit) + port;
1974         cp = &rp->rp_channel;
1975
1976         spl = spltty();
1977
1978         if(tp->t_state & TS_BUSY) {
1979                 if((tp->t_state&TS_TTSTOP) == 0) {
1980                         sFlushTxFIFO(cp);
1981                 } else {
1982                         if(rp->rp_xmit_stopped == 0) {
1983                                 sDisTransmit(cp);
1984                                 rp->rp_xmit_stopped = 1;
1985                         }
1986                 }
1987         }
1988         splx(spl);
1989         rpstart(tp);
1990 }