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