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
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
38 * rp.c - for RocketPort FreeBSD
41 #include "opt_compat.h"
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/endian.h>
46 #include <sys/fcntl.h>
47 #include <sys/malloc.h>
48 #include <sys/serial.h>
51 #include <sys/kernel.h>
52 #include <machine/resource.h>
53 #include <machine/bus.h>
58 #include <dev/rp/rpreg.h>
59 #include <dev/rp/rpvar.h>
61 static const char RocketPortVersion[] = "3.02";
63 static Byte_t RData[RDATASIZE] =
65 0x00, 0x09, 0xf6, 0x82,
66 0x02, 0x09, 0x86, 0xfb,
67 0x04, 0x09, 0x00, 0x0a,
68 0x06, 0x09, 0x01, 0x0a,
69 0x08, 0x09, 0x8a, 0x13,
70 0x0a, 0x09, 0xc5, 0x11,
71 0x0c, 0x09, 0x86, 0x85,
72 0x0e, 0x09, 0x20, 0x0a,
73 0x10, 0x09, 0x21, 0x0a,
74 0x12, 0x09, 0x41, 0xff,
75 0x14, 0x09, 0x82, 0x00,
76 0x16, 0x09, 0x82, 0x7b,
77 0x18, 0x09, 0x8a, 0x7d,
78 0x1a, 0x09, 0x88, 0x81,
79 0x1c, 0x09, 0x86, 0x7a,
80 0x1e, 0x09, 0x84, 0x81,
81 0x20, 0x09, 0x82, 0x7c,
82 0x22, 0x09, 0x0a, 0x0a
85 static Byte_t RRegData[RREGDATASIZE]=
87 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
88 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
89 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
90 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
91 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
92 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
93 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
94 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
95 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
96 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
97 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
98 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
99 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
103 /* IRQ number to MUDBAC register 2 mapping */
106 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
110 Byte_t rp_sBitMapClrTbl[8] =
112 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
115 Byte_t rp_sBitMapSetTbl[8] =
117 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
120 /***************************************************************************
121 Function: sReadAiopID
122 Purpose: Read the AIOP idenfication number directly from an AIOP.
123 Call: sReadAiopID(CtlP, aiop)
124 CONTROLLER_T *CtlP; Ptr to controller structure
126 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
127 is replace by an identifying number.
128 Flag AIOPID_NULL if no valid AIOP is found
129 Warnings: No context switches are allowed while executing this function.
132 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
134 Byte_t AiopID; /* ID byte from AIOP */
136 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
137 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
138 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
141 else /* AIOP does not exist */
145 /***************************************************************************
146 Function: sReadAiopNumChan
147 Purpose: Read the number of channels available in an AIOP directly from
149 Call: sReadAiopNumChan(CtlP, aiop)
150 CONTROLLER_T *CtlP; Ptr to controller structure
152 Return: int: The number of channels available
153 Comments: The number of channels is determined by write/reads from identical
154 offsets within the SRAM address spaces for channels 0 and 4.
155 If the channel 4 space is mirrored to channel 0 it is a 4 channel
156 AIOP, otherwise it is an 8 channel.
157 Warnings: No context switches are allowed while executing this function.
159 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
163 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
164 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
165 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
166 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
167 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
168 if(x != y) /* if different must be 8 chan */
174 /***************************************************************************
176 Purpose: Initialization of a channel and channel structure
177 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
178 CONTROLLER_T *CtlP; Ptr to controller structure
179 CHANNEL_T *ChP; Ptr to channel structure
180 int AiopNum; AIOP number within controller
181 int ChanNum; Channel number within AIOP
182 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
183 number exceeds number of channels available in AIOP.
184 Comments: This function must be called before a channel can be used.
185 Warnings: No range checking on any of the parameters is done.
187 No context switches are allowed while executing this function.
189 int sInitChan( CONTROLLER_T *CtlP,
198 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
199 return(FALSE); /* exceeds num chans in AIOP */
201 /* Channel, AIOP, and controller identifiers */
203 ChP->ChanID = CtlP->AiopID[AiopNum];
204 ChP->AiopNum = AiopNum;
205 ChP->ChanNum = ChanNum;
207 /* Initialize the channel from the RData array */
208 for(i=0; i < RDATASIZE; i+=4)
211 R[1] = RData[i+1] + 0x10 * ChanNum;
214 rp_writech4(ChP,_INDX_ADDR,le32dec(R));
218 for(i=0; i < RREGDATASIZE; i+=4)
220 ChR[i] = RRegData[i];
221 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
222 ChR[i+2] = RRegData[i+2];
223 ChR[i+3] = RRegData[i+3];
226 /* Indexed registers */
227 ChOff = (Word_t)ChanNum * 0x1000;
229 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
230 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
231 ChP->BaudDiv[2] = (Byte_t)BRD9600;
232 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
233 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv));
235 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
236 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
237 ChP->TxControl[2] = 0;
238 ChP->TxControl[3] = 0;
239 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
241 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
242 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
243 ChP->RxControl[2] = 0;
244 ChP->RxControl[3] = 0;
245 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
247 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
248 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
249 ChP->TxEnables[2] = 0;
250 ChP->TxEnables[3] = 0;
251 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables));
253 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
254 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
255 ChP->TxCompare[2] = 0;
256 ChP->TxCompare[3] = 0;
257 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare));
259 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
260 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
261 ChP->TxReplace1[2] = 0;
262 ChP->TxReplace1[3] = 0;
263 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1));
265 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
266 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
267 ChP->TxReplace2[2] = 0;
268 ChP->TxReplace2[3] = 0;
269 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2));
271 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
272 ChP->TxFIFO = ChOff + _TX_FIFO;
274 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
275 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
276 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
277 rp_writech2(ChP,_INDX_DATA,0);
278 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
279 ChP->RxFIFO = ChOff + _RX_FIFO;
281 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
282 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
283 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
284 rp_writech2(ChP,_INDX_DATA,0);
285 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
286 rp_writech2(ChP,_INDX_DATA,0);
287 ChP->TxPrioCnt = ChOff + _TXP_CNT;
288 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
289 rp_writech1(ChP,_INDX_DATA,0);
290 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
291 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
292 rp_writech1(ChP,_INDX_DATA,0);
293 ChP->TxPrioBuf = ChOff + _TXP_BUF;
294 sEnRxProcessor(ChP); /* start the Rx processor */
299 /***************************************************************************
300 Function: sStopRxProcessor
301 Purpose: Stop the receive processor from processing a channel.
302 Call: sStopRxProcessor(ChP)
303 CHANNEL_T *ChP; Ptr to channel structure
305 Comments: The receive processor can be started again with sStartRxProcessor().
306 This function causes the receive processor to skip over the
307 stopped channel. It does not stop it from processing other channels.
309 Warnings: No context switches are allowed while executing this function.
311 Do not leave the receive processor stopped for more than one
314 After calling this function a delay of 4 uS is required to ensure
315 that the receive processor is no longer processing this channel.
317 void sStopRxProcessor(CHANNEL_T *ChP)
325 rp_writech4(ChP,_INDX_ADDR,le32dec(R));
328 /***************************************************************************
329 Function: sFlushRxFIFO
330 Purpose: Flush the Rx FIFO
331 Call: sFlushRxFIFO(ChP)
332 CHANNEL_T *ChP; Ptr to channel structure
334 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
335 while it is being flushed the receive processor is stopped
336 and the transmitter is disabled. After these operations a
337 4 uS delay is done before clearing the pointers to allow
338 the receive processor to stop. These items are handled inside
340 Warnings: No context switches are allowed while executing this function.
342 void sFlushRxFIFO(CHANNEL_T *ChP)
345 Byte_t Ch; /* channel number within AIOP */
346 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
348 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
349 return; /* don't need to flush */
351 RxFIFOEnabled = FALSE;
352 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
354 RxFIFOEnabled = TRUE;
355 sDisRxFIFO(ChP); /* disable it */
356 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
357 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
359 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
360 Ch = (Byte_t)sGetChanNum(ChP);
361 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
362 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
363 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
364 rp_writech2(ChP,_INDX_DATA,0);
365 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
366 rp_writech2(ChP,_INDX_DATA,0);
368 sEnRxFIFO(ChP); /* enable Rx FIFO */
371 /***************************************************************************
372 Function: sFlushTxFIFO
373 Purpose: Flush the Tx FIFO
374 Call: sFlushTxFIFO(ChP)
375 CHANNEL_T *ChP; Ptr to channel structure
377 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
378 while it is being flushed the receive processor is stopped
379 and the transmitter is disabled. After these operations a
380 4 uS delay is done before clearing the pointers to allow
381 the receive processor to stop. These items are handled inside
383 Warnings: No context switches are allowed while executing this function.
385 void sFlushTxFIFO(CHANNEL_T *ChP)
388 Byte_t Ch; /* channel number within AIOP */
389 int TxEnabled; /* TRUE if transmitter enabled */
391 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
392 return; /* don't need to flush */
395 if(ChP->TxControl[3] & TX_ENABLE)
398 sDisTransmit(ChP); /* disable transmitter */
400 sStopRxProcessor(ChP); /* stop Rx processor */
401 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
402 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
403 Ch = (Byte_t)sGetChanNum(ChP);
404 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
405 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
406 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
407 rp_writech2(ChP,_INDX_DATA,0);
409 sEnTransmit(ChP); /* enable transmitter */
410 sStartRxProcessor(ChP); /* restart Rx processor */
413 /***************************************************************************
414 Function: sWriteTxPrioByte
415 Purpose: Write a byte of priority transmit data to a channel
416 Call: sWriteTxPrioByte(ChP,Data)
417 CHANNEL_T *ChP; Ptr to channel structure
418 Byte_t Data; The transmit data byte
420 Return: int: 1 if the bytes is successfully written, otherwise 0.
422 Comments: The priority byte is transmitted before any data in the Tx FIFO.
424 Warnings: No context switches are allowed while executing this function.
426 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
428 Byte_t DWBuf[4]; /* buffer for double word writes */
430 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
432 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
433 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
434 return(0); /* nothing sent */
436 le16enc(DWBuf,ChP->TxPrioBuf); /* data byte address */
438 DWBuf[2] = Data; /* data byte value */
439 DWBuf[3] = 0; /* priority buffer pointer */
440 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
442 le16enc(DWBuf,ChP->TxPrioCnt); /* Tx priority count address */
444 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
445 DWBuf[3] = 0; /* priority buffer pointer */
446 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
448 else /* write it to Tx FIFO */
450 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
452 return(1); /* 1 byte sent */
455 /***************************************************************************
456 Function: sEnInterrupts
457 Purpose: Enable one or more interrupts for a channel
458 Call: sEnInterrupts(ChP,Flags)
459 CHANNEL_T *ChP; Ptr to channel structure
460 Word_t Flags: Interrupt enable flags, can be any combination
461 of the following flags:
462 TXINT_EN: Interrupt on Tx FIFO empty
463 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
465 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
466 MCINT_EN: Interrupt on modem input change
467 CHANINT_EN: Allow channel interrupt signal to the AIOP's
468 Interrupt Channel Register.
470 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
471 enabled. If an interrupt enable flag is not set in Flags, that
472 interrupt will not be changed. Interrupts can be disabled with
473 function sDisInterrupts().
475 This function sets the appropriate bit for the channel in the AIOP's
476 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
477 this channel's bit to be set in the AIOP's Interrupt Channel Register.
479 Interrupts must also be globally enabled before channel interrupts
480 will be passed on to the host. This is done with function
483 In some cases it may be desirable to disable interrupts globally but
484 enable channel interrupts. This would allow the global interrupt
485 status register to be used to determine which AIOPs need service.
487 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
489 Byte_t Mask; /* Interrupt Mask Register */
492 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
494 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
496 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
498 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
500 if(Flags & CHANINT_EN)
502 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
503 rp_writech1(ChP,_INT_MASK,Mask);
507 /***************************************************************************
508 Function: sDisInterrupts
509 Purpose: Disable one or more interrupts for a channel
510 Call: sDisInterrupts(ChP,Flags)
511 CHANNEL_T *ChP; Ptr to channel structure
512 Word_t Flags: Interrupt flags, can be any combination
513 of the following flags:
514 TXINT_EN: Interrupt on Tx FIFO empty
515 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
517 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
518 MCINT_EN: Interrupt on modem input change
519 CHANINT_EN: Disable channel interrupt signal to the
520 AIOP's Interrupt Channel Register.
522 Comments: If an interrupt flag is set in Flags, that interrupt will be
523 disabled. If an interrupt flag is not set in Flags, that
524 interrupt will not be changed. Interrupts can be enabled with
525 function sEnInterrupts().
527 This function clears the appropriate bit for the channel in the AIOP's
528 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
529 this channel's bit from being set in the AIOP's Interrupt Channel
532 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
534 Byte_t Mask; /* Interrupt Mask Register */
537 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
538 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
539 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
540 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
542 if(Flags & CHANINT_EN)
544 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
545 rp_writech1(ChP,_INT_MASK,Mask);
549 /*********************************************************************
550 Begin FreeBsd-specific driver code
551 **********************************************************************/
553 struct callout_handle rp_callout_handle;
555 static int rp_num_ports_open = 0;
556 static int rp_ndevs = 0;
558 static int rp_num_ports[4]; /* Number of ports on each controller */
560 #define POLL_INTERVAL 1
562 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
563 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
564 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
566 static struct rp_port *p_rp_addr[4];
567 static struct rp_port *p_rp_table[MAX_RP_PORTS];
568 #define rp_addr(unit) (p_rp_addr[unit])
569 #define rp_table(port) (p_rp_table[port])
572 * The top-level routines begin here
575 static void rpbreak(struct tty *, int);
576 static void rpclose(struct tty *tp);
577 static void rphardclose(struct tty *tp);
578 static int rpmodem(struct tty *, int, int);
579 static int rpparam(struct tty *, struct termios *);
580 static void rpstart(struct tty *);
581 static void rpstop(struct tty *, int);
582 static t_open_t rpopen;
584 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
585 CHANNEL_t *cp, unsigned int ChanStatus)
588 unsigned int CharNStat;
589 int i, ToRecv, wRecv, ch, ttynocopy;
591 ToRecv = sGetRxCnt(cp);
595 /* If status indicates there are errored characters in the
596 FIFO, then enter status mode (a word in FIFO holds
597 characters and status)
600 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
601 if(!(ChanStatus & STATMODE)) {
602 ChanStatus |= STATMODE;
607 if we previously entered status mode then read down the
608 FIFO one word at a time, pulling apart the character and
609 the status. Update error counters depending on status.
611 if(ChanStatus & STATMODE) {
613 if(tp->t_state & TS_TBLOCK) {
616 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
617 ch = CharNStat & 0xff;
619 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
621 else if (CharNStat & STMPARITYH)
623 else if (CharNStat & STMRCVROVRH)
630 After emtying FIFO in status mode, turn off status mode
633 if(sGetRxCnt(cp) == 0) {
634 sDisRxStatusMode(cp);
638 * Avoid the grotesquely inefficient lineswitch routine
639 * (ttyinput) in "raw" mode. It usually takes about 450
640 * instructions (that's without canonical processing or echo!).
641 * slinput is reasonably fast (usually 40 instructions plus
644 ToRecv = sGetRxCnt(cp);
645 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
646 if ( ToRecv > RXFIFO_SIZE ) {
647 ToRecv = RXFIFO_SIZE;
649 for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) {
650 le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp)));
653 rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp));
657 tp->t_rawcc += ToRecv;
658 ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq);
662 if(tp->t_state & TS_TBLOCK) {
665 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
675 static void rp_handle_port(struct rp_port *rp)
679 unsigned int IntMask, ChanStatus;
684 cp = &rp->rp_channel;
686 IntMask = sGetChanIntID(cp);
687 IntMask = IntMask & rp->rp_intmask;
688 ChanStatus = sGetChanStatus(cp);
689 if(IntMask & RXF_TRIG)
690 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
691 rp_do_receive(rp, tp, cp, ChanStatus);
693 if(IntMask & DELTA_CD) {
694 if(ChanStatus & CD_ACT) {
695 if(!(tp->t_state & TS_CARR_ON) ) {
696 (void)ttyld_modem(tp, 1);
699 if((tp->t_state & TS_CARR_ON)) {
700 (void)ttyld_modem(tp, 0);
701 if(ttyld_modem(tp, 0) == 0) {
707 /* oldcts = rp->rp_cts;
708 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
709 if(oldcts != rp->rp_cts) {
710 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
715 static void rp_do_poll(void *not_used)
720 int unit, aiop, ch, line, count;
721 unsigned char CtlMask, AiopMask;
723 for(unit = 0; unit < rp_ndevs; unit++) {
726 CtlMask = ctl->ctlmask(ctl);
727 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
729 AiopMask = sGetAiopIntStatus(ctl, aiop);
730 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
732 line = (unit << 5) | (aiop << 3) | ch;
740 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
743 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
744 count = sGetTxCnt(&rp->rp_channel);
746 tp->t_state &= ~(TS_BUSY);
747 if(!(tp->t_state & TS_TTSTOP) &&
748 (count <= rp->rp_restart)) {
754 if(rp_num_ports_open)
755 rp_callout_handle = timeout(rp_do_poll,
756 (void *)NULL, POLL_INTERVAL);
760 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
764 int aiop, chan, port;
765 int ChanStatus, line, count;
770 unit = device_get_unit(ctlp->dev);
772 printf("RocketPort%d (Version %s) %d ports.\n", unit,
773 RocketPortVersion, num_ports);
774 rp_num_ports[unit] = num_ports;
775 callout_handle_init(&rp_callout_handle);
777 ctlp->rp = rp = (struct rp_port *)
778 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
780 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
785 count = unit * 32; /* board times max ports per card SG */
787 bzero(rp, sizeof(struct rp_port) * num_ports);
793 for(aiop=0; aiop < num_aiops; aiop++) {
794 num_chan = sGetAiopNumChan(ctlp, aiop);
795 for(chan=0; chan < num_chan; chan++, port++, rp++) {
796 tp = rp->rp_tty = ttyalloc();
798 tp->t_param = rpparam;
799 tp->t_oproc = rpstart;
801 tp->t_break = rpbreak;
802 tp->t_modem = rpmodem;
803 tp->t_close = rpclose;
805 tp->t_ififosize = 512;
806 tp->t_ispeedwat = (speed_t)-1;
807 tp->t_ospeedwat = (speed_t)-1;
814 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
815 DELTA_CD | DELTA_CTS | DELTA_DSR;
817 ChanStatus = sGetChanStatus(&rp->rp_channel);
819 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
820 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
825 ChanStatus = sGetChanStatus(&rp->rp_channel);
826 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
827 line = (unit << 5) | (aiop << 3) | chan;
829 ttycreate(tp, TS_CALLOUT, "R%r%r", unit, port);
837 rp_releaseresource(ctlp);
843 rp_releaseresource(CONTROLLER_t *ctlp)
849 unit = device_get_unit(ctlp->dev);
850 if (rp_addr(unit) != NULL) {
851 for (i = 0; i < rp_num_ports[unit]; i++) {
852 rp = rp_addr(unit) + i;
857 if (ctlp->rp != NULL) {
859 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
860 if (p_rp_addr[i] == ctlp->rp)
862 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
863 if (p_rp_table[i] == ctlp->rp)
864 p_rp_table[i] = NULL;
866 free(ctlp->rp, M_DEVBUF);
874 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
878 rpopen(struct tty *tp, struct cdev *dev)
882 unsigned int IntMask, ChanStatus;
891 rp->rp_channel.TxControl[3] =
892 ((rp->rp_channel.TxControl[3]
893 & ~(SET_RTS | SET_DTR)) | flags);
894 rp_writech4(&rp->rp_channel,_INDX_ADDR,
895 le32dec(rp->rp_channel.TxControl));
896 sSetRxTrigger(&rp->rp_channel, TRIG_1);
897 sDisRxStatusMode(&rp->rp_channel);
898 sFlushRxFIFO(&rp->rp_channel);
899 sFlushTxFIFO(&rp->rp_channel);
901 sEnInterrupts(&rp->rp_channel,
902 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
903 sSetRxTrigger(&rp->rp_channel, TRIG_1);
905 sDisRxStatusMode(&rp->rp_channel);
906 sClrTxXOFF(&rp->rp_channel);
908 /* sDisRTSFlowCtl(&rp->rp_channel);
909 sDisCTSFlowCtl(&rp->rp_channel);
911 sDisTxSoftFlowCtl(&rp->rp_channel);
913 sStartRxProcessor(&rp->rp_channel);
915 sEnRxFIFO(&rp->rp_channel);
916 sEnTransmit(&rp->rp_channel);
918 /* sSetDTR(&rp->rp_channel);
919 sSetRTS(&rp->rp_channel);
924 IntMask = sGetChanIntID(&rp->rp_channel);
925 IntMask = IntMask & rp->rp_intmask;
926 ChanStatus = sGetChanStatus(&rp->rp_channel);
928 if(rp_num_ports_open == 1)
929 rp_callout_handle = timeout(rp_do_poll,
930 (void *)NULL, POLL_INTERVAL);
932 device_busy(rp->rp_ctlp->dev);
937 rpclose(struct tty *tp)
943 device_unbusy(rp->rp_ctlp->dev);
947 rphardclose(struct tty *tp)
953 cp = &rp->rp_channel;
958 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
961 sDisTxSoftFlowCtl(cp);
964 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) {
967 if(ISCALLOUT(tp->t_dev)) {
970 tp->t_actout = FALSE;
971 wakeup(&tp->t_actout);
972 wakeup(TSA_CARR_ON(tp));
976 rpbreak(struct tty *tp, int sig)
982 sSendBreak(&rp->rp_channel);
984 sClrBreak(&rp->rp_channel);
989 rpmodem(struct tty *tp, int sigon, int sigoff)
995 if (sigon != 0 || sigoff != 0) {
999 if (sigoff & SER_DTR)
1001 if (sigon & SER_RTS)
1003 if (sigoff & SER_RTS)
1005 rp->rp_channel.TxControl[3] &= ~i;
1006 rp->rp_channel.TxControl[3] |= j;
1007 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1008 le32dec(rp->rp_channel.TxControl));
1010 i = sGetChanStatusLo(&rp->rp_channel);
1011 j = rp->rp_channel.TxControl[3];
1028 static struct speedtab baud_table[] = {
1029 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1030 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1031 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1032 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1033 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1034 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1035 {B57600, BRD57600}, {B76800, BRD76800},
1036 {B115200, BRD115200}, {B230400, BRD230400},
1047 int oldspl, cflag, iflag, oflag, lflag;
1055 cp = &rp->rp_channel;
1060 devshift = umynor / 32;
1061 devshift = 1 << devshift;
1062 if ( devshift & RPCLOCAL ) {
1070 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1071 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1074 tp->t_ispeed = t->c_ispeed;
1075 tp->t_ospeed = t->c_ospeed;
1076 tp->t_cflag = cflag;
1077 tp->t_iflag = iflag;
1078 tp->t_oflag = oflag;
1079 tp->t_lflag = lflag;
1081 if(t->c_ospeed == 0) {
1085 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1087 /* Set baud rate ----- we only pay attention to ispeed */
1090 sSetBaud(cp, ospeed);
1092 if(cflag & CSTOPB) {
1098 if(cflag & PARENB) {
1100 if(cflag & PARODD) {
1109 if((cflag & CSIZE) == CS8) {
1111 rp->rp_imask = 0xFF;
1114 rp->rp_imask = 0x7F;
1117 if(iflag & ISTRIP) {
1118 rp->rp_imask &= 0x7F;
1121 if(cflag & CLOCAL) {
1122 rp->rp_intmask &= ~DELTA_CD;
1124 rp->rp_intmask |= DELTA_CD;
1127 /* Put flow control stuff here */
1129 if(cflag & CCTS_OFLOW) {
1135 if(cflag & CRTS_IFLOW) {
1136 rp->rp_rts_iflow = 1;
1138 rp->rp_rts_iflow = 0;
1141 if(cflag & CRTS_IFLOW) {
1148 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1149 tp->t_state |= TS_CARR_ON;
1150 wakeup(TSA_CARR_ON(tp));
1153 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1154 flags = rp->rp_channel.TxControl[3];
1173 int spl, xmit_fifo_room;
1174 int i, count, wcount;
1178 cp = &rp->rp_channel;
1179 flags = rp->rp_channel.TxControl[3];
1182 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1187 if(rp->rp_xmit_stopped) {
1189 rp->rp_xmit_stopped = 0;
1191 count = sGetTxCnt(cp);
1193 if(tp->t_outq.c_cc == 0) {
1194 if((tp->t_state & TS_BUSY) && (count == 0)) {
1195 tp->t_state &= ~TS_BUSY;
1201 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1203 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1204 tp->t_state |= TS_BUSY;
1205 count = q_to_b( qp, rp->TxBuf, xmit_fifo_room );
1206 for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) {
1207 rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i));
1210 rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]);
1213 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1222 register struct tty *tp;
1230 cp = &rp->rp_channel;
1234 if(tp->t_state & TS_BUSY) {
1235 if((tp->t_state&TS_TTSTOP) == 0) {
1238 if(rp->rp_xmit_stopped == 0) {
1240 rp->rp_xmit_stopped = 1;