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