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