FreeBSD/Linux Kernel Cross Reference
sys/dev/rp/rp.c
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: src/sys/dev/rp/rp.c,v 1.64.2.2 2005/11/08 15:37:21 jhb Exp $");
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
59 static const char RocketPortVersion[] = "3.02";
60
61 static 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
83 static 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 */
102 Byte_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
108 Byte_t rp_sBitMapClrTbl[8] =
109 {
110 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
111 };
112
113 Byte_t rp_sBitMapSetTbl[8] =
114 {
115 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
116 };
117
118 /* Actually not used */
119 #if notdef
120 struct 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 /***************************************************************************
134 Function: sReadAiopID
135 Purpose: Read the AIOP idenfication number directly from an AIOP.
136 Call: sReadAiopID(CtlP, aiop)
137 CONTROLLER_T *CtlP; Ptr to controller structure
138 int aiop: AIOP index
139 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
140 is replace by an identifying number.
141 Flag AIOPID_NULL if no valid AIOP is found
142 Warnings: No context switches are allowed while executing this function.
143
144 */
145 int 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 /***************************************************************************
159 Function: sReadAiopNumChan
160 Purpose: Read the number of channels available in an AIOP directly from
161 an AIOP.
162 Call: sReadAiopNumChan(CtlP, aiop)
163 CONTROLLER_T *CtlP; Ptr to controller structure
164 int aiop: AIOP index
165 Return: int: The number of channels available
166 Comments: 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.
170 Warnings: No context switches are allowed while executing this function.
171 */
172 int 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 /***************************************************************************
188 Function: sInitChan
189 Purpose: Initialization of a channel and channel structure
190 Call: 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
195 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
196 number exceeds number of channels available in AIOP.
197 Comments: This function must be called before a channel can be used.
198 Warnings: No range checking on any of the parameters is done.
199
200 No context switches are allowed while executing this function.
201 */
202 int 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 /***************************************************************************
313 Function: sStopRxProcessor
314 Purpose: Stop the receive processor from processing a channel.
315 Call: sStopRxProcessor(ChP)
316 CHANNEL_T *ChP; Ptr to channel structure
317
318 Comments: 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
322 Warnings: 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 */
330 void 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 /***************************************************************************
342 Function: sFlushRxFIFO
343 Purpose: Flush the Rx FIFO
344 Call: sFlushRxFIFO(ChP)
345 CHANNEL_T *ChP; Ptr to channel structure
346 Return: void
347 Comments: 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.
353 Warnings: No context switches are allowed while executing this function.
354 */
355 void 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 /***************************************************************************
385 Function: sFlushTxFIFO
386 Purpose: Flush the Tx FIFO
387 Call: sFlushTxFIFO(ChP)
388 CHANNEL_T *ChP; Ptr to channel structure
389 Return: void
390 Comments: 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.
396 Warnings: No context switches are allowed while executing this function.
397 */
398 void 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 /***************************************************************************
427 Function: sWriteTxPrioByte
428 Purpose: Write a byte of priority transmit data to a channel
429 Call: sWriteTxPrioByte(ChP,Data)
430 CHANNEL_T *ChP; Ptr to channel structure
431 Byte_t Data; The transmit data byte
432
433 Return: int: 1 if the bytes is successfully written, otherwise 0.
434
435 Comments: The priority byte is transmitted before any data in the Tx FIFO.
436
437 Warnings: No context switches are allowed while executing this function.
438 */
439 int 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 /***************************************************************************
470 Function: sEnInterrupts
471 Purpose: Enable one or more interrupts for a channel
472 Call: 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.
483 Return: void
484 Comments: 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 */
501 void 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 /***************************************************************************
522 Function: sDisInterrupts
523 Purpose: Disable one or more interrupts for a channel
524 Call: 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.
535 Return: void
536 Comments: 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 */
546 void 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
567 static timeout_t rpdtrwakeup;
568 struct callout_handle rp_callout_handle;
569
570 static d_open_t rpopen;
571 static d_close_t rpclose;
572 static d_write_t rpwrite;
573 static d_ioctl_t rpioctl;
574
575 struct 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
585 static int rp_num_ports_open = 0;
586 static int rp_ndevs = 0;
587 static int minor_to_unit[128];
588
589 static 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
607 static struct rp_port *p_rp_addr[4];
608 static 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
616 static int rpparam(struct tty *, struct termios *);
617 static void rpstart(struct tty *);
618 static void rpstop(struct tty *, int);
619 static void rphardclose (struct rp_port *);
620
621 static 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
713 static 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
753 static 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
797 int
798 rp_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%u%c",
842 unit, i <= 9 ? '' + i : 'a' + i - 10);
843 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20,
844 UID_ROOT, GID_WHEEL, 0666, "ttyiR%u%c",
845 unit, i <= 9 ? '' + i : 'a' + i - 10);
846 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40,
847 UID_ROOT, GID_WHEEL, 0666, "ttylR%u%c",
848 unit, i <= 9 ? '' + i : 'a' + i - 10);
849 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80,
850 UID_ROOT, GID_WHEEL, 0666, "cuaR%u%c",
851 unit, i <= 9 ? '' + i : 'a' + i - 10);
852 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0,
853 UID_ROOT, GID_WHEEL, 0666, "cuaiR%u%c",
854 unit, i <= 9 ? '' + i : 'a' + i - 10);
855 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0,
856 UID_ROOT, GID_WHEEL, 0666, "cualR%u%c",
857 unit, i <= 9 ? '' + i : 'a' + i - 10);
858 }
859
860 /* Aliases for compat. */
861 if (unit == 0) {
862 dev_nodes = ctlp->dev_nodes;
863 for (i = 0 ; i < rp_num_ports[unit] ; i++) {
864 make_dev_alias(*(dev_nodes++), "ttyR%c",
865 i <= 9 ? '' + i : 'a' + i - 10);
866 make_dev_alias(*(dev_nodes++), "ttyiR%c",
867 i <= 9 ? '' + i : 'a' + i - 10);
868 make_dev_alias(*(dev_nodes++), "ttylR%c",
869 i <= 9 ? '' + i : 'a' + i - 10);
870 make_dev_alias(*(dev_nodes++), "cuaR%c",
871 i <= 9 ? '' + i : 'a' + i - 10);
872 make_dev_alias(*(dev_nodes++), "cuaiR%c",
873 i <= 9 ? '' + i : 'a' + i - 10);
874 make_dev_alias(*(dev_nodes++), "cualR%c",
875 i <= 9 ? '' + i : 'a' + i - 10);
876 }
877 }
878
879 port = 0;
880 for(aiop=0; aiop < num_aiops; aiop++) {
881 num_chan = sGetAiopNumChan(ctlp, aiop);
882 for(chan=0; chan < num_chan; chan++, port++, rp++) {
883 rp->rp_tty = ttymalloc(NULL);
884 rp->rp_port = port;
885 rp->rp_ctlp = ctlp;
886 rp->rp_unit = unit;
887 rp->rp_chan = chan;
888 rp->rp_aiop = aiop;
889
890 rp->rp_tty->t_line = 0;
891 /* tty->t_termios = deftermios;
892 */
893 rp->it_in.c_iflag = 0;
894 rp->it_in.c_oflag = 0;
895 rp->it_in.c_cflag = TTYDEF_CFLAG;
896 rp->it_in.c_lflag = 0;
897 termioschars(&rp->it_in);
898 /* termioschars(&tty->t_termios);
899 */
900 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
901 rp->it_out = rp->it_in;
902
903 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
904 DELTA_CD | DELTA_CTS | DELTA_DSR;
905 #if notdef
906 ChanStatus = sGetChanStatus(&rp->rp_channel);
907 #endif /* notdef */
908 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
909 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
910 unit, aiop, chan);
911 retval = ENXIO;
912 goto nogo;
913 }
914 ChanStatus = sGetChanStatus(&rp->rp_channel);
915 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
916 line = (unit << 5) | (aiop << 3) | chan;
917 rp_table(line) = rp;
918 }
919 }
920
921 rp_ndevs++;
922 return (0);
923
924 nogo:
925 rp_releaseresource(ctlp);
926
927 return (retval);
928 }
929
930 void
931 rp_releaseresource(CONTROLLER_t *ctlp)
932 {
933 int i, s, unit;
934 struct rp_port *rp;
935
936
937 unit = device_get_unit(ctlp->dev);
938 if (rp_addr(unit) != NULL) {
939 for (i = 0; i < rp_num_ports[unit]; i++) {
940 rp = rp_addr(unit) + i;
941 s = ttyrel(rp->rp_tty);
942 if (s) {
943 printf("Detaching with active tty (%d refs)!\n", s);
944 }
945 }
946 }
947
948 if (ctlp->rp != NULL) {
949 s = spltty();
950 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
951 if (p_rp_addr[i] == ctlp->rp)
952 p_rp_addr[i] = NULL;
953 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
954 if (p_rp_table[i] == ctlp->rp)
955 p_rp_table[i] = NULL;
956 splx(s);
957 free(ctlp->rp, M_DEVBUF);
958 ctlp->rp = NULL;
959 }
960 if (ctlp->dev != NULL) {
961 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++)
962 destroy_dev(ctlp->dev_nodes[i]);
963 free(ctlp->dev_nodes, M_DEVBUF);
964 ctlp->dev = NULL;
965 }
966 }
967
968 void
969 rp_untimeout(void)
970 {
971 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
972 }
973 static int
974 rpopen(dev, flag, mode, td)
975 struct cdev *dev;
976 int flag, mode;
977 struct thread *td;
978 {
979 struct rp_port *rp;
980 int unit, port, mynor, umynor, flags; /* SG */
981 struct tty *tp;
982 int oldspl, error;
983 unsigned int IntMask, ChanStatus;
984
985
986 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
987 port = (minor(dev) & 0x1f); /* SG */
988 mynor = (port + umynor); /* SG */
989 unit = minor_to_unit[mynor];
990 if (rp_addr(unit) == NULL)
991 return (ENXIO);
992 if(IS_CONTROL(dev))
993 return(0);
994 rp = rp_addr(unit) + port;
995 /* rp->rp_tty = &rp_tty[rp->rp_port];
996 */
997 tp = rp->rp_tty;
998 dev->si_tty = tp;
999
1000 oldspl = spltty();
1001
1002 open_top:
1003 while(rp->state & ~SET_DTR) {
1004 error = tsleep(&tp->t_dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1005 if(error != 0)
1006 goto out;
1007 }
1008
1009 if(tp->t_state & TS_ISOPEN) {
1010 if(IS_CALLOUT(dev)) {
1011 if(!rp->active_out) {
1012 error = EBUSY;
1013 goto out;
1014 }
1015 } else {
1016 if(rp->active_out) {
1017 if(flag & O_NONBLOCK) {
1018 error = EBUSY;
1019 goto out;
1020 }
1021 error = tsleep(&rp->active_out,
1022 TTIPRI | PCATCH, "rpbi", 0);
1023 if(error != 0)
1024 goto out;
1025 goto open_top;
1026 }
1027 }
1028 if(tp->t_state & TS_XCLUDE && suser(td) != 0) {
1029 splx(oldspl);
1030 error = EBUSY;
1031 goto out2;
1032 }
1033 }
1034 else {
1035 tp->t_dev = dev;
1036 tp->t_param = rpparam;
1037 tp->t_oproc = rpstart;
1038 tp->t_stop = rpstop;
1039 tp->t_line = 0;
1040 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1041 tp->t_ififosize = 512;
1042 tp->t_ispeedwat = (speed_t)-1;
1043 tp->t_ospeedwat = (speed_t)-1;
1044 flags = 0;
1045 flags |= SET_RTS;
1046 flags |= SET_DTR;
1047 rp->rp_channel.TxControl[3] =
1048 ((rp->rp_channel.TxControl[3]
1049 & ~(SET_RTS | SET_DTR)) | flags);
1050 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1051 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1052 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1053 sDisRxStatusMode(&rp->rp_channel);
1054 sFlushRxFIFO(&rp->rp_channel);
1055 sFlushTxFIFO(&rp->rp_channel);
1056
1057 sEnInterrupts(&rp->rp_channel,
1058 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1059 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1060
1061 sDisRxStatusMode(&rp->rp_channel);
1062 sClrTxXOFF(&rp->rp_channel);
1063
1064 /* sDisRTSFlowCtl(&rp->rp_channel);
1065 sDisCTSFlowCtl(&rp->rp_channel);
1066 */
1067 sDisTxSoftFlowCtl(&rp->rp_channel);
1068
1069 sStartRxProcessor(&rp->rp_channel);
1070
1071 sEnRxFIFO(&rp->rp_channel);
1072 sEnTransmit(&rp->rp_channel);
1073
1074 /* sSetDTR(&rp->rp_channel);
1075 sSetRTS(&rp->rp_channel);
1076 */
1077
1078 ++rp->wopeners;
1079 error = rpparam(tp, &tp->t_termios);
1080 --rp->wopeners;
1081 if(error != 0) {
1082 splx(oldspl);
1083 return(error);
1084 }
1085
1086 rp_num_ports_open++;
1087
1088 IntMask = sGetChanIntID(&rp->rp_channel);
1089 IntMask = IntMask & rp->rp_intmask;
1090 ChanStatus = sGetChanStatus(&rp->rp_channel);
1091 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1092 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1093 (void)ttyld_modem(tp, 1);
1094 }
1095 }
1096
1097 if(rp_num_ports_open == 1)
1098 rp_callout_handle = timeout(rp_do_poll,
1099 (void *)NULL, POLL_INTERVAL);
1100 }
1101
1102 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1103 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1104 ++rp->wopeners;
1105 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1106 "rpdcd", 0);
1107 --rp->wopeners;
1108 if(error != 0)
1109 goto out;
1110 goto open_top;
1111 }
1112 error = ttyld_open(tp, dev);
1113
1114 ttyldoptim(tp);
1115 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1116 rp->active_out = TRUE;
1117
1118 /* if(rp_num_ports_open == 1)
1119 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1120 */
1121 out:
1122 splx(oldspl);
1123 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1124 rphardclose(rp);
1125 }
1126 out2:
1127 if (error == 0)
1128 device_busy(rp->rp_ctlp->dev);
1129 return(error);
1130 }
1131
1132 static int
1133 rpclose(dev, flag, mode, td)
1134 struct cdev *dev;
1135 int flag, mode;
1136 struct thread *td;
1137 {
1138 int oldspl, unit, mynor, umynor, port; /* SG */
1139 struct rp_port *rp;
1140 struct tty *tp;
1141 CHANNEL_t *cp;
1142
1143 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1144 port = (minor(dev) & 0x1f); /* SG */
1145 mynor = (port + umynor); /* SG */
1146 unit = minor_to_unit[mynor]; /* SG */
1147
1148 if(IS_CONTROL(dev))
1149 return(0);
1150 rp = rp_addr(unit) + port;
1151 cp = &rp->rp_channel;
1152 tp = rp->rp_tty;
1153
1154 oldspl = spltty();
1155 ttyld_close(tp, flag);
1156 ttyldoptim(tp);
1157 rphardclose(rp);
1158
1159 tp->t_state &= ~TS_BUSY;
1160 tty_close(tp);
1161
1162 splx(oldspl);
1163
1164 device_unbusy(rp->rp_ctlp->dev);
1165
1166 return(0);
1167 }
1168
1169 static void
1170 rphardclose(struct rp_port *rp)
1171 {
1172 int mynor;
1173 struct tty *tp;
1174 CHANNEL_t *cp;
1175
1176 cp = &rp->rp_channel;
1177 tp = rp->rp_tty;
1178 mynor = MINOR_MAGIC(tp->t_dev);
1179
1180 sFlushRxFIFO(cp);
1181 sFlushTxFIFO(cp);
1182 sDisTransmit(cp);
1183 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1184 sDisRTSFlowCtl(cp);
1185 sDisCTSFlowCtl(cp);
1186 sDisTxSoftFlowCtl(cp);
1187 sClrTxXOFF(cp);
1188
1189 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1190 sClrDTR(cp);
1191 }
1192 if(IS_CALLOUT(tp->t_dev)) {
1193 sClrDTR(cp);
1194 }
1195 if(tp->t_dtr_wait != 0) {
1196 timeout(rpdtrwakeup, rp, tp->t_dtr_wait);
1197 rp->state |= ~SET_DTR;
1198 }
1199
1200 rp->active_out = FALSE;
1201 wakeup(&rp->active_out);
1202 wakeup(TSA_CARR_ON(tp));
1203 }
1204
1205 static
1206 int
1207 rpwrite(dev, uio, flag)
1208 struct cdev *dev;
1209 struct uio *uio;
1210 int flag;
1211 {
1212 struct rp_port *rp;
1213 struct tty *tp;
1214 int unit, mynor, port, umynor, error = 0; /* SG */
1215
1216 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1217 port = (minor(dev) & 0x1f); /* SG */
1218 mynor = (port + umynor); /* SG */
1219 unit = minor_to_unit[mynor]; /* SG */
1220
1221 if(IS_CONTROL(dev))
1222 return(ENODEV);
1223 rp = rp_addr(unit) + port;
1224 tp = rp->rp_tty;
1225 while(rp->rp_disable_writes) {
1226 rp->rp_waiting = 1;
1227 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1228 if (error)
1229 return(error);
1230 }
1231
1232 error = ttyld_write(tp, uio, flag);
1233 return error;
1234 }
1235
1236 static void
1237 rpdtrwakeup(void *chan)
1238 {
1239 struct rp_port *rp;
1240
1241 rp = (struct rp_port *)chan;
1242 rp->state &= SET_DTR;
1243 wakeup(&rp->rp_tty->t_dtr_wait);
1244 }
1245
1246 static int
1247 rpioctl(dev, cmd, data, flag, td)
1248 struct cdev *dev;
1249 u_long cmd;
1250 caddr_t data;
1251 int flag;
1252 struct thread *td;
1253 {
1254 struct rp_port *rp;
1255 CHANNEL_t *cp;
1256 struct tty *tp;
1257 int unit, mynor, port, umynor; /* SG */
1258 int oldspl;
1259 int error = 0;
1260 int arg, flags, result, ChanStatus;
1261 struct termios *t;
1262 #ifndef BURN_BRIDGES
1263 #if defined(COMPAT_43)
1264 u_long oldcmd;
1265 struct termios term;
1266 #endif
1267 #endif
1268
1269 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1270 port = (minor(dev) & 0x1f); /* SG */
1271 mynor = (port + umynor); /* SG */
1272 unit = minor_to_unit[mynor];
1273 rp = rp_addr(unit) + port;
1274
1275 if(IS_CONTROL(dev)) {
1276 struct termios *ct;
1277
1278 switch (IS_CONTROL(dev)) {
1279 case CONTROL_INIT_STATE:
1280 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1281 break;
1282 case CONTROL_LOCK_STATE:
1283 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1284 break;
1285 default:
1286 return(ENODEV); /* /dev/nodev */
1287 }
1288 switch (cmd) {
1289 case TIOCSETA:
1290 error = suser(td);
1291 if(error != 0)
1292 return(error);
1293 *ct = *(struct termios *)data;
1294 return(0);
1295 case TIOCGETA:
1296 *(struct termios *)data = *ct;
1297 return(0);
1298 case TIOCGETD:
1299 *(int *)data = TTYDISC;
1300 return(0);
1301 case TIOCGWINSZ:
1302 bzero(data, sizeof(struct winsize));
1303 return(0);
1304 default:
1305 return(ENOTTY);
1306 }
1307 }
1308
1309 tp = rp->rp_tty;
1310 cp = &rp->rp_channel;
1311
1312 #ifndef BURN_BRIDGES
1313 #if defined(COMPAT_43)
1314 term = tp->t_termios;
1315 oldcmd = cmd;
1316 error = ttsetcompat(tp, &cmd, data, &term);
1317 if(error != 0)
1318 return(error);
1319 if(cmd != oldcmd) {
1320 data = (caddr_t)&term;
1321 }
1322 #endif
1323 #endif
1324 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1325 int cc;
1326 struct termios *dt = (struct termios *)data;
1327 struct termios *lt = IS_CALLOUT(dev)
1328 ? &rp->lt_out : &rp->lt_in;
1329
1330 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1331 | (dt->c_iflag & ~lt->c_iflag);
1332 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1333 | (dt->c_oflag & ~lt->c_oflag);
1334 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1335 | (dt->c_cflag & ~lt->c_cflag);
1336 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1337 | (dt->c_lflag & ~lt->c_lflag);
1338 for(cc = 0; cc < NCCS; ++cc)
1339 if(lt->c_cc[cc] != 0)
1340 dt->c_cc[cc] = tp->t_cc[cc];
1341 if(lt->c_ispeed != 0)
1342 dt->c_ispeed = tp->t_ispeed;
1343 if(lt->c_ospeed != 0)
1344 dt->c_ospeed = tp->t_ospeed;
1345 }
1346
1347 t = &tp->t_termios;
1348
1349 error = ttyioctl(dev, cmd, data, flag, td);
1350 ttyldoptim(tp);
1351 if(error != ENOTTY)
1352 return(error);
1353 oldspl = spltty();
1354
1355 flags = rp->rp_channel.TxControl[3];
1356
1357 switch(cmd) {
1358 case TIOCSBRK:
1359 sSendBreak(&rp->rp_channel);
1360 break;
1361
1362 case TIOCCBRK:
1363 sClrBreak(&rp->rp_channel);
1364 break;
1365
1366 case TIOCSDTR:
1367 sSetDTR(&rp->rp_channel);
1368 sSetRTS(&rp->rp_channel);
1369 break;
1370
1371 case TIOCCDTR:
1372 sClrDTR(&rp->rp_channel);
1373 break;
1374
1375 case TIOCMSET:
1376 arg = *(int *) data;
1377 flags = 0;
1378 if(arg & TIOCM_RTS)
1379 flags |= SET_RTS;
1380 if(arg & TIOCM_DTR)
1381 flags |= SET_DTR;
1382 rp->rp_channel.TxControl[3] =
1383 ((rp->rp_channel.TxControl[3]
1384 & ~(SET_RTS | SET_DTR)) | flags);
1385 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1386 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1387 break;
1388 case TIOCMBIS:
1389 arg = *(int *) data;
1390 flags = 0;
1391 if(arg & TIOCM_RTS)
1392 flags |= SET_RTS;
1393 if(arg & TIOCM_DTR)
1394 flags |= SET_DTR;
1395 rp->rp_channel.TxControl[3] |= flags;
1396 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1397 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1398 break;
1399 case TIOCMBIC:
1400 arg = *(int *) data;
1401 flags = 0;
1402 if(arg & TIOCM_RTS)
1403 flags |= SET_RTS;
1404 if(arg & TIOCM_DTR)
1405 flags |= SET_DTR;
1406 rp->rp_channel.TxControl[3] &= ~flags;
1407 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1408 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1409 break;
1410
1411
1412 case TIOCMGET:
1413 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1414 flags = rp->rp_channel.TxControl[3];
1415 result = TIOCM_LE; /* always on while open for some reason */
1416 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1417 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1418 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1419 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1420 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1421
1422 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1423 {
1424 result |= TIOCM_RTS;
1425 }
1426
1427 *(int *)data = result;
1428 break;
1429 default:
1430 splx(oldspl);
1431 return ENOTTY;
1432 }
1433 splx(oldspl);
1434 return(0);
1435 }
1436
1437 static struct speedtab baud_table[] = {
1438 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1439 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1440 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1441 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1442 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1443 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1444 {B57600, BRD57600}, {B76800, BRD76800},
1445 {B115200, BRD115200}, {B230400, BRD230400},
1446 {-1, -1}
1447 };
1448
1449 static int
1450 rpparam(tp, t)
1451 struct tty *tp;
1452 struct termios *t;
1453 {
1454 struct rp_port *rp;
1455 CHANNEL_t *cp;
1456 int unit, mynor, port, umynor; /* SG */
1457 int oldspl, cflag, iflag, oflag, lflag;
1458 int ospeed;
1459 #ifdef RPCLOCAL
1460 int devshift;
1461 #endif
1462
1463
1464 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1465 port = (minor(tp->t_dev) & 0x1f); /* SG */
1466 mynor = (port + umynor); /* SG */
1467
1468 unit = minor_to_unit[mynor];
1469 rp = rp_addr(unit) + port;
1470 cp = &rp->rp_channel;
1471 oldspl = spltty();
1472
1473 cflag = t->c_cflag;
1474 #ifdef RPCLOCAL
1475 devshift = umynor / 32;
1476 devshift = 1 << devshift;
1477 if ( devshift & RPCLOCAL ) {
1478 cflag |= CLOCAL;
1479 }
1480 #endif
1481 iflag = t->c_iflag;
1482 oflag = t->c_oflag;
1483 lflag = t->c_lflag;
1484
1485 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1486 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1487 return(EINVAL);
1488
1489 tp->t_ispeed = t->c_ispeed;
1490 tp->t_ospeed = t->c_ospeed;
1491 tp->t_cflag = cflag;
1492 tp->t_iflag = iflag;
1493 tp->t_oflag = oflag;
1494 tp->t_lflag = lflag;
1495
1496 if(t->c_ospeed == 0) {
1497 sClrDTR(cp);
1498 return(0);
1499 }
1500 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1501
1502 /* Set baud rate ----- we only pay attention to ispeed */
1503 sSetDTR(cp);
1504 sSetRTS(cp);
1505 sSetBaud(cp, ospeed);
1506
1507 if(cflag & CSTOPB) {
1508 sSetStop2(cp);
1509 } else {
1510 sSetStop1(cp);
1511 }
1512
1513 if(cflag & PARENB) {
1514 sEnParity(cp);
1515 if(cflag & PARODD) {
1516 sSetOddParity(cp);
1517 } else {
1518 sSetEvenParity(cp);
1519 }
1520 }
1521 else {
1522 sDisParity(cp);
1523 }
1524 if((cflag & CSIZE) == CS8) {
1525 sSetData8(cp);
1526 rp->rp_imask = 0xFF;
1527 } else {
1528 sSetData7(cp);
1529 rp->rp_imask = 0x7F;
1530 }
1531
1532 if(iflag & ISTRIP) {
1533 rp->rp_imask &= 0x7F;
1534 }
1535
1536 if(cflag & CLOCAL) {
1537 rp->rp_intmask &= ~DELTA_CD;
1538 } else {
1539 rp->rp_intmask |= DELTA_CD;
1540 }
1541
1542 /* Put flow control stuff here */
1543
1544 if(cflag & CCTS_OFLOW) {
1545 sEnCTSFlowCtl(cp);
1546 } else {
1547 sDisCTSFlowCtl(cp);
1548 }
1549
1550 if(cflag & CRTS_IFLOW) {
1551 rp->rp_rts_iflow = 1;
1552 } else {
1553 rp->rp_rts_iflow = 0;
1554 }
1555
1556 if(cflag & CRTS_IFLOW) {
1557 sEnRTSFlowCtl(cp);
1558 } else {
1559 sDisRTSFlowCtl(cp);
1560 }
1561 ttyldoptim(tp);
1562
1563 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1564 tp->t_state |= TS_CARR_ON;
1565 wakeup(TSA_CARR_ON(tp));
1566 }
1567
1568 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1569 flags = rp->rp_channel.TxControl[3];
1570 if(flags & SET_DTR)
1571 else
1572 if(flags & SET_RTS)
1573 else
1574 */
1575 splx(oldspl);
1576
1577 return(0);
1578 }
1579
1580 static void
1581 rpstart(tp)
1582 struct tty *tp;
1583 {
1584 struct rp_port *rp;
1585 CHANNEL_t *cp;
1586 struct clist *qp;
1587 int unit, mynor, port, umynor; /* SG */
1588 char flags;
1589 int spl, xmit_fifo_room;
1590 int count, wcount;
1591
1592
1593 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1594 port = (minor(tp->t_dev) & 0x1f); /* SG */
1595 mynor = (port + umynor); /* SG */
1596 unit = minor_to_unit[mynor];
1597 rp = rp_addr(unit) + port;
1598 cp = &rp->rp_channel;
1599 flags = rp->rp_channel.TxControl[3];
1600 spl = spltty();
1601
1602 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1603 ttwwakeup(tp);
1604 splx(spl);
1605 return;
1606 }
1607 if(rp->rp_xmit_stopped) {
1608 sEnTransmit(cp);
1609 rp->rp_xmit_stopped = 0;
1610 }
1611 count = sGetTxCnt(cp);
1612
1613 if(tp->t_outq.c_cc == 0) {
1614 if((tp->t_state & TS_BUSY) && (count == 0)) {
1615 tp->t_state &= ~TS_BUSY;
1616 }
1617 ttwwakeup(tp);
1618 splx(spl);
1619 return;
1620 }
1621 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1622 qp = &tp->t_outq;
1623 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1624 tp->t_state |= TS_BUSY;
1625 count = q_to_b( qp, (char *)rp->TxBuf, xmit_fifo_room );
1626 wcount = count >> 1;
1627 if ( wcount ) {
1628 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount);
1629 }
1630 if ( count & 1 ) {
1631 rp_writech1(cp, sGetTxRxDataIO(cp),
1632 ((unsigned char *)(rp->TxBuf))[(count-1)]);
1633 }
1634 }
1635 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1636
1637 ttwwakeup(tp);
1638 splx(spl);
1639 }
1640
1641 static
1642 void
1643 rpstop(tp, flag)
1644 register struct tty *tp;
1645 int flag;
1646 {
1647 struct rp_port *rp;
1648 CHANNEL_t *cp;
1649 int unit, mynor, port, umynor; /* SG */
1650 int spl;
1651
1652 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1653 port = (minor(tp->t_dev) & 0x1f); /* SG */
1654 mynor = (port + umynor); /* SG */
1655 unit = minor_to_unit[mynor];
1656 rp = rp_addr(unit) + port;
1657 cp = &rp->rp_channel;
1658
1659 spl = spltty();
1660
1661 if(tp->t_state & TS_BUSY) {
1662 if((tp->t_state&TS_TTSTOP) == 0) {
1663 sFlushTxFIFO(cp);
1664 } else {
1665 if(rp->rp_xmit_stopped == 0) {
1666 sDisTransmit(cp);
1667 rp->rp_xmit_stopped = 1;
1668 }
1669 }
1670 }
1671 splx(spl);
1672 rpstart(tp);
1673 }
Cache object: fe23072c6a41125b972a29ef0ee5d90e
|