proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[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.3 2003/06/25 03:55:54 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 <i386/isa/isa_device.h>
52
53 #include <pci/pcivar.h>
54
55 #define ROCKET_C
56 #include <i386/isa/rpreg.h>
57 #include <i386/isa/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    register 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 __P((struct isa_device *));
772 static int rpattach __P((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         /* open */      rpopen,
804         /* close */     rpclose,
805         /* read */      ttyread,
806         /* write */     rpwrite,
807         /* ioctl */     rpioctl,
808         /* poll */      ttypoll,
809         /* mmap */      nommap,
810         /* strategy */  nostrategy,
811         /* name */      driver_name,
812         /* maj */       CDEV_MAJOR,
813         /* dump */      nodump,
814         /* psize */     nopsize,
815         /* flags */     D_TTY | D_KQFILTER,
816         /* bmaj */      -1,
817         /* kqfilter */  ttykqfilter,
818 };
819
820 static int rp_controller_port = 0;
821 static int rp_num_ports_open = 0;
822 static int      ndevs = 0;
823 static int      minor_to_unit[128];
824 #if 0
825 static  struct  tty     rp_tty[128];
826 #endif
827
828 static int rp_num_ports[4];     /* Number of ports on each controller */
829
830 #define _INLINE_ __inline
831 #define POLL_INTERVAL 1
832
833 #define CALLOUT_MASK            0x80
834 #define CONTROL_MASK            0x60
835 #define CONTROL_INIT_STATE      0x20
836 #define CONTROL_LOCK_STATE      0x40
837 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
838 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
839 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
840 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
841 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
842
843 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
844 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
845 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
846
847 static  struct  rp_port *p_rp_addr[4];
848 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
849 #define rp_addr(unit)   (p_rp_addr[unit])
850 #define rp_table(port)  (p_rp_table[port])
851
852 /*
853  * The top-level routines begin here
854  */
855
856 static  int     rpparam __P((struct tty *, struct termios *));
857 static  void    rpstart __P((struct tty *));
858 static  void    rpstop __P((struct tty *, int));
859 static  void    rphardclose     __P((struct rp_port *));
860 static  void    rp_disc_optim   __P((struct tty *tp, struct termios *t,
861                                                 struct rp_port  *rp));
862
863 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
864                         CHANNEL_t *cp, unsigned int ChanStatus)
865 {
866         int     spl;
867         unsigned        int     CharNStat;
868         int     ToRecv, ch;
869
870         ToRecv = sGetRxCnt(cp);
871         if(ToRecv == 0)
872                 return;
873
874 /*      If status indicates there are errored characters in the
875         FIFO, then enter status mode (a word in FIFO holds
876         characters and status)
877 */
878
879         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
880                 if(!(ChanStatus & STATMODE)) {
881                         ChanStatus |= STATMODE;
882                         sEnRxStatusMode(cp);
883                 }
884         }
885 /*
886         if we previously entered status mode then read down the
887         FIFO one word at a time, pulling apart the character and
888         the status. Update error counters depending on status.
889 */
890         if(ChanStatus & STATMODE) {
891                 while(ToRecv) {
892                         if(tp->t_state & TS_TBLOCK) {
893                                 break;
894                         }
895                         CharNStat = sInW(sGetTxRxDataIO(cp));
896                         ch = CharNStat & 0xff;
897
898                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
899                                 ch |= TTY_FE;
900                         else if (CharNStat & STMPARITYH)
901                                 ch |= TTY_PE;
902                         else if (CharNStat & STMRCVROVRH)
903                                 rp->rp_overflows++;
904
905                         (*linesw[tp->t_line].l_rint)(ch, tp);
906                         ToRecv--;
907                 }
908 /*
909         After emtying FIFO in status mode, turn off status mode
910 */
911
912         if(sGetRxCnt(cp) == 0)
913                 sDisRxStatusMode(cp);
914         }
915         else {
916                 while (ToRecv) {
917                         if(tp->t_state & TS_TBLOCK) {
918                                 break;
919                         }
920                         ch = (u_char) sInB(sGetTxRxDataIO(cp));
921                         spl = spltty();
922                         (*linesw[tp->t_line].l_rint)(ch, tp);
923                         splx(spl);
924                         ToRecv--;
925                 }
926         }
927 }
928
929 static _INLINE_ void rp_handle_port(struct rp_port *rp)
930 {
931         CHANNEL_t       *cp;
932         struct  tty     *tp;
933         unsigned        int     IntMask, ChanStatus;
934      /* int     oldcts; */
935
936         if(!rp)
937                 return;
938
939         cp = &rp->rp_channel;
940         tp = rp->rp_tty;
941         IntMask = sGetChanIntID(cp);
942         IntMask = IntMask & rp->rp_intmask;
943         ChanStatus = sGetChanStatus(cp);
944         if(IntMask & RXF_TRIG)
945                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
946                         rp_do_receive(rp, tp, cp, ChanStatus);
947                 }
948         if(IntMask & DELTA_CD) {
949                 if(ChanStatus & CD_ACT) {
950                         if(!(tp->t_state & TS_CARR_ON) ) {
951                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
952                         }
953                 } else {
954                         if((tp->t_state & TS_CARR_ON)) {
955                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
956                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
957                                         rphardclose(rp);
958                                 }
959                         }
960                 }
961         }
962 /*      oldcts = rp->rp_cts;
963         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
964         if(oldcts != rp->rp_cts) {
965                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
966         }
967 */
968 }
969
970 static void rp_do_poll(void *not_used)
971 {
972         CONTROLLER_t    *ctl;
973         struct rp_port  *rp;
974         struct tty      *tp;
975         int     unit, aiop, ch, line, count;
976         unsigned char   CtlMask, AiopMask;
977
978         for(unit = 0; unit <= ndevs; unit++) {
979         rp = rp_addr(unit);
980         ctl = rp->rp_ctlp;
981         if(ctl->BusType == isPCI)
982                 CtlMask = sPCIGetControllerIntStatus(ctl);
983         else
984                 CtlMask = sGetControllerIntStatus(ctl);
985         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
986                 if(CtlMask & 1) {
987                         AiopMask = sGetAiopIntStatus(ctl, aiop);
988                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
989                                 if(AiopMask & 1) {
990                                         line = (unit << 5) | (aiop << 3) | ch;
991                                         rp = rp_table(line);
992                                         rp_handle_port(rp);
993                                 }
994                         }
995                 }
996         }
997
998         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
999                         line++, rp++) {
1000                 tp = rp->rp_tty;
1001                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1002                         count = sGetTxCnt(&rp->rp_channel);
1003                         if(count == 0)
1004                                 tp->t_state &= ~(TS_BUSY);
1005                         if(!(tp->t_state & TS_TTSTOP) &&
1006                                 (count <= rp->rp_restart)) {
1007                                 (*linesw[tp->t_line].l_start)(tp);
1008                         }
1009                 }
1010         }
1011         }
1012         if(rp_num_ports_open)
1013                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1014 }
1015
1016 static const char*
1017 rp_pciprobe(pcici_t tag, pcidi_t type)
1018 {
1019         int     vendor_id;
1020
1021         vendor_id = type & 0xffff;
1022         switch(vendor_id)
1023         case 0x11fe:
1024                 return("rp");
1025         return(NULL);
1026 }
1027
1028 static
1029 int
1030 rpprobe(dev)
1031 struct isa_device *dev;
1032 {
1033         int controller, unit;
1034         int aiop, num_aiops;
1035         unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1036         CONTROLLER_t *ctlp;
1037
1038         unit = dev->id_unit;
1039         if (dev->id_unit >= 4) {
1040                 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1041                 return 1;
1042         }
1043         printf("probing for RocketPort(ISA) unit %d\n", unit);
1044         if (rp_controller_port)
1045                 controller = rp_controller_port;
1046         else {
1047                 controller = dev->id_iobase + 0x40;
1048         }
1049
1050         for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1051                 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1052
1053         ctlp = sCtlNumToCtlPtr(dev->id_unit);
1054         num_aiops = sInitController(ctlp, dev->id_unit,
1055                                 controller + ((unit-rp_pcicount)*0x400),
1056                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
1057                                 FREQ_DIS, 0);
1058         if (num_aiops <= 0) {
1059                 printf("board%d init failed\n", unit);
1060                 return 0;
1061         }
1062
1063         if (rp_controller_port) {
1064                 dev->id_msize = 64;
1065         } else {
1066                 dev->id_msize = 68;
1067                 rp_controller_port = controller;
1068         }
1069
1070         dev->id_irq = 0;
1071
1072         return 1;
1073 }
1074
1075 static void
1076 rp_pciattach(pcici_t tag, int unit)
1077 {
1078         int     success, oldspl;
1079         u_short iobase;
1080         int     num_ports, num_chan, num_aiops;
1081         int     aiop, chan, port;
1082         int     ChanStatus, line, i, count;
1083         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
1084         struct  rp_port *rp;
1085         struct  tty     *tty;
1086         CONTROLLER_t    *ctlp;
1087
1088         success = pci_map_port(tag, 0x10, &iobase);
1089         if(!success)
1090                 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1091
1092         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1093                 aiopio[aiop] = iobase + (aiop * 0x40);
1094
1095         ctlp = sCtlNumToCtlPtr(unit);
1096         num_aiops = sPCIInitController(ctlp, unit,
1097                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
1098                                 FREQ_DIS, 0);
1099
1100         num_ports = 0;
1101         for(aiop=0; aiop < num_aiops; aiop++) {
1102                 sResetAiopByNum(ctlp, aiop);
1103                 num_ports += sGetAiopNumChan(ctlp, aiop);
1104         }
1105         printf("RocketPort%d = %d ports\n", unit, num_ports);
1106         rp_num_ports[unit] = num_ports;
1107
1108         rp = (struct rp_port *)
1109                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1110         if(rp == 0) {
1111                 printf("rp_attach: Could not malloc rp_ports structures\n");
1112                 return;
1113         }
1114
1115         count = unit * 32;      /* board times max ports per card SG */
1116         for(i=count;i < (count + rp_num_ports[unit]);i++)
1117                 minor_to_unit[i] = unit;
1118
1119         bzero(rp, sizeof(struct rp_port) * num_ports);
1120         tty = (struct tty *)
1121                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1122         if(tty == 0) {
1123                 printf("rp_attach: Could not malloc tty structures\n");
1124                 return;
1125         }
1126         bzero(tty, sizeof(struct tty) * num_ports);
1127
1128         oldspl = spltty();
1129         rp_addr(unit) = rp;
1130         splx(oldspl);
1131
1132         cdevsw_add(&rp_cdevsw);
1133
1134         port = 0;
1135         for(aiop=0; aiop < num_aiops; aiop++) {
1136                 num_chan = sGetAiopNumChan(ctlp, aiop);
1137                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1138                         rp->rp_tty = tty;
1139                         rp->rp_port = port;
1140                         rp->rp_ctlp = ctlp;
1141                         rp->rp_unit = unit;
1142                         rp->rp_chan = chan;
1143                         rp->rp_aiop = aiop;
1144
1145                         tty->t_line = 0;
1146         /*              tty->t_termios = deftermios;
1147         */
1148                         rp->dtr_wait = 3 * hz;
1149                         rp->it_in.c_iflag = 0;
1150                         rp->it_in.c_oflag = 0;
1151                         rp->it_in.c_cflag = TTYDEF_CFLAG;
1152                         rp->it_in.c_lflag = 0;
1153                         termioschars(&rp->it_in);
1154         /*              termioschars(&tty->t_termios);
1155         */
1156                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1157                         rp->it_out = rp->it_in;
1158
1159                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1160                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
1161                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1162                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1163                                 printf("RocketPort sInitChan(%d, %d, %d) failed
1164                                         \n", unit, aiop, chan);
1165                                 return;
1166                         }
1167                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1168                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1169                         line = (unit << 5) | (aiop << 3) | chan;
1170                         rp_table(line) = rp;
1171                 }
1172         }
1173 }
1174
1175 static
1176 int
1177 rpattach(dev)
1178 struct  isa_device      *dev;
1179 {
1180         int     iobase, unit, /*rpmajor,*/ oldspl;
1181         int     num_ports, num_chan, num_aiops;
1182         int     aiop, chan, port;
1183         int     ChanStatus, line, i, count;
1184         unsigned int    aiopio[MAX_AIOPS_PER_BOARD];
1185         struct  rp_port *rp;
1186         struct  tty     *tty;
1187         CONTROLLER_t    *ctlp;
1188
1189         iobase = dev->id_iobase;
1190         unit = dev->id_unit;
1191         ndevs = unit;
1192
1193         for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1194                 aiopio[aiop] = iobase + (aiop * 0x400);
1195
1196         ctlp = sCtlNumToCtlPtr(unit);
1197         num_aiops = sInitController(ctlp, unit,
1198                                 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1199                                 aiopio, MAX_AIOPS_PER_BOARD, 0,
1200                                 FREQ_DIS, 0);
1201
1202         num_ports = 0;
1203         for(aiop=0; aiop < num_aiops; aiop++) {
1204                 sResetAiopByNum(ctlp, aiop);
1205                 sEnAiop(ctlp, aiop);
1206                 num_ports += sGetAiopNumChan(ctlp, aiop);
1207         }
1208         printf("RocketPort%d = %d ports\n", unit, num_ports);
1209         rp_num_ports[unit] = num_ports;
1210
1211         rp = (struct rp_port *)
1212                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1213         if(rp == 0) {
1214                 printf("rp_attach: Could not malloc rp_ports structures\n");
1215                 return(0);
1216         }
1217
1218         count = unit * 32;    /* board # times max ports per card  SG */
1219         for(i=count;i < (count + rp_num_ports[unit]);i++)
1220                 minor_to_unit[i] = unit;
1221
1222         bzero(rp, sizeof(struct rp_port) * num_ports);
1223         tty = (struct tty *)
1224                 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1225         if(tty == 0) {
1226                 printf("rp_attach: Could not malloc tty structures\n");
1227                 return(0);
1228         }
1229         bzero(tty, sizeof(struct tty) * num_ports);
1230
1231         oldspl = spltty();
1232         rp_addr(unit) = rp;
1233         splx(oldspl);
1234
1235         cdevsw_add(&rp_cdevsw);
1236
1237         port = 0;
1238         for(aiop=0; aiop < num_aiops; aiop++) {
1239                 num_chan = sGetAiopNumChan(ctlp, aiop);
1240                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1241                         rp->rp_tty = tty;
1242                         rp->rp_port = port;
1243                         rp->rp_ctlp = ctlp;
1244                         rp->rp_unit = unit;
1245                         rp->rp_chan = chan;
1246                         rp->rp_aiop = aiop;
1247
1248                         tty->t_line = 0;
1249         /*              tty->t_termios = deftermios;
1250         */
1251                         rp->dtr_wait = 3 * hz;
1252                         rp->it_in.c_iflag = 0;
1253                         rp->it_in.c_oflag = 0;
1254                         rp->it_in.c_cflag = TTYDEF_CFLAG;
1255                         rp->it_in.c_lflag = 0;
1256                         termioschars(&rp->it_in);
1257         /*              termioschars(&tty->t_termios);
1258         */
1259                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1260                         rp->it_out = rp->it_in;
1261
1262                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1263                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
1264                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1265                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1266                                 printf("RocketPort sInitChan(%d, %d, %d) failed
1267                                         \n", unit, aiop, chan);
1268                                 return(0);
1269                         }
1270                         ChanStatus = sGetChanStatus(&rp->rp_channel);
1271                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1272                         line = (unit << 5) | (aiop << 3) | chan;
1273                         rp_table(line) = rp;
1274                 }
1275         }
1276
1277         return(1);
1278 }
1279
1280 int
1281 rpopen(dev, flag, mode, p)
1282         dev_t   dev;
1283         int     flag, mode;
1284         struct  proc    *p;
1285 {
1286         struct  rp_port *rp;
1287         int     unit, port, mynor, umynor, flags;  /* SG */
1288         struct  tty     *tp;
1289         int     oldspl, error;
1290         unsigned int    IntMask, ChanStatus;
1291
1292
1293    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1294         port  = (minor(dev) & 0x1f);                /* SG */
1295         mynor = (port + umynor);                    /* SG */
1296         unit = minor_to_unit[mynor];
1297         if (rp_addr(unit) == NULL)
1298                 return (ENXIO);
1299         if(IS_CONTROL(dev))
1300                 return(0);
1301         rp = rp_addr(unit) + port;
1302 /*      rp->rp_tty = &rp_tty[rp->rp_port];
1303 */
1304         tp = rp->rp_tty;
1305         dev->si_tty = tp;
1306
1307         oldspl = spltty();
1308
1309 open_top:
1310         while(rp->state & ~SET_DTR) {
1311                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1312                 if(error != 0)
1313                         goto out;
1314         }
1315
1316         if(tp->t_state & TS_ISOPEN) {
1317                 if(IS_CALLOUT(dev)) {
1318                         if(!rp->active_out) {
1319                                 error = EBUSY;
1320                                 goto out;
1321                         }
1322                 } else {
1323                         if(rp->active_out) {
1324                                 if(flag & O_NONBLOCK) {
1325                                         error = EBUSY;
1326                                         goto out;
1327                                 }
1328                                 error = tsleep(&rp->active_out,
1329                                         TTIPRI | PCATCH, "rpbi", 0);
1330                                 if(error != 0)
1331                                         goto out;
1332                                 goto open_top;
1333                         }
1334                 }
1335                 if(tp->t_state & TS_XCLUDE &&
1336                     suser(td)) {
1337                         splx(oldspl);
1338                         return(EBUSY);
1339                 }
1340         }
1341         else {
1342                 tp->t_dev = dev;
1343                 tp->t_param = rpparam;
1344                 tp->t_oproc = rpstart;
1345                 tp->t_stop = rpstop;
1346                 tp->t_line = 0;
1347                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1348                 flags = 0;
1349                 flags |= SET_RTS;
1350                 flags |= SET_DTR;
1351                 rp->rp_channel.TxControl[3] =
1352                         ((rp->rp_channel.TxControl[3]
1353                         & ~(SET_RTS | SET_DTR)) | flags);
1354                 sOutDW(rp->rp_channel.IndexAddr,
1355                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1356                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1357                 sDisRxStatusMode(&rp->rp_channel);
1358                 sFlushRxFIFO(&rp->rp_channel);
1359                 sFlushTxFIFO(&rp->rp_channel);
1360
1361                 sEnInterrupts(&rp->rp_channel,
1362                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1363                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1364
1365                 sDisRxStatusMode(&rp->rp_channel);
1366                 sClrTxXOFF(&rp->rp_channel);
1367
1368 /*              sDisRTSFlowCtl(&rp->rp_channel);
1369                 sDisCTSFlowCtl(&rp->rp_channel);
1370 */
1371                 sDisTxSoftFlowCtl(&rp->rp_channel);
1372
1373                 sStartRxProcessor(&rp->rp_channel);
1374
1375                 sEnRxFIFO(&rp->rp_channel);
1376                 sEnTransmit(&rp->rp_channel);
1377
1378 /*              sSetDTR(&rp->rp_channel);
1379                 sSetRTS(&rp->rp_channel);
1380 */
1381
1382                 ++rp->wopeners;
1383                 error = rpparam(tp, &tp->t_termios);
1384                 --rp->wopeners;
1385                 if(error != 0) {
1386                         splx(oldspl);
1387                         return(error);
1388                 }
1389
1390                 rp_num_ports_open++;
1391
1392                 IntMask = sGetChanIntID(&rp->rp_channel);
1393                 IntMask = IntMask & rp->rp_intmask;
1394                 ChanStatus = sGetChanStatus(&rp->rp_channel);
1395                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1396                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1397                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1398                         }
1399                 }
1400
1401         if(rp_num_ports_open == 1)
1402                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1403
1404         }
1405
1406         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1407                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1408                 ++rp->wopeners;
1409                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1410                                 "rpdcd", 0);
1411                 --rp->wopeners;
1412                 if(error != 0)
1413                         goto out;
1414                 goto open_top;
1415         }
1416         error = (*linesw[tp->t_line].l_open)(dev, tp);
1417
1418         rp_disc_optim(tp, &tp->t_termios, rp);
1419         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1420                 rp->active_out = TRUE;
1421
1422 /*      if(rp_num_ports_open == 1)
1423                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1424 */
1425 out:
1426         splx(oldspl);
1427         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1428                 rphardclose(rp);
1429         }
1430         return(error);
1431 }
1432
1433 int
1434 rpclose(dev, flag, mode, p)
1435         dev_t   dev;
1436         int     flag, mode;
1437         struct  proc    *p;
1438 {
1439         int     oldspl, unit, mynor, umynor, port; /* SG */
1440         struct  rp_port *rp;
1441         struct  tty     *tp;
1442         CHANNEL_t       *cp;
1443
1444    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1445         port  = (minor(dev) & 0x1f);                /* SG */
1446         mynor = (port + umynor);                    /* SG */
1447    unit = minor_to_unit[mynor];                /* SG */
1448
1449         if(IS_CONTROL(dev))
1450                 return(0);
1451         rp = rp_addr(unit) + port;
1452         cp = &rp->rp_channel;
1453         tp = rp->rp_tty;
1454
1455         oldspl = spltty();
1456         (*linesw[tp->t_line].l_close)(tp, flag);
1457         rp_disc_optim(tp, &tp->t_termios, rp);
1458         rpstop(tp, FREAD | FWRITE);
1459         rphardclose(rp);
1460
1461         tp->t_state &= ~TS_BUSY;
1462         ttyclose(tp);
1463
1464         splx(oldspl);
1465
1466         return(0);
1467 }
1468
1469 static void
1470 rphardclose(struct rp_port *rp)
1471 {
1472         int     mynor;
1473         struct  tty     *tp;
1474         CHANNEL_t       *cp;
1475
1476         cp = &rp->rp_channel;
1477         tp = rp->rp_tty;
1478         mynor = MINOR_MAGIC(tp->t_dev);
1479
1480         sFlushRxFIFO(cp);
1481         sFlushTxFIFO(cp);
1482         sDisTransmit(cp);
1483         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1484         sDisRTSFlowCtl(cp);
1485         sDisCTSFlowCtl(cp);
1486         sDisTxSoftFlowCtl(cp);
1487         sClrTxXOFF(cp);
1488
1489         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1490                 sClrDTR(cp);
1491         }
1492         if(IS_CALLOUT(tp->t_dev)) {
1493                 sClrDTR(cp);
1494         }
1495         if(rp->dtr_wait != 0) {
1496                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1497                 rp->state |= ~SET_DTR;
1498         }
1499
1500         rp->active_out = FALSE;
1501         wakeup(&rp->active_out);
1502         wakeup(TSA_CARR_ON(tp));
1503 }
1504
1505 static
1506 int
1507 rpwrite(dev, uio, flag)
1508         dev_t   dev;
1509         struct  uio     *uio;
1510         int     flag;
1511 {
1512         struct  rp_port *rp;
1513         struct  tty     *tp;
1514         int     unit, mynor, port, umynor, error = 0; /* SG */
1515
1516    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1517         port  = (minor(dev) & 0x1f);                /* SG */
1518         mynor = (port + umynor);                    /* SG */
1519    unit = minor_to_unit[mynor];                /* SG */
1520
1521         if(IS_CONTROL(dev))
1522                 return(ENODEV);
1523         rp = rp_addr(unit) + port;
1524         tp = rp->rp_tty;
1525         while(rp->rp_disable_writes) {
1526                 rp->rp_waiting = 1;
1527                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1528                 if (error)
1529                         return(error);
1530         }
1531
1532         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1533         return error;
1534 }
1535
1536 static void
1537 rpdtrwakeup(void *chan)
1538 {
1539         struct  rp_port *rp;
1540
1541         rp = (struct rp_port *)chan;
1542         rp->state &= SET_DTR;
1543         wakeup(&rp->dtr_wait);
1544 }
1545
1546 int
1547 rpioctl(dev, cmd, data, flag, p)
1548         dev_t   dev;
1549         u_long  cmd;
1550         caddr_t data;
1551         int     flag;
1552         struct  proc    *p;
1553 {
1554         struct rp_port  *rp;
1555         CHANNEL_t       *cp;
1556         struct tty      *tp;
1557         int     unit, mynor, port, umynor;            /* SG */
1558         int     oldspl;
1559         int     error = 0;
1560         int     arg, flags, result, ChanStatus;
1561         int     oldcmd;
1562         struct  termios term, *t;
1563
1564    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1565         port  = (minor(dev) & 0x1f);                /* SG */
1566         mynor = (port + umynor);                    /* SG */
1567         unit = minor_to_unit[mynor];
1568         rp = rp_addr(unit) + port;
1569
1570         if(IS_CONTROL(dev)) {
1571                 struct  termios *ct;
1572
1573                 switch (IS_CONTROL(dev)) {
1574                 case CONTROL_INIT_STATE:
1575                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1576                         break;
1577                 case CONTROL_LOCK_STATE:
1578                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1579                         break;
1580                 default:
1581                         return(ENODEV);         /* /dev/nodev */
1582                 }
1583                 switch (cmd) {
1584                 case TIOCSETA:
1585                         error = suser(td);
1586                         if(error != 0)
1587                                 return(error);
1588                         *ct = *(struct termios *)data;
1589                         return(0);
1590                 case TIOCGETA:
1591                         *(struct termios *)data = *ct;
1592                         return(0);
1593                 case TIOCGETD:
1594                         *(int *)data = TTYDISC;
1595                         return(0);
1596                 case TIOCGWINSZ:
1597                         bzero(data, sizeof(struct winsize));
1598                         return(0);
1599                 default:
1600                         return(ENOTTY);
1601                 }
1602         }
1603
1604         tp = rp->rp_tty;
1605         cp = &rp->rp_channel;
1606
1607 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1608         term = tp->t_termios;
1609         oldcmd = cmd;
1610         error = ttsetcompat(tp, &cmd, data, &term);
1611         if(error != 0)
1612                 return(error);
1613         if(cmd != oldcmd) {
1614                 data = (caddr_t)&term;
1615         }
1616 #endif
1617         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1618                 int     cc;
1619                 struct  termios *dt = (struct termios *)data;
1620                 struct  termios *lt = IS_CALLOUT(dev)
1621                                         ? &rp->lt_out : &rp->lt_in;
1622
1623                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1624                                 | (dt->c_iflag & ~lt->c_iflag);
1625                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1626                                 | (dt->c_oflag & ~lt->c_oflag);
1627                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1628                                 | (dt->c_cflag & ~lt->c_cflag);
1629                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1630                                 | (dt->c_lflag & ~lt->c_lflag);
1631                 for(cc = 0; cc < NCCS; ++cc)
1632                         if(lt->c_cc[cc] != 0)
1633                                 dt->c_cc[cc] = tp->t_cc[cc];
1634                 if(lt->c_ispeed != 0)
1635                         dt->c_ispeed = tp->t_ispeed;
1636                 if(lt->c_ospeed != 0)
1637                         dt->c_ospeed = tp->t_ospeed;
1638         }
1639
1640         t = &tp->t_termios;
1641
1642         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1643         if(error != ENOIOCTL) {
1644                 return(error);
1645         }
1646         oldspl = spltty();
1647
1648         flags = rp->rp_channel.TxControl[3];
1649
1650         error = ttioctl(tp, cmd, data, flag);
1651         flags = rp->rp_channel.TxControl[3];
1652         rp_disc_optim(tp, &tp->t_termios, rp);
1653         if(error != ENOIOCTL) {
1654                 splx(oldspl);
1655                 return(error);
1656         }
1657         switch(cmd) {
1658         case TIOCSBRK:
1659                 sSendBreak(&rp->rp_channel);
1660                 break;
1661
1662         case TIOCCBRK:
1663                 sClrBreak(&rp->rp_channel);
1664                 break;
1665
1666         case TIOCSDTR:
1667                 sSetDTR(&rp->rp_channel);
1668                 sSetRTS(&rp->rp_channel);
1669                 break;
1670
1671         case TIOCCDTR:
1672                 sClrDTR(&rp->rp_channel);
1673                 break;
1674
1675         case TIOCMSET:
1676                 arg = *(int *) data;
1677                 flags = 0;
1678                 if(arg & TIOCM_RTS)
1679                         flags |= SET_RTS;
1680                 if(arg & TIOCM_DTR)
1681                         flags |= SET_DTR;
1682                 rp->rp_channel.TxControl[3] =
1683                         ((rp->rp_channel.TxControl[3]
1684                         & ~(SET_RTS | SET_DTR)) | flags);
1685                 sOutDW(rp->rp_channel.IndexAddr,
1686                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1687                 break;
1688         case TIOCMBIS:
1689                 arg = *(int *) data;
1690                 flags = 0;
1691                 if(arg & TIOCM_RTS)
1692                         flags |= SET_RTS;
1693                 if(arg & TIOCM_DTR)
1694                         flags |= SET_DTR;
1695                         rp->rp_channel.TxControl[3] |= flags;
1696                 sOutDW(rp->rp_channel.IndexAddr,
1697                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1698                 break;
1699         case TIOCMBIC:
1700                 arg = *(int *) data;
1701                 flags = 0;
1702                 if(arg & TIOCM_RTS)
1703                         flags |= SET_RTS;
1704                 if(arg & TIOCM_DTR)
1705                         flags |= SET_DTR;
1706                 rp->rp_channel.TxControl[3] &= ~flags;
1707                 sOutDW(rp->rp_channel.IndexAddr,
1708                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1709                 break;
1710
1711
1712         case TIOCMGET:
1713                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1714                 flags = rp->rp_channel.TxControl[3];
1715                 result = TIOCM_LE; /* always on while open for some reason */
1716                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1717                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1718                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1719                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1720                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1721
1722                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1723                 {
1724                         result |= TIOCM_RTS;
1725                 }
1726
1727                 *(int *)data = result;
1728                 break;
1729         case TIOCMSDTRWAIT:
1730                 error = suser(td);
1731                 if(error != 0) {
1732                         splx(oldspl);
1733                         return(error);
1734                 }
1735                 rp->dtr_wait = *(int *)data * hz/100;
1736                 break;
1737         case TIOCMGDTRWAIT:
1738                 *(int *)data = rp->dtr_wait * 100/hz;
1739                 break;
1740         default:
1741                 splx(oldspl);
1742                 return ENOTTY;
1743         }
1744         splx(oldspl);
1745         return(0);
1746 }
1747
1748 static struct speedtab baud_table[] = {
1749         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
1750         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
1751         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
1752         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
1753         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
1754         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
1755                                 {B57600, BRD57600},     {B76800, BRD76800},
1756         {B115200, BRD115200},   {B230400, BRD230400},
1757         -1,     -1
1758 };
1759
1760 static int
1761 rpparam(tp, t)
1762         struct tty *tp;
1763         struct termios *t;
1764 {
1765         struct rp_port  *rp;
1766         CHANNEL_t       *cp;
1767         int     unit, mynor, port, umynor;               /* SG */
1768         int     oldspl, cflag, iflag, oflag, lflag;
1769         int     ospeed;
1770
1771
1772    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1773         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1774         mynor = (port + umynor);                          /* SG */
1775
1776         unit = minor_to_unit[mynor];
1777         rp = rp_addr(unit) + port;
1778         cp = &rp->rp_channel;
1779         oldspl = spltty();
1780
1781         cflag = t->c_cflag;
1782         iflag = t->c_iflag;
1783         oflag = t->c_oflag;
1784         lflag = t->c_lflag;
1785
1786         ospeed = ttspeedtab(t->c_ispeed, baud_table);
1787         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1788                 return(EINVAL);
1789
1790         tp->t_ispeed = t->c_ispeed;
1791         tp->t_ospeed = t->c_ospeed;
1792         tp->t_cflag = cflag;
1793         tp->t_iflag = iflag;
1794         tp->t_oflag = oflag;
1795         tp->t_lflag = lflag;
1796
1797         if(t->c_ospeed == 0) {
1798                 sClrDTR(cp);
1799                 return(0);
1800         }
1801         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1802
1803         /* Set baud rate ----- we only pay attention to ispeed */
1804         sSetDTR(cp);
1805         sSetRTS(cp);
1806         sSetBaud(cp, ospeed);
1807
1808         if(cflag & CSTOPB) {
1809                 sSetStop2(cp);
1810         } else {
1811                 sSetStop1(cp);
1812         }
1813
1814         if(cflag & PARENB) {
1815                 sEnParity(cp);
1816                 if(cflag & PARODD) {
1817                         sSetOddParity(cp);
1818                 } else {
1819                         sSetEvenParity(cp);
1820                 }
1821         }
1822         else {
1823                 sDisParity(cp);
1824         }
1825         if((cflag & CSIZE) == CS8) {
1826                 sSetData8(cp);
1827                 rp->rp_imask = 0xFF;
1828         } else {
1829                 sSetData7(cp);
1830                 rp->rp_imask = 0x7F;
1831         }
1832
1833         if(iflag & ISTRIP) {
1834                 rp->rp_imask &= 0x7F;
1835         }
1836
1837         if(cflag & CLOCAL) {
1838                 rp->rp_intmask &= ~DELTA_CD;
1839         } else {
1840                 rp->rp_intmask |= DELTA_CD;
1841         }
1842
1843         /* Put flow control stuff here */
1844
1845         if(cflag & CCTS_OFLOW) {
1846                 sEnCTSFlowCtl(cp);
1847         } else {
1848                 sDisCTSFlowCtl(cp);
1849         }
1850
1851         if(cflag & CRTS_IFLOW) {
1852                 rp->rp_rts_iflow = 1;
1853         } else {
1854                 rp->rp_rts_iflow = 0;
1855         }
1856
1857         if(cflag & CRTS_IFLOW) {
1858                 sEnRTSFlowCtl(cp);
1859         } else {
1860                 sDisRTSFlowCtl(cp);
1861         }
1862         rp_disc_optim(tp, t, rp);
1863
1864         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1865                 tp->t_state |= TS_CARR_ON;
1866                 wakeup(TSA_CARR_ON(tp));
1867         }
1868
1869 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
1870         flags = rp->rp_channel.TxControl[3];
1871         if(flags & SET_DTR)
1872         else
1873         if(flags & SET_RTS)
1874         else
1875 */
1876         splx(oldspl);
1877
1878         return(0);
1879 }
1880
1881 static void
1882 rp_disc_optim(tp, t, rp)
1883 struct  tty     *tp;
1884 struct  termios *t;
1885 struct  rp_port *rp;
1886 {
1887         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1888                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1889                 &&(!(t->c_iflag & PARMRK)
1890                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1891                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1892                 && linesw[tp->t_line].l_rint == ttyinput)
1893                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1894         else
1895                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1896 }
1897
1898 static void
1899 rpstart(tp)
1900         struct tty *tp;
1901 {
1902         struct rp_port  *rp;
1903         CHANNEL_t       *cp;
1904         struct  clist   *qp;
1905         int     unit, mynor, port, umynor;               /* SG */
1906         char    ch, flags;
1907         int     spl, xmit_fifo_room;
1908         int     count;
1909
1910
1911    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1912         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1913         mynor = (port + umynor);                          /* SG */
1914         unit = minor_to_unit[mynor];
1915         rp = rp_addr(unit) + port;
1916         cp = &rp->rp_channel;
1917         flags = rp->rp_channel.TxControl[3];
1918         spl = spltty();
1919
1920         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1921                 ttwwakeup(tp);
1922                 splx(spl);
1923                 return;
1924         }
1925         if(rp->rp_xmit_stopped) {
1926                 sEnTransmit(cp);
1927                 rp->rp_xmit_stopped = 0;
1928         }
1929         count = sGetTxCnt(cp);
1930
1931         if(tp->t_outq.c_cc == 0) {
1932                 if((tp->t_state & TS_BUSY) && (count == 0)) {
1933                         tp->t_state &= ~TS_BUSY;
1934                 }
1935                 ttwwakeup(tp);
1936                 splx(spl);
1937                 return;
1938         }
1939         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1940         qp = &tp->t_outq;
1941         count = 0;
1942         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1943                 tp->t_state |= TS_BUSY;
1944         }
1945         while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1946                 ch = getc(qp);
1947                 sOutB(sGetTxRxDataIO(cp), ch);
1948                 xmit_fifo_room--;
1949                 count++;
1950         }
1951         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1952
1953         ttwwakeup(tp);
1954         splx(spl);
1955 }
1956
1957 static
1958 void
1959 rpstop(tp, flag)
1960         register struct tty *tp;
1961         int     flag;
1962 {
1963         struct rp_port  *rp;
1964         CHANNEL_t       *cp;
1965         int     unit, mynor, port, umynor;                  /* SG */
1966         int     spl;
1967
1968    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1969         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1970         mynor = (port + umynor);                          /* SG */
1971         unit = minor_to_unit[mynor];
1972         rp = rp_addr(unit) + port;
1973         cp = &rp->rp_channel;
1974
1975         spl = spltty();
1976
1977         if(tp->t_state & TS_BUSY) {
1978                 if((tp->t_state&TS_TTSTOP) == 0) {
1979                         sFlushTxFIFO(cp);
1980                 } else {
1981                         if(rp->rp_xmit_stopped == 0) {
1982                                 sDisTransmit(cp);
1983                                 rp->rp_xmit_stopped = 1;
1984                         }
1985                 }
1986         }
1987         splx(spl);
1988         rpstart(tp);
1989 }