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