Fix broken string literals
[dragonfly.git] / sys / dev / serial / rp2 / rp.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) Comtrol Corporation <support@comtrol.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted prodived that the follwoing conditions
7 * are met.
8 * 1. Redistributions of source code must retain the above copyright
9 * notive, this list of conditions and the following disclainer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials prodided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Comtrol Corporation.
16 * 4. The name of Comtrol Corporation may not be used to endorse or
17 * promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: src/sys/i386/isa/rp.c,v 1.33.2.2 2001/02/26 04:23:10 jlemon Exp $
2a53dae6 33 * $DragonFly: src/sys/dev/serial/rp2/Attic/rp.c,v 1.10 2004/02/13 13:43:21 joerg Exp $
984263bc
MD
34 */
35
36/*
37 * rp.c - for RocketPort FreeBSD
38 */
39
40#include "opt_compat.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/fcntl.h>
45#include <sys/malloc.h>
46#include <sys/tty.h>
47#include <sys/proc.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50
1f2de5d4 51#include <bus/isa/i386/isa_device.h>
984263bc 52
1f2de5d4 53#include <bus/pci/pcivar.h>
984263bc
MD
54
55#define ROCKET_C
1f2de5d4
MD
56#include "rpreg.h"
57#include "rpvar.h"
984263bc
MD
58
59#ifndef TRUE
60#define TRUE 1
61#endif
62
63#ifndef FALSE
64#define FALSE 0
65#endif
66
67static Byte_t RData[RDATASIZE] =
68{
69 0x00, 0x09, 0xf6, 0x82,
70 0x02, 0x09, 0x86, 0xfb,
71 0x04, 0x09, 0x00, 0x0a,
72 0x06, 0x09, 0x01, 0x0a,
73 0x08, 0x09, 0x8a, 0x13,
74 0x0a, 0x09, 0xc5, 0x11,
75 0x0c, 0x09, 0x86, 0x85,
76 0x0e, 0x09, 0x20, 0x0a,
77 0x10, 0x09, 0x21, 0x0a,
78 0x12, 0x09, 0x41, 0xff,
79 0x14, 0x09, 0x82, 0x00,
80 0x16, 0x09, 0x82, 0x7b,
81 0x18, 0x09, 0x8a, 0x7d,
82 0x1a, 0x09, 0x88, 0x81,
83 0x1c, 0x09, 0x86, 0x7a,
84 0x1e, 0x09, 0x84, 0x81,
85 0x20, 0x09, 0x82, 0x7c,
86 0x22, 0x09, 0x0a, 0x0a
87};
88
89static Byte_t RRegData[RREGDATASIZE]=
90{
91 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
92 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
93 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
94 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
95 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
96 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
97 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
98 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
99 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
100 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
101 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
102 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
103 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
104};
105
106static CONTROLLER_T sController[CTL_SIZE] =
107{
108 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
109 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
110 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
111 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
112};
113
114#if 0
115/* IRQ number to MUDBAC register 2 mapping */
116Byte_t sIRQMap[16] =
117{
118 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
119};
120#endif
121
122static Byte_t sBitMapClrTbl[8] =
123{
124 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
125};
126
127static Byte_t sBitMapSetTbl[8] =
128{
129 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
130};
131
132/***************************************************************************
133Function: sInitController
134Purpose: Initialization of controller global registers and controller
135 structure.
136Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
137 IRQNum,Frequency,PeriodicOnly)
138 CONTROLLER_T *CtlP; Ptr to controller structure
139 int CtlNum; Controller number
140 ByteIO_t MudbacIO; Mudbac base I/O address.
141 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
142 This list must be in the order the AIOPs will be found on the
143 controller. Once an AIOP in the list is not found, it is
144 assumed that there are no more AIOPs on the controller.
145 int AiopIOListSize; Number of addresses in AiopIOList
146 int IRQNum; Interrupt Request number. Can be any of the following:
147 0: Disable global interrupts
148 3: IRQ 3
149 4: IRQ 4
150 5: IRQ 5
151 9: IRQ 9
152 10: IRQ 10
153 11: IRQ 11
154 12: IRQ 12
155 15: IRQ 15
156 Byte_t Frequency: A flag identifying the frequency
157 of the periodic interrupt, can be any one of the following:
158 FREQ_DIS - periodic interrupt disabled
159 FREQ_137HZ - 137 Hertz
160 FREQ_69HZ - 69 Hertz
161 FREQ_34HZ - 34 Hertz
162 FREQ_17HZ - 17 Hertz
163 FREQ_9HZ - 9 Hertz
164 FREQ_4HZ - 4 Hertz
165 If IRQNum is set to 0 the Frequency parameter is
166 overidden, it is forced to a value of FREQ_DIS.
167 int PeriodicOnly: TRUE if all interrupts except the periodic
168 interrupt are to be blocked.
169 FALSE is both the periodic interrupt and
170 other channel interrupts are allowed.
171 If IRQNum is set to 0 the PeriodicOnly parameter is
172 overidden, it is forced to a value of FALSE.
173Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
174 initialization failed.
175
176Comments:
177 If periodic interrupts are to be disabled but AIOP interrupts
178 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
179
180 If interrupts are to be completely disabled set IRQNum to 0.
181
182 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
183 invalid combination.
184
185 This function performs initialization of global interrupt modes,
186 but it does not actually enable global interrupts. To enable
187 and disable global interrupts use functions sEnGlobalInt() and
188 sDisGlobalInt(). Enabling of global interrupts is normally not
189 done until all other initializations are complete.
190
191 Even if interrupts are globally enabled, they must also be
192 individually enabled for each channel that is to generate
193 interrupts.
194
195Warnings: No range checking on any of the parameters is done.
196
197 No context switches are allowed while executing this function.
198
199 After this function all AIOPs on the controller are disabled,
200 they can be enabled with sEnAiop().
201*/
202int sInitController( CONTROLLER_T *CtlP,
203 int CtlNum,
204 ByteIO_t MudbacIO,
205 ByteIO_t *AiopIOList,
206 int AiopIOListSize,
207 int IRQNum,
208 Byte_t Frequency,
209 int PeriodicOnly)
210{
211 int i;
212 ByteIO_t io;
213
214 CtlP->CtlNum = CtlNum;
215 CtlP->BusType = isISA;
216 CtlP->CtlID = CTLID_0001; /* controller release 1 */
217
218 CtlP->MBaseIO = MudbacIO;
219 CtlP->MReg1IO = MudbacIO + 1;
220 CtlP->MReg2IO = MudbacIO + 2;
221 CtlP->MReg3IO = MudbacIO + 3;
222#if 1
223 CtlP->MReg2 = 0; /* interrupt disable */
224 CtlP->MReg3 = 0; /* no periodic interrupts */
225#else
226 if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */
227 {
228 CtlP->MReg2 = 0; /* interrupt disable */
229 CtlP->MReg3 = 0; /* no periodic interrupts */
230 }
231 else
232 {
233 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
234 CtlP->MReg3 = Frequency; /* set frequency */
235 if(PeriodicOnly) /* periodic interrupt only */
236 {
237 CtlP->MReg3 |= PERIODIC_ONLY;
238 }
239 }
240#endif
241 sOutB(CtlP->MReg2IO,CtlP->MReg2);
242 sOutB(CtlP->MReg3IO,CtlP->MReg3);
243 sControllerEOI(CtlP); /* clear EOI if warm init */
244
245 /* Init AIOPs */
246 CtlP->NumAiop = 0;
247 for(i=0; i < AiopIOListSize; i++)
248 {
249 io = AiopIOList[i];
250 CtlP->AiopIO[i] = (WordIO_t)io;
251 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
252 sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
253 sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
254 sEnAiop(CtlP,i); /* enable the AIOP */
255
256 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
257 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
258 {
259 sDisAiop(CtlP,i); /* disable AIOP */
260 break; /* done looking for AIOPs */
261 }
262
263 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
264 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
265 sOutB(io + _INDX_DATA,CLOCK_PRESC);
266 CtlP->NumAiop++; /* bump count of AIOPs */
267 sDisAiop(CtlP,i); /* disable AIOP */
268 }
269
270 if(CtlP->NumAiop == 0)
271 return(-1);
272 else
273 return(CtlP->NumAiop);
274}
275
276int sPCIInitController( CONTROLLER_T *CtlP,
277 int CtlNum,
278 ByteIO_t *AiopIOList,
279 int AiopIOListSize,
280 int IRQNum,
281 Byte_t Frequency,
282 int PeriodicOnly)
283{
284 int i;
285 ByteIO_t io;
286
287 CtlP->CtlNum = CtlNum;
288 CtlP->BusType = isPCI;
289 CtlP->CtlID = CTLID_0001; /* controller release 1 */
290 CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
291
292 sPCIControllerEOI(CtlP);
293
294 /* Init AIOPs */
295 CtlP->NumAiop = 0;
296 for(i=0; i < AiopIOListSize; i++)
297 {
298 io = AiopIOList[i];
299 CtlP->AiopIO[i] = (WordIO_t)io;
300 CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
301
302 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
303 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
304 {
305 break; /* done looking for AIOPs */
306 }
307
308 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
309 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
310 sOutB(io + _INDX_DATA,CLOCK_PRESC);
311 CtlP->NumAiop++; /* bump count of AIOPs */
312 }
313
314 if(CtlP->NumAiop == 0)
315 return(-1);
316 else
317 return(CtlP->NumAiop);
318}
319
320/***************************************************************************
321Function: sReadAiopID
322Purpose: Read the AIOP idenfication number directly from an AIOP.
323Call: sReadAiopID(io)
324 ByteIO_t io: AIOP base I/O address
325Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
326 is replace by an identifying number.
327 Flag AIOPID_NULL if no valid AIOP is found
328Warnings: No context switches are allowed while executing this function.
329
330*/
331int sReadAiopID(ByteIO_t io)
332{
333 Byte_t AiopID; /* ID byte from AIOP */
334
335 sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */
336 sOutB(io + _CMD_REG,0x0);
337 AiopID = sInB(io + _CHN_STAT0) & 0x07;
338 if(AiopID == 0x06)
339 return(1);
340 else /* AIOP does not exist */
341 return(-1);
342}
343
344/***************************************************************************
345Function: sReadAiopNumChan
346Purpose: Read the number of channels available in an AIOP directly from
347 an AIOP.
348Call: sReadAiopNumChan(io)
349 WordIO_t io: AIOP base I/O address
350Return: int: The number of channels available
351Comments: The number of channels is determined by write/reads from identical
352 offsets within the SRAM address spaces for channels 0 and 4.
353 If the channel 4 space is mirrored to channel 0 it is a 4 channel
354 AIOP, otherwise it is an 8 channel.
355Warnings: No context switches are allowed while executing this function.
356*/
357int sReadAiopNumChan(WordIO_t io)
358{
359 Word_t x;
360
361 sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
362 sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */
363 x = sInW(io + _INDX_DATA);
364 sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
365 if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
366 return(8);
367 else
368 return(4);
369}
370
371/***************************************************************************
372Function: sInitChan
373Purpose: Initialization of a channel and channel structure
374Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
375 CONTROLLER_T *CtlP; Ptr to controller structure
376 CHANNEL_T *ChP; Ptr to channel structure
377 int AiopNum; AIOP number within controller
378 int ChanNum; Channel number within AIOP
379Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
380 number exceeds number of channels available in AIOP.
381Comments: This function must be called before a channel can be used.
382Warnings: No range checking on any of the parameters is done.
383
384 No context switches are allowed while executing this function.
385*/
386int sInitChan( CONTROLLER_T *CtlP,
387 CHANNEL_T *ChP,
388 int AiopNum,
389 int ChanNum)
390{
391 int i;
392 WordIO_t AiopIO;
393 WordIO_t ChIOOff;
394 Byte_t *ChR;
395 Word_t ChOff;
396 static Byte_t R[4];
397
398 if(ChanNum >= CtlP->AiopNumChan[AiopNum])
399 return(FALSE); /* exceeds num chans in AIOP */
400
401 /* Channel, AIOP, and controller identifiers */
402 ChP->CtlP = CtlP;
403 ChP->ChanID = CtlP->AiopID[AiopNum];
404 ChP->AiopNum = AiopNum;
405 ChP->ChanNum = ChanNum;
406
407 /* Global direct addresses */
408 AiopIO = CtlP->AiopIO[AiopNum];
409 ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
410 ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
411 ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
412 ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
413 ChP->IndexData = AiopIO + _INDX_DATA;
414
415 /* Channel direct addresses */
416 ChIOOff = AiopIO + ChP->ChanNum * 2;
417 ChP->TxRxData = ChIOOff + _TD0;
418 ChP->ChanStat = ChIOOff + _CHN_STAT0;
419 ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
420 ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
421
422 /* Initialize the channel from the RData array */
423 for(i=0; i < RDATASIZE; i+=4)
424 {
425 R[0] = RData[i];
426 R[1] = RData[i+1] + 0x10 * ChanNum;
427 R[2] = RData[i+2];
428 R[3] = RData[i+3];
429 sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
430 }
431
432 ChR = ChP->R;
433 for(i=0; i < RREGDATASIZE; i+=4)
434 {
435 ChR[i] = RRegData[i];
436 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
437 ChR[i+2] = RRegData[i+2];
438 ChR[i+3] = RRegData[i+3];
439 }
440
441 /* Indexed registers */
442 ChOff = (Word_t)ChanNum * 0x1000;
443
444 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
445 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
446 ChP->BaudDiv[2] = (Byte_t)BRD9600;
447 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8);
448 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
449
450 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
451 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
452 ChP->TxControl[2] = 0;
453 ChP->TxControl[3] = 0;
454 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
455
456 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
457 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
458 ChP->RxControl[2] = 0;
459 ChP->RxControl[3] = 0;
460 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
461
462 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
463 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
464 ChP->TxEnables[2] = 0;
465 ChP->TxEnables[3] = 0;
466 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
467
468 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
469 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
470 ChP->TxCompare[2] = 0;
471 ChP->TxCompare[3] = 0;
472 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
473
474 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
475 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
476 ChP->TxReplace1[2] = 0;
477 ChP->TxReplace1[3] = 0;
478 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
479
480 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
481 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
482 ChP->TxReplace2[2] = 0;
483 ChP->TxReplace2[3] = 0;
484 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
485
486 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
487 ChP->TxFIFO = ChOff + _TX_FIFO;
488
489 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
490 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
491 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
492 sOutW(ChP->IndexData,0);
493 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
494 ChP->RxFIFO = ChOff + _RX_FIFO;
495
496 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
497 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
498 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
499 sOutW(ChP->IndexData,0);
500 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
501 sOutW(ChP->IndexData,0);
502 ChP->TxPrioCnt = ChOff + _TXP_CNT;
503 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
504 sOutB(ChP->IndexData,0);
505 ChP->TxPrioPtr = ChOff + _TXP_PNTR;
506 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
507 sOutB(ChP->IndexData,0);
508 ChP->TxPrioBuf = ChOff + _TXP_BUF;
509 sEnRxProcessor(ChP); /* start the Rx processor */
510
511 return(TRUE);
512}
513
514/***************************************************************************
515Function: sStopRxProcessor
516Purpose: Stop the receive processor from processing a channel.
517Call: sStopRxProcessor(ChP)
518 CHANNEL_T *ChP; Ptr to channel structure
519
520Comments: The receive processor can be started again with sStartRxProcessor().
521 This function causes the receive processor to skip over the
522 stopped channel. It does not stop it from processing other channels.
523
524Warnings: No context switches are allowed while executing this function.
525
526 Do not leave the receive processor stopped for more than one
527 character time.
528
529 After calling this function a delay of 4 uS is required to ensure
530 that the receive processor is no longer processing this channel.
531*/
532void sStopRxProcessor(CHANNEL_T *ChP)
533{
534 Byte_t R[4];
535
536 R[0] = ChP->R[0];
537 R[1] = ChP->R[1];
538 R[2] = 0x0a;
539 R[3] = ChP->R[3];
540 sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
541}
542
543/***************************************************************************
544Function: sFlushRxFIFO
545Purpose: Flush the Rx FIFO
546Call: sFlushRxFIFO(ChP)
547 CHANNEL_T *ChP; Ptr to channel structure
548Return: void
549Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
550 while it is being flushed the receive processor is stopped
551 and the transmitter is disabled. After these operations a
552 4 uS delay is done before clearing the pointers to allow
553 the receive processor to stop. These items are handled inside
554 this function.
555Warnings: No context switches are allowed while executing this function.
556*/
557void sFlushRxFIFO(CHANNEL_T *ChP)
558{
559 int i;
560 Byte_t Ch; /* channel number within AIOP */
561 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
562
563 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
564 return; /* don't need to flush */
565
566 RxFIFOEnabled = FALSE;
567 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
568 {
569 RxFIFOEnabled = TRUE;
570 sDisRxFIFO(ChP); /* disable it */
571 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
572 sInB(ChP->IntChan); /* depends on bus i/o timing */
573 }
574 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
575 Ch = (Byte_t)sGetChanNum(ChP);
576 sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
577 sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */
578 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
579 sOutW(ChP->IndexData,0);
580 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
581 sOutW(ChP->IndexData,0);
582 if(RxFIFOEnabled)
583 sEnRxFIFO(ChP); /* enable Rx FIFO */
584}
585
586/***************************************************************************
587Function: sFlushTxFIFO
588Purpose: Flush the Tx FIFO
589Call: sFlushTxFIFO(ChP)
590 CHANNEL_T *ChP; Ptr to channel structure
591Return: void
592Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
593 while it is being flushed the receive processor is stopped
594 and the transmitter is disabled. After these operations a
595 4 uS delay is done before clearing the pointers to allow
596 the receive processor to stop. These items are handled inside
597 this function.
598Warnings: No context switches are allowed while executing this function.
599*/
600void sFlushTxFIFO(CHANNEL_T *ChP)
601{
602 int i;
603 Byte_t Ch; /* channel number within AIOP */
604 int TxEnabled; /* TRUE if transmitter enabled */
605
606 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
607 return; /* don't need to flush */
608
609 TxEnabled = FALSE;
610 if(ChP->TxControl[3] & TX_ENABLE)
611 {
612 TxEnabled = TRUE;
613 sDisTransmit(ChP); /* disable transmitter */
614 }
615 sStopRxProcessor(ChP); /* stop Rx processor */
616 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
617 sInB(ChP->IntChan); /* depends on bus i/o timing */
618 Ch = (Byte_t)sGetChanNum(ChP);
619 sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
620 sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */
621 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
622 sOutW(ChP->IndexData,0);
623 if(TxEnabled)
624 sEnTransmit(ChP); /* enable transmitter */
625 sStartRxProcessor(ChP); /* restart Rx processor */
626}
627
628/***************************************************************************
629Function: sWriteTxPrioByte
630Purpose: Write a byte of priority transmit data to a channel
631Call: sWriteTxPrioByte(ChP,Data)
632 CHANNEL_T *ChP; Ptr to channel structure
633 Byte_t Data; The transmit data byte
634
635Return: int: 1 if the bytes is successfully written, otherwise 0.
636
637Comments: The priority byte is transmitted before any data in the Tx FIFO.
638
639Warnings: No context switches are allowed while executing this function.
640*/
641int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
642{
643 Byte_t DWBuf[4]; /* buffer for double word writes */
644 Word_t *WordPtr; /* must be far because Win SS != DS */
c9faf524 645 DWordIO_t IndexAddr;
984263bc
MD
646
647 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
648 {
649 IndexAddr = ChP->IndexAddr;
650 sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
651 if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
652 return(0); /* nothing sent */
653
654 WordPtr = (Word_t *)(&DWBuf[0]);
655 *WordPtr = ChP->TxPrioBuf; /* data byte address */
656
657 DWBuf[2] = Data; /* data byte value */
658 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
659
660 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
661
662 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
663 DWBuf[3] = 0; /* priority buffer pointer */
664 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
665 }
666 else /* write it to Tx FIFO */
667 {
668 sWriteTxByte(sGetTxRxDataIO(ChP),Data);
669 }
670 return(1); /* 1 byte sent */
671}
672
673/***************************************************************************
674Function: sEnInterrupts
675Purpose: Enable one or more interrupts for a channel
676Call: sEnInterrupts(ChP,Flags)
677 CHANNEL_T *ChP; Ptr to channel structure
678 Word_t Flags: Interrupt enable flags, can be any combination
679 of the following flags:
680 TXINT_EN: Interrupt on Tx FIFO empty
681 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
682 sSetRxTrigger())
683 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
684 MCINT_EN: Interrupt on modem input change
685 CHANINT_EN: Allow channel interrupt signal to the AIOP's
686 Interrupt Channel Register.
687Return: void
688Comments: If an interrupt enable flag is set in Flags, that interrupt will be
689 enabled. If an interrupt enable flag is not set in Flags, that
690 interrupt will not be changed. Interrupts can be disabled with
691 function sDisInterrupts().
692
693 This function sets the appropriate bit for the channel in the AIOP's
694 Interrupt Mask Register if the CHANINT_EN flag is set. This allows
695 this channel's bit to be set in the AIOP's Interrupt Channel Register.
696
697 Interrupts must also be globally enabled before channel interrupts
698 will be passed on to the host. This is done with function
699 sEnGlobalInt().
700
701 In some cases it may be desirable to disable interrupts globally but
702 enable channel interrupts. This would allow the global interrupt
703 status register to be used to determine which AIOPs need service.
704*/
705void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
706{
707 Byte_t Mask; /* Interrupt Mask Register */
708
709 ChP->RxControl[2] |=
710 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
711
712 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
713
714 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
715
716 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
717
718 if(Flags & CHANINT_EN)
719 {
720 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
721 sOutB(ChP->IntMask,Mask);
722 }
723}
724
725/***************************************************************************
726Function: sDisInterrupts
727Purpose: Disable one or more interrupts for a channel
728Call: sDisInterrupts(ChP,Flags)
729 CHANNEL_T *ChP; Ptr to channel structure
730 Word_t Flags: Interrupt flags, can be any combination
731 of the following flags:
732 TXINT_EN: Interrupt on Tx FIFO empty
733 RXINT_EN: Interrupt on Rx FIFO at trigger level (see
734 sSetRxTrigger())
735 SRCINT_EN: Interrupt on SRC (Special Rx Condition)
736 MCINT_EN: Interrupt on modem input change
737 CHANINT_EN: Disable channel interrupt signal to the
738 AIOP's Interrupt Channel Register.
739Return: void
740Comments: If an interrupt flag is set in Flags, that interrupt will be
741 disabled. If an interrupt flag is not set in Flags, that
742 interrupt will not be changed. Interrupts can be enabled with
743 function sEnInterrupts().
744
745 This function clears the appropriate bit for the channel in the AIOP's
746 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
747 this channel's bit from being set in the AIOP's Interrupt Channel
748 Register.
749*/
750void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
751{
752 Byte_t Mask; /* Interrupt Mask Register */
753
754 ChP->RxControl[2] &=
755 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
756 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
757 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
758 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
759
760 if(Flags & CHANINT_EN)
761 {
762 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
763 sOutB(ChP->IntMask,Mask);
764 }
765}
766
767/*********************************************************************
768 Begin FreeBsd-specific driver code
769**********************************************************************/
770
5ca58d54
RG
771static int rpprobe (struct isa_device *);
772static int rpattach (struct isa_device *);
984263bc
MD
773
774static const char* rp_pciprobe(pcici_t tag, pcidi_t type);
775static void rp_pciattach(pcici_t tag, int unit);
776static u_long rp_pcicount;
777
778static struct pci_device rp_pcidevice = {
779 "rp",
780 rp_pciprobe,
781 rp_pciattach,
782 &rp_pcicount,
783 NULL
784};
785
786COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice);
787
788static timeout_t rpdtrwakeup;
789
790struct isa_driver rpdriver = {
791 rpprobe, rpattach, "rp"
792 };
793
794static char driver_name[] = "rp";
795
796static d_open_t rpopen;
797static d_close_t rpclose;
798static d_write_t rpwrite;
799static d_ioctl_t rpioctl;
800
801#define CDEV_MAJOR 81
802static struct cdevsw rp_cdevsw = {
fabb8ceb
MD
803 /* name */ driver_name,
804 /* maj */ CDEV_MAJOR,
805 /* flags */ D_TTY | D_KQFILTER,
806 /* port */ NULL,
807 /* autoq */ 0,
808
984263bc
MD
809 /* open */ rpopen,
810 /* close */ rpclose,
811 /* read */ ttyread,
812 /* write */ rpwrite,
813 /* ioctl */ rpioctl,
814 /* poll */ ttypoll,
815 /* mmap */ nommap,
816 /* strategy */ nostrategy,
984263bc
MD
817 /* dump */ nodump,
818 /* psize */ nopsize,
fabb8ceb 819 /* kqfilter */ ttykqfilter
984263bc
MD
820};
821
822static int rp_controller_port = 0;
823static int rp_num_ports_open = 0;
824static int ndevs = 0;
825static int minor_to_unit[128];
826#if 0
827static struct tty rp_tty[128];
828#endif
829
830static int rp_num_ports[4]; /* Number of ports on each controller */
831
832#define _INLINE_ __inline
833#define POLL_INTERVAL 1
834
835#define CALLOUT_MASK 0x80
836#define CONTROL_MASK 0x60
837#define CONTROL_INIT_STATE 0x20
838#define CONTROL_LOCK_STATE 0x40
839#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
840#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
841#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
842#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
843#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
844
845#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
846#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
847#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
848
849static struct rp_port *p_rp_addr[4];
850static struct rp_port *p_rp_table[MAX_RP_PORTS];
851#define rp_addr(unit) (p_rp_addr[unit])
852#define rp_table(port) (p_rp_table[port])
853
854/*
855 * The top-level routines begin here
856 */
857
5ca58d54
RG
858static int rpparam (struct tty *, struct termios *);
859static void rpstart (struct tty *);
860static void rpstop (struct tty *, int);
861static void rphardclose (struct rp_port *);
862static void rp_disc_optim (struct tty *tp, struct termios *t,
863 struct rp_port *rp);
984263bc
MD
864
865static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
866 CHANNEL_t *cp, unsigned int ChanStatus)
867{
868 int spl;
869 unsigned int CharNStat;
870 int ToRecv, ch;
871
872 ToRecv = sGetRxCnt(cp);
873 if(ToRecv == 0)
874 return;
875
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)
879*/
880
881 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
882 if(!(ChanStatus & STATMODE)) {
883 ChanStatus |= STATMODE;
884 sEnRxStatusMode(cp);
885 }
886 }
887/*
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.
891*/
892 if(ChanStatus & STATMODE) {
893 while(ToRecv) {
894 if(tp->t_state & TS_TBLOCK) {
895 break;
896 }
897 CharNStat = sInW(sGetTxRxDataIO(cp));
898 ch = CharNStat & 0xff;
899
900 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
901 ch |= TTY_FE;
902 else if (CharNStat & STMPARITYH)
903 ch |= TTY_PE;
904 else if (CharNStat & STMRCVROVRH)
905 rp->rp_overflows++;
906
907 (*linesw[tp->t_line].l_rint)(ch, tp);
908 ToRecv--;
909 }
910/*
911 After emtying FIFO in status mode, turn off status mode
912*/
913
914 if(sGetRxCnt(cp) == 0)
915 sDisRxStatusMode(cp);
916 }
917 else {
918 while (ToRecv) {
919 if(tp->t_state & TS_TBLOCK) {
920 break;
921 }
922 ch = (u_char) sInB(sGetTxRxDataIO(cp));
923 spl = spltty();
924 (*linesw[tp->t_line].l_rint)(ch, tp);
925 splx(spl);
926 ToRecv--;
927 }
928 }
929}
930
931static _INLINE_ void rp_handle_port(struct rp_port *rp)
932{
933 CHANNEL_t *cp;
934 struct tty *tp;
935 unsigned int IntMask, ChanStatus;
936 /* int oldcts; */
937
938 if(!rp)
939 return;
940
941 cp = &rp->rp_channel;
942 tp = rp->rp_tty;
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);
949 }
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);
954 }
955 } else {
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) {
959 rphardclose(rp);
960 }
961 }
962 }
963 }
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);
968 }
969*/
970}
971
972static void rp_do_poll(void *not_used)
973{
974 CONTROLLER_t *ctl;
975 struct rp_port *rp;
976 struct tty *tp;
977 int unit, aiop, ch, line, count;
978 unsigned char CtlMask, AiopMask;
979
980 for(unit = 0; unit <= ndevs; unit++) {
981 rp = rp_addr(unit);
982 ctl = rp->rp_ctlp;
983 if(ctl->BusType == isPCI)
984 CtlMask = sPCIGetControllerIntStatus(ctl);
985 else
986 CtlMask = sGetControllerIntStatus(ctl);
987 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
988 if(CtlMask & 1) {
989 AiopMask = sGetAiopIntStatus(ctl, aiop);
990 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
991 if(AiopMask & 1) {
992 line = (unit << 5) | (aiop << 3) | ch;
993 rp = rp_table(line);
994 rp_handle_port(rp);
995 }
996 }
997 }
998 }
999
1000 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
1001 line++, rp++) {
1002 tp = rp->rp_tty;
1003 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1004 count = sGetTxCnt(&rp->rp_channel);
1005 if(count == 0)
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);
1010 }
1011 }
1012 }
1013 }
1014 if(rp_num_ports_open)
1015 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1016}
1017
1018static const char*
1019rp_pciprobe(pcici_t tag, pcidi_t type)
1020{
1021 int vendor_id;
1022
1023 vendor_id = type & 0xffff;
1024 switch(vendor_id)
1025 case 0x11fe:
1026 return("rp");
1027 return(NULL);
1028}
1029
1030static
1031int
1032rpprobe(dev)
1033struct isa_device *dev;
1034{
1035 int controller, unit;
1036 int aiop, num_aiops;
1037 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1038 CONTROLLER_t *ctlp;
1039
1040 unit = dev->id_unit;
1041 if (dev->id_unit >= 4) {
1042 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1043 return 1;
1044 }
1045 printf("probing for RocketPort(ISA) unit %d\n", unit);
1046 if (rp_controller_port)
1047 controller = rp_controller_port;
1048 else {
1049 controller = dev->id_iobase + 0x40;
1050 }
1051
1052 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1053 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1054
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,
1059 FREQ_DIS, 0);
1060 if (num_aiops <= 0) {
1061 printf("board%d init failed\n", unit);
1062 return 0;
1063 }
1064
1065 if (rp_controller_port) {
1066 dev->id_msize = 64;
1067 } else {
1068 dev->id_msize = 68;
1069 rp_controller_port = controller;
1070 }
1071
1072 dev->id_irq = 0;
1073
1074 return 1;
1075}
1076
1077static void
1078rp_pciattach(pcici_t tag, int unit)
1079{
1080 int success, oldspl;
1081 u_short iobase;
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];
1086 struct rp_port *rp;
1087 struct tty *tty;
1088 CONTROLLER_t *ctlp;
1089
1090 success = pci_map_port(tag, 0x10, &iobase);
1091 if(!success)
1092 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1093
1094 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1095 aiopio[aiop] = iobase + (aiop * 0x40);
1096
1097 ctlp = sCtlNumToCtlPtr(unit);
1098 num_aiops = sPCIInitController(ctlp, unit,
1099 aiopio, MAX_AIOPS_PER_BOARD, 0,
1100 FREQ_DIS, 0);
1101
1102 num_ports = 0;
1103 for(aiop=0; aiop < num_aiops; aiop++) {
1104 sResetAiopByNum(ctlp, aiop);
1105 num_ports += sGetAiopNumChan(ctlp, aiop);
1106 }
1107 printf("RocketPort%d = %d ports\n", unit, num_ports);
1108 rp_num_ports[unit] = num_ports;
1109
1110 rp = (struct rp_port *)
1111 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1112 if(rp == 0) {
1113 printf("rp_attach: Could not malloc rp_ports structures\n");
1114 return;
1115 }
1116
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;
1120
1121 bzero(rp, sizeof(struct rp_port) * num_ports);
1122 tty = (struct tty *)
1123 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1124 if(tty == 0) {
1125 printf("rp_attach: Could not malloc tty structures\n");
1126 return;
1127 }
1128 bzero(tty, sizeof(struct tty) * num_ports);
1129
1130 oldspl = spltty();
1131 rp_addr(unit) = rp;
1132 splx(oldspl);
1133
1134 cdevsw_add(&rp_cdevsw);
1135
1136 port = 0;
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++) {
1140 rp->rp_tty = tty;
1141 rp->rp_port = port;
1142 rp->rp_ctlp = ctlp;
1143 rp->rp_unit = unit;
1144 rp->rp_chan = chan;
1145 rp->rp_aiop = aiop;
1146
1147 tty->t_line = 0;
1148 /* tty->t_termios = deftermios;
1149 */
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);
1157 */
1158 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1159 rp->it_out = rp->it_in;
1160
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) {
2a53dae6
JS
1165 printf("RocketPort sInitChan(%d, %d, %d) failed\n",
1166 unit, aiop, chan);
984263bc
MD
1167 return;
1168 }
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;
1173 }
1174 }
1175}
1176
1177static
1178int
1179rpattach(dev)
1180struct isa_device *dev;
1181{
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];
1187 struct rp_port *rp;
1188 struct tty *tty;
1189 CONTROLLER_t *ctlp;
1190
1191 iobase = dev->id_iobase;
1192 unit = dev->id_unit;
1193 ndevs = unit;
1194
1195 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1196 aiopio[aiop] = iobase + (aiop * 0x400);
1197
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,
1202 FREQ_DIS, 0);
1203
1204 num_ports = 0;
1205 for(aiop=0; aiop < num_aiops; aiop++) {
1206 sResetAiopByNum(ctlp, aiop);
1207 sEnAiop(ctlp, aiop);
1208 num_ports += sGetAiopNumChan(ctlp, aiop);
1209 }
1210 printf("RocketPort%d = %d ports\n", unit, num_ports);
1211 rp_num_ports[unit] = num_ports;
1212
1213 rp = (struct rp_port *)
1214 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1215 if(rp == 0) {
1216 printf("rp_attach: Could not malloc rp_ports structures\n");
1217 return(0);
1218 }
1219
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;
1223
1224 bzero(rp, sizeof(struct rp_port) * num_ports);
1225 tty = (struct tty *)
1226 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1227 if(tty == 0) {
1228 printf("rp_attach: Could not malloc tty structures\n");
1229 return(0);
1230 }
1231 bzero(tty, sizeof(struct tty) * num_ports);
1232
1233 oldspl = spltty();
1234 rp_addr(unit) = rp;
1235 splx(oldspl);
1236
1237 cdevsw_add(&rp_cdevsw);
1238
1239 port = 0;
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++) {
1243 rp->rp_tty = tty;
1244 rp->rp_port = port;
1245 rp->rp_ctlp = ctlp;
1246 rp->rp_unit = unit;
1247 rp->rp_chan = chan;
1248 rp->rp_aiop = aiop;
1249
1250 tty->t_line = 0;
1251 /* tty->t_termios = deftermios;
1252 */
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);
1260 */
1261 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1262 rp->it_out = rp->it_in;
1263
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) {
2a53dae6
JS
1268 printf("RocketPort sInitChan(%d, %d, %d) failed\n",
1269 unit, aiop, chan);
984263bc
MD
1270 return(0);
1271 }
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;
1276 }
1277 }
1278
1279 return(1);
1280}
1281
1282int
7b95be2a 1283rpopen(dev, flag, mode, td)
984263bc
MD
1284 dev_t dev;
1285 int flag, mode;
7b95be2a 1286 struct thread *td;
984263bc
MD
1287{
1288 struct rp_port *rp;
1289 int unit, port, mynor, umynor, flags; /* SG */
1290 struct tty *tp;
1291 int oldspl, error;
1292 unsigned int IntMask, ChanStatus;
1293
1294
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];
1299 if (rp_addr(unit) == NULL)
1300 return (ENXIO);
1301 if(IS_CONTROL(dev))
1302 return(0);
1303 rp = rp_addr(unit) + port;
1304/* rp->rp_tty = &rp_tty[rp->rp_port];
1305*/
1306 tp = rp->rp_tty;
1307 dev->si_tty = tp;
1308
1309 oldspl = spltty();
1310
1311open_top:
1312 while(rp->state & ~SET_DTR) {
377d4740 1313 error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0);
984263bc
MD
1314 if(error != 0)
1315 goto out;
1316 }
1317
1318 if(tp->t_state & TS_ISOPEN) {
1319 if(IS_CALLOUT(dev)) {
1320 if(!rp->active_out) {
1321 error = EBUSY;
1322 goto out;
1323 }
1324 } else {
1325 if(rp->active_out) {
1326 if(flag & O_NONBLOCK) {
1327 error = EBUSY;
1328 goto out;
1329 }
1330 error = tsleep(&rp->active_out,
377d4740 1331 PCATCH, "rpbi", 0);
984263bc
MD
1332 if(error != 0)
1333 goto out;
1334 goto open_top;
1335 }
1336 }
1337 if(tp->t_state & TS_XCLUDE &&
dadab5e9 1338 suser(td)) {
984263bc
MD
1339 splx(oldspl);
1340 return(EBUSY);
1341 }
1342 }
1343 else {
1344 tp->t_dev = dev;
1345 tp->t_param = rpparam;
1346 tp->t_oproc = rpstart;
1347 tp->t_stop = rpstop;
1348 tp->t_line = 0;
1349 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1350 flags = 0;
1351 flags |= SET_RTS;
1352 flags |= SET_DTR;
1353 rp->rp_channel.TxControl[3] =
1354 ((rp->rp_channel.TxControl[3]
1355 & ~(SET_RTS | SET_DTR)) | flags);
1356 sOutDW(rp->rp_channel.IndexAddr,
1357 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1358 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1359 sDisRxStatusMode(&rp->rp_channel);
1360 sFlushRxFIFO(&rp->rp_channel);
1361 sFlushTxFIFO(&rp->rp_channel);
1362
1363 sEnInterrupts(&rp->rp_channel,
1364 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1365 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1366
1367 sDisRxStatusMode(&rp->rp_channel);
1368 sClrTxXOFF(&rp->rp_channel);
1369
1370/* sDisRTSFlowCtl(&rp->rp_channel);
1371 sDisCTSFlowCtl(&rp->rp_channel);
1372*/
1373 sDisTxSoftFlowCtl(&rp->rp_channel);
1374
1375 sStartRxProcessor(&rp->rp_channel);
1376
1377 sEnRxFIFO(&rp->rp_channel);
1378 sEnTransmit(&rp->rp_channel);
1379
1380/* sSetDTR(&rp->rp_channel);
1381 sSetRTS(&rp->rp_channel);
1382*/
1383
1384 ++rp->wopeners;
1385 error = rpparam(tp, &tp->t_termios);
1386 --rp->wopeners;
1387 if(error != 0) {
1388 splx(oldspl);
1389 return(error);
1390 }
1391
1392 rp_num_ports_open++;
1393
1394 IntMask = sGetChanIntID(&rp->rp_channel);
1395 IntMask = IntMask & rp->rp_intmask;
1396 ChanStatus = sGetChanStatus(&rp->rp_channel);
1397 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) {
1398 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) {
1399 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1400 }
1401 }
1402
1403 if(rp_num_ports_open == 1)
1404 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1405
1406 }
1407
1408 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1409 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1410 ++rp->wopeners;
377d4740 1411 error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0);
984263bc
MD
1412 --rp->wopeners;
1413 if(error != 0)
1414 goto out;
1415 goto open_top;
1416 }
1417 error = (*linesw[tp->t_line].l_open)(dev, tp);
1418
1419 rp_disc_optim(tp, &tp->t_termios, rp);
1420 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1421 rp->active_out = TRUE;
1422
1423/* if(rp_num_ports_open == 1)
1424 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1425*/
1426out:
1427 splx(oldspl);
1428 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1429 rphardclose(rp);
1430 }
1431 return(error);
1432}
1433
1434int
7b95be2a 1435rpclose(dev, flag, mode, td)
984263bc
MD
1436 dev_t dev;
1437 int flag, mode;
7b95be2a 1438 struct thread *td;
984263bc
MD
1439{
1440 int oldspl, unit, mynor, umynor, port; /* SG */
1441 struct rp_port *rp;
1442 struct tty *tp;
1443 CHANNEL_t *cp;
1444
1445 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1446 port = (minor(dev) & 0x1f); /* SG */
1447 mynor = (port + umynor); /* SG */
1448 unit = minor_to_unit[mynor]; /* SG */
1449
1450 if(IS_CONTROL(dev))
1451 return(0);
1452 rp = rp_addr(unit) + port;
1453 cp = &rp->rp_channel;
1454 tp = rp->rp_tty;
1455
1456 oldspl = spltty();
1457 (*linesw[tp->t_line].l_close)(tp, flag);
1458 rp_disc_optim(tp, &tp->t_termios, rp);
1459 rpstop(tp, FREAD | FWRITE);
1460 rphardclose(rp);
1461
1462 tp->t_state &= ~TS_BUSY;
1463 ttyclose(tp);
1464
1465 splx(oldspl);
1466
1467 return(0);
1468}
1469
1470static void
1471rphardclose(struct rp_port *rp)
1472{
1473 int mynor;
1474 struct tty *tp;
1475 CHANNEL_t *cp;
1476
1477 cp = &rp->rp_channel;
1478 tp = rp->rp_tty;
1479 mynor = MINOR_MAGIC(tp->t_dev);
1480
1481 sFlushRxFIFO(cp);
1482 sFlushTxFIFO(cp);
1483 sDisTransmit(cp);
1484 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1485 sDisRTSFlowCtl(cp);
1486 sDisCTSFlowCtl(cp);
1487 sDisTxSoftFlowCtl(cp);
1488 sClrTxXOFF(cp);
1489
1490 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1491 sClrDTR(cp);
1492 }
1493 if(IS_CALLOUT(tp->t_dev)) {
1494 sClrDTR(cp);
1495 }
1496 if(rp->dtr_wait != 0) {
1497 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1498 rp->state |= ~SET_DTR;
1499 }
1500
1501 rp->active_out = FALSE;
1502 wakeup(&rp->active_out);
1503 wakeup(TSA_CARR_ON(tp));
1504}
1505
1506static
1507int
1508rpwrite(dev, uio, flag)
1509 dev_t dev;
1510 struct uio *uio;
1511 int flag;
1512{
1513 struct rp_port *rp;
1514 struct tty *tp;
1515 int unit, mynor, port, umynor, error = 0; /* SG */
1516
1517 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1518 port = (minor(dev) & 0x1f); /* SG */
1519 mynor = (port + umynor); /* SG */
1520 unit = minor_to_unit[mynor]; /* SG */
1521
1522 if(IS_CONTROL(dev))
1523 return(ENODEV);
1524 rp = rp_addr(unit) + port;
1525 tp = rp->rp_tty;
1526 while(rp->rp_disable_writes) {
1527 rp->rp_waiting = 1;
377d4740 1528 error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0);
984263bc
MD
1529 if (error)
1530 return(error);
1531 }
1532
1533 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1534 return error;
1535}
1536
1537static void
1538rpdtrwakeup(void *chan)
1539{
1540 struct rp_port *rp;
1541
1542 rp = (struct rp_port *)chan;
1543 rp->state &= SET_DTR;
1544 wakeup(&rp->dtr_wait);
1545}
1546
1547int
7b95be2a 1548rpioctl(dev, cmd, data, flag, td)
984263bc
MD
1549 dev_t dev;
1550 u_long cmd;
1551 caddr_t data;
1552 int flag;
7b95be2a 1553 struct thread *td;
984263bc
MD
1554{
1555 struct rp_port *rp;
1556 CHANNEL_t *cp;
1557 struct tty *tp;
1558 int unit, mynor, port, umynor; /* SG */
1559 int oldspl;
1560 int error = 0;
1561 int arg, flags, result, ChanStatus;
1562 int oldcmd;
1563 struct termios term, *t;
1564
1565 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1566 port = (minor(dev) & 0x1f); /* SG */
1567 mynor = (port + umynor); /* SG */
1568 unit = minor_to_unit[mynor];
1569 rp = rp_addr(unit) + port;
1570
1571 if(IS_CONTROL(dev)) {
1572 struct termios *ct;
1573
1574 switch (IS_CONTROL(dev)) {
1575 case CONTROL_INIT_STATE:
1576 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1577 break;
1578 case CONTROL_LOCK_STATE:
1579 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1580 break;
1581 default:
1582 return(ENODEV); /* /dev/nodev */
1583 }
1584 switch (cmd) {
1585 case TIOCSETA:
dadab5e9 1586 error = suser(td);
984263bc
MD
1587 if(error != 0)
1588 return(error);
1589 *ct = *(struct termios *)data;
1590 return(0);
1591 case TIOCGETA:
1592 *(struct termios *)data = *ct;
1593 return(0);
1594 case TIOCGETD:
1595 *(int *)data = TTYDISC;
1596 return(0);
1597 case TIOCGWINSZ:
1598 bzero(data, sizeof(struct winsize));
1599 return(0);
1600 default:
1601 return(ENOTTY);
1602 }
1603 }
1604
1605 tp = rp->rp_tty;
1606 cp = &rp->rp_channel;
1607
1608#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1609 term = tp->t_termios;
1610 oldcmd = cmd;
1611 error = ttsetcompat(tp, &cmd, data, &term);
1612 if(error != 0)
1613 return(error);
1614 if(cmd != oldcmd) {
1615 data = (caddr_t)&term;
1616 }
1617#endif
1618 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1619 int cc;
1620 struct termios *dt = (struct termios *)data;
1621 struct termios *lt = IS_CALLOUT(dev)
1622 ? &rp->lt_out : &rp->lt_in;
1623
1624 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1625 | (dt->c_iflag & ~lt->c_iflag);
1626 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1627 | (dt->c_oflag & ~lt->c_oflag);
1628 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1629 | (dt->c_cflag & ~lt->c_cflag);
1630 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1631 | (dt->c_lflag & ~lt->c_lflag);
1632 for(cc = 0; cc < NCCS; ++cc)
1633 if(lt->c_cc[cc] != 0)
1634 dt->c_cc[cc] = tp->t_cc[cc];
1635 if(lt->c_ispeed != 0)
1636 dt->c_ispeed = tp->t_ispeed;
1637 if(lt->c_ospeed != 0)
1638 dt->c_ospeed = tp->t_ospeed;
1639 }
1640
1641 t = &tp->t_termios;
1642
7b95be2a 1643 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
984263bc
MD
1644 if(error != ENOIOCTL) {
1645 return(error);
1646 }
1647 oldspl = spltty();
1648
1649 flags = rp->rp_channel.TxControl[3];
1650
1651 error = ttioctl(tp, cmd, data, flag);
1652 flags = rp->rp_channel.TxControl[3];
1653 rp_disc_optim(tp, &tp->t_termios, rp);
1654 if(error != ENOIOCTL) {
1655 splx(oldspl);
1656 return(error);
1657 }
1658 switch(cmd) {
1659 case TIOCSBRK:
1660 sSendBreak(&rp->rp_channel);
1661 break;
1662
1663 case TIOCCBRK:
1664 sClrBreak(&rp->rp_channel);
1665 break;
1666
1667 case TIOCSDTR:
1668 sSetDTR(&rp->rp_channel);
1669 sSetRTS(&rp->rp_channel);
1670 break;
1671
1672 case TIOCCDTR:
1673 sClrDTR(&rp->rp_channel);
1674 break;
1675
1676 case TIOCMSET:
1677 arg = *(int *) data;
1678 flags = 0;
1679 if(arg & TIOCM_RTS)
1680 flags |= SET_RTS;
1681 if(arg & TIOCM_DTR)
1682 flags |= SET_DTR;
1683 rp->rp_channel.TxControl[3] =
1684 ((rp->rp_channel.TxControl[3]
1685 & ~(SET_RTS | SET_DTR)) | flags);
1686 sOutDW(rp->rp_channel.IndexAddr,
1687 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1688 break;
1689 case TIOCMBIS:
1690 arg = *(int *) data;
1691 flags = 0;
1692 if(arg & TIOCM_RTS)
1693 flags |= SET_RTS;
1694 if(arg & TIOCM_DTR)
1695 flags |= SET_DTR;
1696 rp->rp_channel.TxControl[3] |= flags;
1697 sOutDW(rp->rp_channel.IndexAddr,
1698 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1699 break;
1700 case TIOCMBIC:
1701 arg = *(int *) data;
1702 flags = 0;
1703 if(arg & TIOCM_RTS)
1704 flags |= SET_RTS;
1705 if(arg & TIOCM_DTR)
1706 flags |= SET_DTR;
1707 rp->rp_channel.TxControl[3] &= ~flags;
1708 sOutDW(rp->rp_channel.IndexAddr,
1709 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1710 break;
1711
1712
1713 case TIOCMGET:
1714 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1715 flags = rp->rp_channel.TxControl[3];
1716 result = TIOCM_LE; /* always on while open for some reason */
1717 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1718 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1719 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1720 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1721 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1722
1723 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1724 {
1725 result |= TIOCM_RTS;
1726 }
1727
1728 *(int *)data = result;
1729 break;
1730 case TIOCMSDTRWAIT:
dadab5e9 1731 error = suser(td);
984263bc
MD
1732 if(error != 0) {
1733 splx(oldspl);
1734 return(error);
1735 }
1736 rp->dtr_wait = *(int *)data * hz/100;
1737 break;
1738 case TIOCMGDTRWAIT:
1739 *(int *)data = rp->dtr_wait * 100/hz;
1740 break;
1741 default:
1742 splx(oldspl);
1743 return ENOTTY;
1744 }
1745 splx(oldspl);
1746 return(0);
1747}
1748
1749static struct speedtab baud_table[] = {
1750 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1751 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1752 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1753 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1754 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1755 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1756 {B57600, BRD57600}, {B76800, BRD76800},
1757 {B115200, BRD115200}, {B230400, BRD230400},
7b95be2a 1758 { -1, -1 }
984263bc
MD
1759};
1760
1761static int
1762rpparam(tp, t)
1763 struct tty *tp;
1764 struct termios *t;
1765{
1766 struct rp_port *rp;
1767 CHANNEL_t *cp;
1768 int unit, mynor, port, umynor; /* SG */
1769 int oldspl, cflag, iflag, oflag, lflag;
1770 int ospeed;
1771
1772
1773 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1774 port = (minor(tp->t_dev) & 0x1f); /* SG */
1775 mynor = (port + umynor); /* SG */
1776
1777 unit = minor_to_unit[mynor];
1778 rp = rp_addr(unit) + port;
1779 cp = &rp->rp_channel;
1780 oldspl = spltty();
1781
1782 cflag = t->c_cflag;
1783 iflag = t->c_iflag;
1784 oflag = t->c_oflag;
1785 lflag = t->c_lflag;
1786
1787 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1788 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1789 return(EINVAL);
1790
1791 tp->t_ispeed = t->c_ispeed;
1792 tp->t_ospeed = t->c_ospeed;
1793 tp->t_cflag = cflag;
1794 tp->t_iflag = iflag;
1795 tp->t_oflag = oflag;
1796 tp->t_lflag = lflag;
1797
1798 if(t->c_ospeed == 0) {
1799 sClrDTR(cp);
1800 return(0);
1801 }
1802 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1803
1804 /* Set baud rate ----- we only pay attention to ispeed */
1805 sSetDTR(cp);
1806 sSetRTS(cp);
1807 sSetBaud(cp, ospeed);
1808
1809 if(cflag & CSTOPB) {
1810 sSetStop2(cp);
1811 } else {
1812 sSetStop1(cp);
1813 }
1814
1815 if(cflag & PARENB) {
1816 sEnParity(cp);
1817 if(cflag & PARODD) {
1818 sSetOddParity(cp);
1819 } else {
1820 sSetEvenParity(cp);
1821 }
1822 }
1823 else {
1824 sDisParity(cp);
1825 }
1826 if((cflag & CSIZE) == CS8) {
1827 sSetData8(cp);
1828 rp->rp_imask = 0xFF;
1829 } else {
1830 sSetData7(cp);
1831 rp->rp_imask = 0x7F;
1832 }
1833
1834 if(iflag & ISTRIP) {
1835 rp->rp_imask &= 0x7F;
1836 }
1837
1838 if(cflag & CLOCAL) {
1839 rp->rp_intmask &= ~DELTA_CD;
1840 } else {
1841 rp->rp_intmask |= DELTA_CD;
1842 }
1843
1844 /* Put flow control stuff here */
1845
1846 if(cflag & CCTS_OFLOW) {
1847 sEnCTSFlowCtl(cp);
1848 } else {
1849 sDisCTSFlowCtl(cp);
1850 }
1851
1852 if(cflag & CRTS_IFLOW) {
1853 rp->rp_rts_iflow = 1;
1854 } else {
1855 rp->rp_rts_iflow = 0;
1856 }
1857
1858 if(cflag & CRTS_IFLOW) {
1859 sEnRTSFlowCtl(cp);
1860 } else {
1861 sDisRTSFlowCtl(cp);
1862 }
1863 rp_disc_optim(tp, t, rp);
1864
1865 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1866 tp->t_state |= TS_CARR_ON;
1867 wakeup(TSA_CARR_ON(tp));
1868 }
1869
1870/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1871 flags = rp->rp_channel.TxControl[3];
1872 if(flags & SET_DTR)
1873 else
1874 if(flags & SET_RTS)
1875 else
1876*/
1877 splx(oldspl);
1878
1879 return(0);
1880}
1881
1882static void
1883rp_disc_optim(tp, t, rp)
1884struct tty *tp;
1885struct termios *t;
1886struct rp_port *rp;
1887{
1888 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1889 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1890 &&(!(t->c_iflag & PARMRK)
1891 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1892 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1893 && linesw[tp->t_line].l_rint == ttyinput)
1894 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1895 else
1896 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1897}
1898
1899static void
1900rpstart(tp)
1901 struct tty *tp;
1902{
1903 struct rp_port *rp;
1904 CHANNEL_t *cp;
1905 struct clist *qp;
1906 int unit, mynor, port, umynor; /* SG */
1907 char ch, flags;
1908 int spl, xmit_fifo_room;
1909 int count;
1910
1911
1912 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1913 port = (minor(tp->t_dev) & 0x1f); /* SG */
1914 mynor = (port + umynor); /* SG */
1915 unit = minor_to_unit[mynor];
1916 rp = rp_addr(unit) + port;
1917 cp = &rp->rp_channel;
1918 flags = rp->rp_channel.TxControl[3];
1919 spl = spltty();
1920
1921 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1922 ttwwakeup(tp);
1923 splx(spl);
1924 return;
1925 }
1926 if(rp->rp_xmit_stopped) {
1927 sEnTransmit(cp);
1928 rp->rp_xmit_stopped = 0;
1929 }
1930 count = sGetTxCnt(cp);
1931
1932 if(tp->t_outq.c_cc == 0) {
1933 if((tp->t_state & TS_BUSY) && (count == 0)) {
1934 tp->t_state &= ~TS_BUSY;
1935 }
1936 ttwwakeup(tp);
1937 splx(spl);
1938 return;
1939 }
1940 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1941 qp = &tp->t_outq;
1942 count = 0;
1943 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1944 tp->t_state |= TS_BUSY;
1945 }
1946 while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1947 ch = getc(qp);
1948 sOutB(sGetTxRxDataIO(cp), ch);
1949 xmit_fifo_room--;
1950 count++;
1951 }
1952 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1953
1954 ttwwakeup(tp);
1955 splx(spl);
1956}
1957
1958static
1959void
1960rpstop(tp, flag)
c9faf524 1961 struct tty *tp;
984263bc
MD
1962 int flag;
1963{
1964 struct rp_port *rp;
1965 CHANNEL_t *cp;
1966 int unit, mynor, port, umynor; /* SG */
1967 int spl;
1968
1969 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1970 port = (minor(tp->t_dev) & 0x1f); /* SG */
1971 mynor = (port + umynor); /* SG */
1972 unit = minor_to_unit[mynor];
1973 rp = rp_addr(unit) + port;
1974 cp = &rp->rp_channel;
1975
1976 spl = spltty();
1977
1978 if(tp->t_state & TS_BUSY) {
1979 if((tp->t_state&TS_TTSTOP) == 0) {
1980 sFlushTxFIFO(cp);
1981 } else {
1982 if(rp->rp_xmit_stopped == 0) {
1983 sDisTransmit(cp);
1984 rp->rp_xmit_stopped = 1;
1985 }
1986 }
1987 }
1988 splx(spl);
1989 rpstart(tp);
1990}