2 * Copyright (c) Comtrol Corporation <support@comtrol.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted prodived that the follwoing conditions
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.
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
32 * $FreeBSD: src/sys/i386/isa/rp.c,v 1.33.2.2 2001/02/26 04:23:10 jlemon Exp $
33 * $DragonFly: src/sys/dev/serial/rp2/Attic/rp.c,v 1.4 2003/07/19 21:14:34 dillon Exp $
37 * rp.c - for RocketPort FreeBSD
40 #include "opt_compat.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/fcntl.h>
45 #include <sys/malloc.h>
49 #include <sys/kernel.h>
51 #include <i386/isa/isa_device.h>
53 #include <pci/pcivar.h>
56 #include <i386/isa/rpreg.h>
57 #include <i386/isa/rpvar.h>
67 static Byte_t RData[RDATASIZE] =
69 0x00, 0x09, 0xf6, 0x82,
70 0x02, 0x09, 0x86, 0xfb,
71 0x04, 0x09, 0x00, 0x0a,
72 0x06, 0x09, 0x01, 0x0a,
73 0x08, 0x09, 0x8a, 0x13,
74 0x0a, 0x09, 0xc5, 0x11,
75 0x0c, 0x09, 0x86, 0x85,
76 0x0e, 0x09, 0x20, 0x0a,
77 0x10, 0x09, 0x21, 0x0a,
78 0x12, 0x09, 0x41, 0xff,
79 0x14, 0x09, 0x82, 0x00,
80 0x16, 0x09, 0x82, 0x7b,
81 0x18, 0x09, 0x8a, 0x7d,
82 0x1a, 0x09, 0x88, 0x81,
83 0x1c, 0x09, 0x86, 0x7a,
84 0x1e, 0x09, 0x84, 0x81,
85 0x20, 0x09, 0x82, 0x7c,
86 0x22, 0x09, 0x0a, 0x0a
89 static Byte_t RRegData[RREGDATASIZE]=
91 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
92 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
93 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
94 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
95 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
96 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
97 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
98 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
99 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
100 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
101 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
102 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
103 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
106 static CONTROLLER_T sController[CTL_SIZE] =
108 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
109 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
110 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
111 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
115 /* IRQ number to MUDBAC register 2 mapping */
118 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
122 static Byte_t sBitMapClrTbl[8] =
124 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
127 static Byte_t sBitMapSetTbl[8] =
129 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
132 /***************************************************************************
133 Function: sInitController
134 Purpose: Initialization of controller global registers and controller
136 Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
137 IRQNum,Frequency,PeriodicOnly)
138 CONTROLLER_T *CtlP; Ptr to controller structure
139 int CtlNum; Controller number
140 ByteIO_t MudbacIO; Mudbac base I/O address.
141 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
142 This list must be in the order the AIOPs will be found on the
143 controller. Once an AIOP in the list is not found, it is
144 assumed that there are no more AIOPs on the controller.
145 int AiopIOListSize; Number of addresses in AiopIOList
146 int IRQNum; Interrupt Request number. Can be any of the following:
147 0: Disable global interrupts
156 Byte_t Frequency: A flag identifying the frequency
157 of the periodic interrupt, can be any one of the following:
158 FREQ_DIS - periodic interrupt disabled
159 FREQ_137HZ - 137 Hertz
165 If IRQNum is set to 0 the Frequency parameter is
166 overidden, it is forced to a value of FREQ_DIS.
167 int PeriodicOnly: TRUE if all interrupts except the periodic
168 interrupt are to be blocked.
169 FALSE is both the periodic interrupt and
170 other channel interrupts are allowed.
171 If IRQNum is set to 0 the PeriodicOnly parameter is
172 overidden, it is forced to a value of FALSE.
173 Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
174 initialization failed.
177 If periodic interrupts are to be disabled but AIOP interrupts
178 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
180 If interrupts are to be completely disabled set IRQNum to 0.
182 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
185 This function performs initialization of global interrupt modes,
186 but it does not actually enable global interrupts. To enable
187 and disable global interrupts use functions sEnGlobalInt() and
188 sDisGlobalInt(). Enabling of global interrupts is normally not
189 done until all other initializations are complete.
191 Even if interrupts are globally enabled, they must also be
192 individually enabled for each channel that is to generate
195 Warnings: No range checking on any of the parameters is done.
197 No context switches are allowed while executing this function.
199 After this function all AIOPs on the controller are disabled,
200 they can be enabled with sEnAiop().
202 int sInitController( CONTROLLER_T *CtlP,
205 ByteIO_t *AiopIOList,
214 CtlP->CtlNum = CtlNum;
215 CtlP->BusType = isISA;
216 CtlP->CtlID = CTLID_0001; /* controller release 1 */
218 CtlP->MBaseIO = MudbacIO;
219 CtlP->MReg1IO = MudbacIO + 1;
220 CtlP->MReg2IO = MudbacIO + 2;
221 CtlP->MReg3IO = MudbacIO + 3;
223 CtlP->MReg2 = 0; /* interrupt disable */
224 CtlP->MReg3 = 0; /* no periodic interrupts */
226 if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */
228 CtlP->MReg2 = 0; /* interrupt disable */
229 CtlP->MReg3 = 0; /* no periodic interrupts */
233 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
234 CtlP->MReg3 = Frequency; /* set frequency */
235 if(PeriodicOnly) /* periodic interrupt only */
237 CtlP->MReg3 |= PERIODIC_ONLY;
241 sOutB(CtlP->MReg2IO,CtlP->MReg2);
242 sOutB(CtlP->MReg3IO,CtlP->MReg3);
243 sControllerEOI(CtlP); /* clear EOI if warm init */
247 for(i=0; i < AiopIOListSize; i++)
250 CtlP->AiopIO[i] = (WordIO_t)io;
251 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
252 sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
253 sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
254 sEnAiop(CtlP,i); /* enable the AIOP */
256 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
257 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
259 sDisAiop(CtlP,i); /* disable AIOP */
260 break; /* done looking for AIOPs */
263 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
264 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
265 sOutB(io + _INDX_DATA,CLOCK_PRESC);
266 CtlP->NumAiop++; /* bump count of AIOPs */
267 sDisAiop(CtlP,i); /* disable AIOP */
270 if(CtlP->NumAiop == 0)
273 return(CtlP->NumAiop);
276 int sPCIInitController( CONTROLLER_T *CtlP,
278 ByteIO_t *AiopIOList,
287 CtlP->CtlNum = CtlNum;
288 CtlP->BusType = isPCI;
289 CtlP->CtlID = CTLID_0001; /* controller release 1 */
290 CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
292 sPCIControllerEOI(CtlP);
296 for(i=0; i < AiopIOListSize; i++)
299 CtlP->AiopIO[i] = (WordIO_t)io;
300 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
302 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
303 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
305 break; /* done looking for AIOPs */
308 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
309 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
310 sOutB(io + _INDX_DATA,CLOCK_PRESC);
311 CtlP->NumAiop++; /* bump count of AIOPs */
314 if(CtlP->NumAiop == 0)
317 return(CtlP->NumAiop);
320 /***************************************************************************
321 Function: sReadAiopID
322 Purpose: Read the AIOP idenfication number directly from an AIOP.
323 Call: sReadAiopID(io)
324 ByteIO_t io: AIOP base I/O address
325 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
326 is replace by an identifying number.
327 Flag AIOPID_NULL if no valid AIOP is found
328 Warnings: No context switches are allowed while executing this function.
331 int sReadAiopID(ByteIO_t io)
333 Byte_t AiopID; /* ID byte from AIOP */
335 sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */
336 sOutB(io + _CMD_REG,0x0);
337 AiopID = sInB(io + _CHN_STAT0) & 0x07;
340 else /* AIOP does not exist */
344 /***************************************************************************
345 Function: sReadAiopNumChan
346 Purpose: Read the number of channels available in an AIOP directly from
348 Call: sReadAiopNumChan(io)
349 WordIO_t io: AIOP base I/O address
350 Return: int: The number of channels available
351 Comments: The number of channels is determined by write/reads from identical
352 offsets within the SRAM address spaces for channels 0 and 4.
353 If the channel 4 space is mirrored to channel 0 it is a 4 channel
354 AIOP, otherwise it is an 8 channel.
355 Warnings: No context switches are allowed while executing this function.
357 int sReadAiopNumChan(WordIO_t io)
361 sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
362 sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */
363 x = sInW(io + _INDX_DATA);
364 sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
365 if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
371 /***************************************************************************
373 Purpose: Initialization of a channel and channel structure
374 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
375 CONTROLLER_T *CtlP; Ptr to controller structure
376 CHANNEL_T *ChP; Ptr to channel structure
377 int AiopNum; AIOP number within controller
378 int ChanNum; Channel number within AIOP
379 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
380 number exceeds number of channels available in AIOP.
381 Comments: This function must be called before a channel can be used.
382 Warnings: No range checking on any of the parameters is done.
384 No context switches are allowed while executing this function.
386 int sInitChan( CONTROLLER_T *CtlP,
398 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
399 return(FALSE); /* exceeds num chans in AIOP */
401 /* Channel, AIOP, and controller identifiers */
403 ChP->ChanID = CtlP->AiopID[AiopNum];
404 ChP->AiopNum = AiopNum;
405 ChP->ChanNum = ChanNum;
407 /* Global direct addresses */
408 AiopIO = CtlP->AiopIO[AiopNum];
409 ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
410 ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
411 ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
412 ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
413 ChP->IndexData = AiopIO + _INDX_DATA;
415 /* Channel direct addresses */
416 ChIOOff = AiopIO + ChP->ChanNum * 2;
417 ChP->TxRxData = ChIOOff + _TD0;
418 ChP->ChanStat = ChIOOff + _CHN_STAT0;
419 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
420 ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
422 /* Initialize the channel from the RData array */
423 for(i=0; i < RDATASIZE; i+=4)
426 R[1] = RData[i+1] + 0x10 * ChanNum;
429 sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
433 for(i=0; i < RREGDATASIZE; i+=4)
435 ChR[i] = RRegData[i];
436 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
437 ChR[i+2] = RRegData[i+2];
438 ChR[i+3] = RRegData[i+3];
441 /* Indexed registers */
442 ChOff = (Word_t)ChanNum * 0x1000;
444 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
445 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
446 ChP->BaudDiv[2] = (Byte_t)BRD9600;
447 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
448 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
450 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
451 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
452 ChP->TxControl[2] = 0;
453 ChP->TxControl[3] = 0;
454 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
456 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
457 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
458 ChP->RxControl[2] = 0;
459 ChP->RxControl[3] = 0;
460 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
462 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
463 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
464 ChP->TxEnables[2] = 0;
465 ChP->TxEnables[3] = 0;
466 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
468 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
469 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
470 ChP->TxCompare[2] = 0;
471 ChP->TxCompare[3] = 0;
472 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
474 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
475 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
476 ChP->TxReplace1[2] = 0;
477 ChP->TxReplace1[3] = 0;
478 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
480 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
481 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
482 ChP->TxReplace2[2] = 0;
483 ChP->TxReplace2[3] = 0;
484 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
486 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
487 ChP->TxFIFO = ChOff + _TX_FIFO;
489 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
490 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
491 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
492 sOutW(ChP->IndexData,0);
493 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
494 ChP->RxFIFO = ChOff + _RX_FIFO;
496 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
497 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
498 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
499 sOutW(ChP->IndexData,0);
500 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
501 sOutW(ChP->IndexData,0);
502 ChP->TxPrioCnt = ChOff + _TXP_CNT;
503 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
504 sOutB(ChP->IndexData,0);
505 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
506 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
507 sOutB(ChP->IndexData,0);
508 ChP->TxPrioBuf = ChOff + _TXP_BUF;
509 sEnRxProcessor(ChP); /* start the Rx processor */
514 /***************************************************************************
515 Function: sStopRxProcessor
516 Purpose: Stop the receive processor from processing a channel.
517 Call: sStopRxProcessor(ChP)
518 CHANNEL_T *ChP; Ptr to channel structure
520 Comments: The receive processor can be started again with sStartRxProcessor().
521 This function causes the receive processor to skip over the
522 stopped channel. It does not stop it from processing other channels.
524 Warnings: No context switches are allowed while executing this function.
526 Do not leave the receive processor stopped for more than one
529 After calling this function a delay of 4 uS is required to ensure
530 that the receive processor is no longer processing this channel.
532 void sStopRxProcessor(CHANNEL_T *ChP)
540 sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
543 /***************************************************************************
544 Function: sFlushRxFIFO
545 Purpose: Flush the Rx FIFO
546 Call: sFlushRxFIFO(ChP)
547 CHANNEL_T *ChP; Ptr to channel structure
549 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
550 while it is being flushed the receive processor is stopped
551 and the transmitter is disabled. After these operations a
552 4 uS delay is done before clearing the pointers to allow
553 the receive processor to stop. These items are handled inside
555 Warnings: No context switches are allowed while executing this function.
557 void sFlushRxFIFO(CHANNEL_T *ChP)
560 Byte_t Ch; /* channel number within AIOP */
561 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
563 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
564 return; /* don't need to flush */
566 RxFIFOEnabled = FALSE;
567 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
569 RxFIFOEnabled = TRUE;
570 sDisRxFIFO(ChP); /* disable it */
571 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
572 sInB(ChP->IntChan); /* depends on bus i/o timing */
574 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
575 Ch = (Byte_t)sGetChanNum(ChP);
576 sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
577 sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */
578 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
579 sOutW(ChP->IndexData,0);
580 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
581 sOutW(ChP->IndexData,0);
583 sEnRxFIFO(ChP); /* enable Rx FIFO */
586 /***************************************************************************
587 Function: sFlushTxFIFO
588 Purpose: Flush the Tx FIFO
589 Call: sFlushTxFIFO(ChP)
590 CHANNEL_T *ChP; Ptr to channel structure
592 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
593 while it is being flushed the receive processor is stopped
594 and the transmitter is disabled. After these operations a
595 4 uS delay is done before clearing the pointers to allow
596 the receive processor to stop. These items are handled inside
598 Warnings: No context switches are allowed while executing this function.
600 void sFlushTxFIFO(CHANNEL_T *ChP)
603 Byte_t Ch; /* channel number within AIOP */
604 int TxEnabled; /* TRUE if transmitter enabled */
606 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
607 return; /* don't need to flush */
610 if(ChP->TxControl[3] & TX_ENABLE)
613 sDisTransmit(ChP); /* disable transmitter */
615 sStopRxProcessor(ChP); /* stop Rx processor */
616 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
617 sInB(ChP->IntChan); /* depends on bus i/o timing */
618 Ch = (Byte_t)sGetChanNum(ChP);
619 sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
620 sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */
621 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
622 sOutW(ChP->IndexData,0);
624 sEnTransmit(ChP); /* enable transmitter */
625 sStartRxProcessor(ChP); /* restart Rx processor */
628 /***************************************************************************
629 Function: sWriteTxPrioByte
630 Purpose: Write a byte of priority transmit data to a channel
631 Call: sWriteTxPrioByte(ChP,Data)
632 CHANNEL_T *ChP; Ptr to channel structure
633 Byte_t Data; The transmit data byte
635 Return: int: 1 if the bytes is successfully written, otherwise 0.
637 Comments: The priority byte is transmitted before any data in the Tx FIFO.
639 Warnings: No context switches are allowed while executing this function.
641 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
643 Byte_t DWBuf[4]; /* buffer for double word writes */
644 Word_t *WordPtr; /* must be far because Win SS != DS */
645 register DWordIO_t IndexAddr;
647 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
649 IndexAddr = ChP->IndexAddr;
650 sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
651 if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
652 return(0); /* nothing sent */
654 WordPtr = (Word_t *)(&DWBuf[0]);
655 *WordPtr = ChP->TxPrioBuf; /* data byte address */
657 DWBuf[2] = Data; /* data byte value */
658 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
660 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
662 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
663 DWBuf[3] = 0; /* priority buffer pointer */
664 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
666 else /* write it to Tx FIFO */
668 sWriteTxByte(sGetTxRxDataIO(ChP),Data);
670 return(1); /* 1 byte sent */
673 /***************************************************************************
674 Function: sEnInterrupts
675 Purpose: Enable one or more interrupts for a channel
676 Call: sEnInterrupts(ChP,Flags)
677 CHANNEL_T *ChP; Ptr to channel structure
678 Word_t Flags: Interrupt enable flags, can be any combination
679 of the following flags:
680 TXINT_EN: Interrupt on Tx FIFO empty
681 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
683 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
684 MCINT_EN: Interrupt on modem input change
685 CHANINT_EN: Allow channel interrupt signal to the AIOP's
686 Interrupt Channel Register.
688 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
689 enabled. If an interrupt enable flag is not set in Flags, that
690 interrupt will not be changed. Interrupts can be disabled with
691 function sDisInterrupts().
693 This function sets the appropriate bit for the channel in the AIOP's
694 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
695 this channel's bit to be set in the AIOP's Interrupt Channel Register.
697 Interrupts must also be globally enabled before channel interrupts
698 will be passed on to the host. This is done with function
701 In some cases it may be desirable to disable interrupts globally but
702 enable channel interrupts. This would allow the global interrupt
703 status register to be used to determine which AIOPs need service.
705 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
707 Byte_t Mask; /* Interrupt Mask Register */
710 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
712 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
714 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
716 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
718 if(Flags & CHANINT_EN)
720 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
721 sOutB(ChP->IntMask,Mask);
725 /***************************************************************************
726 Function: sDisInterrupts
727 Purpose: Disable one or more interrupts for a channel
728 Call: sDisInterrupts(ChP,Flags)
729 CHANNEL_T *ChP; Ptr to channel structure
730 Word_t Flags: Interrupt flags, can be any combination
731 of the following flags:
732 TXINT_EN: Interrupt on Tx FIFO empty
733 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
735 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
736 MCINT_EN: Interrupt on modem input change
737 CHANINT_EN: Disable channel interrupt signal to the
738 AIOP's Interrupt Channel Register.
740 Comments: If an interrupt flag is set in Flags, that interrupt will be
741 disabled. If an interrupt flag is not set in Flags, that
742 interrupt will not be changed. Interrupts can be enabled with
743 function sEnInterrupts().
745 This function clears the appropriate bit for the channel in the AIOP's
746 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
747 this channel's bit from being set in the AIOP's Interrupt Channel
750 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
752 Byte_t Mask; /* Interrupt Mask Register */
755 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
756 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
757 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
758 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
760 if(Flags & CHANINT_EN)
762 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
763 sOutB(ChP->IntMask,Mask);
767 /*********************************************************************
768 Begin FreeBsd-specific driver code
769 **********************************************************************/
771 static int rpprobe __P((struct isa_device *));
772 static int rpattach __P((struct isa_device *));
774 static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
775 static void rp_pciattach(pcici_t tag, int unit);
776 static u_long rp_pcicount;
778 static struct pci_device rp_pcidevice = {
786 COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
788 static timeout_t rpdtrwakeup;
790 struct isa_driver rpdriver = {
791 rpprobe, rpattach, "rp"
794 static char driver_name[] = "rp";
796 static d_open_t rpopen;
797 static d_close_t rpclose;
798 static d_write_t rpwrite;
799 static d_ioctl_t rpioctl;
801 #define CDEV_MAJOR 81
802 static struct cdevsw rp_cdevsw = {
810 /* strategy */ nostrategy,
811 /* name */ driver_name,
812 /* maj */ CDEV_MAJOR,
815 /* flags */ D_TTY | D_KQFILTER,
817 /* kqfilter */ ttykqfilter,
820 static int rp_controller_port = 0;
821 static int rp_num_ports_open = 0;
822 static int ndevs = 0;
823 static int minor_to_unit[128];
825 static struct tty rp_tty[128];
828 static int rp_num_ports[4]; /* Number of ports on each controller */
830 #define _INLINE_ __inline
831 #define POLL_INTERVAL 1
833 #define CALLOUT_MASK 0x80
834 #define CONTROL_MASK 0x60
835 #define CONTROL_INIT_STATE 0x20
836 #define CONTROL_LOCK_STATE 0x40
837 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
838 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
839 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
840 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
841 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
843 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
844 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
845 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
847 static struct rp_port *p_rp_addr[4];
848 static struct rp_port *p_rp_table[MAX_RP_PORTS];
849 #define rp_addr(unit) (p_rp_addr[unit])
850 #define rp_table(port) (p_rp_table[port])
853 * The top-level routines begin here
856 static int rpparam __P((struct tty *, struct termios *));
857 static void rpstart __P((struct tty *));
858 static void rpstop __P((struct tty *, int));
859 static void rphardclose __P((struct rp_port *));
860 static void rp_disc_optim __P((struct tty *tp, struct termios *t,
861 struct rp_port *rp));
863 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
864 CHANNEL_t *cp, unsigned int ChanStatus)
867 unsigned int CharNStat;
870 ToRecv = sGetRxCnt(cp);
874 /* If status indicates there are errored characters in the
875 FIFO, then enter status mode (a word in FIFO holds
876 characters and status)
879 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
880 if(!(ChanStatus & STATMODE)) {
881 ChanStatus |= STATMODE;
886 if we previously entered status mode then read down the
887 FIFO one word at a time, pulling apart the character and
888 the status. Update error counters depending on status.
890 if(ChanStatus & STATMODE) {
892 if(tp->t_state & TS_TBLOCK) {
895 CharNStat = sInW(sGetTxRxDataIO(cp));
896 ch = CharNStat & 0xff;
898 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
900 else if (CharNStat & STMPARITYH)
902 else if (CharNStat & STMRCVROVRH)
905 (*linesw[tp->t_line].l_rint)(ch, tp);
909 After emtying FIFO in status mode, turn off status mode
912 if(sGetRxCnt(cp) == 0)
913 sDisRxStatusMode(cp);
917 if(tp->t_state & TS_TBLOCK) {
920 ch = (u_char) sInB(sGetTxRxDataIO(cp));
922 (*linesw[tp->t_line].l_rint)(ch, tp);
929 static _INLINE_ void rp_handle_port(struct rp_port *rp)
933 unsigned int IntMask, ChanStatus;
939 cp = &rp->rp_channel;
941 IntMask = sGetChanIntID(cp);
942 IntMask = IntMask & rp->rp_intmask;
943 ChanStatus = sGetChanStatus(cp);
944 if(IntMask & RXF_TRIG)
945 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
946 rp_do_receive(rp, tp, cp, ChanStatus);
948 if(IntMask & DELTA_CD) {
949 if(ChanStatus & CD_ACT) {
950 if(!(tp->t_state & TS_CARR_ON) ) {
951 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
954 if((tp->t_state & TS_CARR_ON)) {
955 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
956 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
962 /* oldcts = rp->rp_cts;
963 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
964 if(oldcts != rp->rp_cts) {
965 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
970 static void rp_do_poll(void *not_used)
975 int unit, aiop, ch, line, count;
976 unsigned char CtlMask, AiopMask;
978 for(unit = 0; unit <= ndevs; unit++) {
981 if(ctl->BusType == isPCI)
982 CtlMask = sPCIGetControllerIntStatus(ctl);
984 CtlMask = sGetControllerIntStatus(ctl);
985 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
987 AiopMask = sGetAiopIntStatus(ctl, aiop);
988 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
990 line = (unit << 5) | (aiop << 3) | ch;
998 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
1001 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1002 count = sGetTxCnt(&rp->rp_channel);
1004 tp->t_state &= ~(TS_BUSY);
1005 if(!(tp->t_state & TS_TTSTOP) &&
1006 (count <= rp->rp_restart)) {
1007 (*linesw[tp->t_line].l_start)(tp);
1012 if(rp_num_ports_open)
1013 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1017 rp_pciprobe(pcici_t tag, pcidi_t type)
1021 vendor_id = type & 0xffff;
1031 struct isa_device *dev;
1033 int controller, unit;
1034 int aiop, num_aiops;
1035 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1038 unit = dev->id_unit;
1039 if (dev->id_unit >= 4) {
1040 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1043 printf("probing for RocketPort(ISA) unit %d\n", unit);
1044 if (rp_controller_port)
1045 controller = rp_controller_port;
1047 controller = dev->id_iobase + 0x40;
1050 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1051 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1053 ctlp = sCtlNumToCtlPtr(dev->id_unit);
1054 num_aiops = sInitController(ctlp, dev->id_unit,
1055 controller + ((unit-rp_pcicount)*0x400),
1056 aiopio, MAX_AIOPS_PER_BOARD, 0,
1058 if (num_aiops <= 0) {
1059 printf("board%d init failed\n", unit);
1063 if (rp_controller_port) {
1067 rp_controller_port = controller;
1076 rp_pciattach(pcici_t tag, int unit)
1078 int success, oldspl;
1080 int num_ports, num_chan, num_aiops;
1081 int aiop, chan, port;
1082 int ChanStatus, line, i, count;
1083 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1088 success = pci_map_port(tag, 0x10, &iobase);
1090 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1092 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1093 aiopio[aiop] = iobase + (aiop * 0x40);
1095 ctlp = sCtlNumToCtlPtr(unit);
1096 num_aiops = sPCIInitController(ctlp, unit,
1097 aiopio, MAX_AIOPS_PER_BOARD, 0,
1101 for(aiop=0; aiop < num_aiops; aiop++) {
1102 sResetAiopByNum(ctlp, aiop);
1103 num_ports += sGetAiopNumChan(ctlp, aiop);
1105 printf("RocketPort%d = %d ports\n", unit, num_ports);
1106 rp_num_ports[unit] = num_ports;
1108 rp = (struct rp_port *)
1109 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1111 printf("rp_attach: Could not malloc rp_ports structures\n");
1115 count = unit * 32; /* board times max ports per card SG */
1116 for(i=count;i < (count + rp_num_ports[unit]);i++)
1117 minor_to_unit[i] = unit;
1119 bzero(rp, sizeof(struct rp_port) * num_ports);
1120 tty = (struct tty *)
1121 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1123 printf("rp_attach: Could not malloc tty structures\n");
1126 bzero(tty, sizeof(struct tty) * num_ports);
1132 cdevsw_add(&rp_cdevsw);
1135 for(aiop=0; aiop < num_aiops; aiop++) {
1136 num_chan = sGetAiopNumChan(ctlp, aiop);
1137 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1146 /* tty->t_termios = deftermios;
1148 rp->dtr_wait = 3 * hz;
1149 rp->it_in.c_iflag = 0;
1150 rp->it_in.c_oflag = 0;
1151 rp->it_in.c_cflag = TTYDEF_CFLAG;
1152 rp->it_in.c_lflag = 0;
1153 termioschars(&rp->it_in);
1154 /* termioschars(&tty->t_termios);
1156 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1157 rp->it_out = rp->it_in;
1159 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1160 DELTA_CD | DELTA_CTS | DELTA_DSR;
1161 ChanStatus = sGetChanStatus(&rp->rp_channel);
1162 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1163 printf("RocketPort sInitChan(%d, %d, %d) failed
1164 \n", unit, aiop, chan);
1167 ChanStatus = sGetChanStatus(&rp->rp_channel);
1168 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1169 line = (unit << 5) | (aiop << 3) | chan;
1170 rp_table(line) = rp;
1178 struct isa_device *dev;
1180 int iobase, unit, /*rpmajor,*/ oldspl;
1181 int num_ports, num_chan, num_aiops;
1182 int aiop, chan, port;
1183 int ChanStatus, line, i, count;
1184 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1189 iobase = dev->id_iobase;
1190 unit = dev->id_unit;
1193 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1194 aiopio[aiop] = iobase + (aiop * 0x400);
1196 ctlp = sCtlNumToCtlPtr(unit);
1197 num_aiops = sInitController(ctlp, unit,
1198 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1199 aiopio, MAX_AIOPS_PER_BOARD, 0,
1203 for(aiop=0; aiop < num_aiops; aiop++) {
1204 sResetAiopByNum(ctlp, aiop);
1205 sEnAiop(ctlp, aiop);
1206 num_ports += sGetAiopNumChan(ctlp, aiop);
1208 printf("RocketPort%d = %d ports\n", unit, num_ports);
1209 rp_num_ports[unit] = num_ports;
1211 rp = (struct rp_port *)
1212 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1214 printf("rp_attach: Could not malloc rp_ports structures\n");
1218 count = unit * 32; /* board # times max ports per card SG */
1219 for(i=count;i < (count + rp_num_ports[unit]);i++)
1220 minor_to_unit[i] = unit;
1222 bzero(rp, sizeof(struct rp_port) * num_ports);
1223 tty = (struct tty *)
1224 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1226 printf("rp_attach: Could not malloc tty structures\n");
1229 bzero(tty, sizeof(struct tty) * num_ports);
1235 cdevsw_add(&rp_cdevsw);
1238 for(aiop=0; aiop < num_aiops; aiop++) {
1239 num_chan = sGetAiopNumChan(ctlp, aiop);
1240 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1249 /* tty->t_termios = deftermios;
1251 rp->dtr_wait = 3 * hz;
1252 rp->it_in.c_iflag = 0;
1253 rp->it_in.c_oflag = 0;
1254 rp->it_in.c_cflag = TTYDEF_CFLAG;
1255 rp->it_in.c_lflag = 0;
1256 termioschars(&rp->it_in);
1257 /* termioschars(&tty->t_termios);
1259 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1260 rp->it_out = rp->it_in;
1262 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1263 DELTA_CD | DELTA_CTS | DELTA_DSR;
1264 ChanStatus = sGetChanStatus(&rp->rp_channel);
1265 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1266 printf("RocketPort sInitChan(%d, %d, %d) failed
1267 \n", unit, aiop, chan);
1270 ChanStatus = sGetChanStatus(&rp->rp_channel);
1271 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1272 line = (unit << 5) | (aiop << 3) | chan;
1273 rp_table(line) = rp;
1281 rpopen(dev, flag, mode, p)
1287 int unit, port, mynor, umynor, flags; /* SG */
1290 unsigned int IntMask, ChanStatus;
1293 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1294 port = (minor(dev) & 0x1f); /* SG */
1295 mynor = (port + umynor); /* SG */
1296 unit = minor_to_unit[mynor];
1297 if (rp_addr(unit) == NULL)
1301 rp = rp_addr(unit) + port;
1302 /* rp->rp_tty = &rp_tty[rp->rp_port];
1310 while(rp->state & ~SET_DTR) {
1311 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
1316 if(tp->t_state & TS_ISOPEN) {
1317 if(IS_CALLOUT(dev)) {
1318 if(!rp->active_out) {
1323 if(rp->active_out) {
1324 if(flag & O_NONBLOCK) {
1328 error = tsleep(&rp->active_out,
1335 if(tp->t_state & TS_XCLUDE &&
1343 tp->t_param = rpparam;
1344 tp->t_oproc = rpstart;
1345 tp->t_stop = rpstop;
1347 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1351 rp->rp_channel.TxControl[3] =
1352 ((rp->rp_channel.TxControl[3]
1353 & ~(SET_RTS | SET_DTR)) | flags);
1354 sOutDW(rp->rp_channel.IndexAddr,
1355 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1356 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1357 sDisRxStatusMode(&rp->rp_channel);
1358 sFlushRxFIFO(&rp->rp_channel);
1359 sFlushTxFIFO(&rp->rp_channel);
1361 sEnInterrupts(&rp->rp_channel,
1362 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1363 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1365 sDisRxStatusMode(&rp->rp_channel);
1366 sClrTxXOFF(&rp->rp_channel);
1368 /* sDisRTSFlowCtl(&rp->rp_channel);
1369 sDisCTSFlowCtl(&rp->rp_channel);
1371 sDisTxSoftFlowCtl(&rp->rp_channel);
1373 sStartRxProcessor(&rp->rp_channel);
1375 sEnRxFIFO(&rp->rp_channel);
1376 sEnTransmit(&rp->rp_channel);
1378 /* sSetDTR(&rp->rp_channel);
1379 sSetRTS(&rp->rp_channel);
1383 error = rpparam(tp, &tp->t_termios);
1390 rp_num_ports_open++;
1392 IntMask = sGetChanIntID(&rp->rp_channel);
1393 IntMask = IntMask & rp->rp_intmask;
1394 ChanStatus = sGetChanStatus(&rp->rp_channel);
1395 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1396 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1397 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1401 if(rp_num_ports_open == 1)
1402 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1406 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1407 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1409 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
1415 error = (*linesw[tp->t_line].l_open)(dev, tp);
1417 rp_disc_optim(tp, &tp->t_termios, rp);
1418 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1419 rp->active_out = TRUE;
1421 /* if(rp_num_ports_open == 1)
1422 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1426 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1433 rpclose(dev, flag, mode, p)
1438 int oldspl, unit, mynor, umynor, port; /* SG */
1443 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1444 port = (minor(dev) & 0x1f); /* SG */
1445 mynor = (port + umynor); /* SG */
1446 unit = minor_to_unit[mynor]; /* SG */
1450 rp = rp_addr(unit) + port;
1451 cp = &rp->rp_channel;
1455 (*linesw[tp->t_line].l_close)(tp, flag);
1456 rp_disc_optim(tp, &tp->t_termios, rp);
1457 rpstop(tp, FREAD | FWRITE);
1460 tp->t_state &= ~TS_BUSY;
1469 rphardclose(struct rp_port *rp)
1475 cp = &rp->rp_channel;
1477 mynor = MINOR_MAGIC(tp->t_dev);
1482 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1485 sDisTxSoftFlowCtl(cp);
1488 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1491 if(IS_CALLOUT(tp->t_dev)) {
1494 if(rp->dtr_wait != 0) {
1495 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1496 rp->state |= ~SET_DTR;
1499 rp->active_out = FALSE;
1500 wakeup(&rp->active_out);
1501 wakeup(TSA_CARR_ON(tp));
1506 rpwrite(dev, uio, flag)
1513 int unit, mynor, port, umynor, error = 0; /* SG */
1515 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1516 port = (minor(dev) & 0x1f); /* SG */
1517 mynor = (port + umynor); /* SG */
1518 unit = minor_to_unit[mynor]; /* SG */
1522 rp = rp_addr(unit) + port;
1524 while(rp->rp_disable_writes) {
1526 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
1531 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1536 rpdtrwakeup(void *chan)
1540 rp = (struct rp_port *)chan;
1541 rp->state &= SET_DTR;
1542 wakeup(&rp->dtr_wait);
1546 rpioctl(dev, cmd, data, flag, p)
1556 int unit, mynor, port, umynor; /* SG */
1559 int arg, flags, result, ChanStatus;
1561 struct termios term, *t;
1563 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1564 port = (minor(dev) & 0x1f); /* SG */
1565 mynor = (port + umynor); /* SG */
1566 unit = minor_to_unit[mynor];
1567 rp = rp_addr(unit) + port;
1569 if(IS_CONTROL(dev)) {
1572 switch (IS_CONTROL(dev)) {
1573 case CONTROL_INIT_STATE:
1574 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1576 case CONTROL_LOCK_STATE:
1577 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1580 return(ENODEV); /* /dev/nodev */
1587 *ct = *(struct termios *)data;
1590 *(struct termios *)data = *ct;
1593 *(int *)data = TTYDISC;
1596 bzero(data, sizeof(struct winsize));
1604 cp = &rp->rp_channel;
1606 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1607 term = tp->t_termios;
1609 error = ttsetcompat(tp, &cmd, data, &term);
1613 data = (caddr_t)&term;
1616 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1618 struct termios *dt = (struct termios *)data;
1619 struct termios *lt = IS_CALLOUT(dev)
1620 ? &rp->lt_out : &rp->lt_in;
1622 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1623 | (dt->c_iflag & ~lt->c_iflag);
1624 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1625 | (dt->c_oflag & ~lt->c_oflag);
1626 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1627 | (dt->c_cflag & ~lt->c_cflag);
1628 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1629 | (dt->c_lflag & ~lt->c_lflag);
1630 for(cc = 0; cc < NCCS; ++cc)
1631 if(lt->c_cc[cc] != 0)
1632 dt->c_cc[cc] = tp->t_cc[cc];
1633 if(lt->c_ispeed != 0)
1634 dt->c_ispeed = tp->t_ispeed;
1635 if(lt->c_ospeed != 0)
1636 dt->c_ospeed = tp->t_ospeed;
1641 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1642 if(error != ENOIOCTL) {
1647 flags = rp->rp_channel.TxControl[3];
1649 error = ttioctl(tp, cmd, data, flag);
1650 flags = rp->rp_channel.TxControl[3];
1651 rp_disc_optim(tp, &tp->t_termios, rp);
1652 if(error != ENOIOCTL) {
1658 sSendBreak(&rp->rp_channel);
1662 sClrBreak(&rp->rp_channel);
1666 sSetDTR(&rp->rp_channel);
1667 sSetRTS(&rp->rp_channel);
1671 sClrDTR(&rp->rp_channel);
1675 arg = *(int *) data;
1681 rp->rp_channel.TxControl[3] =
1682 ((rp->rp_channel.TxControl[3]
1683 & ~(SET_RTS | SET_DTR)) | flags);
1684 sOutDW(rp->rp_channel.IndexAddr,
1685 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1688 arg = *(int *) data;
1694 rp->rp_channel.TxControl[3] |= flags;
1695 sOutDW(rp->rp_channel.IndexAddr,
1696 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1699 arg = *(int *) data;
1705 rp->rp_channel.TxControl[3] &= ~flags;
1706 sOutDW(rp->rp_channel.IndexAddr,
1707 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1712 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1713 flags = rp->rp_channel.TxControl[3];
1714 result = TIOCM_LE; /* always on while open for some reason */
1715 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1716 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1717 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1718 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1719 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1721 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1723 result |= TIOCM_RTS;
1726 *(int *)data = result;
1734 rp->dtr_wait = *(int *)data * hz/100;
1737 *(int *)data = rp->dtr_wait * 100/hz;
1747 static struct speedtab baud_table[] = {
1748 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1749 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1750 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1751 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1752 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1753 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1754 {B57600, BRD57600}, {B76800, BRD76800},
1755 {B115200, BRD115200}, {B230400, BRD230400},
1766 int unit, mynor, port, umynor; /* SG */
1767 int oldspl, cflag, iflag, oflag, lflag;
1771 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1772 port = (minor(tp->t_dev) & 0x1f); /* SG */
1773 mynor = (port + umynor); /* SG */
1775 unit = minor_to_unit[mynor];
1776 rp = rp_addr(unit) + port;
1777 cp = &rp->rp_channel;
1785 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1786 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1789 tp->t_ispeed = t->c_ispeed;
1790 tp->t_ospeed = t->c_ospeed;
1791 tp->t_cflag = cflag;
1792 tp->t_iflag = iflag;
1793 tp->t_oflag = oflag;
1794 tp->t_lflag = lflag;
1796 if(t->c_ospeed == 0) {
1800 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1802 /* Set baud rate ----- we only pay attention to ispeed */
1805 sSetBaud(cp, ospeed);
1807 if(cflag & CSTOPB) {
1813 if(cflag & PARENB) {
1815 if(cflag & PARODD) {
1824 if((cflag & CSIZE) == CS8) {
1826 rp->rp_imask = 0xFF;
1829 rp->rp_imask = 0x7F;
1832 if(iflag & ISTRIP) {
1833 rp->rp_imask &= 0x7F;
1836 if(cflag & CLOCAL) {
1837 rp->rp_intmask &= ~DELTA_CD;
1839 rp->rp_intmask |= DELTA_CD;
1842 /* Put flow control stuff here */
1844 if(cflag & CCTS_OFLOW) {
1850 if(cflag & CRTS_IFLOW) {
1851 rp->rp_rts_iflow = 1;
1853 rp->rp_rts_iflow = 0;
1856 if(cflag & CRTS_IFLOW) {
1861 rp_disc_optim(tp, t, rp);
1863 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1864 tp->t_state |= TS_CARR_ON;
1865 wakeup(TSA_CARR_ON(tp));
1868 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1869 flags = rp->rp_channel.TxControl[3];
1881 rp_disc_optim(tp, t, rp)
1886 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1887 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1888 &&(!(t->c_iflag & PARMRK)
1889 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1890 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1891 && linesw[tp->t_line].l_rint == ttyinput)
1892 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1894 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1904 int unit, mynor, port, umynor; /* SG */
1906 int spl, xmit_fifo_room;
1910 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1911 port = (minor(tp->t_dev) & 0x1f); /* SG */
1912 mynor = (port + umynor); /* SG */
1913 unit = minor_to_unit[mynor];
1914 rp = rp_addr(unit) + port;
1915 cp = &rp->rp_channel;
1916 flags = rp->rp_channel.TxControl[3];
1919 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1924 if(rp->rp_xmit_stopped) {
1926 rp->rp_xmit_stopped = 0;
1928 count = sGetTxCnt(cp);
1930 if(tp->t_outq.c_cc == 0) {
1931 if((tp->t_state & TS_BUSY) && (count == 0)) {
1932 tp->t_state &= ~TS_BUSY;
1938 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1941 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1942 tp->t_state |= TS_BUSY;
1944 while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1946 sOutB(sGetTxRxDataIO(cp), ch);
1950 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1959 register struct tty *tp;
1964 int unit, mynor, port, umynor; /* SG */
1967 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1968 port = (minor(tp->t_dev) & 0x1f); /* SG */
1969 mynor = (port + umynor); /* SG */
1970 unit = minor_to_unit[mynor];
1971 rp = rp_addr(unit) + port;
1972 cp = &rp->rp_channel;
1976 if(tp->t_state & TS_BUSY) {
1977 if((tp->t_state&TS_TTSTOP) == 0) {
1980 if(rp->rp_xmit_stopped == 0) {
1982 rp->rp_xmit_stopped = 1;