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; 568struct callout_handle rp_callout_handle; 569 570static d_open_t rpopen; 571static d_close_t rpclose; 572static d_write_t rpwrite; 573static d_ioctl_t rpioctl; 574 575struct cdevsw rp_cdevsw = { 576 .d_version = D_VERSION, 577 .d_open = rpopen, 578 .d_close = rpclose, 579 .d_write = rpwrite, 580 .d_ioctl = rpioctl, 581 .d_name = "rp", 582 .d_flags = D_TTY | D_NEEDGIANT, 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 *); 620 621static void rp_do_receive(struct rp_port *rp, struct tty *tp, 622 CHANNEL_t *cp, unsigned int ChanStatus) 623{ 624 int spl; 625 unsigned int CharNStat; 626 int ToRecv, wRecv, ch, ttynocopy; 627 628 ToRecv = sGetRxCnt(cp); 629 if(ToRecv == 0) 630 return; 631 632/* If status indicates there are errored characters in the 633 FIFO, then enter status mode (a word in FIFO holds 634 characters and status) 635*/ 636 637 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 638 if(!(ChanStatus & STATMODE)) { 639 ChanStatus |= STATMODE; 640 sEnRxStatusMode(cp); 641 } 642 } 643/* 644 if we previously entered status mode then read down the 645 FIFO one word at a time, pulling apart the character and 646 the status. Update error counters depending on status. 647*/ 648 if(ChanStatus & STATMODE) { 649 while(ToRecv) { 650 if(tp->t_state & TS_TBLOCK) { 651 break; 652 } 653 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); 654 ch = CharNStat & 0xff; 655 656 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 657 ch |= TTY_FE; 658 else if (CharNStat & STMPARITYH) 659 ch |= TTY_PE; 660 else if (CharNStat & STMRCVROVRH) 661 rp->rp_overflows++; 662 663 ttyld_rint(tp, ch); 664 ToRecv--; 665 } 666/* 667 After emtying FIFO in status mode, turn off status mode 668*/ 669 670 if(sGetRxCnt(cp) == 0) { 671 sDisRxStatusMode(cp); 672 } 673 } else { 674 /* 675 * Avoid the grotesquely inefficient lineswitch routine 676 * (ttyinput) in "raw" mode. It usually takes about 450 677 * instructions (that's without canonical processing or echo!). 678 * slinput is reasonably fast (usually 40 instructions plus 679 * call overhead). 680 */ 681 ToRecv = sGetRxCnt(cp); 682 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { 683 if ( ToRecv > RXFIFO_SIZE ) { 684 ToRecv = RXFIFO_SIZE; 685 } 686 wRecv = ToRecv >> 1; 687 if ( wRecv ) { 688 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv); 689 } 690 if ( ToRecv & 1 ) { 691 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 692 } 693 tk_nin += ToRecv; 694 tk_rawcc += ToRecv; 695 tp->t_rawcc += ToRecv; 696 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq); 697 ttwakeup(tp); 698 } else { 699 while (ToRecv) { 700 if(tp->t_state & TS_TBLOCK) { 701 break; 702 } 703 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 704 spl = spltty(); 705 ttyld_rint(tp, ch); 706 splx(spl); 707 ToRecv--; 708 } 709 } 710 } 711} 712 713static void rp_handle_port(struct rp_port *rp) 714{ 715 CHANNEL_t *cp; 716 struct tty *tp; 717 unsigned int IntMask, ChanStatus; 718 719 if(!rp) 720 return; 721 722 cp = &rp->rp_channel; 723 tp = rp->rp_tty; 724 IntMask = sGetChanIntID(cp); 725 IntMask = IntMask & rp->rp_intmask; 726 ChanStatus = sGetChanStatus(cp); 727 if(IntMask & RXF_TRIG) 728 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 729 rp_do_receive(rp, tp, cp, ChanStatus); 730 } 731 if(IntMask & DELTA_CD) { 732 if(ChanStatus & CD_ACT) { 733 if(!(tp->t_state & TS_CARR_ON) ) { 734 (void)ttyld_modem(tp, 1); 735 } 736 } else { 737 if((tp->t_state & TS_CARR_ON)) { 738 (void)ttyld_modem(tp, 0); 739 if(ttyld_modem(tp, 0) == 0) { 740 rphardclose(rp); 741 } 742 } 743 } 744 } 745/* oldcts = rp->rp_cts; 746 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 747 if(oldcts != rp->rp_cts) { 748 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 749 } 750*/ 751} 752 753static void rp_do_poll(void *not_used) 754{ 755 CONTROLLER_t *ctl; 756 struct rp_port *rp; 757 struct tty *tp; 758 int unit, aiop, ch, line, count; 759 unsigned char CtlMask, AiopMask; 760 761 for(unit = 0; unit < rp_ndevs; unit++) { 762 rp = rp_addr(unit); 763 ctl = rp->rp_ctlp; 764 CtlMask = ctl->ctlmask(ctl); 765 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 766 if(CtlMask & 1) { 767 AiopMask = sGetAiopIntStatus(ctl, aiop); 768 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 769 if(AiopMask & 1) { 770 line = (unit << 5) | (aiop << 3) | ch; 771 rp = rp_table(line); 772 rp_handle_port(rp); 773 } 774 } 775 } 776 } 777 778 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 779 line++, rp++) { 780 tp = rp->rp_tty; 781 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 782 count = sGetTxCnt(&rp->rp_channel); 783 if(count == 0) 784 tp->t_state &= ~(TS_BUSY); 785 if(!(tp->t_state & TS_TTSTOP) && 786 (count <= rp->rp_restart)) { 787 ttyld_start(tp); 788 } 789 } 790 } 791 } 792 if(rp_num_ports_open) 793 rp_callout_handle = timeout(rp_do_poll, 794 (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 cdev **dev_nodes; 807 808 unit = device_get_unit(ctlp->dev); 809 810 printf("RocketPort%d (Version %s) %d ports.\n", unit, 811 RocketPortVersion, num_ports); 812 rp_num_ports[unit] = num_ports; 813 callout_handle_init(&rp_callout_handle); 814 815 ctlp->rp = rp = (struct rp_port *) 816 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); 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 oldspl = spltty(); 829 rp_addr(unit) = rp; 830 splx(oldspl); 831 832 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO); 833 if(ctlp->dev_nodes == NULL) { 834 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n"); 835 retval = ENOMEM; 836 goto nogo; 837 } 838 839 for (i = 0 ; i < rp_num_ports[unit] ; i++) { 840 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i, 841 UID_ROOT, GID_WHEEL, 0666, "ttyR%c", 842 i <= 9 ? '0' + i : 'a' + i - 10); 843 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20, 844 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c", 845 i <= 9 ? '0' + i : 'a' + i - 10); 846 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40, 847 UID_ROOT, GID_WHEEL, 0666, "ttylR%c", 848 i <= 9 ? '0' + i : 'a' + i - 10); 849 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80, 850 UID_ROOT, GID_WHEEL, 0666, "cuaR%c", 851 i <= 9 ? '0' + i : 'a' + i - 10); 852 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0, 853 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c", 854 i <= 9 ? '0' + i : 'a' + i - 10); 855 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0, 856 UID_ROOT, GID_WHEEL, 0666, "cualR%c", 857 i <= 9 ? '0' + i : 'a' + i - 10); 858 } 859 860 port = 0; 861 for(aiop=0; aiop < num_aiops; aiop++) { 862 num_chan = sGetAiopNumChan(ctlp, aiop); 863 for(chan=0; chan < num_chan; chan++, port++, rp++) { 864 rp->rp_tty = ttymalloc(NULL); 865 rp->rp_port = port; 866 rp->rp_ctlp = ctlp; 867 rp->rp_unit = unit; 868 rp->rp_chan = chan; 869 rp->rp_aiop = aiop; 870 871 rp->rp_tty->t_line = 0; 872 /* tty->t_termios = deftermios; 873 */ 874 rp->dtr_wait = 3 * hz; 875 rp->it_in.c_iflag = 0; 876 rp->it_in.c_oflag = 0; 877 rp->it_in.c_cflag = TTYDEF_CFLAG; 878 rp->it_in.c_lflag = 0; 879 termioschars(&rp->it_in); 880 /* termioschars(&tty->t_termios); 881 */ 882 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 883 rp->it_out = rp->it_in; 884 885 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 886 DELTA_CD | DELTA_CTS | DELTA_DSR; 887#if notdef 888 ChanStatus = sGetChanStatus(&rp->rp_channel); 889#endif /* notdef */ 890 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 891 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", 892 unit, aiop, chan); 893 retval = ENXIO; 894 goto nogo; 895 } 896 ChanStatus = sGetChanStatus(&rp->rp_channel); 897 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 898 line = (unit << 5) | (aiop << 3) | chan; 899 rp_table(line) = rp; 900 } 901 } 902 903 rp_ndevs++; 904 return (0); 905 906nogo: 907 rp_releaseresource(ctlp); 908 909 return (retval); 910} 911 912void 913rp_releaseresource(CONTROLLER_t *ctlp) 914{ 915 int i, s, unit; 916 struct rp_port *rp; 917 918 919 unit = device_get_unit(ctlp->dev); 920 if (rp_addr(unit) != NULL) { 921 for (i = 0; i < rp_num_ports[unit]; i++) { 922 rp = rp_addr(unit) + i; 923 s = ttyrel(rp->rp_tty); 924 if (s) { 925 printf("Detaching with active tty (%d refs)!\n", s); 926 } 927 } 928 } 929 930 if (ctlp->rp != NULL) { 931 s = spltty(); 932 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) 933 if (p_rp_addr[i] == ctlp->rp) 934 p_rp_addr[i] = NULL; 935 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) 936 if (p_rp_table[i] == ctlp->rp) 937 p_rp_table[i] = NULL; 938 splx(s); 939 free(ctlp->rp, M_DEVBUF); 940 ctlp->rp = NULL; 941 } 942 if (ctlp->dev != NULL) { 943 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++) 944 destroy_dev(ctlp->dev_nodes[i]); 945 free(ctlp->dev_nodes, M_DEVBUF); 946 ctlp->dev = NULL; 947 } 948} 949 950void 951rp_untimeout(void) 952{ 953 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle); 954} 955static int 956rpopen(dev, flag, mode, td) 957 struct cdev *dev; 958 int flag, mode; 959 struct thread *td; 960{ 961 struct rp_port *rp; 962 int unit, port, mynor, umynor, flags; /* SG */ 963 struct tty *tp; 964 int oldspl, error; 965 unsigned int IntMask, ChanStatus; 966 967 968 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 969 port = (minor(dev) & 0x1f); /* SG */ 970 mynor = (port + umynor); /* SG */ 971 unit = minor_to_unit[mynor]; 972 if (rp_addr(unit) == NULL) 973 return (ENXIO); 974 if(IS_CONTROL(dev)) 975 return(0); 976 rp = rp_addr(unit) + port; 977/* rp->rp_tty = &rp_tty[rp->rp_port]; 978*/ 979 tp = rp->rp_tty; 980 dev->si_tty = tp; 981 982 oldspl = spltty(); 983 984open_top: 985 while(rp->state & ~SET_DTR) { 986 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0); 987 if(error != 0) 988 goto out; 989 } 990 991 if(tp->t_state & TS_ISOPEN) { 992 if(IS_CALLOUT(dev)) { 993 if(!rp->active_out) { 994 error = EBUSY; 995 goto out; 996 } 997 } else { 998 if(rp->active_out) { 999 if(flag & O_NONBLOCK) { 1000 error = EBUSY; 1001 goto out; 1002 } 1003 error = tsleep(&rp->active_out, 1004 TTIPRI | PCATCH, "rpbi", 0); 1005 if(error != 0) 1006 goto out; 1007 goto open_top; 1008 } 1009 } 1010 if(tp->t_state & TS_XCLUDE && suser(td) != 0) { 1011 splx(oldspl); 1012 error = EBUSY; 1013 goto out2; 1014 } 1015 } 1016 else { 1017 tp->t_dev = dev; 1018 tp->t_param = rpparam; 1019 tp->t_oproc = rpstart; 1020 tp->t_stop = rpstop; 1021 tp->t_line = 0; 1022 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; 1023 tp->t_ififosize = 512; 1024 tp->t_ispeedwat = (speed_t)-1; 1025 tp->t_ospeedwat = (speed_t)-1; 1026 flags = 0; 1027 flags |= SET_RTS; 1028 flags |= SET_DTR; 1029 rp->rp_channel.TxControl[3] = 1030 ((rp->rp_channel.TxControl[3] 1031 & ~(SET_RTS | SET_DTR)) | flags); 1032 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1033 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1034 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1035 sDisRxStatusMode(&rp->rp_channel); 1036 sFlushRxFIFO(&rp->rp_channel); 1037 sFlushTxFIFO(&rp->rp_channel); 1038 1039 sEnInterrupts(&rp->rp_channel, 1040 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 1041 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1042 1043 sDisRxStatusMode(&rp->rp_channel); 1044 sClrTxXOFF(&rp->rp_channel); 1045 1046/* sDisRTSFlowCtl(&rp->rp_channel); 1047 sDisCTSFlowCtl(&rp->rp_channel); 1048*/ 1049 sDisTxSoftFlowCtl(&rp->rp_channel); 1050 1051 sStartRxProcessor(&rp->rp_channel); 1052 1053 sEnRxFIFO(&rp->rp_channel); 1054 sEnTransmit(&rp->rp_channel); 1055 1056/* sSetDTR(&rp->rp_channel); 1057 sSetRTS(&rp->rp_channel); 1058*/ 1059 1060 ++rp->wopeners; 1061 error = rpparam(tp, &tp->t_termios); 1062 --rp->wopeners; 1063 if(error != 0) { 1064 splx(oldspl); 1065 return(error); 1066 } 1067 1068 rp_num_ports_open++; 1069 1070 IntMask = sGetChanIntID(&rp->rp_channel); 1071 IntMask = IntMask & rp->rp_intmask; 1072 ChanStatus = sGetChanStatus(&rp->rp_channel); 1073 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { 1074 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { 1075 (void)ttyld_modem(tp, 1); 1076 } 1077 } 1078 1079 if(rp_num_ports_open == 1) 1080 rp_callout_handle = timeout(rp_do_poll, 1081 (void *)NULL, POLL_INTERVAL); 1082 } 1083 1084 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 1085 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { 1086 ++rp->wopeners; 1087 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, 1088 "rpdcd", 0); 1089 --rp->wopeners; 1090 if(error != 0) 1091 goto out; 1092 goto open_top; 1093 } 1094 error = ttyld_open(tp, dev); 1095 1096 ttyldoptim(tp); 1097 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) 1098 rp->active_out = TRUE; 1099 1100/* if(rp_num_ports_open == 1) 1101 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1102*/ 1103out: 1104 splx(oldspl); 1105 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { 1106 rphardclose(rp); 1107 } 1108out2: 1109 if (error == 0) 1110 device_busy(rp->rp_ctlp->dev); 1111 return(error); 1112} 1113 1114static int 1115rpclose(dev, flag, mode, td) 1116 struct cdev *dev; 1117 int flag, mode; 1118 struct thread *td; 1119{ 1120 int oldspl, unit, mynor, umynor, port; /* SG */ 1121 struct rp_port *rp; 1122 struct tty *tp; 1123 CHANNEL_t *cp; 1124 1125 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1126 port = (minor(dev) & 0x1f); /* SG */ 1127 mynor = (port + umynor); /* SG */ 1128 unit = minor_to_unit[mynor]; /* SG */ 1129 1130 if(IS_CONTROL(dev)) 1131 return(0); 1132 rp = rp_addr(unit) + port; 1133 cp = &rp->rp_channel; 1134 tp = rp->rp_tty; 1135 1136 oldspl = spltty(); 1137 ttyld_close(tp, flag); 1138 ttyldoptim(tp); 1139 rphardclose(rp); 1140 1141 tp->t_state &= ~TS_BUSY; 1142 ttyclose(tp); 1143 1144 splx(oldspl); 1145 1146 device_unbusy(rp->rp_ctlp->dev); 1147 1148 return(0); 1149} 1150 1151static void 1152rphardclose(struct rp_port *rp) 1153{ 1154 int mynor; 1155 struct tty *tp; 1156 CHANNEL_t *cp; 1157 1158 cp = &rp->rp_channel; 1159 tp = rp->rp_tty; 1160 mynor = MINOR_MAGIC(tp->t_dev); 1161 1162 sFlushRxFIFO(cp); 1163 sFlushTxFIFO(cp); 1164 sDisTransmit(cp); 1165 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 1166 sDisRTSFlowCtl(cp); 1167 sDisCTSFlowCtl(cp); 1168 sDisTxSoftFlowCtl(cp); 1169 sClrTxXOFF(cp); 1170 1171 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { 1172 sClrDTR(cp); 1173 } 1174 if(IS_CALLOUT(tp->t_dev)) { 1175 sClrDTR(cp); 1176 } 1177 if(rp->dtr_wait != 0) { 1178 timeout(rpdtrwakeup, rp, rp->dtr_wait); 1179 rp->state |= ~SET_DTR; 1180 } 1181 1182 rp->active_out = FALSE; 1183 wakeup(&rp->active_out); 1184 wakeup(TSA_CARR_ON(tp)); 1185} 1186 1187static 1188int 1189rpwrite(dev, uio, flag) 1190 struct cdev *dev; 1191 struct uio *uio; 1192 int flag; 1193{ 1194 struct rp_port *rp; 1195 struct tty *tp; 1196 int unit, mynor, port, umynor, error = 0; /* SG */ 1197 1198 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1199 port = (minor(dev) & 0x1f); /* SG */ 1200 mynor = (port + umynor); /* SG */ 1201 unit = minor_to_unit[mynor]; /* SG */ 1202 1203 if(IS_CONTROL(dev)) 1204 return(ENODEV); 1205 rp = rp_addr(unit) + port; 1206 tp = rp->rp_tty; 1207 while(rp->rp_disable_writes) { 1208 rp->rp_waiting = 1; 1209 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0); 1210 if (error) 1211 return(error); 1212 } 1213 1214 error = ttyld_write(tp, uio, flag); 1215 return error; 1216} 1217 1218static void 1219rpdtrwakeup(void *chan) 1220{ 1221 struct rp_port *rp; 1222 1223 rp = (struct rp_port *)chan; 1224 rp->state &= SET_DTR; 1225 wakeup(&rp->dtr_wait); 1226} 1227 1228static int 1229rpioctl(dev, cmd, data, flag, td) 1230 struct cdev *dev; 1231 u_long cmd; 1232 caddr_t data; 1233 int flag; 1234 struct thread *td; 1235{ 1236 struct rp_port *rp; 1237 CHANNEL_t *cp; 1238 struct tty *tp; 1239 int unit, mynor, port, umynor; /* SG */ 1240 int oldspl; 1241 int error = 0; 1242 int arg, flags, result, ChanStatus; 1243 struct termios *t;
| 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; 568struct callout_handle rp_callout_handle; 569 570static d_open_t rpopen; 571static d_close_t rpclose; 572static d_write_t rpwrite; 573static d_ioctl_t rpioctl; 574 575struct cdevsw rp_cdevsw = { 576 .d_version = D_VERSION, 577 .d_open = rpopen, 578 .d_close = rpclose, 579 .d_write = rpwrite, 580 .d_ioctl = rpioctl, 581 .d_name = "rp", 582 .d_flags = D_TTY | D_NEEDGIANT, 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 *); 620 621static void rp_do_receive(struct rp_port *rp, struct tty *tp, 622 CHANNEL_t *cp, unsigned int ChanStatus) 623{ 624 int spl; 625 unsigned int CharNStat; 626 int ToRecv, wRecv, ch, ttynocopy; 627 628 ToRecv = sGetRxCnt(cp); 629 if(ToRecv == 0) 630 return; 631 632/* If status indicates there are errored characters in the 633 FIFO, then enter status mode (a word in FIFO holds 634 characters and status) 635*/ 636 637 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 638 if(!(ChanStatus & STATMODE)) { 639 ChanStatus |= STATMODE; 640 sEnRxStatusMode(cp); 641 } 642 } 643/* 644 if we previously entered status mode then read down the 645 FIFO one word at a time, pulling apart the character and 646 the status. Update error counters depending on status. 647*/ 648 if(ChanStatus & STATMODE) { 649 while(ToRecv) { 650 if(tp->t_state & TS_TBLOCK) { 651 break; 652 } 653 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); 654 ch = CharNStat & 0xff; 655 656 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 657 ch |= TTY_FE; 658 else if (CharNStat & STMPARITYH) 659 ch |= TTY_PE; 660 else if (CharNStat & STMRCVROVRH) 661 rp->rp_overflows++; 662 663 ttyld_rint(tp, ch); 664 ToRecv--; 665 } 666/* 667 After emtying FIFO in status mode, turn off status mode 668*/ 669 670 if(sGetRxCnt(cp) == 0) { 671 sDisRxStatusMode(cp); 672 } 673 } else { 674 /* 675 * Avoid the grotesquely inefficient lineswitch routine 676 * (ttyinput) in "raw" mode. It usually takes about 450 677 * instructions (that's without canonical processing or echo!). 678 * slinput is reasonably fast (usually 40 instructions plus 679 * call overhead). 680 */ 681 ToRecv = sGetRxCnt(cp); 682 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { 683 if ( ToRecv > RXFIFO_SIZE ) { 684 ToRecv = RXFIFO_SIZE; 685 } 686 wRecv = ToRecv >> 1; 687 if ( wRecv ) { 688 rp_readmultich2(cp,sGetTxRxDataIO(cp),(u_int16_t *)rp->RxBuf,wRecv); 689 } 690 if ( ToRecv & 1 ) { 691 ((unsigned char *)rp->RxBuf)[(ToRecv-1)] = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 692 } 693 tk_nin += ToRecv; 694 tk_rawcc += ToRecv; 695 tp->t_rawcc += ToRecv; 696 ttynocopy = b_to_q((char *)rp->RxBuf, ToRecv, &tp->t_rawq); 697 ttwakeup(tp); 698 } else { 699 while (ToRecv) { 700 if(tp->t_state & TS_TBLOCK) { 701 break; 702 } 703 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 704 spl = spltty(); 705 ttyld_rint(tp, ch); 706 splx(spl); 707 ToRecv--; 708 } 709 } 710 } 711} 712 713static void rp_handle_port(struct rp_port *rp) 714{ 715 CHANNEL_t *cp; 716 struct tty *tp; 717 unsigned int IntMask, ChanStatus; 718 719 if(!rp) 720 return; 721 722 cp = &rp->rp_channel; 723 tp = rp->rp_tty; 724 IntMask = sGetChanIntID(cp); 725 IntMask = IntMask & rp->rp_intmask; 726 ChanStatus = sGetChanStatus(cp); 727 if(IntMask & RXF_TRIG) 728 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 729 rp_do_receive(rp, tp, cp, ChanStatus); 730 } 731 if(IntMask & DELTA_CD) { 732 if(ChanStatus & CD_ACT) { 733 if(!(tp->t_state & TS_CARR_ON) ) { 734 (void)ttyld_modem(tp, 1); 735 } 736 } else { 737 if((tp->t_state & TS_CARR_ON)) { 738 (void)ttyld_modem(tp, 0); 739 if(ttyld_modem(tp, 0) == 0) { 740 rphardclose(rp); 741 } 742 } 743 } 744 } 745/* oldcts = rp->rp_cts; 746 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 747 if(oldcts != rp->rp_cts) { 748 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 749 } 750*/ 751} 752 753static void rp_do_poll(void *not_used) 754{ 755 CONTROLLER_t *ctl; 756 struct rp_port *rp; 757 struct tty *tp; 758 int unit, aiop, ch, line, count; 759 unsigned char CtlMask, AiopMask; 760 761 for(unit = 0; unit < rp_ndevs; unit++) { 762 rp = rp_addr(unit); 763 ctl = rp->rp_ctlp; 764 CtlMask = ctl->ctlmask(ctl); 765 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 766 if(CtlMask & 1) { 767 AiopMask = sGetAiopIntStatus(ctl, aiop); 768 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 769 if(AiopMask & 1) { 770 line = (unit << 5) | (aiop << 3) | ch; 771 rp = rp_table(line); 772 rp_handle_port(rp); 773 } 774 } 775 } 776 } 777 778 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 779 line++, rp++) { 780 tp = rp->rp_tty; 781 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 782 count = sGetTxCnt(&rp->rp_channel); 783 if(count == 0) 784 tp->t_state &= ~(TS_BUSY); 785 if(!(tp->t_state & TS_TTSTOP) && 786 (count <= rp->rp_restart)) { 787 ttyld_start(tp); 788 } 789 } 790 } 791 } 792 if(rp_num_ports_open) 793 rp_callout_handle = timeout(rp_do_poll, 794 (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 cdev **dev_nodes; 807 808 unit = device_get_unit(ctlp->dev); 809 810 printf("RocketPort%d (Version %s) %d ports.\n", unit, 811 RocketPortVersion, num_ports); 812 rp_num_ports[unit] = num_ports; 813 callout_handle_init(&rp_callout_handle); 814 815 ctlp->rp = rp = (struct rp_port *) 816 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); 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 oldspl = spltty(); 829 rp_addr(unit) = rp; 830 splx(oldspl); 831 832 dev_nodes = ctlp->dev_nodes = malloc(sizeof(*(ctlp->dev_nodes)) * rp_num_ports[unit] * 6, M_DEVBUF, M_NOWAIT | M_ZERO); 833 if(ctlp->dev_nodes == NULL) { 834 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc device node structures.\n"); 835 retval = ENOMEM; 836 goto nogo; 837 } 838 839 for (i = 0 ; i < rp_num_ports[unit] ; i++) { 840 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i, 841 UID_ROOT, GID_WHEEL, 0666, "ttyR%c", 842 i <= 9 ? '0' + i : 'a' + i - 10); 843 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x20, 844 UID_ROOT, GID_WHEEL, 0666, "ttyiR%c", 845 i <= 9 ? '0' + i : 'a' + i - 10); 846 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x40, 847 UID_ROOT, GID_WHEEL, 0666, "ttylR%c", 848 i <= 9 ? '0' + i : 'a' + i - 10); 849 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0x80, 850 UID_ROOT, GID_WHEEL, 0666, "cuaR%c", 851 i <= 9 ? '0' + i : 'a' + i - 10); 852 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xa0, 853 UID_ROOT, GID_WHEEL, 0666, "cuaiR%c", 854 i <= 9 ? '0' + i : 'a' + i - 10); 855 *(dev_nodes++) = make_dev(&rp_cdevsw, ((unit + 1) << 16) | i | 0xc0, 856 UID_ROOT, GID_WHEEL, 0666, "cualR%c", 857 i <= 9 ? '0' + i : 'a' + i - 10); 858 } 859 860 port = 0; 861 for(aiop=0; aiop < num_aiops; aiop++) { 862 num_chan = sGetAiopNumChan(ctlp, aiop); 863 for(chan=0; chan < num_chan; chan++, port++, rp++) { 864 rp->rp_tty = ttymalloc(NULL); 865 rp->rp_port = port; 866 rp->rp_ctlp = ctlp; 867 rp->rp_unit = unit; 868 rp->rp_chan = chan; 869 rp->rp_aiop = aiop; 870 871 rp->rp_tty->t_line = 0; 872 /* tty->t_termios = deftermios; 873 */ 874 rp->dtr_wait = 3 * hz; 875 rp->it_in.c_iflag = 0; 876 rp->it_in.c_oflag = 0; 877 rp->it_in.c_cflag = TTYDEF_CFLAG; 878 rp->it_in.c_lflag = 0; 879 termioschars(&rp->it_in); 880 /* termioschars(&tty->t_termios); 881 */ 882 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 883 rp->it_out = rp->it_in; 884 885 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 886 DELTA_CD | DELTA_CTS | DELTA_DSR; 887#if notdef 888 ChanStatus = sGetChanStatus(&rp->rp_channel); 889#endif /* notdef */ 890 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 891 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", 892 unit, aiop, chan); 893 retval = ENXIO; 894 goto nogo; 895 } 896 ChanStatus = sGetChanStatus(&rp->rp_channel); 897 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 898 line = (unit << 5) | (aiop << 3) | chan; 899 rp_table(line) = rp; 900 } 901 } 902 903 rp_ndevs++; 904 return (0); 905 906nogo: 907 rp_releaseresource(ctlp); 908 909 return (retval); 910} 911 912void 913rp_releaseresource(CONTROLLER_t *ctlp) 914{ 915 int i, s, unit; 916 struct rp_port *rp; 917 918 919 unit = device_get_unit(ctlp->dev); 920 if (rp_addr(unit) != NULL) { 921 for (i = 0; i < rp_num_ports[unit]; i++) { 922 rp = rp_addr(unit) + i; 923 s = ttyrel(rp->rp_tty); 924 if (s) { 925 printf("Detaching with active tty (%d refs)!\n", s); 926 } 927 } 928 } 929 930 if (ctlp->rp != NULL) { 931 s = spltty(); 932 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) 933 if (p_rp_addr[i] == ctlp->rp) 934 p_rp_addr[i] = NULL; 935 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) 936 if (p_rp_table[i] == ctlp->rp) 937 p_rp_table[i] = NULL; 938 splx(s); 939 free(ctlp->rp, M_DEVBUF); 940 ctlp->rp = NULL; 941 } 942 if (ctlp->dev != NULL) { 943 for (i = 0 ; i < rp_num_ports[unit] * 6 ; i++) 944 destroy_dev(ctlp->dev_nodes[i]); 945 free(ctlp->dev_nodes, M_DEVBUF); 946 ctlp->dev = NULL; 947 } 948} 949 950void 951rp_untimeout(void) 952{ 953 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle); 954} 955static int 956rpopen(dev, flag, mode, td) 957 struct cdev *dev; 958 int flag, mode; 959 struct thread *td; 960{ 961 struct rp_port *rp; 962 int unit, port, mynor, umynor, flags; /* SG */ 963 struct tty *tp; 964 int oldspl, error; 965 unsigned int IntMask, ChanStatus; 966 967 968 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 969 port = (minor(dev) & 0x1f); /* SG */ 970 mynor = (port + umynor); /* SG */ 971 unit = minor_to_unit[mynor]; 972 if (rp_addr(unit) == NULL) 973 return (ENXIO); 974 if(IS_CONTROL(dev)) 975 return(0); 976 rp = rp_addr(unit) + port; 977/* rp->rp_tty = &rp_tty[rp->rp_port]; 978*/ 979 tp = rp->rp_tty; 980 dev->si_tty = tp; 981 982 oldspl = spltty(); 983 984open_top: 985 while(rp->state & ~SET_DTR) { 986 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0); 987 if(error != 0) 988 goto out; 989 } 990 991 if(tp->t_state & TS_ISOPEN) { 992 if(IS_CALLOUT(dev)) { 993 if(!rp->active_out) { 994 error = EBUSY; 995 goto out; 996 } 997 } else { 998 if(rp->active_out) { 999 if(flag & O_NONBLOCK) { 1000 error = EBUSY; 1001 goto out; 1002 } 1003 error = tsleep(&rp->active_out, 1004 TTIPRI | PCATCH, "rpbi", 0); 1005 if(error != 0) 1006 goto out; 1007 goto open_top; 1008 } 1009 } 1010 if(tp->t_state & TS_XCLUDE && suser(td) != 0) { 1011 splx(oldspl); 1012 error = EBUSY; 1013 goto out2; 1014 } 1015 } 1016 else { 1017 tp->t_dev = dev; 1018 tp->t_param = rpparam; 1019 tp->t_oproc = rpstart; 1020 tp->t_stop = rpstop; 1021 tp->t_line = 0; 1022 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; 1023 tp->t_ififosize = 512; 1024 tp->t_ispeedwat = (speed_t)-1; 1025 tp->t_ospeedwat = (speed_t)-1; 1026 flags = 0; 1027 flags |= SET_RTS; 1028 flags |= SET_DTR; 1029 rp->rp_channel.TxControl[3] = 1030 ((rp->rp_channel.TxControl[3] 1031 & ~(SET_RTS | SET_DTR)) | flags); 1032 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1033 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1034 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1035 sDisRxStatusMode(&rp->rp_channel); 1036 sFlushRxFIFO(&rp->rp_channel); 1037 sFlushTxFIFO(&rp->rp_channel); 1038 1039 sEnInterrupts(&rp->rp_channel, 1040 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 1041 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1042 1043 sDisRxStatusMode(&rp->rp_channel); 1044 sClrTxXOFF(&rp->rp_channel); 1045 1046/* sDisRTSFlowCtl(&rp->rp_channel); 1047 sDisCTSFlowCtl(&rp->rp_channel); 1048*/ 1049 sDisTxSoftFlowCtl(&rp->rp_channel); 1050 1051 sStartRxProcessor(&rp->rp_channel); 1052 1053 sEnRxFIFO(&rp->rp_channel); 1054 sEnTransmit(&rp->rp_channel); 1055 1056/* sSetDTR(&rp->rp_channel); 1057 sSetRTS(&rp->rp_channel); 1058*/ 1059 1060 ++rp->wopeners; 1061 error = rpparam(tp, &tp->t_termios); 1062 --rp->wopeners; 1063 if(error != 0) { 1064 splx(oldspl); 1065 return(error); 1066 } 1067 1068 rp_num_ports_open++; 1069 1070 IntMask = sGetChanIntID(&rp->rp_channel); 1071 IntMask = IntMask & rp->rp_intmask; 1072 ChanStatus = sGetChanStatus(&rp->rp_channel); 1073 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { 1074 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { 1075 (void)ttyld_modem(tp, 1); 1076 } 1077 } 1078 1079 if(rp_num_ports_open == 1) 1080 rp_callout_handle = timeout(rp_do_poll, 1081 (void *)NULL, POLL_INTERVAL); 1082 } 1083 1084 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 1085 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { 1086 ++rp->wopeners; 1087 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, 1088 "rpdcd", 0); 1089 --rp->wopeners; 1090 if(error != 0) 1091 goto out; 1092 goto open_top; 1093 } 1094 error = ttyld_open(tp, dev); 1095 1096 ttyldoptim(tp); 1097 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) 1098 rp->active_out = TRUE; 1099 1100/* if(rp_num_ports_open == 1) 1101 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1102*/ 1103out: 1104 splx(oldspl); 1105 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { 1106 rphardclose(rp); 1107 } 1108out2: 1109 if (error == 0) 1110 device_busy(rp->rp_ctlp->dev); 1111 return(error); 1112} 1113 1114static int 1115rpclose(dev, flag, mode, td) 1116 struct cdev *dev; 1117 int flag, mode; 1118 struct thread *td; 1119{ 1120 int oldspl, unit, mynor, umynor, port; /* SG */ 1121 struct rp_port *rp; 1122 struct tty *tp; 1123 CHANNEL_t *cp; 1124 1125 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1126 port = (minor(dev) & 0x1f); /* SG */ 1127 mynor = (port + umynor); /* SG */ 1128 unit = minor_to_unit[mynor]; /* SG */ 1129 1130 if(IS_CONTROL(dev)) 1131 return(0); 1132 rp = rp_addr(unit) + port; 1133 cp = &rp->rp_channel; 1134 tp = rp->rp_tty; 1135 1136 oldspl = spltty(); 1137 ttyld_close(tp, flag); 1138 ttyldoptim(tp); 1139 rphardclose(rp); 1140 1141 tp->t_state &= ~TS_BUSY; 1142 ttyclose(tp); 1143 1144 splx(oldspl); 1145 1146 device_unbusy(rp->rp_ctlp->dev); 1147 1148 return(0); 1149} 1150 1151static void 1152rphardclose(struct rp_port *rp) 1153{ 1154 int mynor; 1155 struct tty *tp; 1156 CHANNEL_t *cp; 1157 1158 cp = &rp->rp_channel; 1159 tp = rp->rp_tty; 1160 mynor = MINOR_MAGIC(tp->t_dev); 1161 1162 sFlushRxFIFO(cp); 1163 sFlushTxFIFO(cp); 1164 sDisTransmit(cp); 1165 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 1166 sDisRTSFlowCtl(cp); 1167 sDisCTSFlowCtl(cp); 1168 sDisTxSoftFlowCtl(cp); 1169 sClrTxXOFF(cp); 1170 1171 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { 1172 sClrDTR(cp); 1173 } 1174 if(IS_CALLOUT(tp->t_dev)) { 1175 sClrDTR(cp); 1176 } 1177 if(rp->dtr_wait != 0) { 1178 timeout(rpdtrwakeup, rp, rp->dtr_wait); 1179 rp->state |= ~SET_DTR; 1180 } 1181 1182 rp->active_out = FALSE; 1183 wakeup(&rp->active_out); 1184 wakeup(TSA_CARR_ON(tp)); 1185} 1186 1187static 1188int 1189rpwrite(dev, uio, flag) 1190 struct cdev *dev; 1191 struct uio *uio; 1192 int flag; 1193{ 1194 struct rp_port *rp; 1195 struct tty *tp; 1196 int unit, mynor, port, umynor, error = 0; /* SG */ 1197 1198 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1199 port = (minor(dev) & 0x1f); /* SG */ 1200 mynor = (port + umynor); /* SG */ 1201 unit = minor_to_unit[mynor]; /* SG */ 1202 1203 if(IS_CONTROL(dev)) 1204 return(ENODEV); 1205 rp = rp_addr(unit) + port; 1206 tp = rp->rp_tty; 1207 while(rp->rp_disable_writes) { 1208 rp->rp_waiting = 1; 1209 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0); 1210 if (error) 1211 return(error); 1212 } 1213 1214 error = ttyld_write(tp, uio, flag); 1215 return error; 1216} 1217 1218static void 1219rpdtrwakeup(void *chan) 1220{ 1221 struct rp_port *rp; 1222 1223 rp = (struct rp_port *)chan; 1224 rp->state &= SET_DTR; 1225 wakeup(&rp->dtr_wait); 1226} 1227 1228static int 1229rpioctl(dev, cmd, data, flag, td) 1230 struct cdev *dev; 1231 u_long cmd; 1232 caddr_t data; 1233 int flag; 1234 struct thread *td; 1235{ 1236 struct rp_port *rp; 1237 CHANNEL_t *cp; 1238 struct tty *tp; 1239 int unit, mynor, port, umynor; /* SG */ 1240 int oldspl; 1241 int error = 0; 1242 int arg, flags, result, ChanStatus; 1243 struct termios *t;
|