2 * Copyright (c) Comtrol Corporation <support@comtrol.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted prodived that the follwoing conditions
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.
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
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 $
37 * rp.c - for RocketPort FreeBSD
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/fcntl.h>
43 #include <sys/malloc.h>
46 #include <sys/dkstat.h>
48 #include <sys/kernel.h>
49 #include <machine/resource.h>
50 #include <machine/bus.h>
55 #include <dev/rp/rpreg.h>
56 #include <dev/rp/rpvar.h>
58 static const char RocketPortVersion[] = "3.02";
60 static Byte_t RData[RDATASIZE] =
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
82 static Byte_t RRegData[RREGDATASIZE]=
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 */
100 /* IRQ number to MUDBAC register 2 mapping */
103 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
107 Byte_t rp_sBitMapClrTbl[8] =
109 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
112 Byte_t rp_sBitMapSetTbl[8] =
114 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
117 /* Actually not used */
119 struct termios deftermios = {
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 },
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
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.
144 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
146 Byte_t AiopID; /* ID byte from AIOP */
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;
153 else /* AIOP does not exist */
157 /***************************************************************************
158 Function: sReadAiopNumChan
159 Purpose: Read the number of channels available in an AIOP directly from
161 Call: sReadAiopNumChan(CtlP, aiop)
162 CONTROLLER_T *CtlP; Ptr to controller structure
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.
171 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
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 */
186 /***************************************************************************
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.
199 No context switches are allowed while executing this function.
201 int sInitChan( CONTROLLER_T *CtlP,
210 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
211 return(FALSE); /* exceeds num chans in AIOP */
213 /* Channel, AIOP, and controller identifiers */
215 ChP->ChanID = CtlP->AiopID[AiopNum];
216 ChP->AiopNum = AiopNum;
217 ChP->ChanNum = ChanNum;
219 /* Initialize the channel from the RData array */
220 for(i=0; i < RDATASIZE; i+=4)
223 R[1] = RData[i+1] + 0x10 * ChanNum;
226 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
230 for(i=0; i < RREGDATASIZE; i+=4)
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];
238 /* Indexed registers */
239 ChOff = (Word_t)ChanNum * 0x1000;
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]);
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]);
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]);
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]);
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]);
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]);
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]);
283 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
284 ChP->TxFIFO = ChOff + _TX_FIFO;
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;
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 */
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
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.
321 Warnings: No context switches are allowed while executing this function.
323 Do not leave the receive processor stopped for more than one
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.
329 void sStopRxProcessor(CHANNEL_T *ChP)
337 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
340 /***************************************************************************
341 Function: sFlushRxFIFO
342 Purpose: Flush the Rx FIFO
343 Call: sFlushRxFIFO(ChP)
344 CHANNEL_T *ChP; Ptr to channel structure
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
352 Warnings: No context switches are allowed while executing this function.
354 void sFlushRxFIFO(CHANNEL_T *ChP)
357 Byte_t Ch; /* channel number within AIOP */
358 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
360 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
361 return; /* don't need to flush */
363 RxFIFOEnabled = FALSE;
364 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
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 */
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);
380 sEnRxFIFO(ChP); /* enable Rx FIFO */
383 /***************************************************************************
384 Function: sFlushTxFIFO
385 Purpose: Flush the Tx FIFO
386 Call: sFlushTxFIFO(ChP)
387 CHANNEL_T *ChP; Ptr to channel structure
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
395 Warnings: No context switches are allowed while executing this function.
397 void sFlushTxFIFO(CHANNEL_T *ChP)
400 Byte_t Ch; /* channel number within AIOP */
401 int TxEnabled; /* TRUE if transmitter enabled */
403 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
404 return; /* don't need to flush */
407 if(ChP->TxControl[3] & TX_ENABLE)
410 sDisTransmit(ChP); /* disable transmitter */
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);
421 sEnTransmit(ChP); /* enable transmitter */
422 sStartRxProcessor(ChP); /* restart Rx processor */
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
432 Return: int: 1 if the bytes is successfully written, otherwise 0.
434 Comments: The priority byte is transmitted before any data in the Tx FIFO.
436 Warnings: No context switches are allowed while executing this function.
438 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
440 Byte_t DWBuf[4]; /* buffer for double word writes */
441 Word_t *WordPtr; /* must be far because Win SS != DS */
443 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
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 */
449 WordPtr = (Word_t *)(&DWBuf[0]);
450 *WordPtr = ChP->TxPrioBuf; /* data byte address */
452 DWBuf[2] = Data; /* data byte value */
453 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
455 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
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 */
461 else /* write it to Tx FIFO */
463 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
465 return(1); /* 1 byte sent */
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
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.
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().
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.
492 Interrupts must also be globally enabled before channel interrupts
493 will be passed on to the host. This is done with function
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.
500 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
502 Byte_t Mask; /* Interrupt Mask Register */
505 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
507 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
509 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
511 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
513 if(Flags & CHANINT_EN)
515 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
516 rp_writech1(ChP,_INT_MASK,Mask);
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
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.
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().
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
545 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
547 Byte_t Mask; /* Interrupt Mask Register */
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]);
555 if(Flags & CHANINT_EN)
557 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
558 rp_writech1(ChP,_INT_MASK,Mask);
562 /*********************************************************************
563 Begin FreeBsd-specific driver code
564 **********************************************************************/
566 static timeout_t rpdtrwakeup;
568 static d_open_t rpopen;
569 static d_close_t rpclose;
570 static d_write_t rpwrite;
571 static d_ioctl_t rpioctl;
573 #define CDEV_MAJOR 81
574 struct cdevsw rp_cdevsw = {
582 /* strategy */ nostrategy,
584 /* maj */ CDEV_MAJOR,
590 static int rp_num_ports_open = 0;
591 static int rp_ndevs = 0;
592 static int minor_to_unit[128];
594 static int rp_num_ports[4]; /* Number of ports on each controller */
596 #define _INLINE_ __inline
597 #define POLL_INTERVAL 1
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)
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)
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])
619 * The top-level routines begin here
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));
628 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
629 CHANNEL_t *cp, unsigned int ChanStatus)
632 unsigned int CharNStat;
633 int ToRecv, wRecv, ch, ttynocopy;
635 ToRecv = sGetRxCnt(cp);
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)
644 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
645 if(!(ChanStatus & STATMODE)) {
646 ChanStatus |= STATMODE;
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.
655 if(ChanStatus & STATMODE) {
657 if(tp->t_state & TS_TBLOCK) {
660 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
661 ch = CharNStat & 0xff;
663 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
665 else if (CharNStat & STMPARITYH)
667 else if (CharNStat & STMRCVROVRH)
670 (*linesw[tp->t_line].l_rint)(ch, tp);
674 After emtying FIFO in status mode, turn off status mode
677 if(sGetRxCnt(cp) == 0) {
678 sDisRxStatusMode(cp);
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
688 ToRecv = sGetRxCnt(cp);
689 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
690 if ( ToRecv > RXFIFO_SIZE ) {
691 ToRecv = RXFIFO_SIZE;
695 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
698 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
702 tp->t_rawcc += ToRecv;
703 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
707 if(tp->t_state & TS_TBLOCK) {
710 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
712 (*linesw[tp->t_line].l_rint)(ch, tp);
720 static _INLINE_ void rp_handle_port(struct rp_port *rp)
724 unsigned int IntMask, ChanStatus;
729 cp = &rp->rp_channel;
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);
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);
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) {
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);
760 static void rp_do_poll(void *not_used)
765 int unit, aiop, ch, line, count;
766 unsigned char CtlMask, AiopMask;
768 for(unit = 0; unit < rp_ndevs; unit++) {
771 CtlMask = ctl->ctlmask(ctl);
772 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
774 AiopMask = sGetAiopIntStatus(ctl, aiop);
775 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
777 line = (unit << 5) | (aiop << 3) | ch;
785 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
788 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
789 count = sGetTxCnt(&rp->rp_channel);
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);
799 if(rp_num_ports_open)
800 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
804 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
808 int aiop, chan, port;
809 int ChanStatus, line, i, count;
815 unit = device_get_unit(ctlp->dev);
817 printf("RocketPort%d (Version %s) %d ports.\n", unit,
818 RocketPortVersion, num_ports);
819 rp_num_ports[unit] = num_ports;
821 ctlp->rp = rp = (struct rp_port *)
822 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
824 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
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;
833 bzero(rp, sizeof(struct rp_port) * num_ports);
834 ctlp->tty = tty = (struct tty *)
835 malloc(sizeof(struct tty) * num_ports, M_TTYS,
838 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
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");
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);
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++) {
887 /* tty->t_termios = deftermios;
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);
897 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
898 rp->it_out = rp->it_in;
900 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
901 DELTA_CD | DELTA_CTS | DELTA_DSR;
903 ChanStatus = sGetChanStatus(&rp->rp_channel);
905 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
906 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
911 ChanStatus = sGetChanStatus(&rp->rp_channel);
912 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
913 line = (unit << 5) | (aiop << 3) | chan;
922 rp_releaseresource(ctlp);
928 rp_releaseresource(CONTROLLER_t *ctlp)
932 unit = device_get_unit(ctlp->dev);
934 if (ctlp->rp != NULL) {
936 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
937 if (p_rp_addr[i] == ctlp->rp)
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;
943 free(ctlp->rp, M_DEVBUF);
946 if (ctlp->tty != NULL) {
947 free(ctlp->tty, M_DEVBUF);
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);
959 rpopen(dev_t dev, int flag, int mode, d_thread_t *td)
962 int unit, port, mynor, umynor, flags; /* SG */
965 unsigned int IntMask, ChanStatus;
966 struct proc *p = td->td_proc;
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)
978 rp = rp_addr(unit) + port;
979 /* rp->rp_tty = &rp_tty[rp->rp_port];
987 while(rp->state & ~SET_DTR) {
988 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
993 if(tp->t_state & TS_ISOPEN) {
994 if(IS_CALLOUT(dev)) {
995 if(!rp->active_out) {
1000 if(rp->active_out) {
1001 if(flag & O_NONBLOCK) {
1005 error = tsleep(&rp->active_out,
1006 TTIPRI | PCATCH, "rpbi", 0);
1012 if(tp->t_state & TS_XCLUDE && suser_xxx(p->p_ucred, 0) != 0) {
1020 tp->t_param = rpparam;
1021 tp->t_oproc = rpstart;
1022 tp->t_stop = rpstop;
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;
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);
1041 sEnInterrupts(&rp->rp_channel,
1042 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1043 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1045 sDisRxStatusMode(&rp->rp_channel);
1046 sClrTxXOFF(&rp->rp_channel);
1048 /* sDisRTSFlowCtl(&rp->rp_channel);
1049 sDisCTSFlowCtl(&rp->rp_channel);
1051 sDisTxSoftFlowCtl(&rp->rp_channel);
1053 sStartRxProcessor(&rp->rp_channel);
1055 sEnRxFIFO(&rp->rp_channel);
1056 sEnTransmit(&rp->rp_channel);
1058 /* sSetDTR(&rp->rp_channel);
1059 sSetRTS(&rp->rp_channel);
1063 error = rpparam(tp, &tp->t_termios);
1070 rp_num_ports_open++;
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);
1081 if(rp_num_ports_open == 1)
1082 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1086 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1087 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1089 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1096 error = (*linesw[tp->t_line].l_open)(dev, tp);
1098 rp_disc_optim(tp, &tp->t_termios);
1099 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1100 rp->active_out = TRUE;
1102 /* if(rp_num_ports_open == 1)
1103 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1107 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1112 device_busy(rp->rp_ctlp->dev);
1117 rpclose(dev_t dev, int flag, int mode, d_thread_t *td)
1119 int oldspl, unit, mynor, umynor, port; /* SG */
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 */
1131 rp = rp_addr(unit) + port;
1132 cp = &rp->rp_channel;
1136 (*linesw[tp->t_line].l_close)(tp, flag);
1137 rp_disc_optim(tp, &tp->t_termios);
1138 rpstop(tp, FREAD | FWRITE);
1141 tp->t_state &= ~TS_BUSY;
1146 device_unbusy(rp->rp_ctlp->dev);
1152 rphardclose(struct rp_port *rp)
1158 cp = &rp->rp_channel;
1160 mynor = MINOR_MAGIC(tp->t_dev);
1165 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1168 sDisTxSoftFlowCtl(cp);
1171 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1174 if(IS_CALLOUT(tp->t_dev)) {
1177 if(rp->dtr_wait != 0) {
1178 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1179 rp->state |= ~SET_DTR;
1182 rp->active_out = FALSE;
1183 wakeup(&rp->active_out);
1184 wakeup(TSA_CARR_ON(tp));
1189 rpwrite(dev, uio, flag)
1196 int unit, mynor, port, umynor, error = 0; /* SG */
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 */
1205 rp = rp_addr(unit) + port;
1207 while(rp->rp_disable_writes) {
1209 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1214 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1219 rpdtrwakeup(void *chan)
1223 rp = (struct rp_port *)chan;
1224 rp->state &= SET_DTR;
1225 wakeup(&rp->dtr_wait);
1229 rpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, d_thread_t *td)
1234 int unit, mynor, port, umynor; /* SG */
1237 int arg, flags, result, ChanStatus;
1239 struct proc *p = td->td_proc;
1241 KKASSERT(p != NULL);
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;
1249 if(IS_CONTROL(dev)) {
1252 switch (IS_CONTROL(dev)) {
1253 case CONTROL_INIT_STATE:
1254 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1256 case CONTROL_LOCK_STATE:
1257 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1260 return(ENODEV); /* /dev/nodev */
1264 error = suser_xxx(p->p_ucred, 0);
1267 *ct = *(struct termios *)data;
1270 *(struct termios *)data = *ct;
1273 *(int *)data = TTYDISC;
1276 bzero(data, sizeof(struct winsize));
1284 cp = &rp->rp_channel;
1286 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1287 term = tp->t_termios;
1289 error = ttsetcompat(tp, &cmd, data, &term);
1293 data = (caddr_t)&term;
1296 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1298 struct termios *dt = (struct termios *)data;
1299 struct termios *lt = IS_CALLOUT(dev)
1300 ? &rp->lt_out : &rp->lt_in;
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;
1321 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
1322 if(error != ENOIOCTL) {
1327 flags = rp->rp_channel.TxControl[3];
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) {
1338 sSendBreak(&rp->rp_channel);
1342 sClrBreak(&rp->rp_channel);
1346 sSetDTR(&rp->rp_channel);
1347 sSetRTS(&rp->rp_channel);
1351 sClrDTR(&rp->rp_channel);
1355 arg = *(int *) data;
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]));
1368 arg = *(int *) data;
1374 rp->rp_channel.TxControl[3] |= flags;
1375 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1376 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1379 arg = *(int *) data;
1385 rp->rp_channel.TxControl[3] &= ~flags;
1386 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1387 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
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));
1401 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1403 result |= TIOCM_RTS;
1406 *(int *)data = result;
1409 error = suser_xxx(p->p_ucred, 0);
1414 rp->dtr_wait = *(int *)data * hz/100;
1417 *(int *)data = rp->dtr_wait * 100/hz;
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},
1446 int unit, mynor, port, umynor; /* SG */
1447 int oldspl, cflag, iflag, oflag, lflag;
1454 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1455 port = (minor(tp->t_dev) & 0x1f); /* SG */
1456 mynor = (port + umynor); /* SG */
1458 unit = minor_to_unit[mynor];
1459 rp = rp_addr(unit) + port;
1460 cp = &rp->rp_channel;
1465 devshift = umynor / 32;
1466 devshift = 1 << devshift;
1467 if ( devshift & RPCLOCAL ) {
1475 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1476 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
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;
1486 if(t->c_ospeed == 0) {
1490 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1492 /* Set baud rate ----- we only pay attention to ispeed */
1495 sSetBaud(cp, ospeed);
1497 if(cflag & CSTOPB) {
1503 if(cflag & PARENB) {
1505 if(cflag & PARODD) {
1514 if((cflag & CSIZE) == CS8) {
1516 rp->rp_imask = 0xFF;
1519 rp->rp_imask = 0x7F;
1522 if(iflag & ISTRIP) {
1523 rp->rp_imask &= 0x7F;
1526 if(cflag & CLOCAL) {
1527 rp->rp_intmask &= ~DELTA_CD;
1529 rp->rp_intmask |= DELTA_CD;
1532 /* Put flow control stuff here */
1534 if(cflag & CCTS_OFLOW) {
1540 if(cflag & CRTS_IFLOW) {
1541 rp->rp_rts_iflow = 1;
1543 rp->rp_rts_iflow = 0;
1546 if(cflag & CRTS_IFLOW) {
1551 rp_disc_optim(tp, t);
1553 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1554 tp->t_state |= TS_CARR_ON;
1555 wakeup(TSA_CARR_ON(tp));
1558 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1559 flags = rp->rp_channel.TxControl[3];
1571 rp_disc_optim(tp, t)
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;
1583 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1593 int unit, mynor, port, umynor; /* SG */
1595 int spl, xmit_fifo_room;
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];
1608 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1613 if(rp->rp_xmit_stopped) {
1615 rp->rp_xmit_stopped = 0;
1617 count = sGetTxCnt(cp);
1619 if(tp->t_outq.c_cc == 0) {
1620 if((tp->t_state & TS_BUSY) && (count == 0)) {
1621 tp->t_state &= ~TS_BUSY;
1627 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
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;
1634 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1637 rp_writech1(cp, sGetTxRxDataIO(cp),
1638 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1641 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1650 register struct tty *tp;
1655 int unit, mynor, port, umynor; /* SG */
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;
1667 if(tp->t_state & TS_BUSY) {
1668 if((tp->t_state&TS_TTSTOP) == 0) {
1671 if(rp->rp_xmit_stopped == 0) {
1673 rp->rp_xmit_stopped = 1;