rp.c revision 69781
1/* 2 * Copyright (c) Comtrol Corporation <support@comtrol.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted prodived that the follwoing conditions 7 * are met. 8 * 1. Redistributions of source code must retain the above copyright 9 * notive, this list of conditions and the following disclainer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials prodided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Comtrol Corporation. 16 * 4. The name of Comtrol Corporation may not be used to endorse or 17 * promote products derived from this software without specific 18 * prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/dev/rp/rp.c 69781 2000-12-08 21:51:06Z dwmalone $ 33 */ 34 35/* 36 * rp.c - for RocketPort FreeBSD 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/fcntl.h> 42#include <sys/malloc.h> 43#include <sys/tty.h> 44#include <sys/dkstat.h> 45#include <sys/conf.h> 46#include <sys/kernel.h> 47#include <machine/resource.h> 48#include <machine/bus.h> 49#include <sys/bus.h> 50#include <sys/rman.h> 51 52#define ROCKET_C 53#include <dev/rp/rpreg.h> 54#include <dev/rp/rpvar.h> 55 56static const char RocketPortVersion[] = "3.02"; 57 58static Byte_t RData[RDATASIZE] = 59{ 60 0x00, 0x09, 0xf6, 0x82, 61 0x02, 0x09, 0x86, 0xfb, 62 0x04, 0x09, 0x00, 0x0a, 63 0x06, 0x09, 0x01, 0x0a, 64 0x08, 0x09, 0x8a, 0x13, 65 0x0a, 0x09, 0xc5, 0x11, 66 0x0c, 0x09, 0x86, 0x85, 67 0x0e, 0x09, 0x20, 0x0a, 68 0x10, 0x09, 0x21, 0x0a, 69 0x12, 0x09, 0x41, 0xff, 70 0x14, 0x09, 0x82, 0x00, 71 0x16, 0x09, 0x82, 0x7b, 72 0x18, 0x09, 0x8a, 0x7d, 73 0x1a, 0x09, 0x88, 0x81, 74 0x1c, 0x09, 0x86, 0x7a, 75 0x1e, 0x09, 0x84, 0x81, 76 0x20, 0x09, 0x82, 0x7c, 77 0x22, 0x09, 0x0a, 0x0a 78}; 79 80static Byte_t RRegData[RREGDATASIZE]= 81{ 82 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ 83 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ 84 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ 85 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ 86 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ 87 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ 88 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ 89 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ 90 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ 91 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ 92 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ 93 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ 94 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ 95}; 96 97#if 0 98/* IRQ number to MUDBAC register 2 mapping */ 99Byte_t sIRQMap[16] = 100{ 101 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 102}; 103#endif 104 105Byte_t rp_sBitMapClrTbl[8] = 106{ 107 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f 108}; 109 110Byte_t rp_sBitMapSetTbl[8] = 111{ 112 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 113}; 114 115/* Actually not used */ 116#if notdef 117struct termios deftermios = { 118 TTYDEF_IFLAG, 119 TTYDEF_OFLAG, 120 TTYDEF_CFLAG, 121 TTYDEF_LFLAG, 122 { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, 123 _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, 124 CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE }, 125 TTYDEF_SPEED, 126 TTYDEF_SPEED 127}; 128#endif 129 130/*************************************************************************** 131Function: sReadAiopID 132Purpose: Read the AIOP idenfication number directly from an AIOP. 133Call: sReadAiopID(CtlP, aiop) 134 CONTROLLER_T *CtlP; Ptr to controller structure 135 int aiop: AIOP index 136Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X 137 is replace by an identifying number. 138 Flag AIOPID_NULL if no valid AIOP is found 139Warnings: No context switches are allowed while executing this function. 140 141*/ 142int sReadAiopID(CONTROLLER_T *CtlP, int aiop) 143{ 144 Byte_t AiopID; /* ID byte from AIOP */ 145 146 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */ 147 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0); 148 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07; 149 if(AiopID == 0x06) 150 return(1); 151 else /* AIOP does not exist */ 152 return(-1); 153} 154 155/*************************************************************************** 156Function: sReadAiopNumChan 157Purpose: Read the number of channels available in an AIOP directly from 158 an AIOP. 159Call: sReadAiopNumChan(CtlP, aiop) 160 CONTROLLER_T *CtlP; Ptr to controller structure 161 int aiop: AIOP index 162Return: int: The number of channels available 163Comments: The number of channels is determined by write/reads from identical 164 offsets within the SRAM address spaces for channels 0 and 4. 165 If the channel 4 space is mirrored to channel 0 it is a 4 channel 166 AIOP, otherwise it is an 8 channel. 167Warnings: No context switches are allowed while executing this function. 168*/ 169int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop) 170{ 171 Word_t x, y; 172 173 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ 174 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */ 175 x = rp_readaiop2(CtlP, aiop, _INDX_DATA); 176 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ 177 y = rp_readaiop2(CtlP, aiop, _INDX_DATA); 178 if(x != y) /* if different must be 8 chan */ 179 return(8); 180 else 181 return(4); 182} 183 184/*************************************************************************** 185Function: sInitChan 186Purpose: Initialization of a channel and channel structure 187Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) 188 CONTROLLER_T *CtlP; Ptr to controller structure 189 CHANNEL_T *ChP; Ptr to channel structure 190 int AiopNum; AIOP number within controller 191 int ChanNum; Channel number within AIOP 192Return: int: TRUE if initialization succeeded, FALSE if it fails because channel 193 number exceeds number of channels available in AIOP. 194Comments: This function must be called before a channel can be used. 195Warnings: No range checking on any of the parameters is done. 196 197 No context switches are allowed while executing this function. 198*/ 199int sInitChan( CONTROLLER_T *CtlP, 200 CHANNEL_T *ChP, 201 int AiopNum, 202 int ChanNum) 203{ 204 int i, ChOff; 205 Byte_t *ChR; 206 static Byte_t R[4]; 207 208 if(ChanNum >= CtlP->AiopNumChan[AiopNum]) 209 return(FALSE); /* exceeds num chans in AIOP */ 210 211 /* Channel, AIOP, and controller identifiers */ 212 ChP->CtlP = CtlP; 213 ChP->ChanID = CtlP->AiopID[AiopNum]; 214 ChP->AiopNum = AiopNum; 215 ChP->ChanNum = ChanNum; 216 217 /* Initialize the channel from the RData array */ 218 for(i=0; i < RDATASIZE; i+=4) 219 { 220 R[0] = RData[i]; 221 R[1] = RData[i+1] + 0x10 * ChanNum; 222 R[2] = RData[i+2]; 223 R[3] = RData[i+3]; 224 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)&R[0])); 225 } 226 227 ChR = ChP->R; 228 for(i=0; i < RREGDATASIZE; i+=4) 229 { 230 ChR[i] = RRegData[i]; 231 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; 232 ChR[i+2] = RRegData[i+2]; 233 ChR[i+3] = RRegData[i+3]; 234 } 235 236 /* Indexed registers */ 237 ChOff = (Word_t)ChanNum * 0x1000; 238 239 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); 240 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); 241 ChP->BaudDiv[2] = (Byte_t)BRD9600; 242 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); 243 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->BaudDiv[0]); 244 245 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); 246 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); 247 ChP->TxControl[2] = 0; 248 ChP->TxControl[3] = 0; 249 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]); 250 251 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); 252 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); 253 ChP->RxControl[2] = 0; 254 ChP->RxControl[3] = 0; 255 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]); 256 257 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); 258 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); 259 ChP->TxEnables[2] = 0; 260 ChP->TxEnables[3] = 0; 261 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxEnables[0]); 262 263 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); 264 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); 265 ChP->TxCompare[2] = 0; 266 ChP->TxCompare[3] = 0; 267 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxCompare[0]); 268 269 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); 270 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); 271 ChP->TxReplace1[2] = 0; 272 ChP->TxReplace1[3] = 0; 273 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace1[0]); 274 275 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); 276 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); 277 ChP->TxReplace2[2] = 0; 278 ChP->TxReplace2[3] = 0; 279 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxReplace2[0]); 280 281 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; 282 ChP->TxFIFO = ChOff + _TX_FIFO; 283 284 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ 285 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ 286 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 287 rp_writech2(ChP,_INDX_DATA,0); 288 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; 289 ChP->RxFIFO = ChOff + _RX_FIFO; 290 291 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ 292 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ 293 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 294 rp_writech2(ChP,_INDX_DATA,0); 295 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 296 rp_writech2(ChP,_INDX_DATA,0); 297 ChP->TxPrioCnt = ChOff + _TXP_CNT; 298 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); 299 rp_writech1(ChP,_INDX_DATA,0); 300 ChP->TxPrioPtr = ChOff + _TXP_PNTR; 301 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr); 302 rp_writech1(ChP,_INDX_DATA,0); 303 ChP->TxPrioBuf = ChOff + _TXP_BUF; 304 sEnRxProcessor(ChP); /* start the Rx processor */ 305 306 return(TRUE); 307} 308 309/*************************************************************************** 310Function: sStopRxProcessor 311Purpose: Stop the receive processor from processing a channel. 312Call: sStopRxProcessor(ChP) 313 CHANNEL_T *ChP; Ptr to channel structure 314 315Comments: The receive processor can be started again with sStartRxProcessor(). 316 This function causes the receive processor to skip over the 317 stopped channel. It does not stop it from processing other channels. 318 319Warnings: No context switches are allowed while executing this function. 320 321 Do not leave the receive processor stopped for more than one 322 character time. 323 324 After calling this function a delay of 4 uS is required to ensure 325 that the receive processor is no longer processing this channel. 326*/ 327void sStopRxProcessor(CHANNEL_T *ChP) 328{ 329 Byte_t R[4]; 330 331 R[0] = ChP->R[0]; 332 R[1] = ChP->R[1]; 333 R[2] = 0x0a; 334 R[3] = ChP->R[3]; 335 rp_writech4(ChP, _INDX_ADDR,*(DWord_t *)&R[0]); 336} 337 338/*************************************************************************** 339Function: sFlushRxFIFO 340Purpose: Flush the Rx FIFO 341Call: sFlushRxFIFO(ChP) 342 CHANNEL_T *ChP; Ptr to channel structure 343Return: void 344Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 345 while it is being flushed the receive processor is stopped 346 and the transmitter is disabled. After these operations a 347 4 uS delay is done before clearing the pointers to allow 348 the receive processor to stop. These items are handled inside 349 this function. 350Warnings: No context switches are allowed while executing this function. 351*/ 352void sFlushRxFIFO(CHANNEL_T *ChP) 353{ 354 int i; 355 Byte_t Ch; /* channel number within AIOP */ 356 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ 357 358 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ 359 return; /* don't need to flush */ 360 361 RxFIFOEnabled = FALSE; 362 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ 363 { 364 RxFIFOEnabled = TRUE; 365 sDisRxFIFO(ChP); /* disable it */ 366 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ 367 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ 368 } 369 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ 370 Ch = (Byte_t)sGetChanNum(ChP); 371 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ 372 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */ 373 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 374 rp_writech2(ChP,_INDX_DATA,0); 375 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 376 rp_writech2(ChP,_INDX_DATA,0); 377 if(RxFIFOEnabled) 378 sEnRxFIFO(ChP); /* enable Rx FIFO */ 379} 380 381/*************************************************************************** 382Function: sFlushTxFIFO 383Purpose: Flush the Tx FIFO 384Call: sFlushTxFIFO(ChP) 385 CHANNEL_T *ChP; Ptr to channel structure 386Return: void 387Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 388 while it is being flushed the receive processor is stopped 389 and the transmitter is disabled. After these operations a 390 4 uS delay is done before clearing the pointers to allow 391 the receive processor to stop. These items are handled inside 392 this function. 393Warnings: No context switches are allowed while executing this function. 394*/ 395void sFlushTxFIFO(CHANNEL_T *ChP) 396{ 397 int i; 398 Byte_t Ch; /* channel number within AIOP */ 399 int TxEnabled; /* TRUE if transmitter enabled */ 400 401 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ 402 return; /* don't need to flush */ 403 404 TxEnabled = FALSE; 405 if(ChP->TxControl[3] & TX_ENABLE) 406 { 407 TxEnabled = TRUE; 408 sDisTransmit(ChP); /* disable transmitter */ 409 } 410 sStopRxProcessor(ChP); /* stop Rx processor */ 411 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ 412 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ 413 Ch = (Byte_t)sGetChanNum(ChP); 414 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ 415 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */ 416 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 417 rp_writech2(ChP,_INDX_DATA,0); 418 if(TxEnabled) 419 sEnTransmit(ChP); /* enable transmitter */ 420 sStartRxProcessor(ChP); /* restart Rx processor */ 421} 422 423/*************************************************************************** 424Function: sWriteTxPrioByte 425Purpose: Write a byte of priority transmit data to a channel 426Call: sWriteTxPrioByte(ChP,Data) 427 CHANNEL_T *ChP; Ptr to channel structure 428 Byte_t Data; The transmit data byte 429 430Return: int: 1 if the bytes is successfully written, otherwise 0. 431 432Comments: The priority byte is transmitted before any data in the Tx FIFO. 433 434Warnings: No context switches are allowed while executing this function. 435*/ 436int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) 437{ 438 Byte_t DWBuf[4]; /* buffer for double word writes */ 439 Word_t *WordPtr; /* must be far because Win SS != DS */ 440 441 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ 442 { 443 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */ 444 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */ 445 return(0); /* nothing sent */ 446 447 WordPtr = (Word_t *)(&DWBuf[0]); 448 *WordPtr = ChP->TxPrioBuf; /* data byte address */ 449 450 DWBuf[2] = Data; /* data byte value */ 451 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */ 452 453 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ 454 455 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ 456 DWBuf[3] = 0; /* priority buffer pointer */ 457 rp_writech4(ChP,_INDX_ADDR,*((DWord_t *)(&DWBuf[0]))); /* write it out */ 458 } 459 else /* write it to Tx FIFO */ 460 { 461 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data); 462 } 463 return(1); /* 1 byte sent */ 464} 465 466/*************************************************************************** 467Function: sEnInterrupts 468Purpose: Enable one or more interrupts for a channel 469Call: sEnInterrupts(ChP,Flags) 470 CHANNEL_T *ChP; Ptr to channel structure 471 Word_t Flags: Interrupt enable flags, can be any combination 472 of the following flags: 473 TXINT_EN: Interrupt on Tx FIFO empty 474 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 475 sSetRxTrigger()) 476 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 477 MCINT_EN: Interrupt on modem input change 478 CHANINT_EN: Allow channel interrupt signal to the AIOP's 479 Interrupt Channel Register. 480Return: void 481Comments: If an interrupt enable flag is set in Flags, that interrupt will be 482 enabled. If an interrupt enable flag is not set in Flags, that 483 interrupt will not be changed. Interrupts can be disabled with 484 function sDisInterrupts(). 485 486 This function sets the appropriate bit for the channel in the AIOP's 487 Interrupt Mask Register if the CHANINT_EN flag is set. This allows 488 this channel's bit to be set in the AIOP's Interrupt Channel Register. 489 490 Interrupts must also be globally enabled before channel interrupts 491 will be passed on to the host. This is done with function 492 sEnGlobalInt(). 493 494 In some cases it may be desirable to disable interrupts globally but 495 enable channel interrupts. This would allow the global interrupt 496 status register to be used to determine which AIOPs need service. 497*/ 498void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) 499{ 500 Byte_t Mask; /* Interrupt Mask Register */ 501 502 ChP->RxControl[2] |= 503 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 504 505 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]); 506 507 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); 508 509 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]); 510 511 if(Flags & CHANINT_EN) 512 { 513 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum]; 514 rp_writech1(ChP,_INT_MASK,Mask); 515 } 516} 517 518/*************************************************************************** 519Function: sDisInterrupts 520Purpose: Disable one or more interrupts for a channel 521Call: sDisInterrupts(ChP,Flags) 522 CHANNEL_T *ChP; Ptr to channel structure 523 Word_t Flags: Interrupt flags, can be any combination 524 of the following flags: 525 TXINT_EN: Interrupt on Tx FIFO empty 526 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 527 sSetRxTrigger()) 528 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 529 MCINT_EN: Interrupt on modem input change 530 CHANINT_EN: Disable channel interrupt signal to the 531 AIOP's Interrupt Channel Register. 532Return: void 533Comments: If an interrupt flag is set in Flags, that interrupt will be 534 disabled. If an interrupt flag is not set in Flags, that 535 interrupt will not be changed. Interrupts can be enabled with 536 function sEnInterrupts(). 537 538 This function clears the appropriate bit for the channel in the AIOP's 539 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks 540 this channel's bit from being set in the AIOP's Interrupt Channel 541 Register. 542*/ 543void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) 544{ 545 Byte_t Mask; /* Interrupt Mask Register */ 546 547 ChP->RxControl[2] &= 548 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 549 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->RxControl[0]); 550 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); 551 rp_writech4(ChP,_INDX_ADDR,*(DWord_t *)&ChP->TxControl[0]); 552 553 if(Flags & CHANINT_EN) 554 { 555 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum]; 556 rp_writech1(ChP,_INT_MASK,Mask); 557 } 558} 559 560/********************************************************************* 561 Begin FreeBsd-specific driver code 562**********************************************************************/ 563 564static timeout_t rpdtrwakeup; 565 566static d_open_t rpopen; 567static d_close_t rpclose; 568static d_write_t rpwrite; 569static d_ioctl_t rpioctl; 570 571#define CDEV_MAJOR 81 572struct cdevsw rp_cdevsw = { 573 /* open */ rpopen, 574 /* close */ rpclose, 575 /* read */ ttyread, 576 /* write */ rpwrite, 577 /* ioctl */ rpioctl, 578 /* poll */ ttypoll, 579 /* mmap */ nommap, 580 /* strategy */ nostrategy, 581 /* name */ "rp", 582 /* maj */ CDEV_MAJOR, 583 /* dump */ nodump, 584 /* psize */ nopsize, 585 /* flags */ D_TTY, 586 /* bmaj */ -1 587}; 588 589static int rp_num_ports_open = 0; 590static int rp_ndevs = 0; 591static int minor_to_unit[128]; 592 593static int rp_num_ports[4]; /* Number of ports on each controller */ 594 595#define _INLINE_ __inline 596#define POLL_INTERVAL 1 597 598#define CALLOUT_MASK 0x80 599#define CONTROL_MASK 0x60 600#define CONTROL_INIT_STATE 0x20 601#define CONTROL_LOCK_STATE 0x40 602#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev)) 603#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 604#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK) 605#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK) 606#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK) 607 608#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) 609#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) 610#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) 611 612static struct rp_port *p_rp_addr[4]; 613static struct rp_port *p_rp_table[MAX_RP_PORTS]; 614#define rp_addr(unit) (p_rp_addr[unit]) 615#define rp_table(port) (p_rp_table[port]) 616 617/* 618 * The top-level routines begin here 619 */ 620 621static int rpparam __P((struct tty *, struct termios *)); 622static void rpstart __P((struct tty *)); 623static void rpstop __P((struct tty *, int)); 624static void rphardclose __P((struct rp_port *)); 625static void rp_disc_optim __P((struct tty *tp, struct termios *t)); 626 627static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp, 628 CHANNEL_t *cp, unsigned int ChanStatus) 629{ 630 int spl; 631 unsigned int CharNStat; 632 int ToRecv, wRecv, ch, ttynocopy; 633 634 ToRecv = sGetRxCnt(cp); 635 if(ToRecv == 0) 636 return; 637 638/* If status indicates there are errored characters in the 639 FIFO, then enter status mode (a word in FIFO holds 640 characters and status) 641*/ 642 643 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 644 if(!(ChanStatus & STATMODE)) { 645 ChanStatus |= STATMODE; 646 sEnRxStatusMode(cp); 647 } 648 } 649/* 650 if we previously entered status mode then read down the 651 FIFO one word at a time, pulling apart the character and 652 the status. Update error counters depending on status. 653*/ 654 if(ChanStatus & STATMODE) { 655 while(ToRecv) { 656 if(tp->t_state & TS_TBLOCK) { 657 break; 658 } 659 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); 660 ch = CharNStat & 0xff; 661 662 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 663 ch |= TTY_FE; 664 else if (CharNStat & STMPARITYH) 665 ch |= TTY_PE; 666 else if (CharNStat & STMRCVROVRH) 667 rp->rp_overflows++; 668 669 (*linesw[tp->t_line].l_rint)(ch, tp); 670 ToRecv--; 671 } 672/* 673 After emtying FIFO in status mode, turn off status mode 674*/ 675 676 if(sGetRxCnt(cp) == 0) { 677 sDisRxStatusMode(cp); 678 } 679 } else { 680 /* 681 * Avoid the grotesquely inefficient lineswitch routine 682 * (ttyinput) in "raw" mode. It usually takes about 450 683 * instructions (that's without canonical processing or echo!). 684 * slinput is reasonably fast (usually 40 instructions plus 685 * call overhead). 686 */ 687 ToRecv = sGetRxCnt(cp); 688 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { 689 if ( ToRecv > RXFIFO_SIZE ) { 690 ToRecv = RXFIFO_SIZE; 691 } 692 wRecv = ToRecv >> 1; 693 if ( wRecv ) { 694 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv); 695 } 696 if ( ToRecv & 1 ) { 697 rp->RxBuf[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 698 } 699 tk_nin += ToRecv; 700 tk_rawcc += ToRecv; 701 tp->t_rawcc += ToRecv; 702 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq); 703 ttwakeup(tp); 704 } else { 705 while (ToRecv) { 706 if(tp->t_state & TS_TBLOCK) { 707 break; 708 } 709 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 710 spl = spltty(); 711 (*linesw[tp->t_line].l_rint)(ch, tp); 712 splx(spl); 713 ToRecv--; 714 } 715 } 716 } 717} 718 719static _INLINE_ void rp_handle_port(struct rp_port *rp) 720{ 721 CHANNEL_t *cp; 722 struct tty *tp; 723 unsigned int IntMask, ChanStatus; 724 725 if(!rp) 726 return; 727 728 cp = &rp->rp_channel; 729 tp = rp->rp_tty; 730 IntMask = sGetChanIntID(cp); 731 IntMask = IntMask & rp->rp_intmask; 732 ChanStatus = sGetChanStatus(cp); 733 if(IntMask & RXF_TRIG) 734 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 735 rp_do_receive(rp, tp, cp, ChanStatus); 736 } 737 if(IntMask & DELTA_CD) { 738 if(ChanStatus & CD_ACT) { 739 if(!(tp->t_state & TS_CARR_ON) ) { 740 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 741 } 742 } else { 743 if((tp->t_state & TS_CARR_ON)) { 744 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 745 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 746 rphardclose(rp); 747 } 748 } 749 } 750 } 751/* oldcts = rp->rp_cts; 752 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 753 if(oldcts != rp->rp_cts) { 754 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 755 } 756*/ 757} 758 759static void rp_do_poll(void *not_used) 760{ 761 CONTROLLER_t *ctl; 762 struct rp_port *rp; 763 struct tty *tp; 764 int unit, aiop, ch, line, count; 765 unsigned char CtlMask, AiopMask; 766 767 for(unit = 0; unit < rp_ndevs; unit++) { 768 rp = rp_addr(unit); 769 ctl = rp->rp_ctlp; 770 CtlMask = ctl->ctlmask(ctl); 771 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 772 if(CtlMask & 1) { 773 AiopMask = sGetAiopIntStatus(ctl, aiop); 774 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 775 if(AiopMask & 1) { 776 line = (unit << 5) | (aiop << 3) | ch; 777 rp = rp_table(line); 778 rp_handle_port(rp); 779 } 780 } 781 } 782 } 783 784 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 785 line++, rp++) { 786 tp = rp->rp_tty; 787 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 788 count = sGetTxCnt(&rp->rp_channel); 789 if(count == 0) 790 tp->t_state &= ~(TS_BUSY); 791 if(!(tp->t_state & TS_TTSTOP) && 792 (count <= rp->rp_restart)) { 793 (*linesw[tp->t_line].l_start)(tp); 794 } 795 } 796 } 797 } 798 if(rp_num_ports_open) 799 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 800} 801 802int 803rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) 804{ 805 int oldspl, unit; 806 int num_chan; 807 int aiop, chan, port; 808 int ChanStatus, line, i, count; 809 int retval; 810 struct rp_port *rp; 811 struct tty *tty; 812 dev_t *dev_nodes; 813 814 unit = device_get_unit(ctlp->dev); 815 816 printf("RocketPort%d (Version %s) %d ports.\n", unit, 817 RocketPortVersion, num_ports); 818 rp_num_ports[unit] = num_ports; 819 820 ctlp->rp = rp = (struct rp_port *) 821 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); 822 if (rp == NULL) { 823 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); 824 retval = ENOMEM; 825 goto nogo; 826 } 827 828 count = unit * 32; /* board times max ports per card SG */ 829 for(i=count;i < (count + rp_num_ports[unit]);i++) 830 minor_to_unit[i] = unit; 831 832 bzero(rp, sizeof(struct rp_port) * num_ports); 833 ctlp->tty = tty = (struct tty *) 834 malloc(sizeof(struct tty) * num_ports, M_TTYS, 835 M_NOWAIT | M_ZERO); 836 if(tty == NULL) { 837 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc tty structures.\n"); 838 retval = ENOMEM; 839 goto nogo; 840 } 841 842 oldspl = spltty(); 843 rp_addr(unit) = rp; 844 splx(oldspl); 845 846 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO); 847 if(ctlp->dev_nodes == NULL) { 848 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n"); 849 retval = ENOMEM; 850 goto nogo; 851 } 852 853 for (i = 0 ; i < rp_num_ports[unit] ; i++) { 854 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i, 855 UID_ROOT, GID_WHEEL, 0666, "ttyR%c", 856 i <= 9 ? '0' + i : 'a' + i - 10); 857 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20, 858 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c", 859 i <= 9 ? '0' + i : 'a' + i - 10); 860 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40, 861 UID_ROOT, GID_WHEEL, 0666, "ttylR%c", 862 i <= 9 ? '0' + i : 'a' + i - 10); 863 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80, 864 UID_ROOT, GID_WHEEL, 0666, "cuaR%c", 865 i <= 9 ? '0' + i : 'a' + i - 10); 866 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0, 867 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c", 868 i <= 9 ? '0' + i : 'a' + i - 10); 869 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0, 870 UID_ROOT, GID_WHEEL, 0666, "cualR%c", 871 i <= 9 ? '0' + i : 'a' + i - 10); 872 } 873 874 port = 0; 875 for(aiop=0; aiop < num_aiops; aiop++) { 876 num_chan = sGetAiopNumChan(ctlp, aiop); 877 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { 878 rp->rp_tty = tty; 879 rp->rp_port = port; 880 rp->rp_ctlp = ctlp; 881 rp->rp_unit = unit; 882 rp->rp_chan = chan; 883 rp->rp_aiop = aiop; 884 885 tty->t_line = 0; 886 /* tty->t_termios = deftermios; 887 */ 888 rp->dtr_wait = 3 * hz; 889 rp->it_in.c_iflag = 0; 890 rp->it_in.c_oflag = 0; 891 rp->it_in.c_cflag = TTYDEF_CFLAG; 892 rp->it_in.c_lflag = 0; 893 termioschars(&rp->it_in); 894 /* termioschars(&tty->t_termios); 895 */ 896 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 897 rp->it_out = rp->it_in; 898 899 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 900 DELTA_CD | DELTA_CTS | DELTA_DSR; 901#if notdef 902 ChanStatus = sGetChanStatus(&rp->rp_channel); 903#endif /* notdef */ 904 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 905 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", 906 unit, aiop, chan); 907 retval = ENXIO; 908 goto nogo; 909 } 910 ChanStatus = sGetChanStatus(&rp->rp_channel); 911 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 912 line = (unit << 5) | (aiop << 3) | chan; 913 rp_table(line) = rp; 914 } 915 } 916 917 rp_ndevs++; 918 return (0); 919 920nogo: 921 rp_releaseresource(ctlp); 922 923 return (retval); 924} 925 926void 927rp_releaseresource(CONTROLLER_t *ctlp) 928{ 929 int i, s, unit; 930 931 unit = device_get_unit(ctlp->dev); 932 933 if (ctlp->rp != NULL) { 934 s = spltty(); 935 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) 936 if (p_rp_addr[i] == ctlp->rp) 937 p_rp_addr[i] = NULL; 938 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) 939 if (p_rp_table[i] == ctlp->rp) 940 p_rp_table[i] = NULL; 941 splx(s); 942 free(ctlp->rp, M_DEVBUF); 943 ctlp->rp = NULL; 944 } 945 if (ctlp->tty != NULL) { 946 free(ctlp->tty, M_DEVBUF); 947 ctlp->tty = NULL; 948 } 949 if (ctlp->dev != NULL) { 950 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++) 951 destroy_dev(ctlp->dev_nodes[i]); 952 free(ctlp->dev_nodes, M_DEVBUF); 953 ctlp->dev = NULL; 954 } 955} 956 957int 958rpopen(dev, flag, mode, p) 959 dev_t dev; 960 int flag, mode; 961 struct proc *p; 962{ 963 struct rp_port *rp; 964 int unit, port, mynor, umynor, flags; /* SG */ 965 struct tty *tp; 966 int oldspl, error; 967 unsigned int IntMask, ChanStatus; 968 969 970 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 971 port = (minor(dev) & 0x1f); /* SG */ 972 mynor = (port + umynor); /* SG */ 973 unit = minor_to_unit[mynor]; 974 if (rp_addr(unit) == NULL) 975 return (ENXIO); 976 if(IS_CONTROL(dev)) 977 return(0); 978 rp = rp_addr(unit) + port; 979/* rp->rp_tty = &rp_tty[rp->rp_port]; 980*/ 981 tp = rp->rp_tty; 982 dev->si_tty = tp; 983 984 oldspl = spltty(); 985 986open_top: 987 while(rp->state & ~SET_DTR) { 988 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0); 989 if(error != 0) 990 goto out; 991 } 992 993 if(tp->t_state & TS_ISOPEN) { 994 if(IS_CALLOUT(dev)) { 995 if(!rp->active_out) { 996 error = EBUSY; 997 goto out; 998 } 999 } else { 1000 if(rp->active_out) { 1001 if(flag & O_NONBLOCK) { 1002 error = EBUSY; 1003 goto out; 1004 } 1005 error = tsleep(&rp->active_out, 1006 TTIPRI | PCATCH, "rpbi", 0); 1007 if(error != 0) 1008 goto out; 1009 goto open_top; 1010 } 1011 } 1012 if(tp->t_state & TS_XCLUDE && suser(p) != 0) { 1013 splx(oldspl); 1014 error = EBUSY; 1015 goto out2; 1016 } 1017 } 1018 else { 1019 tp->t_dev = dev; 1020 tp->t_param = rpparam; 1021 tp->t_oproc = rpstart; 1022 tp->t_stop = rpstop; 1023 tp->t_line = 0; 1024 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; 1025 tp->t_ififosize = 512; 1026 tp->t_ispeedwat = (speed_t)-1; 1027 tp->t_ospeedwat = (speed_t)-1; 1028 flags = 0; 1029 flags |= SET_RTS; 1030 flags |= SET_DTR; 1031 rp->rp_channel.TxControl[3] = 1032 ((rp->rp_channel.TxControl[3] 1033 & ~(SET_RTS | SET_DTR)) | flags); 1034 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1035 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1036 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1037 sDisRxStatusMode(&rp->rp_channel); 1038 sFlushRxFIFO(&rp->rp_channel); 1039 sFlushTxFIFO(&rp->rp_channel); 1040 1041 sEnInterrupts(&rp->rp_channel, 1042 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 1043 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1044 1045 sDisRxStatusMode(&rp->rp_channel); 1046 sClrTxXOFF(&rp->rp_channel); 1047 1048/* sDisRTSFlowCtl(&rp->rp_channel); 1049 sDisCTSFlowCtl(&rp->rp_channel); 1050*/ 1051 sDisTxSoftFlowCtl(&rp->rp_channel); 1052 1053 sStartRxProcessor(&rp->rp_channel); 1054 1055 sEnRxFIFO(&rp->rp_channel); 1056 sEnTransmit(&rp->rp_channel); 1057 1058/* sSetDTR(&rp->rp_channel); 1059 sSetRTS(&rp->rp_channel); 1060*/ 1061 1062 ++rp->wopeners; 1063 error = rpparam(tp, &tp->t_termios); 1064 --rp->wopeners; 1065 if(error != 0) { 1066 splx(oldspl); 1067 return(error); 1068 } 1069 1070 rp_num_ports_open++; 1071 1072 IntMask = sGetChanIntID(&rp->rp_channel); 1073 IntMask = IntMask & rp->rp_intmask; 1074 ChanStatus = sGetChanStatus(&rp->rp_channel); 1075 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { 1076 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { 1077 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 1078 } 1079 } 1080 1081 if(rp_num_ports_open == 1) 1082 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1083 1084 } 1085 1086 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 1087 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { 1088 ++rp->wopeners; 1089 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, 1090 "rpdcd", 0); 1091 --rp->wopeners; 1092 if(error != 0) 1093 goto out; 1094 goto open_top; 1095 } 1096 error = (*linesw[tp->t_line].l_open)(dev, tp); 1097 1098 rp_disc_optim(tp, &tp->t_termios); 1099 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) 1100 rp->active_out = TRUE; 1101 1102/* if(rp_num_ports_open == 1) 1103 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1104*/ 1105out: 1106 splx(oldspl); 1107 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { 1108 rphardclose(rp); 1109 } 1110out2: 1111 if (error == 0) 1112 device_busy(rp->rp_ctlp->dev); 1113 return(error); 1114} 1115 1116int 1117rpclose(dev, flag, mode, p) 1118 dev_t dev; 1119 int flag, mode; 1120 struct proc *p; 1121{ 1122 int oldspl, unit, mynor, umynor, port; /* SG */ 1123 struct rp_port *rp; 1124 struct tty *tp; 1125 CHANNEL_t *cp; 1126 1127 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1128 port = (minor(dev) & 0x1f); /* SG */ 1129 mynor = (port + umynor); /* SG */ 1130 unit = minor_to_unit[mynor]; /* SG */ 1131 1132 if(IS_CONTROL(dev)) 1133 return(0); 1134 rp = rp_addr(unit) + port; 1135 cp = &rp->rp_channel; 1136 tp = rp->rp_tty; 1137 1138 oldspl = spltty(); 1139 (*linesw[tp->t_line].l_close)(tp, flag); 1140 rp_disc_optim(tp, &tp->t_termios); 1141 rpstop(tp, FREAD | FWRITE); 1142 rphardclose(rp); 1143 1144 tp->t_state &= ~TS_BUSY; 1145 ttyclose(tp); 1146 1147 splx(oldspl); 1148 1149 device_unbusy(rp->rp_ctlp->dev); 1150 1151 return(0); 1152} 1153 1154static void 1155rphardclose(struct rp_port *rp) 1156{ 1157 int mynor; 1158 struct tty *tp; 1159 CHANNEL_t *cp; 1160 1161 cp = &rp->rp_channel; 1162 tp = rp->rp_tty; 1163 mynor = MINOR_MAGIC(tp->t_dev); 1164 1165 sFlushRxFIFO(cp); 1166 sFlushTxFIFO(cp); 1167 sDisTransmit(cp); 1168 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 1169 sDisRTSFlowCtl(cp); 1170 sDisCTSFlowCtl(cp); 1171 sDisTxSoftFlowCtl(cp); 1172 sClrTxXOFF(cp); 1173 1174 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { 1175 sClrDTR(cp); 1176 } 1177 if(IS_CALLOUT(tp->t_dev)) { 1178 sClrDTR(cp); 1179 } 1180 if(rp->dtr_wait != 0) { 1181 timeout(rpdtrwakeup, rp, rp->dtr_wait); 1182 rp->state |= ~SET_DTR; 1183 } 1184 1185 rp->active_out = FALSE; 1186 wakeup(&rp->active_out); 1187 wakeup(TSA_CARR_ON(tp)); 1188} 1189 1190static 1191int 1192rpwrite(dev, uio, flag) 1193 dev_t dev; 1194 struct uio *uio; 1195 int flag; 1196{ 1197 struct rp_port *rp; 1198 struct tty *tp; 1199 int unit, mynor, port, umynor, error = 0; /* SG */ 1200 1201 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1202 port = (minor(dev) & 0x1f); /* SG */ 1203 mynor = (port + umynor); /* SG */ 1204 unit = minor_to_unit[mynor]; /* SG */ 1205 1206 if(IS_CONTROL(dev)) 1207 return(ENODEV); 1208 rp = rp_addr(unit) + port; 1209 tp = rp->rp_tty; 1210 while(rp->rp_disable_writes) { 1211 rp->rp_waiting = 1; 1212 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0); 1213 if (error) 1214 return(error); 1215 } 1216 1217 error = (*linesw[tp->t_line].l_write)(tp, uio, flag); 1218 return error; 1219} 1220 1221static void 1222rpdtrwakeup(void *chan) 1223{ 1224 struct rp_port *rp; 1225 1226 rp = (struct rp_port *)chan; 1227 rp->state &= SET_DTR; 1228 wakeup(&rp->dtr_wait); 1229} 1230 1231int 1232rpioctl(dev, cmd, data, flag, p) 1233 dev_t dev; 1234 u_long cmd; 1235 caddr_t data; 1236 int flag; 1237 struct proc *p; 1238{ 1239 struct rp_port *rp; 1240 CHANNEL_t *cp; 1241 struct tty *tp; 1242 int unit, mynor, port, umynor; /* SG */ 1243 int oldspl; 1244 int error = 0; 1245 int arg, flags, result, ChanStatus; 1246 struct termios *t; 1247 1248 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1249 port = (minor(dev) & 0x1f); /* SG */ 1250 mynor = (port + umynor); /* SG */ 1251 unit = minor_to_unit[mynor]; 1252 rp = rp_addr(unit) + port; 1253 1254 if(IS_CONTROL(dev)) { 1255 struct termios *ct; 1256 1257 switch (IS_CONTROL(dev)) { 1258 case CONTROL_INIT_STATE: 1259 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in; 1260 break; 1261 case CONTROL_LOCK_STATE: 1262 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in; 1263 break; 1264 default: 1265 return(ENODEV); /* /dev/nodev */ 1266 } 1267 switch (cmd) { 1268 case TIOCSETA: 1269 error = suser(p); 1270 if(error != 0) 1271 return(error); 1272 *ct = *(struct termios *)data; 1273 return(0); 1274 case TIOCGETA: 1275 *(struct termios *)data = *ct; 1276 return(0); 1277 case TIOCGETD: 1278 *(int *)data = TTYDISC; 1279 return(0); 1280 case TIOCGWINSZ: 1281 bzero(data, sizeof(struct winsize)); 1282 return(0); 1283 default: 1284 return(ENOTTY); 1285 } 1286 } 1287 1288 tp = rp->rp_tty; 1289 cp = &rp->rp_channel; 1290 1291#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1292 term = tp->t_termios; 1293 oldcmd = cmd; 1294 error = ttsetcompat(tp, &cmd, data, &term); 1295 if(error != 0) 1296 return(error); 1297 if(cmd != oldcmd) { 1298 data = (caddr_t)&term; 1299 } 1300#endif 1301 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) { 1302 int cc; 1303 struct termios *dt = (struct termios *)data; 1304 struct termios *lt = IS_CALLOUT(dev) 1305 ? &rp->lt_out : &rp->lt_in; 1306 1307 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1308 | (dt->c_iflag & ~lt->c_iflag); 1309 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1310 | (dt->c_oflag & ~lt->c_oflag); 1311 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1312 | (dt->c_cflag & ~lt->c_cflag); 1313 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1314 | (dt->c_lflag & ~lt->c_lflag); 1315 for(cc = 0; cc < NCCS; ++cc) 1316 if(lt->c_cc[cc] != 0) 1317 dt->c_cc[cc] = tp->t_cc[cc]; 1318 if(lt->c_ispeed != 0) 1319 dt->c_ispeed = tp->t_ispeed; 1320 if(lt->c_ospeed != 0) 1321 dt->c_ospeed = tp->t_ospeed; 1322 } 1323 1324 t = &tp->t_termios; 1325 1326 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1327 if(error != ENOIOCTL) { 1328 return(error); 1329 } 1330 oldspl = spltty(); 1331 1332 flags = rp->rp_channel.TxControl[3]; 1333 1334 error = ttioctl(tp, cmd, data, flag); 1335 flags = rp->rp_channel.TxControl[3]; 1336 rp_disc_optim(tp, &tp->t_termios); 1337 if(error != ENOIOCTL) { 1338 splx(oldspl); 1339 return(error); 1340 } 1341 switch(cmd) { 1342 case TIOCSBRK: 1343 sSendBreak(&rp->rp_channel); 1344 break; 1345 1346 case TIOCCBRK: 1347 sClrBreak(&rp->rp_channel); 1348 break; 1349 1350 case TIOCSDTR: 1351 sSetDTR(&rp->rp_channel); 1352 sSetRTS(&rp->rp_channel); 1353 break; 1354 1355 case TIOCCDTR: 1356 sClrDTR(&rp->rp_channel); 1357 break; 1358 1359 case TIOCMSET: 1360 arg = *(int *) data; 1361 flags = 0; 1362 if(arg & TIOCM_RTS) 1363 flags |= SET_RTS; 1364 if(arg & TIOCM_DTR) 1365 flags |= SET_DTR; 1366 rp->rp_channel.TxControl[3] = 1367 ((rp->rp_channel.TxControl[3] 1368 & ~(SET_RTS | SET_DTR)) | flags); 1369 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1370 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1371 break; 1372 case TIOCMBIS: 1373 arg = *(int *) data; 1374 flags = 0; 1375 if(arg & TIOCM_RTS) 1376 flags |= SET_RTS; 1377 if(arg & TIOCM_DTR) 1378 flags |= SET_DTR; 1379 rp->rp_channel.TxControl[3] |= flags; 1380 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1381 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1382 break; 1383 case TIOCMBIC: 1384 arg = *(int *) data; 1385 flags = 0; 1386 if(arg & TIOCM_RTS) 1387 flags |= SET_RTS; 1388 if(arg & TIOCM_DTR) 1389 flags |= SET_DTR; 1390 rp->rp_channel.TxControl[3] &= ~flags; 1391 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1392 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1393 break; 1394 1395 1396 case TIOCMGET: 1397 ChanStatus = sGetChanStatusLo(&rp->rp_channel); 1398 flags = rp->rp_channel.TxControl[3]; 1399 result = TIOCM_LE; /* always on while open for some reason */ 1400 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0) 1401 | ((flags & SET_RTS) ? TIOCM_RTS : 0) 1402 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) 1403 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) 1404 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0)); 1405 1406 if(rp->rp_channel.RxControl[2] & RTSFC_EN) 1407 { 1408 result |= TIOCM_RTS; 1409 } 1410 1411 *(int *)data = result; 1412 break; 1413 case TIOCMSDTRWAIT: 1414 error = suser(p); 1415 if(error != 0) { 1416 splx(oldspl); 1417 return(error); 1418 } 1419 rp->dtr_wait = *(int *)data * hz/100; 1420 break; 1421 case TIOCMGDTRWAIT: 1422 *(int *)data = rp->dtr_wait * 100/hz; 1423 break; 1424 default: 1425 splx(oldspl); 1426 return ENOTTY; 1427 } 1428 splx(oldspl); 1429 return(0); 1430} 1431 1432static struct speedtab baud_table[] = { 1433 {B0, 0}, {B50, BRD50}, {B75, BRD75}, 1434 {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, 1435 {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, 1436 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, 1437 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, 1438 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, 1439 {B57600, BRD57600}, {B76800, BRD76800}, 1440 {B115200, BRD115200}, {B230400, BRD230400}, 1441 {-1, -1} 1442}; 1443 1444static int 1445rpparam(tp, t) 1446 struct tty *tp; 1447 struct termios *t; 1448{ 1449 struct rp_port *rp; 1450 CHANNEL_t *cp; 1451 int unit, mynor, port, umynor; /* SG */ 1452 int oldspl, cflag, iflag, oflag, lflag; 1453 int ospeed; 1454#ifdef RPCLOCAL 1455 int devshift; 1456#endif 1457 1458 1459 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 1460 port = (minor(tp->t_dev) & 0x1f); /* SG */ 1461 mynor = (port + umynor); /* SG */ 1462 1463 unit = minor_to_unit[mynor]; 1464 rp = rp_addr(unit) + port; 1465 cp = &rp->rp_channel; 1466 oldspl = spltty(); 1467 1468 cflag = t->c_cflag; 1469#ifdef RPCLOCAL 1470 devshift = umynor / 32; 1471 devshift = 1 << devshift; 1472 if ( devshift & RPCLOCAL ) { 1473 cflag |= CLOCAL; 1474 } 1475#endif 1476 iflag = t->c_iflag; 1477 oflag = t->c_oflag; 1478 lflag = t->c_lflag; 1479 1480 ospeed = ttspeedtab(t->c_ispeed, baud_table); 1481 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) 1482 return(EINVAL); 1483 1484 tp->t_ispeed = t->c_ispeed; 1485 tp->t_ospeed = t->c_ospeed; 1486 tp->t_cflag = cflag; 1487 tp->t_iflag = iflag; 1488 tp->t_oflag = oflag; 1489 tp->t_lflag = lflag; 1490 1491 if(t->c_ospeed == 0) { 1492 sClrDTR(cp); 1493 return(0); 1494 } 1495 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; 1496 1497 /* Set baud rate ----- we only pay attention to ispeed */ 1498 sSetDTR(cp); 1499 sSetRTS(cp); 1500 sSetBaud(cp, ospeed); 1501 1502 if(cflag & CSTOPB) { 1503 sSetStop2(cp); 1504 } else { 1505 sSetStop1(cp); 1506 } 1507 1508 if(cflag & PARENB) { 1509 sEnParity(cp); 1510 if(cflag & PARODD) { 1511 sSetOddParity(cp); 1512 } else { 1513 sSetEvenParity(cp); 1514 } 1515 } 1516 else { 1517 sDisParity(cp); 1518 } 1519 if((cflag & CSIZE) == CS8) { 1520 sSetData8(cp); 1521 rp->rp_imask = 0xFF; 1522 } else { 1523 sSetData7(cp); 1524 rp->rp_imask = 0x7F; 1525 } 1526 1527 if(iflag & ISTRIP) { 1528 rp->rp_imask &= 0x7F; 1529 } 1530 1531 if(cflag & CLOCAL) { 1532 rp->rp_intmask &= ~DELTA_CD; 1533 } else { 1534 rp->rp_intmask |= DELTA_CD; 1535 } 1536 1537 /* Put flow control stuff here */ 1538 1539 if(cflag & CCTS_OFLOW) { 1540 sEnCTSFlowCtl(cp); 1541 } else { 1542 sDisCTSFlowCtl(cp); 1543 } 1544 1545 if(cflag & CRTS_IFLOW) { 1546 rp->rp_rts_iflow = 1; 1547 } else { 1548 rp->rp_rts_iflow = 0; 1549 } 1550 1551 if(cflag & CRTS_IFLOW) { 1552 sEnRTSFlowCtl(cp); 1553 } else { 1554 sDisRTSFlowCtl(cp); 1555 } 1556 rp_disc_optim(tp, t); 1557 1558 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { 1559 tp->t_state |= TS_CARR_ON; 1560 wakeup(TSA_CARR_ON(tp)); 1561 } 1562 1563/* tp->t_state |= TS_CAN_BYPASS_L_RINT; 1564 flags = rp->rp_channel.TxControl[3]; 1565 if(flags & SET_DTR) 1566 else 1567 if(flags & SET_RTS) 1568 else 1569*/ 1570 splx(oldspl); 1571 1572 return(0); 1573} 1574 1575static void 1576rp_disc_optim(tp, t) 1577struct tty *tp; 1578struct termios *t; 1579{ 1580 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 1581 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 1582 &&(!(t->c_iflag & PARMRK) 1583 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 1584 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 1585 && linesw[tp->t_line].l_rint == ttyinput) 1586 tp->t_state |= TS_CAN_BYPASS_L_RINT; 1587 else 1588 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 1589} 1590 1591static void 1592rpstart(tp) 1593 struct tty *tp; 1594{ 1595 struct rp_port *rp; 1596 CHANNEL_t *cp; 1597 struct clist *qp; 1598 int unit, mynor, port, umynor; /* SG */ 1599 char flags; 1600 int spl, xmit_fifo_room; 1601 int count, wcount; 1602 1603 1604 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 1605 port = (minor(tp->t_dev) & 0x1f); /* SG */ 1606 mynor = (port + umynor); /* SG */ 1607 unit = minor_to_unit[mynor]; 1608 rp = rp_addr(unit) + port; 1609 cp = &rp->rp_channel; 1610 flags = rp->rp_channel.TxControl[3]; 1611 spl = spltty(); 1612 1613 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1614 ttwwakeup(tp); 1615 splx(spl); 1616 return; 1617 } 1618 if(rp->rp_xmit_stopped) { 1619 sEnTransmit(cp); 1620 rp->rp_xmit_stopped = 0; 1621 } 1622 count = sGetTxCnt(cp); 1623 1624 if(tp->t_outq.c_cc == 0) { 1625 if((tp->t_state & TS_BUSY) && (count == 0)) { 1626 tp->t_state &= ~TS_BUSY; 1627 } 1628 ttwwakeup(tp); 1629 splx(spl); 1630 return; 1631 } 1632 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); 1633 qp = &tp->t_outq; 1634 if(xmit_fifo_room > 0 && qp->c_cc > 0) { 1635 tp->t_state |= TS_BUSY; 1636 count = q_to_b( qp, rp->TxBuf, xmit_fifo_room ); 1637 wcount = count >> 1; 1638 if ( wcount ) { 1639 rp_writemultich2(cp, sGetTxRxDataIO(cp), (u_int16_t *)rp->TxBuf, wcount); 1640 } 1641 if ( count & 1 ) { 1642 rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); 1643 } 1644 } 1645 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; 1646 1647 ttwwakeup(tp); 1648 splx(spl); 1649} 1650 1651static 1652void 1653rpstop(tp, flag) 1654 register struct tty *tp; 1655 int flag; 1656{ 1657 struct rp_port *rp; 1658 CHANNEL_t *cp; 1659 int unit, mynor, port, umynor; /* SG */ 1660 int spl; 1661 1662 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 1663 port = (minor(tp->t_dev) & 0x1f); /* SG */ 1664 mynor = (port + umynor); /* SG */ 1665 unit = minor_to_unit[mynor]; 1666 rp = rp_addr(unit) + port; 1667 cp = &rp->rp_channel; 1668 1669 spl = spltty(); 1670 1671 if(tp->t_state & TS_BUSY) { 1672 if((tp->t_state&TS_TTSTOP) == 0) { 1673 sFlushTxFIFO(cp); 1674 } else { 1675 if(rp->rp_xmit_stopped == 0) { 1676 sDisTransmit(cp); 1677 rp->rp_xmit_stopped = 1; 1678 } 1679 } 1680 } 1681 splx(spl); 1682 rpstart(tp); 1683} 1684