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