4 * Copyright (c) Comtrol Corporation <support@comtrol.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted prodived that the follwoing conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notive, this list of conditions and the following disclainer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials prodided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Comtrol Corporation.
18 * 4. The name of Comtrol Corporation may not be used to endorse or
19 * promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $FreeBSD: src/sys/dev/rp/rp.c,v 1.45.2.2 2002/11/07 22:26:59 tegge Exp $
38 * rp.c - for RocketPort FreeBSD
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/fcntl.h>
44 #include <sys/malloc.h>
48 #include <sys/dkstat.h>
50 #include <sys/kernel.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 */
150 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
151 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
152 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
156 else /* AIOP does not exist */
160 /***************************************************************************
161 Function: sReadAiopNumChan
162 Purpose: Read the number of channels available in an AIOP directly from
164 Call: sReadAiopNumChan(CtlP, aiop)
165 CONTROLLER_T *CtlP; Ptr to controller structure
167 Return: int: The number of channels available
168 Comments: The number of channels is determined by write/reads from identical
169 offsets within the SRAM address spaces for channels 0 and 4.
170 If the channel 4 space is mirrored to channel 0 it is a 4 channel
171 AIOP, otherwise it is an 8 channel.
172 Warnings: No context switches are allowed while executing this function.
174 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
179 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
180 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
181 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
182 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
183 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
185 if(x != y) /* if different must be 8 chan */
191 /***************************************************************************
193 Purpose: Initialization of a channel and channel structure
194 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
195 CONTROLLER_T *CtlP; Ptr to controller structure
196 CHANNEL_T *ChP; Ptr to channel structure
197 int AiopNum; AIOP number within controller
198 int ChanNum; Channel number within AIOP
199 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
200 number exceeds number of channels available in AIOP.
201 Comments: This function must be called before a channel can be used.
202 Warnings: No range checking on any of the parameters is done.
204 No context switches are allowed while executing this function.
206 int sInitChan( CONTROLLER_T *CtlP,
215 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
216 return(FALSE); /* exceeds num chans in AIOP */
219 /* Channel, AIOP, and controller identifiers */
221 ChP->ChanID = CtlP->AiopID[AiopNum];
222 ChP->AiopNum = AiopNum;
223 ChP->ChanNum = ChanNum;
225 /* Initialize the channel from the RData array */
226 for(i=0; i < RDATASIZE; i+=4)
229 R[1] = RData[i+1] + 0x10 * ChanNum;
232 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
236 for(i=0; i < RREGDATASIZE; i+=4)
238 ChR[i] = RRegData[i];
239 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
240 ChR[i+2] = RRegData[i+2];
241 ChR[i+3] = RRegData[i+3];
244 /* Indexed registers */
245 ChOff = (Word_t)ChanNum * 0x1000;
247 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
248 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
249 ChP->BaudDiv[2] = (Byte_t)BRD9600;
250 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
251 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
253 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
254 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
255 ChP->TxControl[2] = 0;
256 ChP->TxControl[3] = 0;
257 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
259 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
260 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
261 ChP->RxControl[2] = 0;
262 ChP->RxControl[3] = 0;
263 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
265 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
266 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
267 ChP->TxEnables[2] = 0;
268 ChP->TxEnables[3] = 0;
269 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
271 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
272 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
273 ChP->TxCompare[2] = 0;
274 ChP->TxCompare[3] = 0;
275 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
277 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
278 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
279 ChP->TxReplace1[2] = 0;
280 ChP->TxReplace1[3] = 0;
281 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
283 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
284 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
285 ChP->TxReplace2[2] = 0;
286 ChP->TxReplace2[3] = 0;
287 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
289 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
290 ChP->TxFIFO = ChOff + _TX_FIFO;
292 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
293 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
294 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
295 rp_writech2(ChP,_INDX_DATA,0);
296 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
297 ChP->RxFIFO = ChOff + _RX_FIFO;
299 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
300 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
301 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
302 rp_writech2(ChP,_INDX_DATA,0);
303 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
304 rp_writech2(ChP,_INDX_DATA,0);
305 ChP->TxPrioCnt = ChOff + _TXP_CNT;
306 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
307 rp_writech1(ChP,_INDX_DATA,0);
308 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
309 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
310 rp_writech1(ChP,_INDX_DATA,0);
311 ChP->TxPrioBuf = ChOff + _TXP_BUF;
312 sEnRxProcessor(ChP); /* start the Rx processor */
318 /***************************************************************************
319 Function: sStopRxProcessor
320 Purpose: Stop the receive processor from processing a channel.
321 Call: sStopRxProcessor(ChP)
322 CHANNEL_T *ChP; Ptr to channel structure
324 Comments: The receive processor can be started again with sStartRxProcessor().
325 This function causes the receive processor to skip over the
326 stopped channel. It does not stop it from processing other channels.
328 Warnings: No context switches are allowed while executing this function.
330 Do not leave the receive processor stopped for more than one
333 After calling this function a delay of 4 uS is required to ensure
334 that the receive processor is no longer processing this channel.
336 void sStopRxProcessor(CHANNEL_T *ChP)
345 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
349 /***************************************************************************
350 Function: sFlushRxFIFO
351 Purpose: Flush the Rx FIFO
352 Call: sFlushRxFIFO(ChP)
353 CHANNEL_T *ChP; Ptr to channel structure
355 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
356 while it is being flushed the receive processor is stopped
357 and the transmitter is disabled. After these operations a
358 4 uS delay is done before clearing the pointers to allow
359 the receive processor to stop. These items are handled inside
361 Warnings: No context switches are allowed while executing this function.
363 void sFlushRxFIFO(CHANNEL_T *ChP)
366 Byte_t Ch; /* channel number within AIOP */
367 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
369 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
370 return; /* don't need to flush */
373 RxFIFOEnabled = FALSE;
374 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
376 RxFIFOEnabled = TRUE;
377 sDisRxFIFO(ChP); /* disable it */
378 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
379 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
381 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
382 Ch = (Byte_t)sGetChanNum(ChP);
383 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
384 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
385 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
386 rp_writech2(ChP,_INDX_DATA,0);
387 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
388 rp_writech2(ChP,_INDX_DATA,0);
390 sEnRxFIFO(ChP); /* enable Rx FIFO */
394 /***************************************************************************
395 Function: sFlushTxFIFO
396 Purpose: Flush the Tx FIFO
397 Call: sFlushTxFIFO(ChP)
398 CHANNEL_T *ChP; Ptr to channel structure
400 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
401 while it is being flushed the receive processor is stopped
402 and the transmitter is disabled. After these operations a
403 4 uS delay is done before clearing the pointers to allow
404 the receive processor to stop. These items are handled inside
406 Warnings: No context switches are allowed while executing this function.
408 void sFlushTxFIFO(CHANNEL_T *ChP)
411 Byte_t Ch; /* channel number within AIOP */
412 int TxEnabled; /* TRUE if transmitter enabled */
415 if(sGetTxCnt(ChP) == 0) { /* Tx FIFO empty */
417 return; /* don't need to flush */
421 if(ChP->TxControl[3] & TX_ENABLE)
424 sDisTransmit(ChP); /* disable transmitter */
426 sStopRxProcessor(ChP); /* stop Rx processor */
427 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
428 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
429 Ch = (Byte_t)sGetChanNum(ChP);
430 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
431 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
432 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
433 rp_writech2(ChP,_INDX_DATA,0);
435 sEnTransmit(ChP); /* enable transmitter */
436 sStartRxProcessor(ChP); /* restart Rx processor */
440 /***************************************************************************
441 Function: sWriteTxPrioByte
442 Purpose: Write a byte of priority transmit data to a channel
443 Call: sWriteTxPrioByte(ChP,Data)
444 CHANNEL_T *ChP; Ptr to channel structure
445 Byte_t Data; The transmit data byte
447 Return: int: 1 if the bytes is successfully written, otherwise 0.
449 Comments: The priority byte is transmitted before any data in the Tx FIFO.
451 Warnings: No context switches are allowed while executing this function.
453 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
455 Byte_t DWBuf[4]; /* buffer for double word writes */
456 Word_t *WordPtr; /* must be far because Win SS != DS */
459 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
461 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
462 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) {/* priority buffer busy */
464 return(0); /* nothing sent */
467 WordPtr = (Word_t *)(&DWBuf[0]);
468 *WordPtr = ChP->TxPrioBuf; /* data byte address */
470 DWBuf[2] = Data; /* data byte value */
471 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
473 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
475 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
476 DWBuf[3] = 0; /* priority buffer pointer */
477 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
479 else /* write it to Tx FIFO */
481 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
484 return(1); /* 1 byte sent */
487 /***************************************************************************
488 Function: sEnInterrupts
489 Purpose: Enable one or more interrupts for a channel
490 Call: sEnInterrupts(ChP,Flags)
491 CHANNEL_T *ChP; Ptr to channel structure
492 Word_t Flags: Interrupt enable flags, can be any combination
493 of the following flags:
494 TXINT_EN: Interrupt on Tx FIFO empty
495 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
497 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
498 MCINT_EN: Interrupt on modem input change
499 CHANINT_EN: Allow channel interrupt signal to the AIOP's
500 Interrupt Channel Register.
502 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
503 enabled. If an interrupt enable flag is not set in Flags, that
504 interrupt will not be changed. Interrupts can be disabled with
505 function sDisInterrupts().
507 This function sets the appropriate bit for the channel in the AIOP's
508 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
509 this channel's bit to be set in the AIOP's Interrupt Channel Register.
511 Interrupts must also be globally enabled before channel interrupts
512 will be passed on to the host. This is done with function
515 In some cases it may be desirable to disable interrupts globally but
516 enable channel interrupts. This would allow the global interrupt
517 status register to be used to determine which AIOPs need service.
519 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
521 Byte_t Mask; /* Interrupt Mask Register */
524 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
526 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
528 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
530 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
532 if(Flags & CHANINT_EN)
534 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
535 rp_writech1(ChP,_INT_MASK,Mask);
539 /***************************************************************************
540 Function: sDisInterrupts
541 Purpose: Disable one or more interrupts for a channel
542 Call: sDisInterrupts(ChP,Flags)
543 CHANNEL_T *ChP; Ptr to channel structure
544 Word_t Flags: Interrupt flags, can be any combination
545 of the following flags:
546 TXINT_EN: Interrupt on Tx FIFO empty
547 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
549 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
550 MCINT_EN: Interrupt on modem input change
551 CHANINT_EN: Disable channel interrupt signal to the
552 AIOP's Interrupt Channel Register.
554 Comments: If an interrupt flag is set in Flags, that interrupt will be
555 disabled. If an interrupt flag is not set in Flags, that
556 interrupt will not be changed. Interrupts can be enabled with
557 function sEnInterrupts().
559 This function clears the appropriate bit for the channel in the AIOP's
560 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
561 this channel's bit from being set in the AIOP's Interrupt Channel
564 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
566 Byte_t Mask; /* Interrupt Mask Register */
569 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
570 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
571 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
572 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
574 if(Flags & CHANINT_EN)
576 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
577 rp_writech1(ChP,_INT_MASK,Mask);
581 /*********************************************************************
582 Begin FreeBsd-specific driver code
583 **********************************************************************/
585 static timeout_t rpdtrwakeup;
587 static d_open_t rpopen;
588 static d_close_t rpclose;
589 static d_write_t rpwrite;
590 static d_ioctl_t rpioctl;
592 static struct dev_ops rp_ops = {
599 .d_kqfilter = ttykqfilter,
600 .d_revoke = ttyrevoke
603 static int rp_num_ports_open = 0;
604 static int rp_ndevs = 0;
605 static int minor_to_unit[128];
606 static int rp_initialized;
607 static struct callout rp_poll_ch;
609 static int rp_num_ports[4]; /* Number of ports on each controller */
611 #define POLL_INTERVAL 1
613 #define CALLOUT_MASK 0x80
614 #define CONTROL_MASK 0x60
615 #define CONTROL_INIT_STATE 0x20
616 #define CONTROL_LOCK_STATE 0x40
617 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
618 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
619 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
620 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
621 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
623 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
624 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
625 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
627 static struct rp_port *p_rp_addr[4];
628 static struct rp_port *p_rp_table[MAX_RP_PORTS];
629 #define rp_addr(unit) (p_rp_addr[unit])
630 #define rp_table(port) (p_rp_table[port])
633 * The top-level routines begin here
636 static int rpparam (struct tty *, struct termios *);
637 static void rpstart (struct tty *);
638 static void rpstop (struct tty *, int);
639 static void rphardclose (struct rp_port *);
640 static void rp_disc_optim (struct tty *tp, struct termios *t);
643 * NOTE: Must be called with tty_token held
646 rp_do_receive(struct rp_port *rp, struct tty *tp,
647 CHANNEL_t *cp, unsigned int ChanStatus)
649 unsigned int CharNStat;
650 int ToRecv, wRecv, ch, ttynocopy;
652 ASSERT_LWKT_TOKEN_HELD(&tty_token);
653 ToRecv = sGetRxCnt(cp);
657 /* If status indicates there are errored characters in the
658 FIFO, then enter status mode (a word in FIFO holds
659 characters and status)
662 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
663 if(!(ChanStatus & STATMODE)) {
664 ChanStatus |= STATMODE;
669 if we previously entered status mode then read down the
670 FIFO one word at a time, pulling apart the character and
671 the status. Update error counters depending on status.
673 if(ChanStatus & STATMODE) {
675 if(tp->t_state & TS_TBLOCK) {
678 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
679 ch = CharNStat & 0xff;
681 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
683 else if (CharNStat & STMPARITYH)
685 else if (CharNStat & STMRCVROVRH)
688 (*linesw[tp->t_line].l_rint)(ch, tp);
692 After emtying FIFO in status mode, turn off status mode
695 if(sGetRxCnt(cp) == 0) {
696 sDisRxStatusMode(cp);
700 * Avoid the grotesquely inefficient lineswitch routine
701 * (ttyinput) in "raw" mode. It usually takes about 450
702 * instructions (that's without canonical processing or echo!).
703 * slinput is reasonably fast (usually 40 instructions plus
706 ToRecv = sGetRxCnt(cp);
707 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
708 if ( ToRecv > RXFIFO_SIZE ) {
709 ToRecv = RXFIFO_SIZE;
713 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
716 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
720 tp->t_rawcc += ToRecv;
721 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
725 if(tp->t_state & TS_TBLOCK) {
728 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
730 (*linesw[tp->t_line].l_rint)(ch, tp);
739 * NOTE: Must be called with tty_token held
742 rp_handle_port(struct rp_port *rp)
746 unsigned int IntMask, ChanStatus;
748 ASSERT_LWKT_TOKEN_HELD(&tty_token);
753 cp = &rp->rp_channel;
755 IntMask = sGetChanIntID(cp);
756 IntMask = IntMask & rp->rp_intmask;
757 ChanStatus = sGetChanStatus(cp);
758 if(IntMask & RXF_TRIG)
759 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
760 rp_do_receive(rp, tp, cp, ChanStatus);
762 if(IntMask & DELTA_CD) {
763 if(ChanStatus & CD_ACT) {
764 if(!(tp->t_state & TS_CARR_ON) ) {
765 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
768 if((tp->t_state & TS_CARR_ON)) {
769 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
770 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
776 /* oldcts = rp->rp_cts;
777 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
778 if(oldcts != rp->rp_cts) {
779 kprintf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
784 static void rp_do_poll(void *not_used)
789 int unit, aiop, ch, line, count;
790 unsigned char CtlMask, AiopMask;
792 lwkt_gettoken(&tty_token);
793 for(unit = 0; unit < rp_ndevs; unit++) {
796 CtlMask = ctl->ctlmask(ctl);
797 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
799 AiopMask = sGetAiopIntStatus(ctl, aiop);
800 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
802 line = (unit << 5) | (aiop << 3) | ch;
810 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
813 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
814 count = sGetTxCnt(&rp->rp_channel);
816 tp->t_state &= ~(TS_BUSY);
817 if(!(tp->t_state & TS_TTSTOP) &&
818 (count <= rp->rp_restart)) {
819 (*linesw[tp->t_line].l_start)(tp);
824 if(rp_num_ports_open)
825 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
826 lwkt_reltoken(&tty_token);
830 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
834 int aiop, chan, port;
835 int ChanStatus, line, i, count;
840 lwkt_gettoken(&tty_token);
841 unit = device_get_unit(ctlp->dev);
843 kprintf("RocketPort%d (Version %s) %d ports.\n", unit,
844 RocketPortVersion, num_ports);
845 rp_num_ports[unit] = num_ports;
847 ctlp->rp = rp = kmalloc(sizeof(struct rp_port) * num_ports,
848 M_TTYS, M_WAITOK | M_ZERO);
850 count = unit * 32; /* board times max ports per card SG */
851 for(i=count;i < (count + rp_num_ports[unit]);i++)
852 minor_to_unit[i] = unit;
854 ctlp->tty = tty = kmalloc(sizeof(struct tty) * num_ports,
855 M_TTYS, M_WAITOK | M_ZERO);
861 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
862 make_dev(&rp_ops, ((unit + 1) << 16) | i,
863 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
864 i <= 9 ? '0' + i : 'a' + i - 10);
865 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x20,
866 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
867 i <= 9 ? '0' + i : 'a' + i - 10);
868 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x40,
869 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
870 i <= 9 ? '0' + i : 'a' + i - 10);
871 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0x80,
872 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
873 i <= 9 ? '0' + i : 'a' + i - 10);
874 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0xa0,
875 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
876 i <= 9 ? '0' + i : 'a' + i - 10);
877 make_dev(&rp_ops, ((unit + 1) << 16) | i | 0xc0,
878 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
879 i <= 9 ? '0' + i : 'a' + i - 10);
883 for(aiop=0; aiop < num_aiops; aiop++) {
884 num_chan = sGetAiopNumChan(ctlp, aiop);
885 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
894 /* tty->t_termios = deftermios;
896 rp->dtr_wait = 3 * hz;
897 rp->it_in.c_iflag = 0;
898 rp->it_in.c_oflag = 0;
899 rp->it_in.c_cflag = TTYDEF_CFLAG;
900 rp->it_in.c_lflag = 0;
901 termioschars(&rp->it_in);
902 /* termioschars(&tty->t_termios);
904 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
905 rp->it_out = rp->it_in;
907 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
908 DELTA_CD | DELTA_CTS | DELTA_DSR;
910 ChanStatus = sGetChanStatus(&rp->rp_channel);
912 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
913 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
918 ChanStatus = sGetChanStatus(&rp->rp_channel);
919 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
920 line = (unit << 5) | (aiop << 3) | chan;
926 lwkt_reltoken(&tty_token);
930 rp_releaseresource(ctlp);
931 lwkt_reltoken(&tty_token);
936 rp_releaseresource(CONTROLLER_t *ctlp)
940 lwkt_gettoken(&tty_token);
941 unit = device_get_unit(ctlp->dev);
943 if (ctlp->rp != NULL) {
945 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
946 if (p_rp_addr[i] == ctlp->rp)
948 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
949 if (p_rp_table[i] == ctlp->rp)
950 p_rp_table[i] = NULL;
952 kfree(ctlp->rp, M_DEVBUF);
955 if (ctlp->tty != NULL) {
956 kfree(ctlp->tty, M_DEVBUF);
959 if (ctlp->dev != NULL)
961 dev_ops_remove_minor(&rp_ops, /*0xffff0000, */(unit + 1) << 16);
962 lwkt_reltoken(&tty_token);
966 rpopen(struct dev_open_args *ap)
968 cdev_t dev = ap->a_head.a_dev;
970 int unit, port, mynor, umynor, flags; /* SG */
973 unsigned int IntMask, ChanStatus;
975 lwkt_gettoken(&tty_token);
976 if (!rp_initialized) {
978 callout_init_mp(&rp_poll_ch);
981 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
982 port = (minor(dev) & 0x1f); /* SG */
983 mynor = (port + umynor); /* SG */
984 unit = minor_to_unit[mynor];
985 if (rp_addr(unit) == NULL) {
986 lwkt_reltoken(&tty_token);
989 if(IS_CONTROL(dev)) {
990 lwkt_reltoken(&tty_token);
993 rp = rp_addr(unit) + port;
994 /* rp->rp_tty = &rp_tty[rp->rp_port];
996 callout_init_mp(&rp->wakeup_callout);
1003 while(rp->state & ~SET_DTR) {
1004 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
1009 if(tp->t_state & TS_ISOPEN) {
1010 if(IS_CALLOUT(dev)) {
1011 if(!rp->active_out) {
1016 if(rp->active_out) {
1017 if(ap->a_oflags & O_NONBLOCK) {
1021 error = tsleep(&rp->active_out,
1028 if(tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0) != 0) {
1036 tp->t_param = rpparam;
1037 tp->t_oproc = rpstart;
1038 tp->t_stop = rpstop;
1040 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1041 tp->t_ififosize = 512;
1042 tp->t_ispeedwat = (speed_t)-1;
1043 tp->t_ospeedwat = (speed_t)-1;
1047 rp->rp_channel.TxControl[3] =
1048 ((rp->rp_channel.TxControl[3]
1049 & ~(SET_RTS | SET_DTR)) | flags);
1050 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1051 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1052 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1053 sDisRxStatusMode(&rp->rp_channel);
1054 sFlushRxFIFO(&rp->rp_channel);
1055 sFlushTxFIFO(&rp->rp_channel);
1057 sEnInterrupts(&rp->rp_channel,
1058 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1059 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1061 sDisRxStatusMode(&rp->rp_channel);
1062 sClrTxXOFF(&rp->rp_channel);
1064 /* sDisRTSFlowCtl(&rp->rp_channel);
1065 sDisCTSFlowCtl(&rp->rp_channel);
1067 sDisTxSoftFlowCtl(&rp->rp_channel);
1069 sStartRxProcessor(&rp->rp_channel);
1071 sEnRxFIFO(&rp->rp_channel);
1072 sEnTransmit(&rp->rp_channel);
1074 /* sSetDTR(&rp->rp_channel);
1075 sSetRTS(&rp->rp_channel);
1079 error = rpparam(tp, &tp->t_termios);
1083 lwkt_reltoken(&tty_token);
1087 rp_num_ports_open++;
1089 IntMask = sGetChanIntID(&rp->rp_channel);
1090 IntMask = IntMask & rp->rp_intmask;
1091 ChanStatus = sGetChanStatus(&rp->rp_channel);
1092 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1093 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1094 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1098 if(rp_num_ports_open == 1)
1099 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1103 if(!(ap->a_oflags&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1104 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1106 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
1112 error = (*linesw[tp->t_line].l_open)(dev, tp);
1114 rp_disc_optim(tp, &tp->t_termios);
1115 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1116 rp->active_out = TRUE;
1118 /* if(rp_num_ports_open == 1)
1119 callout_reset(&rp_poll_ch, POLL_INTERVAL, rp_do_poll, NULL);
1123 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1128 device_busy(rp->rp_ctlp->dev);
1129 lwkt_reltoken(&tty_token);
1134 rpclose(struct dev_close_args *ap)
1136 cdev_t dev = ap->a_head.a_dev;
1137 int unit, mynor, umynor, port; /* SG */
1142 lwkt_gettoken(&tty_token);
1143 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1144 port = (minor(dev) & 0x1f); /* SG */
1145 mynor = (port + umynor); /* SG */
1146 unit = minor_to_unit[mynor]; /* SG */
1148 if(IS_CONTROL(dev)) {
1149 lwkt_reltoken(&tty_token);
1152 rp = rp_addr(unit) + port;
1153 cp = &rp->rp_channel;
1157 (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
1158 rp_disc_optim(tp, &tp->t_termios);
1159 rpstop(tp, FREAD | FWRITE);
1162 tp->t_state &= ~TS_BUSY;
1167 device_unbusy(rp->rp_ctlp->dev);
1169 lwkt_reltoken(&tty_token);
1174 * NOTE: Must be called with tty_token held
1177 rphardclose(struct rp_port *rp)
1183 ASSERT_LWKT_TOKEN_HELD(&tty_token);
1184 cp = &rp->rp_channel;
1186 mynor = MINOR_MAGIC(tp->t_dev);
1191 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1194 sDisTxSoftFlowCtl(cp);
1197 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1200 if(IS_CALLOUT(tp->t_dev)) {
1203 if(rp->dtr_wait != 0) {
1204 callout_reset(&rp->wakeup_callout, rp->dtr_wait,
1206 rp->state |= ~SET_DTR;
1209 rp->active_out = FALSE;
1210 wakeup(&rp->active_out);
1211 wakeup(TSA_CARR_ON(tp));
1216 rpwrite(struct dev_write_args *ap)
1218 cdev_t dev = ap->a_head.a_dev;
1221 int unit, mynor, port, umynor, error = 0; /* SG */
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]; /* SG */
1230 lwkt_gettoken(&tty_token);
1231 rp = rp_addr(unit) + port;
1233 while(rp->rp_disable_writes) {
1235 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
1237 lwkt_reltoken(&tty_token);
1242 error = (*linesw[tp->t_line].l_write)(tp, ap->a_uio, ap->a_ioflag);
1243 lwkt_reltoken(&tty_token);
1248 rpdtrwakeup(void *chan)
1252 lwkt_gettoken(&tty_token);
1253 rp = (struct rp_port *)chan;
1254 rp->state &= SET_DTR;
1255 wakeup(&rp->dtr_wait);
1256 lwkt_reltoken(&tty_token);
1260 rpioctl(struct dev_ioctl_args *ap)
1262 cdev_t dev = ap->a_head.a_dev;
1263 u_long cmd = ap->a_cmd;
1264 caddr_t data = ap->a_data;
1268 int unit, mynor, port, umynor; /* SG */
1270 int arg, flags, result, ChanStatus;
1273 lwkt_gettoken(&tty_token);
1274 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1275 port = (minor(dev) & 0x1f); /* SG */
1276 mynor = (port + umynor); /* SG */
1277 unit = minor_to_unit[mynor];
1278 rp = rp_addr(unit) + port;
1280 if(IS_CONTROL(dev)) {
1283 switch (IS_CONTROL(dev)) {
1284 case CONTROL_INIT_STATE:
1285 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1287 case CONTROL_LOCK_STATE:
1288 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1291 lwkt_reltoken(&tty_token);
1292 return(ENODEV); /* /dev/nodev */
1296 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1298 lwkt_reltoken(&tty_token);
1301 *ct = *(struct termios *)data;
1302 lwkt_reltoken(&tty_token);
1305 *(struct termios *)data = *ct;
1306 lwkt_reltoken(&tty_token);
1309 *(int *)data = TTYDISC;
1310 lwkt_reltoken(&tty_token);
1313 bzero(data, sizeof(struct winsize));
1314 lwkt_reltoken(&tty_token);
1317 lwkt_reltoken(&tty_token);
1323 cp = &rp->rp_channel;
1325 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1326 term = tp->t_termios;
1328 error = ttsetcompat(tp, &cmd, data, &term);
1330 lwkt_reltoken(&tty_token);
1334 data = (caddr_t)&term;
1337 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1339 struct termios *dt = (struct termios *)data;
1340 struct termios *lt = IS_CALLOUT(dev)
1341 ? &rp->lt_out : &rp->lt_in;
1343 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1344 | (dt->c_iflag & ~lt->c_iflag);
1345 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1346 | (dt->c_oflag & ~lt->c_oflag);
1347 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1348 | (dt->c_cflag & ~lt->c_cflag);
1349 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1350 | (dt->c_lflag & ~lt->c_lflag);
1351 for(cc = 0; cc < NCCS; ++cc)
1352 if(lt->c_cc[cc] != 0)
1353 dt->c_cc[cc] = tp->t_cc[cc];
1354 if(lt->c_ispeed != 0)
1355 dt->c_ispeed = tp->t_ispeed;
1356 if(lt->c_ospeed != 0)
1357 dt->c_ospeed = tp->t_ospeed;
1362 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data,
1363 ap->a_fflag, ap->a_cred);
1364 if(error != ENOIOCTL) {
1365 lwkt_reltoken(&tty_token);
1370 flags = rp->rp_channel.TxControl[3];
1372 error = ttioctl(tp, cmd, data, ap->a_fflag);
1373 flags = rp->rp_channel.TxControl[3];
1374 rp_disc_optim(tp, &tp->t_termios);
1375 if(error != ENOIOCTL) {
1377 lwkt_reltoken(&tty_token);
1382 sSendBreak(&rp->rp_channel);
1386 sClrBreak(&rp->rp_channel);
1390 sSetDTR(&rp->rp_channel);
1391 sSetRTS(&rp->rp_channel);
1395 sClrDTR(&rp->rp_channel);
1399 arg = *(int *) data;
1405 rp->rp_channel.TxControl[3] =
1406 ((rp->rp_channel.TxControl[3]
1407 & ~(SET_RTS | SET_DTR)) | flags);
1408 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1409 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1412 arg = *(int *) data;
1418 rp->rp_channel.TxControl[3] |= flags;
1419 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1420 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1423 arg = *(int *) data;
1429 rp->rp_channel.TxControl[3] &= ~flags;
1430 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1431 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1436 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1437 flags = rp->rp_channel.TxControl[3];
1438 result = TIOCM_LE; /* always on while open for some reason */
1439 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1440 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1441 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1442 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1443 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1445 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1447 result |= TIOCM_RTS;
1450 *(int *)data = result;
1453 error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0);
1456 lwkt_reltoken(&tty_token);
1459 rp->dtr_wait = *(int *)data * hz/100;
1462 *(int *)data = rp->dtr_wait * 100/hz;
1466 lwkt_reltoken(&tty_token);
1470 lwkt_reltoken(&tty_token);
1474 static struct speedtab baud_table[] = {
1475 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1476 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1477 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1478 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1479 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1480 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1481 {B57600, BRD57600}, {B76800, BRD76800},
1482 {B115200, BRD115200}, {B230400, BRD230400},
1487 rpparam(struct tty *tp, struct termios *t)
1491 int unit, mynor, port, umynor; /* SG */
1492 int cflag, iflag, oflag, lflag;
1498 lwkt_gettoken(&tty_token);
1499 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1500 port = (minor(tp->t_dev) & 0x1f); /* SG */
1501 mynor = (port + umynor); /* SG */
1503 unit = minor_to_unit[mynor];
1504 rp = rp_addr(unit) + port;
1505 cp = &rp->rp_channel;
1510 devshift = umynor / 32;
1511 devshift = 1 << devshift;
1512 if ( devshift & RPCLOCAL ) {
1520 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1521 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) {
1522 lwkt_reltoken(&tty_token);
1526 tp->t_ispeed = t->c_ispeed;
1527 tp->t_ospeed = t->c_ospeed;
1528 tp->t_cflag = cflag;
1529 tp->t_iflag = iflag;
1530 tp->t_oflag = oflag;
1531 tp->t_lflag = lflag;
1533 if(t->c_ospeed == 0) {
1535 lwkt_reltoken(&tty_token);
1538 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1540 /* Set baud rate ----- we only pay attention to ispeed */
1543 sSetBaud(cp, ospeed);
1545 if(cflag & CSTOPB) {
1551 if(cflag & PARENB) {
1553 if(cflag & PARODD) {
1562 if((cflag & CSIZE) == CS8) {
1564 rp->rp_imask = 0xFF;
1567 rp->rp_imask = 0x7F;
1570 if(iflag & ISTRIP) {
1571 rp->rp_imask &= 0x7F;
1574 if(cflag & CLOCAL) {
1575 rp->rp_intmask &= ~DELTA_CD;
1577 rp->rp_intmask |= DELTA_CD;
1580 /* Put flow control stuff here */
1582 if(cflag & CCTS_OFLOW) {
1588 if(cflag & CRTS_IFLOW) {
1589 rp->rp_rts_iflow = 1;
1591 rp->rp_rts_iflow = 0;
1594 if(cflag & CRTS_IFLOW) {
1599 rp_disc_optim(tp, t);
1601 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1602 tp->t_state |= TS_CARR_ON;
1603 wakeup(TSA_CARR_ON(tp));
1606 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1607 flags = rp->rp_channel.TxControl[3];
1615 lwkt_reltoken(&tty_token);
1620 rp_disc_optim(struct tty *tp, struct termios *t)
1622 lwkt_gettoken(&tty_token);
1623 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1624 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1625 &&(!(t->c_iflag & PARMRK)
1626 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1627 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1628 && linesw[tp->t_line].l_rint == ttyinput)
1629 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1631 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1632 lwkt_reltoken(&tty_token);
1636 rpstart(struct tty *tp)
1641 int unit, mynor, port, umynor; /* SG */
1647 lwkt_gettoken(&tty_token);
1648 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1649 port = (minor(tp->t_dev) & 0x1f); /* SG */
1650 mynor = (port + umynor); /* SG */
1651 unit = minor_to_unit[mynor];
1652 rp = rp_addr(unit) + port;
1653 cp = &rp->rp_channel;
1654 flags = rp->rp_channel.TxControl[3];
1657 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1660 lwkt_reltoken(&tty_token);
1663 if(rp->rp_xmit_stopped) {
1665 rp->rp_xmit_stopped = 0;
1667 count = sGetTxCnt(cp);
1669 if(tp->t_outq.c_cc == 0) {
1670 if((tp->t_state & TS_BUSY) && (count == 0)) {
1671 tp->t_state &= ~TS_BUSY;
1675 lwkt_reltoken(&tty_token);
1678 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1680 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1681 tp->t_state |= TS_BUSY;
1682 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1683 wcount = count >> 1;
1685 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1688 rp_writech1(cp, sGetTxRxDataIO(cp),
1689 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1692 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1696 lwkt_reltoken(&tty_token);
1701 rpstop(struct tty *tp, int flag)
1705 int unit, mynor, port, umynor; /* SG */
1707 lwkt_gettoken(&tty_token);
1708 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1709 port = (minor(tp->t_dev) & 0x1f); /* SG */
1710 mynor = (port + umynor); /* SG */
1711 unit = minor_to_unit[mynor];
1712 rp = rp_addr(unit) + port;
1713 cp = &rp->rp_channel;
1717 if(tp->t_state & TS_BUSY) {
1718 if((tp->t_state&TS_TTSTOP) == 0) {
1721 if(rp->rp_xmit_stopped == 0) {
1723 rp->rp_xmit_stopped = 1;
1729 lwkt_reltoken(&tty_token);