rp.c revision 171045
1/*- 2 * Copyright (c) Comtrol Corporation <support@comtrol.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted prodived that the follwoing conditions 7 * are met. 8 * 1. Redistributions of source code must retain the above copyright 9 * notive, this list of conditions and the following disclainer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials prodided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Comtrol Corporation. 16 * 4. The name of Comtrol Corporation may not be used to endorse or 17 * promote products derived from this software without specific 18 * prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: head/sys/dev/rp/rp.c 171045 2007-06-26 13:50:48Z remko $"); 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/endian.h> 46#include <sys/fcntl.h> 47#include <sys/malloc.h> 48#include <sys/serial.h> 49#include <sys/tty.h> 50#include <sys/conf.h> 51#include <sys/kernel.h> 52#include <machine/resource.h> 53#include <machine/bus.h> 54#include <sys/bus.h> 55#include <sys/rman.h> 56 57#define ROCKET_C 58#include <dev/rp/rpreg.h> 59#include <dev/rp/rpvar.h> 60 61static const char RocketPortVersion[] = "3.02"; 62 63static Byte_t RData[RDATASIZE] = 64{ 65 0x00, 0x09, 0xf6, 0x82, 66 0x02, 0x09, 0x86, 0xfb, 67 0x04, 0x09, 0x00, 0x0a, 68 0x06, 0x09, 0x01, 0x0a, 69 0x08, 0x09, 0x8a, 0x13, 70 0x0a, 0x09, 0xc5, 0x11, 71 0x0c, 0x09, 0x86, 0x85, 72 0x0e, 0x09, 0x20, 0x0a, 73 0x10, 0x09, 0x21, 0x0a, 74 0x12, 0x09, 0x41, 0xff, 75 0x14, 0x09, 0x82, 0x00, 76 0x16, 0x09, 0x82, 0x7b, 77 0x18, 0x09, 0x8a, 0x7d, 78 0x1a, 0x09, 0x88, 0x81, 79 0x1c, 0x09, 0x86, 0x7a, 80 0x1e, 0x09, 0x84, 0x81, 81 0x20, 0x09, 0x82, 0x7c, 82 0x22, 0x09, 0x0a, 0x0a 83}; 84 85static Byte_t RRegData[RREGDATASIZE]= 86{ 87 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ 88 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ 89 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ 90 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ 91 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ 92 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ 93 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ 94 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ 95 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ 96 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ 97 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ 98 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ 99 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ 100}; 101 102#if 0 103/* IRQ number to MUDBAC register 2 mapping */ 104Byte_t sIRQMap[16] = 105{ 106 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 107}; 108#endif 109 110Byte_t rp_sBitMapClrTbl[8] = 111{ 112 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f 113}; 114 115Byte_t rp_sBitMapSetTbl[8] = 116{ 117 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 118}; 119 120/*************************************************************************** 121Function: sReadAiopID 122Purpose: Read the AIOP idenfication number directly from an AIOP. 123Call: sReadAiopID(CtlP, aiop) 124 CONTROLLER_T *CtlP; Ptr to controller structure 125 int aiop: AIOP index 126Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X 127 is replace by an identifying number. 128 Flag AIOPID_NULL if no valid AIOP is found 129Warnings: No context switches are allowed while executing this function. 130 131*/ 132int sReadAiopID(CONTROLLER_T *CtlP, int aiop) 133{ 134 Byte_t AiopID; /* ID byte from AIOP */ 135 136 rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */ 137 rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0); 138 AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07; 139 if(AiopID == 0x06) 140 return(1); 141 else /* AIOP does not exist */ 142 return(-1); 143} 144 145/*************************************************************************** 146Function: sReadAiopNumChan 147Purpose: Read the number of channels available in an AIOP directly from 148 an AIOP. 149Call: sReadAiopNumChan(CtlP, aiop) 150 CONTROLLER_T *CtlP; Ptr to controller structure 151 int aiop: AIOP index 152Return: int: The number of channels available 153Comments: The number of channels is determined by write/reads from identical 154 offsets within the SRAM address spaces for channels 0 and 4. 155 If the channel 4 space is mirrored to channel 0 it is a 4 channel 156 AIOP, otherwise it is an 8 channel. 157Warnings: No context switches are allowed while executing this function. 158*/ 159int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop) 160{ 161 Word_t x, y; 162 163 rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ 164 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */ 165 x = rp_readaiop2(CtlP, aiop, _INDX_DATA); 166 rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ 167 y = rp_readaiop2(CtlP, aiop, _INDX_DATA); 168 if(x != y) /* if different must be 8 chan */ 169 return(8); 170 else 171 return(4); 172} 173 174/*************************************************************************** 175Function: sInitChan 176Purpose: Initialization of a channel and channel structure 177Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) 178 CONTROLLER_T *CtlP; Ptr to controller structure 179 CHANNEL_T *ChP; Ptr to channel structure 180 int AiopNum; AIOP number within controller 181 int ChanNum; Channel number within AIOP 182Return: int: TRUE if initialization succeeded, FALSE if it fails because channel 183 number exceeds number of channels available in AIOP. 184Comments: This function must be called before a channel can be used. 185Warnings: No range checking on any of the parameters is done. 186 187 No context switches are allowed while executing this function. 188*/ 189int sInitChan( CONTROLLER_T *CtlP, 190 CHANNEL_T *ChP, 191 int AiopNum, 192 int ChanNum) 193{ 194 int i, ChOff; 195 Byte_t *ChR; 196 static Byte_t R[4]; 197 198 if(ChanNum >= CtlP->AiopNumChan[AiopNum]) 199 return(FALSE); /* exceeds num chans in AIOP */ 200 201 /* Channel, AIOP, and controller identifiers */ 202 ChP->CtlP = CtlP; 203 ChP->ChanID = CtlP->AiopID[AiopNum]; 204 ChP->AiopNum = AiopNum; 205 ChP->ChanNum = ChanNum; 206 207 /* Initialize the channel from the RData array */ 208 for(i=0; i < RDATASIZE; i+=4) 209 { 210 R[0] = RData[i]; 211 R[1] = RData[i+1] + 0x10 * ChanNum; 212 R[2] = RData[i+2]; 213 R[3] = RData[i+3]; 214 rp_writech4(ChP,_INDX_ADDR,le32dec(R)); 215 } 216 217 ChR = ChP->R; 218 for(i=0; i < RREGDATASIZE; i+=4) 219 { 220 ChR[i] = RRegData[i]; 221 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; 222 ChR[i+2] = RRegData[i+2]; 223 ChR[i+3] = RRegData[i+3]; 224 } 225 226 /* Indexed registers */ 227 ChOff = (Word_t)ChanNum * 0x1000; 228 229 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); 230 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); 231 ChP->BaudDiv[2] = (Byte_t)BRD9600; 232 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); 233 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv)); 234 235 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); 236 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); 237 ChP->TxControl[2] = 0; 238 ChP->TxControl[3] = 0; 239 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); 240 241 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); 242 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); 243 ChP->RxControl[2] = 0; 244 ChP->RxControl[3] = 0; 245 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); 246 247 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); 248 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); 249 ChP->TxEnables[2] = 0; 250 ChP->TxEnables[3] = 0; 251 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables)); 252 253 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); 254 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); 255 ChP->TxCompare[2] = 0; 256 ChP->TxCompare[3] = 0; 257 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare)); 258 259 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); 260 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); 261 ChP->TxReplace1[2] = 0; 262 ChP->TxReplace1[3] = 0; 263 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1)); 264 265 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); 266 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); 267 ChP->TxReplace2[2] = 0; 268 ChP->TxReplace2[3] = 0; 269 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2)); 270 271 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; 272 ChP->TxFIFO = ChOff + _TX_FIFO; 273 274 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ 275 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ 276 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 277 rp_writech2(ChP,_INDX_DATA,0); 278 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; 279 ChP->RxFIFO = ChOff + _RX_FIFO; 280 281 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ 282 rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ 283 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 284 rp_writech2(ChP,_INDX_DATA,0); 285 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 286 rp_writech2(ChP,_INDX_DATA,0); 287 ChP->TxPrioCnt = ChOff + _TXP_CNT; 288 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); 289 rp_writech1(ChP,_INDX_DATA,0); 290 ChP->TxPrioPtr = ChOff + _TXP_PNTR; 291 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr); 292 rp_writech1(ChP,_INDX_DATA,0); 293 ChP->TxPrioBuf = ChOff + _TXP_BUF; 294 sEnRxProcessor(ChP); /* start the Rx processor */ 295 296 return(TRUE); 297} 298 299/*************************************************************************** 300Function: sStopRxProcessor 301Purpose: Stop the receive processor from processing a channel. 302Call: sStopRxProcessor(ChP) 303 CHANNEL_T *ChP; Ptr to channel structure 304 305Comments: The receive processor can be started again with sStartRxProcessor(). 306 This function causes the receive processor to skip over the 307 stopped channel. It does not stop it from processing other channels. 308 309Warnings: No context switches are allowed while executing this function. 310 311 Do not leave the receive processor stopped for more than one 312 character time. 313 314 After calling this function a delay of 4 uS is required to ensure 315 that the receive processor is no longer processing this channel. 316*/ 317void sStopRxProcessor(CHANNEL_T *ChP) 318{ 319 Byte_t R[4]; 320 321 R[0] = ChP->R[0]; 322 R[1] = ChP->R[1]; 323 R[2] = 0x0a; 324 R[3] = ChP->R[3]; 325 rp_writech4(ChP,_INDX_ADDR,le32dec(R)); 326} 327 328/*************************************************************************** 329Function: sFlushRxFIFO 330Purpose: Flush the Rx FIFO 331Call: sFlushRxFIFO(ChP) 332 CHANNEL_T *ChP; Ptr to channel structure 333Return: void 334Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 335 while it is being flushed the receive processor is stopped 336 and the transmitter is disabled. After these operations a 337 4 uS delay is done before clearing the pointers to allow 338 the receive processor to stop. These items are handled inside 339 this function. 340Warnings: No context switches are allowed while executing this function. 341*/ 342void sFlushRxFIFO(CHANNEL_T *ChP) 343{ 344 int i; 345 Byte_t Ch; /* channel number within AIOP */ 346 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ 347 348 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ 349 return; /* don't need to flush */ 350 351 RxFIFOEnabled = FALSE; 352 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ 353 { 354 RxFIFOEnabled = TRUE; 355 sDisRxFIFO(ChP); /* disable it */ 356 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ 357 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ 358 } 359 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ 360 Ch = (Byte_t)sGetChanNum(ChP); 361 rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ 362 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */ 363 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 364 rp_writech2(ChP,_INDX_DATA,0); 365 rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 366 rp_writech2(ChP,_INDX_DATA,0); 367 if(RxFIFOEnabled) 368 sEnRxFIFO(ChP); /* enable Rx FIFO */ 369} 370 371/*************************************************************************** 372Function: sFlushTxFIFO 373Purpose: Flush the Tx FIFO 374Call: sFlushTxFIFO(ChP) 375 CHANNEL_T *ChP; Ptr to channel structure 376Return: void 377Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 378 while it is being flushed the receive processor is stopped 379 and the transmitter is disabled. After these operations a 380 4 uS delay is done before clearing the pointers to allow 381 the receive processor to stop. These items are handled inside 382 this function. 383Warnings: No context switches are allowed while executing this function. 384*/ 385void sFlushTxFIFO(CHANNEL_T *ChP) 386{ 387 int i; 388 Byte_t Ch; /* channel number within AIOP */ 389 int TxEnabled; /* TRUE if transmitter enabled */ 390 391 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ 392 return; /* don't need to flush */ 393 394 TxEnabled = FALSE; 395 if(ChP->TxControl[3] & TX_ENABLE) 396 { 397 TxEnabled = TRUE; 398 sDisTransmit(ChP); /* disable transmitter */ 399 } 400 sStopRxProcessor(ChP); /* stop Rx processor */ 401 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ 402 rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ 403 Ch = (Byte_t)sGetChanNum(ChP); 404 rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ 405 rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */ 406 rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 407 rp_writech2(ChP,_INDX_DATA,0); 408 if(TxEnabled) 409 sEnTransmit(ChP); /* enable transmitter */ 410 sStartRxProcessor(ChP); /* restart Rx processor */ 411} 412 413/*************************************************************************** 414Function: sWriteTxPrioByte 415Purpose: Write a byte of priority transmit data to a channel 416Call: sWriteTxPrioByte(ChP,Data) 417 CHANNEL_T *ChP; Ptr to channel structure 418 Byte_t Data; The transmit data byte 419 420Return: int: 1 if the bytes is successfully written, otherwise 0. 421 422Comments: The priority byte is transmitted before any data in the Tx FIFO. 423 424Warnings: No context switches are allowed while executing this function. 425*/ 426int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) 427{ 428 Byte_t DWBuf[4]; /* buffer for double word writes */ 429 430 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ 431 { 432 rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */ 433 if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */ 434 return(0); /* nothing sent */ 435 436 le16enc(DWBuf,ChP->TxPrioBuf); /* data byte address */ 437 438 DWBuf[2] = Data; /* data byte value */ 439 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ 440 441 le16enc(DWBuf,ChP->TxPrioCnt); /* Tx priority count address */ 442 443 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ 444 DWBuf[3] = 0; /* priority buffer pointer */ 445 rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ 446 } 447 else /* write it to Tx FIFO */ 448 { 449 sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data); 450 } 451 return(1); /* 1 byte sent */ 452} 453 454/*************************************************************************** 455Function: sEnInterrupts 456Purpose: Enable one or more interrupts for a channel 457Call: sEnInterrupts(ChP,Flags) 458 CHANNEL_T *ChP; Ptr to channel structure 459 Word_t Flags: Interrupt enable flags, can be any combination 460 of the following flags: 461 TXINT_EN: Interrupt on Tx FIFO empty 462 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 463 sSetRxTrigger()) 464 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 465 MCINT_EN: Interrupt on modem input change 466 CHANINT_EN: Allow channel interrupt signal to the AIOP's 467 Interrupt Channel Register. 468Return: void 469Comments: If an interrupt enable flag is set in Flags, that interrupt will be 470 enabled. If an interrupt enable flag is not set in Flags, that 471 interrupt will not be changed. Interrupts can be disabled with 472 function sDisInterrupts(). 473 474 This function sets the appropriate bit for the channel in the AIOP's 475 Interrupt Mask Register if the CHANINT_EN flag is set. This allows 476 this channel's bit to be set in the AIOP's Interrupt Channel Register. 477 478 Interrupts must also be globally enabled before channel interrupts 479 will be passed on to the host. This is done with function 480 sEnGlobalInt(). 481 482 In some cases it may be desirable to disable interrupts globally but 483 enable channel interrupts. This would allow the global interrupt 484 status register to be used to determine which AIOPs need service. 485*/ 486void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) 487{ 488 Byte_t Mask; /* Interrupt Mask Register */ 489 490 ChP->RxControl[2] |= 491 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 492 493 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); 494 495 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); 496 497 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); 498 499 if(Flags & CHANINT_EN) 500 { 501 Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum]; 502 rp_writech1(ChP,_INT_MASK,Mask); 503 } 504} 505 506/*************************************************************************** 507Function: sDisInterrupts 508Purpose: Disable one or more interrupts for a channel 509Call: sDisInterrupts(ChP,Flags) 510 CHANNEL_T *ChP; Ptr to channel structure 511 Word_t Flags: Interrupt flags, can be any combination 512 of the following flags: 513 TXINT_EN: Interrupt on Tx FIFO empty 514 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 515 sSetRxTrigger()) 516 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 517 MCINT_EN: Interrupt on modem input change 518 CHANINT_EN: Disable channel interrupt signal to the 519 AIOP's Interrupt Channel Register. 520Return: void 521Comments: If an interrupt flag is set in Flags, that interrupt will be 522 disabled. If an interrupt flag is not set in Flags, that 523 interrupt will not be changed. Interrupts can be enabled with 524 function sEnInterrupts(). 525 526 This function clears the appropriate bit for the channel in the AIOP's 527 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks 528 this channel's bit from being set in the AIOP's Interrupt Channel 529 Register. 530*/ 531void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) 532{ 533 Byte_t Mask; /* Interrupt Mask Register */ 534 535 ChP->RxControl[2] &= 536 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 537 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); 538 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); 539 rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); 540 541 if(Flags & CHANINT_EN) 542 { 543 Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum]; 544 rp_writech1(ChP,_INT_MASK,Mask); 545 } 546} 547 548/********************************************************************* 549 Begin FreeBsd-specific driver code 550**********************************************************************/ 551 552struct callout_handle rp_callout_handle; 553 554static int rp_num_ports_open = 0; 555static int rp_ndevs = 0; 556 557static int rp_num_ports[4]; /* Number of ports on each controller */ 558 559#define POLL_INTERVAL 1 560 561#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) 562#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) 563#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) 564 565static struct rp_port *p_rp_addr[4]; 566static struct rp_port *p_rp_table[MAX_RP_PORTS]; 567#define rp_addr(unit) (p_rp_addr[unit]) 568#define rp_table(port) (p_rp_table[port]) 569 570/* 571 * The top-level routines begin here 572 */ 573 574static void rpbreak(struct tty *, int); 575static void rpclose(struct tty *tp); 576static void rphardclose(struct tty *tp); 577static int rpmodem(struct tty *, int, int); 578static int rpparam(struct tty *, struct termios *); 579static void rpstart(struct tty *); 580static void rpstop(struct tty *, int); 581static t_open_t rpopen; 582 583static void rp_do_receive(struct rp_port *rp, struct tty *tp, 584 CHANNEL_t *cp, unsigned int ChanStatus) 585{ 586 int spl; 587 unsigned int CharNStat; 588 int i, ToRecv, wRecv, ch, ttynocopy; 589 590 ToRecv = sGetRxCnt(cp); 591 if(ToRecv == 0) 592 return; 593 594/* If status indicates there are errored characters in the 595 FIFO, then enter status mode (a word in FIFO holds 596 characters and status) 597*/ 598 599 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 600 if(!(ChanStatus & STATMODE)) { 601 ChanStatus |= STATMODE; 602 sEnRxStatusMode(cp); 603 } 604 } 605/* 606 if we previously entered status mode then read down the 607 FIFO one word at a time, pulling apart the character and 608 the status. Update error counters depending on status. 609*/ 610 if(ChanStatus & STATMODE) { 611 while(ToRecv) { 612 if(tp->t_state & TS_TBLOCK) { 613 break; 614 } 615 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); 616 ch = CharNStat & 0xff; 617 618 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 619 ch |= TTY_FE; 620 else if (CharNStat & STMPARITYH) 621 ch |= TTY_PE; 622 else if (CharNStat & STMRCVROVRH) 623 rp->rp_overflows++; 624 625 ttyld_rint(tp, ch); 626 ToRecv--; 627 } 628/* 629 After emtying FIFO in status mode, turn off status mode 630*/ 631 632 if(sGetRxCnt(cp) == 0) { 633 sDisRxStatusMode(cp); 634 } 635 } else { 636 /* 637 * Avoid the grotesquely inefficient lineswitch routine 638 * (ttyinput) in "raw" mode. It usually takes about 450 639 * instructions (that's without canonical processing or echo!). 640 * slinput is reasonably fast (usually 40 instructions plus 641 * call overhead). 642 */ 643 ToRecv = sGetRxCnt(cp); 644 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { 645 if ( ToRecv > RXFIFO_SIZE ) { 646 ToRecv = RXFIFO_SIZE; 647 } 648 for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) { 649 le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp))); 650 } 651 if ( ToRecv & 1 ) { 652 rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp)); 653 } 654 tk_nin += ToRecv; 655 tk_rawcc += ToRecv; 656 tp->t_rawcc += ToRecv; 657 ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq); 658 ttwakeup(tp); 659 } else { 660 while (ToRecv) { 661 if(tp->t_state & TS_TBLOCK) { 662 break; 663 } 664 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 665 spl = spltty(); 666 ttyld_rint(tp, ch); 667 splx(spl); 668 ToRecv--; 669 } 670 } 671 } 672} 673 674static void rp_handle_port(struct rp_port *rp) 675{ 676 CHANNEL_t *cp; 677 struct tty *tp; 678 unsigned int IntMask, ChanStatus; 679 680 if(!rp) 681 return; 682 683 cp = &rp->rp_channel; 684 tp = rp->rp_tty; 685 IntMask = sGetChanIntID(cp); 686 IntMask = IntMask & rp->rp_intmask; 687 ChanStatus = sGetChanStatus(cp); 688 if(IntMask & RXF_TRIG) 689 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 690 rp_do_receive(rp, tp, cp, ChanStatus); 691 } 692 if(IntMask & DELTA_CD) { 693 if(ChanStatus & CD_ACT) { 694 if(!(tp->t_state & TS_CARR_ON) ) { 695 (void)ttyld_modem(tp, 1); 696 } 697 } else { 698 if((tp->t_state & TS_CARR_ON)) { 699 (void)ttyld_modem(tp, 0); 700 if(ttyld_modem(tp, 0) == 0) { 701 rphardclose(tp); 702 } 703 } 704 } 705 } 706/* oldcts = rp->rp_cts; 707 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 708 if(oldcts != rp->rp_cts) { 709 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 710 } 711*/ 712} 713 714static void rp_do_poll(void *not_used) 715{ 716 CONTROLLER_t *ctl; 717 struct rp_port *rp; 718 struct tty *tp; 719 int unit, aiop, ch, line, count; 720 unsigned char CtlMask, AiopMask; 721 722 for(unit = 0; unit < rp_ndevs; unit++) { 723 rp = rp_addr(unit); 724 ctl = rp->rp_ctlp; 725 CtlMask = ctl->ctlmask(ctl); 726 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 727 if(CtlMask & 1) { 728 AiopMask = sGetAiopIntStatus(ctl, aiop); 729 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 730 if(AiopMask & 1) { 731 line = (unit << 5) | (aiop << 3) | ch; 732 rp = rp_table(line); 733 rp_handle_port(rp); 734 } 735 } 736 } 737 } 738 739 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 740 line++, rp++) { 741 tp = rp->rp_tty; 742 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 743 count = sGetTxCnt(&rp->rp_channel); 744 if(count == 0) 745 tp->t_state &= ~(TS_BUSY); 746 if(!(tp->t_state & TS_TTSTOP) && 747 (count <= rp->rp_restart)) { 748 ttyld_start(tp); 749 } 750 } 751 } 752 } 753 if(rp_num_ports_open) 754 rp_callout_handle = timeout(rp_do_poll, 755 (void *)NULL, POLL_INTERVAL); 756} 757 758int 759rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) 760{ 761 int oldspl, unit; 762 int num_chan; 763 int aiop, chan, port; 764 int ChanStatus, line, count; 765 int retval; 766 struct rp_port *rp; 767 struct tty *tp; 768 769 unit = device_get_unit(ctlp->dev); 770 771 printf("RocketPort%d (Version %s) %d ports.\n", unit, 772 RocketPortVersion, num_ports); 773 rp_num_ports[unit] = num_ports; 774 callout_handle_init(&rp_callout_handle); 775 776 ctlp->rp = rp = (struct rp_port *) 777 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); 778 if (rp == NULL) { 779 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); 780 retval = ENOMEM; 781 goto nogo; 782 } 783 784 count = unit * 32; /* board times max ports per card SG */ 785 786 bzero(rp, sizeof(struct rp_port) * num_ports); 787 oldspl = spltty(); 788 rp_addr(unit) = rp; 789 splx(oldspl); 790 791 port = 0; 792 for(aiop=0; aiop < num_aiops; aiop++) { 793 num_chan = sGetAiopNumChan(ctlp, aiop); 794 for(chan=0; chan < num_chan; chan++, port++, rp++) { 795 tp = rp->rp_tty = ttyalloc(); 796 tp->t_sc = rp; 797 tp->t_param = rpparam; 798 tp->t_oproc = rpstart; 799 tp->t_stop = rpstop; 800 tp->t_break = rpbreak; 801 tp->t_modem = rpmodem; 802 tp->t_close = rpclose; 803 tp->t_open = rpopen; 804 tp->t_ififosize = 512; 805 tp->t_ispeedwat = (speed_t)-1; 806 tp->t_ospeedwat = (speed_t)-1; 807 rp->rp_port = port; 808 rp->rp_ctlp = ctlp; 809 rp->rp_unit = unit; 810 rp->rp_chan = chan; 811 rp->rp_aiop = aiop; 812 813 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 814 DELTA_CD | DELTA_CTS | DELTA_DSR; 815#ifdef notdef 816 ChanStatus = sGetChanStatus(&rp->rp_channel); 817#endif /* notdef */ 818 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 819 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", 820 unit, aiop, chan); 821 retval = ENXIO; 822 goto nogo; 823 } 824 ChanStatus = sGetChanStatus(&rp->rp_channel); 825 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 826 line = (unit << 5) | (aiop << 3) | chan; 827 rp_table(line) = rp; 828 ttycreate(tp, TS_CALLOUT, "R%r%r", unit, port); 829 } 830 } 831 832 rp_ndevs++; 833 return (0); 834 835nogo: 836 rp_releaseresource(ctlp); 837 838 return (retval); 839} 840 841void 842rp_releaseresource(CONTROLLER_t *ctlp) 843{ 844 int i, s, unit; 845 struct rp_port *rp; 846 847 848 unit = device_get_unit(ctlp->dev); 849 if (rp_addr(unit) != NULL) { 850 for (i = 0; i < rp_num_ports[unit]; i++) { 851 rp = rp_addr(unit) + i; 852 ttyfree(rp->rp_tty); 853 } 854 } 855 856 if (ctlp->rp != NULL) { 857 s = spltty(); 858 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) 859 if (p_rp_addr[i] == ctlp->rp) 860 p_rp_addr[i] = NULL; 861 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) 862 if (p_rp_table[i] == ctlp->rp) 863 p_rp_table[i] = NULL; 864 splx(s); 865 free(ctlp->rp, M_DEVBUF); 866 ctlp->rp = NULL; 867 } 868} 869 870void 871rp_untimeout(void) 872{ 873 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle); 874} 875 876static int 877rpopen(struct tty *tp, struct cdev *dev) 878{ 879 struct rp_port *rp; 880 int oldspl, flags; 881 unsigned int IntMask, ChanStatus; 882 883 rp = dev->si_drv1; 884 885 oldspl = spltty(); 886 887 flags = 0; 888 flags |= SET_RTS; 889 flags |= SET_DTR; 890 rp->rp_channel.TxControl[3] = 891 ((rp->rp_channel.TxControl[3] 892 & ~(SET_RTS | SET_DTR)) | flags); 893 rp_writech4(&rp->rp_channel,_INDX_ADDR, 894 le32dec(rp->rp_channel.TxControl)); 895 sSetRxTrigger(&rp->rp_channel, TRIG_1); 896 sDisRxStatusMode(&rp->rp_channel); 897 sFlushRxFIFO(&rp->rp_channel); 898 sFlushTxFIFO(&rp->rp_channel); 899 900 sEnInterrupts(&rp->rp_channel, 901 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 902 sSetRxTrigger(&rp->rp_channel, TRIG_1); 903 904 sDisRxStatusMode(&rp->rp_channel); 905 sClrTxXOFF(&rp->rp_channel); 906 907/* sDisRTSFlowCtl(&rp->rp_channel); 908 sDisCTSFlowCtl(&rp->rp_channel); 909*/ 910 sDisTxSoftFlowCtl(&rp->rp_channel); 911 912 sStartRxProcessor(&rp->rp_channel); 913 914 sEnRxFIFO(&rp->rp_channel); 915 sEnTransmit(&rp->rp_channel); 916 917/* sSetDTR(&rp->rp_channel); 918 sSetRTS(&rp->rp_channel); 919*/ 920 921 rp_num_ports_open++; 922 923 IntMask = sGetChanIntID(&rp->rp_channel); 924 IntMask = IntMask & rp->rp_intmask; 925 ChanStatus = sGetChanStatus(&rp->rp_channel); 926 927 if(rp_num_ports_open == 1) 928 rp_callout_handle = timeout(rp_do_poll, 929 (void *)NULL, POLL_INTERVAL); 930 931 device_busy(rp->rp_ctlp->dev); 932 return(0); 933} 934 935static void 936rpclose(struct tty *tp) 937{ 938 struct rp_port *rp; 939 940 rp = tp->t_sc; 941 rphardclose(tp); 942 device_unbusy(rp->rp_ctlp->dev); 943} 944 945static void 946rphardclose(struct tty *tp) 947{ 948 struct rp_port *rp; 949 CHANNEL_t *cp; 950 951 rp = tp->t_sc; 952 cp = &rp->rp_channel; 953 954 sFlushRxFIFO(cp); 955 sFlushTxFIFO(cp); 956 sDisTransmit(cp); 957 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 958 sDisRTSFlowCtl(cp); 959 sDisCTSFlowCtl(cp); 960 sDisTxSoftFlowCtl(cp); 961 sClrTxXOFF(cp); 962 963 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) { 964 sClrDTR(cp); 965 } 966 if(ISCALLOUT(tp->t_dev)) { 967 sClrDTR(cp); 968 } 969 tp->t_actout = FALSE; 970 wakeup(&tp->t_actout); 971 wakeup(TSA_CARR_ON(tp)); 972} 973 974static void 975rpbreak(struct tty *tp, int sig) 976{ 977 struct rp_port *rp; 978 979 rp = tp->t_sc; 980 if (sig) { 981 sSendBreak(&rp->rp_channel); 982 } else { 983 sClrBreak(&rp->rp_channel); 984 } 985} 986 987static int 988rpmodem(struct tty *tp, int sigon, int sigoff) 989{ 990 struct rp_port *rp; 991 int i, j, k; 992 993 rp = tp->t_sc; 994 if (sigon != 0 || sigoff != 0) { 995 i = j = 0; 996 if (sigon & SER_DTR) 997 i = SET_DTR; 998 if (sigoff & SER_DTR) 999 j = SET_DTR; 1000 if (sigon & SER_RTS) 1001 i = SET_RTS; 1002 if (sigoff & SER_RTS) 1003 j = SET_RTS; 1004 rp->rp_channel.TxControl[3] &= ~i; 1005 rp->rp_channel.TxControl[3] |= j; 1006 rp_writech4(&rp->rp_channel,_INDX_ADDR, 1007 le32dec(rp->rp_channel.TxControl)); 1008 } else { 1009 i = sGetChanStatusLo(&rp->rp_channel); 1010 j = rp->rp_channel.TxControl[3]; 1011 k = 0; 1012 if (j & SET_DTR) 1013 k |= SER_DTR; 1014 if (j & SET_RTS) 1015 k |= SER_RTS; 1016 if (i & CD_ACT) 1017 k |= SER_DCD; 1018 if (i & DSR_ACT) 1019 k |= SER_DSR; 1020 if (i & CTS_ACT) 1021 k |= SER_CTS; 1022 return(k); 1023 } 1024 return (0); 1025} 1026 1027static struct speedtab baud_table[] = { 1028 {B0, 0}, {B50, BRD50}, {B75, BRD75}, 1029 {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, 1030 {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, 1031 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, 1032 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, 1033 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, 1034 {B57600, BRD57600}, {B76800, BRD76800}, 1035 {B115200, BRD115200}, {B230400, BRD230400}, 1036 {-1, -1} 1037}; 1038 1039static int 1040rpparam(tp, t) 1041 struct tty *tp; 1042 struct termios *t; 1043{ 1044 struct rp_port *rp; 1045 CHANNEL_t *cp; 1046 int oldspl, cflag, iflag, oflag, lflag; 1047 int ospeed; 1048#ifdef RPCLOCAL 1049 int devshift; 1050#endif 1051 1052 1053 rp = tp->t_sc; 1054 cp = &rp->rp_channel; 1055 oldspl = spltty(); 1056 1057 cflag = t->c_cflag; 1058#ifdef RPCLOCAL 1059 devshift = umynor / 32; 1060 devshift = 1 << devshift; 1061 if ( devshift & RPCLOCAL ) { 1062 cflag |= CLOCAL; 1063 } 1064#endif 1065 iflag = t->c_iflag; 1066 oflag = t->c_oflag; 1067 lflag = t->c_lflag; 1068 1069 ospeed = ttspeedtab(t->c_ispeed, baud_table); 1070 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) 1071 return(EINVAL); 1072 1073 tp->t_ispeed = t->c_ispeed; 1074 tp->t_ospeed = t->c_ospeed; 1075 tp->t_cflag = cflag; 1076 tp->t_iflag = iflag; 1077 tp->t_oflag = oflag; 1078 tp->t_lflag = lflag; 1079 1080 if(t->c_ospeed == 0) { 1081 sClrDTR(cp); 1082 return(0); 1083 } 1084 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; 1085 1086 /* Set baud rate ----- we only pay attention to ispeed */ 1087 sSetDTR(cp); 1088 sSetRTS(cp); 1089 sSetBaud(cp, ospeed); 1090 1091 if(cflag & CSTOPB) { 1092 sSetStop2(cp); 1093 } else { 1094 sSetStop1(cp); 1095 } 1096 1097 if(cflag & PARENB) { 1098 sEnParity(cp); 1099 if(cflag & PARODD) { 1100 sSetOddParity(cp); 1101 } else { 1102 sSetEvenParity(cp); 1103 } 1104 } 1105 else { 1106 sDisParity(cp); 1107 } 1108 if((cflag & CSIZE) == CS8) { 1109 sSetData8(cp); 1110 rp->rp_imask = 0xFF; 1111 } else { 1112 sSetData7(cp); 1113 rp->rp_imask = 0x7F; 1114 } 1115 1116 if(iflag & ISTRIP) { 1117 rp->rp_imask &= 0x7F; 1118 } 1119 1120 if(cflag & CLOCAL) { 1121 rp->rp_intmask &= ~DELTA_CD; 1122 } else { 1123 rp->rp_intmask |= DELTA_CD; 1124 } 1125 1126 /* Put flow control stuff here */ 1127 1128 if(cflag & CCTS_OFLOW) { 1129 sEnCTSFlowCtl(cp); 1130 } else { 1131 sDisCTSFlowCtl(cp); 1132 } 1133 1134 if(cflag & CRTS_IFLOW) { 1135 rp->rp_rts_iflow = 1; 1136 } else { 1137 rp->rp_rts_iflow = 0; 1138 } 1139 1140 if(cflag & CRTS_IFLOW) { 1141 sEnRTSFlowCtl(cp); 1142 } else { 1143 sDisRTSFlowCtl(cp); 1144 } 1145 ttyldoptim(tp); 1146 1147 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { 1148 tp->t_state |= TS_CARR_ON; 1149 wakeup(TSA_CARR_ON(tp)); 1150 } 1151 1152/* tp->t_state |= TS_CAN_BYPASS_L_RINT; 1153 flags = rp->rp_channel.TxControl[3]; 1154 if(flags & SET_DTR) 1155 else 1156 if(flags & SET_RTS) 1157 else 1158*/ 1159 splx(oldspl); 1160 1161 return(0); 1162} 1163 1164static void 1165rpstart(tp) 1166 struct tty *tp; 1167{ 1168 struct rp_port *rp; 1169 CHANNEL_t *cp; 1170 struct clist *qp; 1171 char flags; 1172 int spl, xmit_fifo_room; 1173 int i, count, wcount; 1174 1175 1176 rp = tp->t_sc; 1177 cp = &rp->rp_channel; 1178 flags = rp->rp_channel.TxControl[3]; 1179 spl = spltty(); 1180 1181 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1182 ttwwakeup(tp); 1183 splx(spl); 1184 return; 1185 } 1186 if(rp->rp_xmit_stopped) { 1187 sEnTransmit(cp); 1188 rp->rp_xmit_stopped = 0; 1189 } 1190 count = sGetTxCnt(cp); 1191 1192 if(tp->t_outq.c_cc == 0) { 1193 if((tp->t_state & TS_BUSY) && (count == 0)) { 1194 tp->t_state &= ~TS_BUSY; 1195 } 1196 ttwwakeup(tp); 1197 splx(spl); 1198 return; 1199 } 1200 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); 1201 qp = &tp->t_outq; 1202 if(xmit_fifo_room > 0 && qp->c_cc > 0) { 1203 tp->t_state |= TS_BUSY; 1204 count = q_to_b( qp, rp->TxBuf, xmit_fifo_room ); 1205 for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) { 1206 rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i)); 1207 } 1208 if ( count & 1 ) { 1209 rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); 1210 } 1211 } 1212 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; 1213 1214 ttwwakeup(tp); 1215 splx(spl); 1216} 1217 1218static 1219void 1220rpstop(tp, flag) 1221 register struct tty *tp; 1222 int flag; 1223{ 1224 struct rp_port *rp; 1225 CHANNEL_t *cp; 1226 int spl; 1227 1228 rp = tp->t_sc; 1229 cp = &rp->rp_channel; 1230 1231 spl = spltty(); 1232 1233 if(tp->t_state & TS_BUSY) { 1234 if((tp->t_state&TS_TTSTOP) == 0) { 1235 sFlushTxFIFO(cp); 1236 } else { 1237 if(rp->rp_xmit_stopped == 0) { 1238 sDisTransmit(cp); 1239 rp->rp_xmit_stopped = 1; 1240 } 1241 } 1242 } 1243 splx(spl); 1244 rpstart(tp); 1245} 1246