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