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