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