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