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