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