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