rp.c revision 28987
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 * rp.c - for RocketPort FreeBSD 35 */ 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/fcntl.h> 40#include <sys/tty.h> 41#include <sys/proc.h> 42#include <sys/conf.h> 43#include <sys/kernel.h> 44#include <sys/malloc.h> 45 46#include <i386/isa/isa_device.h> 47 48#include <pci/pcivar.h> 49 50#define ROCKET_C 51#include <i386/isa/rpreg.h> 52#include <i386/isa/rpvar.h> 53 54#ifndef TRUE 55#define TRUE 1 56#endif 57 58#ifndef FALSE 59#define FALSE 0 60#endif 61 62Byte_t RData[RDATASIZE] = 63{ 64 0x00, 0x09, 0xf6, 0x82, 65 0x02, 0x09, 0x86, 0xfb, 66 0x04, 0x09, 0x00, 0x0a, 67 0x06, 0x09, 0x01, 0x0a, 68 0x08, 0x09, 0x8a, 0x13, 69 0x0a, 0x09, 0xc5, 0x11, 70 0x0c, 0x09, 0x86, 0x85, 71 0x0e, 0x09, 0x20, 0x0a, 72 0x10, 0x09, 0x21, 0x0a, 73 0x12, 0x09, 0x41, 0xff, 74 0x14, 0x09, 0x82, 0x00, 75 0x16, 0x09, 0x82, 0x7b, 76 0x18, 0x09, 0x8a, 0x7d, 77 0x1a, 0x09, 0x88, 0x81, 78 0x1c, 0x09, 0x86, 0x7a, 79 0x1e, 0x09, 0x84, 0x81, 80 0x20, 0x09, 0x82, 0x7c, 81 0x22, 0x09, 0x0a, 0x0a 82}; 83 84Byte_t RRegData[RREGDATASIZE]= 85{ 86 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ 87 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ 88 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ 89 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ 90 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ 91 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ 92 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ 93 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ 94 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ 95 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ 96 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ 97 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ 98 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ 99}; 100 101CONTROLLER_T sController[CTL_SIZE] = 102{ 103 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, 104 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, 105 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, 106 {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}} 107}; 108 109#if 0 110/* IRQ number to MUDBAC register 2 mapping */ 111Byte_t sIRQMap[16] = 112{ 113 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 114}; 115#endif 116 117Byte_t sBitMapClrTbl[8] = 118{ 119 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f 120}; 121 122Byte_t sBitMapSetTbl[8] = 123{ 124 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 125}; 126 127/*************************************************************************** 128Function: sInitController 129Purpose: Initialization of controller global registers and controller 130 structure. 131Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize, 132 IRQNum,Frequency,PeriodicOnly) 133 CONTROLLER_T *CtlP; Ptr to controller structure 134 int CtlNum; Controller number 135 ByteIO_t MudbacIO; Mudbac base I/O address. 136 ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. 137 This list must be in the order the AIOPs will be found on the 138 controller. Once an AIOP in the list is not found, it is 139 assumed that there are no more AIOPs on the controller. 140 int AiopIOListSize; Number of addresses in AiopIOList 141 int IRQNum; Interrupt Request number. Can be any of the following: 142 0: Disable global interrupts 143 3: IRQ 3 144 4: IRQ 4 145 5: IRQ 5 146 9: IRQ 9 147 10: IRQ 10 148 11: IRQ 11 149 12: IRQ 12 150 15: IRQ 15 151 Byte_t Frequency: A flag identifying the frequency 152 of the periodic interrupt, can be any one of the following: 153 FREQ_DIS - periodic interrupt disabled 154 FREQ_137HZ - 137 Hertz 155 FREQ_69HZ - 69 Hertz 156 FREQ_34HZ - 34 Hertz 157 FREQ_17HZ - 17 Hertz 158 FREQ_9HZ - 9 Hertz 159 FREQ_4HZ - 4 Hertz 160 If IRQNum is set to 0 the Frequency parameter is 161 overidden, it is forced to a value of FREQ_DIS. 162 int PeriodicOnly: TRUE if all interrupts except the periodic 163 interrupt are to be blocked. 164 FALSE is both the periodic interrupt and 165 other channel interrupts are allowed. 166 If IRQNum is set to 0 the PeriodicOnly parameter is 167 overidden, it is forced to a value of FALSE. 168Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller 169 initialization failed. 170 171Comments: 172 If periodic interrupts are to be disabled but AIOP interrupts 173 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. 174 175 If interrupts are to be completely disabled set IRQNum to 0. 176 177 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an 178 invalid combination. 179 180 This function performs initialization of global interrupt modes, 181 but it does not actually enable global interrupts. To enable 182 and disable global interrupts use functions sEnGlobalInt() and 183 sDisGlobalInt(). Enabling of global interrupts is normally not 184 done until all other initializations are complete. 185 186 Even if interrupts are globally enabled, they must also be 187 individually enabled for each channel that is to generate 188 interrupts. 189 190Warnings: No range checking on any of the parameters is done. 191 192 No context switches are allowed while executing this function. 193 194 After this function all AIOPs on the controller are disabled, 195 they can be enabled with sEnAiop(). 196*/ 197int sInitController( CONTROLLER_T *CtlP, 198 int CtlNum, 199 ByteIO_t MudbacIO, 200 ByteIO_t *AiopIOList, 201 int AiopIOListSize, 202 int IRQNum, 203 Byte_t Frequency, 204 int PeriodicOnly) 205{ 206 int i; 207 ByteIO_t io; 208 209 CtlP->CtlNum = CtlNum; 210 CtlP->BusType = isISA; 211 CtlP->CtlID = CTLID_0001; /* controller release 1 */ 212 213 CtlP->MBaseIO = MudbacIO; 214 CtlP->MReg1IO = MudbacIO + 1; 215 CtlP->MReg2IO = MudbacIO + 2; 216 CtlP->MReg3IO = MudbacIO + 3; 217#if 1 218 CtlP->MReg2 = 0; /* interrupt disable */ 219 CtlP->MReg3 = 0; /* no periodic interrupts */ 220#else 221 if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */ 222 { 223 CtlP->MReg2 = 0; /* interrupt disable */ 224 CtlP->MReg3 = 0; /* no periodic interrupts */ 225 } 226 else 227 { 228 CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ 229 CtlP->MReg3 = Frequency; /* set frequency */ 230 if(PeriodicOnly) /* periodic interrupt only */ 231 { 232 CtlP->MReg3 |= PERIODIC_ONLY; 233 } 234 } 235#endif 236 sOutB(CtlP->MReg2IO,CtlP->MReg2); 237 sOutB(CtlP->MReg3IO,CtlP->MReg3); 238 sControllerEOI(CtlP); /* clear EOI if warm init */ 239 240 /* Init AIOPs */ 241 CtlP->NumAiop = 0; 242 for(i=0; i < AiopIOListSize; i++) 243 { 244 io = AiopIOList[i]; 245 CtlP->AiopIO[i] = (WordIO_t)io; 246 CtlP->AiopIntChanIO[i] = io + _INT_CHAN; 247 sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */ 248 sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */ 249 sEnAiop(CtlP,i); /* enable the AIOP */ 250 251 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ 252 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ 253 { 254 sDisAiop(CtlP,i); /* disable AIOP */ 255 break; /* done looking for AIOPs */ 256 } 257 258 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */ 259 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */ 260 sOutB(io + _INDX_DATA,CLOCK_PRESC); 261 CtlP->NumAiop++; /* bump count of AIOPs */ 262 sDisAiop(CtlP,i); /* disable AIOP */ 263 } 264 265 if(CtlP->NumAiop == 0) 266 return(-1); 267 else 268 return(CtlP->NumAiop); 269} 270 271int sPCIInitController( CONTROLLER_T *CtlP, 272 int CtlNum, 273 ByteIO_t *AiopIOList, 274 int AiopIOListSize, 275 int IRQNum, 276 Byte_t Frequency, 277 int PeriodicOnly) 278{ 279 int i; 280 ByteIO_t io; 281 282 CtlP->CtlNum = CtlNum; 283 CtlP->BusType = isPCI; 284 CtlP->CtlID = CTLID_0001; /* controller release 1 */ 285 CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC); 286 287 sPCIControllerEOI(CtlP); 288 289 /* Init AIOPs */ 290 CtlP->NumAiop = 0; 291 for(i=0; i < AiopIOListSize; i++) 292 { 293 io = AiopIOList[i]; 294 CtlP->AiopIO[i] = (WordIO_t)io; 295 CtlP->AiopIntChanIO[i] = io + _INT_CHAN; 296 297 CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ 298 if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ 299 { 300 break; /* done looking for AIOPs */ 301 } 302 303 CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */ 304 sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */ 305 sOutB(io + _INDX_DATA,CLOCK_PRESC); 306 CtlP->NumAiop++; /* bump count of AIOPs */ 307 } 308 309 if(CtlP->NumAiop == 0) 310 return(-1); 311 else 312 return(CtlP->NumAiop); 313} 314 315/*************************************************************************** 316Function: sReadAiopID 317Purpose: Read the AIOP idenfication number directly from an AIOP. 318Call: sReadAiopID(io) 319 ByteIO_t io: AIOP base I/O address 320Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X 321 is replace by an identifying number. 322 Flag AIOPID_NULL if no valid AIOP is found 323Warnings: No context switches are allowed while executing this function. 324 325*/ 326int sReadAiopID(ByteIO_t io) 327{ 328 Byte_t AiopID; /* ID byte from AIOP */ 329 330 sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */ 331 sOutB(io + _CMD_REG,0x0); 332 AiopID = sInB(io + _CHN_STAT0) & 0x07; 333 if(AiopID == 0x06) 334 return(1); 335 else /* AIOP does not exist */ 336 return(-1); 337} 338 339/*************************************************************************** 340Function: sReadAiopNumChan 341Purpose: Read the number of channels available in an AIOP directly from 342 an AIOP. 343Call: sReadAiopNumChan(io) 344 WordIO_t io: AIOP base I/O address 345Return: int: The number of channels available 346Comments: The number of channels is determined by write/reads from identical 347 offsets within the SRAM address spaces for channels 0 and 4. 348 If the channel 4 space is mirrored to channel 0 it is a 4 channel 349 AIOP, otherwise it is an 8 channel. 350Warnings: No context switches are allowed while executing this function. 351*/ 352int sReadAiopNumChan(WordIO_t io) 353{ 354 Word_t x; 355 356 sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ 357 sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */ 358 x = sInW(io + _INDX_DATA); 359 sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ 360 if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */ 361 return(8); 362 else 363 return(4); 364} 365 366/*************************************************************************** 367Function: sInitChan 368Purpose: Initialization of a channel and channel structure 369Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) 370 CONTROLLER_T *CtlP; Ptr to controller structure 371 CHANNEL_T *ChP; Ptr to channel structure 372 int AiopNum; AIOP number within controller 373 int ChanNum; Channel number within AIOP 374Return: int: TRUE if initialization succeeded, FALSE if it fails because channel 375 number exceeds number of channels available in AIOP. 376Comments: This function must be called before a channel can be used. 377Warnings: No range checking on any of the parameters is done. 378 379 No context switches are allowed while executing this function. 380*/ 381int sInitChan( CONTROLLER_T *CtlP, 382 CHANNEL_T *ChP, 383 int AiopNum, 384 int ChanNum) 385{ 386 int i; 387 WordIO_t AiopIO; 388 WordIO_t ChIOOff; 389 Byte_t *ChR; 390 Word_t ChOff; 391 static Byte_t R[4]; 392 393 if(ChanNum >= CtlP->AiopNumChan[AiopNum]) 394 return(FALSE); /* exceeds num chans in AIOP */ 395 396 /* Channel, AIOP, and controller identifiers */ 397 ChP->CtlP = CtlP; 398 ChP->ChanID = CtlP->AiopID[AiopNum]; 399 ChP->AiopNum = AiopNum; 400 ChP->ChanNum = ChanNum; 401 402 /* Global direct addresses */ 403 AiopIO = CtlP->AiopIO[AiopNum]; 404 ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG; 405 ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN; 406 ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK; 407 ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR; 408 ChP->IndexData = AiopIO + _INDX_DATA; 409 410 /* Channel direct addresses */ 411 ChIOOff = AiopIO + ChP->ChanNum * 2; 412 ChP->TxRxData = ChIOOff + _TD0; 413 ChP->ChanStat = ChIOOff + _CHN_STAT0; 414 ChP->TxRxCount = ChIOOff + _FIFO_CNT0; 415 ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0; 416 417 /* Initialize the channel from the RData array */ 418 for(i=0; i < RDATASIZE; i+=4) 419 { 420 R[0] = RData[i]; 421 R[1] = RData[i+1] + 0x10 * ChanNum; 422 R[2] = RData[i+2]; 423 R[3] = RData[i+3]; 424 sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0])); 425 } 426 427 ChR = ChP->R; 428 for(i=0; i < RREGDATASIZE; i+=4) 429 { 430 ChR[i] = RRegData[i]; 431 ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; 432 ChR[i+2] = RRegData[i+2]; 433 ChR[i+3] = RRegData[i+3]; 434 } 435 436 /* Indexed registers */ 437 ChOff = (Word_t)ChanNum * 0x1000; 438 439 ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); 440 ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); 441 ChP->BaudDiv[2] = (Byte_t)BRD9600; 442 ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); 443 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]); 444 445 ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); 446 ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); 447 ChP->TxControl[2] = 0; 448 ChP->TxControl[3] = 0; 449 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); 450 451 ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); 452 ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); 453 ChP->RxControl[2] = 0; 454 ChP->RxControl[3] = 0; 455 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); 456 457 ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); 458 ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); 459 ChP->TxEnables[2] = 0; 460 ChP->TxEnables[3] = 0; 461 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]); 462 463 ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); 464 ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); 465 ChP->TxCompare[2] = 0; 466 ChP->TxCompare[3] = 0; 467 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]); 468 469 ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); 470 ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); 471 ChP->TxReplace1[2] = 0; 472 ChP->TxReplace1[3] = 0; 473 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]); 474 475 ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); 476 ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); 477 ChP->TxReplace2[2] = 0; 478 ChP->TxReplace2[3] = 0; 479 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]); 480 481 ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; 482 ChP->TxFIFO = ChOff + _TX_FIFO; 483 484 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ 485 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ 486 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 487 sOutW(ChP->IndexData,0); 488 ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; 489 ChP->RxFIFO = ChOff + _RX_FIFO; 490 491 sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ 492 sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ 493 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 494 sOutW(ChP->IndexData,0); 495 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 496 sOutW(ChP->IndexData,0); 497 ChP->TxPrioCnt = ChOff + _TXP_CNT; 498 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt); 499 sOutB(ChP->IndexData,0); 500 ChP->TxPrioPtr = ChOff + _TXP_PNTR; 501 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr); 502 sOutB(ChP->IndexData,0); 503 ChP->TxPrioBuf = ChOff + _TXP_BUF; 504 sEnRxProcessor(ChP); /* start the Rx processor */ 505 506 return(TRUE); 507} 508 509/*************************************************************************** 510Function: sStopRxProcessor 511Purpose: Stop the receive processor from processing a channel. 512Call: sStopRxProcessor(ChP) 513 CHANNEL_T *ChP; Ptr to channel structure 514 515Comments: The receive processor can be started again with sStartRxProcessor(). 516 This function causes the receive processor to skip over the 517 stopped channel. It does not stop it from processing other channels. 518 519Warnings: No context switches are allowed while executing this function. 520 521 Do not leave the receive processor stopped for more than one 522 character time. 523 524 After calling this function a delay of 4 uS is required to ensure 525 that the receive processor is no longer processing this channel. 526*/ 527void sStopRxProcessor(CHANNEL_T *ChP) 528{ 529 Byte_t R[4]; 530 531 R[0] = ChP->R[0]; 532 R[1] = ChP->R[1]; 533 R[2] = 0x0a; 534 R[3] = ChP->R[3]; 535 sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]); 536} 537 538/*************************************************************************** 539Function: sFlushRxFIFO 540Purpose: Flush the Rx FIFO 541Call: sFlushRxFIFO(ChP) 542 CHANNEL_T *ChP; Ptr to channel structure 543Return: void 544Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 545 while it is being flushed the receive processor is stopped 546 and the transmitter is disabled. After these operations a 547 4 uS delay is done before clearing the pointers to allow 548 the receive processor to stop. These items are handled inside 549 this function. 550Warnings: No context switches are allowed while executing this function. 551*/ 552void sFlushRxFIFO(CHANNEL_T *ChP) 553{ 554 int i; 555 Byte_t Ch; /* channel number within AIOP */ 556 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ 557 558 if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ 559 return; /* don't need to flush */ 560 561 RxFIFOEnabled = FALSE; 562 if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ 563 { 564 RxFIFOEnabled = TRUE; 565 sDisRxFIFO(ChP); /* disable it */ 566 for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ 567 sInB(ChP->IntChan); /* depends on bus i/o timing */ 568 } 569 sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ 570 Ch = (Byte_t)sGetChanNum(ChP); 571 sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ 572 sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */ 573 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */ 574 sOutW(ChP->IndexData,0); 575 sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ 576 sOutW(ChP->IndexData,0); 577 if(RxFIFOEnabled) 578 sEnRxFIFO(ChP); /* enable Rx FIFO */ 579} 580 581/*************************************************************************** 582Function: sFlushTxFIFO 583Purpose: Flush the Tx FIFO 584Call: sFlushTxFIFO(ChP) 585 CHANNEL_T *ChP; Ptr to channel structure 586Return: void 587Comments: To prevent data from being enqueued or dequeued in the Tx FIFO 588 while it is being flushed the receive processor is stopped 589 and the transmitter is disabled. After these operations a 590 4 uS delay is done before clearing the pointers to allow 591 the receive processor to stop. These items are handled inside 592 this function. 593Warnings: No context switches are allowed while executing this function. 594*/ 595void sFlushTxFIFO(CHANNEL_T *ChP) 596{ 597 int i; 598 Byte_t Ch; /* channel number within AIOP */ 599 int TxEnabled; /* TRUE if transmitter enabled */ 600 601 if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ 602 return; /* don't need to flush */ 603 604 TxEnabled = FALSE; 605 if(ChP->TxControl[3] & TX_ENABLE) 606 { 607 TxEnabled = TRUE; 608 sDisTransmit(ChP); /* disable transmitter */ 609 } 610 sStopRxProcessor(ChP); /* stop Rx processor */ 611 for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ 612 sInB(ChP->IntChan); /* depends on bus i/o timing */ 613 Ch = (Byte_t)sGetChanNum(ChP); 614 sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ 615 sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */ 616 sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ 617 sOutW(ChP->IndexData,0); 618 if(TxEnabled) 619 sEnTransmit(ChP); /* enable transmitter */ 620 sStartRxProcessor(ChP); /* restart Rx processor */ 621} 622 623/*************************************************************************** 624Function: sWriteTxPrioByte 625Purpose: Write a byte of priority transmit data to a channel 626Call: sWriteTxPrioByte(ChP,Data) 627 CHANNEL_T *ChP; Ptr to channel structure 628 Byte_t Data; The transmit data byte 629 630Return: int: 1 if the bytes is successfully written, otherwise 0. 631 632Comments: The priority byte is transmitted before any data in the Tx FIFO. 633 634Warnings: No context switches are allowed while executing this function. 635*/ 636int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) 637{ 638 Byte_t DWBuf[4]; /* buffer for double word writes */ 639 Word_t *WordPtr; /* must be far because Win SS != DS */ 640 register DWordIO_t IndexAddr; 641 642 if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ 643 { 644 IndexAddr = ChP->IndexAddr; 645 sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */ 646 if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */ 647 return(0); /* nothing sent */ 648 649 WordPtr = (Word_t *)(&DWBuf[0]); 650 *WordPtr = ChP->TxPrioBuf; /* data byte address */ 651 652 DWBuf[2] = Data; /* data byte value */ 653 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */ 654 655 *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ 656 657 DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ 658 DWBuf[3] = 0; /* priority buffer pointer */ 659 sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */ 660 } 661 else /* write it to Tx FIFO */ 662 { 663 sWriteTxByte(sGetTxRxDataIO(ChP),Data); 664 } 665 return(1); /* 1 byte sent */ 666} 667 668/*************************************************************************** 669Function: sEnInterrupts 670Purpose: Enable one or more interrupts for a channel 671Call: sEnInterrupts(ChP,Flags) 672 CHANNEL_T *ChP; Ptr to channel structure 673 Word_t Flags: Interrupt enable flags, can be any combination 674 of the following flags: 675 TXINT_EN: Interrupt on Tx FIFO empty 676 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 677 sSetRxTrigger()) 678 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 679 MCINT_EN: Interrupt on modem input change 680 CHANINT_EN: Allow channel interrupt signal to the AIOP's 681 Interrupt Channel Register. 682Return: void 683Comments: If an interrupt enable flag is set in Flags, that interrupt will be 684 enabled. If an interrupt enable flag is not set in Flags, that 685 interrupt will not be changed. Interrupts can be disabled with 686 function sDisInterrupts(). 687 688 This function sets the appropriate bit for the channel in the AIOP's 689 Interrupt Mask Register if the CHANINT_EN flag is set. This allows 690 this channel's bit to be set in the AIOP's Interrupt Channel Register. 691 692 Interrupts must also be globally enabled before channel interrupts 693 will be passed on to the host. This is done with function 694 sEnGlobalInt(). 695 696 In some cases it may be desirable to disable interrupts globally but 697 enable channel interrupts. This would allow the global interrupt 698 status register to be used to determine which AIOPs need service. 699*/ 700void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) 701{ 702 Byte_t Mask; /* Interrupt Mask Register */ 703 704 ChP->RxControl[2] |= 705 ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 706 707 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); 708 709 ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); 710 711 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); 712 713 if(Flags & CHANINT_EN) 714 { 715 Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; 716 sOutB(ChP->IntMask,Mask); 717 } 718} 719 720/*************************************************************************** 721Function: sDisInterrupts 722Purpose: Disable one or more interrupts for a channel 723Call: sDisInterrupts(ChP,Flags) 724 CHANNEL_T *ChP; Ptr to channel structure 725 Word_t Flags: Interrupt flags, can be any combination 726 of the following flags: 727 TXINT_EN: Interrupt on Tx FIFO empty 728 RXINT_EN: Interrupt on Rx FIFO at trigger level (see 729 sSetRxTrigger()) 730 SRCINT_EN: Interrupt on SRC (Special Rx Condition) 731 MCINT_EN: Interrupt on modem input change 732 CHANINT_EN: Disable channel interrupt signal to the 733 AIOP's Interrupt Channel Register. 734Return: void 735Comments: If an interrupt flag is set in Flags, that interrupt will be 736 disabled. If an interrupt flag is not set in Flags, that 737 interrupt will not be changed. Interrupts can be enabled with 738 function sEnInterrupts(). 739 740 This function clears the appropriate bit for the channel in the AIOP's 741 Interrupt Mask Register if the CHANINT_EN flag is set. This blocks 742 this channel's bit from being set in the AIOP's Interrupt Channel 743 Register. 744*/ 745void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) 746{ 747 Byte_t Mask; /* Interrupt Mask Register */ 748 749 ChP->RxControl[2] &= 750 ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); 751 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); 752 ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); 753 sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); 754 755 if(Flags & CHANINT_EN) 756 { 757 Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; 758 sOutB(ChP->IntMask,Mask); 759 } 760} 761 762/********************************************************************* 763 Begin FreeBsd-specific driver code 764**********************************************************************/ 765 766static int rpprobe __P((struct isa_device *)); 767static int rpattach __P((struct isa_device *)); 768 769static char* rp_pciprobe(pcici_t tag, pcidi_t type); 770static void rp_pciattach(pcici_t tag, int unit); 771static u_long rp_pcicount; 772 773struct pci_device rp_pcidevice = { 774 "rp", 775 rp_pciprobe, 776 rp_pciattach, 777 &rp_pcicount, 778 NULL 779}; 780 781DATA_SET (pcidevice_set, rp_pcidevice); 782 783static timeout_t rpdtrwakeup; 784 785struct isa_driver rpdriver = { 786 rpprobe, rpattach, "rp" 787 }; 788 789#define CDEV_MAJOR 20 790 791static char driver_name[] = "rp"; 792 793static d_open_t rpopen; 794static d_close_t rpclose; 795static d_read_t rpread; 796static d_write_t rpwrite; 797static d_ioctl_t rpioctl; 798static d_stop_t rpstop; 799static d_devtotty_t rpdevtotty; 800 801static struct cdevsw rp_cdevsw = 802 { rpopen, rpclose, rpread, rpwrite, 803 rpioctl, rpstop, noreset, rpdevtotty, 804 ttselect, nommap, NULL, driver_name, 805 NULL, -1}; 806 807static int rp_controller_port = 0; 808static int rp_num_ports_open = 0; 809static int rp_timeout; 810static int ndevs = 0; 811static int minor_to_unit[128]; 812static struct tty rp_tty[128]; 813 814static int rp_num_ports[4]; /* Number of ports on each controller */ 815 816#define _INLINE_ inline 817#define POLL_INTERVAL 1 818 819#define CALLOUT_MASK 0x80 820#define CONTROL_MASK 0x60 821#define CONTROL_INIT_STATE 0x20 822#define CONTROL_LOCK_STATE 0x40 823#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev)) 824#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 825#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK) 826#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK) 827#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK) 828 829#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) 830#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) 831#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) 832 833static struct rp_port *p_rp_addr[4]; 834static struct rp_port *p_rp_table[MAX_RP_PORTS]; 835#define rp_addr(unit) (p_rp_addr[unit]) 836#define rp_table(port) (p_rp_table[port]) 837 838/* 839 * The top-level routines begin here 840 */ 841 842int rpselect __P((dev_t, int, struct proc *)); 843 844static int rpparam __P((struct tty *, struct termios *)); 845static void rpstart __P((struct tty *)); 846static void rphardclose __P((struct rp_port *)); 847#define rpmap nomap 848#define rpreset noreset 849#define rpstrategy nostrategy 850static void rp_disc_optim __P((struct tty *tp, struct termios *t, 851 struct rp_port *rp)); 852 853static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp, 854 CHANNEL_t *cp, unsigned int ChanStatus) 855{ 856 int spl; 857 unsigned int CharNStat; 858 int ToRecv, wRecv, ch; 859 860 ToRecv = sGetRxCnt(cp); 861 if(ToRecv == 0) 862 return; 863 864/* If status indicates there are errored characters in the 865 FIFO, then enter status mode (a word in FIFO holds 866 characters and status) 867*/ 868 869 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 870 if(!(ChanStatus & STATMODE)) { 871 ChanStatus |= STATMODE; 872 sEnRxStatusMode(cp); 873 } 874 } 875/* 876 if we previously entered status mode then read down the 877 FIFO one word at a time, pulling apart the character and 878 the status. Update error counters depending on status. 879*/ 880 if(ChanStatus & STATMODE) { 881 while(ToRecv) { 882 if(tp->t_state & TS_TBLOCK) { 883 break; 884 } 885 CharNStat = sInW(sGetTxRxDataIO(cp)); 886 ch = CharNStat & 0xff; 887 888 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 889 ch |= TTY_FE; 890 else if (CharNStat & STMPARITYH) 891 ch |= TTY_PE; 892 else if (CharNStat & STMRCVROVRH) 893 rp->rp_overflows++; 894 895 (*linesw[tp->t_line].l_rint)(ch, tp); 896 ToRecv--; 897 } 898/* 899 After emtying FIFO in status mode, turn off status mode 900*/ 901 902 if(sGetRxCnt(cp) == 0) 903 sDisRxStatusMode(cp); 904 } 905 else { 906 while (ToRecv) { 907 if(tp->t_state & TS_TBLOCK) { 908 break; 909 } 910 ch = (u_char) sInB(sGetTxRxDataIO(cp)); 911 spl = spltty(); 912 (*linesw[tp->t_line].l_rint)(ch, tp); 913 splx(spl); 914 ToRecv--; 915 } 916 } 917} 918 919static _INLINE_ void rp_handle_port(struct rp_port *rp) 920{ 921 CHANNEL_t *cp; 922 struct tty *tp; 923 unsigned int IntMask, ChanStatus; 924 int oldcts, ToRecv; 925 926 if(!rp) 927 return; 928 929 cp = &rp->rp_channel; 930 tp = rp->rp_tty; 931 IntMask = sGetChanIntID(cp); 932 IntMask = IntMask & rp->rp_intmask; 933 ChanStatus = sGetChanStatus(cp); 934 if(IntMask & RXF_TRIG) 935 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 936 rp_do_receive(rp, tp, cp, ChanStatus); 937 } 938 if(IntMask & DELTA_CD) { 939 if(ChanStatus & CD_ACT) { 940 if(!(tp->t_state & TS_CARR_ON) ) { 941 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 942 } 943 } else { 944 if((tp->t_state & TS_CARR_ON)) { 945 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 946 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 947 rphardclose(rp); 948 } 949 } 950 } 951 } 952/* oldcts = rp->rp_cts; 953 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 954 if(oldcts != rp->rp_cts) { 955 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 956 } 957*/ 958} 959 960static void rp_do_poll(void *not_used) 961{ 962 CONTROLLER_t *ctl; 963 struct rp_port *rp; 964 struct tty *tp; 965 int unit, aiop, ch, line, count; 966 unsigned char CtlMask, AiopMask; 967 968 for(unit = 0; unit <= ndevs; unit++) { 969 rp = rp_addr(unit); 970 ctl = rp->rp_ctlp; 971 if(ctl->BusType == isPCI) 972 CtlMask = sPCIGetControllerIntStatus(ctl); 973 else 974 CtlMask = sGetControllerIntStatus(ctl); 975 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 976 if(CtlMask & 1) { 977 AiopMask = sGetAiopIntStatus(ctl, aiop); 978 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 979 if(AiopMask & 1) { 980 line = (unit << 5) | (aiop << 3) | ch; 981 rp = rp_table(line); 982 rp_handle_port(rp); 983 } 984 } 985 } 986 } 987 988 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 989 line++, rp++) { 990 tp = rp->rp_tty; 991 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 992 count = sGetTxCnt(&rp->rp_channel); 993 if(count == 0) 994 tp->t_state &= ~(TS_BUSY); 995 if(!(tp->t_state & TS_TTSTOP) && 996 (count <= rp->rp_restart)) { 997 (*linesw[tp->t_line].l_start)(tp); 998 } 999 } 1000 } 1001 } 1002 if(rp_num_ports_open) 1003 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1004} 1005 1006static char* 1007rp_pciprobe(pcici_t tag, pcidi_t type) 1008{ 1009 int vendor_id; 1010 1011 vendor_id = type & 0xffff; 1012 switch(vendor_id) 1013 case 0x11fe: 1014 return("rp"); 1015 return(NULL); 1016} 1017 1018static 1019int 1020rpprobe(dev) 1021struct isa_device *dev; 1022{ 1023 struct isa_device *idev; 1024 int controller, unit; 1025 int i, aiop, num_aiops; 1026 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1027 CONTROLLER_t *ctlp; 1028 1029 unit = dev->id_unit; 1030 if (dev->id_unit >= 4) { 1031 printf("rpprobe: unit number %d invalid.\n", dev->id_unit); 1032 return 1; 1033 } 1034 printf("probing for RocketPort(ISA) unit %d\n", unit); 1035 if (rp_controller_port) 1036 controller = rp_controller_port; 1037 else { 1038 controller = dev->id_iobase + 0x40; 1039 } 1040 1041 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++) 1042 aiopio[aiop]= dev->id_iobase + (aiop * 0x400); 1043 1044 ctlp = sCtlNumToCtlPtr(dev->id_unit); 1045 num_aiops = sInitController(ctlp, dev->id_unit, 1046 controller + ((unit-rp_pcicount)*0x400), 1047 aiopio, MAX_AIOPS_PER_BOARD, 0, 1048 FREQ_DIS, 0); 1049 if (num_aiops <= 0) { 1050 printf("board%d init failed\n", unit); 1051 return 0; 1052 } 1053 1054 if (rp_controller_port) { 1055 dev->id_msize = 64; 1056 } else { 1057 dev->id_msize = 68; 1058 rp_controller_port = controller; 1059 } 1060 1061 dev->id_irq = 0; 1062 1063 return 1; 1064} 1065 1066static void 1067rp_pciattach(pcici_t tag, int unit) 1068{ 1069 dev_t rp_dev; 1070 int success, rpmajor, oldspl; 1071 u_short iobase; 1072 int num_ports, num_chan, num_aiops; 1073 int aiop, chan, port; 1074 int ChanStatus, line, i, count; 1075 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1076 struct rp_port *rp; 1077 struct tty *tty; 1078 CONTROLLER_t *ctlp; 1079 char status; 1080 1081 success = pci_map_port(tag, 0x10, &iobase); 1082 if(!success) 1083 printf("ioaddr mapping failed for RocketPort(PCI)\n"); 1084 1085 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) 1086 aiopio[aiop] = iobase + (aiop * 0x40); 1087 1088 ctlp = sCtlNumToCtlPtr(unit); 1089 num_aiops = sPCIInitController(ctlp, unit, 1090 aiopio, MAX_AIOPS_PER_BOARD, 0, 1091 FREQ_DIS, 0); 1092 1093 num_ports = 0; 1094 for(aiop=0; aiop < num_aiops; aiop++) { 1095 sResetAiopByNum(ctlp, aiop); 1096 num_ports += sGetAiopNumChan(ctlp, aiop); 1097 } 1098 printf("RocketPort%d = %d ports\n", unit, num_ports); 1099 rp_num_ports[unit] = num_ports; 1100 1101 rp = (struct rp_port *) 1102 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); 1103 if(rp == 0) { 1104 printf("rp_attach: Could not malloc rp_ports structures\n"); 1105 return; 1106 } 1107 1108 count = 0; 1109 for(i=0;i<unit;i++) 1110 count += rp_num_ports[i]; 1111 for(i=count;i < (count + rp_num_ports[unit]);i++) 1112 minor_to_unit[i] = unit; 1113 1114 bzero(rp, sizeof(struct rp_port) * num_ports); 1115 tty = (struct tty *) 1116 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT); 1117 if(tty == 0) { 1118 printf("rp_attach: Could not malloc tty structures\n"); 1119 return; 1120 } 1121 bzero(tty, sizeof(struct tty) * num_ports); 1122 1123 oldspl = spltty(); 1124 rp_addr(unit) = rp; 1125 splx(oldspl); 1126 1127 rp_dev = makedev(CDEV_MAJOR, unit); 1128 cdevsw_add(&rp_dev, &rp_cdevsw, NULL); 1129 1130 port = 0; 1131 for(aiop=0; aiop < num_aiops; aiop++) { 1132 num_chan = sGetAiopNumChan(ctlp, aiop); 1133 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { 1134 rp->rp_tty = tty; 1135 rp->rp_port = port; 1136 rp->rp_ctlp = ctlp; 1137 rp->rp_unit = unit; 1138 rp->rp_chan = chan; 1139 rp->rp_aiop = aiop; 1140 1141 tty->t_line = 0; 1142 /* tty->t_termios = deftermios; 1143 */ 1144 rp->dtr_wait = 3 * hz; 1145 rp->it_in.c_iflag = 0; 1146 rp->it_in.c_oflag = 0; 1147 rp->it_in.c_cflag = TTYDEF_CFLAG; 1148 rp->it_in.c_lflag = 0; 1149 termioschars(&rp->it_in); 1150 /* termioschars(&tty->t_termios); 1151 */ 1152 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 1153 rp->it_out = rp->it_in; 1154 1155 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 1156 DELTA_CD | DELTA_CTS | DELTA_DSR; 1157 ChanStatus = sGetChanStatus(&rp->rp_channel); 1158 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 1159 printf("RocketPort sInitChan(%d, %d, %d) failed 1160 \n", unit, aiop, chan); 1161 return; 1162 } 1163 ChanStatus = sGetChanStatus(&rp->rp_channel); 1164 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 1165 line = (unit << 5) | (aiop << 3) | chan; 1166 rp_table(line) = rp; 1167/* devfs_add_devswf(&rp_cdevsw, 1168 port, DV_CHR, UID_ROOT, GID_WHEEL, 0600, 1169 "ttyR%n", port); 1170 devfs_add_devswf(&rp_cdevsw, 1171 port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT, 1172 GID_WHEEL, 0600, "ttyRi%n", port); 1173*/ 1174 } 1175 } 1176} 1177 1178static 1179int 1180rpattach(dev) 1181struct isa_device *dev; 1182{ 1183 struct isa_device *idev; 1184 dev_t rp_dev; 1185 int iobase, unit, rpmajor, oldspl; 1186 int num_ports, num_chan, num_aiops; 1187 int aiop, chan, port; 1188 int ChanStatus, line, i, count; 1189 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1190 struct rp_port *rp; 1191 struct tty *tty; 1192 CONTROLLER_t *ctlp; 1193 char status; 1194 1195 iobase = dev->id_iobase; 1196 unit = dev->id_unit; 1197 ndevs = unit; 1198 1199 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) 1200 aiopio[aiop] = iobase + (aiop * 0x400); 1201 1202 ctlp = sCtlNumToCtlPtr(unit); 1203 num_aiops = sInitController(ctlp, unit, 1204 rp_controller_port + ((unit-rp_pcicount) * 0x400), 1205 aiopio, MAX_AIOPS_PER_BOARD, 0, 1206 FREQ_DIS, 0); 1207 1208 num_ports = 0; 1209 for(aiop=0; aiop < num_aiops; aiop++) { 1210 sResetAiopByNum(ctlp, aiop); 1211 sEnAiop(ctlp, aiop); 1212 num_ports += sGetAiopNumChan(ctlp, aiop); 1213 } 1214 printf("RocketPort%d = %d ports\n", unit, num_ports); 1215 rp_num_ports[unit] = num_ports; 1216 1217 rp = (struct rp_port *) 1218 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); 1219 if(rp == 0) { 1220 printf("rp_attach: Could not malloc rp_ports structures\n"); 1221 return(0); 1222 } 1223 1224 count = 0; 1225 for(i=0;i<unit;i++) 1226 count += rp_num_ports[i]; 1227 for(i=count;i < (count + rp_num_ports[unit]);i++) 1228 minor_to_unit[i] = unit; 1229 1230 bzero(rp, sizeof(struct rp_port) * num_ports); 1231 tty = (struct tty *) 1232 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT); 1233 if(tty == 0) { 1234 printf("rp_attach: Could not malloc tty structures\n"); 1235 return(0); 1236 } 1237 bzero(tty, sizeof(struct tty) * num_ports); 1238 1239 oldspl = spltty(); 1240 rp_addr(unit) = rp; 1241 splx(oldspl); 1242 1243 rp_dev = makedev(CDEV_MAJOR, unit); 1244 cdevsw_add(&rp_dev, &rp_cdevsw, NULL); 1245 1246 port = 0; 1247 for(aiop=0; aiop < num_aiops; aiop++) { 1248 num_chan = sGetAiopNumChan(ctlp, aiop); 1249 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { 1250 rp->rp_tty = tty; 1251 rp->rp_port = port; 1252 rp->rp_ctlp = ctlp; 1253 rp->rp_unit = unit; 1254 rp->rp_chan = chan; 1255 rp->rp_aiop = aiop; 1256 1257 tty->t_line = 0; 1258 /* tty->t_termios = deftermios; 1259 */ 1260 rp->dtr_wait = 3 * hz; 1261 rp->it_in.c_iflag = 0; 1262 rp->it_in.c_oflag = 0; 1263 rp->it_in.c_cflag = TTYDEF_CFLAG; 1264 rp->it_in.c_lflag = 0; 1265 termioschars(&rp->it_in); 1266 /* termioschars(&tty->t_termios); 1267 */ 1268 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 1269 rp->it_out = rp->it_in; 1270 1271 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 1272 DELTA_CD | DELTA_CTS | DELTA_DSR; 1273 ChanStatus = sGetChanStatus(&rp->rp_channel); 1274 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 1275 printf("RocketPort sInitChan(%d, %d, %d) failed 1276 \n", unit, aiop, chan); 1277 return(0); 1278 } 1279 ChanStatus = sGetChanStatus(&rp->rp_channel); 1280 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 1281 line = (unit << 5) | (aiop << 3) | chan; 1282 rp_table(line) = rp; 1283 } 1284 } 1285 1286 idev = find_isadev(isa_devtab_tty, &rpdriver, 1287 RP_MPMASTER(dev) + rp_pcicount); 1288 if(idev == NULL) { 1289 printf("rp%d: master device %d not configured\n", 1290 dev->id_unit, RP_MPMASTER(dev)); 1291 } 1292/* printf("COOL!! Device is found!!\n"); 1293 for(rpmajor=0;rpmajor<nchrdev;rpmajor++) 1294 if(cdevsw[rpmajor].d_open == rpopen) 1295 printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor); 1296*/ 1297 return(1); 1298} 1299 1300int 1301rpopen(dev, flag, mode, p) 1302 dev_t dev; 1303 int flag, mode; 1304 struct proc *p; 1305{ 1306 struct rp_port *rp; 1307 int unit, i, port, mynor, flags; 1308 struct tty *tp; 1309 int oldspl, error; 1310 unsigned int IntMask, ChanStatus; 1311 1312 mynor = MINOR_MAGIC(dev); 1313 unit = minor_to_unit[mynor]; 1314 if(IS_CONTROL(dev)) 1315 return(0); 1316 port = mynor; 1317 for(i=0;i<unit;i++) 1318 port -= rp_num_ports[i]; 1319 rp = rp_addr(unit) + port; 1320/* rp->rp_tty = &rp_tty[rp->rp_port]; 1321*/ 1322 tp = rp->rp_tty; 1323 1324 oldspl = spltty(); 1325 1326open_top: 1327 while(rp->state & ~SET_DTR) { 1328 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0); 1329 if(error != 0) 1330 goto out; 1331 } 1332 1333 if(tp->t_state & TS_ISOPEN) { 1334 if(IS_CALLOUT(dev)) { 1335 if(!rp->active_out) { 1336 error = EBUSY; 1337 goto out; 1338 } 1339 } else { 1340 if(rp->active_out) { 1341 if(flag & O_NONBLOCK) { 1342 error = EBUSY; 1343 goto out; 1344 } 1345 error = tsleep(&rp->active_out, 1346 TTIPRI | PCATCH, "rpbi", 0); 1347 if(error != 0) 1348 goto out; 1349 goto open_top; 1350 } 1351 } 1352 if(tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 1353 splx(oldspl); 1354 return(EBUSY); 1355 } 1356 } 1357 else { 1358 tp->t_dev = dev; 1359 tp->t_param = rpparam; 1360 tp->t_oproc = rpstart; 1361 tp->t_line = 0; 1362 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; 1363 flags = 0; 1364 flags |= SET_RTS; 1365 flags |= SET_DTR; 1366 rp->rp_channel.TxControl[3] = 1367 ((rp->rp_channel.TxControl[3] 1368 & ~(SET_RTS | SET_DTR)) | flags); 1369 sOutDW(rp->rp_channel.IndexAddr, 1370 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1371 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1372 sDisRxStatusMode(&rp->rp_channel); 1373 sFlushRxFIFO(&rp->rp_channel); 1374 sFlushTxFIFO(&rp->rp_channel); 1375 1376 sEnInterrupts(&rp->rp_channel, 1377 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 1378 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1379 1380 sDisRxStatusMode(&rp->rp_channel); 1381 sClrTxXOFF(&rp->rp_channel); 1382 1383/* sDisRTSFlowCtl(&rp->rp_channel); 1384 sDisCTSFlowCtl(&rp->rp_channel); 1385*/ 1386 sDisTxSoftFlowCtl(&rp->rp_channel); 1387 1388 sStartRxProcessor(&rp->rp_channel); 1389 1390 sEnRxFIFO(&rp->rp_channel); 1391 sEnTransmit(&rp->rp_channel); 1392 1393/* sSetDTR(&rp->rp_channel); 1394 sSetRTS(&rp->rp_channel); 1395*/ 1396 1397 ++rp->wopeners; 1398 error = rpparam(tp, &tp->t_termios); 1399 --rp->wopeners; 1400 if(error != 0) { 1401 splx(oldspl); 1402 return(error); 1403 } 1404 1405 ttsetwater(tp); 1406 1407 rp_num_ports_open++; 1408 1409 IntMask = sGetChanIntID(&rp->rp_channel); 1410 IntMask = IntMask & rp->rp_intmask; 1411 ChanStatus = sGetChanStatus(&rp->rp_channel); 1412 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { 1413 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { 1414 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 1415 } 1416 } 1417 1418 if(rp_num_ports_open == 1) 1419 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1420 1421 } 1422 1423 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 1424 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { 1425 ++rp->wopeners; 1426 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, 1427 "rpdcd", 0); 1428 --rp->wopeners; 1429 if(error != 0) 1430 goto out; 1431 goto open_top; 1432 } 1433 error = (*linesw[tp->t_line].l_open)(dev, tp); 1434 1435 rp_disc_optim(tp, &tp->t_termios, rp); 1436 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) 1437 rp->active_out = TRUE; 1438 1439/* if(rp_num_ports_open == 1) 1440 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1441*/ 1442out: 1443 splx(oldspl); 1444 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { 1445 rphardclose(rp); 1446 } 1447 return(error); 1448} 1449 1450int 1451rpclose(dev, flag, mode, p) 1452 dev_t dev; 1453 int flag, mode; 1454 struct proc *p; 1455{ 1456 int oldspl, unit, mynor, port, status, i; 1457 struct rp_port *rp; 1458 struct tty *tp; 1459 CHANNEL_t *cp; 1460 1461 mynor = MINOR_MAGIC(dev); 1462 unit = 0; 1463 unit = minor_to_unit[mynor]; 1464 port = mynor; 1465 if(IS_CONTROL(dev)) 1466 return(0); 1467 for(i=0;i<unit;i++) 1468 port -= rp_num_ports[i]; 1469 rp = rp_addr(unit) + port; 1470 cp = &rp->rp_channel; 1471 tp = rp->rp_tty; 1472 1473 oldspl = spltty(); 1474 (*linesw[tp->t_line].l_close)(tp, flag); 1475 rp_disc_optim(tp, &tp->t_termios, rp); 1476 rpstop(tp, FREAD | FWRITE); 1477 rphardclose(rp); 1478 1479 tp->t_state &= ~TS_BUSY; 1480 ttyclose(tp); 1481 1482 splx(oldspl); 1483 1484 return(0); 1485} 1486 1487static void 1488rphardclose(struct rp_port *rp) 1489{ 1490 int status, oldspl, mynor; 1491 struct tty *tp; 1492 CHANNEL_t *cp; 1493 1494 cp = &rp->rp_channel; 1495 tp = rp->rp_tty; 1496 mynor = MINOR_MAGIC(tp->t_dev); 1497 1498 sFlushRxFIFO(cp); 1499 sFlushTxFIFO(cp); 1500 sDisTransmit(cp); 1501 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 1502 sDisRTSFlowCtl(cp); 1503 sDisCTSFlowCtl(cp); 1504 sDisTxSoftFlowCtl(cp); 1505 sClrTxXOFF(cp); 1506 1507 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { 1508 sClrDTR(cp); 1509 } 1510 if(IS_CALLOUT(tp->t_dev)) { 1511 sClrDTR(cp); 1512 } 1513 if(rp->dtr_wait != 0) { 1514 timeout(rpdtrwakeup, rp, rp->dtr_wait); 1515 rp->state |= ~SET_DTR; 1516 } 1517 1518 rp->active_out = FALSE; 1519 wakeup(&rp->active_out); 1520 wakeup(TSA_CARR_ON(tp)); 1521} 1522 1523static 1524int 1525rpread(dev, uio, flag) 1526 dev_t dev; 1527 struct uio *uio; 1528 int flag; 1529{ 1530 struct rp_port *rp; 1531 struct tty *tp; 1532 int unit, i, mynor, port, error = 0; 1533 1534 mynor = MINOR_MAGIC(dev); 1535 if(IS_CONTROL(dev)) 1536 return(ENODEV); 1537 unit = 0; 1538 unit = minor_to_unit[mynor]; 1539 port = mynor; 1540 for(i=0;i<unit;i++) 1541 port -= rp_num_ports[i]; 1542 rp = rp_addr(unit) + port; 1543 tp = rp->rp_tty; 1544 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 1545 return(error); 1546} 1547 1548static 1549int 1550rpwrite(dev, uio, flag) 1551 dev_t dev; 1552 struct uio *uio; 1553 int flag; 1554{ 1555 struct rp_port *rp; 1556 struct tty *tp; 1557 int unit, i, mynor, port, error = 0; 1558 1559 mynor = MINOR_MAGIC(dev); 1560 if(IS_CONTROL(dev)) 1561 return(ENODEV); 1562 unit = 0; 1563 unit = minor_to_unit[mynor]; 1564 port = mynor; 1565 for(i=0;i<unit;i++) 1566 port -= rp_num_ports[i]; 1567 rp = rp_addr(unit) + port; 1568 tp = rp->rp_tty; 1569 while(rp->rp_disable_writes) { 1570 rp->rp_waiting = 1; 1571 if(error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, 1572 "rp_write", 0)) { 1573 return(error); 1574 } 1575 } 1576 1577 error = (*linesw[tp->t_line].l_write)(tp, uio, flag); 1578 return error; 1579} 1580 1581static void 1582rpdtrwakeup(void *chan) 1583{ 1584 struct rp_port *rp; 1585 1586 rp = (struct rp_port *)chan; 1587 rp->state &= SET_DTR; 1588 wakeup(&rp->dtr_wait); 1589} 1590 1591int 1592rpioctl(dev, cmd, data, flag, p) 1593 dev_t dev; 1594 int cmd; 1595 caddr_t data; 1596 int flag; 1597 struct proc *p; 1598{ 1599 struct rp_port *rp; 1600 CHANNEL_t *cp; 1601 struct tty *tp; 1602 int unit, mynor, port; 1603 int oldspl, cflag, iflag, oflag, lflag; 1604 int i, error = 0; 1605 char status; 1606 int arg, flags, result, ChanStatus; 1607 int oldcmd; 1608 struct termios term, *t; 1609 1610 mynor = MINOR_MAGIC(dev); 1611 unit = minor_to_unit[mynor]; 1612 port = mynor; 1613 for(i=0;i<unit;i++) 1614 port -= rp_num_ports[i]; 1615 rp = rp_addr(unit) + port; 1616 1617 if(IS_CONTROL(dev)) { 1618 struct termios *ct; 1619 1620 switch (IS_CONTROL(dev)) { 1621 case CONTROL_INIT_STATE: 1622 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in; 1623 break; 1624 case CONTROL_LOCK_STATE: 1625 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in; 1626 break; 1627 default: 1628 return(ENODEV); /* /dev/nodev */ 1629 } 1630 switch (cmd) { 1631 case TIOCSETA: 1632 error = suser(p->p_ucred, &p->p_acflag); 1633 if(error != 0) 1634 return(error); 1635 *ct = *(struct termios *)data; 1636 return(0); 1637 case TIOCGETA: 1638 *(struct termios *)data = *ct; 1639 return(0); 1640 case TIOCGETD: 1641 *(int *)data = TTYDISC; 1642 return(0); 1643 case TIOCGWINSZ: 1644 bzero(data, sizeof(struct winsize)); 1645 return(0); 1646 default: 1647 return(ENOTTY); 1648 } 1649 } 1650 1651 tp = rp->rp_tty; 1652 cp = &rp->rp_channel; 1653 1654#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1655 term = tp->t_termios; 1656 oldcmd = cmd; 1657 error = ttsetcompat(tp, &cmd, data, &term); 1658 if(error != 0) 1659 return(error); 1660 if(cmd != oldcmd) { 1661 data = (caddr_t)&term; 1662 } 1663#endif 1664 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) { 1665 int cc; 1666 struct termios *dt = (struct termios *)data; 1667 struct termios *lt = IS_CALLOUT(dev) 1668 ? &rp->lt_out : &rp->lt_in; 1669 1670 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1671 | (dt->c_iflag & ~lt->c_iflag); 1672 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1673 | (dt->c_oflag & ~lt->c_oflag); 1674 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1675 | (dt->c_cflag & ~lt->c_cflag); 1676 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1677 | (dt->c_lflag & ~lt->c_lflag); 1678 for(cc = 0; cc < NCCS; ++cc) 1679 if(lt->c_cc[cc] = tp->t_cc[cc]) 1680 dt->c_cc[cc] = tp->t_cc[cc]; 1681 if(lt->c_ispeed != 0) 1682 dt->c_ispeed = tp->t_ispeed; 1683 if(lt->c_ospeed != 0) 1684 dt->c_ospeed = tp->t_ospeed; 1685 } 1686 1687 t = &tp->t_termios; 1688 1689 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1690 if(error >= 0) { 1691 return(error); 1692 } 1693 oldspl = spltty(); 1694 1695 flags = rp->rp_channel.TxControl[3]; 1696 1697 error = ttioctl(tp, cmd, data, flag); 1698 flags = rp->rp_channel.TxControl[3]; 1699 rp_disc_optim(tp, &tp->t_termios, rp); 1700 if(error >= 0) { 1701 splx(oldspl); 1702 return(error); 1703 } 1704 switch(cmd) { 1705 case TIOCSBRK: 1706 sSendBreak(&rp->rp_channel); 1707 break; 1708 1709 case TIOCCBRK: 1710 sClrBreak(&rp->rp_channel); 1711 break; 1712 1713 case TIOCSDTR: 1714 sSetDTR(&rp->rp_channel); 1715 sSetRTS(&rp->rp_channel); 1716 break; 1717 1718 case TIOCCDTR: 1719 sClrDTR(&rp->rp_channel); 1720 break; 1721 1722 case TIOCMSET: 1723 arg = *(int *) data; 1724 flags = 0; 1725 if(arg & TIOCM_RTS) 1726 flags |= SET_RTS; 1727 if(arg & TIOCM_DTR) 1728 flags |= SET_DTR; 1729 rp->rp_channel.TxControl[3] = 1730 ((rp->rp_channel.TxControl[3] 1731 & ~(SET_RTS | SET_DTR)) | flags); 1732 sOutDW(rp->rp_channel.IndexAddr, 1733 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1734 break; 1735 case TIOCMBIS: 1736 arg = *(int *) data; 1737 flags = 0; 1738 if(arg & TIOCM_RTS) 1739 flags |= SET_RTS; 1740 if(arg & TIOCM_DTR) 1741 flags |= SET_DTR; 1742 rp->rp_channel.TxControl[3] |= flags; 1743 sOutDW(rp->rp_channel.IndexAddr, 1744 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1745 break; 1746 case TIOCMBIC: 1747 arg = *(int *) data; 1748 flags = 0; 1749 if(arg & TIOCM_RTS) 1750 flags |= SET_RTS; 1751 if(arg & TIOCM_DTR) 1752 flags |= SET_DTR; 1753 rp->rp_channel.TxControl[3] &= ~flags; 1754 sOutDW(rp->rp_channel.IndexAddr, 1755 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1756 break; 1757 1758 1759 case TIOCMGET: 1760 ChanStatus = sGetChanStatusLo(&rp->rp_channel); 1761 flags = rp->rp_channel.TxControl[3]; 1762 result = TIOCM_LE; /* always on while open for some reason */ 1763 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0) 1764 | ((flags & SET_RTS) ? TIOCM_RTS : 0) 1765 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) 1766 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) 1767 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0)); 1768 1769 if(rp->rp_channel.RxControl[2] & RTSFC_EN) 1770 { 1771 result |= TIOCM_RTS; 1772 } 1773 1774 *(int *)data = result; 1775 break; 1776 case TIOCMSDTRWAIT: 1777 error = suser(p->p_ucred, &p->p_acflag); 1778 if(error != 0) { 1779 splx(oldspl); 1780 return(error); 1781 } 1782 rp->dtr_wait = *(int *)data * hz/100; 1783 break; 1784 case TIOCMGDTRWAIT: 1785 *(int *)data = rp->dtr_wait * 100/hz; 1786 break; 1787 default: 1788 splx(oldspl); 1789 return ENOTTY; 1790 } 1791 splx(oldspl); 1792 return(0); 1793} 1794 1795static struct speedtab baud_table[] = { 1796 B0, 0, B50, BRD50, B75, BRD75, 1797 B110, BRD110, B134, BRD134, B150, BRD150, 1798 B200, BRD200, B300, BRD300, B600, BRD600, 1799 B1200, BRD1200, B1800, BRD1800, B2400, BRD2400, 1800 B4800, BRD4800, B9600, BRD9600, B19200, BRD19200, 1801 B38400, BRD38400, B7200, BRD7200, B14400, BRD14400, 1802 B57600, BRD57600, B76800, BRD76800, 1803 B115200, BRD115200, B230400, BRD230400, 1804 -1, -1 1805}; 1806 1807static int 1808rpparam(tp, t) 1809 struct tty *tp; 1810 struct termios *t; 1811{ 1812 struct rp_port *rp; 1813 CHANNEL_t *cp; 1814 int unit, i, mynor, port; 1815 int oldspl, cflag, iflag, oflag, lflag; 1816 int ospeed, flags; 1817 1818 mynor = MINOR_MAGIC(tp->t_dev); 1819 unit = minor_to_unit[mynor]; 1820 port = mynor; 1821 for(i=0;i<unit;i++) 1822 port -= rp_num_ports[i]; 1823 rp = rp_addr(unit) + port; 1824 cp = &rp->rp_channel; 1825 oldspl = spltty(); 1826 1827 cflag = t->c_cflag; 1828 iflag = t->c_iflag; 1829 oflag = t->c_oflag; 1830 lflag = t->c_lflag; 1831 1832 ospeed = ttspeedtab(t->c_ispeed, baud_table); 1833 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) 1834 return(EINVAL); 1835 1836 tp->t_ispeed = t->c_ispeed; 1837 tp->t_ospeed = t->c_ospeed; 1838 tp->t_cflag = cflag; 1839 tp->t_iflag = iflag; 1840 tp->t_oflag = oflag; 1841 tp->t_lflag = lflag; 1842 1843 if(t->c_ospeed == 0) { 1844 sClrDTR(cp); 1845 return(0); 1846 } 1847 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; 1848 1849 /* Set baud rate ----- we only pay attention to ispeed */ 1850 sSetDTR(cp); 1851 sSetRTS(cp); 1852 sSetBaud(cp, ospeed); 1853 1854 if(cflag & CSTOPB) { 1855 sSetStop2(cp); 1856 } else { 1857 sSetStop1(cp); 1858 } 1859 1860 if(cflag & PARENB) { 1861 sEnParity(cp); 1862 if(cflag & PARODD) { 1863 sSetOddParity(cp); 1864 } else { 1865 sSetEvenParity(cp); 1866 } 1867 } 1868 else { 1869 sDisParity(cp); 1870 } 1871 if((cflag & CSIZE) == CS8) { 1872 sSetData8(cp); 1873 rp->rp_imask = 0xFF; 1874 } else { 1875 sSetData7(cp); 1876 rp->rp_imask = 0x7F; 1877 } 1878 1879 if(iflag & ISTRIP) { 1880 rp->rp_imask &= 0x7F; 1881 } 1882 1883 if(cflag & CLOCAL) { 1884 rp->rp_intmask &= ~DELTA_CD; 1885 } else { 1886 rp->rp_intmask |= DELTA_CD; 1887 } 1888 1889 /* Put flow control stuff here */ 1890 1891 if(cflag & CCTS_OFLOW) { 1892 sEnCTSFlowCtl(cp); 1893 } else { 1894 sDisCTSFlowCtl(cp); 1895 } 1896 1897 if(cflag & CRTS_IFLOW) { 1898 rp->rp_rts_iflow = 1; 1899 } else { 1900 rp->rp_rts_iflow = 0; 1901 } 1902 1903 if(cflag & CRTS_IFLOW) { 1904 sEnRTSFlowCtl(cp); 1905 } else { 1906 sDisRTSFlowCtl(cp); 1907 } 1908 rp_disc_optim(tp, t, rp); 1909 1910 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { 1911 tp->t_state |= TS_CARR_ON; 1912 wakeup(TSA_CARR_ON(tp)); 1913 } 1914 1915/* tp->t_state |= TS_CAN_BYPASS_L_RINT; 1916 flags = rp->rp_channel.TxControl[3]; 1917 if(flags & SET_DTR) 1918 else 1919 if(flags & SET_RTS) 1920 else 1921*/ 1922 splx(oldspl); 1923 1924 return(0); 1925} 1926 1927static void 1928rp_disc_optim(tp, t, rp) 1929struct tty *tp; 1930struct termios *t; 1931struct rp_port *rp; 1932{ 1933 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 1934 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 1935 &&(!(t->c_iflag & PARMRK) 1936 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 1937 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 1938 && linesw[tp->t_line].l_rint == ttyinput) 1939 tp->t_state |= TS_CAN_BYPASS_L_RINT; 1940 else 1941 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 1942} 1943 1944static void 1945rpstart(tp) 1946 struct tty *tp; 1947{ 1948 struct rp_port *rp; 1949 CHANNEL_t *cp; 1950 struct clist *qp; 1951 int unit, i, mynor, port; 1952 char status, ch, flags; 1953 int spl, xmit_fifo_room; 1954 int count, ToRecv; 1955 1956 mynor = MINOR_MAGIC(tp->t_dev); 1957 unit = minor_to_unit[mynor]; 1958 port = mynor; 1959 for(i=0;i<unit;i++) 1960 port -= rp_num_ports[i]; 1961 rp = rp_addr(unit) + port; 1962 cp = &rp->rp_channel; 1963 flags = rp->rp_channel.TxControl[3]; 1964 spl = spltty(); 1965 1966 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1967 ttwwakeup(tp); 1968 splx(spl); 1969 return; 1970 } 1971 if(rp->rp_xmit_stopped) { 1972 sEnTransmit(cp); 1973 rp->rp_xmit_stopped = 0; 1974 } 1975 count = sGetTxCnt(cp); 1976 1977 if(tp->t_outq.c_cc <= tp->t_lowat) { 1978 if(tp->t_state & TS_SO_OLOWAT) { 1979 tp->t_state &= ~TS_SO_OLOWAT; 1980 wakeup(TSA_CARR_ON(tp)); 1981 } 1982 selwakeup(&tp->t_wsel); 1983 } 1984 if(tp->t_outq.c_cc == 0) { 1985 if((tp->t_state & TS_BUSY) && (count == 0)) { 1986 tp->t_state &= ~TS_BUSY; 1987 } 1988 ttwwakeup(tp); 1989 splx(spl); 1990 return; 1991 } 1992/* 1993 if((tp->t_state & TS_BUSY) && count == 0) 1994 tp->t_state &= ~TS_BUSY; 1995 1996 if(tp->t_outq.c_cc <= tp->t_lowat) 1997 ttyowake(tp); 1998 1999*/ 2000 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); 2001 qp = &tp->t_outq; 2002 count = 0; 2003 if(xmit_fifo_room > 0 && qp->c_cc > 0) { 2004 tp->t_state |= TS_BUSY; 2005 } 2006 while(xmit_fifo_room > 0 && qp->c_cc > 0) { 2007 ch = getc(qp); 2008 sOutB(sGetTxRxDataIO(cp), ch); 2009 xmit_fifo_room--; 2010 count++; 2011 } 2012 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; 2013 2014 ttwwakeup(tp); 2015 splx(spl); 2016} 2017 2018static 2019void 2020rpstop(tp, flag) 2021 register struct tty *tp; 2022 int flag; 2023{ 2024 struct rp_port *rp; 2025 CHANNEL_t *cp; 2026 struct clist *qp; 2027 int unit, mynor, port; 2028 char status, ch; 2029 int spl, xmit_fifo_room; 2030 int i, count; 2031 2032 mynor = MINOR_MAGIC(tp->t_dev); 2033 unit = minor_to_unit[mynor]; 2034 port = mynor; 2035 for(i=0;i<unit;i++) 2036 port -= rp_num_ports[i]; 2037 rp = rp_addr(unit) + port; 2038 cp = &rp->rp_channel; 2039 2040 spl = spltty(); 2041 2042 if(tp->t_state & TS_BUSY) { 2043 if((tp->t_state&TS_TTSTOP) == 0) { 2044 sFlushTxFIFO(cp); 2045 } else { 2046 if(rp->rp_xmit_stopped == 0) { 2047 sDisTransmit(cp); 2048 rp->rp_xmit_stopped = 1; 2049 } 2050 } 2051 } 2052 splx(spl); 2053 rpstart(tp); 2054} 2055 2056int 2057rpselect(dev, flag, p) 2058 dev_t dev; 2059 int flag; 2060 struct proc *p; 2061{ 2062 return(0); 2063} 2064 2065struct tty * 2066rpdevtotty(dev_t dev) 2067{ 2068 struct rp_port *rp; 2069 int unit, i, port, mynor; 2070 2071 mynor = MINOR_MAGIC(dev); 2072 if(IS_CONTROL(dev)) 2073 return(NULL); 2074 unit = minor_to_unit[mynor]; 2075 port = mynor; 2076 for(i=0;i<unit;i++) 2077 port -= rp_num_ports[i]; 2078 rp = rp_addr(unit) + port; 2079 return(rp->rp_tty); 2080} 2081