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