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