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