Deleted Added
full compact
rp.c (130096) rp.c (130344)
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 130096 2004-06-04 21:55:55Z phk $");
35__FBSDID("$FreeBSD: head/sys/dev/rp/rp.c 130344 2004-06-11 11:16:26Z 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;
568
569static d_open_t rpopen;
570static d_close_t rpclose;
571static d_write_t rpwrite;
572static d_ioctl_t rpioctl;
573
574struct cdevsw rp_cdevsw = {
575 .d_version = D_VERSION,
576 .d_open = rpopen,
577 .d_close = rpclose,
578 .d_write = rpwrite,
579 .d_ioctl = rpioctl,
580 .d_name = "rp",
581 .d_flags = D_TTY | D_NEEDGIANT,
582};
583
584static int rp_num_ports_open = 0;
585static int rp_ndevs = 0;
586static int minor_to_unit[128];
587
588static int rp_num_ports[4]; /* Number of ports on each controller */
589
590#define POLL_INTERVAL 1
591
592#define CALLOUT_MASK 0x80
593#define CONTROL_MASK 0x60
594#define CONTROL_INIT_STATE 0x20
595#define CONTROL_LOCK_STATE 0x40
596#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
597#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
598#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
599#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
600#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
601
602#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
603#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
604#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
605
606static struct rp_port *p_rp_addr[4];
607static struct rp_port *p_rp_table[MAX_RP_PORTS];
608#define rp_addr(unit) (p_rp_addr[unit])
609#define rp_table(port) (p_rp_table[port])
610
611/*
612 * The top-level routines begin here
613 */
614
615static int rpparam(struct tty *, struct termios *);
616static void rpstart(struct tty *);
617static void rpstop(struct tty *, int);
618static void rphardclose (struct rp_port *);
619
620static void rp_do_receive(struct rp_port *rp, struct tty *tp,
621 CHANNEL_t *cp, unsigned int ChanStatus)
622{
623 int spl;
624 unsigned int CharNStat;
625 int ToRecv, wRecv, ch, ttynocopy;
626
627 ToRecv = sGetRxCnt(cp);
628 if(ToRecv == 0)
629 return;
630
631/* If status indicates there are errored characters in the
632 FIFO, then enter status mode (a word in FIFO holds
633 characters and status)
634*/
635
636 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
637 if(!(ChanStatus & STATMODE)) {
638 ChanStatus |= STATMODE;
639 sEnRxStatusMode(cp);
640 }
641 }
642/*
643 if we previously entered status mode then read down the
644 FIFO one word at a time, pulling apart the character and
645 the status. Update error counters depending on status.
646*/
647 if(ChanStatus & STATMODE) {
648 while(ToRecv) {
649 if(tp->t_state & TS_TBLOCK) {
650 break;
651 }
652 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
653 ch = CharNStat & 0xff;
654
655 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
656 ch |= TTY_FE;
657 else if (CharNStat & STMPARITYH)
658 ch |= TTY_PE;
659 else if (CharNStat & STMRCVROVRH)
660 rp->rp_overflows++;
661
662 ttyld_rint(tp, ch);
663 ToRecv--;
664 }
665/*
666 After emtying FIFO in status mode, turn off status mode
667*/
668
669 if(sGetRxCnt(cp) == 0) {
670 sDisRxStatusMode(cp);
671 }
672 } else {
673 /*
674 * Avoid the grotesquely inefficient lineswitch routine
675 * (ttyinput) in "raw" mode. It usually takes about 450
676 * instructions (that's without canonical processing or echo!).
677 * slinput is reasonably fast (usually 40 instructions plus
678 * call overhead).
679 */
680 ToRecv = sGetRxCnt(cp);
681 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
682 if ( ToRecv > RXFIFO_SIZE ) {
683 ToRecv = RXFIFO_SIZE;
684 }
685 wRecv = ToRecv >> 1;
686 if ( wRecv ) {
687 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
688 }
689 if ( ToRecv & 1 ) {
690 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
691 }
692 tk_nin += ToRecv;
693 tk_rawcc += ToRecv;
694 tp->t_rawcc += ToRecv;
695 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
696 ttwakeup(tp);
697 } else {
698 while (ToRecv) {
699 if(tp->t_state & TS_TBLOCK) {
700 break;
701 }
702 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
703 spl = spltty();
704 ttyld_rint(tp, ch);
705 splx(spl);
706 ToRecv--;
707 }
708 }
709 }
710}
711
712static void rp_handle_port(struct rp_port *rp)
713{
714 CHANNEL_t *cp;
715 struct tty *tp;
716 unsigned int IntMask, ChanStatus;
717
718 if(!rp)
719 return;
720
721 cp = &rp->rp_channel;
722 tp = rp->rp_tty;
723 IntMask = sGetChanIntID(cp);
724 IntMask = IntMask & rp->rp_intmask;
725 ChanStatus = sGetChanStatus(cp);
726 if(IntMask & RXF_TRIG)
727 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
728 rp_do_receive(rp, tp, cp, ChanStatus);
729 }
730 if(IntMask & DELTA_CD) {
731 if(ChanStatus & CD_ACT) {
732 if(!(tp->t_state & TS_CARR_ON) ) {
733 (void)ttyld_modem(tp, 1);
734 }
735 } else {
736 if((tp->t_state & TS_CARR_ON)) {
737 (void)ttyld_modem(tp, 0);
738 if(ttyld_modem(tp, 0) == 0) {
739 rphardclose(rp);
740 }
741 }
742 }
743 }
744/* oldcts = rp->rp_cts;
745 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
746 if(oldcts != rp->rp_cts) {
747 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
748 }
749*/
750}
751
752static void rp_do_poll(void *not_used)
753{
754 CONTROLLER_t *ctl;
755 struct rp_port *rp;
756 struct tty *tp;
757 int unit, aiop, ch, line, count;
758 unsigned char CtlMask, AiopMask;
759
760 for(unit = 0; unit < rp_ndevs; unit++) {
761 rp = rp_addr(unit);
762 ctl = rp->rp_ctlp;
763 CtlMask = ctl->ctlmask(ctl);
764 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
765 if(CtlMask & 1) {
766 AiopMask = sGetAiopIntStatus(ctl, aiop);
767 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
768 if(AiopMask & 1) {
769 line = (unit << 5) | (aiop << 3) | ch;
770 rp = rp_table(line);
771 rp_handle_port(rp);
772 }
773 }
774 }
775 }
776
777 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
778 line++, rp++) {
779 tp = rp->rp_tty;
780 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
781 count = sGetTxCnt(&rp->rp_channel);
782 if(count == 0)
783 tp->t_state &= ~(TS_BUSY);
784 if(!(tp->t_state & TS_TTSTOP) &&
785 (count <= rp->rp_restart)) {
786 ttyld_start(tp);
787 }
788 }
789 }
790 }
791 if(rp_num_ports_open)
792 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
793}
794
795int
796rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
797{
798 int oldspl, unit;
799 int num_chan;
800 int aiop, chan, port;
801 int ChanStatus, line, i, count;
802 int retval;
803 struct rp_port *rp;
804 struct tty *tty;
805 dev_t *dev_nodes;
806
807 unit = device_get_unit(ctlp->dev);
808
809 printf("RocketPort%d (Version %s) %d ports.\n", unit,
810 RocketPortVersion, num_ports);
811 rp_num_ports[unit] = num_ports;
812
813 ctlp->rp = rp = (struct rp_port *)
814 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
815 if (rp == NULL) {
816 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
817 retval = ENOMEM;
818 goto nogo;
819 }
820
821 count = unit * 32; /* board times max ports per card SG */
822 for(i=count;i < (count + rp_num_ports[unit]);i++)
823 minor_to_unit[i] = unit;
824
825 bzero(rp, sizeof(struct rp_port) * num_ports);
826 ctlp->tty = tty = (struct tty *)
827 malloc(sizeof(struct tty) * num_ports, M_TTYS,
828 M_NOWAIT | M_ZERO);
829 if(tty == NULL) {
830 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
831 retval = ENOMEM;
832 goto nogo;
833 }
834
835 oldspl = spltty();
836 rp_addr(unit) = rp;
837 splx(oldspl);
838
839 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
840 if(ctlp->dev_nodes == NULL) {
841 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
842 retval = ENOMEM;
843 goto nogo;
844 }
845
846 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
847 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
848 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
849 i <= 9 ? '0' + i : 'a' + i - 10);
850 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
851 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
852 i <= 9 ? '0' + i : 'a' + i - 10);
853 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
854 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
855 i <= 9 ? '0' + i : 'a' + i - 10);
856 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
857 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
858 i <= 9 ? '0' + i : 'a' + i - 10);
859 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
860 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
861 i <= 9 ? '0' + i : 'a' + i - 10);
862 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
863 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
864 i <= 9 ? '0' + i : 'a' + i - 10);
865 }
866
867 port = 0;
868 for(aiop=0; aiop < num_aiops; aiop++) {
869 num_chan = sGetAiopNumChan(ctlp, aiop);
870 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
871 rp->rp_tty = tty;
872 rp->rp_port = port;
873 rp->rp_ctlp = ctlp;
874 rp->rp_unit = unit;
875 rp->rp_chan = chan;
876 rp->rp_aiop = aiop;
877
878 tty->t_line = 0;
879 /* tty->t_termios = deftermios;
880 */
881 rp->dtr_wait = 3 * hz;
882 rp->it_in.c_iflag = 0;
883 rp->it_in.c_oflag = 0;
884 rp->it_in.c_cflag = TTYDEF_CFLAG;
885 rp->it_in.c_lflag = 0;
886 termioschars(&rp->it_in);
887 /* termioschars(&tty->t_termios);
888 */
889 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
890 rp->it_out = rp->it_in;
891
892 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
893 DELTA_CD | DELTA_CTS | DELTA_DSR;
894#if notdef
895 ChanStatus = sGetChanStatus(&rp->rp_channel);
896#endif /* notdef */
897 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
898 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
899 unit, aiop, chan);
900 retval = ENXIO;
901 goto nogo;
902 }
903 ChanStatus = sGetChanStatus(&rp->rp_channel);
904 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
905 line = (unit << 5) | (aiop << 3) | chan;
906 rp_table(line) = rp;
907 }
908 }
909
910 rp_ndevs++;
911 return (0);
912
913nogo:
914 rp_releaseresource(ctlp);
915
916 return (retval);
917}
918
919void
920rp_releaseresource(CONTROLLER_t *ctlp)
921{
922 int i, s, unit;
923
924 unit = device_get_unit(ctlp->dev);
925
926 if (ctlp->rp != NULL) {
927 s = spltty();
928 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
929 if (p_rp_addr[i] == ctlp->rp)
930 p_rp_addr[i] = NULL;
931 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
932 if (p_rp_table[i] == ctlp->rp)
933 p_rp_table[i] = NULL;
934 splx(s);
935 free(ctlp->rp, M_DEVBUF);
936 ctlp->rp = NULL;
937 }
938 if (ctlp->tty != NULL) {
939 free(ctlp->tty, M_DEVBUF);
940 ctlp->tty = NULL;
941 }
942 if (ctlp->dev != NULL) {
943 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
944 destroy_dev(ctlp->dev_nodes[i]);
945 free(ctlp->dev_nodes, M_DEVBUF);
946 ctlp->dev = NULL;
947 }
948}
949
950static int
951rpopen(dev, flag, mode, td)
952 dev_t dev;
953 int flag, mode;
954 struct thread *td;
955{
956 struct rp_port *rp;
957 int unit, port, mynor, umynor, flags; /* SG */
958 struct tty *tp;
959 int oldspl, error;
960 unsigned int IntMask, ChanStatus;
961
962
963 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
964 port = (minor(dev) & 0x1f); /* SG */
965 mynor = (port + umynor); /* SG */
966 unit = minor_to_unit[mynor];
967 if (rp_addr(unit) == NULL)
968 return (ENXIO);
969 if(IS_CONTROL(dev))
970 return(0);
971 rp = rp_addr(unit) + port;
972/* rp->rp_tty = &rp_tty[rp->rp_port];
973*/
974 tp = rp->rp_tty;
975 dev->si_tty = tp;
976
977 oldspl = spltty();
978
979open_top:
980 while(rp->state & ~SET_DTR) {
981 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
982 if(error != 0)
983 goto out;
984 }
985
986 if(tp->t_state & TS_ISOPEN) {
987 if(IS_CALLOUT(dev)) {
988 if(!rp->active_out) {
989 error = EBUSY;
990 goto out;
991 }
992 } else {
993 if(rp->active_out) {
994 if(flag & O_NONBLOCK) {
995 error = EBUSY;
996 goto out;
997 }
998 error = tsleep(&rp->active_out,
999 TTIPRI | PCATCH, "rpbi", 0);
1000 if(error != 0)
1001 goto out;
1002 goto open_top;
1003 }
1004 }
1005 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1006 splx(oldspl);
1007 error = EBUSY;
1008 goto out2;
1009 }
1010 }
1011 else {
1012 tp->t_dev = dev;
1013 tp->t_param = rpparam;
1014 tp->t_oproc = rpstart;
1015 tp->t_stop = rpstop;
1016 tp->t_line = 0;
1017 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1018 tp->t_ififosize = 512;
1019 tp->t_ispeedwat = (speed_t)-1;
1020 tp->t_ospeedwat = (speed_t)-1;
1021 flags = 0;
1022 flags |= SET_RTS;
1023 flags |= SET_DTR;
1024 rp->rp_channel.TxControl[3] =
1025 ((rp->rp_channel.TxControl[3]
1026 & ~(SET_RTS | SET_DTR)) | flags);
1027 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1028 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1029 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1030 sDisRxStatusMode(&rp->rp_channel);
1031 sFlushRxFIFO(&rp->rp_channel);
1032 sFlushTxFIFO(&rp->rp_channel);
1033
1034 sEnInterrupts(&rp->rp_channel,
1035 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1036 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1037
1038 sDisRxStatusMode(&rp->rp_channel);
1039 sClrTxXOFF(&rp->rp_channel);
1040
1041/* sDisRTSFlowCtl(&rp->rp_channel);
1042 sDisCTSFlowCtl(&rp->rp_channel);
1043*/
1044 sDisTxSoftFlowCtl(&rp->rp_channel);
1045
1046 sStartRxProcessor(&rp->rp_channel);
1047
1048 sEnRxFIFO(&rp->rp_channel);
1049 sEnTransmit(&rp->rp_channel);
1050
1051/* sSetDTR(&rp->rp_channel);
1052 sSetRTS(&rp->rp_channel);
1053*/
1054
1055 ++rp->wopeners;
1056 error = rpparam(tp, &tp->t_termios);
1057 --rp->wopeners;
1058 if(error != 0) {
1059 splx(oldspl);
1060 return(error);
1061 }
1062
1063 rp_num_ports_open++;
1064
1065 IntMask = sGetChanIntID(&rp->rp_channel);
1066 IntMask = IntMask & rp->rp_intmask;
1067 ChanStatus = sGetChanStatus(&rp->rp_channel);
1068 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1069 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1070 (void)ttyld_modem(tp, 1);
1071 }
1072 }
1073
1074 if(rp_num_ports_open == 1)
1075 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1076
1077 }
1078
1079 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1080 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1081 ++rp->wopeners;
1082 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1083 "rpdcd", 0);
1084 --rp->wopeners;
1085 if(error != 0)
1086 goto out;
1087 goto open_top;
1088 }
1089 error = ttyld_open(tp, dev);
1090
1091 ttyldoptim(tp);
1092 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1093 rp->active_out = TRUE;
1094
1095/* if(rp_num_ports_open == 1)
1096 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1097*/
1098out:
1099 splx(oldspl);
1100 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1101 rphardclose(rp);
1102 }
1103out2:
1104 if (error == 0)
1105 device_busy(rp->rp_ctlp->dev);
1106 return(error);
1107}
1108
1109static int
1110rpclose(dev, flag, mode, td)
1111 dev_t dev;
1112 int flag, mode;
1113 struct thread *td;
1114{
1115 int oldspl, unit, mynor, umynor, port; /* SG */
1116 struct rp_port *rp;
1117 struct tty *tp;
1118 CHANNEL_t *cp;
1119
1120 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1121 port = (minor(dev) & 0x1f); /* SG */
1122 mynor = (port + umynor); /* SG */
1123 unit = minor_to_unit[mynor]; /* SG */
1124
1125 if(IS_CONTROL(dev))
1126 return(0);
1127 rp = rp_addr(unit) + port;
1128 cp = &rp->rp_channel;
1129 tp = rp->rp_tty;
1130
1131 oldspl = spltty();
1132 ttyld_close(tp, flag);
1133 ttyldoptim(tp);
1134 rphardclose(rp);
1135
1136 tp->t_state &= ~TS_BUSY;
1137 ttyclose(tp);
1138
1139 splx(oldspl);
1140
1141 device_unbusy(rp->rp_ctlp->dev);
1142
1143 return(0);
1144}
1145
1146static void
1147rphardclose(struct rp_port *rp)
1148{
1149 int mynor;
1150 struct tty *tp;
1151 CHANNEL_t *cp;
1152
1153 cp = &rp->rp_channel;
1154 tp = rp->rp_tty;
1155 mynor = MINOR_MAGIC(tp->t_dev);
1156
1157 sFlushRxFIFO(cp);
1158 sFlushTxFIFO(cp);
1159 sDisTransmit(cp);
1160 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1161 sDisRTSFlowCtl(cp);
1162 sDisCTSFlowCtl(cp);
1163 sDisTxSoftFlowCtl(cp);
1164 sClrTxXOFF(cp);
1165
1166 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1167 sClrDTR(cp);
1168 }
1169 if(IS_CALLOUT(tp->t_dev)) {
1170 sClrDTR(cp);
1171 }
1172 if(rp->dtr_wait != 0) {
1173 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1174 rp->state |= ~SET_DTR;
1175 }
1176
1177 rp->active_out = FALSE;
1178 wakeup(&rp->active_out);
1179 wakeup(TSA_CARR_ON(tp));
1180}
1181
1182static
1183int
1184rpwrite(dev, uio, flag)
1185 dev_t dev;
1186 struct uio *uio;
1187 int flag;
1188{
1189 struct rp_port *rp;
1190 struct tty *tp;
1191 int unit, mynor, port, umynor, error = 0; /* SG */
1192
1193 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1194 port = (minor(dev) & 0x1f); /* SG */
1195 mynor = (port + umynor); /* SG */
1196 unit = minor_to_unit[mynor]; /* SG */
1197
1198 if(IS_CONTROL(dev))
1199 return(ENODEV);
1200 rp = rp_addr(unit) + port;
1201 tp = rp->rp_tty;
1202 while(rp->rp_disable_writes) {
1203 rp->rp_waiting = 1;
1204 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1205 if (error)
1206 return(error);
1207 }
1208
1209 error = ttyld_write(tp, uio, flag);
1210 return error;
1211}
1212
1213static void
1214rpdtrwakeup(void *chan)
1215{
1216 struct rp_port *rp;
1217
1218 rp = (struct rp_port *)chan;
1219 rp->state &= SET_DTR;
1220 wakeup(&rp->dtr_wait);
1221}
1222
1223static int
1224rpioctl(dev, cmd, data, flag, td)
1225 dev_t dev;
1226 u_long cmd;
1227 caddr_t data;
1228 int flag;
1229 struct thread *td;
1230{
1231 struct rp_port *rp;
1232 CHANNEL_t *cp;
1233 struct tty *tp;
1234 int unit, mynor, port, umynor; /* SG */
1235 int oldspl;
1236 int error = 0;
1237 int arg, flags, result, ChanStatus;
1238 struct termios *t;
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;
568
569static d_open_t rpopen;
570static d_close_t rpclose;
571static d_write_t rpwrite;
572static d_ioctl_t rpioctl;
573
574struct cdevsw rp_cdevsw = {
575 .d_version = D_VERSION,
576 .d_open = rpopen,
577 .d_close = rpclose,
578 .d_write = rpwrite,
579 .d_ioctl = rpioctl,
580 .d_name = "rp",
581 .d_flags = D_TTY | D_NEEDGIANT,
582};
583
584static int rp_num_ports_open = 0;
585static int rp_ndevs = 0;
586static int minor_to_unit[128];
587
588static int rp_num_ports[4]; /* Number of ports on each controller */
589
590#define POLL_INTERVAL 1
591
592#define CALLOUT_MASK 0x80
593#define CONTROL_MASK 0x60
594#define CONTROL_INIT_STATE 0x20
595#define CONTROL_LOCK_STATE 0x40
596#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
597#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
598#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
599#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
600#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
601
602#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
603#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
604#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
605
606static struct rp_port *p_rp_addr[4];
607static struct rp_port *p_rp_table[MAX_RP_PORTS];
608#define rp_addr(unit) (p_rp_addr[unit])
609#define rp_table(port) (p_rp_table[port])
610
611/*
612 * The top-level routines begin here
613 */
614
615static int rpparam(struct tty *, struct termios *);
616static void rpstart(struct tty *);
617static void rpstop(struct tty *, int);
618static void rphardclose (struct rp_port *);
619
620static void rp_do_receive(struct rp_port *rp, struct tty *tp,
621 CHANNEL_t *cp, unsigned int ChanStatus)
622{
623 int spl;
624 unsigned int CharNStat;
625 int ToRecv, wRecv, ch, ttynocopy;
626
627 ToRecv = sGetRxCnt(cp);
628 if(ToRecv == 0)
629 return;
630
631/* If status indicates there are errored characters in the
632 FIFO, then enter status mode (a word in FIFO holds
633 characters and status)
634*/
635
636 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
637 if(!(ChanStatus & STATMODE)) {
638 ChanStatus |= STATMODE;
639 sEnRxStatusMode(cp);
640 }
641 }
642/*
643 if we previously entered status mode then read down the
644 FIFO one word at a time, pulling apart the character and
645 the status. Update error counters depending on status.
646*/
647 if(ChanStatus & STATMODE) {
648 while(ToRecv) {
649 if(tp->t_state & TS_TBLOCK) {
650 break;
651 }
652 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
653 ch = CharNStat & 0xff;
654
655 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
656 ch |= TTY_FE;
657 else if (CharNStat & STMPARITYH)
658 ch |= TTY_PE;
659 else if (CharNStat & STMRCVROVRH)
660 rp->rp_overflows++;
661
662 ttyld_rint(tp, ch);
663 ToRecv--;
664 }
665/*
666 After emtying FIFO in status mode, turn off status mode
667*/
668
669 if(sGetRxCnt(cp) == 0) {
670 sDisRxStatusMode(cp);
671 }
672 } else {
673 /*
674 * Avoid the grotesquely inefficient lineswitch routine
675 * (ttyinput) in "raw" mode. It usually takes about 450
676 * instructions (that's without canonical processing or echo!).
677 * slinput is reasonably fast (usually 40 instructions plus
678 * call overhead).
679 */
680 ToRecv = sGetRxCnt(cp);
681 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
682 if ( ToRecv > RXFIFO_SIZE ) {
683 ToRecv = RXFIFO_SIZE;
684 }
685 wRecv = ToRecv >> 1;
686 if ( wRecv ) {
687 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv);
688 }
689 if ( ToRecv & 1 ) {
690 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
691 }
692 tk_nin += ToRecv;
693 tk_rawcc += ToRecv;
694 tp->t_rawcc += ToRecv;
695 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq);
696 ttwakeup(tp);
697 } else {
698 while (ToRecv) {
699 if(tp->t_state & TS_TBLOCK) {
700 break;
701 }
702 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
703 spl = spltty();
704 ttyld_rint(tp, ch);
705 splx(spl);
706 ToRecv--;
707 }
708 }
709 }
710}
711
712static void rp_handle_port(struct rp_port *rp)
713{
714 CHANNEL_t *cp;
715 struct tty *tp;
716 unsigned int IntMask, ChanStatus;
717
718 if(!rp)
719 return;
720
721 cp = &rp->rp_channel;
722 tp = rp->rp_tty;
723 IntMask = sGetChanIntID(cp);
724 IntMask = IntMask & rp->rp_intmask;
725 ChanStatus = sGetChanStatus(cp);
726 if(IntMask & RXF_TRIG)
727 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
728 rp_do_receive(rp, tp, cp, ChanStatus);
729 }
730 if(IntMask & DELTA_CD) {
731 if(ChanStatus & CD_ACT) {
732 if(!(tp->t_state & TS_CARR_ON) ) {
733 (void)ttyld_modem(tp, 1);
734 }
735 } else {
736 if((tp->t_state & TS_CARR_ON)) {
737 (void)ttyld_modem(tp, 0);
738 if(ttyld_modem(tp, 0) == 0) {
739 rphardclose(rp);
740 }
741 }
742 }
743 }
744/* oldcts = rp->rp_cts;
745 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
746 if(oldcts != rp->rp_cts) {
747 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
748 }
749*/
750}
751
752static void rp_do_poll(void *not_used)
753{
754 CONTROLLER_t *ctl;
755 struct rp_port *rp;
756 struct tty *tp;
757 int unit, aiop, ch, line, count;
758 unsigned char CtlMask, AiopMask;
759
760 for(unit = 0; unit < rp_ndevs; unit++) {
761 rp = rp_addr(unit);
762 ctl = rp->rp_ctlp;
763 CtlMask = ctl->ctlmask(ctl);
764 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
765 if(CtlMask & 1) {
766 AiopMask = sGetAiopIntStatus(ctl, aiop);
767 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
768 if(AiopMask & 1) {
769 line = (unit << 5) | (aiop << 3) | ch;
770 rp = rp_table(line);
771 rp_handle_port(rp);
772 }
773 }
774 }
775 }
776
777 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
778 line++, rp++) {
779 tp = rp->rp_tty;
780 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
781 count = sGetTxCnt(&rp->rp_channel);
782 if(count == 0)
783 tp->t_state &= ~(TS_BUSY);
784 if(!(tp->t_state & TS_TTSTOP) &&
785 (count <= rp->rp_restart)) {
786 ttyld_start(tp);
787 }
788 }
789 }
790 }
791 if(rp_num_ports_open)
792 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
793}
794
795int
796rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
797{
798 int oldspl, unit;
799 int num_chan;
800 int aiop, chan, port;
801 int ChanStatus, line, i, count;
802 int retval;
803 struct rp_port *rp;
804 struct tty *tty;
805 dev_t *dev_nodes;
806
807 unit = device_get_unit(ctlp->dev);
808
809 printf("RocketPort%d (Version %s) %d ports.\n", unit,
810 RocketPortVersion, num_ports);
811 rp_num_ports[unit] = num_ports;
812
813 ctlp->rp = rp = (struct rp_port *)
814 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
815 if (rp == NULL) {
816 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
817 retval = ENOMEM;
818 goto nogo;
819 }
820
821 count = unit * 32; /* board times max ports per card SG */
822 for(i=count;i < (count + rp_num_ports[unit]);i++)
823 minor_to_unit[i] = unit;
824
825 bzero(rp, sizeof(struct rp_port) * num_ports);
826 ctlp->tty = tty = (struct tty *)
827 malloc(sizeof(struct tty) * num_ports, M_TTYS,
828 M_NOWAIT | M_ZERO);
829 if(tty == NULL) {
830 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n");
831 retval = ENOMEM;
832 goto nogo;
833 }
834
835 oldspl = spltty();
836 rp_addr(unit) = rp;
837 splx(oldspl);
838
839 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO);
840 if(ctlp->dev_nodes == NULL) {
841 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n");
842 retval = ENOMEM;
843 goto nogo;
844 }
845
846 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
847 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i,
848 UID_ROOT, GID_WHEEL, 0666, "ttyR%c",
849 i <= 9 ? '0' + i : 'a' + i - 10);
850 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
851 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c",
852 i <= 9 ? '0' + i : 'a' + i - 10);
853 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
854 UID_ROOT, GID_WHEEL, 0666, "ttylR%c",
855 i <= 9 ? '0' + i : 'a' + i - 10);
856 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
857 UID_ROOT, GID_WHEEL, 0666, "cuaR%c",
858 i <= 9 ? '0' + i : 'a' + i - 10);
859 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
860 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c",
861 i <= 9 ? '0' + i : 'a' + i - 10);
862 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
863 UID_ROOT, GID_WHEEL, 0666, "cualR%c",
864 i <= 9 ? '0' + i : 'a' + i - 10);
865 }
866
867 port = 0;
868 for(aiop=0; aiop < num_aiops; aiop++) {
869 num_chan = sGetAiopNumChan(ctlp, aiop);
870 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
871 rp->rp_tty = tty;
872 rp->rp_port = port;
873 rp->rp_ctlp = ctlp;
874 rp->rp_unit = unit;
875 rp->rp_chan = chan;
876 rp->rp_aiop = aiop;
877
878 tty->t_line = 0;
879 /* tty->t_termios = deftermios;
880 */
881 rp->dtr_wait = 3 * hz;
882 rp->it_in.c_iflag = 0;
883 rp->it_in.c_oflag = 0;
884 rp->it_in.c_cflag = TTYDEF_CFLAG;
885 rp->it_in.c_lflag = 0;
886 termioschars(&rp->it_in);
887 /* termioschars(&tty->t_termios);
888 */
889 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
890 rp->it_out = rp->it_in;
891
892 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
893 DELTA_CD | DELTA_CTS | DELTA_DSR;
894#if notdef
895 ChanStatus = sGetChanStatus(&rp->rp_channel);
896#endif /* notdef */
897 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
898 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
899 unit, aiop, chan);
900 retval = ENXIO;
901 goto nogo;
902 }
903 ChanStatus = sGetChanStatus(&rp->rp_channel);
904 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
905 line = (unit << 5) | (aiop << 3) | chan;
906 rp_table(line) = rp;
907 }
908 }
909
910 rp_ndevs++;
911 return (0);
912
913nogo:
914 rp_releaseresource(ctlp);
915
916 return (retval);
917}
918
919void
920rp_releaseresource(CONTROLLER_t *ctlp)
921{
922 int i, s, unit;
923
924 unit = device_get_unit(ctlp->dev);
925
926 if (ctlp->rp != NULL) {
927 s = spltty();
928 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
929 if (p_rp_addr[i] == ctlp->rp)
930 p_rp_addr[i] = NULL;
931 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
932 if (p_rp_table[i] == ctlp->rp)
933 p_rp_table[i] = NULL;
934 splx(s);
935 free(ctlp->rp, M_DEVBUF);
936 ctlp->rp = NULL;
937 }
938 if (ctlp->tty != NULL) {
939 free(ctlp->tty, M_DEVBUF);
940 ctlp->tty = NULL;
941 }
942 if (ctlp->dev != NULL) {
943 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
944 destroy_dev(ctlp->dev_nodes[i]);
945 free(ctlp->dev_nodes, M_DEVBUF);
946 ctlp->dev = NULL;
947 }
948}
949
950static int
951rpopen(dev, flag, mode, td)
952 dev_t dev;
953 int flag, mode;
954 struct thread *td;
955{
956 struct rp_port *rp;
957 int unit, port, mynor, umynor, flags; /* SG */
958 struct tty *tp;
959 int oldspl, error;
960 unsigned int IntMask, ChanStatus;
961
962
963 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
964 port = (minor(dev) & 0x1f); /* SG */
965 mynor = (port + umynor); /* SG */
966 unit = minor_to_unit[mynor];
967 if (rp_addr(unit) == NULL)
968 return (ENXIO);
969 if(IS_CONTROL(dev))
970 return(0);
971 rp = rp_addr(unit) + port;
972/* rp->rp_tty = &rp_tty[rp->rp_port];
973*/
974 tp = rp->rp_tty;
975 dev->si_tty = tp;
976
977 oldspl = spltty();
978
979open_top:
980 while(rp->state & ~SET_DTR) {
981 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
982 if(error != 0)
983 goto out;
984 }
985
986 if(tp->t_state & TS_ISOPEN) {
987 if(IS_CALLOUT(dev)) {
988 if(!rp->active_out) {
989 error = EBUSY;
990 goto out;
991 }
992 } else {
993 if(rp->active_out) {
994 if(flag & O_NONBLOCK) {
995 error = EBUSY;
996 goto out;
997 }
998 error = tsleep(&rp->active_out,
999 TTIPRI | PCATCH, "rpbi", 0);
1000 if(error != 0)
1001 goto out;
1002 goto open_top;
1003 }
1004 }
1005 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1006 splx(oldspl);
1007 error = EBUSY;
1008 goto out2;
1009 }
1010 }
1011 else {
1012 tp->t_dev = dev;
1013 tp->t_param = rpparam;
1014 tp->t_oproc = rpstart;
1015 tp->t_stop = rpstop;
1016 tp->t_line = 0;
1017 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1018 tp->t_ififosize = 512;
1019 tp->t_ispeedwat = (speed_t)-1;
1020 tp->t_ospeedwat = (speed_t)-1;
1021 flags = 0;
1022 flags |= SET_RTS;
1023 flags |= SET_DTR;
1024 rp->rp_channel.TxControl[3] =
1025 ((rp->rp_channel.TxControl[3]
1026 & ~(SET_RTS | SET_DTR)) | flags);
1027 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1028 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1029 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1030 sDisRxStatusMode(&rp->rp_channel);
1031 sFlushRxFIFO(&rp->rp_channel);
1032 sFlushTxFIFO(&rp->rp_channel);
1033
1034 sEnInterrupts(&rp->rp_channel,
1035 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1036 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1037
1038 sDisRxStatusMode(&rp->rp_channel);
1039 sClrTxXOFF(&rp->rp_channel);
1040
1041/* sDisRTSFlowCtl(&rp->rp_channel);
1042 sDisCTSFlowCtl(&rp->rp_channel);
1043*/
1044 sDisTxSoftFlowCtl(&rp->rp_channel);
1045
1046 sStartRxProcessor(&rp->rp_channel);
1047
1048 sEnRxFIFO(&rp->rp_channel);
1049 sEnTransmit(&rp->rp_channel);
1050
1051/* sSetDTR(&rp->rp_channel);
1052 sSetRTS(&rp->rp_channel);
1053*/
1054
1055 ++rp->wopeners;
1056 error = rpparam(tp, &tp->t_termios);
1057 --rp->wopeners;
1058 if(error != 0) {
1059 splx(oldspl);
1060 return(error);
1061 }
1062
1063 rp_num_ports_open++;
1064
1065 IntMask = sGetChanIntID(&rp->rp_channel);
1066 IntMask = IntMask & rp->rp_intmask;
1067 ChanStatus = sGetChanStatus(&rp->rp_channel);
1068 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1069 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1070 (void)ttyld_modem(tp, 1);
1071 }
1072 }
1073
1074 if(rp_num_ports_open == 1)
1075 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1076
1077 }
1078
1079 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1080 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1081 ++rp->wopeners;
1082 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1083 "rpdcd", 0);
1084 --rp->wopeners;
1085 if(error != 0)
1086 goto out;
1087 goto open_top;
1088 }
1089 error = ttyld_open(tp, dev);
1090
1091 ttyldoptim(tp);
1092 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1093 rp->active_out = TRUE;
1094
1095/* if(rp_num_ports_open == 1)
1096 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1097*/
1098out:
1099 splx(oldspl);
1100 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1101 rphardclose(rp);
1102 }
1103out2:
1104 if (error == 0)
1105 device_busy(rp->rp_ctlp->dev);
1106 return(error);
1107}
1108
1109static int
1110rpclose(dev, flag, mode, td)
1111 dev_t dev;
1112 int flag, mode;
1113 struct thread *td;
1114{
1115 int oldspl, unit, mynor, umynor, port; /* SG */
1116 struct rp_port *rp;
1117 struct tty *tp;
1118 CHANNEL_t *cp;
1119
1120 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1121 port = (minor(dev) & 0x1f); /* SG */
1122 mynor = (port + umynor); /* SG */
1123 unit = minor_to_unit[mynor]; /* SG */
1124
1125 if(IS_CONTROL(dev))
1126 return(0);
1127 rp = rp_addr(unit) + port;
1128 cp = &rp->rp_channel;
1129 tp = rp->rp_tty;
1130
1131 oldspl = spltty();
1132 ttyld_close(tp, flag);
1133 ttyldoptim(tp);
1134 rphardclose(rp);
1135
1136 tp->t_state &= ~TS_BUSY;
1137 ttyclose(tp);
1138
1139 splx(oldspl);
1140
1141 device_unbusy(rp->rp_ctlp->dev);
1142
1143 return(0);
1144}
1145
1146static void
1147rphardclose(struct rp_port *rp)
1148{
1149 int mynor;
1150 struct tty *tp;
1151 CHANNEL_t *cp;
1152
1153 cp = &rp->rp_channel;
1154 tp = rp->rp_tty;
1155 mynor = MINOR_MAGIC(tp->t_dev);
1156
1157 sFlushRxFIFO(cp);
1158 sFlushTxFIFO(cp);
1159 sDisTransmit(cp);
1160 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1161 sDisRTSFlowCtl(cp);
1162 sDisCTSFlowCtl(cp);
1163 sDisTxSoftFlowCtl(cp);
1164 sClrTxXOFF(cp);
1165
1166 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1167 sClrDTR(cp);
1168 }
1169 if(IS_CALLOUT(tp->t_dev)) {
1170 sClrDTR(cp);
1171 }
1172 if(rp->dtr_wait != 0) {
1173 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1174 rp->state |= ~SET_DTR;
1175 }
1176
1177 rp->active_out = FALSE;
1178 wakeup(&rp->active_out);
1179 wakeup(TSA_CARR_ON(tp));
1180}
1181
1182static
1183int
1184rpwrite(dev, uio, flag)
1185 dev_t dev;
1186 struct uio *uio;
1187 int flag;
1188{
1189 struct rp_port *rp;
1190 struct tty *tp;
1191 int unit, mynor, port, umynor, error = 0; /* SG */
1192
1193 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1194 port = (minor(dev) & 0x1f); /* SG */
1195 mynor = (port + umynor); /* SG */
1196 unit = minor_to_unit[mynor]; /* SG */
1197
1198 if(IS_CONTROL(dev))
1199 return(ENODEV);
1200 rp = rp_addr(unit) + port;
1201 tp = rp->rp_tty;
1202 while(rp->rp_disable_writes) {
1203 rp->rp_waiting = 1;
1204 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1205 if (error)
1206 return(error);
1207 }
1208
1209 error = ttyld_write(tp, uio, flag);
1210 return error;
1211}
1212
1213static void
1214rpdtrwakeup(void *chan)
1215{
1216 struct rp_port *rp;
1217
1218 rp = (struct rp_port *)chan;
1219 rp->state &= SET_DTR;
1220 wakeup(&rp->dtr_wait);
1221}
1222
1223static int
1224rpioctl(dev, cmd, data, flag, td)
1225 dev_t dev;
1226 u_long cmd;
1227 caddr_t data;
1228 int flag;
1229 struct thread *td;
1230{
1231 struct rp_port *rp;
1232 CHANNEL_t *cp;
1233 struct tty *tp;
1234 int unit, mynor, port, umynor; /* SG */
1235 int oldspl;
1236 int error = 0;
1237 int arg, flags, result, ChanStatus;
1238 struct termios *t;
1239#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1239#if defined(COMPAT_43)
1240 u_long oldcmd;
1241 struct termios term;
1242#endif
1243
1244 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1245 port = (minor(dev) & 0x1f); /* SG */
1246 mynor = (port + umynor); /* SG */
1247 unit = minor_to_unit[mynor];
1248 rp = rp_addr(unit) + port;
1249
1250 if(IS_CONTROL(dev)) {
1251 struct termios *ct;
1252
1253 switch (IS_CONTROL(dev)) {
1254 case CONTROL_INIT_STATE:
1255 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1256 break;
1257 case CONTROL_LOCK_STATE:
1258 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1259 break;
1260 default:
1261 return(ENODEV); /* /dev/nodev */
1262 }
1263 switch (cmd) {
1264 case TIOCSETA:
1265 error = suser(td);
1266 if(error != 0)
1267 return(error);
1268 *ct = *(struct termios *)data;
1269 return(0);
1270 case TIOCGETA:
1271 *(struct termios *)data = *ct;
1272 return(0);
1273 case TIOCGETD:
1274 *(int *)data = TTYDISC;
1275 return(0);
1276 case TIOCGWINSZ:
1277 bzero(data, sizeof(struct winsize));
1278 return(0);
1279 default:
1280 return(ENOTTY);
1281 }
1282 }
1283
1284 tp = rp->rp_tty;
1285 cp = &rp->rp_channel;
1286
1240 u_long oldcmd;
1241 struct termios term;
1242#endif
1243
1244 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1245 port = (minor(dev) & 0x1f); /* SG */
1246 mynor = (port + umynor); /* SG */
1247 unit = minor_to_unit[mynor];
1248 rp = rp_addr(unit) + port;
1249
1250 if(IS_CONTROL(dev)) {
1251 struct termios *ct;
1252
1253 switch (IS_CONTROL(dev)) {
1254 case CONTROL_INIT_STATE:
1255 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1256 break;
1257 case CONTROL_LOCK_STATE:
1258 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1259 break;
1260 default:
1261 return(ENODEV); /* /dev/nodev */
1262 }
1263 switch (cmd) {
1264 case TIOCSETA:
1265 error = suser(td);
1266 if(error != 0)
1267 return(error);
1268 *ct = *(struct termios *)data;
1269 return(0);
1270 case TIOCGETA:
1271 *(struct termios *)data = *ct;
1272 return(0);
1273 case TIOCGETD:
1274 *(int *)data = TTYDISC;
1275 return(0);
1276 case TIOCGWINSZ:
1277 bzero(data, sizeof(struct winsize));
1278 return(0);
1279 default:
1280 return(ENOTTY);
1281 }
1282 }
1283
1284 tp = rp->rp_tty;
1285 cp = &rp->rp_channel;
1286
1287#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1287#if defined(COMPAT_43)
1288 term = tp->t_termios;
1289 oldcmd = cmd;
1290 error = ttsetcompat(tp, &cmd, data, &term);
1291 if(error != 0)
1292 return(error);
1293 if(cmd != oldcmd) {
1294 data = (caddr_t)&term;
1295 }
1296#endif
1297 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1298 int cc;
1299 struct termios *dt = (struct termios *)data;
1300 struct termios *lt = IS_CALLOUT(dev)
1301 ? &rp->lt_out : &rp->lt_in;
1302
1303 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1304 | (dt->c_iflag & ~lt->c_iflag);
1305 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1306 | (dt->c_oflag & ~lt->c_oflag);
1307 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1308 | (dt->c_cflag & ~lt->c_cflag);
1309 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1310 | (dt->c_lflag & ~lt->c_lflag);
1311 for(cc = 0; cc < NCCS; ++cc)
1312 if(lt->c_cc[cc] != 0)
1313 dt->c_cc[cc] = tp->t_cc[cc];
1314 if(lt->c_ispeed != 0)
1315 dt->c_ispeed = tp->t_ispeed;
1316 if(lt->c_ospeed != 0)
1317 dt->c_ospeed = tp->t_ospeed;
1318 }
1319
1320 t = &tp->t_termios;
1321
1322 error = ttyioctl(dev, cmd, data, flag, td);
1323 ttyldoptim(tp);
1324 if(error != ENOTTY)
1325 return(error);
1326 oldspl = spltty();
1327
1328 flags = rp->rp_channel.TxControl[3];
1329
1330 switch(cmd) {
1331 case TIOCSBRK:
1332 sSendBreak(&rp->rp_channel);
1333 break;
1334
1335 case TIOCCBRK:
1336 sClrBreak(&rp->rp_channel);
1337 break;
1338
1339 case TIOCSDTR:
1340 sSetDTR(&rp->rp_channel);
1341 sSetRTS(&rp->rp_channel);
1342 break;
1343
1344 case TIOCCDTR:
1345 sClrDTR(&rp->rp_channel);
1346 break;
1347
1348 case TIOCMSET:
1349 arg = *(int *) data;
1350 flags = 0;
1351 if(arg & TIOCM_RTS)
1352 flags |= SET_RTS;
1353 if(arg & TIOCM_DTR)
1354 flags |= SET_DTR;
1355 rp->rp_channel.TxControl[3] =
1356 ((rp->rp_channel.TxControl[3]
1357 & ~(SET_RTS | SET_DTR)) | flags);
1358 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1359 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1360 break;
1361 case TIOCMBIS:
1362 arg = *(int *) data;
1363 flags = 0;
1364 if(arg & TIOCM_RTS)
1365 flags |= SET_RTS;
1366 if(arg & TIOCM_DTR)
1367 flags |= SET_DTR;
1368 rp->rp_channel.TxControl[3] |= flags;
1369 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1370 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1371 break;
1372 case TIOCMBIC:
1373 arg = *(int *) data;
1374 flags = 0;
1375 if(arg & TIOCM_RTS)
1376 flags |= SET_RTS;
1377 if(arg & TIOCM_DTR)
1378 flags |= SET_DTR;
1379 rp->rp_channel.TxControl[3] &= ~flags;
1380 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1381 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1382 break;
1383
1384
1385 case TIOCMGET:
1386 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1387 flags = rp->rp_channel.TxControl[3];
1388 result = TIOCM_LE; /* always on while open for some reason */
1389 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1390 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1391 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1392 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1393 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1394
1395 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1396 {
1397 result |= TIOCM_RTS;
1398 }
1399
1400 *(int *)data = result;
1401 break;
1402 case TIOCMSDTRWAIT:
1403 error = suser(td);
1404 if(error != 0) {
1405 splx(oldspl);
1406 return(error);
1407 }
1408 rp->dtr_wait = *(int *)data * hz/100;
1409 break;
1410 case TIOCMGDTRWAIT:
1411 *(int *)data = rp->dtr_wait * 100/hz;
1412 break;
1413 default:
1414 splx(oldspl);
1415 return ENOTTY;
1416 }
1417 splx(oldspl);
1418 return(0);
1419}
1420
1421static struct speedtab baud_table[] = {
1422 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1423 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1424 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1425 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1426 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1427 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1428 {B57600, BRD57600}, {B76800, BRD76800},
1429 {B115200, BRD115200}, {B230400, BRD230400},
1430 {-1, -1}
1431};
1432
1433static int
1434rpparam(tp, t)
1435 struct tty *tp;
1436 struct termios *t;
1437{
1438 struct rp_port *rp;
1439 CHANNEL_t *cp;
1440 int unit, mynor, port, umynor; /* SG */
1441 int oldspl, cflag, iflag, oflag, lflag;
1442 int ospeed;
1443#ifdef RPCLOCAL
1444 int devshift;
1445#endif
1446
1447
1448 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1449 port = (minor(tp->t_dev) & 0x1f); /* SG */
1450 mynor = (port + umynor); /* SG */
1451
1452 unit = minor_to_unit[mynor];
1453 rp = rp_addr(unit) + port;
1454 cp = &rp->rp_channel;
1455 oldspl = spltty();
1456
1457 cflag = t->c_cflag;
1458#ifdef RPCLOCAL
1459 devshift = umynor / 32;
1460 devshift = 1 << devshift;
1461 if ( devshift & RPCLOCAL ) {
1462 cflag |= CLOCAL;
1463 }
1464#endif
1465 iflag = t->c_iflag;
1466 oflag = t->c_oflag;
1467 lflag = t->c_lflag;
1468
1469 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1470 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1471 return(EINVAL);
1472
1473 tp->t_ispeed = t->c_ispeed;
1474 tp->t_ospeed = t->c_ospeed;
1475 tp->t_cflag = cflag;
1476 tp->t_iflag = iflag;
1477 tp->t_oflag = oflag;
1478 tp->t_lflag = lflag;
1479
1480 if(t->c_ospeed == 0) {
1481 sClrDTR(cp);
1482 return(0);
1483 }
1484 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1485
1486 /* Set baud rate ----- we only pay attention to ispeed */
1487 sSetDTR(cp);
1488 sSetRTS(cp);
1489 sSetBaud(cp, ospeed);
1490
1491 if(cflag & CSTOPB) {
1492 sSetStop2(cp);
1493 } else {
1494 sSetStop1(cp);
1495 }
1496
1497 if(cflag & PARENB) {
1498 sEnParity(cp);
1499 if(cflag & PARODD) {
1500 sSetOddParity(cp);
1501 } else {
1502 sSetEvenParity(cp);
1503 }
1504 }
1505 else {
1506 sDisParity(cp);
1507 }
1508 if((cflag & CSIZE) == CS8) {
1509 sSetData8(cp);
1510 rp->rp_imask = 0xFF;
1511 } else {
1512 sSetData7(cp);
1513 rp->rp_imask = 0x7F;
1514 }
1515
1516 if(iflag & ISTRIP) {
1517 rp->rp_imask &= 0x7F;
1518 }
1519
1520 if(cflag & CLOCAL) {
1521 rp->rp_intmask &= ~DELTA_CD;
1522 } else {
1523 rp->rp_intmask |= DELTA_CD;
1524 }
1525
1526 /* Put flow control stuff here */
1527
1528 if(cflag & CCTS_OFLOW) {
1529 sEnCTSFlowCtl(cp);
1530 } else {
1531 sDisCTSFlowCtl(cp);
1532 }
1533
1534 if(cflag & CRTS_IFLOW) {
1535 rp->rp_rts_iflow = 1;
1536 } else {
1537 rp->rp_rts_iflow = 0;
1538 }
1539
1540 if(cflag & CRTS_IFLOW) {
1541 sEnRTSFlowCtl(cp);
1542 } else {
1543 sDisRTSFlowCtl(cp);
1544 }
1545 ttyldoptim(tp);
1546
1547 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1548 tp->t_state |= TS_CARR_ON;
1549 wakeup(TSA_CARR_ON(tp));
1550 }
1551
1552/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1553 flags = rp->rp_channel.TxControl[3];
1554 if(flags & SET_DTR)
1555 else
1556 if(flags & SET_RTS)
1557 else
1558*/
1559 splx(oldspl);
1560
1561 return(0);
1562}
1563
1564static void
1565rpstart(tp)
1566 struct tty *tp;
1567{
1568 struct rp_port *rp;
1569 CHANNEL_t *cp;
1570 struct clist *qp;
1571 int unit, mynor, port, umynor; /* SG */
1572 char flags;
1573 int spl, xmit_fifo_room;
1574 int count, wcount;
1575
1576
1577 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1578 port = (minor(tp->t_dev) & 0x1f); /* SG */
1579 mynor = (port + umynor); /* SG */
1580 unit = minor_to_unit[mynor];
1581 rp = rp_addr(unit) + port;
1582 cp = &rp->rp_channel;
1583 flags = rp->rp_channel.TxControl[3];
1584 spl = spltty();
1585
1586 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1587 ttwwakeup(tp);
1588 splx(spl);
1589 return;
1590 }
1591 if(rp->rp_xmit_stopped) {
1592 sEnTransmit(cp);
1593 rp->rp_xmit_stopped = 0;
1594 }
1595 count = sGetTxCnt(cp);
1596
1597 if(tp->t_outq.c_cc == 0) {
1598 if((tp->t_state & TS_BUSY) && (count == 0)) {
1599 tp->t_state &= ~TS_BUSY;
1600 }
1601 ttwwakeup(tp);
1602 splx(spl);
1603 return;
1604 }
1605 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1606 qp = &tp->t_outq;
1607 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1608 tp->t_state |= TS_BUSY;
1609 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1610 wcount = count >> 1;
1611 if ( wcount ) {
1612 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1613 }
1614 if ( count & 1 ) {
1615 rp_writech1(cp, sGetTxRxDataIO(cp),
1616 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1617 }
1618 }
1619 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1620
1621 ttwwakeup(tp);
1622 splx(spl);
1623}
1624
1625static
1626void
1627rpstop(tp, flag)
1628 register struct tty *tp;
1629 int flag;
1630{
1631 struct rp_port *rp;
1632 CHANNEL_t *cp;
1633 int unit, mynor, port, umynor; /* SG */
1634 int spl;
1635
1636 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1637 port = (minor(tp->t_dev) & 0x1f); /* SG */
1638 mynor = (port + umynor); /* SG */
1639 unit = minor_to_unit[mynor];
1640 rp = rp_addr(unit) + port;
1641 cp = &rp->rp_channel;
1642
1643 spl = spltty();
1644
1645 if(tp->t_state & TS_BUSY) {
1646 if((tp->t_state&TS_TTSTOP) == 0) {
1647 sFlushTxFIFO(cp);
1648 } else {
1649 if(rp->rp_xmit_stopped == 0) {
1650 sDisTransmit(cp);
1651 rp->rp_xmit_stopped = 1;
1652 }
1653 }
1654 }
1655 splx(spl);
1656 rpstart(tp);
1657}
1288 term = tp->t_termios;
1289 oldcmd = cmd;
1290 error = ttsetcompat(tp, &cmd, data, &term);
1291 if(error != 0)
1292 return(error);
1293 if(cmd != oldcmd) {
1294 data = (caddr_t)&term;
1295 }
1296#endif
1297 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1298 int cc;
1299 struct termios *dt = (struct termios *)data;
1300 struct termios *lt = IS_CALLOUT(dev)
1301 ? &rp->lt_out : &rp->lt_in;
1302
1303 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1304 | (dt->c_iflag & ~lt->c_iflag);
1305 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1306 | (dt->c_oflag & ~lt->c_oflag);
1307 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1308 | (dt->c_cflag & ~lt->c_cflag);
1309 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1310 | (dt->c_lflag & ~lt->c_lflag);
1311 for(cc = 0; cc < NCCS; ++cc)
1312 if(lt->c_cc[cc] != 0)
1313 dt->c_cc[cc] = tp->t_cc[cc];
1314 if(lt->c_ispeed != 0)
1315 dt->c_ispeed = tp->t_ispeed;
1316 if(lt->c_ospeed != 0)
1317 dt->c_ospeed = tp->t_ospeed;
1318 }
1319
1320 t = &tp->t_termios;
1321
1322 error = ttyioctl(dev, cmd, data, flag, td);
1323 ttyldoptim(tp);
1324 if(error != ENOTTY)
1325 return(error);
1326 oldspl = spltty();
1327
1328 flags = rp->rp_channel.TxControl[3];
1329
1330 switch(cmd) {
1331 case TIOCSBRK:
1332 sSendBreak(&rp->rp_channel);
1333 break;
1334
1335 case TIOCCBRK:
1336 sClrBreak(&rp->rp_channel);
1337 break;
1338
1339 case TIOCSDTR:
1340 sSetDTR(&rp->rp_channel);
1341 sSetRTS(&rp->rp_channel);
1342 break;
1343
1344 case TIOCCDTR:
1345 sClrDTR(&rp->rp_channel);
1346 break;
1347
1348 case TIOCMSET:
1349 arg = *(int *) data;
1350 flags = 0;
1351 if(arg & TIOCM_RTS)
1352 flags |= SET_RTS;
1353 if(arg & TIOCM_DTR)
1354 flags |= SET_DTR;
1355 rp->rp_channel.TxControl[3] =
1356 ((rp->rp_channel.TxControl[3]
1357 & ~(SET_RTS | SET_DTR)) | flags);
1358 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1359 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1360 break;
1361 case TIOCMBIS:
1362 arg = *(int *) data;
1363 flags = 0;
1364 if(arg & TIOCM_RTS)
1365 flags |= SET_RTS;
1366 if(arg & TIOCM_DTR)
1367 flags |= SET_DTR;
1368 rp->rp_channel.TxControl[3] |= flags;
1369 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1370 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1371 break;
1372 case TIOCMBIC:
1373 arg = *(int *) data;
1374 flags = 0;
1375 if(arg & TIOCM_RTS)
1376 flags |= SET_RTS;
1377 if(arg & TIOCM_DTR)
1378 flags |= SET_DTR;
1379 rp->rp_channel.TxControl[3] &= ~flags;
1380 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1381 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1382 break;
1383
1384
1385 case TIOCMGET:
1386 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1387 flags = rp->rp_channel.TxControl[3];
1388 result = TIOCM_LE; /* always on while open for some reason */
1389 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1390 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1391 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1392 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1393 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1394
1395 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1396 {
1397 result |= TIOCM_RTS;
1398 }
1399
1400 *(int *)data = result;
1401 break;
1402 case TIOCMSDTRWAIT:
1403 error = suser(td);
1404 if(error != 0) {
1405 splx(oldspl);
1406 return(error);
1407 }
1408 rp->dtr_wait = *(int *)data * hz/100;
1409 break;
1410 case TIOCMGDTRWAIT:
1411 *(int *)data = rp->dtr_wait * 100/hz;
1412 break;
1413 default:
1414 splx(oldspl);
1415 return ENOTTY;
1416 }
1417 splx(oldspl);
1418 return(0);
1419}
1420
1421static struct speedtab baud_table[] = {
1422 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1423 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1424 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1425 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1426 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1427 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1428 {B57600, BRD57600}, {B76800, BRD76800},
1429 {B115200, BRD115200}, {B230400, BRD230400},
1430 {-1, -1}
1431};
1432
1433static int
1434rpparam(tp, t)
1435 struct tty *tp;
1436 struct termios *t;
1437{
1438 struct rp_port *rp;
1439 CHANNEL_t *cp;
1440 int unit, mynor, port, umynor; /* SG */
1441 int oldspl, cflag, iflag, oflag, lflag;
1442 int ospeed;
1443#ifdef RPCLOCAL
1444 int devshift;
1445#endif
1446
1447
1448 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1449 port = (minor(tp->t_dev) & 0x1f); /* SG */
1450 mynor = (port + umynor); /* SG */
1451
1452 unit = minor_to_unit[mynor];
1453 rp = rp_addr(unit) + port;
1454 cp = &rp->rp_channel;
1455 oldspl = spltty();
1456
1457 cflag = t->c_cflag;
1458#ifdef RPCLOCAL
1459 devshift = umynor / 32;
1460 devshift = 1 << devshift;
1461 if ( devshift & RPCLOCAL ) {
1462 cflag |= CLOCAL;
1463 }
1464#endif
1465 iflag = t->c_iflag;
1466 oflag = t->c_oflag;
1467 lflag = t->c_lflag;
1468
1469 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1470 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1471 return(EINVAL);
1472
1473 tp->t_ispeed = t->c_ispeed;
1474 tp->t_ospeed = t->c_ospeed;
1475 tp->t_cflag = cflag;
1476 tp->t_iflag = iflag;
1477 tp->t_oflag = oflag;
1478 tp->t_lflag = lflag;
1479
1480 if(t->c_ospeed == 0) {
1481 sClrDTR(cp);
1482 return(0);
1483 }
1484 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1485
1486 /* Set baud rate ----- we only pay attention to ispeed */
1487 sSetDTR(cp);
1488 sSetRTS(cp);
1489 sSetBaud(cp, ospeed);
1490
1491 if(cflag & CSTOPB) {
1492 sSetStop2(cp);
1493 } else {
1494 sSetStop1(cp);
1495 }
1496
1497 if(cflag & PARENB) {
1498 sEnParity(cp);
1499 if(cflag & PARODD) {
1500 sSetOddParity(cp);
1501 } else {
1502 sSetEvenParity(cp);
1503 }
1504 }
1505 else {
1506 sDisParity(cp);
1507 }
1508 if((cflag & CSIZE) == CS8) {
1509 sSetData8(cp);
1510 rp->rp_imask = 0xFF;
1511 } else {
1512 sSetData7(cp);
1513 rp->rp_imask = 0x7F;
1514 }
1515
1516 if(iflag & ISTRIP) {
1517 rp->rp_imask &= 0x7F;
1518 }
1519
1520 if(cflag & CLOCAL) {
1521 rp->rp_intmask &= ~DELTA_CD;
1522 } else {
1523 rp->rp_intmask |= DELTA_CD;
1524 }
1525
1526 /* Put flow control stuff here */
1527
1528 if(cflag & CCTS_OFLOW) {
1529 sEnCTSFlowCtl(cp);
1530 } else {
1531 sDisCTSFlowCtl(cp);
1532 }
1533
1534 if(cflag & CRTS_IFLOW) {
1535 rp->rp_rts_iflow = 1;
1536 } else {
1537 rp->rp_rts_iflow = 0;
1538 }
1539
1540 if(cflag & CRTS_IFLOW) {
1541 sEnRTSFlowCtl(cp);
1542 } else {
1543 sDisRTSFlowCtl(cp);
1544 }
1545 ttyldoptim(tp);
1546
1547 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1548 tp->t_state |= TS_CARR_ON;
1549 wakeup(TSA_CARR_ON(tp));
1550 }
1551
1552/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1553 flags = rp->rp_channel.TxControl[3];
1554 if(flags & SET_DTR)
1555 else
1556 if(flags & SET_RTS)
1557 else
1558*/
1559 splx(oldspl);
1560
1561 return(0);
1562}
1563
1564static void
1565rpstart(tp)
1566 struct tty *tp;
1567{
1568 struct rp_port *rp;
1569 CHANNEL_t *cp;
1570 struct clist *qp;
1571 int unit, mynor, port, umynor; /* SG */
1572 char flags;
1573 int spl, xmit_fifo_room;
1574 int count, wcount;
1575
1576
1577 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1578 port = (minor(tp->t_dev) & 0x1f); /* SG */
1579 mynor = (port + umynor); /* SG */
1580 unit = minor_to_unit[mynor];
1581 rp = rp_addr(unit) + port;
1582 cp = &rp->rp_channel;
1583 flags = rp->rp_channel.TxControl[3];
1584 spl = spltty();
1585
1586 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1587 ttwwakeup(tp);
1588 splx(spl);
1589 return;
1590 }
1591 if(rp->rp_xmit_stopped) {
1592 sEnTransmit(cp);
1593 rp->rp_xmit_stopped = 0;
1594 }
1595 count = sGetTxCnt(cp);
1596
1597 if(tp->t_outq.c_cc == 0) {
1598 if((tp->t_state & TS_BUSY) && (count == 0)) {
1599 tp->t_state &= ~TS_BUSY;
1600 }
1601 ttwwakeup(tp);
1602 splx(spl);
1603 return;
1604 }
1605 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1606 qp = &tp->t_outq;
1607 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1608 tp->t_state |= TS_BUSY;
1609 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1610 wcount = count >> 1;
1611 if ( wcount ) {
1612 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1613 }
1614 if ( count & 1 ) {
1615 rp_writech1(cp, sGetTxRxDataIO(cp),
1616 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1617 }
1618 }
1619 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1620
1621 ttwwakeup(tp);
1622 splx(spl);
1623}
1624
1625static
1626void
1627rpstop(tp, flag)
1628 register struct tty *tp;
1629 int flag;
1630{
1631 struct rp_port *rp;
1632 CHANNEL_t *cp;
1633 int unit, mynor, port, umynor; /* SG */
1634 int spl;
1635
1636 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1637 port = (minor(tp->t_dev) & 0x1f); /* SG */
1638 mynor = (port + umynor); /* SG */
1639 unit = minor_to_unit[mynor];
1640 rp = rp_addr(unit) + port;
1641 cp = &rp->rp_channel;
1642
1643 spl = spltty();
1644
1645 if(tp->t_state & TS_BUSY) {
1646 if((tp->t_state&TS_TTSTOP) == 0) {
1647 sFlushTxFIFO(cp);
1648 } else {
1649 if(rp->rp_xmit_stopped == 0) {
1650 sDisTransmit(cp);
1651 rp->rp_xmit_stopped = 1;
1652 }
1653 }
1654 }
1655 splx(spl);
1656 rpstart(tp);
1657}