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