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.21 2006/12/22 23:26:24 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>
51 #include <sys/thread2.h>
57 static const char RocketPortVersion[] = "3.02";
59 static Byte_t RData[RDATASIZE] =
61 0x00, 0x09, 0xf6, 0x82,
62 0x02, 0x09, 0x86, 0xfb,
63 0x04, 0x09, 0x00, 0x0a,
64 0x06, 0x09, 0x01, 0x0a,
65 0x08, 0x09, 0x8a, 0x13,
66 0x0a, 0x09, 0xc5, 0x11,
67 0x0c, 0x09, 0x86, 0x85,
68 0x0e, 0x09, 0x20, 0x0a,
69 0x10, 0x09, 0x21, 0x0a,
70 0x12, 0x09, 0x41, 0xff,
71 0x14, 0x09, 0x82, 0x00,
72 0x16, 0x09, 0x82, 0x7b,
73 0x18, 0x09, 0x8a, 0x7d,
74 0x1a, 0x09, 0x88, 0x81,
75 0x1c, 0x09, 0x86, 0x7a,
76 0x1e, 0x09, 0x84, 0x81,
77 0x20, 0x09, 0x82, 0x7c,
78 0x22, 0x09, 0x0a, 0x0a
81 static Byte_t RRegData[RREGDATASIZE]=
83 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
84 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
85 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
86 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
87 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
88 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
89 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
90 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
91 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
92 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
93 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
94 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
95 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
99 /* IRQ number to MUDBAC register 2 mapping */
102 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
106 Byte_t rp_sBitMapClrTbl[8] =
108 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
111 Byte_t rp_sBitMapSetTbl[8] =
113 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
116 /* Actually not used */
118 struct termios deftermios = {
123 { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
124 _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
125 CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE },
131 /***************************************************************************
132 Function: sReadAiopID
133 Purpose: Read the AIOP idenfication number directly from an AIOP.
134 Call: sReadAiopID(CtlP, aiop)
135 CONTROLLER_T *CtlP; Ptr to controller structure
137 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
138 is replace by an identifying number.
139 Flag AIOPID_NULL if no valid AIOP is found
140 Warnings: No context switches are allowed while executing this function.
143 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
145 Byte_t AiopID; /* ID byte from AIOP */
147 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
148 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
149 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
152 else /* AIOP does not exist */
156 /***************************************************************************
157 Function: sReadAiopNumChan
158 Purpose: Read the number of channels available in an AIOP directly from
160 Call: sReadAiopNumChan(CtlP, aiop)
161 CONTROLLER_T *CtlP; Ptr to controller structure
163 Return: int: The number of channels available
164 Comments: The number of channels is determined by write/reads from identical
165 offsets within the SRAM address spaces for channels 0 and 4.
166 If the channel 4 space is mirrored to channel 0 it is a 4 channel
167 AIOP, otherwise it is an 8 channel.
168 Warnings: No context switches are allowed while executing this function.
170 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
174 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
175 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
176 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
177 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
178 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
179 if(x != y) /* if different must be 8 chan */
185 /***************************************************************************
187 Purpose: Initialization of a channel and channel structure
188 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
189 CONTROLLER_T *CtlP; Ptr to controller structure
190 CHANNEL_T *ChP; Ptr to channel structure
191 int AiopNum; AIOP number within controller
192 int ChanNum; Channel number within AIOP
193 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
194 number exceeds number of channels available in AIOP.
195 Comments: This function must be called before a channel can be used.
196 Warnings: No range checking on any of the parameters is done.
198 No context switches are allowed while executing this function.
200 int sInitChan( CONTROLLER_T *CtlP,
209 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
210 return(FALSE); /* exceeds num chans in AIOP */
212 /* Channel, AIOP, and controller identifiers */
214 ChP->ChanID = CtlP->AiopID[AiopNum];
215 ChP->AiopNum = AiopNum;
216 ChP->ChanNum = ChanNum;
218 /* Initialize the channel from the RData array */
219 for(i=0; i < RDATASIZE; i+=4)
222 R[1] = RData[i+1] + 0x10 * ChanNum;
225 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
229 for(i=0; i < RREGDATASIZE; i+=4)
231 ChR[i] = RRegData[i];
232 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
233 ChR[i+2] = RRegData[i+2];
234 ChR[i+3] = RRegData[i+3];
237 /* Indexed registers */
238 ChOff = (Word_t)ChanNum * 0x1000;
240 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
241 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
242 ChP->BaudDiv[2] = (Byte_t)BRD9600;
243 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
244 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
246 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
247 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
248 ChP->TxControl[2] = 0;
249 ChP->TxControl[3] = 0;
250 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
252 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
253 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
254 ChP->RxControl[2] = 0;
255 ChP->RxControl[3] = 0;
256 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
258 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
259 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
260 ChP->TxEnables[2] = 0;
261 ChP->TxEnables[3] = 0;
262 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
264 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
265 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
266 ChP->TxCompare[2] = 0;
267 ChP->TxCompare[3] = 0;
268 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
270 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
271 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
272 ChP->TxReplace1[2] = 0;
273 ChP->TxReplace1[3] = 0;
274 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
276 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
277 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
278 ChP->TxReplace2[2] = 0;
279 ChP->TxReplace2[3] = 0;
280 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
282 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
283 ChP->TxFIFO = ChOff + _TX_FIFO;
285 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
286 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
287 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
288 rp_writech2(ChP,_INDX_DATA,0);
289 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
290 ChP->RxFIFO = ChOff + _RX_FIFO;
292 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
293 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
294 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
295 rp_writech2(ChP,_INDX_DATA,0);
296 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
297 rp_writech2(ChP,_INDX_DATA,0);
298 ChP->TxPrioCnt = ChOff + _TXP_CNT;
299 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
300 rp_writech1(ChP,_INDX_DATA,0);
301 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
302 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
303 rp_writech1(ChP,_INDX_DATA,0);
304 ChP->TxPrioBuf = ChOff + _TXP_BUF;
305 sEnRxProcessor(ChP); /* start the Rx processor */
310 /***************************************************************************
311 Function: sStopRxProcessor
312 Purpose: Stop the receive processor from processing a channel.
313 Call: sStopRxProcessor(ChP)
314 CHANNEL_T *ChP; Ptr to channel structure
316 Comments: The receive processor can be started again with sStartRxProcessor().
317 This function causes the receive processor to skip over the
318 stopped channel. It does not stop it from processing other channels.
320 Warnings: No context switches are allowed while executing this function.
322 Do not leave the receive processor stopped for more than one
325 After calling this function a delay of 4 uS is required to ensure
326 that the receive processor is no longer processing this channel.
328 void sStopRxProcessor(CHANNEL_T *ChP)
336 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
339 /***************************************************************************
340 Function: sFlushRxFIFO
341 Purpose: Flush the Rx FIFO
342 Call: sFlushRxFIFO(ChP)
343 CHANNEL_T *ChP; Ptr to channel structure
345 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
346 while it is being flushed the receive processor is stopped
347 and the transmitter is disabled. After these operations a
348 4 uS delay is done before clearing the pointers to allow
349 the receive processor to stop. These items are handled inside
351 Warnings: No context switches are allowed while executing this function.
353 void sFlushRxFIFO(CHANNEL_T *ChP)
356 Byte_t Ch; /* channel number within AIOP */
357 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
359 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
360 return; /* don't need to flush */
362 RxFIFOEnabled = FALSE;
363 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
365 RxFIFOEnabled = TRUE;
366 sDisRxFIFO(ChP); /* disable it */
367 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
368 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
370 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
371 Ch = (Byte_t)sGetChanNum(ChP);
372 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
373 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
374 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
375 rp_writech2(ChP,_INDX_DATA,0);
376 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
377 rp_writech2(ChP,_INDX_DATA,0);
379 sEnRxFIFO(ChP); /* enable Rx FIFO */
382 /***************************************************************************
383 Function: sFlushTxFIFO
384 Purpose: Flush the Tx FIFO
385 Call: sFlushTxFIFO(ChP)
386 CHANNEL_T *ChP; Ptr to channel structure
388 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
389 while it is being flushed the receive processor is stopped
390 and the transmitter is disabled. After these operations a
391 4 uS delay is done before clearing the pointers to allow
392 the receive processor to stop. These items are handled inside
394 Warnings: No context switches are allowed while executing this function.
396 void sFlushTxFIFO(CHANNEL_T *ChP)
399 Byte_t Ch; /* channel number within AIOP */
400 int TxEnabled; /* TRUE if transmitter enabled */
402 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
403 return; /* don't need to flush */
406 if(ChP->TxControl[3] & TX_ENABLE)
409 sDisTransmit(ChP); /* disable transmitter */
411 sStopRxProcessor(ChP); /* stop Rx processor */
412 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
413 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
414 Ch = (Byte_t)sGetChanNum(ChP);
415 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
416 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
417 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
418 rp_writech2(ChP,_INDX_DATA,0);
420 sEnTransmit(ChP); /* enable transmitter */
421 sStartRxProcessor(ChP); /* restart Rx processor */
424 /***************************************************************************
425 Function: sWriteTxPrioByte
426 Purpose: Write a byte of priority transmit data to a channel
427 Call: sWriteTxPrioByte(ChP,Data)
428 CHANNEL_T *ChP; Ptr to channel structure
429 Byte_t Data; The transmit data byte
431 Return: int: 1 if the bytes is successfully written, otherwise 0.
433 Comments: The priority byte is transmitted before any data in the Tx FIFO.
435 Warnings: No context switches are allowed while executing this function.
437 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
439 Byte_t DWBuf[4]; /* buffer for double word writes */
440 Word_t *WordPtr; /* must be far because Win SS != DS */
442 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
444 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
445 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
446 return(0); /* nothing sent */
448 WordPtr = (Word_t *)(&DWBuf[0]);
449 *WordPtr = ChP->TxPrioBuf; /* data byte address */
451 DWBuf[2] = Data; /* data byte value */
452 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
454 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
456 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
457 DWBuf[3] = 0; /* priority buffer pointer */
458 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
460 else /* write it to Tx FIFO */
462 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
464 return(1); /* 1 byte sent */
467 /***************************************************************************
468 Function: sEnInterrupts
469 Purpose: Enable one or more interrupts for a channel
470 Call: sEnInterrupts(ChP,Flags)
471 CHANNEL_T *ChP; Ptr to channel structure
472 Word_t Flags: Interrupt enable flags, can be any combination
473 of the following flags:
474 TXINT_EN: Interrupt on Tx FIFO empty
475 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
477 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
478 MCINT_EN: Interrupt on modem input change
479 CHANINT_EN: Allow channel interrupt signal to the AIOP's
480 Interrupt Channel Register.
482 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
483 enabled. If an interrupt enable flag is not set in Flags, that
484 interrupt will not be changed. Interrupts can be disabled with
485 function sDisInterrupts().
487 This function sets the appropriate bit for the channel in the AIOP's
488 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
489 this channel's bit to be set in the AIOP's Interrupt Channel Register.
491 Interrupts must also be globally enabled before channel interrupts
492 will be passed on to the host. This is done with function
495 In some cases it may be desirable to disable interrupts globally but
496 enable channel interrupts. This would allow the global interrupt
497 status register to be used to determine which AIOPs need service.
499 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
501 Byte_t Mask; /* Interrupt Mask Register */
504 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
506 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
508 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
510 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
512 if(Flags & CHANINT_EN)
514 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
515 rp_writech1(ChP,_INT_MASK,Mask);
519 /***************************************************************************
520 Function: sDisInterrupts
521 Purpose: Disable one or more interrupts for a channel
522 Call: sDisInterrupts(ChP,Flags)
523 CHANNEL_T *ChP; Ptr to channel structure
524 Word_t Flags: Interrupt flags, can be any combination
525 of the following flags:
526 TXINT_EN: Interrupt on Tx FIFO empty
527 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
529 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
530 MCINT_EN: Interrupt on modem input change
531 CHANINT_EN: Disable channel interrupt signal to the
532 AIOP's Interrupt Channel Register.
534 Comments: If an interrupt flag is set in Flags, that interrupt will be
535 disabled. If an interrupt flag is not set in Flags, that
536 interrupt will not be changed. Interrupts can be enabled with
537 function sEnInterrupts().
539 This function clears the appropriate bit for the channel in the AIOP's
540 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
541 this channel's bit from being set in the AIOP's Interrupt Channel
544 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
546 Byte_t Mask; /* Interrupt Mask Register */
549 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
550 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
551 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
552 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
554 if(Flags & CHANINT_EN)
556 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
557 rp_writech1(ChP,_INT_MASK,Mask);
561 /*********************************************************************
562 Begin FreeBsd-specific driver code
563 **********************************************************************/
565 static timeout_t rpdtrwakeup;
567 static d_open_t rpopen;
568 static d_close_t rpclose;
569 static d_write_t rpwrite;
570 static d_ioctl_t rpioctl;
572 #define CDEV_MAJOR 81
573 struct dev_ops rp_ops = {
574 { "rp", CDEV_MAJOR, D_TTY },
583 static int rp_num_ports_open = 0;
584 static int rp_ndevs = 0;
585 static int minor_to_unit[128];
586 static int rp_initialized;
587 static struct callout rp_poll_ch;
589 static int rp_num_ports[4]; /* Number of ports on each controller */
591 #define POLL_INTERVAL 1
593 #define CALLOUT_MASK 0x80
594 #define CONTROL_MASK 0x60
595 #define CONTROL_INIT_STATE 0x20
596 #define CONTROL_LOCK_STATE 0x40
597 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
598 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
599 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
600 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
601 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
603 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
604 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
605 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
607 static struct rp_port *p_rp_addr[4];
608 static struct rp_port *p_rp_table[MAX_RP_PORTS];
609 #define rp_addr(unit) (p_rp_addr[unit])
610 #define rp_table(port) (p_rp_table[port])
613 * The top-level routines begin here
616 static int rpparam (struct tty *, struct termios *);
617 static void rpstart (struct tty *);
618 static void rpstop (struct tty *, int);
619 static void rphardclose (struct rp_port *);
620 static void rp_disc_optim (struct tty *tp, struct termios *t);
623 rp_do_receive(struct rp_port *rp, struct tty *tp,
624 CHANNEL_t *cp, unsigned int ChanStatus)
626 unsigned int CharNStat;
627 int ToRecv, wRecv, ch, ttynocopy;
629 ToRecv = sGetRxCnt(cp);
633 /* If status indicates there are errored characters in the
634 FIFO, then enter status mode (a word in FIFO holds
635 characters and status)
638 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
639 if(!(ChanStatus & STATMODE)) {
640 ChanStatus |= STATMODE;
645 if we previously entered status mode then read down the
646 FIFO one word at a time, pulling apart the character and
647 the status. Update error counters depending on status.
649 if(ChanStatus & STATMODE) {
651 if(tp->t_state & TS_TBLOCK) {
654 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
655 ch = CharNStat & 0xff;
657 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
659 else if (CharNStat & STMPARITYH)
661 else if (CharNStat & STMRCVROVRH)
664 (*linesw[tp->t_line].l_rint)(ch, tp);
668 After emtying FIFO in status mode, turn off status mode
671 if(sGetRxCnt(cp) == 0) {
672 sDisRxStatusMode(cp);
676 * Avoid the grotesquely inefficient lineswitch routine
677 * (ttyinput) in "raw" mode. It usually takes about 450
678 * instructions (that's without canonical processing or echo!).
679 * slinput is reasonably fast (usually 40 instructions plus
682 ToRecv = sGetRxCnt(cp);
683 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
684 if ( ToRecv > RXFIFO_SIZE ) {
685 ToRecv = RXFIFO_SIZE;
689 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
692 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
696 tp->t_rawcc += ToRecv;
697 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
701 if(tp->t_state & TS_TBLOCK) {
704 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
706 (*linesw[tp->t_line].l_rint)(ch, tp);
715 rp_handle_port(struct rp_port *rp)
719 unsigned int IntMask, ChanStatus;
724 cp = &rp->rp_channel;
726 IntMask = sGetChanIntID(cp);
727 IntMask = IntMask & rp->rp_intmask;
728 ChanStatus = sGetChanStatus(cp);
729 if(IntMask & RXF_TRIG)
730 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
731 rp_do_receive(rp, tp, cp, ChanStatus);
733 if(IntMask & DELTA_CD) {
734 if(ChanStatus & CD_ACT) {
735 if(!(tp->t_state & TS_CARR_ON) ) {
736 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
739 if((tp->t_state & TS_CARR_ON)) {
740 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
741 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
747 /* oldcts = rp->rp_cts;
748 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
749 if(oldcts != rp->rp_cts) {
750 kprintf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
755 static void rp_do_poll(void *not_used)
760 int unit, aiop, ch, line, count;
761 unsigned char CtlMask, AiopMask;
763 for(unit = 0; unit < rp_ndevs; unit++) {
766 CtlMask = ctl->ctlmask(ctl);
767 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
769 AiopMask = sGetAiopIntStatus(ctl, aiop);
770 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
772 line = (unit << 5) | (aiop << 3) | ch;
780 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
783 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
784 count = sGetTxCnt(&rp->rp_channel);
786 tp->t_state &= ~(TS_BUSY);
787 if(!(tp->t_state & TS_TTSTOP) &&
788 (count <= rp->rp_restart)) {
789 (*linesw[tp->t_line].l_start)(tp);
794 if(rp_num_ports_open)
795 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
799 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
803 int aiop, chan, port;
804 int ChanStatus, line, i, count;
809 unit = device_get_unit(ctlp->dev);
811 kprintf("RocketPort%d (Version %s) %d ports.\n", unit,
812 RocketPortVersion, num_ports);
813 rp_num_ports[unit] = num_ports;
815 ctlp->rp = rp = kmalloc(sizeof(struct rp_port) * num_ports,
816 M_TTYS, M_WAITOK | M_ZERO);
818 count = unit * 32; /* board times max ports per card SG */
819 for(i=count;i < (count + rp_num_ports[unit]);i++)
820 minor_to_unit[i] = unit;
822 ctlp->tty = tty = kmalloc(sizeof(struct tty) * num_ports,
823 M_TTYS, M_WAITOK | M_ZERO);
829 dev_ops_add(&rp_ops, 0xffff0000, (unit + 1) << 16);
830 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
831 make_dev(&rp_ops, ((unit + 1) << 16) | i,
832 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
833 i <= 9 ? '0' + i : 'a' + i - 10);
834 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x20,
835 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
836 i <= 9 ? '0' + i : 'a' + i - 10);
837 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x40,
838 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
839 i <= 9 ? '0' + i : 'a' + i - 10);
840 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x80,
841 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
842 i <= 9 ? '0' + i : 'a' + i - 10);
843 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0xa0,
844 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
845 i <= 9 ? '0' + i : 'a' + i - 10);
846 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0xc0,
847 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
848 i <= 9 ? '0' + i : 'a' + i - 10);
852 for(aiop=0; aiop < num_aiops; aiop++) {
853 num_chan = sGetAiopNumChan(ctlp, aiop);
854 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
863 /* tty->t_termios = deftermios;
865 rp->dtr_wait = 3 * hz;
866 rp->it_in.c_iflag = 0;
867 rp->it_in.c_oflag = 0;
868 rp->it_in.c_cflag = TTYDEF_CFLAG;
869 rp->it_in.c_lflag = 0;
870 termioschars(&rp->it_in);
871 /* termioschars(&tty->t_termios);
873 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
874 rp->it_out = rp->it_in;
876 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
877 DELTA_CD | DELTA_CTS | DELTA_DSR;
879 ChanStatus = sGetChanStatus(&rp->rp_channel);
881 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
882 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
887 ChanStatus = sGetChanStatus(&rp->rp_channel);
888 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
889 line = (unit << 5) | (aiop << 3) | chan;
898 rp_releaseresource(ctlp);
904 rp_releaseresource(CONTROLLER_t *ctlp)
908 unit = device_get_unit(ctlp->dev);
910 if (ctlp->rp != NULL) {
912 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
913 if (p_rp_addr[i] == ctlp->rp)
915 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
916 if (p_rp_table[i] == ctlp->rp)
917 p_rp_table[i] = NULL;
919 kfree(ctlp->rp, M_DEVBUF);
922 if (ctlp->tty != NULL) {
923 kfree(ctlp->tty, M_DEVBUF);
926 if (ctlp->dev != NULL)
928 dev_ops_remove(&rp_ops, 0xffff0000, (unit + 1) << 16);
932 rpopen(struct dev_open_args *ap)
934 cdev_t dev = ap->a_head.a_dev;
936 int unit, port, mynor, umynor, flags; /* SG */
939 unsigned int IntMask, ChanStatus;
941 if (!rp_initialized) {
943 callout_init(&rp_poll_ch);
946 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
947 port = (minor(dev) & 0x1f); /* SG */
948 mynor = (port + umynor); /* SG */
949 unit = minor_to_unit[mynor];
950 if (rp_addr(unit) == NULL)
954 rp = rp_addr(unit) + port;
955 /* rp->rp_tty = &rp_tty[rp->rp_port];
957 callout_init(&rp->wakeup_callout);
964 while(rp->state & ~SET_DTR) {
965 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
970 if(tp->t_state & TS_ISOPEN) {
971 if(IS_CALLOUT(dev)) {
972 if(!rp->active_out) {
978 if(ap->a_oflags & O_NONBLOCK) {
982 error = tsleep(&rp->active_out,
989 if(tp->t_state & TS_XCLUDE && suser_cred(ap->a_cred, 0) != 0) {
997 tp->t_param = rpparam;
998 tp->t_oproc = rpstart;
1001 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1002 tp->t_ififosize = 512;
1003 tp->t_ispeedwat = (speed_t)-1;
1004 tp->t_ospeedwat = (speed_t)-1;
1008 rp->rp_channel.TxControl[3] =
1009 ((rp->rp_channel.TxControl[3]
1010 & ~(SET_RTS | SET_DTR)) | flags);
1011 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1012 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1013 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1014 sDisRxStatusMode(&rp->rp_channel);
1015 sFlushRxFIFO(&rp->rp_channel);
1016 sFlushTxFIFO(&rp->rp_channel);
1018 sEnInterrupts(&rp->rp_channel,
1019 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1020 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1022 sDisRxStatusMode(&rp->rp_channel);
1023 sClrTxXOFF(&rp->rp_channel);
1025 /* sDisRTSFlowCtl(&rp->rp_channel);
1026 sDisCTSFlowCtl(&rp->rp_channel);
1028 sDisTxSoftFlowCtl(&rp->rp_channel);
1030 sStartRxProcessor(&rp->rp_channel);
1032 sEnRxFIFO(&rp->rp_channel);
1033 sEnTransmit(&rp->rp_channel);
1035 /* sSetDTR(&rp->rp_channel);
1036 sSetRTS(&rp->rp_channel);
1040 error = rpparam(tp, &tp->t_termios);
1047 rp_num_ports_open++;
1049 IntMask = sGetChanIntID(&rp->rp_channel);
1050 IntMask = IntMask & rp->rp_intmask;
1051 ChanStatus = sGetChanStatus(&rp->rp_channel);
1052 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1053 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1054 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1058 if(rp_num_ports_open == 1)
1059 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1063 if(!(ap->a_oflags&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1064 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1066 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
1072 error = (*linesw[tp->t_line].l_open)(dev, tp);
1074 rp_disc_optim(tp, &tp->t_termios);
1075 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1076 rp->active_out = TRUE;
1078 /* if(rp_num_ports_open == 1)
1079 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1083 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1088 device_busy(rp->rp_ctlp->dev);
1093 rpclose(struct dev_close_args *ap)
1095 cdev_t dev = ap->a_head.a_dev;
1096 int unit, mynor, umynor, port; /* SG */
1101 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1102 port = (minor(dev) & 0x1f); /* SG */
1103 mynor = (port + umynor); /* SG */
1104 unit = minor_to_unit[mynor]; /* SG */
1108 rp = rp_addr(unit) + port;
1109 cp = &rp->rp_channel;
1113 (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
1114 rp_disc_optim(tp, &tp->t_termios);
1115 rpstop(tp, FREAD | FWRITE);
1118 tp->t_state &= ~TS_BUSY;
1123 device_unbusy(rp->rp_ctlp->dev);
1129 rphardclose(struct rp_port *rp)
1135 cp = &rp->rp_channel;
1137 mynor = MINOR_MAGIC(tp->t_dev);
1142 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1145 sDisTxSoftFlowCtl(cp);
1148 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1151 if(IS_CALLOUT(tp->t_dev)) {
1154 if(rp->dtr_wait != 0) {
1155 callout_reset(&rp->wakeup_callout, rp->dtr_wait,
1157 rp->state |= ~SET_DTR;
1160 rp->active_out = FALSE;
1161 wakeup(&rp->active_out);
1162 wakeup(TSA_CARR_ON(tp));
1167 rpwrite(struct dev_write_args *ap)
1169 cdev_t dev = ap->a_head.a_dev;
1172 int unit, mynor, port, umynor, error = 0; /* SG */
1174 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1175 port = (minor(dev) & 0x1f); /* SG */
1176 mynor = (port + umynor); /* SG */
1177 unit = minor_to_unit[mynor]; /* SG */
1181 rp = rp_addr(unit) + port;
1183 while(rp->rp_disable_writes) {
1185 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
1190 error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag);
1195 rpdtrwakeup(void *chan)
1199 rp = (struct rp_port *)chan;
1200 rp->state &= SET_DTR;
1201 wakeup(&rp->dtr_wait);
1205 rpioctl(struct dev_ioctl_args *ap)
1207 cdev_t dev = ap->a_head.a_dev;
1208 u_long cmd = ap->a_cmd;
1209 caddr_t data = ap->a_data;
1213 int unit, mynor, port, umynor; /* SG */
1215 int arg, flags, result, ChanStatus;
1218 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1219 port = (minor(dev) & 0x1f); /* SG */
1220 mynor = (port + umynor); /* SG */
1221 unit = minor_to_unit[mynor];
1222 rp = rp_addr(unit) + port;
1224 if(IS_CONTROL(dev)) {
1227 switch (IS_CONTROL(dev)) {
1228 case CONTROL_INIT_STATE:
1229 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1231 case CONTROL_LOCK_STATE:
1232 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1235 return(ENODEV); /* /dev/nodev */
1239 error = suser_cred(ap->a_cred, 0);
1242 *ct = *(struct termios *)data;
1245 *(struct termios *)data = *ct;
1248 *(int *)data = TTYDISC;
1251 bzero(data, sizeof(struct winsize));
1259 cp = &rp->rp_channel;
1261 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1262 term = tp->t_termios;
1264 error = ttsetcompat(tp, &cmd, data, &term);
1268 data = (caddr_t)&term;
1271 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1273 struct termios *dt = (struct termios *)data;
1274 struct termios *lt = IS_CALLOUT(dev)
1275 ? &rp->lt_out : &rp->lt_in;
1277 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1278 | (dt->c_iflag & ~lt->c_iflag);
1279 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1280 | (dt->c_oflag & ~lt->c_oflag);
1281 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1282 | (dt->c_cflag & ~lt->c_cflag);
1283 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1284 | (dt->c_lflag & ~lt->c_lflag);
1285 for(cc = 0; cc < NCCS; ++cc)
1286 if(lt->c_cc[cc] != 0)
1287 dt->c_cc[cc] = tp->t_cc[cc];
1288 if(lt->c_ispeed != 0)
1289 dt->c_ispeed = tp->t_ispeed;
1290 if(lt->c_ospeed != 0)
1291 dt->c_ospeed = tp->t_ospeed;
1296 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
1297 ap->a_fflag, ap->a_cred);
1298 if(error != ENOIOCTL) {
1303 flags = rp->rp_channel.TxControl[3];
1305 error = ttioctl(tp, cmd, data, ap->a_fflag);
1306 flags = rp->rp_channel.TxControl[3];
1307 rp_disc_optim(tp, &tp->t_termios);
1308 if(error != ENOIOCTL) {
1314 sSendBreak(&rp->rp_channel);
1318 sClrBreak(&rp->rp_channel);
1322 sSetDTR(&rp->rp_channel);
1323 sSetRTS(&rp->rp_channel);
1327 sClrDTR(&rp->rp_channel);
1331 arg = *(int *) data;
1337 rp->rp_channel.TxControl[3] =
1338 ((rp->rp_channel.TxControl[3]
1339 & ~(SET_RTS | SET_DTR)) | flags);
1340 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1341 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1344 arg = *(int *) data;
1350 rp->rp_channel.TxControl[3] |= flags;
1351 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1352 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1355 arg = *(int *) data;
1361 rp->rp_channel.TxControl[3] &= ~flags;
1362 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1363 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1368 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1369 flags = rp->rp_channel.TxControl[3];
1370 result = TIOCM_LE; /* always on while open for some reason */
1371 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1372 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1373 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1374 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1375 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1377 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1379 result |= TIOCM_RTS;
1382 *(int *)data = result;
1385 error = suser_cred(ap->a_cred, 0);
1390 rp->dtr_wait = *(int *)data * hz/100;
1393 *(int *)data = rp->dtr_wait * 100/hz;
1403 static struct speedtab baud_table[] = {
1404 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1405 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1406 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1407 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1408 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1409 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1410 {B57600, BRD57600}, {B76800, BRD76800},
1411 {B115200, BRD115200}, {B230400, BRD230400},
1416 rpparam(struct tty *tp, struct termios *t)
1420 int unit, mynor, port, umynor; /* SG */
1421 int cflag, iflag, oflag, lflag;
1428 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1429 port = (minor(tp->t_dev) & 0x1f); /* SG */
1430 mynor = (port + umynor); /* SG */
1432 unit = minor_to_unit[mynor];
1433 rp = rp_addr(unit) + port;
1434 cp = &rp->rp_channel;
1439 devshift = umynor / 32;
1440 devshift = 1 << devshift;
1441 if ( devshift & RPCLOCAL ) {
1449 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1450 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1453 tp->t_ispeed = t->c_ispeed;
1454 tp->t_ospeed = t->c_ospeed;
1455 tp->t_cflag = cflag;
1456 tp->t_iflag = iflag;
1457 tp->t_oflag = oflag;
1458 tp->t_lflag = lflag;
1460 if(t->c_ospeed == 0) {
1464 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1466 /* Set baud rate ----- we only pay attention to ispeed */
1469 sSetBaud(cp, ospeed);
1471 if(cflag & CSTOPB) {
1477 if(cflag & PARENB) {
1479 if(cflag & PARODD) {
1488 if((cflag & CSIZE) == CS8) {
1490 rp->rp_imask = 0xFF;
1493 rp->rp_imask = 0x7F;
1496 if(iflag & ISTRIP) {
1497 rp->rp_imask &= 0x7F;
1500 if(cflag & CLOCAL) {
1501 rp->rp_intmask &= ~DELTA_CD;
1503 rp->rp_intmask |= DELTA_CD;
1506 /* Put flow control stuff here */
1508 if(cflag & CCTS_OFLOW) {
1514 if(cflag & CRTS_IFLOW) {
1515 rp->rp_rts_iflow = 1;
1517 rp->rp_rts_iflow = 0;
1520 if(cflag & CRTS_IFLOW) {
1525 rp_disc_optim(tp, t);
1527 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1528 tp->t_state |= TS_CARR_ON;
1529 wakeup(TSA_CARR_ON(tp));
1532 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1533 flags = rp->rp_channel.TxControl[3];
1545 rp_disc_optim(struct tty *tp, struct termios *t)
1547 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1548 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1549 &&(!(t->c_iflag & PARMRK)
1550 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1551 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1552 && linesw[tp->t_line].l_rint == ttyinput)
1553 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1555 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1559 rpstart(struct tty *tp)
1564 int unit, mynor, port, umynor; /* SG */
1570 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1571 port = (minor(tp->t_dev) & 0x1f); /* SG */
1572 mynor = (port + umynor); /* SG */
1573 unit = minor_to_unit[mynor];
1574 rp = rp_addr(unit) + port;
1575 cp = &rp->rp_channel;
1576 flags = rp->rp_channel.TxControl[3];
1579 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1584 if(rp->rp_xmit_stopped) {
1586 rp->rp_xmit_stopped = 0;
1588 count = sGetTxCnt(cp);
1590 if(tp->t_outq.c_cc == 0) {
1591 if((tp->t_state & TS_BUSY) && (count == 0)) {
1592 tp->t_state &= ~TS_BUSY;
1598 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1600 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1601 tp->t_state |= TS_BUSY;
1602 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1603 wcount = count >> 1;
1605 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1608 rp_writech1(cp, sGetTxRxDataIO(cp),
1609 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1612 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1620 rpstop(struct tty *tp, int flag)
1624 int unit, mynor, port, umynor; /* SG */
1626 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1627 port = (minor(tp->t_dev) & 0x1f); /* SG */
1628 mynor = (port + umynor); /* SG */
1629 unit = minor_to_unit[mynor];
1630 rp = rp_addr(unit) + port;
1631 cp = &rp->rp_channel;
1635 if(tp->t_state & TS_BUSY) {
1636 if((tp->t_state&TS_TTSTOP) == 0) {
1639 if(rp->rp_xmit_stopped == 0) {
1641 rp->rp_xmit_stopped = 1;