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