proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / dev / serial / rp2 / rp.c
... / ...
CommitLineData
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 $
33 * $DragonFly: src/sys/dev/serial/rp2/Attic/rp.c,v 1.3 2003/06/25 03:55:54 dillon Exp $
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
51#include <i386/isa/isa_device.h>
52
53#include <pci/pcivar.h>
54
55#define ROCKET_C
56#include <i386/isa/rpreg.h>
57#include <i386/isa/rpvar.h>
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 */
645 register DWordIO_t IndexAddr;
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
771static int rpprobe __P((struct isa_device *));
772static int rpattach __P((struct isa_device *));
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 = {
803 /* open */ rpopen,
804 /* close */ rpclose,
805 /* read */ ttyread,
806 /* write */ rpwrite,
807 /* ioctl */ rpioctl,
808 /* poll */ ttypoll,
809 /* mmap */ nommap,
810 /* strategy */ nostrategy,
811 /* name */ driver_name,
812 /* maj */ CDEV_MAJOR,
813 /* dump */ nodump,
814 /* psize */ nopsize,
815 /* flags */ D_TTY | D_KQFILTER,
816 /* bmaj */ -1,
817 /* kqfilter */ ttykqfilter,
818};
819
820static int rp_controller_port = 0;
821static int rp_num_ports_open = 0;
822static int ndevs = 0;
823static int minor_to_unit[128];
824#if 0
825static struct tty rp_tty[128];
826#endif
827
828static int rp_num_ports[4]; /* Number of ports on each controller */
829
830#define _INLINE_ __inline
831#define POLL_INTERVAL 1
832
833#define CALLOUT_MASK 0x80
834#define CONTROL_MASK 0x60
835#define CONTROL_INIT_STATE 0x20
836#define CONTROL_LOCK_STATE 0x40
837#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev))
838#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK)
839#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK)
840#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK)
841#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK)
842
843#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1)
844#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff)
845#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04)
846
847static struct rp_port *p_rp_addr[4];
848static struct rp_port *p_rp_table[MAX_RP_PORTS];
849#define rp_addr(unit) (p_rp_addr[unit])
850#define rp_table(port) (p_rp_table[port])
851
852/*
853 * The top-level routines begin here
854 */
855
856static int rpparam __P((struct tty *, struct termios *));
857static void rpstart __P((struct tty *));
858static void rpstop __P((struct tty *, int));
859static void rphardclose __P((struct rp_port *));
860static void rp_disc_optim __P((struct tty *tp, struct termios *t,
861 struct rp_port *rp));
862
863static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp,
864 CHANNEL_t *cp, unsigned int ChanStatus)
865{
866 int spl;
867 unsigned int CharNStat;
868 int ToRecv, ch;
869
870 ToRecv = sGetRxCnt(cp);
871 if(ToRecv == 0)
872 return;
873
874/* If status indicates there are errored characters in the
875 FIFO, then enter status mode (a word in FIFO holds
876 characters and status)
877*/
878
879 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
880 if(!(ChanStatus & STATMODE)) {
881 ChanStatus |= STATMODE;
882 sEnRxStatusMode(cp);
883 }
884 }
885/*
886 if we previously entered status mode then read down the
887 FIFO one word at a time, pulling apart the character and
888 the status. Update error counters depending on status.
889*/
890 if(ChanStatus & STATMODE) {
891 while(ToRecv) {
892 if(tp->t_state & TS_TBLOCK) {
893 break;
894 }
895 CharNStat = sInW(sGetTxRxDataIO(cp));
896 ch = CharNStat & 0xff;
897
898 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH))
899 ch |= TTY_FE;
900 else if (CharNStat & STMPARITYH)
901 ch |= TTY_PE;
902 else if (CharNStat & STMRCVROVRH)
903 rp->rp_overflows++;
904
905 (*linesw[tp->t_line].l_rint)(ch, tp);
906 ToRecv--;
907 }
908/*
909 After emtying FIFO in status mode, turn off status mode
910*/
911
912 if(sGetRxCnt(cp) == 0)
913 sDisRxStatusMode(cp);
914 }
915 else {
916 while (ToRecv) {
917 if(tp->t_state & TS_TBLOCK) {
918 break;
919 }
920 ch = (u_char) sInB(sGetTxRxDataIO(cp));
921 spl = spltty();
922 (*linesw[tp->t_line].l_rint)(ch, tp);
923 splx(spl);
924 ToRecv--;
925 }
926 }
927}
928
929static _INLINE_ void rp_handle_port(struct rp_port *rp)
930{
931 CHANNEL_t *cp;
932 struct tty *tp;
933 unsigned int IntMask, ChanStatus;
934 /* int oldcts; */
935
936 if(!rp)
937 return;
938
939 cp = &rp->rp_channel;
940 tp = rp->rp_tty;
941 IntMask = sGetChanIntID(cp);
942 IntMask = IntMask & rp->rp_intmask;
943 ChanStatus = sGetChanStatus(cp);
944 if(IntMask & RXF_TRIG)
945 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) {
946 rp_do_receive(rp, tp, cp, ChanStatus);
947 }
948 if(IntMask & DELTA_CD) {
949 if(ChanStatus & CD_ACT) {
950 if(!(tp->t_state & TS_CARR_ON) ) {
951 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
952 }
953 } else {
954 if((tp->t_state & TS_CARR_ON)) {
955 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
956 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
957 rphardclose(rp);
958 }
959 }
960 }
961 }
962/* oldcts = rp->rp_cts;
963 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0);
964 if(oldcts != rp->rp_cts) {
965 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port);
966 }
967*/
968}
969
970static void rp_do_poll(void *not_used)
971{
972 CONTROLLER_t *ctl;
973 struct rp_port *rp;
974 struct tty *tp;
975 int unit, aiop, ch, line, count;
976 unsigned char CtlMask, AiopMask;
977
978 for(unit = 0; unit <= ndevs; unit++) {
979 rp = rp_addr(unit);
980 ctl = rp->rp_ctlp;
981 if(ctl->BusType == isPCI)
982 CtlMask = sPCIGetControllerIntStatus(ctl);
983 else
984 CtlMask = sGetControllerIntStatus(ctl);
985 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) {
986 if(CtlMask & 1) {
987 AiopMask = sGetAiopIntStatus(ctl, aiop);
988 for(ch = 0; AiopMask; AiopMask >>=1, ch++) {
989 if(AiopMask & 1) {
990 line = (unit << 5) | (aiop << 3) | ch;
991 rp = rp_table(line);
992 rp_handle_port(rp);
993 }
994 }
995 }
996 }
997
998 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit];
999 line++, rp++) {
1000 tp = rp->rp_tty;
1001 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) {
1002 count = sGetTxCnt(&rp->rp_channel);
1003 if(count == 0)
1004 tp->t_state &= ~(TS_BUSY);
1005 if(!(tp->t_state & TS_TTSTOP) &&
1006 (count <= rp->rp_restart)) {
1007 (*linesw[tp->t_line].l_start)(tp);
1008 }
1009 }
1010 }
1011 }
1012 if(rp_num_ports_open)
1013 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1014}
1015
1016static const char*
1017rp_pciprobe(pcici_t tag, pcidi_t type)
1018{
1019 int vendor_id;
1020
1021 vendor_id = type & 0xffff;
1022 switch(vendor_id)
1023 case 0x11fe:
1024 return("rp");
1025 return(NULL);
1026}
1027
1028static
1029int
1030rpprobe(dev)
1031struct isa_device *dev;
1032{
1033 int controller, unit;
1034 int aiop, num_aiops;
1035 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1036 CONTROLLER_t *ctlp;
1037
1038 unit = dev->id_unit;
1039 if (dev->id_unit >= 4) {
1040 printf("rpprobe: unit number %d invalid.\n", dev->id_unit);
1041 return 1;
1042 }
1043 printf("probing for RocketPort(ISA) unit %d\n", unit);
1044 if (rp_controller_port)
1045 controller = rp_controller_port;
1046 else {
1047 controller = dev->id_iobase + 0x40;
1048 }
1049
1050 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
1051 aiopio[aiop]= dev->id_iobase + (aiop * 0x400);
1052
1053 ctlp = sCtlNumToCtlPtr(dev->id_unit);
1054 num_aiops = sInitController(ctlp, dev->id_unit,
1055 controller + ((unit-rp_pcicount)*0x400),
1056 aiopio, MAX_AIOPS_PER_BOARD, 0,
1057 FREQ_DIS, 0);
1058 if (num_aiops <= 0) {
1059 printf("board%d init failed\n", unit);
1060 return 0;
1061 }
1062
1063 if (rp_controller_port) {
1064 dev->id_msize = 64;
1065 } else {
1066 dev->id_msize = 68;
1067 rp_controller_port = controller;
1068 }
1069
1070 dev->id_irq = 0;
1071
1072 return 1;
1073}
1074
1075static void
1076rp_pciattach(pcici_t tag, int unit)
1077{
1078 int success, oldspl;
1079 u_short iobase;
1080 int num_ports, num_chan, num_aiops;
1081 int aiop, chan, port;
1082 int ChanStatus, line, i, count;
1083 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1084 struct rp_port *rp;
1085 struct tty *tty;
1086 CONTROLLER_t *ctlp;
1087
1088 success = pci_map_port(tag, 0x10, &iobase);
1089 if(!success)
1090 printf("ioaddr mapping failed for RocketPort(PCI)\n");
1091
1092 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1093 aiopio[aiop] = iobase + (aiop * 0x40);
1094
1095 ctlp = sCtlNumToCtlPtr(unit);
1096 num_aiops = sPCIInitController(ctlp, unit,
1097 aiopio, MAX_AIOPS_PER_BOARD, 0,
1098 FREQ_DIS, 0);
1099
1100 num_ports = 0;
1101 for(aiop=0; aiop < num_aiops; aiop++) {
1102 sResetAiopByNum(ctlp, aiop);
1103 num_ports += sGetAiopNumChan(ctlp, aiop);
1104 }
1105 printf("RocketPort%d = %d ports\n", unit, num_ports);
1106 rp_num_ports[unit] = num_ports;
1107
1108 rp = (struct rp_port *)
1109 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1110 if(rp == 0) {
1111 printf("rp_attach: Could not malloc rp_ports structures\n");
1112 return;
1113 }
1114
1115 count = unit * 32; /* board times max ports per card SG */
1116 for(i=count;i < (count + rp_num_ports[unit]);i++)
1117 minor_to_unit[i] = unit;
1118
1119 bzero(rp, sizeof(struct rp_port) * num_ports);
1120 tty = (struct tty *)
1121 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1122 if(tty == 0) {
1123 printf("rp_attach: Could not malloc tty structures\n");
1124 return;
1125 }
1126 bzero(tty, sizeof(struct tty) * num_ports);
1127
1128 oldspl = spltty();
1129 rp_addr(unit) = rp;
1130 splx(oldspl);
1131
1132 cdevsw_add(&rp_cdevsw);
1133
1134 port = 0;
1135 for(aiop=0; aiop < num_aiops; aiop++) {
1136 num_chan = sGetAiopNumChan(ctlp, aiop);
1137 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1138 rp->rp_tty = tty;
1139 rp->rp_port = port;
1140 rp->rp_ctlp = ctlp;
1141 rp->rp_unit = unit;
1142 rp->rp_chan = chan;
1143 rp->rp_aiop = aiop;
1144
1145 tty->t_line = 0;
1146 /* tty->t_termios = deftermios;
1147 */
1148 rp->dtr_wait = 3 * hz;
1149 rp->it_in.c_iflag = 0;
1150 rp->it_in.c_oflag = 0;
1151 rp->it_in.c_cflag = TTYDEF_CFLAG;
1152 rp->it_in.c_lflag = 0;
1153 termioschars(&rp->it_in);
1154 /* termioschars(&tty->t_termios);
1155 */
1156 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1157 rp->it_out = rp->it_in;
1158
1159 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1160 DELTA_CD | DELTA_CTS | DELTA_DSR;
1161 ChanStatus = sGetChanStatus(&rp->rp_channel);
1162 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1163 printf("RocketPort sInitChan(%d, %d, %d) failed
1164 \n", unit, aiop, chan);
1165 return;
1166 }
1167 ChanStatus = sGetChanStatus(&rp->rp_channel);
1168 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1169 line = (unit << 5) | (aiop << 3) | chan;
1170 rp_table(line) = rp;
1171 }
1172 }
1173}
1174
1175static
1176int
1177rpattach(dev)
1178struct isa_device *dev;
1179{
1180 int iobase, unit, /*rpmajor,*/ oldspl;
1181 int num_ports, num_chan, num_aiops;
1182 int aiop, chan, port;
1183 int ChanStatus, line, i, count;
1184 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
1185 struct rp_port *rp;
1186 struct tty *tty;
1187 CONTROLLER_t *ctlp;
1188
1189 iobase = dev->id_iobase;
1190 unit = dev->id_unit;
1191 ndevs = unit;
1192
1193 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
1194 aiopio[aiop] = iobase + (aiop * 0x400);
1195
1196 ctlp = sCtlNumToCtlPtr(unit);
1197 num_aiops = sInitController(ctlp, unit,
1198 rp_controller_port + ((unit-rp_pcicount) * 0x400),
1199 aiopio, MAX_AIOPS_PER_BOARD, 0,
1200 FREQ_DIS, 0);
1201
1202 num_ports = 0;
1203 for(aiop=0; aiop < num_aiops; aiop++) {
1204 sResetAiopByNum(ctlp, aiop);
1205 sEnAiop(ctlp, aiop);
1206 num_ports += sGetAiopNumChan(ctlp, aiop);
1207 }
1208 printf("RocketPort%d = %d ports\n", unit, num_ports);
1209 rp_num_ports[unit] = num_ports;
1210
1211 rp = (struct rp_port *)
1212 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT);
1213 if(rp == 0) {
1214 printf("rp_attach: Could not malloc rp_ports structures\n");
1215 return(0);
1216 }
1217
1218 count = unit * 32; /* board # times max ports per card SG */
1219 for(i=count;i < (count + rp_num_ports[unit]);i++)
1220 minor_to_unit[i] = unit;
1221
1222 bzero(rp, sizeof(struct rp_port) * num_ports);
1223 tty = (struct tty *)
1224 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT);
1225 if(tty == 0) {
1226 printf("rp_attach: Could not malloc tty structures\n");
1227 return(0);
1228 }
1229 bzero(tty, sizeof(struct tty) * num_ports);
1230
1231 oldspl = spltty();
1232 rp_addr(unit) = rp;
1233 splx(oldspl);
1234
1235 cdevsw_add(&rp_cdevsw);
1236
1237 port = 0;
1238 for(aiop=0; aiop < num_aiops; aiop++) {
1239 num_chan = sGetAiopNumChan(ctlp, aiop);
1240 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) {
1241 rp->rp_tty = tty;
1242 rp->rp_port = port;
1243 rp->rp_ctlp = ctlp;
1244 rp->rp_unit = unit;
1245 rp->rp_chan = chan;
1246 rp->rp_aiop = aiop;
1247
1248 tty->t_line = 0;
1249 /* tty->t_termios = deftermios;
1250 */
1251 rp->dtr_wait = 3 * hz;
1252 rp->it_in.c_iflag = 0;
1253 rp->it_in.c_oflag = 0;
1254 rp->it_in.c_cflag = TTYDEF_CFLAG;
1255 rp->it_in.c_lflag = 0;
1256 termioschars(&rp->it_in);
1257 /* termioschars(&tty->t_termios);
1258 */
1259 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED;
1260 rp->it_out = rp->it_in;
1261
1262 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT |
1263 DELTA_CD | DELTA_CTS | DELTA_DSR;
1264 ChanStatus = sGetChanStatus(&rp->rp_channel);
1265 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) {
1266 printf("RocketPort sInitChan(%d, %d, %d) failed
1267 \n", unit, aiop, chan);
1268 return(0);
1269 }
1270 ChanStatus = sGetChanStatus(&rp->rp_channel);
1271 rp->rp_cts = (ChanStatus & CTS_ACT) != 0;
1272 line = (unit << 5) | (aiop << 3) | chan;
1273 rp_table(line) = rp;
1274 }
1275 }
1276
1277 return(1);
1278}
1279
1280int
1281rpopen(dev, flag, mode, p)
1282 dev_t dev;
1283 int flag, mode;
1284 struct proc *p;
1285{
1286 struct rp_port *rp;
1287 int unit, port, mynor, umynor, flags; /* SG */
1288 struct tty *tp;
1289 int oldspl, error;
1290 unsigned int IntMask, ChanStatus;
1291
1292
1293 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1294 port = (minor(dev) & 0x1f); /* SG */
1295 mynor = (port + umynor); /* SG */
1296 unit = minor_to_unit[mynor];
1297 if (rp_addr(unit) == NULL)
1298 return (ENXIO);
1299 if(IS_CONTROL(dev))
1300 return(0);
1301 rp = rp_addr(unit) + port;
1302/* rp->rp_tty = &rp_tty[rp->rp_port];
1303*/
1304 tp = rp->rp_tty;
1305 dev->si_tty = tp;
1306
1307 oldspl = spltty();
1308
1309open_top:
1310 while(rp->state & ~SET_DTR) {
1311 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0);
1312 if(error != 0)
1313 goto out;
1314 }
1315
1316 if(tp->t_state & TS_ISOPEN) {
1317 if(IS_CALLOUT(dev)) {
1318 if(!rp->active_out) {
1319 error = EBUSY;
1320 goto out;
1321 }
1322 } else {
1323 if(rp->active_out) {
1324 if(flag & O_NONBLOCK) {
1325 error = EBUSY;
1326 goto out;
1327 }
1328 error = tsleep(&rp->active_out,
1329 TTIPRI | PCATCH, "rpbi", 0);
1330 if(error != 0)
1331 goto out;
1332 goto open_top;
1333 }
1334 }
1335 if(tp->t_state & TS_XCLUDE &&
1336 suser(td)) {
1337 splx(oldspl);
1338 return(EBUSY);
1339 }
1340 }
1341 else {
1342 tp->t_dev = dev;
1343 tp->t_param = rpparam;
1344 tp->t_oproc = rpstart;
1345 tp->t_stop = rpstop;
1346 tp->t_line = 0;
1347 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in;
1348 flags = 0;
1349 flags |= SET_RTS;
1350 flags |= SET_DTR;
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);
1360
1361 sEnInterrupts(&rp->rp_channel,
1362 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
1363 sSetRxTrigger(&rp->rp_channel, TRIG_1);
1364
1365 sDisRxStatusMode(&rp->rp_channel);
1366 sClrTxXOFF(&rp->rp_channel);
1367
1368/* sDisRTSFlowCtl(&rp->rp_channel);
1369 sDisCTSFlowCtl(&rp->rp_channel);
1370*/
1371 sDisTxSoftFlowCtl(&rp->rp_channel);
1372
1373 sStartRxProcessor(&rp->rp_channel);
1374
1375 sEnRxFIFO(&rp->rp_channel);
1376 sEnTransmit(&rp->rp_channel);
1377
1378/* sSetDTR(&rp->rp_channel);
1379 sSetRTS(&rp->rp_channel);
1380*/
1381
1382 ++rp->wopeners;
1383 error = rpparam(tp, &tp->t_termios);
1384 --rp->wopeners;
1385 if(error != 0) {
1386 splx(oldspl);
1387 return(error);
1388 }
1389
1390 rp_num_ports_open++;
1391
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);
1398 }
1399 }
1400
1401 if(rp_num_ports_open == 1)
1402 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1403
1404 }
1405
1406 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) &&
1407 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) {
1408 ++rp->wopeners;
1409 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH,
1410 "rpdcd", 0);
1411 --rp->wopeners;
1412 if(error != 0)
1413 goto out;
1414 goto open_top;
1415 }
1416 error = (*linesw[tp->t_line].l_open)(dev, tp);
1417
1418 rp_disc_optim(tp, &tp->t_termios, rp);
1419 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev))
1420 rp->active_out = TRUE;
1421
1422/* if(rp_num_ports_open == 1)
1423 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL);
1424*/
1425out:
1426 splx(oldspl);
1427 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) {
1428 rphardclose(rp);
1429 }
1430 return(error);
1431}
1432
1433int
1434rpclose(dev, flag, mode, p)
1435 dev_t dev;
1436 int flag, mode;
1437 struct proc *p;
1438{
1439 int oldspl, unit, mynor, umynor, port; /* SG */
1440 struct rp_port *rp;
1441 struct tty *tp;
1442 CHANNEL_t *cp;
1443
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 */
1448
1449 if(IS_CONTROL(dev))
1450 return(0);
1451 rp = rp_addr(unit) + port;
1452 cp = &rp->rp_channel;
1453 tp = rp->rp_tty;
1454
1455 oldspl = spltty();
1456 (*linesw[tp->t_line].l_close)(tp, flag);
1457 rp_disc_optim(tp, &tp->t_termios, rp);
1458 rpstop(tp, FREAD | FWRITE);
1459 rphardclose(rp);
1460
1461 tp->t_state &= ~TS_BUSY;
1462 ttyclose(tp);
1463
1464 splx(oldspl);
1465
1466 return(0);
1467}
1468
1469static void
1470rphardclose(struct rp_port *rp)
1471{
1472 int mynor;
1473 struct tty *tp;
1474 CHANNEL_t *cp;
1475
1476 cp = &rp->rp_channel;
1477 tp = rp->rp_tty;
1478 mynor = MINOR_MAGIC(tp->t_dev);
1479
1480 sFlushRxFIFO(cp);
1481 sFlushTxFIFO(cp);
1482 sDisTransmit(cp);
1483 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN);
1484 sDisRTSFlowCtl(cp);
1485 sDisCTSFlowCtl(cp);
1486 sDisTxSoftFlowCtl(cp);
1487 sClrTxXOFF(cp);
1488
1489 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) {
1490 sClrDTR(cp);
1491 }
1492 if(IS_CALLOUT(tp->t_dev)) {
1493 sClrDTR(cp);
1494 }
1495 if(rp->dtr_wait != 0) {
1496 timeout(rpdtrwakeup, rp, rp->dtr_wait);
1497 rp->state |= ~SET_DTR;
1498 }
1499
1500 rp->active_out = FALSE;
1501 wakeup(&rp->active_out);
1502 wakeup(TSA_CARR_ON(tp));
1503}
1504
1505static
1506int
1507rpwrite(dev, uio, flag)
1508 dev_t dev;
1509 struct uio *uio;
1510 int flag;
1511{
1512 struct rp_port *rp;
1513 struct tty *tp;
1514 int unit, mynor, port, umynor, error = 0; /* SG */
1515
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 */
1520
1521 if(IS_CONTROL(dev))
1522 return(ENODEV);
1523 rp = rp_addr(unit) + port;
1524 tp = rp->rp_tty;
1525 while(rp->rp_disable_writes) {
1526 rp->rp_waiting = 1;
1527 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0);
1528 if (error)
1529 return(error);
1530 }
1531
1532 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
1533 return error;
1534}
1535
1536static void
1537rpdtrwakeup(void *chan)
1538{
1539 struct rp_port *rp;
1540
1541 rp = (struct rp_port *)chan;
1542 rp->state &= SET_DTR;
1543 wakeup(&rp->dtr_wait);
1544}
1545
1546int
1547rpioctl(dev, cmd, data, flag, p)
1548 dev_t dev;
1549 u_long cmd;
1550 caddr_t data;
1551 int flag;
1552 struct proc *p;
1553{
1554 struct rp_port *rp;
1555 CHANNEL_t *cp;
1556 struct tty *tp;
1557 int unit, mynor, port, umynor; /* SG */
1558 int oldspl;
1559 int error = 0;
1560 int arg, flags, result, ChanStatus;
1561 int oldcmd;
1562 struct termios term, *t;
1563
1564 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */
1565 port = (minor(dev) & 0x1f); /* SG */
1566 mynor = (port + umynor); /* SG */
1567 unit = minor_to_unit[mynor];
1568 rp = rp_addr(unit) + port;
1569
1570 if(IS_CONTROL(dev)) {
1571 struct termios *ct;
1572
1573 switch (IS_CONTROL(dev)) {
1574 case CONTROL_INIT_STATE:
1575 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in;
1576 break;
1577 case CONTROL_LOCK_STATE:
1578 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in;
1579 break;
1580 default:
1581 return(ENODEV); /* /dev/nodev */
1582 }
1583 switch (cmd) {
1584 case TIOCSETA:
1585 error = suser(td);
1586 if(error != 0)
1587 return(error);
1588 *ct = *(struct termios *)data;
1589 return(0);
1590 case TIOCGETA:
1591 *(struct termios *)data = *ct;
1592 return(0);
1593 case TIOCGETD:
1594 *(int *)data = TTYDISC;
1595 return(0);
1596 case TIOCGWINSZ:
1597 bzero(data, sizeof(struct winsize));
1598 return(0);
1599 default:
1600 return(ENOTTY);
1601 }
1602 }
1603
1604 tp = rp->rp_tty;
1605 cp = &rp->rp_channel;
1606
1607#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1608 term = tp->t_termios;
1609 oldcmd = cmd;
1610 error = ttsetcompat(tp, &cmd, data, &term);
1611 if(error != 0)
1612 return(error);
1613 if(cmd != oldcmd) {
1614 data = (caddr_t)&term;
1615 }
1616#endif
1617 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
1618 int cc;
1619 struct termios *dt = (struct termios *)data;
1620 struct termios *lt = IS_CALLOUT(dev)
1621 ? &rp->lt_out : &rp->lt_in;
1622
1623 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
1624 | (dt->c_iflag & ~lt->c_iflag);
1625 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
1626 | (dt->c_oflag & ~lt->c_oflag);
1627 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
1628 | (dt->c_cflag & ~lt->c_cflag);
1629 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
1630 | (dt->c_lflag & ~lt->c_lflag);
1631 for(cc = 0; cc < NCCS; ++cc)
1632 if(lt->c_cc[cc] != 0)
1633 dt->c_cc[cc] = tp->t_cc[cc];
1634 if(lt->c_ispeed != 0)
1635 dt->c_ispeed = tp->t_ispeed;
1636 if(lt->c_ospeed != 0)
1637 dt->c_ospeed = tp->t_ospeed;
1638 }
1639
1640 t = &tp->t_termios;
1641
1642 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1643 if(error != ENOIOCTL) {
1644 return(error);
1645 }
1646 oldspl = spltty();
1647
1648 flags = rp->rp_channel.TxControl[3];
1649
1650 error = ttioctl(tp, cmd, data, flag);
1651 flags = rp->rp_channel.TxControl[3];
1652 rp_disc_optim(tp, &tp->t_termios, rp);
1653 if(error != ENOIOCTL) {
1654 splx(oldspl);
1655 return(error);
1656 }
1657 switch(cmd) {
1658 case TIOCSBRK:
1659 sSendBreak(&rp->rp_channel);
1660 break;
1661
1662 case TIOCCBRK:
1663 sClrBreak(&rp->rp_channel);
1664 break;
1665
1666 case TIOCSDTR:
1667 sSetDTR(&rp->rp_channel);
1668 sSetRTS(&rp->rp_channel);
1669 break;
1670
1671 case TIOCCDTR:
1672 sClrDTR(&rp->rp_channel);
1673 break;
1674
1675 case TIOCMSET:
1676 arg = *(int *) data;
1677 flags = 0;
1678 if(arg & TIOCM_RTS)
1679 flags |= SET_RTS;
1680 if(arg & TIOCM_DTR)
1681 flags |= SET_DTR;
1682 rp->rp_channel.TxControl[3] =
1683 ((rp->rp_channel.TxControl[3]
1684 & ~(SET_RTS | SET_DTR)) | flags);
1685 sOutDW(rp->rp_channel.IndexAddr,
1686 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1687 break;
1688 case TIOCMBIS:
1689 arg = *(int *) data;
1690 flags = 0;
1691 if(arg & TIOCM_RTS)
1692 flags |= SET_RTS;
1693 if(arg & TIOCM_DTR)
1694 flags |= SET_DTR;
1695 rp->rp_channel.TxControl[3] |= flags;
1696 sOutDW(rp->rp_channel.IndexAddr,
1697 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1698 break;
1699 case TIOCMBIC:
1700 arg = *(int *) data;
1701 flags = 0;
1702 if(arg & TIOCM_RTS)
1703 flags |= SET_RTS;
1704 if(arg & TIOCM_DTR)
1705 flags |= SET_DTR;
1706 rp->rp_channel.TxControl[3] &= ~flags;
1707 sOutDW(rp->rp_channel.IndexAddr,
1708 *(DWord_t *) &(rp->rp_channel.TxControl[0]));
1709 break;
1710
1711
1712 case TIOCMGET:
1713 ChanStatus = sGetChanStatusLo(&rp->rp_channel);
1714 flags = rp->rp_channel.TxControl[3];
1715 result = TIOCM_LE; /* always on while open for some reason */
1716 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0)
1717 | ((flags & SET_RTS) ? TIOCM_RTS : 0)
1718 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
1719 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
1720 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0));
1721
1722 if(rp->rp_channel.RxControl[2] & RTSFC_EN)
1723 {
1724 result |= TIOCM_RTS;
1725 }
1726
1727 *(int *)data = result;
1728 break;
1729 case TIOCMSDTRWAIT:
1730 error = suser(td);
1731 if(error != 0) {
1732 splx(oldspl);
1733 return(error);
1734 }
1735 rp->dtr_wait = *(int *)data * hz/100;
1736 break;
1737 case TIOCMGDTRWAIT:
1738 *(int *)data = rp->dtr_wait * 100/hz;
1739 break;
1740 default:
1741 splx(oldspl);
1742 return ENOTTY;
1743 }
1744 splx(oldspl);
1745 return(0);
1746}
1747
1748static struct speedtab baud_table[] = {
1749 {B0, 0}, {B50, BRD50}, {B75, BRD75},
1750 {B110, BRD110}, {B134, BRD134}, {B150, BRD150},
1751 {B200, BRD200}, {B300, BRD300}, {B600, BRD600},
1752 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400},
1753 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200},
1754 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400},
1755 {B57600, BRD57600}, {B76800, BRD76800},
1756 {B115200, BRD115200}, {B230400, BRD230400},
1757 -1, -1
1758};
1759
1760static int
1761rpparam(tp, t)
1762 struct tty *tp;
1763 struct termios *t;
1764{
1765 struct rp_port *rp;
1766 CHANNEL_t *cp;
1767 int unit, mynor, port, umynor; /* SG */
1768 int oldspl, cflag, iflag, oflag, lflag;
1769 int ospeed;
1770
1771
1772 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1773 port = (minor(tp->t_dev) & 0x1f); /* SG */
1774 mynor = (port + umynor); /* SG */
1775
1776 unit = minor_to_unit[mynor];
1777 rp = rp_addr(unit) + port;
1778 cp = &rp->rp_channel;
1779 oldspl = spltty();
1780
1781 cflag = t->c_cflag;
1782 iflag = t->c_iflag;
1783 oflag = t->c_oflag;
1784 lflag = t->c_lflag;
1785
1786 ospeed = ttspeedtab(t->c_ispeed, baud_table);
1787 if(ospeed < 0 || t->c_ispeed != t->c_ospeed)
1788 return(EINVAL);
1789
1790 tp->t_ispeed = t->c_ispeed;
1791 tp->t_ospeed = t->c_ospeed;
1792 tp->t_cflag = cflag;
1793 tp->t_iflag = iflag;
1794 tp->t_oflag = oflag;
1795 tp->t_lflag = lflag;
1796
1797 if(t->c_ospeed == 0) {
1798 sClrDTR(cp);
1799 return(0);
1800 }
1801 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1;
1802
1803 /* Set baud rate ----- we only pay attention to ispeed */
1804 sSetDTR(cp);
1805 sSetRTS(cp);
1806 sSetBaud(cp, ospeed);
1807
1808 if(cflag & CSTOPB) {
1809 sSetStop2(cp);
1810 } else {
1811 sSetStop1(cp);
1812 }
1813
1814 if(cflag & PARENB) {
1815 sEnParity(cp);
1816 if(cflag & PARODD) {
1817 sSetOddParity(cp);
1818 } else {
1819 sSetEvenParity(cp);
1820 }
1821 }
1822 else {
1823 sDisParity(cp);
1824 }
1825 if((cflag & CSIZE) == CS8) {
1826 sSetData8(cp);
1827 rp->rp_imask = 0xFF;
1828 } else {
1829 sSetData7(cp);
1830 rp->rp_imask = 0x7F;
1831 }
1832
1833 if(iflag & ISTRIP) {
1834 rp->rp_imask &= 0x7F;
1835 }
1836
1837 if(cflag & CLOCAL) {
1838 rp->rp_intmask &= ~DELTA_CD;
1839 } else {
1840 rp->rp_intmask |= DELTA_CD;
1841 }
1842
1843 /* Put flow control stuff here */
1844
1845 if(cflag & CCTS_OFLOW) {
1846 sEnCTSFlowCtl(cp);
1847 } else {
1848 sDisCTSFlowCtl(cp);
1849 }
1850
1851 if(cflag & CRTS_IFLOW) {
1852 rp->rp_rts_iflow = 1;
1853 } else {
1854 rp->rp_rts_iflow = 0;
1855 }
1856
1857 if(cflag & CRTS_IFLOW) {
1858 sEnRTSFlowCtl(cp);
1859 } else {
1860 sDisRTSFlowCtl(cp);
1861 }
1862 rp_disc_optim(tp, t, rp);
1863
1864 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) {
1865 tp->t_state |= TS_CARR_ON;
1866 wakeup(TSA_CARR_ON(tp));
1867 }
1868
1869/* tp->t_state |= TS_CAN_BYPASS_L_RINT;
1870 flags = rp->rp_channel.TxControl[3];
1871 if(flags & SET_DTR)
1872 else
1873 if(flags & SET_RTS)
1874 else
1875*/
1876 splx(oldspl);
1877
1878 return(0);
1879}
1880
1881static void
1882rp_disc_optim(tp, t, rp)
1883struct tty *tp;
1884struct termios *t;
1885struct rp_port *rp;
1886{
1887 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
1888 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
1889 &&(!(t->c_iflag & PARMRK)
1890 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
1891 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
1892 && linesw[tp->t_line].l_rint == ttyinput)
1893 tp->t_state |= TS_CAN_BYPASS_L_RINT;
1894 else
1895 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
1896}
1897
1898static void
1899rpstart(tp)
1900 struct tty *tp;
1901{
1902 struct rp_port *rp;
1903 CHANNEL_t *cp;
1904 struct clist *qp;
1905 int unit, mynor, port, umynor; /* SG */
1906 char ch, flags;
1907 int spl, xmit_fifo_room;
1908 int count;
1909
1910
1911 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1912 port = (minor(tp->t_dev) & 0x1f); /* SG */
1913 mynor = (port + umynor); /* SG */
1914 unit = minor_to_unit[mynor];
1915 rp = rp_addr(unit) + port;
1916 cp = &rp->rp_channel;
1917 flags = rp->rp_channel.TxControl[3];
1918 spl = spltty();
1919
1920 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
1921 ttwwakeup(tp);
1922 splx(spl);
1923 return;
1924 }
1925 if(rp->rp_xmit_stopped) {
1926 sEnTransmit(cp);
1927 rp->rp_xmit_stopped = 0;
1928 }
1929 count = sGetTxCnt(cp);
1930
1931 if(tp->t_outq.c_cc == 0) {
1932 if((tp->t_state & TS_BUSY) && (count == 0)) {
1933 tp->t_state &= ~TS_BUSY;
1934 }
1935 ttwwakeup(tp);
1936 splx(spl);
1937 return;
1938 }
1939 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
1940 qp = &tp->t_outq;
1941 count = 0;
1942 if(xmit_fifo_room > 0 && qp->c_cc > 0) {
1943 tp->t_state |= TS_BUSY;
1944 }
1945 while(xmit_fifo_room > 0 && qp->c_cc > 0) {
1946 ch = getc(qp);
1947 sOutB(sGetTxRxDataIO(cp), ch);
1948 xmit_fifo_room--;
1949 count++;
1950 }
1951 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0;
1952
1953 ttwwakeup(tp);
1954 splx(spl);
1955}
1956
1957static
1958void
1959rpstop(tp, flag)
1960 register struct tty *tp;
1961 int flag;
1962{
1963 struct rp_port *rp;
1964 CHANNEL_t *cp;
1965 int unit, mynor, port, umynor; /* SG */
1966 int spl;
1967
1968 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */
1969 port = (minor(tp->t_dev) & 0x1f); /* SG */
1970 mynor = (port + umynor); /* SG */
1971 unit = minor_to_unit[mynor];
1972 rp = rp_addr(unit) + port;
1973 cp = &rp->rp_channel;
1974
1975 spl = spltty();
1976
1977 if(tp->t_state & TS_BUSY) {
1978 if((tp->t_state&TS_TTSTOP) == 0) {
1979 sFlushTxFIFO(cp);
1980 } else {
1981 if(rp->rp_xmit_stopped == 0) {
1982 sDisTransmit(cp);
1983 rp->rp_xmit_stopped = 1;
1984 }
1985 }
1986 }
1987 splx(spl);
1988 rpstart(tp);
1989}