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$");
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/endian.h>
46 #include <sys/fcntl.h>
47 #include <sys/malloc.h>
48 #include <sys/serial.h>
49 #include <sys/tty.h>
50 #include <sys/conf.h>
51 #include <sys/kernel.h>
52 #include <machine/resource.h>
53 #include <machine/bus.h>
54 #include <sys/bus.h>
55 #include <sys/rman.h>
56
57 #define ROCKET_C
58 #include <dev/rp/rpreg.h>
59 #include <dev/rp/rpvar.h>
60
61 static const char RocketPortVersion[] = "3.02";
62
63 static Byte_t RData[RDATASIZE] =
64 {
65 0x00, 0x09, 0xf6, 0x82,
66 0x02, 0x09, 0x86, 0xfb,
67 0x04, 0x09, 0x00, 0x0a,
68 0x06, 0x09, 0x01, 0x0a,
69 0x08, 0x09, 0x8a, 0x13,
70 0x0a, 0x09, 0xc5, 0x11,
71 0x0c, 0x09, 0x86, 0x85,
72 0x0e, 0x09, 0x20, 0x0a,
73 0x10, 0x09, 0x21, 0x0a,
74 0x12, 0x09, 0x41, 0xff,
75 0x14, 0x09, 0x82, 0x00,
76 0x16, 0x09, 0x82, 0x7b,
77 0x18, 0x09, 0x8a, 0x7d,
78 0x1a, 0x09, 0x88, 0x81,
79 0x1c, 0x09, 0x86, 0x7a,
80 0x1e, 0x09, 0x84, 0x81,
81 0x20, 0x09, 0x82, 0x7c,
82 0x22, 0x09, 0x0a, 0x0a
83 };
84
85 static Byte_t RRegData[RREGDATASIZE]=
86 {
87 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
88 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
89 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
90 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
91 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
92 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
93 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
94 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
95 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
96 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
97 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
98 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
99 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
100 };
101
102 #if 0
103 /* IRQ number to MUDBAC register 2 mapping */
104 Byte_t sIRQMap[16] =
105 {
106 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
107 };
108 #endif
109
110 Byte_t rp_sBitMapClrTbl[8] =
111 {
112 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
113 };
114
115 Byte_t rp_sBitMapSetTbl[8] =
116 {
117 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
118 };
119
120 /***************************************************************************
121 Function: sReadAiopID
122 Purpose: Read the AIOP idenfication number directly from an AIOP.
123 Call: sReadAiopID(CtlP, aiop)
124 CONTROLLER_T *CtlP; Ptr to controller structure
125 int aiop: AIOP index
126 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
127 is replace by an identifying number.
128 Flag AIOPID_NULL if no valid AIOP is found
129 Warnings: No context switches are allowed while executing this function.
130
131 */
132 int sReadAiopID(CONTROLLER_T *CtlP, int aiop)
133 {
134 Byte_t AiopID; /* ID byte from AIOP */
135
136 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */
137 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0);
138 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07;
139 if(AiopID == 0x06)
140 return(1);
141 else /* AIOP does not exist */
142 return(-1);
143 }
144
145 /***************************************************************************
146 Function: sReadAiopNumChan
147 Purpose: Read the number of channels available in an AIOP directly from
148 an AIOP.
149 Call: sReadAiopNumChan(CtlP, aiop)
150 CONTROLLER_T *CtlP; Ptr to controller structure
151 int aiop: AIOP index
152 Return: int: The number of channels available
153 Comments: The number of channels is determined by write/reads from identical
154 offsets within the SRAM address spaces for channels 0 and 4.
155 If the channel 4 space is mirrored to channel 0 it is a 4 channel
156 AIOP, otherwise it is an 8 channel.
157 Warnings: No context switches are allowed while executing this function.
158 */
159 int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop)
160 {
161 Word_t x, y;
162
163 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
164 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */
165 x = rp_readaiop2(CtlP, aiop, _INDX_DATA);
166 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
167 y = rp_readaiop2(CtlP, aiop, _INDX_DATA);
168 if(x != y) /* if different must be 8 chan */
169 return(8);
170 else
171 return(4);
172 }
173
174 /***************************************************************************
175 Function: sInitChan
176 Purpose: Initialization of a channel and channel structure
177 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
178 CONTROLLER_T *CtlP; Ptr to controller structure
179 CHANNEL_T *ChP; Ptr to channel structure
180 int AiopNum; AIOP number within controller
181 int ChanNum; Channel number within AIOP
182 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
183 number exceeds number of channels available in AIOP.
184 Comments: This function must be called before a channel can be used.
185 Warnings: No range checking on any of the parameters is done.
186
187 No context switches are allowed while executing this function.
188 */
189 int sInitChan( CONTROLLER_T *CtlP,
190 CHANNEL_T *ChP,
191 int AiopNum,
192 int ChanNum)
193 {
194 int i, ChOff;
195 Byte_t *ChR;
196 static Byte_t R[4];
197
198 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
199 return(FALSE); /* exceeds num chans in AIOP */
200
201 /* Channel, AIOP, and controller identifiers */
202 ChP->CtlP = CtlP;
203 ChP->ChanID = CtlP->AiopID[AiopNum];
204 ChP->AiopNum = AiopNum;
205 ChP->ChanNum = ChanNum;
206
207 /* Initialize the channel from the RData array */
208 for(i=0; i < RDATASIZE; i+=4)
209 {
210 R[0] = RData[i];
211 R[1] = RData[i+1] + 0x10 * ChanNum;
212 R[2] = RData[i+2];
213 R[3] = RData[i+3];
214 rp_writech4(ChP,_INDX_ADDR,le32dec(R));
215 }
216
217 ChR = ChP->R;
218 for(i=0; i < RREGDATASIZE; i+=4)
219 {
220 ChR[i] = RRegData[i];
221 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
222 ChR[i+2] = RRegData[i+2];
223 ChR[i+3] = RRegData[i+3];
224 }
225
226 /* Indexed registers */
227 ChOff = (Word_t)ChanNum * 0x1000;
228
229 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
230 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
231 ChP->BaudDiv[2] = (Byte_t)BRD9600;
232 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
233 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv));
234
235 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
236 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
237 ChP->TxControl[2] = 0;
238 ChP->TxControl[3] = 0;
239 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
240
241 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
242 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
243 ChP->RxControl[2] = 0;
244 ChP->RxControl[3] = 0;
245 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
246
247 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
248 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
249 ChP->TxEnables[2] = 0;
250 ChP->TxEnables[3] = 0;
251 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables));
252
253 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
254 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
255 ChP->TxCompare[2] = 0;
256 ChP->TxCompare[3] = 0;
257 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare));
258
259 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
260 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
261 ChP->TxReplace1[2] = 0;
262 ChP->TxReplace1[3] = 0;
263 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1));
264
265 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
266 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
267 ChP->TxReplace2[2] = 0;
268 ChP->TxReplace2[3] = 0;
269 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2));
270
271 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
272 ChP->TxFIFO = ChOff + _TX_FIFO;
273
274 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
275 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
276 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
277 rp_writech2(ChP,_INDX_DATA,0);
278 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
279 ChP->RxFIFO = ChOff + _RX_FIFO;
280
281 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
282 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
283 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
284 rp_writech2(ChP,_INDX_DATA,0);
285 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
286 rp_writech2(ChP,_INDX_DATA,0);
287 ChP->TxPrioCnt = ChOff + _TXP_CNT;
288 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt);
289 rp_writech1(ChP,_INDX_DATA,0);
290 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
291 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr);
292 rp_writech1(ChP,_INDX_DATA,0);
293 ChP->TxPrioBuf = ChOff + _TXP_BUF;
294 sEnRxProcessor(ChP); /* start the Rx processor */
295
296 return(TRUE);
297 }
298
299 /***************************************************************************
300 Function: sStopRxProcessor
301 Purpose: Stop the receive processor from processing a channel.
302 Call: sStopRxProcessor(ChP)
303 CHANNEL_T *ChP; Ptr to channel structure
304
305 Comments: The receive processor can be started again with sStartRxProcessor().
306 This function causes the receive processor to skip over the
307 stopped channel. It does not stop it from processing other channels.
308
309 Warnings: No context switches are allowed while executing this function.
310
311 Do not leave the receive processor stopped for more than one
312 character time.
313
314 After calling this function a delay of 4 uS is required to ensure
315 that the receive processor is no longer processing this channel.
316 */
317 void sStopRxProcessor(CHANNEL_T *ChP)
318 {
319 Byte_t R[4];
320
321 R[0] = ChP->R[0];
322 R[1] = ChP->R[1];
323 R[2] = 0x0a;
324 R[3] = ChP->R[3];
325 rp_writech4(ChP,_INDX_ADDR,le32dec(R));
326 }
327
328 /***************************************************************************
329 Function: sFlushRxFIFO
330 Purpose: Flush the Rx FIFO
331 Call: sFlushRxFIFO(ChP)
332 CHANNEL_T *ChP; Ptr to channel structure
333 Return: void
334 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
335 while it is being flushed the receive processor is stopped
336 and the transmitter is disabled. After these operations a
337 4 uS delay is done before clearing the pointers to allow
338 the receive processor to stop. These items are handled inside
339 this function.
340 Warnings: No context switches are allowed while executing this function.
341 */
342 void sFlushRxFIFO(CHANNEL_T *ChP)
343 {
344 int i;
345 Byte_t Ch; /* channel number within AIOP */
346 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
347
348 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
349 return; /* don't need to flush */
350
351 RxFIFOEnabled = FALSE;
352 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
353 {
354 RxFIFOEnabled = TRUE;
355 sDisRxFIFO(ChP); /* disable it */
356 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
357 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
358 }
359 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
360 Ch = (Byte_t)sGetChanNum(ChP);
361 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
362 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */
363 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */
364 rp_writech2(ChP,_INDX_DATA,0);
365 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
366 rp_writech2(ChP,_INDX_DATA,0);
367 if(RxFIFOEnabled)
368 sEnRxFIFO(ChP); /* enable Rx FIFO */
369 }
370
371 /***************************************************************************
372 Function: sFlushTxFIFO
373 Purpose: Flush the Tx FIFO
374 Call: sFlushTxFIFO(ChP)
375 CHANNEL_T *ChP; Ptr to channel structure
376 Return: void
377 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
378 while it is being flushed the receive processor is stopped
379 and the transmitter is disabled. After these operations a
380 4 uS delay is done before clearing the pointers to allow
381 the receive processor to stop. These items are handled inside
382 this function.
383 Warnings: No context switches are allowed while executing this function.
384 */
385 void sFlushTxFIFO(CHANNEL_T *ChP)
386 {
387 int i;
388 Byte_t Ch; /* channel number within AIOP */
389 int TxEnabled; /* TRUE if transmitter enabled */
390
391 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
392 return; /* don't need to flush */
393
394 TxEnabled = FALSE;
395 if(ChP->TxControl[3] & TX_ENABLE)
396 {
397 TxEnabled = TRUE;
398 sDisTransmit(ChP); /* disable transmitter */
399 }
400 sStopRxProcessor(ChP); /* stop Rx processor */
401 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
402 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */
403 Ch = (Byte_t)sGetChanNum(ChP);
404 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
405 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */
406 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
407 rp_writech2(ChP,_INDX_DATA,0);
408 if(TxEnabled)
409 sEnTransmit(ChP); /* enable transmitter */
410 sStartRxProcessor(ChP); /* restart Rx processor */
411 }
412
413 /***************************************************************************
414 Function: sWriteTxPrioByte
415 Purpose: Write a byte of priority transmit data to a channel
416 Call: sWriteTxPrioByte(ChP,Data)
417 CHANNEL_T *ChP; Ptr to channel structure
418 Byte_t Data; The transmit data byte
419
420 Return: int: 1 if the bytes is successfully written, otherwise 0.
421
422 Comments: The priority byte is transmitted before any data in the Tx FIFO.
423
424 Warnings: No context switches are allowed while executing this function.
425 */
426 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
427 {
428 Byte_t DWBuf[4]; /* buffer for double word writes */
429
430 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
431 {
432 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */
433 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */
434 return(0); /* nothing sent */
435
436 le16enc(DWBuf,ChP->TxPrioBuf); /* data byte address */
437
438 DWBuf[2] = Data; /* data byte value */
439 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
440
441 le16enc(DWBuf,ChP->TxPrioCnt); /* Tx priority count address */
442
443 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
444 DWBuf[3] = 0; /* priority buffer pointer */
445 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */
446 }
447 else /* write it to Tx FIFO */
448 {
449 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data);
450 }
451 return(1); /* 1 byte sent */
452 }
453
454 /***************************************************************************
455 Function: sEnInterrupts
456 Purpose: Enable one or more interrupts for a channel
457 Call: sEnInterrupts(ChP,Flags)
458 CHANNEL_T *ChP; Ptr to channel structure
459 Word_t Flags: Interrupt enable flags, can be any combination
460 of the following flags:
461 TXINT_EN: Interrupt on Tx FIFO empty
462 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
463 sSetRxTrigger())
464 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
465 MCINT_EN: Interrupt on modem input change
466 CHANINT_EN: Allow channel interrupt signal to the AIOP's
467 Interrupt Channel Register.
468 Return: void
469 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
470 enabled. If an interrupt enable flag is not set in Flags, that
471 interrupt will not be changed. Interrupts can be disabled with
472 function sDisInterrupts().
473
474 This function sets the appropriate bit for the channel in the AIOP's
475 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
476 this channel's bit to be set in the AIOP's Interrupt Channel Register.
477
478 Interrupts must also be globally enabled before channel interrupts
479 will be passed on to the host. This is done with function
480 sEnGlobalInt().
481
482 In some cases it may be desirable to disable interrupts globally but
483 enable channel interrupts. This would allow the global interrupt
484 status register to be used to determine which AIOPs need service.
485 */
486 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
487 {
488 Byte_t Mask; /* Interrupt Mask Register */
489
490 ChP->RxControl[2] |=
491 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
492
493 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
494
495 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
496
497 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
498
499 if(Flags & CHANINT_EN)
500 {
501 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum];
502 rp_writech1(ChP,_INT_MASK,Mask);
503 }
504 }
505
506 /***************************************************************************
507 Function: sDisInterrupts
508 Purpose: Disable one or more interrupts for a channel
509 Call: sDisInterrupts(ChP,Flags)
510 CHANNEL_T *ChP; Ptr to channel structure
511 Word_t Flags: Interrupt flags, can be any combination
512 of the following flags:
513 TXINT_EN: Interrupt on Tx FIFO empty
514 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
515 sSetRxTrigger())
516 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
517 MCINT_EN: Interrupt on modem input change
518 CHANINT_EN: Disable channel interrupt signal to the
519 AIOP's Interrupt Channel Register.
520 Return: void
521 Comments: If an interrupt flag is set in Flags, that interrupt will be
522 disabled. If an interrupt flag is not set in Flags, that
523 interrupt will not be changed. Interrupts can be enabled with
524 function sEnInterrupts().
525
526 This function clears the appropriate bit for the channel in the AIOP's
527 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
528 this channel's bit from being set in the AIOP's Interrupt Channel
529 Register.
530 */
531 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
532 {
533 Byte_t Mask; /* Interrupt Mask Register */
534
535 ChP->RxControl[2] &=
536 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
537 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl));
538 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
539 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl));
540
541 if(Flags & CHANINT_EN)
542 {
543 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum];
544 rp_writech1(ChP,_INT_MASK,Mask);
545 }
546 }
547
548 /*********************************************************************
549 Begin FreeBsd-specific driver code
550 **********************************************************************/
551
552 struct callout_handle rp_callout_handle;
553
554 static int rp_num_ports_open = 0;
555 static int rp_ndevs = 0;
556
557 static int rp_num_ports[4]; /* Number of ports on each controller */
558
559 #define POLL_INTERVAL 1
560
561 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
562 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
563 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
564
565 static struct rp_port *p_rp_addr[4];
566 static struct rp_port *p_rp_table[MAX_RP_PORTS];
567 #define rp_addr(unit) (p_rp_addr[unit])
568 #define rp_table(port) (p_rp_table[port])
569
570 /*
571 * The top-level routines begin here
572 */
573
574 static void rpbreak(struct tty *, int);
575 static void rpclose(struct tty *tp);
576 static void rphardclose(struct tty *tp);
577 static int rpmodem(struct tty *, int, int);
578 static int rpparam(struct tty *, struct termios *);
579 static void rpstart(struct tty *);
580 static void rpstop(struct tty *, int);
581 static t_open_t rpopen;
582
583 static void rp_do_receive(struct rp_port *rp, struct tty *tp,
584 CHANNEL_t *cp, unsigned int ChanStatus)
585 {
586 int spl;
587 unsigned int CharNStat;
588 int i, ToRecv, wRecv, ch, ttynocopy;
589
590 ToRecv = sGetRxCnt(cp);
591 if(ToRecv == 0)
592 return;
593
594 /* If status indicates there are errored characters in the
595 FIFO, then enter status mode (a word in FIFO holds
596 characters and status)
597 */
598
599 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
600 if(!(ChanStatus & STATMODE)) {
601 ChanStatus |= STATMODE;
602 sEnRxStatusMode(cp);
603 }
604 }
605 /*
606 if we previously entered status mode then read down the
607 FIFO one word at a time, pulling apart the character and
608 the status. Update error counters depending on status.
609 */
610 if(ChanStatus & STATMODE) {
611 while(ToRecv) {
612 if(tp->t_state & TS_TBLOCK) {
613 break;
614 }
615 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp));
616 ch = CharNStat & 0xff;
617
618 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
619 ch |= TTY_FE;
620 else if (CharNStat & STMPARITYH)
621 ch |= TTY_PE;
622 else if (CharNStat & STMRCVROVRH)
623 rp->rp_overflows++;
624
625 ttyld_rint(tp, ch);
626 ToRecv--;
627 }
628 /*
629 After emtying FIFO in status mode, turn off status mode
630 */
631
632 if(sGetRxCnt(cp) == 0) {
633 sDisRxStatusMode(cp);
634 }
635 } else {
636 /*
637 * Avoid the grotesquely inefficient lineswitch routine
638 * (ttyinput) in "raw" mode. It usually takes about 450
639 * instructions (that's without canonical processing or echo!).
640 * slinput is reasonably fast (usually 40 instructions plus
641 * call overhead).
642 */
643 ToRecv = sGetRxCnt(cp);
644 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) {
645 if ( ToRecv > RXFIFO_SIZE ) {
646 ToRecv = RXFIFO_SIZE;
647 }
648 for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) {
649 le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp)));
650 }
651 if ( ToRecv & 1 ) {
652 rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp));
653 }
654 tk_nin += ToRecv;
655 tk_rawcc += ToRecv;
656 tp->t_rawcc += ToRecv;
657 ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq);
658 ttwakeup(tp);
659 } else {
660 while (ToRecv) {
661 if(tp->t_state & TS_TBLOCK) {
662 break;
663 }
664 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp));
665 spl = spltty();
666 ttyld_rint(tp, ch);
667 splx(spl);
668 ToRecv--;
669 }
670 }
671 }
672 }
673
674 static void rp_handle_port(struct rp_port *rp)
675 {
676 CHANNEL_t *cp;
677 struct tty *tp;
678 unsigned int IntMask, ChanStatus;
679
680 if(!rp)
681 return;
682
683 cp = &rp->rp_channel;
684 tp = rp->rp_tty;
685 IntMask = sGetChanIntID(cp);
686 IntMask = IntMask & rp->rp_intmask;
687 ChanStatus = sGetChanStatus(cp);
688 if(IntMask & RXF_TRIG)
689 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
690 rp_do_receive(rp, tp, cp, ChanStatus);
691 }
692 if(IntMask & DELTA_CD) {
693 if(ChanStatus & CD_ACT) {
694 if(!(tp->t_state & TS_CARR_ON) ) {
695 (void)ttyld_modem(tp, 1);
696 }
697 } else {
698 if((tp->t_state & TS_CARR_ON)) {
699 (void)ttyld_modem(tp, 0);
700 if(ttyld_modem(tp, 0) == 0) {
701 rphardclose(tp);
702 }
703 }
704 }
705 }
706 /* oldcts = rp->rp_cts;
707 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
708 if(oldcts != rp->rp_cts) {
709 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
710 }
711 */
712 }
713
714 static void rp_do_poll(void *not_used)
715 {
716 CONTROLLER_t *ctl;
717 struct rp_port *rp;
718 struct tty *tp;
719 int unit, aiop, ch, line, count;
720 unsigned char CtlMask, AiopMask;
721
722 for(unit = 0; unit < rp_ndevs; unit++) {
723 rp = rp_addr(unit);
724 ctl = rp->rp_ctlp;
725 CtlMask = ctl->ctlmask(ctl);
726 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
727 if(CtlMask & 1) {
728 AiopMask = sGetAiopIntStatus(ctl, aiop);
729 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
730 if(AiopMask & 1) {
731 line = (unit << 5) | (aiop << 3) | ch;
732 rp = rp_table(line);
733 rp_handle_port(rp);
734 }
735 }
736 }
737 }
738
739 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
740 line++, rp++) {
741 tp = rp->rp_tty;
742 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
743 count = sGetTxCnt(&rp->rp_channel);
744 if(count == 0)
745 tp->t_state &= ~(TS_BUSY);
746 if(!(tp->t_state & TS_TTSTOP) &&
747 (count <= rp->rp_restart)) {
748 ttyld_start(tp);
749 }
750 }
751 }
752 }
753 if(rp_num_ports_open)
754 rp_callout_handle = timeout(rp_do_poll,
755 (void *)NULL, POLL_INTERVAL);
756 }
757
758 int
759 rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports)
760 {
761 int oldspl, unit;
762 int num_chan;
763 int aiop, chan, port;
764 int ChanStatus, line, count;
765 int retval;
766 struct rp_port *rp;
767 struct tty *tp;
768
769 unit = device_get_unit(ctlp->dev);
770
771 printf("RocketPort%d (Version %s) %d ports.\n", unit,
772 RocketPortVersion, num_ports);
773 rp_num_ports[unit] = num_ports;
774 callout_handle_init(&rp_callout_handle);
775
776 ctlp->rp = rp = (struct rp_port *)
777 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO);
778 if (rp == NULL) {
779 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n");
780 retval = ENOMEM;
781 goto nogo;
782 }
783
784 count = unit * 32; /* board times max ports per card SG */
785
786 bzero(rp, sizeof(struct rp_port) * num_ports);
787 oldspl = spltty();
788 rp_addr(unit) = rp;
789 splx(oldspl);
790
791 port = 0;
792 for(aiop=0; aiop < num_aiops; aiop++) {
793 num_chan = sGetAiopNumChan(ctlp, aiop);
794 for(chan=0; chan < num_chan; chan++, port++, rp++) {
795 tp = rp->rp_tty = ttyalloc();
796 tp->t_sc = rp;
797 tp->t_param = rpparam;
798 tp->t_oproc = rpstart;
799 tp->t_stop = rpstop;
800 tp->t_break = rpbreak;
801 tp->t_modem = rpmodem;
802 tp->t_close = rpclose;
803 tp->t_open = rpopen;
804 tp->t_ififosize = 512;
805 tp->t_ispeedwat = (speed_t)-1;
806 tp->t_ospeedwat = (speed_t)-1;
807 rp->rp_port = port;
808 rp->rp_ctlp = ctlp;
809 rp->rp_unit = unit;
810 rp->rp_chan = chan;
811 rp->rp_aiop = aiop;
812
813 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
814 DELTA_CD | DELTA_CTS | DELTA_DSR;
815 #ifdef notdef
816 ChanStatus = sGetChanStatus(&rp->rp_channel);
817 #endif /* notdef */
818 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
819 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n",
820 unit, aiop, chan);
821 retval = ENXIO;
822 goto nogo;
823 }
824 ChanStatus = sGetChanStatus(&rp->rp_channel);
825 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
826 line = (unit << 5) | (aiop << 3) | chan;
827 rp_table(line) = rp;
828 ttycreate(tp, NULL, 0, MINOR_CALLOUT, "R%r%r", unit,
829 port);
830 }
831 }
832
833 rp_ndevs++;
834 return (0);
835
836 nogo:
837 rp_releaseresource(ctlp);
838
839 return (retval);
840 }
841
842 void
843 rp_releaseresource(CONTROLLER_t *ctlp)
844 {
845 int i, s, unit;
846 struct rp_port *rp;
847
848
849 unit = device_get_unit(ctlp->dev);
850 if (rp_addr(unit) != NULL) {
851 for (i = 0; i < rp_num_ports[unit]; i++) {
852 rp = rp_addr(unit) + i;
853 ttyfree(rp->rp_tty);
854 }
855 }
856
857 if (ctlp->rp != NULL) {
858 s = spltty();
859 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++)
860 if (p_rp_addr[i] == ctlp->rp)
861 p_rp_addr[i] = NULL;
862 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++)
863 if (p_rp_table[i] == ctlp->rp)
864 p_rp_table[i] = NULL;
865 splx(s);
866 free(ctlp->rp, M_DEVBUF);
867 ctlp->rp = NULL;
868 }
869 }
870
871 void
872 rp_untimeout(void)
873 {
874 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle);
875 }
876
877 static int
878 rpopen(struct tty *tp, struct cdev *dev)
879 {
880 struct rp_port *rp;
881 int oldspl, flags;
882 unsigned int IntMask, ChanStatus;
883
884 rp = dev->si_drv1;
885
886 oldspl = spltty();
887
888 flags = 0;
889 flags |= SET_RTS;
890 flags |= SET_DTR;
891 rp->rp_channel.TxControl[3] =
892 ((rp->rp_channel.TxControl[3]
893 & ~(SET_RTS | SET_DTR)) | flags);
894 rp_writech4(&rp->rp_channel,_INDX_ADDR,
895 le32dec(rp->rp_channel.TxControl));
896 sSetRxTrigger(&rp->rp_channel, TRIG_1);
897 sDisRxStatusMode(&rp->rp_channel);
898 sFlushRxFIFO(&rp->rp_channel);
899 sFlushTxFIFO(&rp->rp_channel);
900
901 sEnInterrupts(&rp->rp_channel,
902 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
903 sSetRxTrigger(&rp->rp_channel, TRIG_1);
904
905 sDisRxStatusMode(&rp->rp_channel);
906 sClrTxXOFF(&rp->rp_channel);
907
908 /* sDisRTSFlowCtl(&rp->rp_channel);
909 sDisCTSFlowCtl(&rp->rp_channel);
910 */
911 sDisTxSoftFlowCtl(&rp->rp_channel);
912
913 sStartRxProcessor(&rp->rp_channel);
914
915 sEnRxFIFO(&rp->rp_channel);
916 sEnTransmit(&rp->rp_channel);
917
918 /* sSetDTR(&rp->rp_channel);
919 sSetRTS(&rp->rp_channel);
920 */
921
922 rp_num_ports_open++;
923
924 IntMask = sGetChanIntID(&rp->rp_channel);
925 IntMask = IntMask & rp->rp_intmask;
926 ChanStatus = sGetChanStatus(&rp->rp_channel);
927
928 if(rp_num_ports_open == 1)
929 rp_callout_handle = timeout(rp_do_poll,
930 (void *)NULL, POLL_INTERVAL);
931
932 device_busy(rp->rp_ctlp->dev);
933 return(0);
934 }
935
936 static void
937 rpclose(struct tty *tp)
938 {
939 struct rp_port *rp;
940
941 rp = tp->t_sc;
942 rphardclose(tp);
943 device_unbusy(rp->rp_ctlp->dev);
944 }
945
946 static void
947 rphardclose(struct tty *tp)
948 {
949 struct rp_port *rp;
950 CHANNEL_t *cp;
951
952 rp = tp->t_sc;
953 cp = &rp->rp_channel;
954
955 sFlushRxFIFO(cp);
956 sFlushTxFIFO(cp);
957 sDisTransmit(cp);
958 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
959 sDisRTSFlowCtl(cp);
960 sDisCTSFlowCtl(cp);
961 sDisTxSoftFlowCtl(cp);
962 sClrTxXOFF(cp);
963
964 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) {
965 sClrDTR(cp);
966 }
967 if(ISCALLOUT(tp->t_dev)) {
968 sClrDTR(cp);
969 }
970 tp->t_actout = FALSE;
971 wakeup(&tp->t_actout);
972 wakeup(TSA_CARR_ON(tp));
973 }
974
975 static void
976 rpbreak(struct tty *tp, int sig)
977 {
978 struct rp_port *rp;
979
980 rp = tp->t_sc;
981 if (sig) {
982 sSendBreak(&rp->rp_channel);
983 } else {
984 sClrBreak(&rp->rp_channel);
985 }
986 }
987
988 static int
989 rpmodem(struct tty *tp, int sigon, int sigoff)
990 {
991 struct rp_port *rp;
992 int i, j, k;
993
994 rp = tp->t_sc;
995 if (sigon != 0 || sigoff != 0) {
996 i = j = 0;
997 if (sigon & SER_DTR)
998 i = SET_DTR;
999 if (sigoff & SER_DTR)
1000 j = SET_DTR;
1001 if (sigon & SER_RTS)
1002 i = SET_RTS;
1003 if (sigoff & SER_RTS)
1004 j = SET_RTS;
1005 rp->rp_channel.TxControl[3] &= ~i;
1006 rp->rp_channel.TxControl[3] |= j;
1007 rp_writech4(&rp->rp_channel,_INDX_ADDR,
1008 le32dec(rp->rp_channel.TxControl));
1009 } else {
1010 i = sGetChanStatusLo(&rp->rp_channel);
1011 j = rp->rp_channel.TxControl[3];
1012 k = 0;
1013 if (j & SET_DTR)
1014 k |= SER_DTR;
1015 if (j & SET_RTS)
1016 k |= SER_RTS;
1017 if (i & CD_ACT)
1018 k |= SER_DCD;
1019 if (i & DSR_ACT)
1020 k |= SER_DSR;
1021 if (i & CTS_ACT)
1022 k |= SER_CTS;
1023 return(k);
1024 }
1025 return (0);
1026 }
1027
1028 static struct speedtab baud_table[] = {
1029 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1030 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1031 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1032 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1033 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1034 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1035 {B57600, BRD57600}, {B76800, BRD76800},
1036 {B115200, BRD115200}, {B230400, BRD230400},
1037 {-1, -1}
1038 };
1039
1040 static int
1041 rpparam(tp, t)
1042 struct tty *tp;
1043 struct termios *t;
1044 {
1045 struct rp_port *rp;
1046 CHANNEL_t *cp;
1047 int oldspl, cflag, iflag, oflag, lflag;
1048 int ospeed;
1049 #ifdef RPCLOCAL
1050 int devshift;
1051 #endif
1052
1053
1054 rp = tp->t_sc;
1055 cp = &rp->rp_channel;
1056 oldspl = spltty();
1057
1058 cflag = t->c_cflag;
1059 #ifdef RPCLOCAL
1060 devshift = umynor / 32;
1061 devshift = 1 << devshift;
1062 if ( devshift & RPCLOCAL ) {
1063 cflag |= CLOCAL;
1064 }
1065 #endif
1066 iflag = t->c_iflag;
1067 oflag = t->c_oflag;
1068 lflag = t->c_lflag;
1069
1070 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1071 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1072 return(EINVAL);
1073
1074 tp->t_ispeed = t->c_ispeed;
1075 tp->t_ospeed = t->c_ospeed;
1076 tp->t_cflag = cflag;
1077 tp->t_iflag = iflag;
1078 tp->t_oflag = oflag;
1079 tp->t_lflag = lflag;
1080
1081 if(t->c_ospeed == 0) {
1082 sClrDTR(cp);
1083 return(0);
1084 }
1085 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1086
1087 /* Set baud rate ----- we only pay attention to ispeed */
1088 sSetDTR(cp);
1089 sSetRTS(cp);
1090 sSetBaud(cp, ospeed);
1091
1092 if(cflag & CSTOPB) {
1093 sSetStop2(cp);
1094 } else {
1095 sSetStop1(cp);
1096 }
1097
1098 if(cflag & PARENB) {
1099 sEnParity(cp);
1100 if(cflag & PARODD) {
1101 sSetOddParity(cp);
1102 } else {
1103 sSetEvenParity(cp);
1104 }
1105 }
1106 else {
1107 sDisParity(cp);
1108 }
1109 if((cflag & CSIZE) == CS8) {
1110 sSetData8(cp);
1111 rp->rp_imask = 0xFF;
1112 } else {
1113 sSetData7(cp);
1114 rp->rp_imask = 0x7F;
1115 }
1116
1117 if(iflag & ISTRIP) {
1118 rp->rp_imask &= 0x7F;
1119 }
1120
1121 if(cflag & CLOCAL) {
1122 rp->rp_intmask &= ~DELTA_CD;
1123 } else {
1124 rp->rp_intmask |= DELTA_CD;
1125 }
1126
1127 /* Put flow control stuff here */
1128
1129 if(cflag & CCTS_OFLOW) {
1130 sEnCTSFlowCtl(cp);
1131 } else {
1132 sDisCTSFlowCtl(cp);
1133 }
1134
1135 if(cflag & CRTS_IFLOW) {
1136 rp->rp_rts_iflow = 1;
1137 } else {
1138 rp->rp_rts_iflow = 0;
1139 }
1140
1141 if(cflag & CRTS_IFLOW) {
1142 sEnRTSFlowCtl(cp);
1143 } else {
1144 sDisRTSFlowCtl(cp);
1145 }
1146 ttyldoptim(tp);
1147
1148 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1149 tp->t_state |= TS_CARR_ON;
1150 wakeup(TSA_CARR_ON(tp));
1151 }
1152
1153 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1154 flags = rp->rp_channel.TxControl[3];
1155 if(flags & SET_DTR)
1156 else
1157 if(flags & SET_RTS)
1158 else
1159 */
1160 splx(oldspl);
1161
1162 return(0);
1163 }
1164
1165 static void
1166 rpstart(tp)
1167 struct tty *tp;
1168 {
1169 struct rp_port *rp;
1170 CHANNEL_t *cp;
1171 struct clist *qp;
1172 char flags;
1173 int spl, xmit_fifo_room;
1174 int i, count, wcount;
1175
1176
1177 rp = tp->t_sc;
1178 cp = &rp->rp_channel;
1179 flags = rp->rp_channel.TxControl[3];
1180 spl = spltty();
1181
1182 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1183 ttwwakeup(tp);
1184 splx(spl);
1185 return;
1186 }
1187 if(rp->rp_xmit_stopped) {
1188 sEnTransmit(cp);
1189 rp->rp_xmit_stopped = 0;
1190 }
1191 count = sGetTxCnt(cp);
1192
1193 if(tp->t_outq.c_cc == 0) {
1194 if((tp->t_state & TS_BUSY) && (count == 0)) {
1195 tp->t_state &= ~TS_BUSY;
1196 }
1197 ttwwakeup(tp);
1198 splx(spl);
1199 return;
1200 }
1201 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1202 qp = &tp->t_outq;
1203 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1204 tp->t_state |= TS_BUSY;
1205 count = q_to_b( qp, rp->TxBuf, xmit_fifo_room );
1206 for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) {
1207 rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i));
1208 }
1209 if ( count & 1 ) {
1210 rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]);
1211 }
1212 }
1213 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1214
1215 ttwwakeup(tp);
1216 splx(spl);
1217 }
1218
1219 static
1220 void
1221 rpstop(tp, flag)
1222 register struct tty *tp;
1223 int flag;
1224 {
1225 struct rp_port *rp;
1226 CHANNEL_t *cp;
1227 int spl;
1228
1229 rp = tp->t_sc;
1230 cp = &rp->rp_channel;
1231
1232 spl = spltty();
1233
1234 if(tp->t_state & TS_BUSY) {
1235 if((tp->t_state&TS_TTSTOP) == 0) {
1236 sFlushTxFIFO(cp);
1237 } else {
1238 if(rp->rp_xmit_stopped == 0) {
1239 sDisTransmit(cp);
1240 rp->rp_xmit_stopped = 1;
1241 }
1242 }
1243 }
1244 splx(spl);
1245 rpstart(tp);
1246 }
Cache object: 49dd79458864d004cb41830f24749537
|