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
36 * rp.c - for RocketPort FreeBSD
39 #include "opt_compat.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/fcntl.h>
44 #include <sys/malloc.h>
48 #include <sys/kernel.h>
50 #include <i386/isa/isa_device.h>
52 #include <pci/pcivar.h>
55 #include <i386/isa/rpreg.h>
56 #include <i386/isa/rpvar.h>
66 static Byte_t RData[RDATASIZE] =
68 0x00, 0x09, 0xf6, 0x82,
69 0x02, 0x09, 0x86, 0xfb,
70 0x04, 0x09, 0x00, 0x0a,
71 0x06, 0x09, 0x01, 0x0a,
72 0x08, 0x09, 0x8a, 0x13,
73 0x0a, 0x09, 0xc5, 0x11,
74 0x0c, 0x09, 0x86, 0x85,
75 0x0e, 0x09, 0x20, 0x0a,
76 0x10, 0x09, 0x21, 0x0a,
77 0x12, 0x09, 0x41, 0xff,
78 0x14, 0x09, 0x82, 0x00,
79 0x16, 0x09, 0x82, 0x7b,
80 0x18, 0x09, 0x8a, 0x7d,
81 0x1a, 0x09, 0x88, 0x81,
82 0x1c, 0x09, 0x86, 0x7a,
83 0x1e, 0x09, 0x84, 0x81,
84 0x20, 0x09, 0x82, 0x7c,
85 0x22, 0x09, 0x0a, 0x0a
88 static Byte_t RRegData[RREGDATASIZE]=
90 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
91 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
92 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
93 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
94 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
95 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
96 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
97 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
98 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
99 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
100 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
101 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
102 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
105 static CONTROLLER_T sController[CTL_SIZE] =
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}},
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}}
114 /* IRQ number to MUDBAC register 2 mapping */
117 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
121 static Byte_t sBitMapClrTbl[8] =
123 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
126 static Byte_t sBitMapSetTbl[8] =
128 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
131 /***************************************************************************
132 Function: sInitController
133 Purpose: Initialization of controller global registers and controller
135 Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
136 IRQNum,Frequency,PeriodicOnly)
137 CONTROLLER_T *CtlP; Ptr to controller structure
138 int CtlNum; Controller number
139 ByteIO_t MudbacIO; Mudbac base I/O address.
140 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
141 This list must be in the order the AIOPs will be found on the
142 controller. Once an AIOP in the list is not found, it is
143 assumed that there are no more AIOPs on the controller.
144 int AiopIOListSize; Number of addresses in AiopIOList
145 int IRQNum; Interrupt Request number. Can be any of the following:
146 0: Disable global interrupts
155 Byte_t Frequency: A flag identifying the frequency
156 of the periodic interrupt, can be any one of the following:
157 FREQ_DIS - periodic interrupt disabled
158 FREQ_137HZ - 137 Hertz
164 If IRQNum is set to 0 the Frequency parameter is
165 overidden, it is forced to a value of FREQ_DIS.
166 int PeriodicOnly: TRUE if all interrupts except the periodic
167 interrupt are to be blocked.
168 FALSE is both the periodic interrupt and
169 other channel interrupts are allowed.
170 If IRQNum is set to 0 the PeriodicOnly parameter is
171 overidden, it is forced to a value of FALSE.
172 Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
173 initialization failed.
176 If periodic interrupts are to be disabled but AIOP interrupts
177 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
179 If interrupts are to be completely disabled set IRQNum to 0.
181 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
184 This function performs initialization of global interrupt modes,
185 but it does not actually enable global interrupts. To enable
186 and disable global interrupts use functions sEnGlobalInt() and
187 sDisGlobalInt(). Enabling of global interrupts is normally not
188 done until all other initializations are complete.
190 Even if interrupts are globally enabled, they must also be
191 individually enabled for each channel that is to generate
194 Warnings: No range checking on any of the parameters is done.
196 No context switches are allowed while executing this function.
198 After this function all AIOPs on the controller are disabled,
199 they can be enabled with sEnAiop().
201 int sInitController( CONTROLLER_T *CtlP,
204 ByteIO_t *AiopIOList,
213 CtlP->CtlNum = CtlNum;
214 CtlP->BusType = isISA;
215 CtlP->CtlID = CTLID_0001; /* controller release 1 */
217 CtlP->MBaseIO = MudbacIO;
218 CtlP->MReg1IO = MudbacIO + 1;
219 CtlP->MReg2IO = MudbacIO + 2;
220 CtlP->MReg3IO = MudbacIO + 3;
222 CtlP->MReg2 = 0; /* interrupt disable */
223 CtlP->MReg3 = 0; /* no periodic interrupts */
225 if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */
227 CtlP->MReg2 = 0; /* interrupt disable */
228 CtlP->MReg3 = 0; /* no periodic interrupts */
232 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
233 CtlP->MReg3 = Frequency; /* set frequency */
234 if(PeriodicOnly) /* periodic interrupt only */
236 CtlP->MReg3 |= PERIODIC_ONLY;
240 sOutB(CtlP->MReg2IO,CtlP->MReg2);
241 sOutB(CtlP->MReg3IO,CtlP->MReg3);
242 sControllerEOI(CtlP); /* clear EOI if warm init */
246 for(i=0; i < AiopIOListSize; i++)
249 CtlP->AiopIO[i] = (WordIO_t)io;
250 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
251 sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
252 sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
253 sEnAiop(CtlP,i); /* enable the AIOP */
255 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
256 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
258 sDisAiop(CtlP,i); /* disable AIOP */
259 break; /* done looking for AIOPs */
262 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
263 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
264 sOutB(io + _INDX_DATA,CLOCK_PRESC);
265 CtlP->NumAiop++; /* bump count of AIOPs */
266 sDisAiop(CtlP,i); /* disable AIOP */
269 if(CtlP->NumAiop == 0)
272 return(CtlP->NumAiop);
275 int sPCIInitController( CONTROLLER_T *CtlP,
277 ByteIO_t *AiopIOList,
286 CtlP->CtlNum = CtlNum;
287 CtlP->BusType = isPCI;
288 CtlP->CtlID = CTLID_0001; /* controller release 1 */
289 CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
291 sPCIControllerEOI(CtlP);
295 for(i=0; i < AiopIOListSize; i++)
298 CtlP->AiopIO[i] = (WordIO_t)io;
299 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
301 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
302 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
304 break; /* done looking for AIOPs */
307 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
308 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
309 sOutB(io + _INDX_DATA,CLOCK_PRESC);
310 CtlP->NumAiop++; /* bump count of AIOPs */
313 if(CtlP->NumAiop == 0)
316 return(CtlP->NumAiop);
319 /***************************************************************************
320 Function: sReadAiopID
321 Purpose: Read the AIOP idenfication number directly from an AIOP.
322 Call: sReadAiopID(io)
323 ByteIO_t io: AIOP base I/O address
324 Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
325 is replace by an identifying number.
326 Flag AIOPID_NULL if no valid AIOP is found
327 Warnings: No context switches are allowed while executing this function.
330 int sReadAiopID(ByteIO_t io)
332 Byte_t AiopID; /* ID byte from AIOP */
334 sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */
335 sOutB(io + _CMD_REG,0x0);
336 AiopID = sInB(io + _CHN_STAT0) & 0x07;
339 else /* AIOP does not exist */
343 /***************************************************************************
344 Function: sReadAiopNumChan
345 Purpose: Read the number of channels available in an AIOP directly from
347 Call: sReadAiopNumChan(io)
348 WordIO_t io: AIOP base I/O address
349 Return: int: The number of channels available
350 Comments: The number of channels is determined by write/reads from identical
351 offsets within the SRAM address spaces for channels 0 and 4.
352 If the channel 4 space is mirrored to channel 0 it is a 4 channel
353 AIOP, otherwise it is an 8 channel.
354 Warnings: No context switches are allowed while executing this function.
356 int sReadAiopNumChan(WordIO_t io)
360 sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
361 sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */
362 x = sInW(io + _INDX_DATA);
363 sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
364 if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
370 /***************************************************************************
372 Purpose: Initialization of a channel and channel structure
373 Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
374 CONTROLLER_T *CtlP; Ptr to controller structure
375 CHANNEL_T *ChP; Ptr to channel structure
376 int AiopNum; AIOP number within controller
377 int ChanNum; Channel number within AIOP
378 Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
379 number exceeds number of channels available in AIOP.
380 Comments: This function must be called before a channel can be used.
381 Warnings: No range checking on any of the parameters is done.
383 No context switches are allowed while executing this function.
385 int sInitChan( CONTROLLER_T *CtlP,
397 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
398 return(FALSE); /* exceeds num chans in AIOP */
400 /* Channel, AIOP, and controller identifiers */
402 ChP->ChanID = CtlP->AiopID[AiopNum];
403 ChP->AiopNum = AiopNum;
404 ChP->ChanNum = ChanNum;
406 /* Global direct addresses */
407 AiopIO = CtlP->AiopIO[AiopNum];
408 ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
409 ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
410 ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
411 ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
412 ChP->IndexData = AiopIO + _INDX_DATA;
414 /* Channel direct addresses */
415 ChIOOff = AiopIO + ChP->ChanNum * 2;
416 ChP->TxRxData = ChIOOff + _TD0;
417 ChP->ChanStat = ChIOOff + _CHN_STAT0;
418 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
419 ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
421 /* Initialize the channel from the RData array */
422 for(i=0; i < RDATASIZE; i+=4)
425 R[1] = RData[i+1] + 0x10 * ChanNum;
428 sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
432 for(i=0; i < RREGDATASIZE; i+=4)
434 ChR[i] = RRegData[i];
435 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
436 ChR[i+2] = RRegData[i+2];
437 ChR[i+3] = RRegData[i+3];
440 /* Indexed registers */
441 ChOff = (Word_t)ChanNum * 0x1000;
443 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
444 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
445 ChP->BaudDiv[2] = (Byte_t)BRD9600;
446 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
447 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
449 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
450 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
451 ChP->TxControl[2] = 0;
452 ChP->TxControl[3] = 0;
453 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
455 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
456 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
457 ChP->RxControl[2] = 0;
458 ChP->RxControl[3] = 0;
459 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
461 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
462 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
463 ChP->TxEnables[2] = 0;
464 ChP->TxEnables[3] = 0;
465 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
467 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
468 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
469 ChP->TxCompare[2] = 0;
470 ChP->TxCompare[3] = 0;
471 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
473 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
474 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
475 ChP->TxReplace1[2] = 0;
476 ChP->TxReplace1[3] = 0;
477 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
479 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
480 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
481 ChP->TxReplace2[2] = 0;
482 ChP->TxReplace2[3] = 0;
483 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
485 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
486 ChP->TxFIFO = ChOff + _TX_FIFO;
488 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
489 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
490 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
491 sOutW(ChP->IndexData,0);
492 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
493 ChP->RxFIFO = ChOff + _RX_FIFO;
495 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
496 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
497 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
498 sOutW(ChP->IndexData,0);
499 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
500 sOutW(ChP->IndexData,0);
501 ChP->TxPrioCnt = ChOff + _TXP_CNT;
502 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
503 sOutB(ChP->IndexData,0);
504 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
505 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
506 sOutB(ChP->IndexData,0);
507 ChP->TxPrioBuf = ChOff + _TXP_BUF;
508 sEnRxProcessor(ChP); /* start the Rx processor */
513 /***************************************************************************
514 Function: sStopRxProcessor
515 Purpose: Stop the receive processor from processing a channel.
516 Call: sStopRxProcessor(ChP)
517 CHANNEL_T *ChP; Ptr to channel structure
519 Comments: The receive processor can be started again with sStartRxProcessor().
520 This function causes the receive processor to skip over the
521 stopped channel. It does not stop it from processing other channels.
523 Warnings: No context switches are allowed while executing this function.
525 Do not leave the receive processor stopped for more than one
528 After calling this function a delay of 4 uS is required to ensure
529 that the receive processor is no longer processing this channel.
531 void sStopRxProcessor(CHANNEL_T *ChP)
539 sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
542 /***************************************************************************
543 Function: sFlushRxFIFO
544 Purpose: Flush the Rx FIFO
545 Call: sFlushRxFIFO(ChP)
546 CHANNEL_T *ChP; Ptr to channel structure
548 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
549 while it is being flushed the receive processor is stopped
550 and the transmitter is disabled. After these operations a
551 4 uS delay is done before clearing the pointers to allow
552 the receive processor to stop. These items are handled inside
554 Warnings: No context switches are allowed while executing this function.
556 void sFlushRxFIFO(CHANNEL_T *ChP)
559 Byte_t Ch; /* channel number within AIOP */
560 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
562 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
563 return; /* don't need to flush */
565 RxFIFOEnabled = FALSE;
566 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
568 RxFIFOEnabled = TRUE;
569 sDisRxFIFO(ChP); /* disable it */
570 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
571 sInB(ChP->IntChan); /* depends on bus i/o timing */
573 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
574 Ch = (Byte_t)sGetChanNum(ChP);
575 sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
576 sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */
577 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
578 sOutW(ChP->IndexData,0);
579 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
580 sOutW(ChP->IndexData,0);
582 sEnRxFIFO(ChP); /* enable Rx FIFO */
585 /***************************************************************************
586 Function: sFlushTxFIFO
587 Purpose: Flush the Tx FIFO
588 Call: sFlushTxFIFO(ChP)
589 CHANNEL_T *ChP; Ptr to channel structure
591 Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
592 while it is being flushed the receive processor is stopped
593 and the transmitter is disabled. After these operations a
594 4 uS delay is done before clearing the pointers to allow
595 the receive processor to stop. These items are handled inside
597 Warnings: No context switches are allowed while executing this function.
599 void sFlushTxFIFO(CHANNEL_T *ChP)
602 Byte_t Ch; /* channel number within AIOP */
603 int TxEnabled; /* TRUE if transmitter enabled */
605 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
606 return; /* don't need to flush */
609 if(ChP->TxControl[3] & TX_ENABLE)
612 sDisTransmit(ChP); /* disable transmitter */
614 sStopRxProcessor(ChP); /* stop Rx processor */
615 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
616 sInB(ChP->IntChan); /* depends on bus i/o timing */
617 Ch = (Byte_t)sGetChanNum(ChP);
618 sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
619 sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */
620 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
621 sOutW(ChP->IndexData,0);
623 sEnTransmit(ChP); /* enable transmitter */
624 sStartRxProcessor(ChP); /* restart Rx processor */
627 /***************************************************************************
628 Function: sWriteTxPrioByte
629 Purpose: Write a byte of priority transmit data to a channel
630 Call: sWriteTxPrioByte(ChP,Data)
631 CHANNEL_T *ChP; Ptr to channel structure
632 Byte_t Data; The transmit data byte
634 Return: int: 1 if the bytes is successfully written, otherwise 0.
636 Comments: The priority byte is transmitted before any data in the Tx FIFO.
638 Warnings: No context switches are allowed while executing this function.
640 int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
642 Byte_t DWBuf[4]; /* buffer for double word writes */
643 Word_t *WordPtr; /* must be far because Win SS != DS */
644 register DWordIO_t IndexAddr;
646 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
648 IndexAddr = ChP->IndexAddr;
649 sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
650 if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
651 return(0); /* nothing sent */
653 WordPtr = (Word_t *)(&DWBuf[0]);
654 *WordPtr = ChP->TxPrioBuf; /* data byte address */
656 DWBuf[2] = Data; /* data byte value */
657 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
659 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
661 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
662 DWBuf[3] = 0; /* priority buffer pointer */
663 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
665 else /* write it to Tx FIFO */
667 sWriteTxByte(sGetTxRxDataIO(ChP),Data);
669 return(1); /* 1 byte sent */
672 /***************************************************************************
673 Function: sEnInterrupts
674 Purpose: Enable one or more interrupts for a channel
675 Call: sEnInterrupts(ChP,Flags)
676 CHANNEL_T *ChP; Ptr to channel structure
677 Word_t Flags: Interrupt enable flags, can be any combination
678 of the following flags:
679 TXINT_EN: Interrupt on Tx FIFO empty
680 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
682 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
683 MCINT_EN: Interrupt on modem input change
684 CHANINT_EN: Allow channel interrupt signal to the AIOP's
685 Interrupt Channel Register.
687 Comments: If an interrupt enable flag is set in Flags, that interrupt will be
688 enabled. If an interrupt enable flag is not set in Flags, that
689 interrupt will not be changed. Interrupts can be disabled with
690 function sDisInterrupts().
692 This function sets the appropriate bit for the channel in the AIOP's
693 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
694 this channel's bit to be set in the AIOP's Interrupt Channel Register.
696 Interrupts must also be globally enabled before channel interrupts
697 will be passed on to the host. This is done with function
700 In some cases it may be desirable to disable interrupts globally but
701 enable channel interrupts. This would allow the global interrupt
702 status register to be used to determine which AIOPs need service.
704 void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
706 Byte_t Mask; /* Interrupt Mask Register */
709 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
711 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
713 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
715 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
717 if(Flags & CHANINT_EN)
719 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
720 sOutB(ChP->IntMask,Mask);
724 /***************************************************************************
725 Function: sDisInterrupts
726 Purpose: Disable one or more interrupts for a channel
727 Call: sDisInterrupts(ChP,Flags)
728 CHANNEL_T *ChP; Ptr to channel structure
729 Word_t Flags: Interrupt flags, can be any combination
730 of the following flags:
731 TXINT_EN: Interrupt on Tx FIFO empty
732 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
734 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
735 MCINT_EN: Interrupt on modem input change
736 CHANINT_EN: Disable channel interrupt signal to the
737 AIOP's Interrupt Channel Register.
739 Comments: If an interrupt flag is set in Flags, that interrupt will be
740 disabled. If an interrupt flag is not set in Flags, that
741 interrupt will not be changed. Interrupts can be enabled with
742 function sEnInterrupts().
744 This function clears the appropriate bit for the channel in the AIOP's
745 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
746 this channel's bit from being set in the AIOP's Interrupt Channel
749 void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
751 Byte_t Mask; /* Interrupt Mask Register */
754 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
755 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
756 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
757 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
759 if(Flags & CHANINT_EN)
761 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
762 sOutB(ChP->IntMask,Mask);
766 /*********************************************************************
767 Begin FreeBsd-specific driver code
768 **********************************************************************/
770 static int rpprobe __P((struct isa_device *));
771 static int rpattach __P((struct isa_device *));
773 static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
774 static void rp_pciattach(pcici_t tag, int unit);
775 static u_long rp_pcicount;
777 static struct pci_device rp_pcidevice = {
785 COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
787 static timeout_t rpdtrwakeup;
789 struct isa_driver rpdriver = {
790 rpprobe, rpattach, "rp"
793 static char driver_name[] = "rp";
795 static d_open_t rpopen;
796 static d_close_t rpclose;
797 static d_read_t rpread;
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,
819 static int rp_controller_port = 0;
820 static int rp_num_ports_open = 0;
821 static int ndevs = 0;
822 static int minor_to_unit[128];
824 static struct tty rp_tty[128];
827 static int rp_num_ports[4]; /* Number of ports on each controller */
829 #define _INLINE_ __inline
830 #define POLL_INTERVAL 1
832 #define CALLOUT_MASK 0x80
833 #define CONTROL_MASK 0x60
834 #define CONTROL_INIT_STATE 0x20
835 #define CONTROL_LOCK_STATE 0x40
836 #define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
837 #define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
838 #define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
839 #define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
840 #define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
842 #define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
843 #define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
844 #define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
846 static struct rp_port *p_rp_addr[4];
847 static struct rp_port *p_rp_table[MAX_RP_PORTS];
848 #define rp_addr(unit) (p_rp_addr[unit])
849 #define rp_table(port) (p_rp_table[port])
852 * The top-level routines begin here
855 static int rpparam __P((struct tty *, struct termios *));
856 static void rpstart __P((struct tty *));
857 static void rpstop __P((struct tty *, int));
858 static void rphardclose __P((struct rp_port *));
860 #define rpreset noreset
861 #define rpstrategy nostrategy
862 static void rp_disc_optim __P((struct tty *tp, struct termios *t,
863 struct rp_port *rp));
865 static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
866 CHANNEL_t *cp, unsigned int ChanStatus)
869 unsigned int CharNStat;
872 ToRecv = sGetRxCnt(cp);
876 /* If status indicates there are errored characters in the
877 FIFO, then enter status mode (a word in FIFO holds
878 characters and status)
881 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
882 if(!(ChanStatus & STATMODE)) {
883 ChanStatus |= STATMODE;
888 if we previously entered status mode then read down the
889 FIFO one word at a time, pulling apart the character and
890 the status. Update error counters depending on status.
892 if(ChanStatus & STATMODE) {
894 if(tp->t_state & TS_TBLOCK) {
897 CharNStat = sInW(sGetTxRxDataIO(cp));
898 ch = CharNStat & 0xff;
900 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
902 else if (CharNStat & STMPARITYH)
904 else if (CharNStat & STMRCVROVRH)
907 (*linesw[tp->t_line].l_rint)(ch, tp);
911 After emtying FIFO in status mode, turn off status mode
914 if(sGetRxCnt(cp) == 0)
915 sDisRxStatusMode(cp);
919 if(tp->t_state & TS_TBLOCK) {
922 ch = (u_char) sInB(sGetTxRxDataIO(cp));
924 (*linesw[tp->t_line].l_rint)(ch, tp);
931 static _INLINE_ void rp_handle_port(struct rp_port *rp)
935 unsigned int IntMask, ChanStatus;
941 cp = &rp->rp_channel;
943 IntMask = sGetChanIntID(cp);
944 IntMask = IntMask & rp->rp_intmask;
945 ChanStatus = sGetChanStatus(cp);
946 if(IntMask & RXF_TRIG)
947 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
948 rp_do_receive(rp, tp, cp, ChanStatus);
950 if(IntMask & DELTA_CD) {
951 if(ChanStatus & CD_ACT) {
952 if(!(tp->t_state & TS_CARR_ON) ) {
953 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
956 if((tp->t_state & TS_CARR_ON)) {
957 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
958 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
964 /* oldcts = rp->rp_cts;
965 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
966 if(oldcts != rp->rp_cts) {
967 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
972 static void rp_do_poll(void *not_used)
977 int unit, aiop, ch, line, count;
978 unsigned char CtlMask, AiopMask;
980 for(unit = 0; unit <= ndevs; unit++) {
983 if(ctl->BusType == isPCI)
984 CtlMask = sPCIGetControllerIntStatus(ctl);
986 CtlMask = sGetControllerIntStatus(ctl);
987 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
989 AiopMask = sGetAiopIntStatus(ctl, aiop);
990 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
992 line = (unit << 5) | (aiop << 3) | ch;
1000 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
1003 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1004 count = sGetTxCnt(&rp->rp_channel);
1006 tp->t_state &= ~(TS_BUSY);
1007 if(!(tp->t_state & TS_TTSTOP) &&
1008 (count <= rp->rp_restart)) {
1009 (*linesw[tp->t_line].l_start)(tp);
1014 if(rp_num_ports_open)
1015 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1019 rp_pciprobe(pcici_t tag, pcidi_t type)
1023 vendor_id = type & 0xffff;
1033 struct isa_device *dev;
1035 int controller, unit;
1036 int aiop, num_aiops;
1037 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1040 unit = dev->id_unit;
1041 if (dev->id_unit >= 4) {
1042 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1045 printf("probing for RocketPort(ISA) unit %d\n", unit);
1046 if (rp_controller_port)
1047 controller = rp_controller_port;
1049 controller = dev->id_iobase + 0x40;
1052 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1053 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1055 ctlp = sCtlNumToCtlPtr(dev->id_unit);
1056 num_aiops = sInitController(ctlp, dev->id_unit,
1057 controller + ((unit-rp_pcicount)*0x400),
1058 aiopio, MAX_AIOPS_PER_BOARD, 0,
1060 if (num_aiops <= 0) {
1061 printf("board%d init failed\n", unit);
1065 if (rp_controller_port) {
1069 rp_controller_port = controller;
1078 rp_pciattach(pcici_t tag, int unit)
1080 int success, oldspl;
1082 int num_ports, num_chan, num_aiops;
1083 int aiop, chan, port;
1084 int ChanStatus, line, i, count;
1085 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1090 success = pci_map_port(tag, 0x10, &iobase);
1092 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1094 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1095 aiopio[aiop] = iobase + (aiop * 0x40);
1097 ctlp = sCtlNumToCtlPtr(unit);
1098 num_aiops = sPCIInitController(ctlp, unit,
1099 aiopio, MAX_AIOPS_PER_BOARD, 0,
1103 for(aiop=0; aiop < num_aiops; aiop++) {
1104 sResetAiopByNum(ctlp, aiop);
1105 num_ports += sGetAiopNumChan(ctlp, aiop);
1107 printf("RocketPort%d = %d ports\n", unit, num_ports);
1108 rp_num_ports[unit] = num_ports;
1110 rp = (struct rp_port *)
1111 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1113 printf("rp_attach: Could not malloc rp_ports structures\n");
1117 count = unit * 32; /* board times max ports per card SG */
1118 for(i=count;i < (count + rp_num_ports[unit]);i++)
1119 minor_to_unit[i] = unit;
1121 bzero(rp, sizeof(struct rp_port) * num_ports);
1122 tty = (struct tty *)
1123 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1125 printf("rp_attach: Could not malloc tty structures\n");
1128 bzero(tty, sizeof(struct tty) * num_ports);
1134 cdevsw_add(&rp_cdevsw);
1137 for(aiop=0; aiop < num_aiops; aiop++) {
1138 num_chan = sGetAiopNumChan(ctlp, aiop);
1139 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1148 /* tty->t_termios = deftermios;
1150 rp->dtr_wait = 3 * hz;
1151 rp->it_in.c_iflag = 0;
1152 rp->it_in.c_oflag = 0;
1153 rp->it_in.c_cflag = TTYDEF_CFLAG;
1154 rp->it_in.c_lflag = 0;
1155 termioschars(&rp->it_in);
1156 /* termioschars(&tty->t_termios);
1158 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1159 rp->it_out = rp->it_in;
1161 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1162 DELTA_CD | DELTA_CTS | DELTA_DSR;
1163 ChanStatus = sGetChanStatus(&rp->rp_channel);
1164 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1165 printf("RocketPort sInitChan(%d, %d, %d) failed
1166 \n", unit, aiop, chan);
1169 ChanStatus = sGetChanStatus(&rp->rp_channel);
1170 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1171 line = (unit << 5) | (aiop << 3) | chan;
1172 rp_table(line) = rp;
1180 struct isa_device *dev;
1182 int iobase, unit, /*rpmajor,*/ oldspl;
1183 int num_ports, num_chan, num_aiops;
1184 int aiop, chan, port;
1185 int ChanStatus, line, i, count;
1186 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1191 iobase = dev->id_iobase;
1192 unit = dev->id_unit;
1195 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1196 aiopio[aiop] = iobase + (aiop * 0x400);
1198 ctlp = sCtlNumToCtlPtr(unit);
1199 num_aiops = sInitController(ctlp, unit,
1200 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1201 aiopio, MAX_AIOPS_PER_BOARD, 0,
1205 for(aiop=0; aiop < num_aiops; aiop++) {
1206 sResetAiopByNum(ctlp, aiop);
1207 sEnAiop(ctlp, aiop);
1208 num_ports += sGetAiopNumChan(ctlp, aiop);
1210 printf("RocketPort%d = %d ports\n", unit, num_ports);
1211 rp_num_ports[unit] = num_ports;
1213 rp = (struct rp_port *)
1214 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1216 printf("rp_attach: Could not malloc rp_ports structures\n");
1220 count = unit * 32; /* board # times max ports per card SG */
1221 for(i=count;i < (count + rp_num_ports[unit]);i++)
1222 minor_to_unit[i] = unit;
1224 bzero(rp, sizeof(struct rp_port) * num_ports);
1225 tty = (struct tty *)
1226 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1228 printf("rp_attach: Could not malloc tty structures\n");
1231 bzero(tty, sizeof(struct tty) * num_ports);
1237 cdevsw_add(&rp_cdevsw);
1240 for(aiop=0; aiop < num_aiops; aiop++) {
1241 num_chan = sGetAiopNumChan(ctlp, aiop);
1242 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1251 /* tty->t_termios = deftermios;
1253 rp->dtr_wait = 3 * hz;
1254 rp->it_in.c_iflag = 0;
1255 rp->it_in.c_oflag = 0;
1256 rp->it_in.c_cflag = TTYDEF_CFLAG;
1257 rp->it_in.c_lflag = 0;
1258 termioschars(&rp->it_in);
1259 /* termioschars(&tty->t_termios);
1261 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1262 rp->it_out = rp->it_in;
1264 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1265 DELTA_CD | DELTA_CTS | DELTA_DSR;
1266 ChanStatus = sGetChanStatus(&rp->rp_channel);
1267 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1268 printf("RocketPort sInitChan(%d, %d, %d) failed
1269 \n", unit, aiop, chan);
1272 ChanStatus = sGetChanStatus(&rp->rp_channel);
1273 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1274 line = (unit << 5) | (aiop << 3) | chan;
1275 rp_table(line) = rp;
1283 rpopen(dev, flag, mode, p)
1289 int unit, port, mynor, umynor, flags; /* SG */
1292 unsigned int IntMask, ChanStatus;
1295 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1296 port = (minor(dev) & 0x1f); /* SG */
1297 mynor = (port + umynor); /* SG */
1298 unit = minor_to_unit[mynor];
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, TTIPRI | 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,
1329 TTIPRI | PCATCH, "rpbi", 0);
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), TTIPRI | PCATCH,
1416 error = (*linesw[tp->t_line].l_open)(dev, tp);
1418 rp_disc_optim(tp, &tp->t_termios, rp);
1419 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1420 rp->active_out = TRUE;
1422 /* if(rp_num_ports_open == 1)
1423 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1427 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1434 rpclose(dev, flag, mode, p)
1439 int oldspl, unit, mynor, umynor, port; /* SG */
1444 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1445 port = (minor(dev) & 0x1f); /* SG */
1446 mynor = (port + umynor); /* SG */
1447 unit = minor_to_unit[mynor]; /* SG */
1451 rp = rp_addr(unit) + port;
1452 cp = &rp->rp_channel;
1456 (*linesw[tp->t_line].l_close)(tp, flag);
1457 rp_disc_optim(tp, &tp->t_termios, rp);
1458 rpstop(tp, FREAD | FWRITE);
1461 tp->t_state &= ~TS_BUSY;
1470 rphardclose(struct rp_port *rp)
1476 cp = &rp->rp_channel;
1478 mynor = MINOR_MAGIC(tp->t_dev);
1483 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1486 sDisTxSoftFlowCtl(cp);
1489 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1492 if(IS_CALLOUT(tp->t_dev)) {
1495 if(rp->dtr_wait != 0) {
1496 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1497 rp->state |= ~SET_DTR;
1500 rp->active_out = FALSE;
1501 wakeup(&rp->active_out);
1502 wakeup(TSA_CARR_ON(tp));
1507 rpread(dev, uio, flag)
1514 int unit, mynor, umynor, port, error = 0; /* SG */
1516 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1517 port = (minor(dev) & 0x1f); /* SG */
1518 mynor = (port + umynor); /* SG */
1519 unit = minor_to_unit[mynor]; /* SG */
1523 rp = rp_addr(unit) + port;
1525 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
1531 rpwrite(dev, uio, flag)
1538 int unit, mynor, port, umynor, error = 0; /* SG */
1540 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1541 port = (minor(dev) & 0x1f); /* SG */
1542 mynor = (port + umynor); /* SG */
1543 unit = minor_to_unit[mynor]; /* SG */
1547 rp = rp_addr(unit) + port;
1549 while(rp->rp_disable_writes) {
1551 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1556 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1561 rpdtrwakeup(void *chan)
1565 rp = (struct rp_port *)chan;
1566 rp->state &= SET_DTR;
1567 wakeup(&rp->dtr_wait);
1571 rpioctl(dev, cmd, data, flag, p)
1581 int unit, mynor, port, umynor; /* SG */
1584 int arg, flags, result, ChanStatus;
1586 struct termios term, *t;
1588 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1589 port = (minor(dev) & 0x1f); /* SG */
1590 mynor = (port + umynor); /* SG */
1591 unit = minor_to_unit[mynor];
1592 rp = rp_addr(unit) + port;
1594 if(IS_CONTROL(dev)) {
1597 switch (IS_CONTROL(dev)) {
1598 case CONTROL_INIT_STATE:
1599 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1601 case CONTROL_LOCK_STATE:
1602 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1605 return(ENODEV); /* /dev/nodev */
1612 *ct = *(struct termios *)data;
1615 *(struct termios *)data = *ct;
1618 *(int *)data = TTYDISC;
1621 bzero(data, sizeof(struct winsize));
1629 cp = &rp->rp_channel;
1631 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1632 term = tp->t_termios;
1634 error = ttsetcompat(tp, &cmd, data, &term);
1638 data = (caddr_t)&term;
1641 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1643 struct termios *dt = (struct termios *)data;
1644 struct termios *lt = IS_CALLOUT(dev)
1645 ? &rp->lt_out : &rp->lt_in;
1647 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1648 | (dt->c_iflag & ~lt->c_iflag);
1649 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1650 | (dt->c_oflag & ~lt->c_oflag);
1651 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1652 | (dt->c_cflag & ~lt->c_cflag);
1653 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1654 | (dt->c_lflag & ~lt->c_lflag);
1655 for(cc = 0; cc < NCCS; ++cc)
1656 if((lt->c_cc[cc] = tp->t_cc[cc]) != 0)
1657 dt->c_cc[cc] = tp->t_cc[cc];
1658 if(lt->c_ispeed != 0)
1659 dt->c_ispeed = tp->t_ispeed;
1660 if(lt->c_ospeed != 0)
1661 dt->c_ospeed = tp->t_ospeed;
1666 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1667 if(error != ENOIOCTL) {
1672 flags = rp->rp_channel.TxControl[3];
1674 error = ttioctl(tp, cmd, data, flag);
1675 flags = rp->rp_channel.TxControl[3];
1676 rp_disc_optim(tp, &tp->t_termios, rp);
1677 if(error != ENOIOCTL) {
1683 sSendBreak(&rp->rp_channel);
1687 sClrBreak(&rp->rp_channel);
1691 sSetDTR(&rp->rp_channel);
1692 sSetRTS(&rp->rp_channel);
1696 sClrDTR(&rp->rp_channel);
1700 arg = *(int *) data;
1706 rp->rp_channel.TxControl[3] =
1707 ((rp->rp_channel.TxControl[3]
1708 & ~(SET_RTS | SET_DTR)) | flags);
1709 sOutDW(rp->rp_channel.IndexAddr,
1710 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1713 arg = *(int *) data;
1719 rp->rp_channel.TxControl[3] |= flags;
1720 sOutDW(rp->rp_channel.IndexAddr,
1721 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1724 arg = *(int *) data;
1730 rp->rp_channel.TxControl[3] &= ~flags;
1731 sOutDW(rp->rp_channel.IndexAddr,
1732 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1737 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1738 flags = rp->rp_channel.TxControl[3];
1739 result = TIOCM_LE; /* always on while open for some reason */
1740 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1741 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1742 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1743 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1744 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1746 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1748 result |= TIOCM_RTS;
1751 *(int *)data = result;
1759 rp->dtr_wait = *(int *)data * hz/100;
1762 *(int *)data = rp->dtr_wait * 100/hz;
1772 static struct speedtab baud_table[] = {
1773 B0, 0, B50, BRD50, B75, BRD75,
1774 B110, BRD110, B134, BRD134, B150, BRD150,
1775 B200, BRD200, B300, BRD300, B600, BRD600,
1776 B1200, BRD1200, B1800, BRD1800, B2400, BRD2400,
1777 B4800, BRD4800, B9600, BRD9600, B19200, BRD19200,
1778 B38400, BRD38400, B7200, BRD7200, B14400, BRD14400,
1779 B57600, BRD57600, B76800, BRD76800,
1780 B115200, BRD115200, B230400, BRD230400,
1791 int unit, mynor, port, umynor; /* SG */
1792 int oldspl, cflag, iflag, oflag, lflag;
1796 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1797 port = (minor(tp->t_dev) & 0x1f); /* SG */
1798 mynor = (port + umynor); /* SG */
1800 unit = minor_to_unit[mynor];
1801 rp = rp_addr(unit) + port;
1802 cp = &rp->rp_channel;
1810 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1811 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1814 tp->t_ispeed = t->c_ispeed;
1815 tp->t_ospeed = t->c_ospeed;
1816 tp->t_cflag = cflag;
1817 tp->t_iflag = iflag;
1818 tp->t_oflag = oflag;
1819 tp->t_lflag = lflag;
1821 if(t->c_ospeed == 0) {
1825 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1827 /* Set baud rate ----- we only pay attention to ispeed */
1830 sSetBaud(cp, ospeed);
1832 if(cflag & CSTOPB) {
1838 if(cflag & PARENB) {
1840 if(cflag & PARODD) {
1849 if((cflag & CSIZE) == CS8) {
1851 rp->rp_imask = 0xFF;
1854 rp->rp_imask = 0x7F;
1857 if(iflag & ISTRIP) {
1858 rp->rp_imask &= 0x7F;
1861 if(cflag & CLOCAL) {
1862 rp->rp_intmask &= ~DELTA_CD;
1864 rp->rp_intmask |= DELTA_CD;
1867 /* Put flow control stuff here */
1869 if(cflag & CCTS_OFLOW) {
1875 if(cflag & CRTS_IFLOW) {
1876 rp->rp_rts_iflow = 1;
1878 rp->rp_rts_iflow = 0;
1881 if(cflag & CRTS_IFLOW) {
1886 rp_disc_optim(tp, t, rp);
1888 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1889 tp->t_state |= TS_CARR_ON;
1890 wakeup(TSA_CARR_ON(tp));
1893 /* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1894 flags = rp->rp_channel.TxControl[3];
1906 rp_disc_optim(tp, t, rp)
1911 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1912 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1913 &&(!(t->c_iflag & PARMRK)
1914 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1915 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1916 && linesw[tp->t_line].l_rint == ttyinput)
1917 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1919 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1929 int unit, mynor, port, umynor; /* SG */
1931 int spl, xmit_fifo_room;
1935 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1936 port = (minor(tp->t_dev) & 0x1f); /* SG */
1937 mynor = (port + umynor); /* SG */
1938 unit = minor_to_unit[mynor];
1939 rp = rp_addr(unit) + port;
1940 cp = &rp->rp_channel;
1941 flags = rp->rp_channel.TxControl[3];
1944 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1949 if(rp->rp_xmit_stopped) {
1951 rp->rp_xmit_stopped = 0;
1953 count = sGetTxCnt(cp);
1955 if(tp->t_outq.c_cc == 0) {
1956 if((tp->t_state & TS_BUSY) && (count == 0)) {
1957 tp->t_state &= ~TS_BUSY;
1963 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1966 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1967 tp->t_state |= TS_BUSY;
1969 while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1971 sOutB(sGetTxRxDataIO(cp), ch);
1975 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1984 register struct tty *tp;
1989 int unit, mynor, port, umynor; /* SG */
1992 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1993 port = (minor(tp->t_dev) & 0x1f); /* SG */
1994 mynor = (port + umynor); /* SG */
1995 unit = minor_to_unit[mynor];
1996 rp = rp_addr(unit) + port;
1997 cp = &rp->rp_channel;
2001 if(tp->t_state & TS_BUSY) {
2002 if((tp->t_state&TS_TTSTOP) == 0) {
2005 if(rp->rp_xmit_stopped == 0) {
2007 rp->rp_xmit_stopped = 1;