rp.c revision 164439
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 164439 2006-11-20 12:59:27Z marius $"); 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 int rpmodem(struct tty *, int, int); 577static int rpparam(struct tty *, struct termios *); 578static void rpstart(struct tty *); 579static void rpstop(struct tty *, int); 580static t_open_t rpopen; 581 582static void rp_do_receive(struct rp_port *rp, struct tty *tp, 583 CHANNEL_t *cp, unsigned int ChanStatus) 584{ 585 int spl; 586 unsigned int CharNStat; 587 int i, ToRecv, wRecv, ch, ttynocopy; 588 589 ToRecv = sGetRxCnt(cp); 590 if(ToRecv == 0) 591 return; 592 593/* If status indicates there are errored characters in the 594 FIFO, then enter status mode (a word in FIFO holds 595 characters and status) 596*/ 597 598 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 599 if(!(ChanStatus & STATMODE)) { 600 ChanStatus |= STATMODE; 601 sEnRxStatusMode(cp); 602 } 603 } 604/* 605 if we previously entered status mode then read down the 606 FIFO one word at a time, pulling apart the character and 607 the status. Update error counters depending on status. 608*/ 609 if(ChanStatus & STATMODE) { 610 while(ToRecv) { 611 if(tp->t_state & TS_TBLOCK) { 612 break; 613 } 614 CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); 615 ch = CharNStat & 0xff; 616 617 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 618 ch |= TTY_FE; 619 else if (CharNStat & STMPARITYH) 620 ch |= TTY_PE; 621 else if (CharNStat & STMRCVROVRH) 622 rp->rp_overflows++; 623 624 ttyld_rint(tp, ch); 625 ToRecv--; 626 } 627/* 628 After emtying FIFO in status mode, turn off status mode 629*/ 630 631 if(sGetRxCnt(cp) == 0) { 632 sDisRxStatusMode(cp); 633 } 634 } else { 635 /* 636 * Avoid the grotesquely inefficient lineswitch routine 637 * (ttyinput) in "raw" mode. It usually takes about 450 638 * instructions (that's without canonical processing or echo!). 639 * slinput is reasonably fast (usually 40 instructions plus 640 * call overhead). 641 */ 642 ToRecv = sGetRxCnt(cp); 643 if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { 644 if ( ToRecv > RXFIFO_SIZE ) { 645 ToRecv = RXFIFO_SIZE; 646 } 647 for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) { 648 le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp))); 649 } 650 if ( ToRecv & 1 ) { 651 rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp)); 652 } 653 tk_nin += ToRecv; 654 tk_rawcc += ToRecv; 655 tp->t_rawcc += ToRecv; 656 ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq); 657 ttwakeup(tp); 658 } else { 659 while (ToRecv) { 660 if(tp->t_state & TS_TBLOCK) { 661 break; 662 } 663 ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); 664 spl = spltty(); 665 ttyld_rint(tp, ch); 666 splx(spl); 667 ToRecv--; 668 } 669 } 670 } 671} 672 673static void rp_handle_port(struct rp_port *rp) 674{ 675 CHANNEL_t *cp; 676 struct tty *tp; 677 unsigned int IntMask, ChanStatus; 678 679 if(!rp) 680 return; 681 682 cp = &rp->rp_channel; 683 tp = rp->rp_tty; 684 IntMask = sGetChanIntID(cp); 685 IntMask = IntMask & rp->rp_intmask; 686 ChanStatus = sGetChanStatus(cp); 687 if(IntMask & RXF_TRIG) 688 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 689 rp_do_receive(rp, tp, cp, ChanStatus); 690 } 691 if(IntMask & DELTA_CD) { 692 if(ChanStatus & CD_ACT) { 693 if(!(tp->t_state & TS_CARR_ON) ) { 694 (void)ttyld_modem(tp, 1); 695 } 696 } else { 697 if((tp->t_state & TS_CARR_ON)) { 698 (void)ttyld_modem(tp, 0); 699 if(ttyld_modem(tp, 0) == 0) { 700 rpclose(tp); 701 } 702 } 703 } 704 } 705/* oldcts = rp->rp_cts; 706 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 707 if(oldcts != rp->rp_cts) { 708 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 709 } 710*/ 711} 712 713static void rp_do_poll(void *not_used) 714{ 715 CONTROLLER_t *ctl; 716 struct rp_port *rp; 717 struct tty *tp; 718 int unit, aiop, ch, line, count; 719 unsigned char CtlMask, AiopMask; 720 721 for(unit = 0; unit < rp_ndevs; unit++) { 722 rp = rp_addr(unit); 723 ctl = rp->rp_ctlp; 724 CtlMask = ctl->ctlmask(ctl); 725 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 726 if(CtlMask & 1) { 727 AiopMask = sGetAiopIntStatus(ctl, aiop); 728 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 729 if(AiopMask & 1) { 730 line = (unit << 5) | (aiop << 3) | ch; 731 rp = rp_table(line); 732 rp_handle_port(rp); 733 } 734 } 735 } 736 } 737 738 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 739 line++, rp++) { 740 tp = rp->rp_tty; 741 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 742 count = sGetTxCnt(&rp->rp_channel); 743 if(count == 0) 744 tp->t_state &= ~(TS_BUSY); 745 if(!(tp->t_state & TS_TTSTOP) && 746 (count <= rp->rp_restart)) { 747 ttyld_start(tp); 748 } 749 } 750 } 751 } 752 if(rp_num_ports_open) 753 rp_callout_handle = timeout(rp_do_poll, 754 (void *)NULL, POLL_INTERVAL); 755} 756 757int 758rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) 759{ 760 int oldspl, unit; 761 int num_chan; 762 int aiop, chan, port; 763 int ChanStatus, line, count; 764 int retval; 765 struct rp_port *rp; 766 struct tty *tp; 767 768 unit = device_get_unit(ctlp->dev); 769 770 printf("RocketPort%d (Version %s) %d ports.\n", unit, 771 RocketPortVersion, num_ports); 772 rp_num_ports[unit] = num_ports; 773 callout_handle_init(&rp_callout_handle); 774 775 ctlp->rp = rp = (struct rp_port *) 776 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); 777 if (rp == NULL) { 778 device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); 779 retval = ENOMEM; 780 goto nogo; 781 } 782 783 count = unit * 32; /* board times max ports per card SG */ 784 785 bzero(rp, sizeof(struct rp_port) * num_ports); 786 oldspl = spltty(); 787 rp_addr(unit) = rp; 788 splx(oldspl); 789 790 port = 0; 791 for(aiop=0; aiop < num_aiops; aiop++) { 792 num_chan = sGetAiopNumChan(ctlp, aiop); 793 for(chan=0; chan < num_chan; chan++, port++, rp++) { 794 tp = rp->rp_tty = ttyalloc(); 795 tp->t_sc = rp; 796 tp->t_param = rpparam; 797 tp->t_oproc = rpstart; 798 tp->t_stop = rpstop; 799 tp->t_break = rpbreak; 800 tp->t_modem = rpmodem; 801 tp->t_close = rpclose; 802 tp->t_open = rpopen; 803 tp->t_ififosize = 512; 804 tp->t_ispeedwat = (speed_t)-1; 805 tp->t_ospeedwat = (speed_t)-1; 806 rp->rp_port = port; 807 rp->rp_ctlp = ctlp; 808 rp->rp_unit = unit; 809 rp->rp_chan = chan; 810 rp->rp_aiop = aiop; 811 812 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 813 DELTA_CD | DELTA_CTS | DELTA_DSR; 814#ifdef notdef 815 ChanStatus = sGetChanStatus(&rp->rp_channel); 816#endif /* notdef */ 817 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 818 device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", 819 unit, aiop, chan); 820 retval = ENXIO; 821 goto nogo; 822 } 823 ChanStatus = sGetChanStatus(&rp->rp_channel); 824 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 825 line = (unit << 5) | (aiop << 3) | chan; 826 rp_table(line) = rp; 827 ttycreate(tp, TS_CALLOUT, "R%r%r", unit, port); 828 } 829 } 830 831 rp_ndevs++; 832 return (0); 833 834nogo: 835 rp_releaseresource(ctlp); 836 837 return (retval); 838} 839 840void 841rp_releaseresource(CONTROLLER_t *ctlp) 842{ 843 int i, s, unit; 844 struct rp_port *rp; 845 846 847 unit = device_get_unit(ctlp->dev); 848 if (rp_addr(unit) != NULL) { 849 for (i = 0; i < rp_num_ports[unit]; i++) { 850 rp = rp_addr(unit) + i; 851 ttyfree(rp->rp_tty); 852 } 853 } 854 855 if (ctlp->rp != NULL) { 856 s = spltty(); 857 for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) 858 if (p_rp_addr[i] == ctlp->rp) 859 p_rp_addr[i] = NULL; 860 for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) 861 if (p_rp_table[i] == ctlp->rp) 862 p_rp_table[i] = NULL; 863 splx(s); 864 free(ctlp->rp, M_DEVBUF); 865 ctlp->rp = NULL; 866 } 867} 868 869void 870rp_untimeout(void) 871{ 872 untimeout(rp_do_poll, (void *)NULL, rp_callout_handle); 873} 874 875static int 876rpopen(struct tty *tp, struct cdev *dev) 877{ 878 struct rp_port *rp; 879 int oldspl, flags; 880 unsigned int IntMask, ChanStatus; 881 882 rp = dev->si_drv1; 883 884 oldspl = spltty(); 885 886 flags = 0; 887 flags |= SET_RTS; 888 flags |= SET_DTR; 889 rp->rp_channel.TxControl[3] = 890 ((rp->rp_channel.TxControl[3] 891 & ~(SET_RTS | SET_DTR)) | flags); 892 rp_writech4(&rp->rp_channel,_INDX_ADDR, 893 le32dec(rp->rp_channel.TxControl)); 894 sSetRxTrigger(&rp->rp_channel, TRIG_1); 895 sDisRxStatusMode(&rp->rp_channel); 896 sFlushRxFIFO(&rp->rp_channel); 897 sFlushTxFIFO(&rp->rp_channel); 898 899 sEnInterrupts(&rp->rp_channel, 900 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 901 sSetRxTrigger(&rp->rp_channel, TRIG_1); 902 903 sDisRxStatusMode(&rp->rp_channel); 904 sClrTxXOFF(&rp->rp_channel); 905 906/* sDisRTSFlowCtl(&rp->rp_channel); 907 sDisCTSFlowCtl(&rp->rp_channel); 908*/ 909 sDisTxSoftFlowCtl(&rp->rp_channel); 910 911 sStartRxProcessor(&rp->rp_channel); 912 913 sEnRxFIFO(&rp->rp_channel); 914 sEnTransmit(&rp->rp_channel); 915 916/* sSetDTR(&rp->rp_channel); 917 sSetRTS(&rp->rp_channel); 918*/ 919 920 rp_num_ports_open++; 921 922 IntMask = sGetChanIntID(&rp->rp_channel); 923 IntMask = IntMask & rp->rp_intmask; 924 ChanStatus = sGetChanStatus(&rp->rp_channel); 925 926 if(rp_num_ports_open == 1) 927 rp_callout_handle = timeout(rp_do_poll, 928 (void *)NULL, POLL_INTERVAL); 929 930 device_busy(rp->rp_ctlp->dev); 931 return(0); 932} 933 934static void 935rpclose(struct tty *tp) 936{ 937 struct rp_port *rp; 938 CHANNEL_t *cp; 939 940 rp = tp->t_sc; 941 cp = &rp->rp_channel; 942 943 sFlushRxFIFO(cp); 944 sFlushTxFIFO(cp); 945 sDisTransmit(cp); 946 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 947 sDisRTSFlowCtl(cp); 948 sDisCTSFlowCtl(cp); 949 sDisTxSoftFlowCtl(cp); 950 sClrTxXOFF(cp); 951 952 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) { 953 sClrDTR(cp); 954 } 955 if(ISCALLOUT(tp->t_dev)) { 956 sClrDTR(cp); 957 } 958 tp->t_actout = FALSE; 959 wakeup(&tp->t_actout); 960 wakeup(TSA_CARR_ON(tp)); 961 device_unbusy(rp->rp_ctlp->dev); 962} 963 964static void 965rpbreak(struct tty *tp, int sig) 966{ 967 struct rp_port *rp; 968 969 rp = tp->t_sc; 970 if (sig) { 971 sSendBreak(&rp->rp_channel); 972 } else { 973 sClrBreak(&rp->rp_channel); 974 } 975} 976 977static int 978rpmodem(struct tty *tp, int sigon, int sigoff) 979{ 980 struct rp_port *rp; 981 int i, j, k; 982 983 rp = tp->t_sc; 984 if (sigon != 0 || sigoff != 0) { 985 i = j = 0; 986 if (sigon & SER_DTR) 987 i = SET_DTR; 988 if (sigoff & SER_DTR) 989 j = SET_DTR; 990 if (sigon & SER_RTS) 991 i = SET_RTS; 992 if (sigoff & SER_RTS) 993 j = SET_RTS; 994 rp->rp_channel.TxControl[3] &= ~i; 995 rp->rp_channel.TxControl[3] |= j; 996 rp_writech4(&rp->rp_channel,_INDX_ADDR, 997 le32dec(rp->rp_channel.TxControl)); 998 } else { 999 i = sGetChanStatusLo(&rp->rp_channel); 1000 j = rp->rp_channel.TxControl[3]; 1001 k = 0; 1002 if (j & SET_DTR) 1003 k |= SER_DTR; 1004 if (j & SET_RTS) 1005 k |= SER_RTS; 1006 if (i & CD_ACT) 1007 k |= SER_DCD; 1008 if (i & DSR_ACT) 1009 k |= SER_DSR; 1010 if (i & CTS_ACT) 1011 k |= SER_CTS; 1012 return(k); 1013 } 1014 return (0); 1015} 1016 1017static struct speedtab baud_table[] = { 1018 {B0, 0}, {B50, BRD50}, {B75, BRD75}, 1019 {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, 1020 {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, 1021 {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, 1022 {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, 1023 {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, 1024 {B57600, BRD57600}, {B76800, BRD76800}, 1025 {B115200, BRD115200}, {B230400, BRD230400}, 1026 {-1, -1} 1027}; 1028 1029static int 1030rpparam(tp, t) 1031 struct tty *tp; 1032 struct termios *t; 1033{ 1034 struct rp_port *rp; 1035 CHANNEL_t *cp; 1036 int oldspl, cflag, iflag, oflag, lflag; 1037 int ospeed; 1038#ifdef RPCLOCAL 1039 int devshift; 1040#endif 1041 1042 1043 rp = tp->t_sc; 1044 cp = &rp->rp_channel; 1045 oldspl = spltty(); 1046 1047 cflag = t->c_cflag; 1048#ifdef RPCLOCAL 1049 devshift = umynor / 32; 1050 devshift = 1 << devshift; 1051 if ( devshift & RPCLOCAL ) { 1052 cflag |= CLOCAL; 1053 } 1054#endif 1055 iflag = t->c_iflag; 1056 oflag = t->c_oflag; 1057 lflag = t->c_lflag; 1058 1059 ospeed = ttspeedtab(t->c_ispeed, baud_table); 1060 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) 1061 return(EINVAL); 1062 1063 tp->t_ispeed = t->c_ispeed; 1064 tp->t_ospeed = t->c_ospeed; 1065 tp->t_cflag = cflag; 1066 tp->t_iflag = iflag; 1067 tp->t_oflag = oflag; 1068 tp->t_lflag = lflag; 1069 1070 if(t->c_ospeed == 0) { 1071 sClrDTR(cp); 1072 return(0); 1073 } 1074 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; 1075 1076 /* Set baud rate ----- we only pay attention to ispeed */ 1077 sSetDTR(cp); 1078 sSetRTS(cp); 1079 sSetBaud(cp, ospeed); 1080 1081 if(cflag & CSTOPB) { 1082 sSetStop2(cp); 1083 } else { 1084 sSetStop1(cp); 1085 } 1086 1087 if(cflag & PARENB) { 1088 sEnParity(cp); 1089 if(cflag & PARODD) { 1090 sSetOddParity(cp); 1091 } else { 1092 sSetEvenParity(cp); 1093 } 1094 } 1095 else { 1096 sDisParity(cp); 1097 } 1098 if((cflag & CSIZE) == CS8) { 1099 sSetData8(cp); 1100 rp->rp_imask = 0xFF; 1101 } else { 1102 sSetData7(cp); 1103 rp->rp_imask = 0x7F; 1104 } 1105 1106 if(iflag & ISTRIP) { 1107 rp->rp_imask &= 0x7F; 1108 } 1109 1110 if(cflag & CLOCAL) { 1111 rp->rp_intmask &= ~DELTA_CD; 1112 } else { 1113 rp->rp_intmask |= DELTA_CD; 1114 } 1115 1116 /* Put flow control stuff here */ 1117 1118 if(cflag & CCTS_OFLOW) { 1119 sEnCTSFlowCtl(cp); 1120 } else { 1121 sDisCTSFlowCtl(cp); 1122 } 1123 1124 if(cflag & CRTS_IFLOW) { 1125 rp->rp_rts_iflow = 1; 1126 } else { 1127 rp->rp_rts_iflow = 0; 1128 } 1129 1130 if(cflag & CRTS_IFLOW) { 1131 sEnRTSFlowCtl(cp); 1132 } else { 1133 sDisRTSFlowCtl(cp); 1134 } 1135 ttyldoptim(tp); 1136 1137 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { 1138 tp->t_state |= TS_CARR_ON; 1139 wakeup(TSA_CARR_ON(tp)); 1140 } 1141 1142/* tp->t_state |= TS_CAN_BYPASS_L_RINT; 1143 flags = rp->rp_channel.TxControl[3]; 1144 if(flags & SET_DTR) 1145 else 1146 if(flags & SET_RTS) 1147 else 1148*/ 1149 splx(oldspl); 1150 1151 return(0); 1152} 1153 1154static void 1155rpstart(tp) 1156 struct tty *tp; 1157{ 1158 struct rp_port *rp; 1159 CHANNEL_t *cp; 1160 struct clist *qp; 1161 char flags; 1162 int spl, xmit_fifo_room; 1163 int i, count, wcount; 1164 1165 1166 rp = tp->t_sc; 1167 cp = &rp->rp_channel; 1168 flags = rp->rp_channel.TxControl[3]; 1169 spl = spltty(); 1170 1171 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1172 ttwwakeup(tp); 1173 splx(spl); 1174 return; 1175 } 1176 if(rp->rp_xmit_stopped) { 1177 sEnTransmit(cp); 1178 rp->rp_xmit_stopped = 0; 1179 } 1180 count = sGetTxCnt(cp); 1181 1182 if(tp->t_outq.c_cc == 0) { 1183 if((tp->t_state & TS_BUSY) && (count == 0)) { 1184 tp->t_state &= ~TS_BUSY; 1185 } 1186 ttwwakeup(tp); 1187 splx(spl); 1188 return; 1189 } 1190 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); 1191 qp = &tp->t_outq; 1192 if(xmit_fifo_room > 0 && qp->c_cc > 0) { 1193 tp->t_state |= TS_BUSY; 1194 count = q_to_b( qp, rp->TxBuf, xmit_fifo_room ); 1195 for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) { 1196 rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i)); 1197 } 1198 if ( count & 1 ) { 1199 rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); 1200 } 1201 } 1202 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; 1203 1204 ttwwakeup(tp); 1205 splx(spl); 1206} 1207 1208static 1209void 1210rpstop(tp, flag) 1211 register struct tty *tp; 1212 int flag; 1213{ 1214 struct rp_port *rp; 1215 CHANNEL_t *cp; 1216 int spl; 1217 1218 rp = tp->t_sc; 1219 cp = &rp->rp_channel; 1220 1221 spl = spltty(); 1222 1223 if(tp->t_state & TS_BUSY) { 1224 if((tp->t_state&TS_TTSTOP) == 0) { 1225 sFlushTxFIFO(cp); 1226 } else { 1227 if(rp->rp_xmit_stopped == 0) { 1228 sDisTransmit(cp); 1229 rp->rp_xmit_stopped = 1; 1230 } 1231 } 1232 } 1233 splx(spl); 1234 rpstart(tp); 1235} 1236