proc->thread stage 2: MAJOR revamping of system calls, ucred, jail API,
[dragonfly.git] / sys / dev / serial / rp / rp.c
1 /* 
2  * Copyright (c) Comtrol Corporation <support@comtrol.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted prodived that the follwoing conditions
7  * are met.
8  * 1. Redistributions of source code must retain the above copyright 
9  *    notive, this list of conditions and the following disclainer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials prodided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *       This product includes software developed by Comtrol Corporation.
16  * 4. The name of Comtrol Corporation may not be used to endorse or 
17  *    promote products derived from this software without specific 
18  *    prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/dev/rp/rp.c,v 1.45.2.2 2002/11/07 22:26:59 tegge Exp $
33  * $DragonFly: src/sys/dev/serial/rp/rp.c,v 1.3 2003/06/23 17:55:33 dillon Exp $
34  */
35
36 /* 
37  * rp.c - for RocketPort FreeBSD
38  */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/fcntl.h>
43 #include <sys/malloc.h>
44 #include <sys/tty.h>
45 #include <sys/proc.h>
46 #include <sys/dkstat.h>
47 #include <sys/conf.h>
48 #include <sys/kernel.h>
49 #include <machine/resource.h>
50 #include <machine/bus.h>
51 #include <sys/bus.h>
52 #include <sys/rman.h>
53
54 #define ROCKET_C
55 #include <dev/rp/rpreg.h>
56 #include <dev/rp/rpvar.h>
57
58 static const char RocketPortVersion[] = "3.02";
59
60 static Byte_t RData[RDATASIZE] =
61 {
62    0x00, 0x09, 0xf6, 0x82,
63    0x02, 0x09, 0x86, 0xfb,
64    0x04, 0x09, 0x00, 0x0a,
65    0x06, 0x09, 0x01, 0x0a,
66    0x08, 0x09, 0x8a, 0x13,
67    0x0a, 0x09, 0xc5, 0x11,
68    0x0c, 0x09, 0x86, 0x85,
69    0x0e, 0x09, 0x20, 0x0a,
70    0x10, 0x09, 0x21, 0x0a,
71    0x12, 0x09, 0x41, 0xff,
72    0x14, 0x09, 0x82, 0x00,
73    0x16, 0x09, 0x82, 0x7b,
74    0x18, 0x09, 0x8a, 0x7d,
75    0x1a, 0x09, 0x88, 0x81,
76    0x1c, 0x09, 0x86, 0x7a,
77    0x1e, 0x09, 0x84, 0x81,
78    0x20, 0x09, 0x82, 0x7c,
79    0x22, 0x09, 0x0a, 0x0a
80 };
81
82 static Byte_t RRegData[RREGDATASIZE]=
83 {
84    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
85    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
86    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
87    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
88    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
89    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
90    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
91    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
92    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
93    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
94    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
95    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
96    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
97 };
98
99 #if 0
100 /* IRQ number to MUDBAC register 2 mapping */
101 Byte_t sIRQMap[16] =
102 {
103    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
104 };
105 #endif
106
107 Byte_t rp_sBitMapClrTbl[8] =
108 {
109    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
110 };
111
112 Byte_t rp_sBitMapSetTbl[8] =
113 {
114    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
115 };
116
117 /* Actually not used */
118 #if notdef
119 struct termios deftermios = {
120         TTYDEF_IFLAG,
121         TTYDEF_OFLAG,
122         TTYDEF_CFLAG,
123         TTYDEF_LFLAG,
124         { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
125         _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
126         CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
127         TTYDEF_SPEED,
128         TTYDEF_SPEED
129 };
130 #endif
131
132 /***************************************************************************
133 Function: sReadAiopID
134 Purpose:  Read the AIOP idenfication number directly from an AIOP.
135 Call:     sReadAiopID(CtlP, aiop)
136           CONTROLLER_T *CtlP; Ptr to controller structure
137           int aiop: AIOP index
138 Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
139                  is replace by an identifying number.
140           Flag AIOPID_NULL if no valid AIOP is found
141 Warnings: No context switches are allowed while executing this function.
142
143 */
144 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
145 {
146    Byte_t AiopID;               /* ID byte from AIOP */
147
148    rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL);     /* reset AIOP */
149    rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
150    AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
151    if(AiopID == 0x06)
152       return(1);
153    else                                /* AIOP does not exist */
154       return(-1);
155 }
156
157 /***************************************************************************
158 Function: sReadAiopNumChan
159 Purpose:  Read the number of channels available in an AIOP directly from
160           an AIOP.
161 Call:     sReadAiopNumChan(CtlP, aiop)
162           CONTROLLER_T *CtlP; Ptr to controller structure
163           int aiop: AIOP index
164 Return:   int: The number of channels available
165 Comments: The number of channels is determined by write/reads from identical
166           offsets within the SRAM address spaces for channels 0 and 4.
167           If the channel 4 space is mirrored to channel 0 it is a 4 channel
168           AIOP, otherwise it is an 8 channel.
169 Warnings: No context switches are allowed while executing this function.
170 */
171 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
172 {
173    Word_t x, y;
174
175    rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
176    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0);        /* read from SRAM, chan 0 */
177    x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
178    rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
179    y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
180    if(x != y)  /* if different must be 8 chan */
181       return(8);
182    else
183       return(4);
184 }
185
186 /***************************************************************************
187 Function: sInitChan
188 Purpose:  Initialization of a channel and channel structure
189 Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
190           CONTROLLER_T *CtlP; Ptr to controller structure
191           CHANNEL_T *ChP; Ptr to channel structure
192           int AiopNum; AIOP number within controller
193           int ChanNum; Channel number within AIOP
194 Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
195                number exceeds number of channels available in AIOP.
196 Comments: This function must be called before a channel can be used.
197 Warnings: No range checking on any of the parameters is done.
198
199           No context switches are allowed while executing this function.
200 */
201 int sInitChan(  CONTROLLER_T *CtlP,
202                 CHANNEL_T *ChP,
203                 int AiopNum,
204                 int ChanNum)
205 {
206    int i, ChOff;
207    Byte_t *ChR;
208    static Byte_t R[4];
209
210    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
211       return(FALSE);                   /* exceeds num chans in AIOP */
212
213    /* Channel, AIOP, and controller identifiers */
214    ChP->CtlP = CtlP;
215    ChP->ChanID = CtlP->AiopID[AiopNum];
216    ChP->AiopNum = AiopNum;
217    ChP->ChanNum = ChanNum;
218
219    /* Initialize the channel from the RData array */
220    for(i=0; i < RDATASIZE; i+=4)
221    {
222       R[0] = RData[i];
223       R[1] = RData[i+1] + 0x10 * ChanNum;
224       R[2] = RData[i+2];
225       R[3] = RData[i+3];
226       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
227    }
228
229    ChR = ChP->R;
230    for(i=0; i < RREGDATASIZE; i+=4)
231    {
232       ChR[i] = RRegData[i];
233       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
234       ChR[i+2] = RRegData[i+2];
235       ChR[i+3] = RRegData[i+3];
236    }
237
238    /* Indexed registers */
239    ChOff = (Word_t)ChanNum * 0x1000;
240
241    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
242    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
243    ChP->BaudDiv[2] = (Byte_t)BRD9600;
244    ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
245    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
246
247    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
248    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
249    ChP->TxControl[2] = 0;
250    ChP->TxControl[3] = 0;
251    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
252
253    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
254    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
255    ChP->RxControl[2] = 0;
256    ChP->RxControl[3] = 0;
257    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
258
259    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
260    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
261    ChP->TxEnables[2] = 0;
262    ChP->TxEnables[3] = 0;
263    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
264
265    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
266    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
267    ChP->TxCompare[2] = 0;
268    ChP->TxCompare[3] = 0;
269    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
270
271    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
272    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
273    ChP->TxReplace1[2] = 0;
274    ChP->TxReplace1[3] = 0;
275    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
276
277    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
278    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
279    ChP->TxReplace2[2] = 0;
280    ChP->TxReplace2[3] = 0;
281    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
282
283    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
284    ChP->TxFIFO = ChOff + _TX_FIFO;
285
286    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
287    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
288    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
289    rp_writech2(ChP,_INDX_DATA,0);
290    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
291    ChP->RxFIFO = ChOff + _RX_FIFO;
292
293    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
294    rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
295    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
296    rp_writech2(ChP,_INDX_DATA,0);
297    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
298    rp_writech2(ChP,_INDX_DATA,0);
299    ChP->TxPrioCnt = ChOff + _TXP_CNT;
300    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
301    rp_writech1(ChP,_INDX_DATA,0);
302    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
303    rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
304    rp_writech1(ChP,_INDX_DATA,0);
305    ChP->TxPrioBuf = ChOff + _TXP_BUF;
306    sEnRxProcessor(ChP);                /* start the Rx processor */
307
308    return(TRUE);
309 }
310
311 /***************************************************************************
312 Function: sStopRxProcessor
313 Purpose:  Stop the receive processor from processing a channel.
314 Call:     sStopRxProcessor(ChP)
315           CHANNEL_T *ChP; Ptr to channel structure
316
317 Comments: The receive processor can be started again with sStartRxProcessor().
318           This function causes the receive processor to skip over the
319           stopped channel.  It does not stop it from processing other channels.
320
321 Warnings: No context switches are allowed while executing this function.
322
323           Do not leave the receive processor stopped for more than one
324           character time.
325
326           After calling this function a delay of 4 uS is required to ensure
327           that the receive processor is no longer processing this channel.
328 */
329 void sStopRxProcessor(CHANNEL_T *ChP)
330 {
331    Byte_t R[4];
332
333    R[0] = ChP->R[0];
334    R[1] = ChP->R[1];
335    R[2] = 0x0a;
336    R[3] = ChP->R[3];
337    rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
338 }
339
340 /***************************************************************************
341 Function: sFlushRxFIFO
342 Purpose:  Flush the Rx FIFO
343 Call:     sFlushRxFIFO(ChP)
344           CHANNEL_T *ChP; Ptr to channel structure
345 Return:   void
346 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
347           while it is being flushed the receive processor is stopped
348           and the transmitter is disabled.  After these operations a
349           4 uS delay is done before clearing the pointers to allow
350           the receive processor to stop.  These items are handled inside
351           this function.
352 Warnings: No context switches are allowed while executing this function.
353 */
354 void sFlushRxFIFO(CHANNEL_T *ChP)
355 {
356    int i;
357    Byte_t Ch;                   /* channel number within AIOP */
358    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
359
360    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
361       return;                          /* don't need to flush */
362
363    RxFIFOEnabled = FALSE;
364    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
365    {
366       RxFIFOEnabled = TRUE;
367       sDisRxFIFO(ChP);                 /* disable it */
368       for(i=0; i < 2000/200; i++)       /* delay 2 uS to allow proc to disable FIFO*/
369          rp_readch1(ChP,_INT_CHAN);             /* depends on bus i/o timing */
370    }
371    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
372    Ch = (Byte_t)sGetChanNum(ChP);
373    rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
374    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Rx FIFO count */
375    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
376    rp_writech2(ChP,_INDX_DATA,0);
377    rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
378    rp_writech2(ChP,_INDX_DATA,0);
379    if(RxFIFOEnabled)
380       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
381 }
382
383 /***************************************************************************
384 Function: sFlushTxFIFO
385 Purpose:  Flush the Tx FIFO
386 Call:     sFlushTxFIFO(ChP)
387           CHANNEL_T *ChP; Ptr to channel structure
388 Return:   void
389 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
390           while it is being flushed the receive processor is stopped
391           and the transmitter is disabled.  After these operations a
392           4 uS delay is done before clearing the pointers to allow
393           the receive processor to stop.  These items are handled inside
394           this function.
395 Warnings: No context switches are allowed while executing this function.
396 */
397 void sFlushTxFIFO(CHANNEL_T *ChP)
398 {
399    int i;
400    Byte_t Ch;                   /* channel number within AIOP */
401    int TxEnabled;                      /* TRUE if transmitter enabled */
402
403    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
404       return;                          /* don't need to flush */
405
406    TxEnabled = FALSE;
407    if(ChP->TxControl[3] & TX_ENABLE)
408    {
409       TxEnabled = TRUE;
410       sDisTransmit(ChP);               /* disable transmitter */
411    }
412    sStopRxProcessor(ChP);              /* stop Rx processor */
413    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
414       rp_readch1(ChP,_INT_CHAN);        /* depends on bus i/o timing */
415    Ch = (Byte_t)sGetChanNum(ChP);
416    rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
417    rp_writech1(ChP,_CMD_REG,Ch);                       /* remove reset Tx FIFO count */
418    rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
419    rp_writech2(ChP,_INDX_DATA,0);
420    if(TxEnabled)
421       sEnTransmit(ChP);                /* enable transmitter */
422    sStartRxProcessor(ChP);             /* restart Rx processor */
423 }
424
425 /***************************************************************************
426 Function: sWriteTxPrioByte
427 Purpose:  Write a byte of priority transmit data to a channel
428 Call:     sWriteTxPrioByte(ChP,Data)
429           CHANNEL_T *ChP; Ptr to channel structure
430           Byte_t Data; The transmit data byte
431
432 Return:   int: 1 if the bytes is successfully written, otherwise 0.
433
434 Comments: The priority byte is transmitted before any data in the Tx FIFO.
435
436 Warnings: No context switches are allowed while executing this function.
437 */
438 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
439 {
440    Byte_t DWBuf[4];             /* buffer for double word writes */
441    Word_t *WordPtr;          /* must be far because Win SS != DS */
442
443    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
444    {
445       rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
446       if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
447          return(0);                    /* nothing sent */
448
449       WordPtr = (Word_t *)(&DWBuf[0]);
450       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
451
452       DWBuf[2] = Data;                 /* data byte value */
453       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
454
455       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
456
457       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
458       DWBuf[3] = 0;                    /* priority buffer pointer */
459       rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
460    }
461    else                                /* write it to Tx FIFO */
462    {
463       sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
464    }
465    return(1);                          /* 1 byte sent */
466 }
467
468 /***************************************************************************
469 Function: sEnInterrupts
470 Purpose:  Enable one or more interrupts for a channel
471 Call:     sEnInterrupts(ChP,Flags)
472           CHANNEL_T *ChP; Ptr to channel structure
473           Word_t Flags: Interrupt enable flags, can be any combination
474              of the following flags:
475                 TXINT_EN:   Interrupt on Tx FIFO empty
476                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
477                             sSetRxTrigger())
478                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
479                 MCINT_EN:   Interrupt on modem input change
480                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
481                             Interrupt Channel Register.
482 Return:   void
483 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
484           enabled.  If an interrupt enable flag is not set in Flags, that
485           interrupt will not be changed.  Interrupts can be disabled with
486           function sDisInterrupts().
487
488           This function sets the appropriate bit for the channel in the AIOP's
489           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
490           this channel's bit to be set in the AIOP's Interrupt Channel Register.
491
492           Interrupts must also be globally enabled before channel interrupts
493           will be passed on to the host.  This is done with function
494           sEnGlobalInt().
495
496           In some cases it may be desirable to disable interrupts globally but
497           enable channel interrupts.  This would allow the global interrupt
498           status register to be used to determine which AIOPs need service.
499 */
500 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
501 {
502    Byte_t Mask;                 /* Interrupt Mask Register */
503
504    ChP->RxControl[2] |=
505       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
506
507    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
508
509    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
510
511    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
512
513    if(Flags & CHANINT_EN)
514    {
515       Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
516       rp_writech1(ChP,_INT_MASK,Mask);
517    }
518 }
519
520 /***************************************************************************
521 Function: sDisInterrupts
522 Purpose:  Disable one or more interrupts for a channel
523 Call:     sDisInterrupts(ChP,Flags)
524           CHANNEL_T *ChP; Ptr to channel structure
525           Word_t Flags: Interrupt flags, can be any combination
526              of the following flags:
527                 TXINT_EN:   Interrupt on Tx FIFO empty
528                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
529                             sSetRxTrigger())
530                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
531                 MCINT_EN:   Interrupt on modem input change
532                 CHANINT_EN: Disable channel interrupt signal to the
533                             AIOP's Interrupt Channel Register.
534 Return:   void
535 Comments: If an interrupt flag is set in Flags, that interrupt will be
536           disabled.  If an interrupt flag is not set in Flags, that
537           interrupt will not be changed.  Interrupts can be enabled with
538           function sEnInterrupts().
539
540           This function clears the appropriate bit for the channel in the AIOP's
541           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
542           this channel's bit from being set in the AIOP's Interrupt Channel
543           Register.
544 */
545 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
546 {
547    Byte_t Mask;                 /* Interrupt Mask Register */
548
549    ChP->RxControl[2] &=
550          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
551    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
552    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
553    rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
554
555    if(Flags & CHANINT_EN)
556    {
557       Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
558       rp_writech1(ChP,_INT_MASK,Mask);
559    }
560 }
561
562 /*********************************************************************
563   Begin FreeBsd-specific driver code
564 **********************************************************************/
565
566 static timeout_t rpdtrwakeup;
567
568 static  d_open_t        rpopen;
569 static  d_close_t       rpclose;
570 static  d_write_t       rpwrite;
571 static  d_ioctl_t       rpioctl;
572
573 #define CDEV_MAJOR      81
574 struct cdevsw rp_cdevsw = {
575         /* open */      rpopen,
576         /* close */     rpclose,
577         /* read */      ttyread,
578         /* write */     rpwrite,
579         /* ioctl */     rpioctl,
580         /* poll */      ttypoll,
581         /* mmap */      nommap,
582         /* strategy */  nostrategy,
583         /* name */      "rp",
584         /* maj */       CDEV_MAJOR,
585         /* dump */      nodump,
586         /* psize */     nopsize,
587         /* flags */     D_TTY,
588 };
589
590 static int      rp_num_ports_open = 0;
591 static int      rp_ndevs = 0;
592 static int      minor_to_unit[128];
593
594 static int rp_num_ports[4];     /* Number of ports on each controller */
595
596 #define _INLINE_ __inline
597 #define POLL_INTERVAL 1
598
599 #define CALLOUT_MASK            0x80
600 #define CONTROL_MASK            0x60
601 #define CONTROL_INIT_STATE      0x20
602 #define CONTROL_LOCK_STATE      0x40
603 #define DEV_UNIT(dev)   (MINOR_TO_UNIT(minor(dev))
604 #define MINOR_MAGIC_MASK        (CALLOUT_MASK | CONTROL_MASK)
605 #define MINOR_MAGIC(dev)        ((minor(dev)) & ~MINOR_MAGIC_MASK)
606 #define IS_CALLOUT(dev)         (minor(dev) & CALLOUT_MASK)
607 #define IS_CONTROL(dev)         (minor(dev) & CONTROL_MASK)
608
609 #define RP_ISMULTIPORT(dev)     ((dev)->id_flags & 0x1)
610 #define RP_MPMASTER(dev)        (((dev)->id_flags >> 8) & 0xff)
611 #define RP_NOTAST4(dev)         ((dev)->id_flags & 0x04)
612
613 static  struct  rp_port *p_rp_addr[4];
614 static  struct  rp_port *p_rp_table[MAX_RP_PORTS];
615 #define rp_addr(unit)   (p_rp_addr[unit])
616 #define rp_table(port)  (p_rp_table[port])
617
618 /*
619  * The top-level routines begin here
620  */
621
622 static  int     rpparam __P((struct tty *, struct termios *));
623 static  void    rpstart __P((struct tty *));
624 static  void    rpstop __P((struct tty *, int));
625 static  void    rphardclose     __P((struct rp_port *));
626 static  void    rp_disc_optim   __P((struct tty *tp, struct termios *t));
627
628 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
629                         CHANNEL_t *cp, unsigned int ChanStatus)
630 {
631         int     spl;
632         unsigned        int     CharNStat;
633         int     ToRecv, wRecv, ch, ttynocopy;
634
635         ToRecv = sGetRxCnt(cp);
636         if(ToRecv == 0)
637                 return;
638
639 /*      If status indicates there are errored characters in the
640         FIFO, then enter status mode (a word in FIFO holds
641         characters and status)
642 */
643
644         if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
645                 if(!(ChanStatus & STATMODE)) {
646                         ChanStatus |= STATMODE;
647                         sEnRxStatusMode(cp);
648                 }
649         }
650 /*
651         if we previously entered status mode then read down the
652         FIFO one word at a time, pulling apart the character and
653         the status. Update error counters depending on status.
654 */
655         if(ChanStatus & STATMODE) {
656                 while(ToRecv) {
657                         if(tp->t_state & TS_TBLOCK) {
658                                 break;
659                         }
660                         CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
661                         ch = CharNStat & 0xff;
662
663                         if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
664                                 ch |= TTY_FE;
665                         else if (CharNStat & STMPARITYH)
666                                 ch |= TTY_PE;
667                         else if (CharNStat & STMRCVROVRH)
668                                 rp->rp_overflows++;
669
670                         (*linesw[tp->t_line].l_rint)(ch, tp);
671                         ToRecv--;
672                 }
673 /*
674         After emtying FIFO in status mode, turn off status mode
675 */
676
677                 if(sGetRxCnt(cp) == 0) {
678                         sDisRxStatusMode(cp);
679                 }
680         } else {
681                 /*
682                  * Avoid the grotesquely inefficient lineswitch routine
683                  * (ttyinput) in "raw" mode.  It usually takes about 450
684                  * instructions (that's without canonical processing or echo!).
685                  * slinput is reasonably fast (usually 40 instructions plus
686                  * call overhead).
687                  */
688                 ToRecv = sGetRxCnt(cp);
689                 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
690                         if ( ToRecv > RXFIFO_SIZE ) {
691                                 ToRecv = RXFIFO_SIZE;
692                         }
693                         wRecv = ToRecv >> 1;
694                         if ( wRecv ) {
695                                 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
696                         }
697                         if ( ToRecv & 1 ) {
698                                 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
699                         }
700                         tk_nin += ToRecv;
701                         tk_rawcc += ToRecv;
702                         tp->t_rawcc += ToRecv;
703                         ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
704                         ttwakeup(tp);
705                 } else {
706                         while (ToRecv) {
707                                 if(tp->t_state & TS_TBLOCK) {
708                                         break;
709                                 }
710                                 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
711                                 spl = spltty();
712                                 (*linesw[tp->t_line].l_rint)(ch, tp);
713                                 splx(spl);
714                                 ToRecv--;
715                         }
716                 }
717         }
718 }
719
720 static _INLINE_ void rp_handle_port(struct rp_port *rp)
721 {
722         CHANNEL_t       *cp;
723         struct  tty     *tp;
724         unsigned        int     IntMask, ChanStatus;
725
726         if(!rp)
727                 return;
728
729         cp = &rp->rp_channel;
730         tp = rp->rp_tty;
731         IntMask = sGetChanIntID(cp);
732         IntMask = IntMask & rp->rp_intmask;
733         ChanStatus = sGetChanStatus(cp);
734         if(IntMask & RXF_TRIG)
735                 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
736                         rp_do_receive(rp, tp, cp, ChanStatus);
737                 }
738         if(IntMask & DELTA_CD) {
739                 if(ChanStatus & CD_ACT) {
740                         if(!(tp->t_state & TS_CARR_ON) ) {
741                                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
742                         }
743                 } else {
744                         if((tp->t_state & TS_CARR_ON)) {
745                                 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
746                                 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
747                                         rphardclose(rp);
748                                 }
749                         }
750                 }
751         }
752 /*      oldcts = rp->rp_cts;
753         rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
754         if(oldcts != rp->rp_cts) {
755                 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
756         }
757 */
758 }
759
760 static void rp_do_poll(void *not_used)
761 {
762         CONTROLLER_t    *ctl;
763         struct rp_port  *rp;
764         struct tty      *tp;
765         int     unit, aiop, ch, line, count;
766         unsigned char   CtlMask, AiopMask;
767
768         for(unit = 0; unit < rp_ndevs; unit++) {
769         rp = rp_addr(unit);
770         ctl = rp->rp_ctlp;
771         CtlMask = ctl->ctlmask(ctl);
772         for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
773                 if(CtlMask & 1) {
774                         AiopMask = sGetAiopIntStatus(ctl, aiop);
775                         for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
776                                 if(AiopMask & 1) {
777                                         line = (unit << 5) | (aiop << 3) | ch;
778                                         rp = rp_table(line);
779                                         rp_handle_port(rp);
780                                 }
781                         }
782                 }
783         }
784
785         for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
786                         line++, rp++) {
787                 tp = rp->rp_tty;
788                 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
789                         count = sGetTxCnt(&rp->rp_channel);
790                         if(count == 0)
791                                 tp->t_state &= ~(TS_BUSY);
792                         if(!(tp->t_state & TS_TTSTOP) &&
793                                 (count <= rp->rp_restart)) {
794                                 (*linesw[tp->t_line].l_start)(tp);
795                         }
796                 }
797         }
798         }
799         if(rp_num_ports_open)
800                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
801 }
802
803 int
804 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
805 {
806         int     oldspl, unit;
807         int     num_chan;
808         int     aiop, chan, port;
809         int     ChanStatus, line, i, count;
810         int     retval;
811         struct  rp_port *rp;
812         struct  tty     *tty;
813         dev_t   *dev_nodes;
814
815         unit = device_get_unit(ctlp->dev);
816
817         printf("RocketPort%d (Version %s) %d ports.\n", unit,
818                 RocketPortVersion, num_ports);
819         rp_num_ports[unit] = num_ports;
820
821         ctlp->rp = rp = (struct rp_port *)
822                 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
823         if (rp == NULL) {
824                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
825                 retval = ENOMEM;
826                 goto nogo;
827         }
828
829         count = unit * 32;      /* board times max ports per card SG */
830         for(i=count;i < (count + rp_num_ports[unit]);i++)
831                 minor_to_unit[i] = unit;
832
833         bzero(rp, sizeof(struct rp_port) * num_ports);
834         ctlp->tty = tty = (struct tty *)
835                 malloc(sizeof(struct tty) * num_ports, M_TTYS,
836                         M_NOWAIT | M_ZERO);
837         if(tty == NULL) {
838                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
839                 retval = ENOMEM;
840                 goto nogo;
841         }
842
843         oldspl = spltty();
844         rp_addr(unit) = rp;
845         splx(oldspl);
846
847         dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
848         if(ctlp->dev_nodes == NULL) {
849                 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
850                 retval = ENOMEM;
851                 goto nogo;
852         }
853
854         for (i = 0 ; i < rp_num_ports[unit] ; i++) {
855                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
856                                           UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
857                                           i <= 9 ? '0' + i : 'a' + i - 10);
858                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
859                                           UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
860                                           i <= 9 ? '0' + i : 'a' + i - 10);
861                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
862                                           UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
863                                           i <= 9 ? '0' + i : 'a' + i - 10);
864                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
865                                           UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
866                                           i <= 9 ? '0' + i : 'a' + i - 10);
867                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
868                                           UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
869                                           i <= 9 ? '0' + i : 'a' + i - 10);
870                 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
871                                           UID_ROOT, GID_WHEEL, 0666, "cualR%c",
872                                           i <= 9 ? '0' + i : 'a' + i - 10);
873         }
874
875         port = 0;
876         for(aiop=0; aiop < num_aiops; aiop++) {
877                 num_chan = sGetAiopNumChan(ctlp, aiop);
878                 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
879                         rp->rp_tty = tty;
880                         rp->rp_port = port;
881                         rp->rp_ctlp = ctlp;
882                         rp->rp_unit = unit;
883                         rp->rp_chan = chan;
884                         rp->rp_aiop = aiop;
885
886                         tty->t_line = 0;
887         /*              tty->t_termios = deftermios;
888         */
889                         rp->dtr_wait = 3 * hz;
890                         rp->it_in.c_iflag = 0;
891                         rp->it_in.c_oflag = 0;
892                         rp->it_in.c_cflag = TTYDEF_CFLAG;
893                         rp->it_in.c_lflag = 0;
894                         termioschars(&rp->it_in);
895         /*              termioschars(&tty->t_termios);
896         */
897                         rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
898                         rp->it_out = rp->it_in;
899
900                         rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
901                                 DELTA_CD | DELTA_CTS | DELTA_DSR;
902 #if notdef
903                         ChanStatus = sGetChanStatus(&rp->rp_channel);
904 #endif /* notdef */
905                         if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
906                                 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
907                                               unit, aiop, chan);
908                                 retval = ENXIO;
909                                 goto nogo;
910                         }
911                         ChanStatus = sGetChanStatus(&rp->rp_channel);
912                         rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
913                         line = (unit << 5) | (aiop << 3) | chan;
914                         rp_table(line) = rp;
915                 }
916         }
917
918         rp_ndevs++;
919         return (0);
920
921 nogo:
922         rp_releaseresource(ctlp);
923
924         return (retval);
925 }
926
927 void
928 rp_releaseresource(CONTROLLER_t *ctlp)
929 {
930         int i, s, unit;
931
932         unit = device_get_unit(ctlp->dev);
933
934         if (ctlp->rp != NULL) {
935                 s = spltty();
936                 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
937                         if (p_rp_addr[i] == ctlp->rp)
938                                 p_rp_addr[i] = NULL;
939                 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
940                         if (p_rp_table[i] == ctlp->rp)
941                                 p_rp_table[i] = NULL;
942                 splx(s);
943                 free(ctlp->rp, M_DEVBUF);
944                 ctlp->rp = NULL;
945         }
946         if (ctlp->tty != NULL) {
947                 free(ctlp->tty, M_DEVBUF);
948                 ctlp->tty = NULL;
949         }
950         if (ctlp->dev != NULL) {
951                 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
952                         destroy_dev(ctlp->dev_nodes[i]);
953                 free(ctlp->dev_nodes, M_DEVBUF);
954                 ctlp->dev = NULL;
955         }
956 }
957
958 int
959 rpopen(dev_t dev, int flag, int mode, d_thread_t *td)
960 {
961         struct  rp_port *rp;
962         int     unit, port, mynor, umynor, flags;  /* SG */
963         struct  tty     *tp;
964         int     oldspl, error;
965         unsigned int    IntMask, ChanStatus;
966         struct proc *p = td->td_proc;
967
968         KKASSERT(p != NULL);
969
970    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
971         port  = (minor(dev) & 0x1f);                /* SG */
972         mynor = (port + umynor);                    /* SG */
973         unit = minor_to_unit[mynor];
974         if (rp_addr(unit) == NULL)
975                 return (ENXIO);
976         if(IS_CONTROL(dev))
977                 return(0);
978         rp = rp_addr(unit) + port;
979 /*      rp->rp_tty = &rp_tty[rp->rp_port];
980 */
981         tp = rp->rp_tty;
982         dev->si_tty = tp;
983
984         oldspl = spltty();
985
986 open_top:
987         while(rp->state & ~SET_DTR) {
988                 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
989                 if(error != 0)
990                         goto out;
991         }
992
993         if(tp->t_state & TS_ISOPEN) {
994                 if(IS_CALLOUT(dev)) {
995                         if(!rp->active_out) {
996                                 error = EBUSY;
997                                 goto out;
998                         }
999                 } else {
1000                         if(rp->active_out) {
1001                                 if(flag & O_NONBLOCK) {
1002                                         error = EBUSY;
1003                                         goto out;
1004                                 }
1005                                 error = tsleep(&rp->active_out,
1006                                         TTIPRI | PCATCH, "rpbi", 0);
1007                                 if(error != 0)
1008                                         goto out;
1009                                 goto open_top;
1010                         }
1011                 }
1012                 if(tp->t_state & TS_XCLUDE && suser_xxx(p->p_ucred, 0) != 0) {
1013                         splx(oldspl);
1014                         error = EBUSY;
1015                         goto out2;
1016                 }
1017         }
1018         else {
1019                 tp->t_dev = dev;
1020                 tp->t_param = rpparam;
1021                 tp->t_oproc = rpstart;
1022                 tp->t_stop = rpstop;
1023                 tp->t_line = 0;
1024                 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1025                 tp->t_ififosize = 512;
1026                 tp->t_ispeedwat = (speed_t)-1;
1027                 tp->t_ospeedwat = (speed_t)-1;
1028                 flags = 0;
1029                 flags |= SET_RTS;
1030                 flags |= SET_DTR;
1031                 rp->rp_channel.TxControl[3] =
1032                         ((rp->rp_channel.TxControl[3]
1033                         & ~(SET_RTS | SET_DTR)) | flags);
1034                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1035                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1036                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1037                 sDisRxStatusMode(&rp->rp_channel);
1038                 sFlushRxFIFO(&rp->rp_channel);
1039                 sFlushTxFIFO(&rp->rp_channel);
1040
1041                 sEnInterrupts(&rp->rp_channel,
1042                         (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1043                 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1044
1045                 sDisRxStatusMode(&rp->rp_channel);
1046                 sClrTxXOFF(&rp->rp_channel);
1047
1048 /*              sDisRTSFlowCtl(&rp->rp_channel);
1049                 sDisCTSFlowCtl(&rp->rp_channel);
1050 */
1051                 sDisTxSoftFlowCtl(&rp->rp_channel);
1052
1053                 sStartRxProcessor(&rp->rp_channel);
1054
1055                 sEnRxFIFO(&rp->rp_channel);
1056                 sEnTransmit(&rp->rp_channel);
1057
1058 /*              sSetDTR(&rp->rp_channel);
1059                 sSetRTS(&rp->rp_channel);
1060 */
1061
1062                 ++rp->wopeners;
1063                 error = rpparam(tp, &tp->t_termios);
1064                 --rp->wopeners;
1065                 if(error != 0) {
1066                         splx(oldspl);
1067                         return(error);
1068                 }
1069
1070                 rp_num_ports_open++;
1071
1072                 IntMask = sGetChanIntID(&rp->rp_channel);
1073                 IntMask = IntMask & rp->rp_intmask;
1074                 ChanStatus = sGetChanStatus(&rp->rp_channel);
1075                 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1076                         if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1077                                         (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1078                         }
1079                 }
1080
1081         if(rp_num_ports_open == 1)
1082                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1083
1084         }
1085
1086         if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1087                 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1088                 ++rp->wopeners;
1089                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1090                                 "rpdcd", 0);
1091                 --rp->wopeners;
1092                 if(error != 0)
1093                         goto out;
1094                 goto open_top;
1095         }
1096         error = (*linesw[tp->t_line].l_open)(dev, tp);
1097
1098         rp_disc_optim(tp, &tp->t_termios);
1099         if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1100                 rp->active_out = TRUE;
1101
1102 /*      if(rp_num_ports_open == 1)
1103                 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1104 */
1105 out:
1106         splx(oldspl);
1107         if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1108                 rphardclose(rp);
1109         }
1110 out2:
1111         if (error == 0)
1112                 device_busy(rp->rp_ctlp->dev);
1113         return(error);
1114 }
1115
1116 int
1117 rpclose(dev_t dev, int flag, int mode, d_thread_t *td)
1118 {
1119         int     oldspl, unit, mynor, umynor, port; /* SG */
1120         struct  rp_port *rp;
1121         struct  tty     *tp;
1122         CHANNEL_t       *cp;
1123
1124    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1125         port  = (minor(dev) & 0x1f);                /* SG */
1126         mynor = (port + umynor);                    /* SG */
1127    unit = minor_to_unit[mynor];                /* SG */
1128
1129         if(IS_CONTROL(dev))
1130                 return(0);
1131         rp = rp_addr(unit) + port;
1132         cp = &rp->rp_channel;
1133         tp = rp->rp_tty;
1134
1135         oldspl = spltty();
1136         (*linesw[tp->t_line].l_close)(tp, flag);
1137         rp_disc_optim(tp, &tp->t_termios);
1138         rpstop(tp, FREAD | FWRITE);
1139         rphardclose(rp);
1140
1141         tp->t_state &= ~TS_BUSY;
1142         ttyclose(tp);
1143
1144         splx(oldspl);
1145
1146         device_unbusy(rp->rp_ctlp->dev);
1147
1148         return(0);
1149 }
1150
1151 static void
1152 rphardclose(struct rp_port *rp)
1153 {
1154         int     mynor;
1155         struct  tty     *tp;
1156         CHANNEL_t       *cp;
1157
1158         cp = &rp->rp_channel;
1159         tp = rp->rp_tty;
1160         mynor = MINOR_MAGIC(tp->t_dev);
1161
1162         sFlushRxFIFO(cp);
1163         sFlushTxFIFO(cp);
1164         sDisTransmit(cp);
1165         sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1166         sDisRTSFlowCtl(cp);
1167         sDisCTSFlowCtl(cp);
1168         sDisTxSoftFlowCtl(cp);
1169         sClrTxXOFF(cp);
1170
1171         if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1172                 sClrDTR(cp);
1173         }
1174         if(IS_CALLOUT(tp->t_dev)) {
1175                 sClrDTR(cp);
1176         }
1177         if(rp->dtr_wait != 0) {
1178                 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1179                 rp->state |= ~SET_DTR;
1180         }
1181
1182         rp->active_out = FALSE;
1183         wakeup(&rp->active_out);
1184         wakeup(TSA_CARR_ON(tp));
1185 }
1186
1187 static
1188 int
1189 rpwrite(dev, uio, flag)
1190         dev_t   dev;
1191         struct  uio     *uio;
1192         int     flag;
1193 {
1194         struct  rp_port *rp;
1195         struct  tty     *tp;
1196         int     unit, mynor, port, umynor, error = 0; /* SG */
1197
1198    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1199         port  = (minor(dev) & 0x1f);                /* SG */
1200         mynor = (port + umynor);                    /* SG */
1201    unit = minor_to_unit[mynor];                /* SG */
1202
1203         if(IS_CONTROL(dev))
1204                 return(ENODEV);
1205         rp = rp_addr(unit) + port;
1206         tp = rp->rp_tty;
1207         while(rp->rp_disable_writes) {
1208                 rp->rp_waiting = 1;
1209                 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1210                 if (error)
1211                         return(error);
1212         }
1213
1214         error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1215         return error;
1216 }
1217
1218 static void
1219 rpdtrwakeup(void *chan)
1220 {
1221         struct  rp_port *rp;
1222
1223         rp = (struct rp_port *)chan;
1224         rp->state &= SET_DTR;
1225         wakeup(&rp->dtr_wait);
1226 }
1227
1228 int
1229 rpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, d_thread_t *td)
1230 {
1231         struct rp_port  *rp;
1232         CHANNEL_t       *cp;
1233         struct tty      *tp;
1234         int     unit, mynor, port, umynor;            /* SG */
1235         int     oldspl;
1236         int     error = 0;
1237         int     arg, flags, result, ChanStatus;
1238         struct  termios *t;
1239         struct proc *p = td->td_proc;
1240
1241         KKASSERT(p != NULL);
1242
1243    umynor = (((minor(dev) >> 16) -1) * 32);    /* SG */
1244         port  = (minor(dev) & 0x1f);                /* SG */
1245         mynor = (port + umynor);                    /* SG */
1246         unit = minor_to_unit[mynor];
1247         rp = rp_addr(unit) + port;
1248
1249         if(IS_CONTROL(dev)) {
1250                 struct  termios *ct;
1251
1252                 switch (IS_CONTROL(dev)) {
1253                 case CONTROL_INIT_STATE:
1254                         ct =  IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1255                         break;
1256                 case CONTROL_LOCK_STATE:
1257                         ct =  IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1258                         break;
1259                 default:
1260                         return(ENODEV);         /* /dev/nodev */
1261                 }
1262                 switch (cmd) {
1263                 case TIOCSETA:
1264                         error = suser_xxx(p->p_ucred, 0);
1265                         if(error != 0)
1266                                 return(error);
1267                         *ct = *(struct termios *)data;
1268                         return(0);
1269                 case TIOCGETA:
1270                         *(struct termios *)data = *ct;
1271                         return(0);
1272                 case TIOCGETD:
1273                         *(int *)data = TTYDISC;
1274                         return(0);
1275                 case TIOCGWINSZ:
1276                         bzero(data, sizeof(struct winsize));
1277                         return(0);
1278                 default:
1279                         return(ENOTTY);
1280                 }
1281         }
1282
1283         tp = rp->rp_tty;
1284         cp = &rp->rp_channel;
1285
1286 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1287         term = tp->t_termios;
1288         oldcmd = cmd;
1289         error = ttsetcompat(tp, &cmd, data, &term);
1290         if(error != 0)
1291                 return(error);
1292         if(cmd != oldcmd) {
1293                 data = (caddr_t)&term;
1294         }
1295 #endif
1296         if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1297                 int     cc;
1298                 struct  termios *dt = (struct termios *)data;
1299                 struct  termios *lt = IS_CALLOUT(dev)
1300                                         ? &rp->lt_out : &rp->lt_in;
1301
1302                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1303                                 | (dt->c_iflag & ~lt->c_iflag);
1304                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1305                                 | (dt->c_oflag & ~lt->c_oflag);
1306                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1307                                 | (dt->c_cflag & ~lt->c_cflag);
1308                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1309                                 | (dt->c_lflag & ~lt->c_lflag);
1310                 for(cc = 0; cc < NCCS; ++cc)
1311                         if(lt->c_cc[cc] != 0)
1312                                 dt->c_cc[cc] = tp->t_cc[cc];
1313                 if(lt->c_ispeed != 0)
1314                         dt->c_ispeed = tp->t_ispeed;
1315                 if(lt->c_ospeed != 0)
1316                         dt->c_ospeed = tp->t_ospeed;
1317         }
1318
1319         t = &tp->t_termios;
1320
1321         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
1322         if(error != ENOIOCTL) {
1323                 return(error);
1324         }
1325         oldspl = spltty();
1326
1327         flags = rp->rp_channel.TxControl[3];
1328
1329         error = ttioctl(tp, cmd, data, flag);
1330         flags = rp->rp_channel.TxControl[3];
1331         rp_disc_optim(tp, &tp->t_termios);
1332         if(error != ENOIOCTL) {
1333                 splx(oldspl);
1334                 return(error);
1335         }
1336         switch(cmd) {
1337         case TIOCSBRK:
1338                 sSendBreak(&rp->rp_channel);
1339                 break;
1340
1341         case TIOCCBRK:
1342                 sClrBreak(&rp->rp_channel);
1343                 break;
1344
1345         case TIOCSDTR:
1346                 sSetDTR(&rp->rp_channel);
1347                 sSetRTS(&rp->rp_channel);
1348                 break;
1349
1350         case TIOCCDTR:
1351                 sClrDTR(&rp->rp_channel);
1352                 break;
1353
1354         case TIOCMSET:
1355                 arg = *(int *) data;
1356                 flags = 0;
1357                 if(arg & TIOCM_RTS)
1358                         flags |= SET_RTS;
1359                 if(arg & TIOCM_DTR)
1360                         flags |= SET_DTR;
1361                 rp->rp_channel.TxControl[3] =
1362                         ((rp->rp_channel.TxControl[3]
1363                         & ~(SET_RTS | SET_DTR)) | flags);
1364                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1365                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1366                 break;
1367         case TIOCMBIS:
1368                 arg = *(int *) data;
1369                 flags = 0;
1370                 if(arg & TIOCM_RTS)
1371                         flags |= SET_RTS;
1372                 if(arg & TIOCM_DTR)
1373                         flags |= SET_DTR;
1374                         rp->rp_channel.TxControl[3] |= flags;
1375                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1376                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1377                 break;
1378         case TIOCMBIC:
1379                 arg = *(int *) data;
1380                 flags = 0;
1381                 if(arg & TIOCM_RTS)
1382                         flags |= SET_RTS;
1383                 if(arg & TIOCM_DTR)
1384                         flags |= SET_DTR;
1385                 rp->rp_channel.TxControl[3] &= ~flags;
1386                 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1387                         *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1388                 break;
1389
1390
1391         case TIOCMGET:
1392                 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1393                 flags = rp->rp_channel.TxControl[3];
1394                 result = TIOCM_LE; /* always on while open for some reason */
1395                 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1396                         | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1397                         | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1398                         | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1399                         | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1400
1401                 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1402                 {
1403                         result |= TIOCM_RTS;
1404                 }
1405
1406                 *(int *)data = result;
1407                 break;
1408         case TIOCMSDTRWAIT:
1409                 error = suser_xxx(p->p_ucred, 0);
1410                 if(error != 0) {
1411                         splx(oldspl);
1412                         return(error);
1413                 }
1414                 rp->dtr_wait = *(int *)data * hz/100;
1415                 break;
1416         case TIOCMGDTRWAIT:
1417                 *(int *)data = rp->dtr_wait * 100/hz;
1418                 break;
1419         default:
1420                 splx(oldspl);
1421                 return ENOTTY;
1422         }
1423         splx(oldspl);
1424         return(0);
1425 }
1426
1427 static struct speedtab baud_table[] = {
1428         {B0,    0},             {B50,   BRD50},         {B75,   BRD75},
1429         {B110,  BRD110},        {B134,  BRD134},        {B150,  BRD150},
1430         {B200,  BRD200},        {B300,  BRD300},        {B600,  BRD600},
1431         {B1200, BRD1200},       {B1800, BRD1800},       {B2400, BRD2400},
1432         {B4800, BRD4800},       {B9600, BRD9600},       {B19200, BRD19200},
1433         {B38400, BRD38400},     {B7200, BRD7200},       {B14400, BRD14400},
1434                                 {B57600, BRD57600},     {B76800, BRD76800},
1435         {B115200, BRD115200},   {B230400, BRD230400},
1436         {-1,    -1}
1437 };
1438
1439 static int
1440 rpparam(tp, t)
1441         struct tty *tp;
1442         struct termios *t;
1443 {
1444         struct rp_port  *rp;
1445         CHANNEL_t       *cp;
1446         int     unit, mynor, port, umynor;               /* SG */
1447         int     oldspl, cflag, iflag, oflag, lflag;
1448         int     ospeed;
1449 #ifdef RPCLOCAL
1450         int     devshift;
1451 #endif
1452
1453
1454    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1455         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1456         mynor = (port + umynor);                          /* SG */
1457
1458         unit = minor_to_unit[mynor];
1459         rp = rp_addr(unit) + port;
1460         cp = &rp->rp_channel;
1461         oldspl = spltty();
1462
1463         cflag = t->c_cflag;
1464 #ifdef RPCLOCAL
1465         devshift = umynor / 32;
1466         devshift = 1 << devshift;
1467         if ( devshift & RPCLOCAL ) {
1468                 cflag |= CLOCAL;
1469         }
1470 #endif
1471         iflag = t->c_iflag;
1472         oflag = t->c_oflag;
1473         lflag = t->c_lflag;
1474
1475         ospeed = ttspeedtab(t->c_ispeed, baud_table);
1476         if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1477                 return(EINVAL);
1478
1479         tp->t_ispeed = t->c_ispeed;
1480         tp->t_ospeed = t->c_ospeed;
1481         tp->t_cflag = cflag;
1482         tp->t_iflag = iflag;
1483         tp->t_oflag = oflag;
1484         tp->t_lflag = lflag;
1485
1486         if(t->c_ospeed == 0) {
1487                 sClrDTR(cp);
1488                 return(0);
1489         }
1490         rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1491
1492         /* Set baud rate ----- we only pay attention to ispeed */
1493         sSetDTR(cp);
1494         sSetRTS(cp);
1495         sSetBaud(cp, ospeed);
1496
1497         if(cflag & CSTOPB) {
1498                 sSetStop2(cp);
1499         } else {
1500                 sSetStop1(cp);
1501         }
1502
1503         if(cflag & PARENB) {
1504                 sEnParity(cp);
1505                 if(cflag & PARODD) {
1506                         sSetOddParity(cp);
1507                 } else {
1508                         sSetEvenParity(cp);
1509                 }
1510         }
1511         else {
1512                 sDisParity(cp);
1513         }
1514         if((cflag & CSIZE) == CS8) {
1515                 sSetData8(cp);
1516                 rp->rp_imask = 0xFF;
1517         } else {
1518                 sSetData7(cp);
1519                 rp->rp_imask = 0x7F;
1520         }
1521
1522         if(iflag & ISTRIP) {
1523                 rp->rp_imask &= 0x7F;
1524         }
1525
1526         if(cflag & CLOCAL) {
1527                 rp->rp_intmask &= ~DELTA_CD;
1528         } else {
1529                 rp->rp_intmask |= DELTA_CD;
1530         }
1531
1532         /* Put flow control stuff here */
1533
1534         if(cflag & CCTS_OFLOW) {
1535                 sEnCTSFlowCtl(cp);
1536         } else {
1537                 sDisCTSFlowCtl(cp);
1538         }
1539
1540         if(cflag & CRTS_IFLOW) {
1541                 rp->rp_rts_iflow = 1;
1542         } else {
1543                 rp->rp_rts_iflow = 0;
1544         }
1545
1546         if(cflag & CRTS_IFLOW) {
1547                 sEnRTSFlowCtl(cp);
1548         } else {
1549                 sDisRTSFlowCtl(cp);
1550         }
1551         rp_disc_optim(tp, t);
1552
1553         if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1554                 tp->t_state |= TS_CARR_ON;
1555                 wakeup(TSA_CARR_ON(tp));
1556         }
1557
1558 /*      tp->t_state |= TS_CAN_BYPASS_L_RINT;
1559         flags = rp->rp_channel.TxControl[3];
1560         if(flags & SET_DTR)
1561         else
1562         if(flags & SET_RTS)
1563         else
1564 */
1565         splx(oldspl);
1566
1567         return(0);
1568 }
1569
1570 static void
1571 rp_disc_optim(tp, t)
1572 struct  tty     *tp;
1573 struct  termios *t;
1574 {
1575         if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1576                 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1577                 &&(!(t->c_iflag & PARMRK)
1578                   ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1579                 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1580                 && linesw[tp->t_line].l_rint == ttyinput)
1581                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1582         else
1583                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1584 }
1585
1586 static void
1587 rpstart(tp)
1588         struct tty *tp;
1589 {
1590         struct rp_port  *rp;
1591         CHANNEL_t       *cp;
1592         struct  clist   *qp;
1593         int     unit, mynor, port, umynor;               /* SG */
1594         char    flags;
1595         int     spl, xmit_fifo_room;
1596         int     count, wcount;
1597
1598
1599    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1600         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1601         mynor = (port + umynor);                          /* SG */
1602         unit = minor_to_unit[mynor];
1603         rp = rp_addr(unit) + port;
1604         cp = &rp->rp_channel;
1605         flags = rp->rp_channel.TxControl[3];
1606         spl = spltty();
1607
1608         if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1609                 ttwwakeup(tp);
1610                 splx(spl);
1611                 return;
1612         }
1613         if(rp->rp_xmit_stopped) {
1614                 sEnTransmit(cp);
1615                 rp->rp_xmit_stopped = 0;
1616         }
1617         count = sGetTxCnt(cp);
1618
1619         if(tp->t_outq.c_cc == 0) {
1620                 if((tp->t_state & TS_BUSY) && (count == 0)) {
1621                         tp->t_state &= ~TS_BUSY;
1622                 }
1623                 ttwwakeup(tp);
1624                 splx(spl);
1625                 return;
1626         }
1627         xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1628         qp = &tp->t_outq;
1629         if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1630                 tp->t_state |= TS_BUSY;
1631                 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1632                 wcount = count >> 1;
1633                 if ( wcount ) {
1634                         rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1635                 }
1636                 if ( count & 1 ) {
1637                         rp_writech1(cp, sGetTxRxDataIO(cp),
1638                                     ((unsigned char *)(rp->TxBuf))[(count-1)]);
1639                 }
1640         }
1641         rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1642
1643         ttwwakeup(tp);
1644         splx(spl);
1645 }
1646
1647 static
1648 void
1649 rpstop(tp, flag)
1650         register struct tty *tp;
1651         int     flag;
1652 {
1653         struct rp_port  *rp;
1654         CHANNEL_t       *cp;
1655         int     unit, mynor, port, umynor;                  /* SG */
1656         int     spl;
1657
1658    umynor = (((minor(tp->t_dev) >> 16) -1) * 32);    /* SG */
1659         port  = (minor(tp->t_dev) & 0x1f);                /* SG */
1660         mynor = (port + umynor);                          /* SG */
1661         unit = minor_to_unit[mynor];
1662         rp = rp_addr(unit) + port;
1663         cp = &rp->rp_channel;
1664
1665         spl = spltty();
1666
1667         if(tp->t_state & TS_BUSY) {
1668                 if((tp->t_state&TS_TTSTOP) == 0) {
1669                         sFlushTxFIFO(cp);
1670                 } else {
1671                         if(rp->rp_xmit_stopped == 0) {
1672                                 sDisTransmit(cp);
1673                                 rp->rp_xmit_stopped = 1;
1674                         }
1675                 }
1676         }
1677         splx(spl);
1678         rpstart(tp);
1679 }