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.15 2005/12/11 01:54:09 swildner 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>
53 #include <sys/thread2.h>
59 static const char RocketPortVersion[] = "3.02";
61 static Byte_t RData[RDATASIZE] =
63 0x00, 0x09, 0xf6, 0x82,
64 0x02, 0x09, 0x86, 0xfb,
65 0x04, 0x09, 0x00, 0x0a,
66 0x06, 0x09, 0x01, 0x0a,
67 0x08, 0x09, 0x8a, 0x13,
68 0x0a, 0x09, 0xc5, 0x11,
69 0x0c, 0x09, 0x86, 0x85,
70 0x0e, 0x09, 0x20, 0x0a,
71 0x10, 0x09, 0x21, 0x0a,
72 0x12, 0x09, 0x41, 0xff,
73 0x14, 0x09, 0x82, 0x00,
74 0x16, 0x09, 0x82, 0x7b,
75 0x18, 0x09, 0x8a, 0x7d,
76 0x1a, 0x09, 0x88, 0x81,
77 0x1c, 0x09, 0x86, 0x7a,
78 0x1e, 0x09, 0x84, 0x81,
79 0x20, 0x09, 0x82, 0x7c,
80 0x22, 0x09, 0x0a, 0x0a
83 static Byte_t RRegData[RREGDATASIZE]=
85 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
86 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
87 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
88 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
89 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
90 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
91 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
92 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
93 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
94 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
95 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
96 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
97 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
101 /* IRQ number to MUDBAC register 2 mapping */
104 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
108 Byte_t rp_sBitMapClrTbl[8] =
110 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
113 Byte_t rp_sBitMapSetTbl[8] =
115 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
118 /* Actually not used */
120 struct termios deftermios = {
125 { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
126 _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
127 CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
133 /***************************************************************************
134 Function: sReadAiopID
135 Purpose: Read the AIOP idenfication number directly from an AIOP.
136 Call: sReadAiopID(CtlP, aiop)
137 CONTROLLER_T *CtlP; Ptr to controller structure
139 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
140 is replace by an identifying number.
141 Flag AIOPID_NULL if no valid AIOP is found
142 Warnings: No context switches are allowed while executing this function.
145 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
147 Byte_t AiopID; /* ID byte from AIOP */
149 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
150 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
151 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
154 else /* AIOP does not exist */
158 /***************************************************************************
159 Function: sReadAiopNumChan
160 Purpose: Read the number of channels available in an AIOP directly from
162 Call: sReadAiopNumChan(CtlP, aiop)
163 CONTROLLER_T *CtlP; Ptr to controller structure
165 Return: int: The number of channels available
166 Comments: The number of channels is determined by write/reads from identical
167 offsets within the SRAM address spaces for channels 0 and 4.
168 If the channel 4 space is mirrored to channel 0 it is a 4 channel
169 AIOP, otherwise it is an 8 channel.
170 Warnings: No context switches are allowed while executing this function.
172 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
176 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
177 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
178 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
179 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
180 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
181 if(x != y) /* if different must be 8 chan */
187 /***************************************************************************
189 Purpose: Initialization of a channel and channel structure
190 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
191 CONTROLLER_T *CtlP; Ptr to controller structure
192 CHANNEL_T *ChP; Ptr to channel structure
193 int AiopNum; AIOP number within controller
194 int ChanNum; Channel number within AIOP
195 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
196 number exceeds number of channels available in AIOP.
197 Comments: This function must be called before a channel can be used.
198 Warnings: No range checking on any of the parameters is done.
200 No context switches are allowed while executing this function.
202 int sInitChan( CONTROLLER_T *CtlP,
211 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
212 return(FALSE); /* exceeds num chans in AIOP */
214 /* Channel, AIOP, and controller identifiers */
216 ChP->ChanID = CtlP->AiopID[AiopNum];
217 ChP->AiopNum = AiopNum;
218 ChP->ChanNum = ChanNum;
220 /* Initialize the channel from the RData array */
221 for(i=0; i < RDATASIZE; i+=4)
224 R[1] = RData[i+1] + 0x10 * ChanNum;
227 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
231 for(i=0; i < RREGDATASIZE; i+=4)
233 ChR[i] = RRegData[i];
234 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
235 ChR[i+2] = RRegData[i+2];
236 ChR[i+3] = RRegData[i+3];
239 /* Indexed registers */
240 ChOff = (Word_t)ChanNum * 0x1000;
242 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
243 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
244 ChP->BaudDiv[2] = (Byte_t)BRD9600;
245 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
246 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
248 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
249 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
250 ChP->TxControl[2] = 0;
251 ChP->TxControl[3] = 0;
252 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
254 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
255 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
256 ChP->RxControl[2] = 0;
257 ChP->RxControl[3] = 0;
258 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
260 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
261 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
262 ChP->TxEnables[2] = 0;
263 ChP->TxEnables[3] = 0;
264 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
266 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
267 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
268 ChP->TxCompare[2] = 0;
269 ChP->TxCompare[3] = 0;
270 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
272 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
273 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
274 ChP->TxReplace1[2] = 0;
275 ChP->TxReplace1[3] = 0;
276 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
278 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
279 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
280 ChP->TxReplace2[2] = 0;
281 ChP->TxReplace2[3] = 0;
282 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
284 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
285 ChP->TxFIFO = ChOff + _TX_FIFO;
287 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
288 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
289 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
290 rp_writech2(ChP,_INDX_DATA,0);
291 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
292 ChP->RxFIFO = ChOff + _RX_FIFO;
294 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
295 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
296 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
297 rp_writech2(ChP,_INDX_DATA,0);
298 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
299 rp_writech2(ChP,_INDX_DATA,0);
300 ChP->TxPrioCnt = ChOff + _TXP_CNT;
301 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
302 rp_writech1(ChP,_INDX_DATA,0);
303 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
304 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
305 rp_writech1(ChP,_INDX_DATA,0);
306 ChP->TxPrioBuf = ChOff + _TXP_BUF;
307 sEnRxProcessor(ChP); /* start the Rx processor */
312 /***************************************************************************
313 Function: sStopRxProcessor
314 Purpose: Stop the receive processor from processing a channel.
315 Call: sStopRxProcessor(ChP)
316 CHANNEL_T *ChP; Ptr to channel structure
318 Comments: The receive processor can be started again with sStartRxProcessor().
319 This function causes the receive processor to skip over the
320 stopped channel. It does not stop it from processing other channels.
322 Warnings: No context switches are allowed while executing this function.
324 Do not leave the receive processor stopped for more than one
327 After calling this function a delay of 4 uS is required to ensure
328 that the receive processor is no longer processing this channel.
330 void sStopRxProcessor(CHANNEL_T *ChP)
338 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
341 /***************************************************************************
342 Function: sFlushRxFIFO
343 Purpose: Flush the Rx FIFO
344 Call: sFlushRxFIFO(ChP)
345 CHANNEL_T *ChP; Ptr to channel structure
347 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
348 while it is being flushed the receive processor is stopped
349 and the transmitter is disabled. After these operations a
350 4 uS delay is done before clearing the pointers to allow
351 the receive processor to stop. These items are handled inside
353 Warnings: No context switches are allowed while executing this function.
355 void sFlushRxFIFO(CHANNEL_T *ChP)
358 Byte_t Ch; /* channel number within AIOP */
359 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
361 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
362 return; /* don't need to flush */
364 RxFIFOEnabled = FALSE;
365 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
367 RxFIFOEnabled = TRUE;
368 sDisRxFIFO(ChP); /* disable it */
369 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
370 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
372 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
373 Ch = (Byte_t)sGetChanNum(ChP);
374 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
375 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
376 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
377 rp_writech2(ChP,_INDX_DATA,0);
378 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
379 rp_writech2(ChP,_INDX_DATA,0);
381 sEnRxFIFO(ChP); /* enable Rx FIFO */
384 /***************************************************************************
385 Function: sFlushTxFIFO
386 Purpose: Flush the Tx FIFO
387 Call: sFlushTxFIFO(ChP)
388 CHANNEL_T *ChP; Ptr to channel structure
390 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
391 while it is being flushed the receive processor is stopped
392 and the transmitter is disabled. After these operations a
393 4 uS delay is done before clearing the pointers to allow
394 the receive processor to stop. These items are handled inside
396 Warnings: No context switches are allowed while executing this function.
398 void sFlushTxFIFO(CHANNEL_T *ChP)
401 Byte_t Ch; /* channel number within AIOP */
402 int TxEnabled; /* TRUE if transmitter enabled */
404 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
405 return; /* don't need to flush */
408 if(ChP->TxControl[3] & TX_ENABLE)
411 sDisTransmit(ChP); /* disable transmitter */
413 sStopRxProcessor(ChP); /* stop Rx processor */
414 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
415 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
416 Ch = (Byte_t)sGetChanNum(ChP);
417 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
418 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
419 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
420 rp_writech2(ChP,_INDX_DATA,0);
422 sEnTransmit(ChP); /* enable transmitter */
423 sStartRxProcessor(ChP); /* restart Rx processor */
426 /***************************************************************************
427 Function: sWriteTxPrioByte
428 Purpose: Write a byte of priority transmit data to a channel
429 Call: sWriteTxPrioByte(ChP,Data)
430 CHANNEL_T *ChP; Ptr to channel structure
431 Byte_t Data; The transmit data byte
433 Return: int: 1 if the bytes is successfully written, otherwise 0.
435 Comments: The priority byte is transmitted before any data in the Tx FIFO.
437 Warnings: No context switches are allowed while executing this function.
439 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
441 Byte_t DWBuf[4]; /* buffer for double word writes */
442 Word_t *WordPtr; /* must be far because Win SS != DS */
444 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
446 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
447 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
448 return(0); /* nothing sent */
450 WordPtr = (Word_t *)(&DWBuf[0]);
451 *WordPtr = ChP->TxPrioBuf; /* data byte address */
453 DWBuf[2] = Data; /* data byte value */
454 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
456 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
458 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
459 DWBuf[3] = 0; /* priority buffer pointer */
460 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
462 else /* write it to Tx FIFO */
464 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
466 return(1); /* 1 byte sent */
469 /***************************************************************************
470 Function: sEnInterrupts
471 Purpose: Enable one or more interrupts for a channel
472 Call: sEnInterrupts(ChP,Flags)
473 CHANNEL_T *ChP; Ptr to channel structure
474 Word_t Flags: Interrupt enable flags, can be any combination
475 of the following flags:
476 TXINT_EN: Interrupt on Tx FIFO empty
477 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
479 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
480 MCINT_EN: Interrupt on modem input change
481 CHANINT_EN: Allow channel interrupt signal to the AIOP's
482 Interrupt Channel Register.
484 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
485 enabled. If an interrupt enable flag is not set in Flags, that
486 interrupt will not be changed. Interrupts can be disabled with
487 function sDisInterrupts().
489 This function sets the appropriate bit for the channel in the AIOP's
490 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
491 this channel's bit to be set in the AIOP's Interrupt Channel Register.
493 Interrupts must also be globally enabled before channel interrupts
494 will be passed on to the host. This is done with function
497 In some cases it may be desirable to disable interrupts globally but
498 enable channel interrupts. This would allow the global interrupt
499 status register to be used to determine which AIOPs need service.
501 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
503 Byte_t Mask; /* Interrupt Mask Register */
506 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
508 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
510 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
512 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
514 if(Flags & CHANINT_EN)
516 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
517 rp_writech1(ChP,_INT_MASK,Mask);
521 /***************************************************************************
522 Function: sDisInterrupts
523 Purpose: Disable one or more interrupts for a channel
524 Call: sDisInterrupts(ChP,Flags)
525 CHANNEL_T *ChP; Ptr to channel structure
526 Word_t Flags: Interrupt flags, can be any combination
527 of the following flags:
528 TXINT_EN: Interrupt on Tx FIFO empty
529 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
531 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
532 MCINT_EN: Interrupt on modem input change
533 CHANINT_EN: Disable channel interrupt signal to the
534 AIOP's Interrupt Channel Register.
536 Comments: If an interrupt flag is set in Flags, that interrupt will be
537 disabled. If an interrupt flag is not set in Flags, that
538 interrupt will not be changed. Interrupts can be enabled with
539 function sEnInterrupts().
541 This function clears the appropriate bit for the channel in the AIOP's
542 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
543 this channel's bit from being set in the AIOP's Interrupt Channel
546 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
548 Byte_t Mask; /* Interrupt Mask Register */
551 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
552 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
553 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
554 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
556 if(Flags & CHANINT_EN)
558 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
559 rp_writech1(ChP,_INT_MASK,Mask);
563 /*********************************************************************
564 Begin FreeBsd-specific driver code
565 **********************************************************************/
567 static timeout_t rpdtrwakeup;
569 static d_open_t rpopen;
570 static d_close_t rpclose;
571 static d_write_t rpwrite;
572 static d_ioctl_t rpioctl;
574 #define CDEV_MAJOR 81
575 struct cdevsw rp_cdevsw = {
577 /* maj */ CDEV_MAJOR,
589 /* strategy */ nostrategy,
594 static int rp_num_ports_open = 0;
595 static int rp_ndevs = 0;
596 static int minor_to_unit[128];
597 static int rp_initialized;
598 static struct callout rp_poll_ch;
600 static int rp_num_ports[4]; /* Number of ports on each controller */
602 #define POLL_INTERVAL 1
604 #define CALLOUT_MASK 0x80
605 #define CONTROL_MASK 0x60
606 #define CONTROL_INIT_STATE 0x20
607 #define CONTROL_LOCK_STATE 0x40
608 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
609 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
610 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
611 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
612 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
614 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
615 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
616 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
618 static struct rp_port *p_rp_addr[4];
619 static struct rp_port *p_rp_table[MAX_RP_PORTS];
620 #define rp_addr(unit) (p_rp_addr[unit])
621 #define rp_table(port) (p_rp_table[port])
624 * The top-level routines begin here
627 static int rpparam (struct tty *, struct termios *);
628 static void rpstart (struct tty *);
629 static void rpstop (struct tty *, int);
630 static void rphardclose (struct rp_port *);
631 static void rp_disc_optim (struct tty *tp, struct termios *t);
634 rp_do_receive(struct rp_port *rp, struct tty *tp,
635 CHANNEL_t *cp, unsigned int ChanStatus)
637 unsigned int CharNStat;
638 int ToRecv, wRecv, ch, ttynocopy;
640 ToRecv = sGetRxCnt(cp);
644 /* If status indicates there are errored characters in the
645 FIFO, then enter status mode (a word in FIFO holds
646 characters and status)
649 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
650 if(!(ChanStatus & STATMODE)) {
651 ChanStatus |= STATMODE;
656 if we previously entered status mode then read down the
657 FIFO one word at a time, pulling apart the character and
658 the status. Update error counters depending on status.
660 if(ChanStatus & STATMODE) {
662 if(tp->t_state & TS_TBLOCK) {
665 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
666 ch = CharNStat & 0xff;
668 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
670 else if (CharNStat & STMPARITYH)
672 else if (CharNStat & STMRCVROVRH)
675 (*linesw[tp->t_line].l_rint)(ch, tp);
679 After emtying FIFO in status mode, turn off status mode
682 if(sGetRxCnt(cp) == 0) {
683 sDisRxStatusMode(cp);
687 * Avoid the grotesquely inefficient lineswitch routine
688 * (ttyinput) in "raw" mode. It usually takes about 450
689 * instructions (that's without canonical processing or echo!).
690 * slinput is reasonably fast (usually 40 instructions plus
693 ToRecv = sGetRxCnt(cp);
694 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
695 if ( ToRecv > RXFIFO_SIZE ) {
696 ToRecv = RXFIFO_SIZE;
700 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
703 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
707 tp->t_rawcc += ToRecv;
708 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
712 if(tp->t_state & TS_TBLOCK) {
715 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
717 (*linesw[tp->t_line].l_rint)(ch, tp);
726 rp_handle_port(struct rp_port *rp)
730 unsigned int IntMask, ChanStatus;
735 cp = &rp->rp_channel;
737 IntMask = sGetChanIntID(cp);
738 IntMask = IntMask & rp->rp_intmask;
739 ChanStatus = sGetChanStatus(cp);
740 if(IntMask & RXF_TRIG)
741 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
742 rp_do_receive(rp, tp, cp, ChanStatus);
744 if(IntMask & DELTA_CD) {
745 if(ChanStatus & CD_ACT) {
746 if(!(tp->t_state & TS_CARR_ON) ) {
747 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
750 if((tp->t_state & TS_CARR_ON)) {
751 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
752 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
758 /* oldcts = rp->rp_cts;
759 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
760 if(oldcts != rp->rp_cts) {
761 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
766 static void rp_do_poll(void *not_used)
771 int unit, aiop, ch, line, count;
772 unsigned char CtlMask, AiopMask;
774 for(unit = 0; unit < rp_ndevs; unit++) {
777 CtlMask = ctl->ctlmask(ctl);
778 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
780 AiopMask = sGetAiopIntStatus(ctl, aiop);
781 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
783 line = (unit << 5) | (aiop << 3) | ch;
791 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
794 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
795 count = sGetTxCnt(&rp->rp_channel);
797 tp->t_state &= ~(TS_BUSY);
798 if(!(tp->t_state & TS_TTSTOP) &&
799 (count <= rp->rp_restart)) {
800 (*linesw[tp->t_line].l_start)(tp);
805 if(rp_num_ports_open)
806 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
810 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
814 int aiop, chan, port;
815 int ChanStatus, line, i, count;
820 unit = device_get_unit(ctlp->dev);
822 printf("RocketPort%d (Version %s) %d ports.\n", unit,
823 RocketPortVersion, num_ports);
824 rp_num_ports[unit] = num_ports;
826 ctlp->rp = rp = malloc(sizeof(struct rp_port) * num_ports,
827 M_TTYS, M_WAITOK | M_ZERO);
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 ctlp->tty = tty = malloc(sizeof(struct tty) * num_ports,
834 M_TTYS, M_WAITOK | M_ZERO);
840 cdevsw_add(&rp_cdevsw, 0xffff0000, (unit + 1) << 16);
841 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
842 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
843 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
844 i <= 9 ? '0' + i : 'a' + i - 10);
845 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
846 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
847 i <= 9 ? '0' + i : 'a' + i - 10);
848 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
849 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
850 i <= 9 ? '0' + i : 'a' + i - 10);
851 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
852 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
853 i <= 9 ? '0' + i : 'a' + i - 10);
854 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
855 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
856 i <= 9 ? '0' + i : 'a' + i - 10);
857 make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
858 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
859 i <= 9 ? '0' + i : 'a' + i - 10);
863 for(aiop=0; aiop < num_aiops; aiop++) {
864 num_chan = sGetAiopNumChan(ctlp, aiop);
865 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
874 /* tty->t_termios = deftermios;
876 rp->dtr_wait = 3 * hz;
877 rp->it_in.c_iflag = 0;
878 rp->it_in.c_oflag = 0;
879 rp->it_in.c_cflag = TTYDEF_CFLAG;
880 rp->it_in.c_lflag = 0;
881 termioschars(&rp->it_in);
882 /* termioschars(&tty->t_termios);
884 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
885 rp->it_out = rp->it_in;
887 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
888 DELTA_CD | DELTA_CTS | DELTA_DSR;
890 ChanStatus = sGetChanStatus(&rp->rp_channel);
892 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
893 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
898 ChanStatus = sGetChanStatus(&rp->rp_channel);
899 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
900 line = (unit << 5) | (aiop << 3) | chan;
909 rp_releaseresource(ctlp);
915 rp_releaseresource(CONTROLLER_t *ctlp)
919 unit = device_get_unit(ctlp->dev);
921 if (ctlp->rp != NULL) {
923 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
924 if (p_rp_addr[i] == ctlp->rp)
926 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
927 if (p_rp_table[i] == ctlp->rp)
928 p_rp_table[i] = NULL;
930 free(ctlp->rp, M_DEVBUF);
933 if (ctlp->tty != NULL) {
934 free(ctlp->tty, M_DEVBUF);
937 if (ctlp->dev != NULL)
939 cdevsw_remove(&rp_cdevsw, 0xffff0000, (unit + 1) << 16);
943 rpopen(dev_t dev, int flag, int mode, d_thread_t *td)
946 int unit, port, mynor, umynor, flags; /* SG */
949 unsigned int IntMask, ChanStatus;
951 if (!rp_initialized) {
953 callout_init(&rp_poll_ch);
956 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
957 port = (minor(dev) & 0x1f); /* SG */
958 mynor = (port + umynor); /* SG */
959 unit = minor_to_unit[mynor];
960 if (rp_addr(unit) == NULL)
964 rp = rp_addr(unit) + port;
965 /* rp->rp_tty = &rp_tty[rp->rp_port];
967 callout_init(&rp->wakeup_callout);
974 while(rp->state & ~SET_DTR) {
975 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
980 if(tp->t_state & TS_ISOPEN) {
981 if(IS_CALLOUT(dev)) {
982 if(!rp->active_out) {
988 if(flag & O_NONBLOCK) {
992 error = tsleep(&rp->active_out,
999 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1007 tp->t_param = rpparam;
1008 tp->t_oproc = rpstart;
1009 tp->t_stop = rpstop;
1011 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1012 tp->t_ififosize = 512;
1013 tp->t_ispeedwat = (speed_t)-1;
1014 tp->t_ospeedwat = (speed_t)-1;
1018 rp->rp_channel.TxControl[3] =
1019 ((rp->rp_channel.TxControl[3]
1020 & ~(SET_RTS | SET_DTR)) | flags);
1021 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1022 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1023 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1024 sDisRxStatusMode(&rp->rp_channel);
1025 sFlushRxFIFO(&rp->rp_channel);
1026 sFlushTxFIFO(&rp->rp_channel);
1028 sEnInterrupts(&rp->rp_channel,
1029 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1030 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1032 sDisRxStatusMode(&rp->rp_channel);
1033 sClrTxXOFF(&rp->rp_channel);
1035 /* sDisRTSFlowCtl(&rp->rp_channel);
1036 sDisCTSFlowCtl(&rp->rp_channel);
1038 sDisTxSoftFlowCtl(&rp->rp_channel);
1040 sStartRxProcessor(&rp->rp_channel);
1042 sEnRxFIFO(&rp->rp_channel);
1043 sEnTransmit(&rp->rp_channel);
1045 /* sSetDTR(&rp->rp_channel);
1046 sSetRTS(&rp->rp_channel);
1050 error = rpparam(tp, &tp->t_termios);
1057 rp_num_ports_open++;
1059 IntMask = sGetChanIntID(&rp->rp_channel);
1060 IntMask = IntMask & rp->rp_intmask;
1061 ChanStatus = sGetChanStatus(&rp->rp_channel);
1062 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1063 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1064 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1068 if(rp_num_ports_open == 1)
1069 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1073 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1074 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1076 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
1082 error = (*linesw[tp->t_line].l_open)(dev, tp);
1084 rp_disc_optim(tp, &tp->t_termios);
1085 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1086 rp->active_out = TRUE;
1088 /* if(rp_num_ports_open == 1)
1089 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1093 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1098 device_busy(rp->rp_ctlp->dev);
1103 rpclose(dev_t dev, int flag, int mode, d_thread_t *td)
1105 int unit, mynor, umynor, port; /* SG */
1110 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1111 port = (minor(dev) & 0x1f); /* SG */
1112 mynor = (port + umynor); /* SG */
1113 unit = minor_to_unit[mynor]; /* SG */
1117 rp = rp_addr(unit) + port;
1118 cp = &rp->rp_channel;
1122 (*linesw[tp->t_line].l_close)(tp, flag);
1123 rp_disc_optim(tp, &tp->t_termios);
1124 rpstop(tp, FREAD | FWRITE);
1127 tp->t_state &= ~TS_BUSY;
1132 device_unbusy(rp->rp_ctlp->dev);
1138 rphardclose(struct rp_port *rp)
1144 cp = &rp->rp_channel;
1146 mynor = MINOR_MAGIC(tp->t_dev);
1151 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1154 sDisTxSoftFlowCtl(cp);
1157 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1160 if(IS_CALLOUT(tp->t_dev)) {
1163 if(rp->dtr_wait != 0) {
1164 callout_reset(&rp->wakeup_callout, rp->dtr_wait,
1166 rp->state |= ~SET_DTR;
1169 rp->active_out = FALSE;
1170 wakeup(&rp->active_out);
1171 wakeup(TSA_CARR_ON(tp));
1176 rpwrite(dev_t dev, struct uio *uio, int flag)
1180 int unit, mynor, port, umynor, error = 0; /* SG */
1182 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1183 port = (minor(dev) & 0x1f); /* SG */
1184 mynor = (port + umynor); /* SG */
1185 unit = minor_to_unit[mynor]; /* SG */
1189 rp = rp_addr(unit) + port;
1191 while(rp->rp_disable_writes) {
1193 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
1198 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1203 rpdtrwakeup(void *chan)
1207 rp = (struct rp_port *)chan;
1208 rp->state &= SET_DTR;
1209 wakeup(&rp->dtr_wait);
1213 rpioctl(dev_t dev, u_long cmd, caddr_t data, int flag, d_thread_t *td)
1218 int unit, mynor, port, umynor; /* SG */
1220 int arg, flags, result, ChanStatus;
1223 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1224 port = (minor(dev) & 0x1f); /* SG */
1225 mynor = (port + umynor); /* SG */
1226 unit = minor_to_unit[mynor];
1227 rp = rp_addr(unit) + port;
1229 if(IS_CONTROL(dev)) {
1232 switch (IS_CONTROL(dev)) {
1233 case CONTROL_INIT_STATE:
1234 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1236 case CONTROL_LOCK_STATE:
1237 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1240 return(ENODEV); /* /dev/nodev */
1247 *ct = *(struct termios *)data;
1250 *(struct termios *)data = *ct;
1253 *(int *)data = TTYDISC;
1256 bzero(data, sizeof(struct winsize));
1264 cp = &rp->rp_channel;
1266 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1267 term = tp->t_termios;
1269 error = ttsetcompat(tp, &cmd, data, &term);
1273 data = (caddr_t)&term;
1276 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1278 struct termios *dt = (struct termios *)data;
1279 struct termios *lt = IS_CALLOUT(dev)
1280 ? &rp->lt_out : &rp->lt_in;
1282 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1283 | (dt->c_iflag & ~lt->c_iflag);
1284 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1285 | (dt->c_oflag & ~lt->c_oflag);
1286 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1287 | (dt->c_cflag & ~lt->c_cflag);
1288 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1289 | (dt->c_lflag & ~lt->c_lflag);
1290 for(cc = 0; cc < NCCS; ++cc)
1291 if(lt->c_cc[cc] != 0)
1292 dt->c_cc[cc] = tp->t_cc[cc];
1293 if(lt->c_ispeed != 0)
1294 dt->c_ispeed = tp->t_ispeed;
1295 if(lt->c_ospeed != 0)
1296 dt->c_ospeed = tp->t_ospeed;
1301 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
1302 if(error != ENOIOCTL) {
1307 flags = rp->rp_channel.TxControl[3];
1309 error = ttioctl(tp, cmd, data, flag);
1310 flags = rp->rp_channel.TxControl[3];
1311 rp_disc_optim(tp, &tp->t_termios);
1312 if(error != ENOIOCTL) {
1318 sSendBreak(&rp->rp_channel);
1322 sClrBreak(&rp->rp_channel);
1326 sSetDTR(&rp->rp_channel);
1327 sSetRTS(&rp->rp_channel);
1331 sClrDTR(&rp->rp_channel);
1335 arg = *(int *) data;
1341 rp->rp_channel.TxControl[3] =
1342 ((rp->rp_channel.TxControl[3]
1343 & ~(SET_RTS | SET_DTR)) | flags);
1344 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1345 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1348 arg = *(int *) data;
1354 rp->rp_channel.TxControl[3] |= flags;
1355 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1356 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1359 arg = *(int *) data;
1365 rp->rp_channel.TxControl[3] &= ~flags;
1366 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1367 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1372 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1373 flags = rp->rp_channel.TxControl[3];
1374 result = TIOCM_LE; /* always on while open for some reason */
1375 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1376 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1377 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1378 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1379 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1381 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1383 result |= TIOCM_RTS;
1386 *(int *)data = result;
1394 rp->dtr_wait = *(int *)data * hz/100;
1397 *(int *)data = rp->dtr_wait * 100/hz;
1407 static struct speedtab baud_table[] = {
1408 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1409 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1410 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1411 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1412 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1413 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1414 {B57600, BRD57600}, {B76800, BRD76800},
1415 {B115200, BRD115200}, {B230400, BRD230400},
1420 rpparam(struct tty *tp, struct termios *t)
1424 int unit, mynor, port, umynor; /* SG */
1425 int cflag, iflag, oflag, lflag;
1432 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1433 port = (minor(tp->t_dev) & 0x1f); /* SG */
1434 mynor = (port + umynor); /* SG */
1436 unit = minor_to_unit[mynor];
1437 rp = rp_addr(unit) + port;
1438 cp = &rp->rp_channel;
1443 devshift = umynor / 32;
1444 devshift = 1 << devshift;
1445 if ( devshift & RPCLOCAL ) {
1453 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1454 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1457 tp->t_ispeed = t->c_ispeed;
1458 tp->t_ospeed = t->c_ospeed;
1459 tp->t_cflag = cflag;
1460 tp->t_iflag = iflag;
1461 tp->t_oflag = oflag;
1462 tp->t_lflag = lflag;
1464 if(t->c_ospeed == 0) {
1468 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1470 /* Set baud rate ----- we only pay attention to ispeed */
1473 sSetBaud(cp, ospeed);
1475 if(cflag & CSTOPB) {
1481 if(cflag & PARENB) {
1483 if(cflag & PARODD) {
1492 if((cflag & CSIZE) == CS8) {
1494 rp->rp_imask = 0xFF;
1497 rp->rp_imask = 0x7F;
1500 if(iflag & ISTRIP) {
1501 rp->rp_imask &= 0x7F;
1504 if(cflag & CLOCAL) {
1505 rp->rp_intmask &= ~DELTA_CD;
1507 rp->rp_intmask |= DELTA_CD;
1510 /* Put flow control stuff here */
1512 if(cflag & CCTS_OFLOW) {
1518 if(cflag & CRTS_IFLOW) {
1519 rp->rp_rts_iflow = 1;
1521 rp->rp_rts_iflow = 0;
1524 if(cflag & CRTS_IFLOW) {
1529 rp_disc_optim(tp, t);
1531 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1532 tp->t_state |= TS_CARR_ON;
1533 wakeup(TSA_CARR_ON(tp));
1536 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1537 flags = rp->rp_channel.TxControl[3];
1549 rp_disc_optim(struct tty *tp, struct termios *t)
1551 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1552 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1553 &&(!(t->c_iflag & PARMRK)
1554 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1555 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1556 && linesw[tp->t_line].l_rint == ttyinput)
1557 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1559 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1563 rpstart(struct tty *tp)
1568 int unit, mynor, port, umynor; /* SG */
1574 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1575 port = (minor(tp->t_dev) & 0x1f); /* SG */
1576 mynor = (port + umynor); /* SG */
1577 unit = minor_to_unit[mynor];
1578 rp = rp_addr(unit) + port;
1579 cp = &rp->rp_channel;
1580 flags = rp->rp_channel.TxControl[3];
1583 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1588 if(rp->rp_xmit_stopped) {
1590 rp->rp_xmit_stopped = 0;
1592 count = sGetTxCnt(cp);
1594 if(tp->t_outq.c_cc == 0) {
1595 if((tp->t_state & TS_BUSY) && (count == 0)) {
1596 tp->t_state &= ~TS_BUSY;
1602 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1604 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1605 tp->t_state |= TS_BUSY;
1606 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1607 wcount = count >> 1;
1609 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1612 rp_writech1(cp, sGetTxRxDataIO(cp),
1613 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1616 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1624 rpstop(struct tty *tp, int flag)
1628 int unit, mynor, port, umynor; /* SG */
1630 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1631 port = (minor(tp->t_dev) & 0x1f); /* SG */
1632 mynor = (port + umynor); /* SG */
1633 unit = minor_to_unit[mynor];
1634 rp = rp_addr(unit) + port;
1635 cp = &rp->rp_channel;
1639 if(tp->t_state & TS_BUSY) {
1640 if((tp->t_state&TS_TTSTOP) == 0) {
1643 if(rp->rp_xmit_stopped == 0) {
1645 rp->rp_xmit_stopped = 1;