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
34 * rp.c - for RocketPort FreeBSD
37 #include "opt_compat.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/fcntl.h>
42 #include <sys/malloc.h>
46 #include <sys/kernel.h>
48 #include <i386/isa/isa_device.h>
50 #include <pci/pcivar.h>
53 #include <i386/isa/rpreg.h>
54 #include <i386/isa/rpvar.h>
64 static Byte_t RData[RDATASIZE] =
66 0x00, 0x09, 0xf6, 0x82,
67 0x02, 0x09, 0x86, 0xfb,
68 0x04, 0x09, 0x00, 0x0a,
69 0x06, 0x09, 0x01, 0x0a,
70 0x08, 0x09, 0x8a, 0x13,
71 0x0a, 0x09, 0xc5, 0x11,
72 0x0c, 0x09, 0x86, 0x85,
73 0x0e, 0x09, 0x20, 0x0a,
74 0x10, 0x09, 0x21, 0x0a,
75 0x12, 0x09, 0x41, 0xff,
76 0x14, 0x09, 0x82, 0x00,
77 0x16, 0x09, 0x82, 0x7b,
78 0x18, 0x09, 0x8a, 0x7d,
79 0x1a, 0x09, 0x88, 0x81,
80 0x1c, 0x09, 0x86, 0x7a,
81 0x1e, 0x09, 0x84, 0x81,
82 0x20, 0x09, 0x82, 0x7c,
83 0x22, 0x09, 0x0a, 0x0a
86 static Byte_t RRegData[RREGDATASIZE]=
88 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
89 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
90 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
91 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
92 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
93 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
94 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
95 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
96 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
97 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
98 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
99 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
100 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
103 static CONTROLLER_T sController[CTL_SIZE] =
105 {-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}},
106 {-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}},
107 {-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}},
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}}
112 /* IRQ number to MUDBAC register 2 mapping */
115 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
119 static Byte_t sBitMapClrTbl[8] =
121 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
124 static Byte_t sBitMapSetTbl[8] =
126 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
129 /***************************************************************************
130 Function: sInitController
131 Purpose: Initialization of controller global registers and controller
133 Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
134 IRQNum,Frequency,PeriodicOnly)
135 CONTROLLER_T *CtlP; Ptr to controller structure
136 int CtlNum; Controller number
137 ByteIO_t MudbacIO; Mudbac base I/O address.
138 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
139 This list must be in the order the AIOPs will be found on the
140 controller. Once an AIOP in the list is not found, it is
141 assumed that there are no more AIOPs on the controller.
142 int AiopIOListSize; Number of addresses in AiopIOList
143 int IRQNum; Interrupt Request number. Can be any of the following:
144 0: Disable global interrupts
153 Byte_t Frequency: A flag identifying the frequency
154 of the periodic interrupt, can be any one of the following:
155 FREQ_DIS - periodic interrupt disabled
156 FREQ_137HZ - 137 Hertz
162 If IRQNum is set to 0 the Frequency parameter is
163 overidden, it is forced to a value of FREQ_DIS.
164 int PeriodicOnly: TRUE if all interrupts except the periodic
165 interrupt are to be blocked.
166 FALSE is both the periodic interrupt and
167 other channel interrupts are allowed.
168 If IRQNum is set to 0 the PeriodicOnly parameter is
169 overidden, it is forced to a value of FALSE.
170 Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
171 initialization failed.
174 If periodic interrupts are to be disabled but AIOP interrupts
175 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
177 If interrupts are to be completely disabled set IRQNum to 0.
179 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
182 This function performs initialization of global interrupt modes,
183 but it does not actually enable global interrupts. To enable
184 and disable global interrupts use functions sEnGlobalInt() and
185 sDisGlobalInt(). Enabling of global interrupts is normally not
186 done until all other initializations are complete.
188 Even if interrupts are globally enabled, they must also be
189 individually enabled for each channel that is to generate
192 Warnings: No range checking on any of the parameters is done.
194 No context switches are allowed while executing this function.
196 After this function all AIOPs on the controller are disabled,
197 they can be enabled with sEnAiop().
199 int sInitController( CONTROLLER_T *CtlP,
202 ByteIO_t *AiopIOList,
211 CtlP->CtlNum = CtlNum;
212 CtlP->BusType = isISA;
213 CtlP->CtlID = CTLID_0001; /* controller release 1 */
215 CtlP->MBaseIO = MudbacIO;
216 CtlP->MReg1IO = MudbacIO + 1;
217 CtlP->MReg2IO = MudbacIO + 2;
218 CtlP->MReg3IO = MudbacIO + 3;
220 CtlP->MReg2 = 0; /* interrupt disable */
221 CtlP->MReg3 = 0; /* no periodic interrupts */
223 if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */
225 CtlP->MReg2 = 0; /* interrupt disable */
226 CtlP->MReg3 = 0; /* no periodic interrupts */
230 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
231 CtlP->MReg3 = Frequency; /* set frequency */
232 if(PeriodicOnly) /* periodic interrupt only */
234 CtlP->MReg3 |= PERIODIC_ONLY;
238 sOutB(CtlP->MReg2IO,CtlP->MReg2);
239 sOutB(CtlP->MReg3IO,CtlP->MReg3);
240 sControllerEOI(CtlP); /* clear EOI if warm init */
244 for(i=0; i < AiopIOListSize; i++)
247 CtlP->AiopIO[i] = (WordIO_t)io;
248 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
249 sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
250 sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
251 sEnAiop(CtlP,i); /* enable the AIOP */
253 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
254 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
256 sDisAiop(CtlP,i); /* disable AIOP */
257 break; /* done looking for AIOPs */
260 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
261 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
262 sOutB(io + _INDX_DATA,CLOCK_PRESC);
263 CtlP->NumAiop++; /* bump count of AIOPs */
264 sDisAiop(CtlP,i); /* disable AIOP */
267 if(CtlP->NumAiop == 0)
270 return(CtlP->NumAiop);
273 int sPCIInitController( CONTROLLER_T *CtlP,
275 ByteIO_t *AiopIOList,
284 CtlP->CtlNum = CtlNum;
285 CtlP->BusType = isPCI;
286 CtlP->CtlID = CTLID_0001; /* controller release 1 */
287 CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
289 sPCIControllerEOI(CtlP);
293 for(i=0; i < AiopIOListSize; i++)
296 CtlP->AiopIO[i] = (WordIO_t)io;
297 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
299 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
300 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
302 break; /* done looking for AIOPs */
305 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
306 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
307 sOutB(io + _INDX_DATA,CLOCK_PRESC);
308 CtlP->NumAiop++; /* bump count of AIOPs */
311 if(CtlP->NumAiop == 0)
314 return(CtlP->NumAiop);
317 /***************************************************************************
318 Function: sReadAiopID
319 Purpose: Read the AIOP idenfication number directly from an AIOP.
320 Call: sReadAiopID(io)
321 ByteIO_t io: AIOP base I/O address
322 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
323 is replace by an identifying number.
324 Flag AIOPID_NULL if no valid AIOP is found
325 Warnings: No context switches are allowed while executing this function.
328 int sReadAiopID(ByteIO_t io)
330 Byte_t AiopID; /* ID byte from AIOP */
332 sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */
333 sOutB(io + _CMD_REG,0x0);
334 AiopID = sInB(io + _CHN_STAT0) & 0x07;
337 else /* AIOP does not exist */
341 /***************************************************************************
342 Function: sReadAiopNumChan
343 Purpose: Read the number of channels available in an AIOP directly from
345 Call: sReadAiopNumChan(io)
346 WordIO_t io: AIOP base I/O address
347 Return: int: The number of channels available
348 Comments: The number of channels is determined by write/reads from identical
349 offsets within the SRAM address spaces for channels 0 and 4.
350 If the channel 4 space is mirrored to channel 0 it is a 4 channel
351 AIOP, otherwise it is an 8 channel.
352 Warnings: No context switches are allowed while executing this function.
354 int sReadAiopNumChan(WordIO_t io)
358 sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
359 sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */
360 x = sInW(io + _INDX_DATA);
361 sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
362 if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
368 /***************************************************************************
370 Purpose: Initialization of a channel and channel structure
371 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
372 CONTROLLER_T *CtlP; Ptr to controller structure
373 CHANNEL_T *ChP; Ptr to channel structure
374 int AiopNum; AIOP number within controller
375 int ChanNum; Channel number within AIOP
376 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
377 number exceeds number of channels available in AIOP.
378 Comments: This function must be called before a channel can be used.
379 Warnings: No range checking on any of the parameters is done.
381 No context switches are allowed while executing this function.
383 int sInitChan( CONTROLLER_T *CtlP,
395 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
396 return(FALSE); /* exceeds num chans in AIOP */
398 /* Channel, AIOP, and controller identifiers */
400 ChP->ChanID = CtlP->AiopID[AiopNum];
401 ChP->AiopNum = AiopNum;
402 ChP->ChanNum = ChanNum;
404 /* Global direct addresses */
405 AiopIO = CtlP->AiopIO[AiopNum];
406 ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
407 ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
408 ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
409 ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
410 ChP->IndexData = AiopIO + _INDX_DATA;
412 /* Channel direct addresses */
413 ChIOOff = AiopIO + ChP->ChanNum * 2;
414 ChP->TxRxData = ChIOOff + _TD0;
415 ChP->ChanStat = ChIOOff + _CHN_STAT0;
416 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
417 ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
419 /* Initialize the channel from the RData array */
420 for(i=0; i < RDATASIZE; i+=4)
423 R[1] = RData[i+1] + 0x10 * ChanNum;
426 sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
430 for(i=0; i < RREGDATASIZE; i+=4)
432 ChR[i] = RRegData[i];
433 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
434 ChR[i+2] = RRegData[i+2];
435 ChR[i+3] = RRegData[i+3];
438 /* Indexed registers */
439 ChOff = (Word_t)ChanNum * 0x1000;
441 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
442 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
443 ChP->BaudDiv[2] = (Byte_t)BRD9600;
444 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
445 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
447 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
448 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
449 ChP->TxControl[2] = 0;
450 ChP->TxControl[3] = 0;
451 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
453 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
454 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
455 ChP->RxControl[2] = 0;
456 ChP->RxControl[3] = 0;
457 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
459 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
460 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
461 ChP->TxEnables[2] = 0;
462 ChP->TxEnables[3] = 0;
463 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
465 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
466 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
467 ChP->TxCompare[2] = 0;
468 ChP->TxCompare[3] = 0;
469 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
471 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
472 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
473 ChP->TxReplace1[2] = 0;
474 ChP->TxReplace1[3] = 0;
475 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
477 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
478 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
479 ChP->TxReplace2[2] = 0;
480 ChP->TxReplace2[3] = 0;
481 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
483 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
484 ChP->TxFIFO = ChOff + _TX_FIFO;
486 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
487 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
488 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
489 sOutW(ChP->IndexData,0);
490 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
491 ChP->RxFIFO = ChOff + _RX_FIFO;
493 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
494 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
495 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
496 sOutW(ChP->IndexData,0);
497 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
498 sOutW(ChP->IndexData,0);
499 ChP->TxPrioCnt = ChOff + _TXP_CNT;
500 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
501 sOutB(ChP->IndexData,0);
502 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
503 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
504 sOutB(ChP->IndexData,0);
505 ChP->TxPrioBuf = ChOff + _TXP_BUF;
506 sEnRxProcessor(ChP); /* start the Rx processor */
511 /***************************************************************************
512 Function: sStopRxProcessor
513 Purpose: Stop the receive processor from processing a channel.
514 Call: sStopRxProcessor(ChP)
515 CHANNEL_T *ChP; Ptr to channel structure
517 Comments: The receive processor can be started again with sStartRxProcessor().
518 This function causes the receive processor to skip over the
519 stopped channel. It does not stop it from processing other channels.
521 Warnings: No context switches are allowed while executing this function.
523 Do not leave the receive processor stopped for more than one
526 After calling this function a delay of 4 uS is required to ensure
527 that the receive processor is no longer processing this channel.
529 void sStopRxProcessor(CHANNEL_T *ChP)
537 sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
540 /***************************************************************************
541 Function: sFlushRxFIFO
542 Purpose: Flush the Rx FIFO
543 Call: sFlushRxFIFO(ChP)
544 CHANNEL_T *ChP; Ptr to channel structure
546 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
547 while it is being flushed the receive processor is stopped
548 and the transmitter is disabled. After these operations a
549 4 uS delay is done before clearing the pointers to allow
550 the receive processor to stop. These items are handled inside
552 Warnings: No context switches are allowed while executing this function.
554 void sFlushRxFIFO(CHANNEL_T *ChP)
557 Byte_t Ch; /* channel number within AIOP */
558 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
560 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
561 return; /* don't need to flush */
563 RxFIFOEnabled = FALSE;
564 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
566 RxFIFOEnabled = TRUE;
567 sDisRxFIFO(ChP); /* disable it */
568 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
569 sInB(ChP->IntChan); /* depends on bus i/o timing */
571 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
572 Ch = (Byte_t)sGetChanNum(ChP);
573 sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
574 sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */
575 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
576 sOutW(ChP->IndexData,0);
577 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
578 sOutW(ChP->IndexData,0);
580 sEnRxFIFO(ChP); /* enable Rx FIFO */
583 /***************************************************************************
584 Function: sFlushTxFIFO
585 Purpose: Flush the Tx FIFO
586 Call: sFlushTxFIFO(ChP)
587 CHANNEL_T *ChP; Ptr to channel structure
589 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
590 while it is being flushed the receive processor is stopped
591 and the transmitter is disabled. After these operations a
592 4 uS delay is done before clearing the pointers to allow
593 the receive processor to stop. These items are handled inside
595 Warnings: No context switches are allowed while executing this function.
597 void sFlushTxFIFO(CHANNEL_T *ChP)
600 Byte_t Ch; /* channel number within AIOP */
601 int TxEnabled; /* TRUE if transmitter enabled */
603 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
604 return; /* don't need to flush */
607 if(ChP->TxControl[3] & TX_ENABLE)
610 sDisTransmit(ChP); /* disable transmitter */
612 sStopRxProcessor(ChP); /* stop Rx processor */
613 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
614 sInB(ChP->IntChan); /* depends on bus i/o timing */
615 Ch = (Byte_t)sGetChanNum(ChP);
616 sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
617 sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */
618 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
619 sOutW(ChP->IndexData,0);
621 sEnTransmit(ChP); /* enable transmitter */
622 sStartRxProcessor(ChP); /* restart Rx processor */
625 /***************************************************************************
626 Function: sWriteTxPrioByte
627 Purpose: Write a byte of priority transmit data to a channel
628 Call: sWriteTxPrioByte(ChP,Data)
629 CHANNEL_T *ChP; Ptr to channel structure
630 Byte_t Data; The transmit data byte
632 Return: int: 1 if the bytes is successfully written, otherwise 0.
634 Comments: The priority byte is transmitted before any data in the Tx FIFO.
636 Warnings: No context switches are allowed while executing this function.
638 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
640 Byte_t DWBuf[4]; /* buffer for double word writes */
641 Word_t *WordPtr; /* must be far because Win SS != DS */
642 register DWordIO_t IndexAddr;
644 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
646 IndexAddr = ChP->IndexAddr;
647 sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
648 if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
649 return(0); /* nothing sent */
651 WordPtr = (Word_t *)(&DWBuf[0]);
652 *WordPtr = ChP->TxPrioBuf; /* data byte address */
654 DWBuf[2] = Data; /* data byte value */
655 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
657 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
659 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
660 DWBuf[3] = 0; /* priority buffer pointer */
661 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
663 else /* write it to Tx FIFO */
665 sWriteTxByte(sGetTxRxDataIO(ChP),Data);
667 return(1); /* 1 byte sent */
670 /***************************************************************************
671 Function: sEnInterrupts
672 Purpose: Enable one or more interrupts for a channel
673 Call: sEnInterrupts(ChP,Flags)
674 CHANNEL_T *ChP; Ptr to channel structure
675 Word_t Flags: Interrupt enable flags, can be any combination
676 of the following flags:
677 TXINT_EN: Interrupt on Tx FIFO empty
678 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
680 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
681 MCINT_EN: Interrupt on modem input change
682 CHANINT_EN: Allow channel interrupt signal to the AIOP's
683 Interrupt Channel Register.
685 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
686 enabled. If an interrupt enable flag is not set in Flags, that
687 interrupt will not be changed. Interrupts can be disabled with
688 function sDisInterrupts().
690 This function sets the appropriate bit for the channel in the AIOP's
691 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
692 this channel's bit to be set in the AIOP's Interrupt Channel Register.
694 Interrupts must also be globally enabled before channel interrupts
695 will be passed on to the host. This is done with function
698 In some cases it may be desirable to disable interrupts globally but
699 enable channel interrupts. This would allow the global interrupt
700 status register to be used to determine which AIOPs need service.
702 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
704 Byte_t Mask; /* Interrupt Mask Register */
707 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
709 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
711 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
713 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
715 if(Flags & CHANINT_EN)
717 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
718 sOutB(ChP->IntMask,Mask);
722 /***************************************************************************
723 Function: sDisInterrupts
724 Purpose: Disable one or more interrupts for a channel
725 Call: sDisInterrupts(ChP,Flags)
726 CHANNEL_T *ChP; Ptr to channel structure
727 Word_t Flags: Interrupt flags, can be any combination
728 of the following flags:
729 TXINT_EN: Interrupt on Tx FIFO empty
730 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
732 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
733 MCINT_EN: Interrupt on modem input change
734 CHANINT_EN: Disable channel interrupt signal to the
735 AIOP's Interrupt Channel Register.
737 Comments: If an interrupt flag is set in Flags, that interrupt will be
738 disabled. If an interrupt flag is not set in Flags, that
739 interrupt will not be changed. Interrupts can be enabled with
740 function sEnInterrupts().
742 This function clears the appropriate bit for the channel in the AIOP's
743 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
744 this channel's bit from being set in the AIOP's Interrupt Channel
747 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
749 Byte_t Mask; /* Interrupt Mask Register */
752 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
753 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
754 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
755 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
757 if(Flags & CHANINT_EN)
759 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
760 sOutB(ChP->IntMask,Mask);
764 /*********************************************************************
765 Begin FreeBsd-specific driver code
766 **********************************************************************/
768 static int rpprobe __P((struct isa_device *));
769 static int rpattach __P((struct isa_device *));
771 static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
772 static void rp_pciattach(pcici_t tag, int unit);
773 static u_long rp_pcicount;
775 static struct pci_device rp_pcidevice = {
783 DATA_SET (pcidevice_set, rp_pcidevice);
785 static timeout_t rpdtrwakeup;
787 struct isa_driver rpdriver = {
788 rpprobe, rpattach, "rp"
791 static char driver_name[] = "rp";
793 static d_open_t rpopen;
794 static d_close_t rpclose;
795 static d_read_t rpread;
796 static d_write_t rpwrite;
797 static d_ioctl_t rpioctl;
798 static d_stop_t rpstop;
799 static d_devtotty_t rpdevtotty;
801 #define CDEV_MAJOR 81
802 static struct cdevsw rp_cdevsw = {
803 rpopen, rpclose, rpread, rpwrite,
804 rpioctl, rpstop, noreset, rpdevtotty,
805 ttpoll, nommap, NULL, driver_name,
806 NULL, -1, nodump, nopsize,
810 static int rp_controller_port = 0;
811 static int rp_num_ports_open = 0;
812 static int ndevs = 0;
813 static int minor_to_unit[128];
815 static struct tty rp_tty[128];
818 static int rp_num_ports[4]; /* Number of ports on each controller */
820 #define _INLINE_ __inline
821 #define POLL_INTERVAL 1
823 #define CALLOUT_MASK 0x80
824 #define CONTROL_MASK 0x60
825 #define CONTROL_INIT_STATE 0x20
826 #define CONTROL_LOCK_STATE 0x40
827 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
828 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
829 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
830 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
831 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
833 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
834 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
835 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
837 static struct rp_port *p_rp_addr[4];
838 static struct rp_port *p_rp_table[MAX_RP_PORTS];
839 #define rp_addr(unit) (p_rp_addr[unit])
840 #define rp_table(port) (p_rp_table[port])
843 * The top-level routines begin here
846 int rpselect __P((dev_t, int, struct proc *));
848 static int rpparam __P((struct tty *, struct termios *));
849 static void rpstart __P((struct tty *));
850 static void rphardclose __P((struct rp_port *));
852 #define rpreset noreset
853 #define rpstrategy nostrategy
854 static void rp_disc_optim __P((struct tty *tp, struct termios *t,
855 struct rp_port *rp));
857 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
858 CHANNEL_t *cp, unsigned int ChanStatus)
861 unsigned int CharNStat;
864 ToRecv = sGetRxCnt(cp);
868 /* If status indicates there are errored characters in the
869 FIFO, then enter status mode (a word in FIFO holds
870 characters and status)
873 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
874 if(!(ChanStatus & STATMODE)) {
875 ChanStatus |= STATMODE;
880 if we previously entered status mode then read down the
881 FIFO one word at a time, pulling apart the character and
882 the status. Update error counters depending on status.
884 if(ChanStatus & STATMODE) {
886 if(tp->t_state & TS_TBLOCK) {
889 CharNStat = sInW(sGetTxRxDataIO(cp));
890 ch = CharNStat & 0xff;
892 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
894 else if (CharNStat & STMPARITYH)
896 else if (CharNStat & STMRCVROVRH)
899 (*linesw[tp->t_line].l_rint)(ch, tp);
903 After emtying FIFO in status mode, turn off status mode
906 if(sGetRxCnt(cp) == 0)
907 sDisRxStatusMode(cp);
911 if(tp->t_state & TS_TBLOCK) {
914 ch = (u_char) sInB(sGetTxRxDataIO(cp));
916 (*linesw[tp->t_line].l_rint)(ch, tp);
923 static _INLINE_ void rp_handle_port(struct rp_port *rp)
927 unsigned int IntMask, ChanStatus;
933 cp = &rp->rp_channel;
935 IntMask = sGetChanIntID(cp);
936 IntMask = IntMask & rp->rp_intmask;
937 ChanStatus = sGetChanStatus(cp);
938 if(IntMask & RXF_TRIG)
939 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
940 rp_do_receive(rp, tp, cp, ChanStatus);
942 if(IntMask & DELTA_CD) {
943 if(ChanStatus & CD_ACT) {
944 if(!(tp->t_state & TS_CARR_ON) ) {
945 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
948 if((tp->t_state & TS_CARR_ON)) {
949 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
950 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
956 /* oldcts = rp->rp_cts;
957 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
958 if(oldcts != rp->rp_cts) {
959 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
964 static void rp_do_poll(void *not_used)
969 int unit, aiop, ch, line, count;
970 unsigned char CtlMask, AiopMask;
972 for(unit = 0; unit <= ndevs; unit++) {
975 if(ctl->BusType == isPCI)
976 CtlMask = sPCIGetControllerIntStatus(ctl);
978 CtlMask = sGetControllerIntStatus(ctl);
979 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
981 AiopMask = sGetAiopIntStatus(ctl, aiop);
982 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
984 line = (unit << 5) | (aiop << 3) | ch;
992 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
995 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
996 count = sGetTxCnt(&rp->rp_channel);
998 tp->t_state &= ~(TS_BUSY);
999 if(!(tp->t_state & TS_TTSTOP) &&
1000 (count <= rp->rp_restart)) {
1001 (*linesw[tp->t_line].l_start)(tp);
1006 if(rp_num_ports_open)
1007 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1011 rp_pciprobe(pcici_t tag, pcidi_t type)
1015 vendor_id = type & 0xffff;
1025 struct isa_device *dev;
1027 int controller, unit;
1028 int aiop, num_aiops;
1029 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1032 unit = dev->id_unit;
1033 if (dev->id_unit >= 4) {
1034 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1037 printf("probing for RocketPort(ISA) unit %d\n", unit);
1038 if (rp_controller_port)
1039 controller = rp_controller_port;
1041 controller = dev->id_iobase + 0x40;
1044 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1045 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1047 ctlp = sCtlNumToCtlPtr(dev->id_unit);
1048 num_aiops = sInitController(ctlp, dev->id_unit,
1049 controller + ((unit-rp_pcicount)*0x400),
1050 aiopio, MAX_AIOPS_PER_BOARD, 0,
1052 if (num_aiops <= 0) {
1053 printf("board%d init failed\n", unit);
1057 if (rp_controller_port) {
1061 rp_controller_port = controller;
1070 rp_pciattach(pcici_t tag, int unit)
1073 int success, oldspl;
1075 int num_ports, num_chan, num_aiops;
1076 int aiop, chan, port;
1077 int ChanStatus, line, i, count;
1078 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1083 success = pci_map_port(tag, 0x10, &iobase);
1085 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1087 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1088 aiopio[aiop] = iobase + (aiop * 0x40);
1090 ctlp = sCtlNumToCtlPtr(unit);
1091 num_aiops = sPCIInitController(ctlp, unit,
1092 aiopio, MAX_AIOPS_PER_BOARD, 0,
1096 for(aiop=0; aiop < num_aiops; aiop++) {
1097 sResetAiopByNum(ctlp, aiop);
1098 num_ports += sGetAiopNumChan(ctlp, aiop);
1100 printf("RocketPort%d = %d ports\n", unit, num_ports);
1101 rp_num_ports[unit] = num_ports;
1103 rp = (struct rp_port *)
1104 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1106 printf("rp_attach: Could not malloc rp_ports structures\n");
1110 count = unit * 32; /* board times max ports per card SG */
1111 for(i=count;i < (count + rp_num_ports[unit]);i++)
1112 minor_to_unit[i] = unit;
1114 bzero(rp, sizeof(struct rp_port) * num_ports);
1115 tty = (struct tty *)
1116 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1118 printf("rp_attach: Could not malloc tty structures\n");
1121 bzero(tty, sizeof(struct tty) * num_ports);
1127 rp_dev = makedev(CDEV_MAJOR, unit);
1128 cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1131 for(aiop=0; aiop < num_aiops; aiop++) {
1132 num_chan = sGetAiopNumChan(ctlp, aiop);
1133 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1142 /* tty->t_termios = deftermios;
1144 rp->dtr_wait = 3 * hz;
1145 rp->it_in.c_iflag = 0;
1146 rp->it_in.c_oflag = 0;
1147 rp->it_in.c_cflag = TTYDEF_CFLAG;
1148 rp->it_in.c_lflag = 0;
1149 termioschars(&rp->it_in);
1150 /* termioschars(&tty->t_termios);
1152 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1153 rp->it_out = rp->it_in;
1155 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1156 DELTA_CD | DELTA_CTS | DELTA_DSR;
1157 ChanStatus = sGetChanStatus(&rp->rp_channel);
1158 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1159 printf("RocketPort sInitChan(%d, %d, %d) failed
1160 \n", unit, aiop, chan);
1163 ChanStatus = sGetChanStatus(&rp->rp_channel);
1164 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1165 line = (unit << 5) | (aiop << 3) | chan;
1166 rp_table(line) = rp;
1167 /* devfs_add_devswf(&rp_cdevsw,
1168 port, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
1170 devfs_add_devswf(&rp_cdevsw,
1171 port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT,
1172 GID_WHEEL, 0600, "ttyRi%r", port);
1181 struct isa_device *dev;
1183 struct isa_device *idev;
1185 int iobase, unit, /*rpmajor,*/ oldspl;
1186 int num_ports, num_chan, num_aiops;
1187 int aiop, chan, port;
1188 int ChanStatus, line, i, count;
1189 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1194 iobase = dev->id_iobase;
1195 unit = dev->id_unit;
1198 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1199 aiopio[aiop] = iobase + (aiop * 0x400);
1201 ctlp = sCtlNumToCtlPtr(unit);
1202 num_aiops = sInitController(ctlp, unit,
1203 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1204 aiopio, MAX_AIOPS_PER_BOARD, 0,
1208 for(aiop=0; aiop < num_aiops; aiop++) {
1209 sResetAiopByNum(ctlp, aiop);
1210 sEnAiop(ctlp, aiop);
1211 num_ports += sGetAiopNumChan(ctlp, aiop);
1213 printf("RocketPort%d = %d ports\n", unit, num_ports);
1214 rp_num_ports[unit] = num_ports;
1216 rp = (struct rp_port *)
1217 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1219 printf("rp_attach: Could not malloc rp_ports structures\n");
1223 count = unit * 32; /* board # times max ports per card SG */
1224 for(i=count;i < (count + rp_num_ports[unit]);i++)
1225 minor_to_unit[i] = unit;
1227 bzero(rp, sizeof(struct rp_port) * num_ports);
1228 tty = (struct tty *)
1229 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1231 printf("rp_attach: Could not malloc tty structures\n");
1234 bzero(tty, sizeof(struct tty) * num_ports);
1240 rp_dev = makedev(CDEV_MAJOR, unit);
1241 cdevsw_add(&rp_dev, &rp_cdevsw, NULL);
1244 for(aiop=0; aiop < num_aiops; aiop++) {
1245 num_chan = sGetAiopNumChan(ctlp, aiop);
1246 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1255 /* tty->t_termios = deftermios;
1257 rp->dtr_wait = 3 * hz;
1258 rp->it_in.c_iflag = 0;
1259 rp->it_in.c_oflag = 0;
1260 rp->it_in.c_cflag = TTYDEF_CFLAG;
1261 rp->it_in.c_lflag = 0;
1262 termioschars(&rp->it_in);
1263 /* termioschars(&tty->t_termios);
1265 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1266 rp->it_out = rp->it_in;
1268 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1269 DELTA_CD | DELTA_CTS | DELTA_DSR;
1270 ChanStatus = sGetChanStatus(&rp->rp_channel);
1271 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1272 printf("RocketPort sInitChan(%d, %d, %d) failed
1273 \n", unit, aiop, chan);
1276 ChanStatus = sGetChanStatus(&rp->rp_channel);
1277 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1278 line = (unit << 5) | (aiop << 3) | chan;
1279 rp_table(line) = rp;
1283 idev = find_isadev(isa_devtab_tty, &rpdriver,
1284 RP_MPMASTER(dev) + rp_pcicount);
1286 printf("rp%d: master device %d not configured\n",
1287 dev->id_unit, RP_MPMASTER(dev));
1289 /* printf("COOL!! Device is found!!\n");
1290 for(rpmajor=0;rpmajor<nchrdev;rpmajor++)
1291 if(cdevsw[rpmajor].d_open == rpopen)
1292 printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor);
1298 rpopen(dev, flag, mode, p)
1304 int unit, port, mynor, umynor, flags; /* SG */
1307 unsigned int IntMask, ChanStatus;
1310 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1311 port = (minor(dev) & 0x1f); /* SG */
1312 mynor = (port + umynor); /* SG */
1313 unit = minor_to_unit[mynor];
1316 rp = rp_addr(unit) + port;
1317 /* rp->rp_tty = &rp_tty[rp->rp_port];
1324 while(rp->state & ~SET_DTR) {
1325 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1330 if(tp->t_state & TS_ISOPEN) {
1331 if(IS_CALLOUT(dev)) {
1332 if(!rp->active_out) {
1337 if(rp->active_out) {
1338 if(flag & O_NONBLOCK) {
1342 error = tsleep(&rp->active_out,
1343 TTIPRI | PCATCH, "rpbi", 0);
1349 if(tp->t_state & TS_XCLUDE &&
1350 suser(p->p_ucred, &p->p_acflag)) {
1357 tp->t_param = rpparam;
1358 tp->t_oproc = rpstart;
1360 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1364 rp->rp_channel.TxControl[3] =
1365 ((rp->rp_channel.TxControl[3]
1366 & ~(SET_RTS | SET_DTR)) | flags);
1367 sOutDW(rp->rp_channel.IndexAddr,
1368 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1369 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1370 sDisRxStatusMode(&rp->rp_channel);
1371 sFlushRxFIFO(&rp->rp_channel);
1372 sFlushTxFIFO(&rp->rp_channel);
1374 sEnInterrupts(&rp->rp_channel,
1375 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1376 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1378 sDisRxStatusMode(&rp->rp_channel);
1379 sClrTxXOFF(&rp->rp_channel);
1381 /* sDisRTSFlowCtl(&rp->rp_channel);
1382 sDisCTSFlowCtl(&rp->rp_channel);
1384 sDisTxSoftFlowCtl(&rp->rp_channel);
1386 sStartRxProcessor(&rp->rp_channel);
1388 sEnRxFIFO(&rp->rp_channel);
1389 sEnTransmit(&rp->rp_channel);
1391 /* sSetDTR(&rp->rp_channel);
1392 sSetRTS(&rp->rp_channel);
1396 error = rpparam(tp, &tp->t_termios);
1403 rp_num_ports_open++;
1405 IntMask = sGetChanIntID(&rp->rp_channel);
1406 IntMask = IntMask & rp->rp_intmask;
1407 ChanStatus = sGetChanStatus(&rp->rp_channel);
1408 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1409 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1410 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1414 if(rp_num_ports_open == 1)
1415 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1419 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1420 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1422 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1429 error = (*linesw[tp->t_line].l_open)(dev, tp);
1431 rp_disc_optim(tp, &tp->t_termios, rp);
1432 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1433 rp->active_out = TRUE;
1435 /* if(rp_num_ports_open == 1)
1436 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1440 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1447 rpclose(dev, flag, mode, p)
1452 int oldspl, unit, mynor, umynor, port; /* SG */
1457 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1458 port = (minor(dev) & 0x1f); /* SG */
1459 mynor = (port + umynor); /* SG */
1460 unit = minor_to_unit[mynor]; /* SG */
1464 rp = rp_addr(unit) + port;
1465 cp = &rp->rp_channel;
1469 (*linesw[tp->t_line].l_close)(tp, flag);
1470 rp_disc_optim(tp, &tp->t_termios, rp);
1471 rpstop(tp, FREAD | FWRITE);
1474 tp->t_state &= ~TS_BUSY;
1483 rphardclose(struct rp_port *rp)
1489 cp = &rp->rp_channel;
1491 mynor = MINOR_MAGIC(tp->t_dev);
1496 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1499 sDisTxSoftFlowCtl(cp);
1502 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1505 if(IS_CALLOUT(tp->t_dev)) {
1508 if(rp->dtr_wait != 0) {
1509 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1510 rp->state |= ~SET_DTR;
1513 rp->active_out = FALSE;
1514 wakeup(&rp->active_out);
1515 wakeup(TSA_CARR_ON(tp));
1520 rpread(dev, uio, flag)
1527 int unit, mynor, umynor, port, error = 0; /* SG */
1529 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1530 port = (minor(dev) & 0x1f); /* SG */
1531 mynor = (port + umynor); /* SG */
1532 unit = minor_to_unit[mynor]; /* SG */
1536 rp = rp_addr(unit) + port;
1538 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
1544 rpwrite(dev, uio, flag)
1551 int unit, mynor, port, umynor, error = 0; /* SG */
1553 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1554 port = (minor(dev) & 0x1f); /* SG */
1555 mynor = (port + umynor); /* SG */
1556 unit = minor_to_unit[mynor]; /* SG */
1560 rp = rp_addr(unit) + port;
1562 while(rp->rp_disable_writes) {
1564 if(error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH,
1570 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1575 rpdtrwakeup(void *chan)
1579 rp = (struct rp_port *)chan;
1580 rp->state &= SET_DTR;
1581 wakeup(&rp->dtr_wait);
1585 rpioctl(dev, cmd, data, flag, p)
1595 int unit, mynor, port, umynor; /* SG */
1598 int arg, flags, result, ChanStatus;
1600 struct termios term, *t;
1602 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1603 port = (minor(dev) & 0x1f); /* SG */
1604 mynor = (port + umynor); /* SG */
1605 unit = minor_to_unit[mynor];
1606 rp = rp_addr(unit) + port;
1608 if(IS_CONTROL(dev)) {
1611 switch (IS_CONTROL(dev)) {
1612 case CONTROL_INIT_STATE:
1613 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1615 case CONTROL_LOCK_STATE:
1616 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1619 return(ENODEV); /* /dev/nodev */
1623 error = suser(p->p_ucred, &p->p_acflag);
1626 *ct = *(struct termios *)data;
1629 *(struct termios *)data = *ct;
1632 *(int *)data = TTYDISC;
1635 bzero(data, sizeof(struct winsize));
1643 cp = &rp->rp_channel;
1645 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1646 term = tp->t_termios;
1648 error = ttsetcompat(tp, &cmd, data, &term);
1652 data = (caddr_t)&term;
1655 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1657 struct termios *dt = (struct termios *)data;
1658 struct termios *lt = IS_CALLOUT(dev)
1659 ? &rp->lt_out : &rp->lt_in;
1661 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1662 | (dt->c_iflag & ~lt->c_iflag);
1663 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1664 | (dt->c_oflag & ~lt->c_oflag);
1665 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1666 | (dt->c_cflag & ~lt->c_cflag);
1667 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1668 | (dt->c_lflag & ~lt->c_lflag);
1669 for(cc = 0; cc < NCCS; ++cc)
1670 if(lt->c_cc[cc] = tp->t_cc[cc])
1671 dt->c_cc[cc] = tp->t_cc[cc];
1672 if(lt->c_ispeed != 0)
1673 dt->c_ispeed = tp->t_ispeed;
1674 if(lt->c_ospeed != 0)
1675 dt->c_ospeed = tp->t_ospeed;
1680 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1681 if(error != ENOIOCTL) {
1686 flags = rp->rp_channel.TxControl[3];
1688 error = ttioctl(tp, cmd, data, flag);
1689 flags = rp->rp_channel.TxControl[3];
1690 rp_disc_optim(tp, &tp->t_termios, rp);
1691 if(error != ENOIOCTL) {
1697 sSendBreak(&rp->rp_channel);
1701 sClrBreak(&rp->rp_channel);
1705 sSetDTR(&rp->rp_channel);
1706 sSetRTS(&rp->rp_channel);
1710 sClrDTR(&rp->rp_channel);
1714 arg = *(int *) data;
1720 rp->rp_channel.TxControl[3] =
1721 ((rp->rp_channel.TxControl[3]
1722 & ~(SET_RTS | SET_DTR)) | flags);
1723 sOutDW(rp->rp_channel.IndexAddr,
1724 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1727 arg = *(int *) data;
1733 rp->rp_channel.TxControl[3] |= flags;
1734 sOutDW(rp->rp_channel.IndexAddr,
1735 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1738 arg = *(int *) data;
1744 rp->rp_channel.TxControl[3] &= ~flags;
1745 sOutDW(rp->rp_channel.IndexAddr,
1746 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1751 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1752 flags = rp->rp_channel.TxControl[3];
1753 result = TIOCM_LE; /* always on while open for some reason */
1754 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1755 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1756 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1757 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1758 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1760 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1762 result |= TIOCM_RTS;
1765 *(int *)data = result;
1768 error = suser(p->p_ucred, &p->p_acflag);
1773 rp->dtr_wait = *(int *)data * hz/100;
1776 *(int *)data = rp->dtr_wait * 100/hz;
1786 static struct speedtab baud_table[] = {
1787 B0, 0, B50, BRD50, B75, BRD75,
1788 B110, BRD110, B134, BRD134, B150, BRD150,
1789 B200, BRD200, B300, BRD300, B600, BRD600,
1790 B1200, BRD1200, B1800, BRD1800, B2400, BRD2400,
1791 B4800, BRD4800, B9600, BRD9600, B19200, BRD19200,
1792 B38400, BRD38400, B7200, BRD7200, B14400, BRD14400,
1793 B57600, BRD57600, B76800, BRD76800,
1794 B115200, BRD115200, B230400, BRD230400,
1805 int unit, mynor, port, umynor; /* SG */
1806 int oldspl, cflag, iflag, oflag, lflag;
1810 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1811 port = (minor(tp->t_dev) & 0x1f); /* SG */
1812 mynor = (port + umynor); /* SG */
1814 unit = minor_to_unit[mynor];
1815 rp = rp_addr(unit) + port;
1816 cp = &rp->rp_channel;
1824 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1825 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1828 tp->t_ispeed = t->c_ispeed;
1829 tp->t_ospeed = t->c_ospeed;
1830 tp->t_cflag = cflag;
1831 tp->t_iflag = iflag;
1832 tp->t_oflag = oflag;
1833 tp->t_lflag = lflag;
1835 if(t->c_ospeed == 0) {
1839 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1841 /* Set baud rate ----- we only pay attention to ispeed */
1844 sSetBaud(cp, ospeed);
1846 if(cflag & CSTOPB) {
1852 if(cflag & PARENB) {
1854 if(cflag & PARODD) {
1863 if((cflag & CSIZE) == CS8) {
1865 rp->rp_imask = 0xFF;
1868 rp->rp_imask = 0x7F;
1871 if(iflag & ISTRIP) {
1872 rp->rp_imask &= 0x7F;
1875 if(cflag & CLOCAL) {
1876 rp->rp_intmask &= ~DELTA_CD;
1878 rp->rp_intmask |= DELTA_CD;
1881 /* Put flow control stuff here */
1883 if(cflag & CCTS_OFLOW) {
1889 if(cflag & CRTS_IFLOW) {
1890 rp->rp_rts_iflow = 1;
1892 rp->rp_rts_iflow = 0;
1895 if(cflag & CRTS_IFLOW) {
1900 rp_disc_optim(tp, t, rp);
1902 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1903 tp->t_state |= TS_CARR_ON;
1904 wakeup(TSA_CARR_ON(tp));
1907 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1908 flags = rp->rp_channel.TxControl[3];
1920 rp_disc_optim(tp, t, rp)
1925 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1926 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1927 &&(!(t->c_iflag & PARMRK)
1928 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1929 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1930 && linesw[tp->t_line].l_rint == ttyinput)
1931 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1933 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1943 int unit, mynor, port, umynor; /* SG */
1945 int spl, xmit_fifo_room;
1949 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1950 port = (minor(tp->t_dev) & 0x1f); /* SG */
1951 mynor = (port + umynor); /* SG */
1952 unit = minor_to_unit[mynor];
1953 rp = rp_addr(unit) + port;
1954 cp = &rp->rp_channel;
1955 flags = rp->rp_channel.TxControl[3];
1958 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1963 if(rp->rp_xmit_stopped) {
1965 rp->rp_xmit_stopped = 0;
1967 count = sGetTxCnt(cp);
1969 if(tp->t_outq.c_cc == 0) {
1970 if((tp->t_state & TS_BUSY) && (count == 0)) {
1971 tp->t_state &= ~TS_BUSY;
1977 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1980 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1981 tp->t_state |= TS_BUSY;
1983 while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1985 sOutB(sGetTxRxDataIO(cp), ch);
1989 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1998 register struct tty *tp;
2003 int unit, mynor, port, umynor; /* SG */
2006 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
2007 port = (minor(tp->t_dev) & 0x1f); /* SG */
2008 mynor = (port + umynor); /* SG */
2009 unit = minor_to_unit[mynor];
2010 rp = rp_addr(unit) + port;
2011 cp = &rp->rp_channel;
2015 if(tp->t_state & TS_BUSY) {
2016 if((tp->t_state&TS_TTSTOP) == 0) {
2019 if(rp->rp_xmit_stopped == 0) {
2021 rp->rp_xmit_stopped = 1;
2030 rpselect(dev, flag, p)
2039 rpdevtotty(dev_t dev)
2042 int unit, port, mynor, umynor; /* SG */
2044 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
2045 port = (minor(dev) & 0x1f); /* SG */
2046 mynor = (port + umynor); /* SG */
2047 unit = minor_to_unit[mynor]; /* SG */
2051 rp = rp_addr(unit) + port;