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