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