Deleted Added
full compact
rp.c (131981) rp.c (132226)
1/*
2 * Copyright (c) Comtrol Corporation <support@comtrol.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted prodived that the follwoing conditions
7 * are met.
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.
19 *
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
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <sys/cdefs.h>
1/*
2 * Copyright (c) Comtrol Corporation <support@comtrol.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted prodived that the follwoing conditions
7 * are met.
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.
19 *
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
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/dev/rp/rp.c 131981 2004-07-11 15:18:39Z phk $");
35__FBSDID("$FreeBSD: head/sys/dev/rp/rp.c 132226 2004-07-15 20:47:41Z phk $");
36
37/*
38 * rp.c - for RocketPort FreeBSD
39 */
40
41#include "opt_compat.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/fcntl.h>
46#include <sys/malloc.h>
47#include <sys/tty.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <machine/resource.h>
51#include <machine/bus.h>
52#include <sys/bus.h>
53#include <sys/rman.h>
54
55#define ROCKET_C
56#include <dev/rp/rpreg.h>
57#include <dev/rp/rpvar.h>
58
59static const char RocketPortVersion[] = "3.02";
60
61static Byte_t RData[RDATASIZE] =
62{
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
81};
82
83static Byte_t RRegData[RREGDATASIZE]=
84{
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 */
98};
99
100#if 0
101/* IRQ number to MUDBAC register 2 mapping */
102Byte_t sIRQMap[16] =
103{
104 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
105};
106#endif
107
108Byte_t rp_sBitMapClrTbl[8] =
109{
110 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
111};
112
113Byte_t rp_sBitMapSetTbl[8] =
114{
115 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
116};
117
118/* Actually not used */
119#if notdef
120struct termios deftermios = {
121 TTYDEF_IFLAG,
122 TTYDEF_OFLAG,
123 TTYDEF_CFLAG,
124 TTYDEF_LFLAG,
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 },
128 TTYDEF_SPEED,
129 TTYDEF_SPEED
130};
131#endif
132
133/***************************************************************************
134Function: sReadAiopID
135Purpose: Read the AIOP idenfication number directly from an AIOP.
136Call: sReadAiopID(CtlP, aiop)
137 CONTROLLER_T *CtlP; Ptr to controller structure
138 int aiop: AIOP index
139Return: 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
142Warnings: No context switches are allowed while executing this function.
143
144*/
145int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
146{
147 Byte_t AiopID; /* ID byte from AIOP */
148
149 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
150 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
151 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
152 if(AiopID == 0x06)
153 return(1);
154 else /* AIOP does not exist */
155 return(-1);
156}
157
158/***************************************************************************
159Function: sReadAiopNumChan
160Purpose: Read the number of channels available in an AIOP directly from
161 an AIOP.
162Call: sReadAiopNumChan(CtlP, aiop)
163 CONTROLLER_T *CtlP; Ptr to controller structure
164 int aiop: AIOP index
165Return: int: The number of channels available
166Comments: The number of channels is determined by write/reads from identical
167 offsets within the SRAM address spaces for channels 0 and 4.
168 If the channel 4 space is mirrored to channel 0 it is a 4 channel
169 AIOP, otherwise it is an 8 channel.
170Warnings: No context switches are allowed while executing this function.
171*/
172int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
173{
174 Word_t x, y;
175
176 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
177 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
178 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
179 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
180 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
181 if(x != y) /* if different must be 8 chan */
182 return(8);
183 else
184 return(4);
185}
186
187/***************************************************************************
188Function: sInitChan
189Purpose: Initialization of a channel and channel structure
190Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
191 CONTROLLER_T *CtlP; Ptr to controller structure
192 CHANNEL_T *ChP; Ptr to channel structure
193 int AiopNum; AIOP number within controller
194 int ChanNum; Channel number within AIOP
195Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
196 number exceeds number of channels available in AIOP.
197Comments: This function must be called before a channel can be used.
198Warnings: No range checking on any of the parameters is done.
199
200 No context switches are allowed while executing this function.
201*/
202int sInitChan( CONTROLLER_T *CtlP,
203 CHANNEL_T *ChP,
204 int AiopNum,
205 int ChanNum)
206{
207 int i, ChOff;
208 Byte_t *ChR;
209 static Byte_t R[4];
210
211 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
212 return(FALSE); /* exceeds num chans in AIOP */
213
214 /* Channel, AIOP, and controller identifiers */
215 ChP->CtlP = CtlP;
216 ChP->ChanID = CtlP->AiopID[AiopNum];
217 ChP->AiopNum = AiopNum;
218 ChP->ChanNum = ChanNum;
219
220 /* Initialize the channel from the RData array */
221 for(i=0; i < RDATASIZE; i+=4)
222 {
223 R[0] = RData[i];
224 R[1] = RData[i+1] + 0x10 * ChanNum;
225 R[2] = RData[i+2];
226 R[3] = RData[i+3];
227 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
228 }
229
230 ChR = ChP->R;
231 for(i=0; i < RREGDATASIZE; i+=4)
232 {
233 ChR[i] = RRegData[i];
234 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
235 ChR[i+2] = RRegData[i+2];
236 ChR[i+3] = RRegData[i+3];
237 }
238
239 /* Indexed registers */
240 ChOff = (Word_t)ChanNum * 0x1000;
241
242 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
243 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
244 ChP->BaudDiv[2] = (Byte_t)BRD9600;
245 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
246 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
247
248 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
249 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
250 ChP->TxControl[2] = 0;
251 ChP->TxControl[3] = 0;
252 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
253
254 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
255 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
256 ChP->RxControl[2] = 0;
257 ChP->RxControl[3] = 0;
258 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
259
260 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
261 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
262 ChP->TxEnables[2] = 0;
263 ChP->TxEnables[3] = 0;
264 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
265
266 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
267 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
268 ChP->TxCompare[2] = 0;
269 ChP->TxCompare[3] = 0;
270 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
271
272 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
273 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
274 ChP->TxReplace1[2] = 0;
275 ChP->TxReplace1[3] = 0;
276 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
277
278 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
279 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
280 ChP->TxReplace2[2] = 0;
281 ChP->TxReplace2[3] = 0;
282 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
283
284 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
285 ChP->TxFIFO = ChOff + _TX_FIFO;
286
287 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
288 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
289 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
290 rp_writech2(ChP,_INDX_DATA,0);
291 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
292 ChP->RxFIFO = ChOff + _RX_FIFO;
293
294 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
295 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
296 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
297 rp_writech2(ChP,_INDX_DATA,0);
298 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
299 rp_writech2(ChP,_INDX_DATA,0);
300 ChP->TxPrioCnt = ChOff + _TXP_CNT;
301 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
302 rp_writech1(ChP,_INDX_DATA,0);
303 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
304 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
305 rp_writech1(ChP,_INDX_DATA,0);
306 ChP->TxPrioBuf = ChOff + _TXP_BUF;
307 sEnRxProcessor(ChP); /* start the Rx processor */
308
309 return(TRUE);
310}
311
312/***************************************************************************
313Function: sStopRxProcessor
314Purpose: Stop the receive processor from processing a channel.
315Call: sStopRxProcessor(ChP)
316 CHANNEL_T *ChP; Ptr to channel structure
317
318Comments: The receive processor can be started again with sStartRxProcessor().
319 This function causes the receive processor to skip over the
320 stopped channel. It does not stop it from processing other channels.
321
322Warnings: No context switches are allowed while executing this function.
323
324 Do not leave the receive processor stopped for more than one
325 character time.
326
327 After calling this function a delay of 4 uS is required to ensure
328 that the receive processor is no longer processing this channel.
329*/
330void sStopRxProcessor(CHANNEL_T *ChP)
331{
332 Byte_t R[4];
333
334 R[0] = ChP->R[0];
335 R[1] = ChP->R[1];
336 R[2] = 0x0a;
337 R[3] = ChP->R[3];
338 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
339}
340
341/***************************************************************************
342Function: sFlushRxFIFO
343Purpose: Flush the Rx FIFO
344Call: sFlushRxFIFO(ChP)
345 CHANNEL_T *ChP; Ptr to channel structure
346Return: void
347Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
348 while it is being flushed the receive processor is stopped
349 and the transmitter is disabled. After these operations a
350 4 uS delay is done before clearing the pointers to allow
351 the receive processor to stop. These items are handled inside
352 this function.
353Warnings: No context switches are allowed while executing this function.
354*/
355void sFlushRxFIFO(CHANNEL_T *ChP)
356{
357 int i;
358 Byte_t Ch; /* channel number within AIOP */
359 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
360
361 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
362 return; /* don't need to flush */
363
364 RxFIFOEnabled = FALSE;
365 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
366 {
367 RxFIFOEnabled = TRUE;
368 sDisRxFIFO(ChP); /* disable it */
369 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
370 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
371 }
372 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
373 Ch = (Byte_t)sGetChanNum(ChP);
374 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
375 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
376 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
377 rp_writech2(ChP,_INDX_DATA,0);
378 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
379 rp_writech2(ChP,_INDX_DATA,0);
380 if(RxFIFOEnabled)
381 sEnRxFIFO(ChP); /* enable Rx FIFO */
382}
383
384/***************************************************************************
385Function: sFlushTxFIFO
386Purpose: Flush the Tx FIFO
387Call: sFlushTxFIFO(ChP)
388 CHANNEL_T *ChP; Ptr to channel structure
389Return: void
390Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
391 while it is being flushed the receive processor is stopped
392 and the transmitter is disabled. After these operations a
393 4 uS delay is done before clearing the pointers to allow
394 the receive processor to stop. These items are handled inside
395 this function.
396Warnings: No context switches are allowed while executing this function.
397*/
398void sFlushTxFIFO(CHANNEL_T *ChP)
399{
400 int i;
401 Byte_t Ch; /* channel number within AIOP */
402 int TxEnabled; /* TRUE if transmitter enabled */
403
404 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
405 return; /* don't need to flush */
406
407 TxEnabled = FALSE;
408 if(ChP->TxControl[3] & TX_ENABLE)
409 {
410 TxEnabled = TRUE;
411 sDisTransmit(ChP); /* disable transmitter */
412 }
413 sStopRxProcessor(ChP); /* stop Rx processor */
414 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
415 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
416 Ch = (Byte_t)sGetChanNum(ChP);
417 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
418 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
419 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
420 rp_writech2(ChP,_INDX_DATA,0);
421 if(TxEnabled)
422 sEnTransmit(ChP); /* enable transmitter */
423 sStartRxProcessor(ChP); /* restart Rx processor */
424}
425
426/***************************************************************************
427Function: sWriteTxPrioByte
428Purpose: Write a byte of priority transmit data to a channel
429Call: sWriteTxPrioByte(ChP,Data)
430 CHANNEL_T *ChP; Ptr to channel structure
431 Byte_t Data; The transmit data byte
432
433Return: int: 1 if the bytes is successfully written, otherwise 0.
434
435Comments: The priority byte is transmitted before any data in the Tx FIFO.
436
437Warnings: No context switches are allowed while executing this function.
438*/
439int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
440{
441 Byte_t DWBuf[4]; /* buffer for double word writes */
442 Word_t *WordPtr; /* must be far because Win SS != DS */
443
444 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
445 {
446 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
447 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
448 return(0); /* nothing sent */
449
450 WordPtr = (Word_t *)(&DWBuf[0]);
451 *WordPtr = ChP->TxPrioBuf; /* data byte address */
452
453 DWBuf[2] = Data; /* data byte value */
454 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
455
456 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
457
458 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
459 DWBuf[3] = 0; /* priority buffer pointer */
460 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
461 }
462 else /* write it to Tx FIFO */
463 {
464 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
465 }
466 return(1); /* 1 byte sent */
467}
468
469/***************************************************************************
470Function: sEnInterrupts
471Purpose: Enable one or more interrupts for a channel
472Call: sEnInterrupts(ChP,Flags)
473 CHANNEL_T *ChP; Ptr to channel structure
474 Word_t Flags: Interrupt enable flags, can be any combination
475 of the following flags:
476 TXINT_EN: Interrupt on Tx FIFO empty
477 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
478 sSetRxTrigger())
479 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
480 MCINT_EN: Interrupt on modem input change
481 CHANINT_EN: Allow channel interrupt signal to the AIOP's
482 Interrupt Channel Register.
483Return: void
484Comments: If an interrupt enable flag is set in Flags, that interrupt will be
485 enabled. If an interrupt enable flag is not set in Flags, that
486 interrupt will not be changed. Interrupts can be disabled with
487 function sDisInterrupts().
488
489 This function sets the appropriate bit for the channel in the AIOP's
490 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
491 this channel's bit to be set in the AIOP's Interrupt Channel Register.
492
493 Interrupts must also be globally enabled before channel interrupts
494 will be passed on to the host. This is done with function
495 sEnGlobalInt().
496
497 In some cases it may be desirable to disable interrupts globally but
498 enable channel interrupts. This would allow the global interrupt
499 status register to be used to determine which AIOPs need service.
500*/
501void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
502{
503 Byte_t Mask; /* Interrupt Mask Register */
504
505 ChP->RxControl[2] |=
506 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
507
508 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
509
510 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
511
512 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
513
514 if(Flags & CHANINT_EN)
515 {
516 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
517 rp_writech1(ChP,_INT_MASK,Mask);
518 }
519}
520
521/***************************************************************************
522Function: sDisInterrupts
523Purpose: Disable one or more interrupts for a channel
524Call: sDisInterrupts(ChP,Flags)
525 CHANNEL_T *ChP; Ptr to channel structure
526 Word_t Flags: Interrupt flags, can be any combination
527 of the following flags:
528 TXINT_EN: Interrupt on Tx FIFO empty
529 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
530 sSetRxTrigger())
531 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
532 MCINT_EN: Interrupt on modem input change
533 CHANINT_EN: Disable channel interrupt signal to the
534 AIOP's Interrupt Channel Register.
535Return: void
536Comments: If an interrupt flag is set in Flags, that interrupt will be
537 disabled. If an interrupt flag is not set in Flags, that
538 interrupt will not be changed. Interrupts can be enabled with
539 function sEnInterrupts().
540
541 This function clears the appropriate bit for the channel in the AIOP's
542 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
543 this channel's bit from being set in the AIOP's Interrupt Channel
544 Register.
545*/
546void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
547{
548 Byte_t Mask; /* Interrupt Mask Register */
549
550 ChP->RxControl[2] &=
551 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
552 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
553 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
554 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
555
556 if(Flags & CHANINT_EN)
557 {
558 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
559 rp_writech1(ChP,_INT_MASK,Mask);
560 }
561}
562
563/*********************************************************************
564 Begin FreeBsd-specific driver code
565**********************************************************************/
566
567static timeout_t rpdtrwakeup;
568struct callout_handle rp_callout_handle;
569
570static d_open_t rpopen;
571static d_close_t rpclose;
572static d_write_t rpwrite;
573static d_ioctl_t rpioctl;
574
575struct cdevsw rp_cdevsw = {
576 .d_version = D_VERSION,
577 .d_open = rpopen,
578 .d_close = rpclose,
579 .d_write = rpwrite,
580 .d_ioctl = rpioctl,
581 .d_name = "rp",
582 .d_flags = D_TTY | D_NEEDGIANT,
583};
584
585static int rp_num_ports_open = 0;
586static int rp_ndevs = 0;
587static int minor_to_unit[128];
588
589static int rp_num_ports[4]; /* Number of ports on each controller */
590
591#define POLL_INTERVAL 1
592
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)
602
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)
606
607static struct rp_port *p_rp_addr[4];
608static 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])
611
612/*
613 * The top-level routines begin here
614 */
615
616static int rpparam(struct tty *, struct termios *);
617static void rpstart(struct tty *);
618static void rpstop(struct tty *, int);
619static void rphardclose (struct rp_port *);
620
621static void rp_do_receive(struct rp_port *rp, struct tty *tp,
622 CHANNEL_t *cp, unsigned int ChanStatus)
623{
624 int spl;
625 unsigned int CharNStat;
626 int ToRecv, wRecv, ch, ttynocopy;
627
628 ToRecv = sGetRxCnt(cp);
629 if(ToRecv == 0)
630 return;
631
632/* If status indicates there are errored characters in the
633 FIFO, then enter status mode (a word in FIFO holds
634 characters and status)
635*/
636
637 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
638 if(!(ChanStatus & STATMODE)) {
639 ChanStatus |= STATMODE;
640 sEnRxStatusMode(cp);
641 }
642 }
643/*
644 if we previously entered status mode then read down the
645 FIFO one word at a time, pulling apart the character and
646 the status. Update error counters depending on status.
647*/
648 if(ChanStatus & STATMODE) {
649 while(ToRecv) {
650 if(tp->t_state & TS_TBLOCK) {
651 break;
652 }
653 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
654 ch = CharNStat & 0xff;
655
656 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
657 ch |= TTY_FE;
658 else if (CharNStat & STMPARITYH)
659 ch |= TTY_PE;
660 else if (CharNStat & STMRCVROVRH)
661 rp->rp_overflows++;
662
663 ttyld_rint(tp, ch);
664 ToRecv--;
665 }
666/*
667 After emtying FIFO in status mode, turn off status mode
668*/
669
670 if(sGetRxCnt(cp) == 0) {
671 sDisRxStatusMode(cp);
672 }
673 } else {
674 /*
675 * Avoid the grotesquely inefficient lineswitch routine
676 * (ttyinput) in "raw" mode. It usually takes about 450
677 * instructions (that's without canonical processing or echo!).
678 * slinput is reasonably fast (usually 40 instructions plus
679 * call overhead).
680 */
681 ToRecv = sGetRxCnt(cp);
682 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
683 if ( ToRecv > RXFIFO_SIZE ) {
684 ToRecv = RXFIFO_SIZE;
685 }
686 wRecv = ToRecv >> 1;
687 if ( wRecv ) {
688 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
689 }
690 if ( ToRecv & 1 ) {
691 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
692 }
693 tk_nin += ToRecv;
694 tk_rawcc += ToRecv;
695 tp->t_rawcc += ToRecv;
696 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
697 ttwakeup(tp);
698 } else {
699 while (ToRecv) {
700 if(tp->t_state & TS_TBLOCK) {
701 break;
702 }
703 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
704 spl = spltty();
705 ttyld_rint(tp, ch);
706 splx(spl);
707 ToRecv--;
708 }
709 }
710 }
711}
712
713static void rp_handle_port(struct rp_port *rp)
714{
715 CHANNEL_t *cp;
716 struct tty *tp;
717 unsigned int IntMask, ChanStatus;
718
719 if(!rp)
720 return;
721
722 cp = &rp->rp_channel;
723 tp = rp->rp_tty;
724 IntMask = sGetChanIntID(cp);
725 IntMask = IntMask & rp->rp_intmask;
726 ChanStatus = sGetChanStatus(cp);
727 if(IntMask & RXF_TRIG)
728 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
729 rp_do_receive(rp, tp, cp, ChanStatus);
730 }
731 if(IntMask & DELTA_CD) {
732 if(ChanStatus & CD_ACT) {
733 if(!(tp->t_state & TS_CARR_ON) ) {
734 (void)ttyld_modem(tp, 1);
735 }
736 } else {
737 if((tp->t_state & TS_CARR_ON)) {
738 (void)ttyld_modem(tp, 0);
739 if(ttyld_modem(tp, 0) == 0) {
740 rphardclose(rp);
741 }
742 }
743 }
744 }
745/* oldcts = rp->rp_cts;
746 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
747 if(oldcts != rp->rp_cts) {
748 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
749 }
750*/
751}
752
753static void rp_do_poll(void *not_used)
754{
755 CONTROLLER_t *ctl;
756 struct rp_port *rp;
757 struct tty *tp;
758 int unit, aiop, ch, line, count;
759 unsigned char CtlMask, AiopMask;
760
761 for(unit = 0; unit < rp_ndevs; unit++) {
762 rp = rp_addr(unit);
763 ctl = rp->rp_ctlp;
764 CtlMask = ctl->ctlmask(ctl);
765 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
766 if(CtlMask & 1) {
767 AiopMask = sGetAiopIntStatus(ctl, aiop);
768 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
769 if(AiopMask & 1) {
770 line = (unit << 5) | (aiop << 3) | ch;
771 rp = rp_table(line);
772 rp_handle_port(rp);
773 }
774 }
775 }
776 }
777
778 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
779 line++, rp++) {
780 tp = rp->rp_tty;
781 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
782 count = sGetTxCnt(&rp->rp_channel);
783 if(count == 0)
784 tp->t_state &= ~(TS_BUSY);
785 if(!(tp->t_state & TS_TTSTOP) &&
786 (count <= rp->rp_restart)) {
787 ttyld_start(tp);
788 }
789 }
790 }
791 }
792 if(rp_num_ports_open)
793 rp_callout_handle = timeout(rp_do_poll,
794 (void *)NULL, POLL_INTERVAL);
795}
796
797int
798rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
799{
800 int oldspl, unit;
801 int num_chan;
802 int aiop, chan, port;
803 int ChanStatus, line, i, count;
804 int retval;
805 struct rp_port *rp;
806 struct cdev **dev_nodes;
807
808 unit = device_get_unit(ctlp->dev);
809
810 printf("RocketPort%d (Version %s) %d ports.\n", unit,
811 RocketPortVersion, num_ports);
812 rp_num_ports[unit] = num_ports;
813 callout_handle_init(&rp_callout_handle);
814
815 ctlp->rp = rp = (struct rp_port *)
816 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
817 if (rp == NULL) {
818 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
819 retval = ENOMEM;
820 goto nogo;
821 }
822
823 count = unit * 32; /* board times max ports per card SG */
824 for(i=count;i < (count + rp_num_ports[unit]);i++)
825 minor_to_unit[i] = unit;
826
827 bzero(rp, sizeof(struct rp_port) * num_ports);
828 oldspl = spltty();
829 rp_addr(unit) = rp;
830 splx(oldspl);
831
832 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
833 if(ctlp->dev_nodes == NULL) {
834 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
835 retval = ENOMEM;
836 goto nogo;
837 }
838
839 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
840 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
841 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
842 i <= 9 ? '0' + i : 'a' + i - 10);
843 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
844 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
845 i <= 9 ? '0' + i : 'a' + i - 10);
846 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
847 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
848 i <= 9 ? '0' + i : 'a' + i - 10);
849 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
850 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
851 i <= 9 ? '0' + i : 'a' + i - 10);
852 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
853 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
854 i <= 9 ? '0' + i : 'a' + i - 10);
855 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
856 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
857 i <= 9 ? '0' + i : 'a' + i - 10);
858 }
859
860 port = 0;
861 for(aiop=0; aiop < num_aiops; aiop++) {
862 num_chan = sGetAiopNumChan(ctlp, aiop);
863 for(chan=0; chan < num_chan; chan++, port++, rp++) {
864 rp->rp_tty = ttymalloc(NULL);
865 rp->rp_port = port;
866 rp->rp_ctlp = ctlp;
867 rp->rp_unit = unit;
868 rp->rp_chan = chan;
869 rp->rp_aiop = aiop;
870
871 rp->rp_tty->t_line = 0;
872 /* tty->t_termios = deftermios;
873 */
874 rp->it_in.c_iflag = 0;
875 rp->it_in.c_oflag = 0;
876 rp->it_in.c_cflag = TTYDEF_CFLAG;
877 rp->it_in.c_lflag = 0;
878 termioschars(&rp->it_in);
879 /* termioschars(&tty->t_termios);
880 */
881 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
882 rp->it_out = rp->it_in;
883
884 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
885 DELTA_CD | DELTA_CTS | DELTA_DSR;
886#if notdef
887 ChanStatus = sGetChanStatus(&rp->rp_channel);
888#endif /* notdef */
889 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
890 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
891 unit, aiop, chan);
892 retval = ENXIO;
893 goto nogo;
894 }
895 ChanStatus = sGetChanStatus(&rp->rp_channel);
896 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
897 line = (unit << 5) | (aiop << 3) | chan;
898 rp_table(line) = rp;
899 }
900 }
901
902 rp_ndevs++;
903 return (0);
904
905nogo:
906 rp_releaseresource(ctlp);
907
908 return (retval);
909}
910
911void
912rp_releaseresource(CONTROLLER_t *ctlp)
913{
914 int i, s, unit;
915 struct rp_port *rp;
916
917
918 unit = device_get_unit(ctlp->dev);
919 if (rp_addr(unit) != NULL) {
920 for (i = 0; i < rp_num_ports[unit]; i++) {
921 rp = rp_addr(unit) + i;
922 s = ttyrel(rp->rp_tty);
923 if (s) {
924 printf("Detaching with active tty (%d refs)!\n", s);
925 }
926 }
927 }
928
929 if (ctlp->rp != NULL) {
930 s = spltty();
931 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
932 if (p_rp_addr[i] == ctlp->rp)
933 p_rp_addr[i] = NULL;
934 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
935 if (p_rp_table[i] == ctlp->rp)
936 p_rp_table[i] = NULL;
937 splx(s);
938 free(ctlp->rp, M_DEVBUF);
939 ctlp->rp = NULL;
940 }
941 if (ctlp->dev != NULL) {
942 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
943 destroy_dev(ctlp->dev_nodes[i]);
944 free(ctlp->dev_nodes, M_DEVBUF);
945 ctlp->dev = NULL;
946 }
947}
948
949void
950rp_untimeout(void)
951{
952 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
953}
954static int
955rpopen(dev, flag, mode, td)
956 struct cdev *dev;
957 int flag, mode;
958 struct thread *td;
959{
960 struct rp_port *rp;
961 int unit, port, mynor, umynor, flags; /* SG */
962 struct tty *tp;
963 int oldspl, error;
964 unsigned int IntMask, ChanStatus;
965
966
967 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
968 port = (minor(dev) & 0x1f); /* SG */
969 mynor = (port + umynor); /* SG */
970 unit = minor_to_unit[mynor];
971 if (rp_addr(unit) == NULL)
972 return (ENXIO);
973 if(IS_CONTROL(dev))
974 return(0);
975 rp = rp_addr(unit) + port;
976/* rp->rp_tty = &rp_tty[rp->rp_port];
977*/
978 tp = rp->rp_tty;
979 dev->si_tty = tp;
980
981 oldspl = spltty();
982
983open_top:
984 while(rp->state & ~SET_DTR) {
985 error = tsleep(&tp->t_dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
986 if(error != 0)
987 goto out;
988 }
989
990 if(tp->t_state & TS_ISOPEN) {
991 if(IS_CALLOUT(dev)) {
992 if(!rp->active_out) {
993 error = EBUSY;
994 goto out;
995 }
996 } else {
997 if(rp->active_out) {
998 if(flag & O_NONBLOCK) {
999 error = EBUSY;
1000 goto out;
1001 }
1002 error = tsleep(&rp->active_out,
1003 TTIPRI | PCATCH, "rpbi", 0);
1004 if(error != 0)
1005 goto out;
1006 goto open_top;
1007 }
1008 }
1009 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1010 splx(oldspl);
1011 error = EBUSY;
1012 goto out2;
1013 }
1014 }
1015 else {
1016 tp->t_dev = dev;
1017 tp->t_param = rpparam;
1018 tp->t_oproc = rpstart;
1019 tp->t_stop = rpstop;
1020 tp->t_line = 0;
1021 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1022 tp->t_ififosize = 512;
1023 tp->t_ispeedwat = (speed_t)-1;
1024 tp->t_ospeedwat = (speed_t)-1;
1025 flags = 0;
1026 flags |= SET_RTS;
1027 flags |= SET_DTR;
1028 rp->rp_channel.TxControl[3] =
1029 ((rp->rp_channel.TxControl[3]
1030 & ~(SET_RTS | SET_DTR)) | flags);
1031 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1032 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1033 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1034 sDisRxStatusMode(&rp->rp_channel);
1035 sFlushRxFIFO(&rp->rp_channel);
1036 sFlushTxFIFO(&rp->rp_channel);
1037
1038 sEnInterrupts(&rp->rp_channel,
1039 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1040 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1041
1042 sDisRxStatusMode(&rp->rp_channel);
1043 sClrTxXOFF(&rp->rp_channel);
1044
1045/* sDisRTSFlowCtl(&rp->rp_channel);
1046 sDisCTSFlowCtl(&rp->rp_channel);
1047*/
1048 sDisTxSoftFlowCtl(&rp->rp_channel);
1049
1050 sStartRxProcessor(&rp->rp_channel);
1051
1052 sEnRxFIFO(&rp->rp_channel);
1053 sEnTransmit(&rp->rp_channel);
1054
1055/* sSetDTR(&rp->rp_channel);
1056 sSetRTS(&rp->rp_channel);
1057*/
1058
1059 ++rp->wopeners;
1060 error = rpparam(tp, &tp->t_termios);
1061 --rp->wopeners;
1062 if(error != 0) {
1063 splx(oldspl);
1064 return(error);
1065 }
1066
1067 rp_num_ports_open++;
1068
1069 IntMask = sGetChanIntID(&rp->rp_channel);
1070 IntMask = IntMask & rp->rp_intmask;
1071 ChanStatus = sGetChanStatus(&rp->rp_channel);
1072 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1073 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1074 (void)ttyld_modem(tp, 1);
1075 }
1076 }
1077
1078 if(rp_num_ports_open == 1)
1079 rp_callout_handle = timeout(rp_do_poll,
1080 (void *)NULL, POLL_INTERVAL);
1081 }
1082
1083 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1084 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1085 ++rp->wopeners;
1086 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1087 "rpdcd", 0);
1088 --rp->wopeners;
1089 if(error != 0)
1090 goto out;
1091 goto open_top;
1092 }
1093 error = ttyld_open(tp, dev);
1094
1095 ttyldoptim(tp);
1096 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1097 rp->active_out = TRUE;
1098
1099/* if(rp_num_ports_open == 1)
1100 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1101*/
1102out:
1103 splx(oldspl);
1104 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1105 rphardclose(rp);
1106 }
1107out2:
1108 if (error == 0)
1109 device_busy(rp->rp_ctlp->dev);
1110 return(error);
1111}
1112
1113static int
1114rpclose(dev, flag, mode, td)
1115 struct cdev *dev;
1116 int flag, mode;
1117 struct thread *td;
1118{
1119 int oldspl, unit, mynor, umynor, port; /* SG */
1120 struct rp_port *rp;
1121 struct tty *tp;
1122 CHANNEL_t *cp;
1123
1124 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1125 port = (minor(dev) & 0x1f); /* SG */
1126 mynor = (port + umynor); /* SG */
1127 unit = minor_to_unit[mynor]; /* SG */
1128
1129 if(IS_CONTROL(dev))
1130 return(0);
1131 rp = rp_addr(unit) + port;
1132 cp = &rp->rp_channel;
1133 tp = rp->rp_tty;
1134
1135 oldspl = spltty();
1136 ttyld_close(tp, flag);
1137 ttyldoptim(tp);
1138 rphardclose(rp);
1139
1140 tp->t_state &= ~TS_BUSY;
36
37/*
38 * rp.c - for RocketPort FreeBSD
39 */
40
41#include "opt_compat.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/fcntl.h>
46#include <sys/malloc.h>
47#include <sys/tty.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <machine/resource.h>
51#include <machine/bus.h>
52#include <sys/bus.h>
53#include <sys/rman.h>
54
55#define ROCKET_C
56#include <dev/rp/rpreg.h>
57#include <dev/rp/rpvar.h>
58
59static const char RocketPortVersion[] = "3.02";
60
61static Byte_t RData[RDATASIZE] =
62{
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
81};
82
83static Byte_t RRegData[RREGDATASIZE]=
84{
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 */
98};
99
100#if 0
101/* IRQ number to MUDBAC register 2 mapping */
102Byte_t sIRQMap[16] =
103{
104 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
105};
106#endif
107
108Byte_t rp_sBitMapClrTbl[8] =
109{
110 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
111};
112
113Byte_t rp_sBitMapSetTbl[8] =
114{
115 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
116};
117
118/* Actually not used */
119#if notdef
120struct termios deftermios = {
121 TTYDEF_IFLAG,
122 TTYDEF_OFLAG,
123 TTYDEF_CFLAG,
124 TTYDEF_LFLAG,
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 },
128 TTYDEF_SPEED,
129 TTYDEF_SPEED
130};
131#endif
132
133/***************************************************************************
134Function: sReadAiopID
135Purpose: Read the AIOP idenfication number directly from an AIOP.
136Call: sReadAiopID(CtlP, aiop)
137 CONTROLLER_T *CtlP; Ptr to controller structure
138 int aiop: AIOP index
139Return: 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
142Warnings: No context switches are allowed while executing this function.
143
144*/
145int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
146{
147 Byte_t AiopID; /* ID byte from AIOP */
148
149 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
150 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
151 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
152 if(AiopID == 0x06)
153 return(1);
154 else /* AIOP does not exist */
155 return(-1);
156}
157
158/***************************************************************************
159Function: sReadAiopNumChan
160Purpose: Read the number of channels available in an AIOP directly from
161 an AIOP.
162Call: sReadAiopNumChan(CtlP, aiop)
163 CONTROLLER_T *CtlP; Ptr to controller structure
164 int aiop: AIOP index
165Return: int: The number of channels available
166Comments: The number of channels is determined by write/reads from identical
167 offsets within the SRAM address spaces for channels 0 and 4.
168 If the channel 4 space is mirrored to channel 0 it is a 4 channel
169 AIOP, otherwise it is an 8 channel.
170Warnings: No context switches are allowed while executing this function.
171*/
172int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
173{
174 Word_t x, y;
175
176 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
177 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
178 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
179 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
180 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
181 if(x != y) /* if different must be 8 chan */
182 return(8);
183 else
184 return(4);
185}
186
187/***************************************************************************
188Function: sInitChan
189Purpose: Initialization of a channel and channel structure
190Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
191 CONTROLLER_T *CtlP; Ptr to controller structure
192 CHANNEL_T *ChP; Ptr to channel structure
193 int AiopNum; AIOP number within controller
194 int ChanNum; Channel number within AIOP
195Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
196 number exceeds number of channels available in AIOP.
197Comments: This function must be called before a channel can be used.
198Warnings: No range checking on any of the parameters is done.
199
200 No context switches are allowed while executing this function.
201*/
202int sInitChan( CONTROLLER_T *CtlP,
203 CHANNEL_T *ChP,
204 int AiopNum,
205 int ChanNum)
206{
207 int i, ChOff;
208 Byte_t *ChR;
209 static Byte_t R[4];
210
211 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
212 return(FALSE); /* exceeds num chans in AIOP */
213
214 /* Channel, AIOP, and controller identifiers */
215 ChP->CtlP = CtlP;
216 ChP->ChanID = CtlP->AiopID[AiopNum];
217 ChP->AiopNum = AiopNum;
218 ChP->ChanNum = ChanNum;
219
220 /* Initialize the channel from the RData array */
221 for(i=0; i < RDATASIZE; i+=4)
222 {
223 R[0] = RData[i];
224 R[1] = RData[i+1] + 0x10 * ChanNum;
225 R[2] = RData[i+2];
226 R[3] = RData[i+3];
227 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0]));
228 }
229
230 ChR = ChP->R;
231 for(i=0; i < RREGDATASIZE; i+=4)
232 {
233 ChR[i] = RRegData[i];
234 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
235 ChR[i+2] = RRegData[i+2];
236 ChR[i+3] = RRegData[i+3];
237 }
238
239 /* Indexed registers */
240 ChOff = (Word_t)ChanNum * 0x1000;
241
242 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
243 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
244 ChP->BaudDiv[2] = (Byte_t)BRD9600;
245 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
246 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]);
247
248 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
249 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
250 ChP->TxControl[2] = 0;
251 ChP->TxControl[3] = 0;
252 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
253
254 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
255 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
256 ChP->RxControl[2] = 0;
257 ChP->RxControl[3] = 0;
258 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
259
260 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
261 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
262 ChP->TxEnables[2] = 0;
263 ChP->TxEnables[3] = 0;
264 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]);
265
266 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
267 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
268 ChP->TxCompare[2] = 0;
269 ChP->TxCompare[3] = 0;
270 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]);
271
272 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
273 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
274 ChP->TxReplace1[2] = 0;
275 ChP->TxReplace1[3] = 0;
276 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]);
277
278 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
279 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
280 ChP->TxReplace2[2] = 0;
281 ChP->TxReplace2[3] = 0;
282 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]);
283
284 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
285 ChP->TxFIFO = ChOff + _TX_FIFO;
286
287 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
288 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
289 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
290 rp_writech2(ChP,_INDX_DATA,0);
291 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
292 ChP->RxFIFO = ChOff + _RX_FIFO;
293
294 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
295 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
296 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
297 rp_writech2(ChP,_INDX_DATA,0);
298 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
299 rp_writech2(ChP,_INDX_DATA,0);
300 ChP->TxPrioCnt = ChOff + _TXP_CNT;
301 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
302 rp_writech1(ChP,_INDX_DATA,0);
303 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
304 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
305 rp_writech1(ChP,_INDX_DATA,0);
306 ChP->TxPrioBuf = ChOff + _TXP_BUF;
307 sEnRxProcessor(ChP); /* start the Rx processor */
308
309 return(TRUE);
310}
311
312/***************************************************************************
313Function: sStopRxProcessor
314Purpose: Stop the receive processor from processing a channel.
315Call: sStopRxProcessor(ChP)
316 CHANNEL_T *ChP; Ptr to channel structure
317
318Comments: The receive processor can be started again with sStartRxProcessor().
319 This function causes the receive processor to skip over the
320 stopped channel. It does not stop it from processing other channels.
321
322Warnings: No context switches are allowed while executing this function.
323
324 Do not leave the receive processor stopped for more than one
325 character time.
326
327 After calling this function a delay of 4 uS is required to ensure
328 that the receive processor is no longer processing this channel.
329*/
330void sStopRxProcessor(CHANNEL_T *ChP)
331{
332 Byte_t R[4];
333
334 R[0] = ChP->R[0];
335 R[1] = ChP->R[1];
336 R[2] = 0x0a;
337 R[3] = ChP->R[3];
338 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]);
339}
340
341/***************************************************************************
342Function: sFlushRxFIFO
343Purpose: Flush the Rx FIFO
344Call: sFlushRxFIFO(ChP)
345 CHANNEL_T *ChP; Ptr to channel structure
346Return: void
347Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
348 while it is being flushed the receive processor is stopped
349 and the transmitter is disabled. After these operations a
350 4 uS delay is done before clearing the pointers to allow
351 the receive processor to stop. These items are handled inside
352 this function.
353Warnings: No context switches are allowed while executing this function.
354*/
355void sFlushRxFIFO(CHANNEL_T *ChP)
356{
357 int i;
358 Byte_t Ch; /* channel number within AIOP */
359 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
360
361 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
362 return; /* don't need to flush */
363
364 RxFIFOEnabled = FALSE;
365 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
366 {
367 RxFIFOEnabled = TRUE;
368 sDisRxFIFO(ChP); /* disable it */
369 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
370 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
371 }
372 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
373 Ch = (Byte_t)sGetChanNum(ChP);
374 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
375 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
376 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
377 rp_writech2(ChP,_INDX_DATA,0);
378 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
379 rp_writech2(ChP,_INDX_DATA,0);
380 if(RxFIFOEnabled)
381 sEnRxFIFO(ChP); /* enable Rx FIFO */
382}
383
384/***************************************************************************
385Function: sFlushTxFIFO
386Purpose: Flush the Tx FIFO
387Call: sFlushTxFIFO(ChP)
388 CHANNEL_T *ChP; Ptr to channel structure
389Return: void
390Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
391 while it is being flushed the receive processor is stopped
392 and the transmitter is disabled. After these operations a
393 4 uS delay is done before clearing the pointers to allow
394 the receive processor to stop. These items are handled inside
395 this function.
396Warnings: No context switches are allowed while executing this function.
397*/
398void sFlushTxFIFO(CHANNEL_T *ChP)
399{
400 int i;
401 Byte_t Ch; /* channel number within AIOP */
402 int TxEnabled; /* TRUE if transmitter enabled */
403
404 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
405 return; /* don't need to flush */
406
407 TxEnabled = FALSE;
408 if(ChP->TxControl[3] & TX_ENABLE)
409 {
410 TxEnabled = TRUE;
411 sDisTransmit(ChP); /* disable transmitter */
412 }
413 sStopRxProcessor(ChP); /* stop Rx processor */
414 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
415 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
416 Ch = (Byte_t)sGetChanNum(ChP);
417 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
418 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
419 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
420 rp_writech2(ChP,_INDX_DATA,0);
421 if(TxEnabled)
422 sEnTransmit(ChP); /* enable transmitter */
423 sStartRxProcessor(ChP); /* restart Rx processor */
424}
425
426/***************************************************************************
427Function: sWriteTxPrioByte
428Purpose: Write a byte of priority transmit data to a channel
429Call: sWriteTxPrioByte(ChP,Data)
430 CHANNEL_T *ChP; Ptr to channel structure
431 Byte_t Data; The transmit data byte
432
433Return: int: 1 if the bytes is successfully written, otherwise 0.
434
435Comments: The priority byte is transmitted before any data in the Tx FIFO.
436
437Warnings: No context switches are allowed while executing this function.
438*/
439int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
440{
441 Byte_t DWBuf[4]; /* buffer for double word writes */
442 Word_t *WordPtr; /* must be far because Win SS != DS */
443
444 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
445 {
446 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
447 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
448 return(0); /* nothing sent */
449
450 WordPtr = (Word_t *)(&DWBuf[0]);
451 *WordPtr = ChP->TxPrioBuf; /* data byte address */
452
453 DWBuf[2] = Data; /* data byte value */
454 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
455
456 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
457
458 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
459 DWBuf[3] = 0; /* priority buffer pointer */
460 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */
461 }
462 else /* write it to Tx FIFO */
463 {
464 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
465 }
466 return(1); /* 1 byte sent */
467}
468
469/***************************************************************************
470Function: sEnInterrupts
471Purpose: Enable one or more interrupts for a channel
472Call: sEnInterrupts(ChP,Flags)
473 CHANNEL_T *ChP; Ptr to channel structure
474 Word_t Flags: Interrupt enable flags, can be any combination
475 of the following flags:
476 TXINT_EN: Interrupt on Tx FIFO empty
477 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
478 sSetRxTrigger())
479 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
480 MCINT_EN: Interrupt on modem input change
481 CHANINT_EN: Allow channel interrupt signal to the AIOP's
482 Interrupt Channel Register.
483Return: void
484Comments: If an interrupt enable flag is set in Flags, that interrupt will be
485 enabled. If an interrupt enable flag is not set in Flags, that
486 interrupt will not be changed. Interrupts can be disabled with
487 function sDisInterrupts().
488
489 This function sets the appropriate bit for the channel in the AIOP's
490 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
491 this channel's bit to be set in the AIOP's Interrupt Channel Register.
492
493 Interrupts must also be globally enabled before channel interrupts
494 will be passed on to the host. This is done with function
495 sEnGlobalInt().
496
497 In some cases it may be desirable to disable interrupts globally but
498 enable channel interrupts. This would allow the global interrupt
499 status register to be used to determine which AIOPs need service.
500*/
501void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
502{
503 Byte_t Mask; /* Interrupt Mask Register */
504
505 ChP->RxControl[2] |=
506 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
507
508 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
509
510 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
511
512 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
513
514 if(Flags & CHANINT_EN)
515 {
516 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
517 rp_writech1(ChP,_INT_MASK,Mask);
518 }
519}
520
521/***************************************************************************
522Function: sDisInterrupts
523Purpose: Disable one or more interrupts for a channel
524Call: sDisInterrupts(ChP,Flags)
525 CHANNEL_T *ChP; Ptr to channel structure
526 Word_t Flags: Interrupt flags, can be any combination
527 of the following flags:
528 TXINT_EN: Interrupt on Tx FIFO empty
529 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
530 sSetRxTrigger())
531 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
532 MCINT_EN: Interrupt on modem input change
533 CHANINT_EN: Disable channel interrupt signal to the
534 AIOP's Interrupt Channel Register.
535Return: void
536Comments: If an interrupt flag is set in Flags, that interrupt will be
537 disabled. If an interrupt flag is not set in Flags, that
538 interrupt will not be changed. Interrupts can be enabled with
539 function sEnInterrupts().
540
541 This function clears the appropriate bit for the channel in the AIOP's
542 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
543 this channel's bit from being set in the AIOP's Interrupt Channel
544 Register.
545*/
546void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
547{
548 Byte_t Mask; /* Interrupt Mask Register */
549
550 ChP->RxControl[2] &=
551 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
552 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]);
553 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
554 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]);
555
556 if(Flags & CHANINT_EN)
557 {
558 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
559 rp_writech1(ChP,_INT_MASK,Mask);
560 }
561}
562
563/*********************************************************************
564 Begin FreeBsd-specific driver code
565**********************************************************************/
566
567static timeout_t rpdtrwakeup;
568struct callout_handle rp_callout_handle;
569
570static d_open_t rpopen;
571static d_close_t rpclose;
572static d_write_t rpwrite;
573static d_ioctl_t rpioctl;
574
575struct cdevsw rp_cdevsw = {
576 .d_version = D_VERSION,
577 .d_open = rpopen,
578 .d_close = rpclose,
579 .d_write = rpwrite,
580 .d_ioctl = rpioctl,
581 .d_name = "rp",
582 .d_flags = D_TTY | D_NEEDGIANT,
583};
584
585static int rp_num_ports_open = 0;
586static int rp_ndevs = 0;
587static int minor_to_unit[128];
588
589static int rp_num_ports[4]; /* Number of ports on each controller */
590
591#define POLL_INTERVAL 1
592
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)
602
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)
606
607static struct rp_port *p_rp_addr[4];
608static 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])
611
612/*
613 * The top-level routines begin here
614 */
615
616static int rpparam(struct tty *, struct termios *);
617static void rpstart(struct tty *);
618static void rpstop(struct tty *, int);
619static void rphardclose (struct rp_port *);
620
621static void rp_do_receive(struct rp_port *rp, struct tty *tp,
622 CHANNEL_t *cp, unsigned int ChanStatus)
623{
624 int spl;
625 unsigned int CharNStat;
626 int ToRecv, wRecv, ch, ttynocopy;
627
628 ToRecv = sGetRxCnt(cp);
629 if(ToRecv == 0)
630 return;
631
632/* If status indicates there are errored characters in the
633 FIFO, then enter status mode (a word in FIFO holds
634 characters and status)
635*/
636
637 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
638 if(!(ChanStatus & STATMODE)) {
639 ChanStatus |= STATMODE;
640 sEnRxStatusMode(cp);
641 }
642 }
643/*
644 if we previously entered status mode then read down the
645 FIFO one word at a time, pulling apart the character and
646 the status. Update error counters depending on status.
647*/
648 if(ChanStatus & STATMODE) {
649 while(ToRecv) {
650 if(tp->t_state & TS_TBLOCK) {
651 break;
652 }
653 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
654 ch = CharNStat & 0xff;
655
656 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
657 ch |= TTY_FE;
658 else if (CharNStat & STMPARITYH)
659 ch |= TTY_PE;
660 else if (CharNStat & STMRCVROVRH)
661 rp->rp_overflows++;
662
663 ttyld_rint(tp, ch);
664 ToRecv--;
665 }
666/*
667 After emtying FIFO in status mode, turn off status mode
668*/
669
670 if(sGetRxCnt(cp) == 0) {
671 sDisRxStatusMode(cp);
672 }
673 } else {
674 /*
675 * Avoid the grotesquely inefficient lineswitch routine
676 * (ttyinput) in "raw" mode. It usually takes about 450
677 * instructions (that's without canonical processing or echo!).
678 * slinput is reasonably fast (usually 40 instructions plus
679 * call overhead).
680 */
681 ToRecv = sGetRxCnt(cp);
682 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
683 if ( ToRecv > RXFIFO_SIZE ) {
684 ToRecv = RXFIFO_SIZE;
685 }
686 wRecv = ToRecv >> 1;
687 if ( wRecv ) {
688 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
689 }
690 if ( ToRecv & 1 ) {
691 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
692 }
693 tk_nin += ToRecv;
694 tk_rawcc += ToRecv;
695 tp->t_rawcc += ToRecv;
696 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
697 ttwakeup(tp);
698 } else {
699 while (ToRecv) {
700 if(tp->t_state & TS_TBLOCK) {
701 break;
702 }
703 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
704 spl = spltty();
705 ttyld_rint(tp, ch);
706 splx(spl);
707 ToRecv--;
708 }
709 }
710 }
711}
712
713static void rp_handle_port(struct rp_port *rp)
714{
715 CHANNEL_t *cp;
716 struct tty *tp;
717 unsigned int IntMask, ChanStatus;
718
719 if(!rp)
720 return;
721
722 cp = &rp->rp_channel;
723 tp = rp->rp_tty;
724 IntMask = sGetChanIntID(cp);
725 IntMask = IntMask & rp->rp_intmask;
726 ChanStatus = sGetChanStatus(cp);
727 if(IntMask & RXF_TRIG)
728 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
729 rp_do_receive(rp, tp, cp, ChanStatus);
730 }
731 if(IntMask & DELTA_CD) {
732 if(ChanStatus & CD_ACT) {
733 if(!(tp->t_state & TS_CARR_ON) ) {
734 (void)ttyld_modem(tp, 1);
735 }
736 } else {
737 if((tp->t_state & TS_CARR_ON)) {
738 (void)ttyld_modem(tp, 0);
739 if(ttyld_modem(tp, 0) == 0) {
740 rphardclose(rp);
741 }
742 }
743 }
744 }
745/* oldcts = rp->rp_cts;
746 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
747 if(oldcts != rp->rp_cts) {
748 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
749 }
750*/
751}
752
753static void rp_do_poll(void *not_used)
754{
755 CONTROLLER_t *ctl;
756 struct rp_port *rp;
757 struct tty *tp;
758 int unit, aiop, ch, line, count;
759 unsigned char CtlMask, AiopMask;
760
761 for(unit = 0; unit < rp_ndevs; unit++) {
762 rp = rp_addr(unit);
763 ctl = rp->rp_ctlp;
764 CtlMask = ctl->ctlmask(ctl);
765 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
766 if(CtlMask & 1) {
767 AiopMask = sGetAiopIntStatus(ctl, aiop);
768 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
769 if(AiopMask & 1) {
770 line = (unit << 5) | (aiop << 3) | ch;
771 rp = rp_table(line);
772 rp_handle_port(rp);
773 }
774 }
775 }
776 }
777
778 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
779 line++, rp++) {
780 tp = rp->rp_tty;
781 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
782 count = sGetTxCnt(&rp->rp_channel);
783 if(count == 0)
784 tp->t_state &= ~(TS_BUSY);
785 if(!(tp->t_state & TS_TTSTOP) &&
786 (count <= rp->rp_restart)) {
787 ttyld_start(tp);
788 }
789 }
790 }
791 }
792 if(rp_num_ports_open)
793 rp_callout_handle = timeout(rp_do_poll,
794 (void *)NULL, POLL_INTERVAL);
795}
796
797int
798rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
799{
800 int oldspl, unit;
801 int num_chan;
802 int aiop, chan, port;
803 int ChanStatus, line, i, count;
804 int retval;
805 struct rp_port *rp;
806 struct cdev **dev_nodes;
807
808 unit = device_get_unit(ctlp->dev);
809
810 printf("RocketPort%d (Version %s) %d ports.\n", unit,
811 RocketPortVersion, num_ports);
812 rp_num_ports[unit] = num_ports;
813 callout_handle_init(&rp_callout_handle);
814
815 ctlp->rp = rp = (struct rp_port *)
816 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
817 if (rp == NULL) {
818 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
819 retval = ENOMEM;
820 goto nogo;
821 }
822
823 count = unit * 32; /* board times max ports per card SG */
824 for(i=count;i < (count + rp_num_ports[unit]);i++)
825 minor_to_unit[i] = unit;
826
827 bzero(rp, sizeof(struct rp_port) * num_ports);
828 oldspl = spltty();
829 rp_addr(unit) = rp;
830 splx(oldspl);
831
832 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
833 if(ctlp->dev_nodes == NULL) {
834 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
835 retval = ENOMEM;
836 goto nogo;
837 }
838
839 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
840 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
841 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
842 i <= 9 ? '0' + i : 'a' + i - 10);
843 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
844 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
845 i <= 9 ? '0' + i : 'a' + i - 10);
846 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
847 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
848 i <= 9 ? '0' + i : 'a' + i - 10);
849 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
850 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
851 i <= 9 ? '0' + i : 'a' + i - 10);
852 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
853 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
854 i <= 9 ? '0' + i : 'a' + i - 10);
855 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
856 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
857 i <= 9 ? '0' + i : 'a' + i - 10);
858 }
859
860 port = 0;
861 for(aiop=0; aiop < num_aiops; aiop++) {
862 num_chan = sGetAiopNumChan(ctlp, aiop);
863 for(chan=0; chan < num_chan; chan++, port++, rp++) {
864 rp->rp_tty = ttymalloc(NULL);
865 rp->rp_port = port;
866 rp->rp_ctlp = ctlp;
867 rp->rp_unit = unit;
868 rp->rp_chan = chan;
869 rp->rp_aiop = aiop;
870
871 rp->rp_tty->t_line = 0;
872 /* tty->t_termios = deftermios;
873 */
874 rp->it_in.c_iflag = 0;
875 rp->it_in.c_oflag = 0;
876 rp->it_in.c_cflag = TTYDEF_CFLAG;
877 rp->it_in.c_lflag = 0;
878 termioschars(&rp->it_in);
879 /* termioschars(&tty->t_termios);
880 */
881 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
882 rp->it_out = rp->it_in;
883
884 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
885 DELTA_CD | DELTA_CTS | DELTA_DSR;
886#if notdef
887 ChanStatus = sGetChanStatus(&rp->rp_channel);
888#endif /* notdef */
889 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
890 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
891 unit, aiop, chan);
892 retval = ENXIO;
893 goto nogo;
894 }
895 ChanStatus = sGetChanStatus(&rp->rp_channel);
896 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
897 line = (unit << 5) | (aiop << 3) | chan;
898 rp_table(line) = rp;
899 }
900 }
901
902 rp_ndevs++;
903 return (0);
904
905nogo:
906 rp_releaseresource(ctlp);
907
908 return (retval);
909}
910
911void
912rp_releaseresource(CONTROLLER_t *ctlp)
913{
914 int i, s, unit;
915 struct rp_port *rp;
916
917
918 unit = device_get_unit(ctlp->dev);
919 if (rp_addr(unit) != NULL) {
920 for (i = 0; i < rp_num_ports[unit]; i++) {
921 rp = rp_addr(unit) + i;
922 s = ttyrel(rp->rp_tty);
923 if (s) {
924 printf("Detaching with active tty (%d refs)!\n", s);
925 }
926 }
927 }
928
929 if (ctlp->rp != NULL) {
930 s = spltty();
931 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
932 if (p_rp_addr[i] == ctlp->rp)
933 p_rp_addr[i] = NULL;
934 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
935 if (p_rp_table[i] == ctlp->rp)
936 p_rp_table[i] = NULL;
937 splx(s);
938 free(ctlp->rp, M_DEVBUF);
939 ctlp->rp = NULL;
940 }
941 if (ctlp->dev != NULL) {
942 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
943 destroy_dev(ctlp->dev_nodes[i]);
944 free(ctlp->dev_nodes, M_DEVBUF);
945 ctlp->dev = NULL;
946 }
947}
948
949void
950rp_untimeout(void)
951{
952 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
953}
954static int
955rpopen(dev, flag, mode, td)
956 struct cdev *dev;
957 int flag, mode;
958 struct thread *td;
959{
960 struct rp_port *rp;
961 int unit, port, mynor, umynor, flags; /* SG */
962 struct tty *tp;
963 int oldspl, error;
964 unsigned int IntMask, ChanStatus;
965
966
967 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
968 port = (minor(dev) & 0x1f); /* SG */
969 mynor = (port + umynor); /* SG */
970 unit = minor_to_unit[mynor];
971 if (rp_addr(unit) == NULL)
972 return (ENXIO);
973 if(IS_CONTROL(dev))
974 return(0);
975 rp = rp_addr(unit) + port;
976/* rp->rp_tty = &rp_tty[rp->rp_port];
977*/
978 tp = rp->rp_tty;
979 dev->si_tty = tp;
980
981 oldspl = spltty();
982
983open_top:
984 while(rp->state & ~SET_DTR) {
985 error = tsleep(&tp->t_dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
986 if(error != 0)
987 goto out;
988 }
989
990 if(tp->t_state & TS_ISOPEN) {
991 if(IS_CALLOUT(dev)) {
992 if(!rp->active_out) {
993 error = EBUSY;
994 goto out;
995 }
996 } else {
997 if(rp->active_out) {
998 if(flag & O_NONBLOCK) {
999 error = EBUSY;
1000 goto out;
1001 }
1002 error = tsleep(&rp->active_out,
1003 TTIPRI | PCATCH, "rpbi", 0);
1004 if(error != 0)
1005 goto out;
1006 goto open_top;
1007 }
1008 }
1009 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1010 splx(oldspl);
1011 error = EBUSY;
1012 goto out2;
1013 }
1014 }
1015 else {
1016 tp->t_dev = dev;
1017 tp->t_param = rpparam;
1018 tp->t_oproc = rpstart;
1019 tp->t_stop = rpstop;
1020 tp->t_line = 0;
1021 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1022 tp->t_ififosize = 512;
1023 tp->t_ispeedwat = (speed_t)-1;
1024 tp->t_ospeedwat = (speed_t)-1;
1025 flags = 0;
1026 flags |= SET_RTS;
1027 flags |= SET_DTR;
1028 rp->rp_channel.TxControl[3] =
1029 ((rp->rp_channel.TxControl[3]
1030 & ~(SET_RTS | SET_DTR)) | flags);
1031 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1032 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1033 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1034 sDisRxStatusMode(&rp->rp_channel);
1035 sFlushRxFIFO(&rp->rp_channel);
1036 sFlushTxFIFO(&rp->rp_channel);
1037
1038 sEnInterrupts(&rp->rp_channel,
1039 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1040 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1041
1042 sDisRxStatusMode(&rp->rp_channel);
1043 sClrTxXOFF(&rp->rp_channel);
1044
1045/* sDisRTSFlowCtl(&rp->rp_channel);
1046 sDisCTSFlowCtl(&rp->rp_channel);
1047*/
1048 sDisTxSoftFlowCtl(&rp->rp_channel);
1049
1050 sStartRxProcessor(&rp->rp_channel);
1051
1052 sEnRxFIFO(&rp->rp_channel);
1053 sEnTransmit(&rp->rp_channel);
1054
1055/* sSetDTR(&rp->rp_channel);
1056 sSetRTS(&rp->rp_channel);
1057*/
1058
1059 ++rp->wopeners;
1060 error = rpparam(tp, &tp->t_termios);
1061 --rp->wopeners;
1062 if(error != 0) {
1063 splx(oldspl);
1064 return(error);
1065 }
1066
1067 rp_num_ports_open++;
1068
1069 IntMask = sGetChanIntID(&rp->rp_channel);
1070 IntMask = IntMask & rp->rp_intmask;
1071 ChanStatus = sGetChanStatus(&rp->rp_channel);
1072 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1073 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1074 (void)ttyld_modem(tp, 1);
1075 }
1076 }
1077
1078 if(rp_num_ports_open == 1)
1079 rp_callout_handle = timeout(rp_do_poll,
1080 (void *)NULL, POLL_INTERVAL);
1081 }
1082
1083 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1084 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1085 ++rp->wopeners;
1086 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1087 "rpdcd", 0);
1088 --rp->wopeners;
1089 if(error != 0)
1090 goto out;
1091 goto open_top;
1092 }
1093 error = ttyld_open(tp, dev);
1094
1095 ttyldoptim(tp);
1096 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1097 rp->active_out = TRUE;
1098
1099/* if(rp_num_ports_open == 1)
1100 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1101*/
1102out:
1103 splx(oldspl);
1104 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1105 rphardclose(rp);
1106 }
1107out2:
1108 if (error == 0)
1109 device_busy(rp->rp_ctlp->dev);
1110 return(error);
1111}
1112
1113static int
1114rpclose(dev, flag, mode, td)
1115 struct cdev *dev;
1116 int flag, mode;
1117 struct thread *td;
1118{
1119 int oldspl, unit, mynor, umynor, port; /* SG */
1120 struct rp_port *rp;
1121 struct tty *tp;
1122 CHANNEL_t *cp;
1123
1124 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1125 port = (minor(dev) & 0x1f); /* SG */
1126 mynor = (port + umynor); /* SG */
1127 unit = minor_to_unit[mynor]; /* SG */
1128
1129 if(IS_CONTROL(dev))
1130 return(0);
1131 rp = rp_addr(unit) + port;
1132 cp = &rp->rp_channel;
1133 tp = rp->rp_tty;
1134
1135 oldspl = spltty();
1136 ttyld_close(tp, flag);
1137 ttyldoptim(tp);
1138 rphardclose(rp);
1139
1140 tp->t_state &= ~TS_BUSY;
1141 ttyclose(tp);
1141 tty_close(tp);
1142
1143 splx(oldspl);
1144
1145 device_unbusy(rp->rp_ctlp->dev);
1146
1147 return(0);
1148}
1149
1150static void
1151rphardclose(struct rp_port *rp)
1152{
1153 int mynor;
1154 struct tty *tp;
1155 CHANNEL_t *cp;
1156
1157 cp = &rp->rp_channel;
1158 tp = rp->rp_tty;
1159 mynor = MINOR_MAGIC(tp->t_dev);
1160
1161 sFlushRxFIFO(cp);
1162 sFlushTxFIFO(cp);
1163 sDisTransmit(cp);
1164 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1165 sDisRTSFlowCtl(cp);
1166 sDisCTSFlowCtl(cp);
1167 sDisTxSoftFlowCtl(cp);
1168 sClrTxXOFF(cp);
1169
1170 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1171 sClrDTR(cp);
1172 }
1173 if(IS_CALLOUT(tp->t_dev)) {
1174 sClrDTR(cp);
1175 }
1176 if(tp->t_dtr_wait != 0) {
1177 timeout(rpdtrwakeup, rp, tp->t_dtr_wait);
1178 rp->state |= ~SET_DTR;
1179 }
1180
1181 rp->active_out = FALSE;
1182 wakeup(&rp->active_out);
1183 wakeup(TSA_CARR_ON(tp));
1184}
1185
1186static
1187int
1188rpwrite(dev, uio, flag)
1189 struct cdev *dev;
1190 struct uio *uio;
1191 int flag;
1192{
1193 struct rp_port *rp;
1194 struct tty *tp;
1195 int unit, mynor, port, umynor, error = 0; /* SG */
1196
1197 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1198 port = (minor(dev) & 0x1f); /* SG */
1199 mynor = (port + umynor); /* SG */
1200 unit = minor_to_unit[mynor]; /* SG */
1201
1202 if(IS_CONTROL(dev))
1203 return(ENODEV);
1204 rp = rp_addr(unit) + port;
1205 tp = rp->rp_tty;
1206 while(rp->rp_disable_writes) {
1207 rp->rp_waiting = 1;
1208 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1209 if (error)
1210 return(error);
1211 }
1212
1213 error = ttyld_write(tp, uio, flag);
1214 return error;
1215}
1216
1217static void
1218rpdtrwakeup(void *chan)
1219{
1220 struct rp_port *rp;
1221
1222 rp = (struct rp_port *)chan;
1223 rp->state &= SET_DTR;
1224 wakeup(&rp->rp_tty->t_dtr_wait);
1225}
1226
1227static int
1228rpioctl(dev, cmd, data, flag, td)
1229 struct cdev *dev;
1230 u_long cmd;
1231 caddr_t data;
1232 int flag;
1233 struct thread *td;
1234{
1235 struct rp_port *rp;
1236 CHANNEL_t *cp;
1237 struct tty *tp;
1238 int unit, mynor, port, umynor; /* SG */
1239 int oldspl;
1240 int error = 0;
1241 int arg, flags, result, ChanStatus;
1242 struct termios *t;
1243#ifndef BURN_BRIDGES
1244#if defined(COMPAT_43)
1245 u_long oldcmd;
1246 struct termios term;
1247#endif
1248#endif
1249
1250 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1251 port = (minor(dev) & 0x1f); /* SG */
1252 mynor = (port + umynor); /* SG */
1253 unit = minor_to_unit[mynor];
1254 rp = rp_addr(unit) + port;
1255
1256 if(IS_CONTROL(dev)) {
1257 struct termios *ct;
1258
1259 switch (IS_CONTROL(dev)) {
1260 case CONTROL_INIT_STATE:
1261 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1262 break;
1263 case CONTROL_LOCK_STATE:
1264 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1265 break;
1266 default:
1267 return(ENODEV); /* /dev/nodev */
1268 }
1269 switch (cmd) {
1270 case TIOCSETA:
1271 error = suser(td);
1272 if(error != 0)
1273 return(error);
1274 *ct = *(struct termios *)data;
1275 return(0);
1276 case TIOCGETA:
1277 *(struct termios *)data = *ct;
1278 return(0);
1279 case TIOCGETD:
1280 *(int *)data = TTYDISC;
1281 return(0);
1282 case TIOCGWINSZ:
1283 bzero(data, sizeof(struct winsize));
1284 return(0);
1285 default:
1286 return(ENOTTY);
1287 }
1288 }
1289
1290 tp = rp->rp_tty;
1291 cp = &rp->rp_channel;
1292
1293#ifndef BURN_BRIDGES
1294#if defined(COMPAT_43)
1295 term = tp->t_termios;
1296 oldcmd = cmd;
1297 error = ttsetcompat(tp, &cmd, data, &term);
1298 if(error != 0)
1299 return(error);
1300 if(cmd != oldcmd) {
1301 data = (caddr_t)&term;
1302 }
1303#endif
1304#endif
1305 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1306 int cc;
1307 struct termios *dt = (struct termios *)data;
1308 struct termios *lt = IS_CALLOUT(dev)
1309 ? &rp->lt_out : &rp->lt_in;
1310
1311 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1312 | (dt->c_iflag & ~lt->c_iflag);
1313 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1314 | (dt->c_oflag & ~lt->c_oflag);
1315 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1316 | (dt->c_cflag & ~lt->c_cflag);
1317 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1318 | (dt->c_lflag & ~lt->c_lflag);
1319 for(cc = 0; cc < NCCS; ++cc)
1320 if(lt->c_cc[cc] != 0)
1321 dt->c_cc[cc] = tp->t_cc[cc];
1322 if(lt->c_ispeed != 0)
1323 dt->c_ispeed = tp->t_ispeed;
1324 if(lt->c_ospeed != 0)
1325 dt->c_ospeed = tp->t_ospeed;
1326 }
1327
1328 t = &tp->t_termios;
1329
1330 error = ttyioctl(dev, cmd, data, flag, td);
1331 ttyldoptim(tp);
1332 if(error != ENOTTY)
1333 return(error);
1334 oldspl = spltty();
1335
1336 flags = rp->rp_channel.TxControl[3];
1337
1338 switch(cmd) {
1339 case TIOCSBRK:
1340 sSendBreak(&rp->rp_channel);
1341 break;
1342
1343 case TIOCCBRK:
1344 sClrBreak(&rp->rp_channel);
1345 break;
1346
1347 case TIOCSDTR:
1348 sSetDTR(&rp->rp_channel);
1349 sSetRTS(&rp->rp_channel);
1350 break;
1351
1352 case TIOCCDTR:
1353 sClrDTR(&rp->rp_channel);
1354 break;
1355
1356 case TIOCMSET:
1357 arg = *(int *) data;
1358 flags = 0;
1359 if(arg & TIOCM_RTS)
1360 flags |= SET_RTS;
1361 if(arg & TIOCM_DTR)
1362 flags |= SET_DTR;
1363 rp->rp_channel.TxControl[3] =
1364 ((rp->rp_channel.TxControl[3]
1365 & ~(SET_RTS | SET_DTR)) | flags);
1366 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1367 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1368 break;
1369 case TIOCMBIS:
1370 arg = *(int *) data;
1371 flags = 0;
1372 if(arg & TIOCM_RTS)
1373 flags |= SET_RTS;
1374 if(arg & TIOCM_DTR)
1375 flags |= SET_DTR;
1376 rp->rp_channel.TxControl[3] |= flags;
1377 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1378 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1379 break;
1380 case TIOCMBIC:
1381 arg = *(int *) data;
1382 flags = 0;
1383 if(arg & TIOCM_RTS)
1384 flags |= SET_RTS;
1385 if(arg & TIOCM_DTR)
1386 flags |= SET_DTR;
1387 rp->rp_channel.TxControl[3] &= ~flags;
1388 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1389 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1390 break;
1391
1392
1393 case TIOCMGET:
1394 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1395 flags = rp->rp_channel.TxControl[3];
1396 result = TIOCM_LE; /* always on while open for some reason */
1397 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1398 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1399 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1400 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1401 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1402
1403 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1404 {
1405 result |= TIOCM_RTS;
1406 }
1407
1408 *(int *)data = result;
1409 break;
1410 default:
1411 splx(oldspl);
1412 return ENOTTY;
1413 }
1414 splx(oldspl);
1415 return(0);
1416}
1417
1418static struct speedtab baud_table[] = {
1419 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1420 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1421 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1422 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1423 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1424 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1425 {B57600, BRD57600}, {B76800, BRD76800},
1426 {B115200, BRD115200}, {B230400, BRD230400},
1427 {-1, -1}
1428};
1429
1430static int
1431rpparam(tp, t)
1432 struct tty *tp;
1433 struct termios *t;
1434{
1435 struct rp_port *rp;
1436 CHANNEL_t *cp;
1437 int unit, mynor, port, umynor; /* SG */
1438 int oldspl, cflag, iflag, oflag, lflag;
1439 int ospeed;
1440#ifdef RPCLOCAL
1441 int devshift;
1442#endif
1443
1444
1445 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1446 port = (minor(tp->t_dev) & 0x1f); /* SG */
1447 mynor = (port + umynor); /* SG */
1448
1449 unit = minor_to_unit[mynor];
1450 rp = rp_addr(unit) + port;
1451 cp = &rp->rp_channel;
1452 oldspl = spltty();
1453
1454 cflag = t->c_cflag;
1455#ifdef RPCLOCAL
1456 devshift = umynor / 32;
1457 devshift = 1 << devshift;
1458 if ( devshift & RPCLOCAL ) {
1459 cflag |= CLOCAL;
1460 }
1461#endif
1462 iflag = t->c_iflag;
1463 oflag = t->c_oflag;
1464 lflag = t->c_lflag;
1465
1466 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1467 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1468 return(EINVAL);
1469
1470 tp->t_ispeed = t->c_ispeed;
1471 tp->t_ospeed = t->c_ospeed;
1472 tp->t_cflag = cflag;
1473 tp->t_iflag = iflag;
1474 tp->t_oflag = oflag;
1475 tp->t_lflag = lflag;
1476
1477 if(t->c_ospeed == 0) {
1478 sClrDTR(cp);
1479 return(0);
1480 }
1481 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1482
1483 /* Set baud rate ----- we only pay attention to ispeed */
1484 sSetDTR(cp);
1485 sSetRTS(cp);
1486 sSetBaud(cp, ospeed);
1487
1488 if(cflag & CSTOPB) {
1489 sSetStop2(cp);
1490 } else {
1491 sSetStop1(cp);
1492 }
1493
1494 if(cflag & PARENB) {
1495 sEnParity(cp);
1496 if(cflag & PARODD) {
1497 sSetOddParity(cp);
1498 } else {
1499 sSetEvenParity(cp);
1500 }
1501 }
1502 else {
1503 sDisParity(cp);
1504 }
1505 if((cflag & CSIZE) == CS8) {
1506 sSetData8(cp);
1507 rp->rp_imask = 0xFF;
1508 } else {
1509 sSetData7(cp);
1510 rp->rp_imask = 0x7F;
1511 }
1512
1513 if(iflag & ISTRIP) {
1514 rp->rp_imask &= 0x7F;
1515 }
1516
1517 if(cflag & CLOCAL) {
1518 rp->rp_intmask &= ~DELTA_CD;
1519 } else {
1520 rp->rp_intmask |= DELTA_CD;
1521 }
1522
1523 /* Put flow control stuff here */
1524
1525 if(cflag & CCTS_OFLOW) {
1526 sEnCTSFlowCtl(cp);
1527 } else {
1528 sDisCTSFlowCtl(cp);
1529 }
1530
1531 if(cflag & CRTS_IFLOW) {
1532 rp->rp_rts_iflow = 1;
1533 } else {
1534 rp->rp_rts_iflow = 0;
1535 }
1536
1537 if(cflag & CRTS_IFLOW) {
1538 sEnRTSFlowCtl(cp);
1539 } else {
1540 sDisRTSFlowCtl(cp);
1541 }
1542 ttyldoptim(tp);
1543
1544 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1545 tp->t_state |= TS_CARR_ON;
1546 wakeup(TSA_CARR_ON(tp));
1547 }
1548
1549/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1550 flags = rp->rp_channel.TxControl[3];
1551 if(flags & SET_DTR)
1552 else
1553 if(flags & SET_RTS)
1554 else
1555*/
1556 splx(oldspl);
1557
1558 return(0);
1559}
1560
1561static void
1562rpstart(tp)
1563 struct tty *tp;
1564{
1565 struct rp_port *rp;
1566 CHANNEL_t *cp;
1567 struct clist *qp;
1568 int unit, mynor, port, umynor; /* SG */
1569 char flags;
1570 int spl, xmit_fifo_room;
1571 int count, wcount;
1572
1573
1574 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1575 port = (minor(tp->t_dev) & 0x1f); /* SG */
1576 mynor = (port + umynor); /* SG */
1577 unit = minor_to_unit[mynor];
1578 rp = rp_addr(unit) + port;
1579 cp = &rp->rp_channel;
1580 flags = rp->rp_channel.TxControl[3];
1581 spl = spltty();
1582
1583 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1584 ttwwakeup(tp);
1585 splx(spl);
1586 return;
1587 }
1588 if(rp->rp_xmit_stopped) {
1589 sEnTransmit(cp);
1590 rp->rp_xmit_stopped = 0;
1591 }
1592 count = sGetTxCnt(cp);
1593
1594 if(tp->t_outq.c_cc == 0) {
1595 if((tp->t_state & TS_BUSY) && (count == 0)) {
1596 tp->t_state &= ~TS_BUSY;
1597 }
1598 ttwwakeup(tp);
1599 splx(spl);
1600 return;
1601 }
1602 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1603 qp = &tp->t_outq;
1604 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1605 tp->t_state |= TS_BUSY;
1606 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1607 wcount = count >> 1;
1608 if ( wcount ) {
1609 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1610 }
1611 if ( count & 1 ) {
1612 rp_writech1(cp, sGetTxRxDataIO(cp),
1613 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1614 }
1615 }
1616 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1617
1618 ttwwakeup(tp);
1619 splx(spl);
1620}
1621
1622static
1623void
1624rpstop(tp, flag)
1625 register struct tty *tp;
1626 int flag;
1627{
1628 struct rp_port *rp;
1629 CHANNEL_t *cp;
1630 int unit, mynor, port, umynor; /* SG */
1631 int spl;
1632
1633 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1634 port = (minor(tp->t_dev) & 0x1f); /* SG */
1635 mynor = (port + umynor); /* SG */
1636 unit = minor_to_unit[mynor];
1637 rp = rp_addr(unit) + port;
1638 cp = &rp->rp_channel;
1639
1640 spl = spltty();
1641
1642 if(tp->t_state & TS_BUSY) {
1643 if((tp->t_state&TS_TTSTOP) == 0) {
1644 sFlushTxFIFO(cp);
1645 } else {
1646 if(rp->rp_xmit_stopped == 0) {
1647 sDisTransmit(cp);
1648 rp->rp_xmit_stopped = 1;
1649 }
1650 }
1651 }
1652 splx(spl);
1653 rpstart(tp);
1654}
1142
1143 splx(oldspl);
1144
1145 device_unbusy(rp->rp_ctlp->dev);
1146
1147 return(0);
1148}
1149
1150static void
1151rphardclose(struct rp_port *rp)
1152{
1153 int mynor;
1154 struct tty *tp;
1155 CHANNEL_t *cp;
1156
1157 cp = &rp->rp_channel;
1158 tp = rp->rp_tty;
1159 mynor = MINOR_MAGIC(tp->t_dev);
1160
1161 sFlushRxFIFO(cp);
1162 sFlushTxFIFO(cp);
1163 sDisTransmit(cp);
1164 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1165 sDisRTSFlowCtl(cp);
1166 sDisCTSFlowCtl(cp);
1167 sDisTxSoftFlowCtl(cp);
1168 sClrTxXOFF(cp);
1169
1170 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1171 sClrDTR(cp);
1172 }
1173 if(IS_CALLOUT(tp->t_dev)) {
1174 sClrDTR(cp);
1175 }
1176 if(tp->t_dtr_wait != 0) {
1177 timeout(rpdtrwakeup, rp, tp->t_dtr_wait);
1178 rp->state |= ~SET_DTR;
1179 }
1180
1181 rp->active_out = FALSE;
1182 wakeup(&rp->active_out);
1183 wakeup(TSA_CARR_ON(tp));
1184}
1185
1186static
1187int
1188rpwrite(dev, uio, flag)
1189 struct cdev *dev;
1190 struct uio *uio;
1191 int flag;
1192{
1193 struct rp_port *rp;
1194 struct tty *tp;
1195 int unit, mynor, port, umynor, error = 0; /* SG */
1196
1197 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1198 port = (minor(dev) & 0x1f); /* SG */
1199 mynor = (port + umynor); /* SG */
1200 unit = minor_to_unit[mynor]; /* SG */
1201
1202 if(IS_CONTROL(dev))
1203 return(ENODEV);
1204 rp = rp_addr(unit) + port;
1205 tp = rp->rp_tty;
1206 while(rp->rp_disable_writes) {
1207 rp->rp_waiting = 1;
1208 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1209 if (error)
1210 return(error);
1211 }
1212
1213 error = ttyld_write(tp, uio, flag);
1214 return error;
1215}
1216
1217static void
1218rpdtrwakeup(void *chan)
1219{
1220 struct rp_port *rp;
1221
1222 rp = (struct rp_port *)chan;
1223 rp->state &= SET_DTR;
1224 wakeup(&rp->rp_tty->t_dtr_wait);
1225}
1226
1227static int
1228rpioctl(dev, cmd, data, flag, td)
1229 struct cdev *dev;
1230 u_long cmd;
1231 caddr_t data;
1232 int flag;
1233 struct thread *td;
1234{
1235 struct rp_port *rp;
1236 CHANNEL_t *cp;
1237 struct tty *tp;
1238 int unit, mynor, port, umynor; /* SG */
1239 int oldspl;
1240 int error = 0;
1241 int arg, flags, result, ChanStatus;
1242 struct termios *t;
1243#ifndef BURN_BRIDGES
1244#if defined(COMPAT_43)
1245 u_long oldcmd;
1246 struct termios term;
1247#endif
1248#endif
1249
1250 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1251 port = (minor(dev) & 0x1f); /* SG */
1252 mynor = (port + umynor); /* SG */
1253 unit = minor_to_unit[mynor];
1254 rp = rp_addr(unit) + port;
1255
1256 if(IS_CONTROL(dev)) {
1257 struct termios *ct;
1258
1259 switch (IS_CONTROL(dev)) {
1260 case CONTROL_INIT_STATE:
1261 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1262 break;
1263 case CONTROL_LOCK_STATE:
1264 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1265 break;
1266 default:
1267 return(ENODEV); /* /dev/nodev */
1268 }
1269 switch (cmd) {
1270 case TIOCSETA:
1271 error = suser(td);
1272 if(error != 0)
1273 return(error);
1274 *ct = *(struct termios *)data;
1275 return(0);
1276 case TIOCGETA:
1277 *(struct termios *)data = *ct;
1278 return(0);
1279 case TIOCGETD:
1280 *(int *)data = TTYDISC;
1281 return(0);
1282 case TIOCGWINSZ:
1283 bzero(data, sizeof(struct winsize));
1284 return(0);
1285 default:
1286 return(ENOTTY);
1287 }
1288 }
1289
1290 tp = rp->rp_tty;
1291 cp = &rp->rp_channel;
1292
1293#ifndef BURN_BRIDGES
1294#if defined(COMPAT_43)
1295 term = tp->t_termios;
1296 oldcmd = cmd;
1297 error = ttsetcompat(tp, &cmd, data, &term);
1298 if(error != 0)
1299 return(error);
1300 if(cmd != oldcmd) {
1301 data = (caddr_t)&term;
1302 }
1303#endif
1304#endif
1305 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1306 int cc;
1307 struct termios *dt = (struct termios *)data;
1308 struct termios *lt = IS_CALLOUT(dev)
1309 ? &rp->lt_out : &rp->lt_in;
1310
1311 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1312 | (dt->c_iflag & ~lt->c_iflag);
1313 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1314 | (dt->c_oflag & ~lt->c_oflag);
1315 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1316 | (dt->c_cflag & ~lt->c_cflag);
1317 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1318 | (dt->c_lflag & ~lt->c_lflag);
1319 for(cc = 0; cc < NCCS; ++cc)
1320 if(lt->c_cc[cc] != 0)
1321 dt->c_cc[cc] = tp->t_cc[cc];
1322 if(lt->c_ispeed != 0)
1323 dt->c_ispeed = tp->t_ispeed;
1324 if(lt->c_ospeed != 0)
1325 dt->c_ospeed = tp->t_ospeed;
1326 }
1327
1328 t = &tp->t_termios;
1329
1330 error = ttyioctl(dev, cmd, data, flag, td);
1331 ttyldoptim(tp);
1332 if(error != ENOTTY)
1333 return(error);
1334 oldspl = spltty();
1335
1336 flags = rp->rp_channel.TxControl[3];
1337
1338 switch(cmd) {
1339 case TIOCSBRK:
1340 sSendBreak(&rp->rp_channel);
1341 break;
1342
1343 case TIOCCBRK:
1344 sClrBreak(&rp->rp_channel);
1345 break;
1346
1347 case TIOCSDTR:
1348 sSetDTR(&rp->rp_channel);
1349 sSetRTS(&rp->rp_channel);
1350 break;
1351
1352 case TIOCCDTR:
1353 sClrDTR(&rp->rp_channel);
1354 break;
1355
1356 case TIOCMSET:
1357 arg = *(int *) data;
1358 flags = 0;
1359 if(arg & TIOCM_RTS)
1360 flags |= SET_RTS;
1361 if(arg & TIOCM_DTR)
1362 flags |= SET_DTR;
1363 rp->rp_channel.TxControl[3] =
1364 ((rp->rp_channel.TxControl[3]
1365 & ~(SET_RTS | SET_DTR)) | flags);
1366 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1367 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1368 break;
1369 case TIOCMBIS:
1370 arg = *(int *) data;
1371 flags = 0;
1372 if(arg & TIOCM_RTS)
1373 flags |= SET_RTS;
1374 if(arg & TIOCM_DTR)
1375 flags |= SET_DTR;
1376 rp->rp_channel.TxControl[3] |= flags;
1377 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1378 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1379 break;
1380 case TIOCMBIC:
1381 arg = *(int *) data;
1382 flags = 0;
1383 if(arg & TIOCM_RTS)
1384 flags |= SET_RTS;
1385 if(arg & TIOCM_DTR)
1386 flags |= SET_DTR;
1387 rp->rp_channel.TxControl[3] &= ~flags;
1388 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1389 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1390 break;
1391
1392
1393 case TIOCMGET:
1394 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1395 flags = rp->rp_channel.TxControl[3];
1396 result = TIOCM_LE; /* always on while open for some reason */
1397 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1398 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1399 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1400 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1401 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1402
1403 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1404 {
1405 result |= TIOCM_RTS;
1406 }
1407
1408 *(int *)data = result;
1409 break;
1410 default:
1411 splx(oldspl);
1412 return ENOTTY;
1413 }
1414 splx(oldspl);
1415 return(0);
1416}
1417
1418static struct speedtab baud_table[] = {
1419 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1420 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1421 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1422 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1423 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1424 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1425 {B57600, BRD57600}, {B76800, BRD76800},
1426 {B115200, BRD115200}, {B230400, BRD230400},
1427 {-1, -1}
1428};
1429
1430static int
1431rpparam(tp, t)
1432 struct tty *tp;
1433 struct termios *t;
1434{
1435 struct rp_port *rp;
1436 CHANNEL_t *cp;
1437 int unit, mynor, port, umynor; /* SG */
1438 int oldspl, cflag, iflag, oflag, lflag;
1439 int ospeed;
1440#ifdef RPCLOCAL
1441 int devshift;
1442#endif
1443
1444
1445 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1446 port = (minor(tp->t_dev) & 0x1f); /* SG */
1447 mynor = (port + umynor); /* SG */
1448
1449 unit = minor_to_unit[mynor];
1450 rp = rp_addr(unit) + port;
1451 cp = &rp->rp_channel;
1452 oldspl = spltty();
1453
1454 cflag = t->c_cflag;
1455#ifdef RPCLOCAL
1456 devshift = umynor / 32;
1457 devshift = 1 << devshift;
1458 if ( devshift & RPCLOCAL ) {
1459 cflag |= CLOCAL;
1460 }
1461#endif
1462 iflag = t->c_iflag;
1463 oflag = t->c_oflag;
1464 lflag = t->c_lflag;
1465
1466 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1467 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1468 return(EINVAL);
1469
1470 tp->t_ispeed = t->c_ispeed;
1471 tp->t_ospeed = t->c_ospeed;
1472 tp->t_cflag = cflag;
1473 tp->t_iflag = iflag;
1474 tp->t_oflag = oflag;
1475 tp->t_lflag = lflag;
1476
1477 if(t->c_ospeed == 0) {
1478 sClrDTR(cp);
1479 return(0);
1480 }
1481 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1482
1483 /* Set baud rate ----- we only pay attention to ispeed */
1484 sSetDTR(cp);
1485 sSetRTS(cp);
1486 sSetBaud(cp, ospeed);
1487
1488 if(cflag & CSTOPB) {
1489 sSetStop2(cp);
1490 } else {
1491 sSetStop1(cp);
1492 }
1493
1494 if(cflag & PARENB) {
1495 sEnParity(cp);
1496 if(cflag & PARODD) {
1497 sSetOddParity(cp);
1498 } else {
1499 sSetEvenParity(cp);
1500 }
1501 }
1502 else {
1503 sDisParity(cp);
1504 }
1505 if((cflag & CSIZE) == CS8) {
1506 sSetData8(cp);
1507 rp->rp_imask = 0xFF;
1508 } else {
1509 sSetData7(cp);
1510 rp->rp_imask = 0x7F;
1511 }
1512
1513 if(iflag & ISTRIP) {
1514 rp->rp_imask &= 0x7F;
1515 }
1516
1517 if(cflag & CLOCAL) {
1518 rp->rp_intmask &= ~DELTA_CD;
1519 } else {
1520 rp->rp_intmask |= DELTA_CD;
1521 }
1522
1523 /* Put flow control stuff here */
1524
1525 if(cflag & CCTS_OFLOW) {
1526 sEnCTSFlowCtl(cp);
1527 } else {
1528 sDisCTSFlowCtl(cp);
1529 }
1530
1531 if(cflag & CRTS_IFLOW) {
1532 rp->rp_rts_iflow = 1;
1533 } else {
1534 rp->rp_rts_iflow = 0;
1535 }
1536
1537 if(cflag & CRTS_IFLOW) {
1538 sEnRTSFlowCtl(cp);
1539 } else {
1540 sDisRTSFlowCtl(cp);
1541 }
1542 ttyldoptim(tp);
1543
1544 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1545 tp->t_state |= TS_CARR_ON;
1546 wakeup(TSA_CARR_ON(tp));
1547 }
1548
1549/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1550 flags = rp->rp_channel.TxControl[3];
1551 if(flags & SET_DTR)
1552 else
1553 if(flags & SET_RTS)
1554 else
1555*/
1556 splx(oldspl);
1557
1558 return(0);
1559}
1560
1561static void
1562rpstart(tp)
1563 struct tty *tp;
1564{
1565 struct rp_port *rp;
1566 CHANNEL_t *cp;
1567 struct clist *qp;
1568 int unit, mynor, port, umynor; /* SG */
1569 char flags;
1570 int spl, xmit_fifo_room;
1571 int count, wcount;
1572
1573
1574 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1575 port = (minor(tp->t_dev) & 0x1f); /* SG */
1576 mynor = (port + umynor); /* SG */
1577 unit = minor_to_unit[mynor];
1578 rp = rp_addr(unit) + port;
1579 cp = &rp->rp_channel;
1580 flags = rp->rp_channel.TxControl[3];
1581 spl = spltty();
1582
1583 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1584 ttwwakeup(tp);
1585 splx(spl);
1586 return;
1587 }
1588 if(rp->rp_xmit_stopped) {
1589 sEnTransmit(cp);
1590 rp->rp_xmit_stopped = 0;
1591 }
1592 count = sGetTxCnt(cp);
1593
1594 if(tp->t_outq.c_cc == 0) {
1595 if((tp->t_state & TS_BUSY) && (count == 0)) {
1596 tp->t_state &= ~TS_BUSY;
1597 }
1598 ttwwakeup(tp);
1599 splx(spl);
1600 return;
1601 }
1602 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1603 qp = &tp->t_outq;
1604 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1605 tp->t_state |= TS_BUSY;
1606 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1607 wcount = count >> 1;
1608 if ( wcount ) {
1609 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1610 }
1611 if ( count & 1 ) {
1612 rp_writech1(cp, sGetTxRxDataIO(cp),
1613 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1614 }
1615 }
1616 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1617
1618 ttwwakeup(tp);
1619 splx(spl);
1620}
1621
1622static
1623void
1624rpstop(tp, flag)
1625 register struct tty *tp;
1626 int flag;
1627{
1628 struct rp_port *rp;
1629 CHANNEL_t *cp;
1630 int unit, mynor, port, umynor; /* SG */
1631 int spl;
1632
1633 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1634 port = (minor(tp->t_dev) & 0x1f); /* SG */
1635 mynor = (port + umynor); /* SG */
1636 unit = minor_to_unit[mynor];
1637 rp = rp_addr(unit) + port;
1638 cp = &rp->rp_channel;
1639
1640 spl = spltty();
1641
1642 if(tp->t_state & TS_BUSY) {
1643 if((tp->t_state&TS_TTSTOP) == 0) {
1644 sFlushTxFIFO(cp);
1645 } else {
1646 if(rp->rp_xmit_stopped == 0) {
1647 sDisTransmit(cp);
1648 rp->rp_xmit_stopped = 1;
1649 }
1650 }
1651 }
1652 splx(spl);
1653 rpstart(tp);
1654}