rp.c revision 47640
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: rp.c,v 1.27 1999/05/30 16:52:22 phk Exp $ 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 785COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice); 786 787static timeout_t rpdtrwakeup; 788 789struct isa_driver rpdriver = { 790 rpprobe, rpattach, "rp" 791 }; 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 803#define CDEV_MAJOR 81 804static struct cdevsw rp_cdevsw = { 805 /* open */ rpopen, 806 /* close */ rpclose, 807 /* read */ rpread, 808 /* write */ rpwrite, 809 /* ioctl */ rpioctl, 810 /* stop */ rpstop, 811 /* reset */ noreset, 812 /* devtotty */ rpdevtotty, 813 /* poll */ ttpoll, 814 /* mmap */ nommap, 815 /* strategy */ nostrategy, 816 /* name */ driver_name, 817 /* parms */ noparms, 818 /* maj */ CDEV_MAJOR, 819 /* dump */ nodump, 820 /* psize */ nopsize, 821 /* flags */ D_TTY, 822 /* maxio */ 0, 823 /* bmaj */ -1 824}; 825 826static int rp_controller_port = 0; 827static int rp_num_ports_open = 0; 828static int ndevs = 0; 829static int minor_to_unit[128]; 830#if 0 831static struct tty rp_tty[128]; 832#endif 833 834static int rp_num_ports[4]; /* Number of ports on each controller */ 835 836#define _INLINE_ __inline 837#define POLL_INTERVAL 1 838 839#define CALLOUT_MASK 0x80 840#define CONTROL_MASK 0x60 841#define CONTROL_INIT_STATE 0x20 842#define CONTROL_LOCK_STATE 0x40 843#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev)) 844#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 845#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK) 846#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK) 847#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK) 848 849#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) 850#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) 851#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) 852 853static struct rp_port *p_rp_addr[4]; 854static struct rp_port *p_rp_table[MAX_RP_PORTS]; 855#define rp_addr(unit) (p_rp_addr[unit]) 856#define rp_table(port) (p_rp_table[port]) 857 858/* 859 * The top-level routines begin here 860 */ 861 862int rpselect __P((dev_t, int, struct proc *)); 863 864static int rpparam __P((struct tty *, struct termios *)); 865static void rpstart __P((struct tty *)); 866static void rphardclose __P((struct rp_port *)); 867#define rpmap nomap 868#define rpreset noreset 869#define rpstrategy nostrategy 870static void rp_disc_optim __P((struct tty *tp, struct termios *t, 871 struct rp_port *rp)); 872 873static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp, 874 CHANNEL_t *cp, unsigned int ChanStatus) 875{ 876 int spl; 877 unsigned int CharNStat; 878 int ToRecv, ch; 879 880 ToRecv = sGetRxCnt(cp); 881 if(ToRecv == 0) 882 return; 883 884/* If status indicates there are errored characters in the 885 FIFO, then enter status mode (a word in FIFO holds 886 characters and status) 887*/ 888 889 if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { 890 if(!(ChanStatus & STATMODE)) { 891 ChanStatus |= STATMODE; 892 sEnRxStatusMode(cp); 893 } 894 } 895/* 896 if we previously entered status mode then read down the 897 FIFO one word at a time, pulling apart the character and 898 the status. Update error counters depending on status. 899*/ 900 if(ChanStatus & STATMODE) { 901 while(ToRecv) { 902 if(tp->t_state & TS_TBLOCK) { 903 break; 904 } 905 CharNStat = sInW(sGetTxRxDataIO(cp)); 906 ch = CharNStat & 0xff; 907 908 if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) 909 ch |= TTY_FE; 910 else if (CharNStat & STMPARITYH) 911 ch |= TTY_PE; 912 else if (CharNStat & STMRCVROVRH) 913 rp->rp_overflows++; 914 915 (*linesw[tp->t_line].l_rint)(ch, tp); 916 ToRecv--; 917 } 918/* 919 After emtying FIFO in status mode, turn off status mode 920*/ 921 922 if(sGetRxCnt(cp) == 0) 923 sDisRxStatusMode(cp); 924 } 925 else { 926 while (ToRecv) { 927 if(tp->t_state & TS_TBLOCK) { 928 break; 929 } 930 ch = (u_char) sInB(sGetTxRxDataIO(cp)); 931 spl = spltty(); 932 (*linesw[tp->t_line].l_rint)(ch, tp); 933 splx(spl); 934 ToRecv--; 935 } 936 } 937} 938 939static _INLINE_ void rp_handle_port(struct rp_port *rp) 940{ 941 CHANNEL_t *cp; 942 struct tty *tp; 943 unsigned int IntMask, ChanStatus; 944 /* int oldcts; */ 945 946 if(!rp) 947 return; 948 949 cp = &rp->rp_channel; 950 tp = rp->rp_tty; 951 IntMask = sGetChanIntID(cp); 952 IntMask = IntMask & rp->rp_intmask; 953 ChanStatus = sGetChanStatus(cp); 954 if(IntMask & RXF_TRIG) 955 if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { 956 rp_do_receive(rp, tp, cp, ChanStatus); 957 } 958 if(IntMask & DELTA_CD) { 959 if(ChanStatus & CD_ACT) { 960 if(!(tp->t_state & TS_CARR_ON) ) { 961 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 962 } 963 } else { 964 if((tp->t_state & TS_CARR_ON)) { 965 (void)(*linesw[tp->t_line].l_modem)(tp, 0); 966 if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { 967 rphardclose(rp); 968 } 969 } 970 } 971 } 972/* oldcts = rp->rp_cts; 973 rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); 974 if(oldcts != rp->rp_cts) { 975 printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); 976 } 977*/ 978} 979 980static void rp_do_poll(void *not_used) 981{ 982 CONTROLLER_t *ctl; 983 struct rp_port *rp; 984 struct tty *tp; 985 int unit, aiop, ch, line, count; 986 unsigned char CtlMask, AiopMask; 987 988 for(unit = 0; unit <= ndevs; unit++) { 989 rp = rp_addr(unit); 990 ctl = rp->rp_ctlp; 991 if(ctl->BusType == isPCI) 992 CtlMask = sPCIGetControllerIntStatus(ctl); 993 else 994 CtlMask = sGetControllerIntStatus(ctl); 995 for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { 996 if(CtlMask & 1) { 997 AiopMask = sGetAiopIntStatus(ctl, aiop); 998 for(ch = 0; AiopMask; AiopMask >>=1, ch++) { 999 if(AiopMask & 1) { 1000 line = (unit << 5) | (aiop << 3) | ch; 1001 rp = rp_table(line); 1002 rp_handle_port(rp); 1003 } 1004 } 1005 } 1006 } 1007 1008 for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; 1009 line++, rp++) { 1010 tp = rp->rp_tty; 1011 if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { 1012 count = sGetTxCnt(&rp->rp_channel); 1013 if(count == 0) 1014 tp->t_state &= ~(TS_BUSY); 1015 if(!(tp->t_state & TS_TTSTOP) && 1016 (count <= rp->rp_restart)) { 1017 (*linesw[tp->t_line].l_start)(tp); 1018 } 1019 } 1020 } 1021 } 1022 if(rp_num_ports_open) 1023 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1024} 1025 1026static const char* 1027rp_pciprobe(pcici_t tag, pcidi_t type) 1028{ 1029 int vendor_id; 1030 1031 vendor_id = type & 0xffff; 1032 switch(vendor_id) 1033 case 0x11fe: 1034 return("rp"); 1035 return(NULL); 1036} 1037 1038static 1039int 1040rpprobe(dev) 1041struct isa_device *dev; 1042{ 1043 int controller, unit; 1044 int aiop, num_aiops; 1045 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1046 CONTROLLER_t *ctlp; 1047 1048 unit = dev->id_unit; 1049 if (dev->id_unit >= 4) { 1050 printf("rpprobe: unit number %d invalid.\n", dev->id_unit); 1051 return 1; 1052 } 1053 printf("probing for RocketPort(ISA) unit %d\n", unit); 1054 if (rp_controller_port) 1055 controller = rp_controller_port; 1056 else { 1057 controller = dev->id_iobase + 0x40; 1058 } 1059 1060 for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++) 1061 aiopio[aiop]= dev->id_iobase + (aiop * 0x400); 1062 1063 ctlp = sCtlNumToCtlPtr(dev->id_unit); 1064 num_aiops = sInitController(ctlp, dev->id_unit, 1065 controller + ((unit-rp_pcicount)*0x400), 1066 aiopio, MAX_AIOPS_PER_BOARD, 0, 1067 FREQ_DIS, 0); 1068 if (num_aiops <= 0) { 1069 printf("board%d init failed\n", unit); 1070 return 0; 1071 } 1072 1073 if (rp_controller_port) { 1074 dev->id_msize = 64; 1075 } else { 1076 dev->id_msize = 68; 1077 rp_controller_port = controller; 1078 } 1079 1080 dev->id_irq = 0; 1081 1082 return 1; 1083} 1084 1085static void 1086rp_pciattach(pcici_t tag, int unit) 1087{ 1088 int success, oldspl; 1089 u_short iobase; 1090 int num_ports, num_chan, num_aiops; 1091 int aiop, chan, port; 1092 int ChanStatus, line, i, count; 1093 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1094 struct rp_port *rp; 1095 struct tty *tty; 1096 CONTROLLER_t *ctlp; 1097 1098 success = pci_map_port(tag, 0x10, &iobase); 1099 if(!success) 1100 printf("ioaddr mapping failed for RocketPort(PCI)\n"); 1101 1102 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) 1103 aiopio[aiop] = iobase + (aiop * 0x40); 1104 1105 ctlp = sCtlNumToCtlPtr(unit); 1106 num_aiops = sPCIInitController(ctlp, unit, 1107 aiopio, MAX_AIOPS_PER_BOARD, 0, 1108 FREQ_DIS, 0); 1109 1110 num_ports = 0; 1111 for(aiop=0; aiop < num_aiops; aiop++) { 1112 sResetAiopByNum(ctlp, aiop); 1113 num_ports += sGetAiopNumChan(ctlp, aiop); 1114 } 1115 printf("RocketPort%d = %d ports\n", unit, num_ports); 1116 rp_num_ports[unit] = num_ports; 1117 1118 rp = (struct rp_port *) 1119 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); 1120 if(rp == 0) { 1121 printf("rp_attach: Could not malloc rp_ports structures\n"); 1122 return; 1123 } 1124 1125 count = unit * 32; /* board times max ports per card SG */ 1126 for(i=count;i < (count + rp_num_ports[unit]);i++) 1127 minor_to_unit[i] = unit; 1128 1129 bzero(rp, sizeof(struct rp_port) * num_ports); 1130 tty = (struct tty *) 1131 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT); 1132 if(tty == 0) { 1133 printf("rp_attach: Could not malloc tty structures\n"); 1134 return; 1135 } 1136 bzero(tty, sizeof(struct tty) * num_ports); 1137 1138 oldspl = spltty(); 1139 rp_addr(unit) = rp; 1140 splx(oldspl); 1141 1142 cdevsw_add(&rp_cdevsw); 1143 1144 port = 0; 1145 for(aiop=0; aiop < num_aiops; aiop++) { 1146 num_chan = sGetAiopNumChan(ctlp, aiop); 1147 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { 1148 rp->rp_tty = tty; 1149 rp->rp_port = port; 1150 rp->rp_ctlp = ctlp; 1151 rp->rp_unit = unit; 1152 rp->rp_chan = chan; 1153 rp->rp_aiop = aiop; 1154 1155 tty->t_line = 0; 1156 /* tty->t_termios = deftermios; 1157 */ 1158 rp->dtr_wait = 3 * hz; 1159 rp->it_in.c_iflag = 0; 1160 rp->it_in.c_oflag = 0; 1161 rp->it_in.c_cflag = TTYDEF_CFLAG; 1162 rp->it_in.c_lflag = 0; 1163 termioschars(&rp->it_in); 1164 /* termioschars(&tty->t_termios); 1165 */ 1166 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 1167 rp->it_out = rp->it_in; 1168 1169 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 1170 DELTA_CD | DELTA_CTS | DELTA_DSR; 1171 ChanStatus = sGetChanStatus(&rp->rp_channel); 1172 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 1173 printf("RocketPort sInitChan(%d, %d, %d) failed 1174 \n", unit, aiop, chan); 1175 return; 1176 } 1177 ChanStatus = sGetChanStatus(&rp->rp_channel); 1178 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 1179 line = (unit << 5) | (aiop << 3) | chan; 1180 rp_table(line) = rp; 1181/* devfs_add_devswf(&rp_cdevsw, 1182 port, DV_CHR, UID_ROOT, GID_WHEEL, 0600, 1183 "ttyR%r", port); 1184 devfs_add_devswf(&rp_cdevsw, 1185 port | CONTROL_INIT_STATE, DV_CHR, UID_ROOT, 1186 GID_WHEEL, 0600, "ttyRi%r", port); 1187*/ 1188 } 1189 } 1190} 1191 1192static 1193int 1194rpattach(dev) 1195struct isa_device *dev; 1196{ 1197 int iobase, unit, /*rpmajor,*/ oldspl; 1198 int num_ports, num_chan, num_aiops; 1199 int aiop, chan, port; 1200 int ChanStatus, line, i, count; 1201 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1202 struct rp_port *rp; 1203 struct tty *tty; 1204 CONTROLLER_t *ctlp; 1205 1206 iobase = dev->id_iobase; 1207 unit = dev->id_unit; 1208 ndevs = unit; 1209 1210 for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) 1211 aiopio[aiop] = iobase + (aiop * 0x400); 1212 1213 ctlp = sCtlNumToCtlPtr(unit); 1214 num_aiops = sInitController(ctlp, unit, 1215 rp_controller_port + ((unit-rp_pcicount) * 0x400), 1216 aiopio, MAX_AIOPS_PER_BOARD, 0, 1217 FREQ_DIS, 0); 1218 1219 num_ports = 0; 1220 for(aiop=0; aiop < num_aiops; aiop++) { 1221 sResetAiopByNum(ctlp, aiop); 1222 sEnAiop(ctlp, aiop); 1223 num_ports += sGetAiopNumChan(ctlp, aiop); 1224 } 1225 printf("RocketPort%d = %d ports\n", unit, num_ports); 1226 rp_num_ports[unit] = num_ports; 1227 1228 rp = (struct rp_port *) 1229 malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT); 1230 if(rp == 0) { 1231 printf("rp_attach: Could not malloc rp_ports structures\n"); 1232 return(0); 1233 } 1234 1235 count = unit * 32; /* board # times max ports per card SG */ 1236 for(i=count;i < (count + rp_num_ports[unit]);i++) 1237 minor_to_unit[i] = unit; 1238 1239 bzero(rp, sizeof(struct rp_port) * num_ports); 1240 tty = (struct tty *) 1241 malloc(sizeof(struct tty) * num_ports, M_TTYS, M_NOWAIT); 1242 if(tty == 0) { 1243 printf("rp_attach: Could not malloc tty structures\n"); 1244 return(0); 1245 } 1246 bzero(tty, sizeof(struct tty) * num_ports); 1247 1248 oldspl = spltty(); 1249 rp_addr(unit) = rp; 1250 splx(oldspl); 1251 1252 cdevsw_add(&rp_cdevsw); 1253 1254 port = 0; 1255 for(aiop=0; aiop < num_aiops; aiop++) { 1256 num_chan = sGetAiopNumChan(ctlp, aiop); 1257 for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { 1258 rp->rp_tty = tty; 1259 rp->rp_port = port; 1260 rp->rp_ctlp = ctlp; 1261 rp->rp_unit = unit; 1262 rp->rp_chan = chan; 1263 rp->rp_aiop = aiop; 1264 1265 tty->t_line = 0; 1266 /* tty->t_termios = deftermios; 1267 */ 1268 rp->dtr_wait = 3 * hz; 1269 rp->it_in.c_iflag = 0; 1270 rp->it_in.c_oflag = 0; 1271 rp->it_in.c_cflag = TTYDEF_CFLAG; 1272 rp->it_in.c_lflag = 0; 1273 termioschars(&rp->it_in); 1274 /* termioschars(&tty->t_termios); 1275 */ 1276 rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; 1277 rp->it_out = rp->it_in; 1278 1279 rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | 1280 DELTA_CD | DELTA_CTS | DELTA_DSR; 1281 ChanStatus = sGetChanStatus(&rp->rp_channel); 1282 if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { 1283 printf("RocketPort sInitChan(%d, %d, %d) failed 1284 \n", unit, aiop, chan); 1285 return(0); 1286 } 1287 ChanStatus = sGetChanStatus(&rp->rp_channel); 1288 rp->rp_cts = (ChanStatus & CTS_ACT) != 0; 1289 line = (unit << 5) | (aiop << 3) | chan; 1290 rp_table(line) = rp; 1291 } 1292 } 1293 1294 return(1); 1295} 1296 1297int 1298rpopen(dev, flag, mode, p) 1299 dev_t dev; 1300 int flag, mode; 1301 struct proc *p; 1302{ 1303 struct rp_port *rp; 1304 int unit, port, mynor, umynor, flags; /* SG */ 1305 struct tty *tp; 1306 int oldspl, error; 1307 unsigned int IntMask, ChanStatus; 1308 1309 1310 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1311 port = (minor(dev) & 0x1f); /* SG */ 1312 mynor = (port + umynor); /* SG */ 1313 unit = minor_to_unit[mynor]; 1314 if(IS_CONTROL(dev)) 1315 return(0); 1316 rp = rp_addr(unit) + port; 1317/* rp->rp_tty = &rp_tty[rp->rp_port]; 1318*/ 1319 tp = rp->rp_tty; 1320 1321 oldspl = spltty(); 1322 1323open_top: 1324 while(rp->state & ~SET_DTR) { 1325 error = tsleep(&rp->dtr_wait, TTIPRI | PCATCH, "rpdtr", 0); 1326 if(error != 0) 1327 goto out; 1328 } 1329 1330 if(tp->t_state & TS_ISOPEN) { 1331 if(IS_CALLOUT(dev)) { 1332 if(!rp->active_out) { 1333 error = EBUSY; 1334 goto out; 1335 } 1336 } else { 1337 if(rp->active_out) { 1338 if(flag & O_NONBLOCK) { 1339 error = EBUSY; 1340 goto out; 1341 } 1342 error = tsleep(&rp->active_out, 1343 TTIPRI | PCATCH, "rpbi", 0); 1344 if(error != 0) 1345 goto out; 1346 goto open_top; 1347 } 1348 } 1349 if(tp->t_state & TS_XCLUDE && 1350 suser(p)) { 1351 splx(oldspl); 1352 return(EBUSY); 1353 } 1354 } 1355 else { 1356 tp->t_dev = dev; 1357 tp->t_param = rpparam; 1358 tp->t_oproc = rpstart; 1359 tp->t_line = 0; 1360 tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; 1361 flags = 0; 1362 flags |= SET_RTS; 1363 flags |= SET_DTR; 1364 rp->rp_channel.TxControl[3] = 1365 ((rp->rp_channel.TxControl[3] 1366 & ~(SET_RTS | SET_DTR)) | flags); 1367 sOutDW(rp->rp_channel.IndexAddr, 1368 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1369 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1370 sDisRxStatusMode(&rp->rp_channel); 1371 sFlushRxFIFO(&rp->rp_channel); 1372 sFlushTxFIFO(&rp->rp_channel); 1373 1374 sEnInterrupts(&rp->rp_channel, 1375 (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); 1376 sSetRxTrigger(&rp->rp_channel, TRIG_1); 1377 1378 sDisRxStatusMode(&rp->rp_channel); 1379 sClrTxXOFF(&rp->rp_channel); 1380 1381/* sDisRTSFlowCtl(&rp->rp_channel); 1382 sDisCTSFlowCtl(&rp->rp_channel); 1383*/ 1384 sDisTxSoftFlowCtl(&rp->rp_channel); 1385 1386 sStartRxProcessor(&rp->rp_channel); 1387 1388 sEnRxFIFO(&rp->rp_channel); 1389 sEnTransmit(&rp->rp_channel); 1390 1391/* sSetDTR(&rp->rp_channel); 1392 sSetRTS(&rp->rp_channel); 1393*/ 1394 1395 ++rp->wopeners; 1396 error = rpparam(tp, &tp->t_termios); 1397 --rp->wopeners; 1398 if(error != 0) { 1399 splx(oldspl); 1400 return(error); 1401 } 1402 1403 rp_num_ports_open++; 1404 1405 IntMask = sGetChanIntID(&rp->rp_channel); 1406 IntMask = IntMask & rp->rp_intmask; 1407 ChanStatus = sGetChanStatus(&rp->rp_channel); 1408 if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { 1409 if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { 1410 (void)(*linesw[tp->t_line].l_modem)(tp, 1); 1411 } 1412 } 1413 1414 if(rp_num_ports_open == 1) 1415 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1416 1417 } 1418 1419 if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 1420 !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { 1421 ++rp->wopeners; 1422 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, 1423 "rpdcd", 0); 1424 --rp->wopeners; 1425 if(error != 0) 1426 goto out; 1427 goto open_top; 1428 } 1429 error = (*linesw[tp->t_line].l_open)(dev, tp); 1430 1431 rp_disc_optim(tp, &tp->t_termios, rp); 1432 if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) 1433 rp->active_out = TRUE; 1434 1435/* if(rp_num_ports_open == 1) 1436 timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); 1437*/ 1438out: 1439 splx(oldspl); 1440 if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { 1441 rphardclose(rp); 1442 } 1443 return(error); 1444} 1445 1446int 1447rpclose(dev, flag, mode, p) 1448 dev_t dev; 1449 int flag, mode; 1450 struct proc *p; 1451{ 1452 int oldspl, unit, mynor, umynor, port; /* SG */ 1453 struct rp_port *rp; 1454 struct tty *tp; 1455 CHANNEL_t *cp; 1456 1457 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1458 port = (minor(dev) & 0x1f); /* SG */ 1459 mynor = (port + umynor); /* SG */ 1460 unit = minor_to_unit[mynor]; /* SG */ 1461 1462 if(IS_CONTROL(dev)) 1463 return(0); 1464 rp = rp_addr(unit) + port; 1465 cp = &rp->rp_channel; 1466 tp = rp->rp_tty; 1467 1468 oldspl = spltty(); 1469 (*linesw[tp->t_line].l_close)(tp, flag); 1470 rp_disc_optim(tp, &tp->t_termios, rp); 1471 rpstop(tp, FREAD | FWRITE); 1472 rphardclose(rp); 1473 1474 tp->t_state &= ~TS_BUSY; 1475 ttyclose(tp); 1476 1477 splx(oldspl); 1478 1479 return(0); 1480} 1481 1482static void 1483rphardclose(struct rp_port *rp) 1484{ 1485 int mynor; 1486 struct tty *tp; 1487 CHANNEL_t *cp; 1488 1489 cp = &rp->rp_channel; 1490 tp = rp->rp_tty; 1491 mynor = MINOR_MAGIC(tp->t_dev); 1492 1493 sFlushRxFIFO(cp); 1494 sFlushTxFIFO(cp); 1495 sDisTransmit(cp); 1496 sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); 1497 sDisRTSFlowCtl(cp); 1498 sDisCTSFlowCtl(cp); 1499 sDisTxSoftFlowCtl(cp); 1500 sClrTxXOFF(cp); 1501 1502 if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { 1503 sClrDTR(cp); 1504 } 1505 if(IS_CALLOUT(tp->t_dev)) { 1506 sClrDTR(cp); 1507 } 1508 if(rp->dtr_wait != 0) { 1509 timeout(rpdtrwakeup, rp, rp->dtr_wait); 1510 rp->state |= ~SET_DTR; 1511 } 1512 1513 rp->active_out = FALSE; 1514 wakeup(&rp->active_out); 1515 wakeup(TSA_CARR_ON(tp)); 1516} 1517 1518static 1519int 1520rpread(dev, uio, flag) 1521 dev_t dev; 1522 struct uio *uio; 1523 int flag; 1524{ 1525 struct rp_port *rp; 1526 struct tty *tp; 1527 int unit, mynor, umynor, port, error = 0; /* SG */ 1528 1529 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1530 port = (minor(dev) & 0x1f); /* SG */ 1531 mynor = (port + umynor); /* SG */ 1532 unit = minor_to_unit[mynor]; /* SG */ 1533 1534 if(IS_CONTROL(dev)) 1535 return(ENODEV); 1536 rp = rp_addr(unit) + port; 1537 tp = rp->rp_tty; 1538 error = (*linesw[tp->t_line].l_read)(tp, uio, flag); 1539 return(error); 1540} 1541 1542static 1543int 1544rpwrite(dev, uio, flag) 1545 dev_t dev; 1546 struct uio *uio; 1547 int flag; 1548{ 1549 struct rp_port *rp; 1550 struct tty *tp; 1551 int unit, mynor, port, umynor, error = 0; /* SG */ 1552 1553 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1554 port = (minor(dev) & 0x1f); /* SG */ 1555 mynor = (port + umynor); /* SG */ 1556 unit = minor_to_unit[mynor]; /* SG */ 1557 1558 if(IS_CONTROL(dev)) 1559 return(ENODEV); 1560 rp = rp_addr(unit) + port; 1561 tp = rp->rp_tty; 1562 while(rp->rp_disable_writes) { 1563 rp->rp_waiting = 1; 1564 error = ttysleep(tp, (caddr_t)rp, TTOPRI|PCATCH, "rp_write", 0); 1565 if (error) 1566 return(error); 1567 } 1568 1569 error = (*linesw[tp->t_line].l_write)(tp, uio, flag); 1570 return error; 1571} 1572 1573static void 1574rpdtrwakeup(void *chan) 1575{ 1576 struct rp_port *rp; 1577 1578 rp = (struct rp_port *)chan; 1579 rp->state &= SET_DTR; 1580 wakeup(&rp->dtr_wait); 1581} 1582 1583int 1584rpioctl(dev, cmd, data, flag, p) 1585 dev_t dev; 1586 u_long cmd; 1587 caddr_t data; 1588 int flag; 1589 struct proc *p; 1590{ 1591 struct rp_port *rp; 1592 CHANNEL_t *cp; 1593 struct tty *tp; 1594 int unit, mynor, port, umynor; /* SG */ 1595 int oldspl; 1596 int error = 0; 1597 int arg, flags, result, ChanStatus; 1598 int oldcmd; 1599 struct termios term, *t; 1600 1601 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 1602 port = (minor(dev) & 0x1f); /* SG */ 1603 mynor = (port + umynor); /* SG */ 1604 unit = minor_to_unit[mynor]; 1605 rp = rp_addr(unit) + port; 1606 1607 if(IS_CONTROL(dev)) { 1608 struct termios *ct; 1609 1610 switch (IS_CONTROL(dev)) { 1611 case CONTROL_INIT_STATE: 1612 ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in; 1613 break; 1614 case CONTROL_LOCK_STATE: 1615 ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in; 1616 break; 1617 default: 1618 return(ENODEV); /* /dev/nodev */ 1619 } 1620 switch (cmd) { 1621 case TIOCSETA: 1622 error = suser(p); 1623 if(error != 0) 1624 return(error); 1625 *ct = *(struct termios *)data; 1626 return(0); 1627 case TIOCGETA: 1628 *(struct termios *)data = *ct; 1629 return(0); 1630 case TIOCGETD: 1631 *(int *)data = TTYDISC; 1632 return(0); 1633 case TIOCGWINSZ: 1634 bzero(data, sizeof(struct winsize)); 1635 return(0); 1636 default: 1637 return(ENOTTY); 1638 } 1639 } 1640 1641 tp = rp->rp_tty; 1642 cp = &rp->rp_channel; 1643 1644#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1645 term = tp->t_termios; 1646 oldcmd = cmd; 1647 error = ttsetcompat(tp, &cmd, data, &term); 1648 if(error != 0) 1649 return(error); 1650 if(cmd != oldcmd) { 1651 data = (caddr_t)&term; 1652 } 1653#endif 1654 if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) { 1655 int cc; 1656 struct termios *dt = (struct termios *)data; 1657 struct termios *lt = IS_CALLOUT(dev) 1658 ? &rp->lt_out : &rp->lt_in; 1659 1660 dt->c_iflag = (tp->t_iflag & lt->c_iflag) 1661 | (dt->c_iflag & ~lt->c_iflag); 1662 dt->c_oflag = (tp->t_oflag & lt->c_oflag) 1663 | (dt->c_oflag & ~lt->c_oflag); 1664 dt->c_cflag = (tp->t_cflag & lt->c_cflag) 1665 | (dt->c_cflag & ~lt->c_cflag); 1666 dt->c_lflag = (tp->t_lflag & lt->c_lflag) 1667 | (dt->c_lflag & ~lt->c_lflag); 1668 for(cc = 0; cc < NCCS; ++cc) 1669 if((lt->c_cc[cc] = tp->t_cc[cc]) != 0) 1670 dt->c_cc[cc] = tp->t_cc[cc]; 1671 if(lt->c_ispeed != 0) 1672 dt->c_ispeed = tp->t_ispeed; 1673 if(lt->c_ospeed != 0) 1674 dt->c_ospeed = tp->t_ospeed; 1675 } 1676 1677 t = &tp->t_termios; 1678 1679 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 1680 if(error != ENOIOCTL) { 1681 return(error); 1682 } 1683 oldspl = spltty(); 1684 1685 flags = rp->rp_channel.TxControl[3]; 1686 1687 error = ttioctl(tp, cmd, data, flag); 1688 flags = rp->rp_channel.TxControl[3]; 1689 rp_disc_optim(tp, &tp->t_termios, rp); 1690 if(error != ENOIOCTL) { 1691 splx(oldspl); 1692 return(error); 1693 } 1694 switch(cmd) { 1695 case TIOCSBRK: 1696 sSendBreak(&rp->rp_channel); 1697 break; 1698 1699 case TIOCCBRK: 1700 sClrBreak(&rp->rp_channel); 1701 break; 1702 1703 case TIOCSDTR: 1704 sSetDTR(&rp->rp_channel); 1705 sSetRTS(&rp->rp_channel); 1706 break; 1707 1708 case TIOCCDTR: 1709 sClrDTR(&rp->rp_channel); 1710 break; 1711 1712 case TIOCMSET: 1713 arg = *(int *) data; 1714 flags = 0; 1715 if(arg & TIOCM_RTS) 1716 flags |= SET_RTS; 1717 if(arg & TIOCM_DTR) 1718 flags |= SET_DTR; 1719 rp->rp_channel.TxControl[3] = 1720 ((rp->rp_channel.TxControl[3] 1721 & ~(SET_RTS | SET_DTR)) | flags); 1722 sOutDW(rp->rp_channel.IndexAddr, 1723 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1724 break; 1725 case TIOCMBIS: 1726 arg = *(int *) data; 1727 flags = 0; 1728 if(arg & TIOCM_RTS) 1729 flags |= SET_RTS; 1730 if(arg & TIOCM_DTR) 1731 flags |= SET_DTR; 1732 rp->rp_channel.TxControl[3] |= flags; 1733 sOutDW(rp->rp_channel.IndexAddr, 1734 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1735 break; 1736 case TIOCMBIC: 1737 arg = *(int *) data; 1738 flags = 0; 1739 if(arg & TIOCM_RTS) 1740 flags |= SET_RTS; 1741 if(arg & TIOCM_DTR) 1742 flags |= SET_DTR; 1743 rp->rp_channel.TxControl[3] &= ~flags; 1744 sOutDW(rp->rp_channel.IndexAddr, 1745 *(DWord_t *) &(rp->rp_channel.TxControl[0])); 1746 break; 1747 1748 1749 case TIOCMGET: 1750 ChanStatus = sGetChanStatusLo(&rp->rp_channel); 1751 flags = rp->rp_channel.TxControl[3]; 1752 result = TIOCM_LE; /* always on while open for some reason */ 1753 result |= (((flags & SET_DTR) ? TIOCM_DTR : 0) 1754 | ((flags & SET_RTS) ? TIOCM_RTS : 0) 1755 | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) 1756 | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) 1757 | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0)); 1758 1759 if(rp->rp_channel.RxControl[2] & RTSFC_EN) 1760 { 1761 result |= TIOCM_RTS; 1762 } 1763 1764 *(int *)data = result; 1765 break; 1766 case TIOCMSDTRWAIT: 1767 error = suser(p); 1768 if(error != 0) { 1769 splx(oldspl); 1770 return(error); 1771 } 1772 rp->dtr_wait = *(int *)data * hz/100; 1773 break; 1774 case TIOCMGDTRWAIT: 1775 *(int *)data = rp->dtr_wait * 100/hz; 1776 break; 1777 default: 1778 splx(oldspl); 1779 return ENOTTY; 1780 } 1781 splx(oldspl); 1782 return(0); 1783} 1784 1785static struct speedtab baud_table[] = { 1786 B0, 0, B50, BRD50, B75, BRD75, 1787 B110, BRD110, B134, BRD134, B150, BRD150, 1788 B200, BRD200, B300, BRD300, B600, BRD600, 1789 B1200, BRD1200, B1800, BRD1800, B2400, BRD2400, 1790 B4800, BRD4800, B9600, BRD9600, B19200, BRD19200, 1791 B38400, BRD38400, B7200, BRD7200, B14400, BRD14400, 1792 B57600, BRD57600, B76800, BRD76800, 1793 B115200, BRD115200, B230400, BRD230400, 1794 -1, -1 1795}; 1796 1797static int 1798rpparam(tp, t) 1799 struct tty *tp; 1800 struct termios *t; 1801{ 1802 struct rp_port *rp; 1803 CHANNEL_t *cp; 1804 int unit, mynor, port, umynor; /* SG */ 1805 int oldspl, cflag, iflag, oflag, lflag; 1806 int ospeed; 1807 1808 1809 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 1810 port = (minor(tp->t_dev) & 0x1f); /* SG */ 1811 mynor = (port + umynor); /* SG */ 1812 1813 unit = minor_to_unit[mynor]; 1814 rp = rp_addr(unit) + port; 1815 cp = &rp->rp_channel; 1816 oldspl = spltty(); 1817 1818 cflag = t->c_cflag; 1819 iflag = t->c_iflag; 1820 oflag = t->c_oflag; 1821 lflag = t->c_lflag; 1822 1823 ospeed = ttspeedtab(t->c_ispeed, baud_table); 1824 if(ospeed < 0 || t->c_ispeed != t->c_ospeed) 1825 return(EINVAL); 1826 1827 tp->t_ispeed = t->c_ispeed; 1828 tp->t_ospeed = t->c_ospeed; 1829 tp->t_cflag = cflag; 1830 tp->t_iflag = iflag; 1831 tp->t_oflag = oflag; 1832 tp->t_lflag = lflag; 1833 1834 if(t->c_ospeed == 0) { 1835 sClrDTR(cp); 1836 return(0); 1837 } 1838 rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; 1839 1840 /* Set baud rate ----- we only pay attention to ispeed */ 1841 sSetDTR(cp); 1842 sSetRTS(cp); 1843 sSetBaud(cp, ospeed); 1844 1845 if(cflag & CSTOPB) { 1846 sSetStop2(cp); 1847 } else { 1848 sSetStop1(cp); 1849 } 1850 1851 if(cflag & PARENB) { 1852 sEnParity(cp); 1853 if(cflag & PARODD) { 1854 sSetOddParity(cp); 1855 } else { 1856 sSetEvenParity(cp); 1857 } 1858 } 1859 else { 1860 sDisParity(cp); 1861 } 1862 if((cflag & CSIZE) == CS8) { 1863 sSetData8(cp); 1864 rp->rp_imask = 0xFF; 1865 } else { 1866 sSetData7(cp); 1867 rp->rp_imask = 0x7F; 1868 } 1869 1870 if(iflag & ISTRIP) { 1871 rp->rp_imask &= 0x7F; 1872 } 1873 1874 if(cflag & CLOCAL) { 1875 rp->rp_intmask &= ~DELTA_CD; 1876 } else { 1877 rp->rp_intmask |= DELTA_CD; 1878 } 1879 1880 /* Put flow control stuff here */ 1881 1882 if(cflag & CCTS_OFLOW) { 1883 sEnCTSFlowCtl(cp); 1884 } else { 1885 sDisCTSFlowCtl(cp); 1886 } 1887 1888 if(cflag & CRTS_IFLOW) { 1889 rp->rp_rts_iflow = 1; 1890 } else { 1891 rp->rp_rts_iflow = 0; 1892 } 1893 1894 if(cflag & CRTS_IFLOW) { 1895 sEnRTSFlowCtl(cp); 1896 } else { 1897 sDisRTSFlowCtl(cp); 1898 } 1899 rp_disc_optim(tp, t, rp); 1900 1901 if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { 1902 tp->t_state |= TS_CARR_ON; 1903 wakeup(TSA_CARR_ON(tp)); 1904 } 1905 1906/* tp->t_state |= TS_CAN_BYPASS_L_RINT; 1907 flags = rp->rp_channel.TxControl[3]; 1908 if(flags & SET_DTR) 1909 else 1910 if(flags & SET_RTS) 1911 else 1912*/ 1913 splx(oldspl); 1914 1915 return(0); 1916} 1917 1918static void 1919rp_disc_optim(tp, t, rp) 1920struct tty *tp; 1921struct termios *t; 1922struct rp_port *rp; 1923{ 1924 if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) 1925 &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) 1926 &&(!(t->c_iflag & PARMRK) 1927 ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) 1928 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) 1929 && linesw[tp->t_line].l_rint == ttyinput) 1930 tp->t_state |= TS_CAN_BYPASS_L_RINT; 1931 else 1932 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 1933} 1934 1935static void 1936rpstart(tp) 1937 struct tty *tp; 1938{ 1939 struct rp_port *rp; 1940 CHANNEL_t *cp; 1941 struct clist *qp; 1942 int unit, mynor, port, umynor; /* SG */ 1943 char ch, flags; 1944 int spl, xmit_fifo_room; 1945 int count; 1946 1947 1948 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 1949 port = (minor(tp->t_dev) & 0x1f); /* SG */ 1950 mynor = (port + umynor); /* SG */ 1951 unit = minor_to_unit[mynor]; 1952 rp = rp_addr(unit) + port; 1953 cp = &rp->rp_channel; 1954 flags = rp->rp_channel.TxControl[3]; 1955 spl = spltty(); 1956 1957 if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 1958 ttwwakeup(tp); 1959 splx(spl); 1960 return; 1961 } 1962 if(rp->rp_xmit_stopped) { 1963 sEnTransmit(cp); 1964 rp->rp_xmit_stopped = 0; 1965 } 1966 count = sGetTxCnt(cp); 1967 1968 if(tp->t_outq.c_cc == 0) { 1969 if((tp->t_state & TS_BUSY) && (count == 0)) { 1970 tp->t_state &= ~TS_BUSY; 1971 } 1972 ttwwakeup(tp); 1973 splx(spl); 1974 return; 1975 } 1976 xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); 1977 qp = &tp->t_outq; 1978 count = 0; 1979 if(xmit_fifo_room > 0 && qp->c_cc > 0) { 1980 tp->t_state |= TS_BUSY; 1981 } 1982 while(xmit_fifo_room > 0 && qp->c_cc > 0) { 1983 ch = getc(qp); 1984 sOutB(sGetTxRxDataIO(cp), ch); 1985 xmit_fifo_room--; 1986 count++; 1987 } 1988 rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; 1989 1990 ttwwakeup(tp); 1991 splx(spl); 1992} 1993 1994static 1995void 1996rpstop(tp, flag) 1997 register struct tty *tp; 1998 int flag; 1999{ 2000 struct rp_port *rp; 2001 CHANNEL_t *cp; 2002 int unit, mynor, port, umynor; /* SG */ 2003 int spl; 2004 2005 umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ 2006 port = (minor(tp->t_dev) & 0x1f); /* SG */ 2007 mynor = (port + umynor); /* SG */ 2008 unit = minor_to_unit[mynor]; 2009 rp = rp_addr(unit) + port; 2010 cp = &rp->rp_channel; 2011 2012 spl = spltty(); 2013 2014 if(tp->t_state & TS_BUSY) { 2015 if((tp->t_state&TS_TTSTOP) == 0) { 2016 sFlushTxFIFO(cp); 2017 } else { 2018 if(rp->rp_xmit_stopped == 0) { 2019 sDisTransmit(cp); 2020 rp->rp_xmit_stopped = 1; 2021 } 2022 } 2023 } 2024 splx(spl); 2025 rpstart(tp); 2026} 2027 2028int 2029rpselect(dev, flag, p) 2030 dev_t dev; 2031 int flag; 2032 struct proc *p; 2033{ 2034 return(0); 2035} 2036 2037struct tty * 2038rpdevtotty(dev_t dev) 2039{ 2040 struct rp_port *rp; 2041 int unit, port, mynor, umynor; /* SG */ 2042 2043 umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ 2044 port = (minor(dev) & 0x1f); /* SG */ 2045 mynor = (port + umynor); /* SG */ 2046 unit = minor_to_unit[mynor]; /* SG */ 2047 2048 if(IS_CONTROL(dev)) 2049 return(NULL); 2050 rp = rp_addr(unit) + port; 2051 return(rp->rp_tty); 2052} 2053