1/******************************************************************************* 2* 3* (c) 1999 by Computone Corporation 4* 5******************************************************************************** 6* 7* 8* PACKAGE: Linux tty Device Driver for IntelliPort family of multiport 9* serial I/O controllers. 10* 11* DESCRIPTION: High-level interface code for the device driver. Uses the 12* Extremely Low Level Interface Support (i2ellis.c). Provides an 13* interface to the standard loadware, to support drivers or 14* application code. (This is included source code, not a separate 15* compilation module.) 16* 17*******************************************************************************/ 18//------------------------------------------------------------------------------ 19// Note on Strategy: 20// Once the board has been initialized, it will interrupt us when: 21// 1) It has something in the fifo for us to read (incoming data, flow control 22// packets, or whatever). 23// 2) It has stripped whatever we have sent last time in the FIFO (and 24// consequently is ready for more). 25// 26// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This 27// worsens performance considerably, but is done so that a great many channels 28// might use only a little memory. 29//------------------------------------------------------------------------------ 30 31//------------------------------------------------------------------------------ 32// Revision History: 33// 34// 0.00 - 4/16/91 --- First Draft 35// 0.01 - 4/29/91 --- 1st beta release 36// 0.02 - 6/14/91 --- Changes to allow small model compilation 37// 0.03 - 6/17/91 MAG Break reporting protected from interrupts routines with 38// in-line asm added for moving data to/from ring buffers, 39// replacing a variety of methods used previously. 40// 0.04 - 6/21/91 MAG Initial flow-control packets not queued until 41// i2_enable_interrupts time. Former versions would enqueue 42// them at i2_init_channel time, before we knew how many 43// channels were supposed to exist! 44// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now; 45// supports new 16-bit protocol and expandable boards. 46// - 10/24/91 MAG Most changes in place and stable. 47// 0.06 - 2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no 48// argument. 49// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt 50// level (mostly responses to specific commands.) 51// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet 52// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE 53// turning on the interrupt. 54// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check 55// some incoming. 56// 57// 1.1 - 12/25/96 AKM Linux version. 58// - 10/09/98 DMC Revised Linux version. 59//------------------------------------------------------------------------------ 60 61/ 62 63//******** 64//* Code * 65//******** 66 67static inline int 68i2Validate ( i2ChanStrPtr pCh ) 69{ 70 //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, 71 // (CHANNEL_MAGIC | CHANNEL_SUPPORT)); 72 return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 73 == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); 74} 75 76static void iiSendPendingMail_t(unsigned long data) 77{ 78 i2eBordStrPtr pB = (i2eBordStrPtr)data; 79 80 iiSendPendingMail(pB); 81} 82 83//****************************************************************************** 84// Function: iiSendPendingMail(pB) 85// Parameters: Pointer to a board structure 86// Returns: Nothing 87// 88// Description: 89// If any outgoing mail bits are set and there is outgoing mailbox is empty, 90// send the mail and clear the bits. 91//****************************************************************************** 92static void 93iiSendPendingMail(i2eBordStrPtr pB) 94{ 95 if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) 96 { 97 if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) 98 { 99 /* If we were already waiting for fifo to empty, 100 * or just sent MB_OUT_STUFFED, then we are 101 * still waiting for it to empty, until we should 102 * receive an MB_IN_STRIPPED from the board. 103 */ 104 pB->i2eWaitingForEmptyFifo |= 105 (pB->i2eOutMailWaiting & MB_OUT_STUFFED); 106 pB->i2eOutMailWaiting = 0; 107 pB->SendPendingRetry = 0; 108 } else { 109/* The only time we hit this area is when "iiTrySendMail" has 110 failed. That only occurs when the outbound mailbox is 111 still busy with the last message. We take a short breather 112 to let the board catch up with itself and then try again. 113 16 Retries is the limit - then we got a borked board. 114 /\/\|=mhw=|\/\/ */ 115 116 if( ++pB->SendPendingRetry < 16 ) { 117 setup_timer(&pB->SendPendingTimer, 118 iiSendPendingMail_t, (unsigned long)pB); 119 mod_timer(&pB->SendPendingTimer, jiffies + 1); 120 } else { 121 printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); 122 } 123 } 124 } 125} 126 127//****************************************************************************** 128// Function: i2InitChannels(pB, nChannels, pCh) 129// Parameters: Pointer to Ellis Board structure 130// Number of channels to initialize 131// Pointer to first element in an array of channel structures 132// Returns: Success or failure 133// 134// Description: 135// 136// This function patches pointers, back-pointers, and initializes all the 137// elements in the channel structure array. 138// 139// This should be run after the board structure is initialized, through having 140// loaded the standard loadware (otherwise it complains). 141// 142// In any case, it must be done before any serious work begins initializing the 143// irq's or sending commands... 144// 145//****************************************************************************** 146static int 147i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) 148{ 149 int index, stuffIndex; 150 i2ChanStrPtr *ppCh; 151 152 if (pB->i2eValid != I2E_MAGIC) { 153 COMPLETE(pB, I2EE_BADMAGIC); 154 } 155 if (pB->i2eState != II_STATE_STDLOADED) { 156 COMPLETE(pB, I2EE_BADSTATE); 157 } 158 159 LOCK_INIT(&pB->read_fifo_spinlock); 160 LOCK_INIT(&pB->write_fifo_spinlock); 161 LOCK_INIT(&pB->Dbuf_spinlock); 162 LOCK_INIT(&pB->Bbuf_spinlock); 163 LOCK_INIT(&pB->Fbuf_spinlock); 164 165 // NO LOCK needed yet - this is init 166 167 pB->i2eChannelPtr = pCh; 168 pB->i2eChannelCnt = nChannels; 169 170 pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0; 171 pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0; 172 pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0; 173 174 pB->SendPendingRetry = 0; 175 176 memset ( pCh, 0, sizeof (i2ChanStr) * nChannels ); 177 178 for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf); 179 nChannels && index < ABS_MOST_PORTS; 180 index++) 181 { 182 if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) { 183 continue; 184 } 185 LOCK_INIT(&pCh->Ibuf_spinlock); 186 LOCK_INIT(&pCh->Obuf_spinlock); 187 LOCK_INIT(&pCh->Cbuf_spinlock); 188 LOCK_INIT(&pCh->Pbuf_spinlock); 189 // NO LOCK needed yet - this is init 190 // Set up validity flag according to support level 191 if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) { 192 pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT; 193 } else { 194 pCh->validity = CHANNEL_MAGIC; 195 } 196 pCh->pMyBord = pB; /* Back-pointer */ 197 198 // Prepare an outgoing flow-control packet to send as soon as the chance 199 // occurs. 200 if ( pCh->validity & CHANNEL_SUPPORT ) { 201 pCh->infl.hd.i2sChannel = index; 202 pCh->infl.hd.i2sCount = 5; 203 pCh->infl.hd.i2sType = PTYPE_BYPASS; 204 pCh->infl.fcmd = 37; 205 pCh->infl.asof = 0; 206 pCh->infl.room = IBUF_SIZE - 1; 207 208 pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full 209 210 // The following is similar to calling i2QueueNeeds, except that this 211 // is done in longhand, since we are setting up initial conditions on 212 // many channels at once. 213 pCh->channelNeeds = NEED_FLOW; // Since starting from scratch 214 pCh->sinceLastFlow = 0; // No bytes received since last flow 215 // control packet was queued 216 stuffIndex++; 217 *ppCh++ = pCh; // List this channel as needing 218 // initial flow control packet sent 219 } 220 221 // Don't allow anything to be sent until the status packets come in from 222 // the board. 223 224 pCh->outfl.asof = 0; 225 pCh->outfl.room = 0; 226 227 // Initialize all the ring buffers 228 229 pCh->Ibuf_stuff = pCh->Ibuf_strip = 0; 230 pCh->Obuf_stuff = pCh->Obuf_strip = 0; 231 pCh->Cbuf_stuff = pCh->Cbuf_strip = 0; 232 233 memset( &pCh->icount, 0, sizeof (struct async_icount) ); 234 pCh->hotKeyIn = HOT_CLEAR; 235 pCh->channelOptions = 0; 236 pCh->bookMarks = 0; 237 init_waitqueue_head(&pCh->pBookmarkWait); 238 239 init_waitqueue_head(&pCh->open_wait); 240 init_waitqueue_head(&pCh->close_wait); 241 init_waitqueue_head(&pCh->delta_msr_wait); 242 243 // Set base and divisor so default custom rate is 9600 244 pCh->BaudBase = 921600; // MAX for ST654, changed after we get 245 pCh->BaudDivisor = 96; // the boxids (UART types) later 246 247 pCh->dataSetIn = 0; 248 pCh->dataSetOut = 0; 249 250 pCh->wopen = 0; 251 pCh->throttled = 0; 252 253 pCh->speed = CBR_9600; 254 255 pCh->flags = 0; 256 257 pCh->ClosingDelay = 5*HZ/10; 258 pCh->ClosingWaitTime = 30*HZ; 259 260 // Initialize task queue objects 261 INIT_WORK(&pCh->tqueue_input, do_input); 262 INIT_WORK(&pCh->tqueue_status, do_status); 263 264#ifdef IP2DEBUG_TRACE 265 pCh->trace = ip2trace; 266#endif 267 268 ++pCh; 269 --nChannels; 270 } 271 // No need to check for wrap here; this is initialization. 272 pB->i2Fbuf_stuff = stuffIndex; 273 COMPLETE(pB, I2EE_GOOD); 274 275} 276 277//****************************************************************************** 278// Function: i2DeQueueNeeds(pB, type) 279// Parameters: Pointer to a board structure 280// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW 281// Returns: 282// Pointer to a channel structure 283// 284// Description: Returns pointer struct of next channel that needs service of 285// the type specified. Otherwise returns a NULL reference. 286// 287//****************************************************************************** 288static i2ChanStrPtr 289i2DeQueueNeeds(i2eBordStrPtr pB, int type) 290{ 291 unsigned short queueIndex; 292 unsigned long flags; 293 294 i2ChanStrPtr pCh = NULL; 295 296 switch(type) { 297 298 case NEED_INLINE: 299 300 WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags); 301 if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip) 302 { 303 queueIndex = pB->i2Dbuf_strip; 304 pCh = pB->i2Dbuf[queueIndex]; 305 queueIndex++; 306 if (queueIndex >= CH_QUEUE_SIZE) { 307 queueIndex = 0; 308 } 309 pB->i2Dbuf_strip = queueIndex; 310 pCh->channelNeeds &= ~NEED_INLINE; 311 } 312 WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 313 break; 314 315 case NEED_BYPASS: 316 317 WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags); 318 if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip) 319 { 320 queueIndex = pB->i2Bbuf_strip; 321 pCh = pB->i2Bbuf[queueIndex]; 322 queueIndex++; 323 if (queueIndex >= CH_QUEUE_SIZE) { 324 queueIndex = 0; 325 } 326 pB->i2Bbuf_strip = queueIndex; 327 pCh->channelNeeds &= ~NEED_BYPASS; 328 } 329 WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 330 break; 331 332 case NEED_FLOW: 333 334 WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags); 335 if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip) 336 { 337 queueIndex = pB->i2Fbuf_strip; 338 pCh = pB->i2Fbuf[queueIndex]; 339 queueIndex++; 340 if (queueIndex >= CH_QUEUE_SIZE) { 341 queueIndex = 0; 342 } 343 pB->i2Fbuf_strip = queueIndex; 344 pCh->channelNeeds &= ~NEED_FLOW; 345 } 346 WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 347 break; 348 default: 349 printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type); 350 break; 351 } 352 return pCh; 353} 354 355//****************************************************************************** 356// Function: i2QueueNeeds(pB, pCh, type) 357// Parameters: Pointer to a board structure 358// Pointer to a channel structure 359// type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW 360// Returns: Nothing 361// 362// Description: 363// For each type of need selected, if the given channel is not already in the 364// queue, adds it, and sets the flag indicating it is in the queue. 365//****************************************************************************** 366static void 367i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type) 368{ 369 unsigned short queueIndex; 370 unsigned long flags; 371 372 // We turn off all the interrupts during this brief process, since the 373 // interrupt-level code might want to put things on the queue as well. 374 375 switch (type) { 376 377 case NEED_INLINE: 378 379 WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags); 380 if ( !(pCh->channelNeeds & NEED_INLINE) ) 381 { 382 pCh->channelNeeds |= NEED_INLINE; 383 queueIndex = pB->i2Dbuf_stuff; 384 pB->i2Dbuf[queueIndex++] = pCh; 385 if (queueIndex >= CH_QUEUE_SIZE) 386 queueIndex = 0; 387 pB->i2Dbuf_stuff = queueIndex; 388 } 389 WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 390 break; 391 392 case NEED_BYPASS: 393 394 WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags); 395 if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS)) 396 { 397 pCh->channelNeeds |= NEED_BYPASS; 398 queueIndex = pB->i2Bbuf_stuff; 399 pB->i2Bbuf[queueIndex++] = pCh; 400 if (queueIndex >= CH_QUEUE_SIZE) 401 queueIndex = 0; 402 pB->i2Bbuf_stuff = queueIndex; 403 } 404 WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 405 break; 406 407 case NEED_FLOW: 408 409 WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags); 410 if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW)) 411 { 412 pCh->channelNeeds |= NEED_FLOW; 413 queueIndex = pB->i2Fbuf_stuff; 414 pB->i2Fbuf[queueIndex++] = pCh; 415 if (queueIndex >= CH_QUEUE_SIZE) 416 queueIndex = 0; 417 pB->i2Fbuf_stuff = queueIndex; 418 } 419 WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 420 break; 421 422 case NEED_CREDIT: 423 pCh->channelNeeds |= NEED_CREDIT; 424 break; 425 default: 426 printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type); 427 break; 428 } 429 return; 430} 431 432//****************************************************************************** 433// Function: i2QueueCommands(type, pCh, timeout, nCommands, pCs,...) 434// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE 435// pointer to the channel structure 436// maximum period to wait 437// number of commands (n) 438// n commands 439// Returns: Number of commands sent, or -1 for error 440// 441// get board lock before calling 442// 443// Description: 444// Queues up some commands to be sent to a channel. To send possibly several 445// bypass or inline commands to the given channel. The timeout parameter 446// indicates how many HUNDREDTHS OF SECONDS to wait until there is room: 447// 0 = return immediately if no room, -ive = wait forever, +ive = number of 448// 1/100 seconds to wait. Return values: 449// -1 Some kind of nasty error: bad channel structure or invalid arguments. 450// 0 No room to send all the commands 451// (+) Number of commands sent 452//****************************************************************************** 453static int 454i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, 455 cmdSyntaxPtr pCs0,...) 456{ 457 int totalsize = 0; 458 int blocksize; 459 int lastended; 460 cmdSyntaxPtr *ppCs; 461 cmdSyntaxPtr pCs; 462 int count; 463 int flag; 464 i2eBordStrPtr pB; 465 466 unsigned short maxBlock; 467 unsigned short maxBuff; 468 short bufroom; 469 unsigned short stuffIndex; 470 unsigned char *pBuf; 471 unsigned char *pInsert; 472 unsigned char *pDest, *pSource; 473 unsigned short channel; 474 int cnt; 475 unsigned long flags = 0; 476 rwlock_t *lock_var_p = NULL; 477 478 // Make sure the channel exists, otherwise do nothing 479 if ( !i2Validate ( pCh ) ) { 480 return -1; 481 } 482 483 ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 ); 484 485 pB = pCh->pMyBord; 486 487 // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT 488 if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == IRQ_UNDEFINED) { 489 return -2; 490 } 491 // If the board has gone fatal, return bad, and also hit the trap routine if 492 // it exists. 493 if (pB->i2eFatal) { 494 if ( pB->i2eFatalTrap ) { 495 (*(pB)->i2eFatalTrap)(pB); 496 } 497 return -3; 498 } 499 // Set up some variables, Which buffers are we using? How big are they? 500 switch(type) 501 { 502 case PTYPE_INLINE: 503 flag = INL; 504 maxBlock = MAX_OBUF_BLOCK; 505 maxBuff = OBUF_SIZE; 506 pBuf = pCh->Obuf; 507 break; 508 case PTYPE_BYPASS: 509 flag = BYP; 510 maxBlock = MAX_CBUF_BLOCK; 511 maxBuff = CBUF_SIZE; 512 pBuf = pCh->Cbuf; 513 break; 514 default: 515 return -4; 516 } 517 // Determine the total size required for all the commands 518 totalsize = blocksize = sizeof(i2CmdHeader); 519 lastended = 0; 520 ppCs = &pCs0; 521 for ( count = nCommands; count; count--, ppCs++) 522 { 523 pCs = *ppCs; 524 cnt = pCs->length; 525 // Will a new block be needed for this one? 526 // Two possible reasons: too 527 // big or previous command has to be at the end of a packet. 528 if ((blocksize + cnt > maxBlock) || lastended) { 529 blocksize = sizeof(i2CmdHeader); 530 totalsize += sizeof(i2CmdHeader); 531 } 532 totalsize += cnt; 533 blocksize += cnt; 534 535 // If this command had to end a block, then we will make sure to 536 // account for it should there be any more blocks. 537 lastended = pCs->flags & END; 538 } 539 for (;;) { 540 // Make sure any pending flush commands go out before we add more data. 541 if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) { 542 // How much room (this time through) ? 543 switch(type) { 544 case PTYPE_INLINE: 545 lock_var_p = &pCh->Obuf_spinlock; 546 WRITE_LOCK_IRQSAVE(lock_var_p,flags); 547 stuffIndex = pCh->Obuf_stuff; 548 bufroom = pCh->Obuf_strip - stuffIndex; 549 break; 550 case PTYPE_BYPASS: 551 lock_var_p = &pCh->Cbuf_spinlock; 552 WRITE_LOCK_IRQSAVE(lock_var_p,flags); 553 stuffIndex = pCh->Cbuf_stuff; 554 bufroom = pCh->Cbuf_strip - stuffIndex; 555 break; 556 default: 557 return -5; 558 } 559 if (--bufroom < 0) { 560 bufroom += maxBuff; 561 } 562 563 ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom ); 564 565 // Check for overflow 566 if (totalsize <= bufroom) { 567 // Normal Expected path - We still hold LOCK 568 break; /* from for()- Enough room: goto proceed */ 569 } 570 } 571 572 ip2trace (CHANN, ITRC_QUEUE, 3, 1, totalsize ); 573 574 // Prepare to wait for buffers to empty 575 WRITE_UNLOCK_IRQRESTORE(lock_var_p,flags); 576 serviceOutgoingFifo(pB); // Dump what we got 577 578 if (timeout == 0) { 579 return 0; // Tired of waiting 580 } 581 if (timeout > 0) 582 timeout--; // So negative values == forever 583 584 if (!in_interrupt()) { 585 schedule_timeout_interruptible(1); // short nap 586 } else { 587 // we cannot sched/sleep in interrrupt silly 588 return 0; 589 } 590 if (signal_pending(current)) { 591 return 0; // Wake up! Time to die!!! 592 } 593 594 ip2trace (CHANN, ITRC_QUEUE, 4, 0 ); 595 596 } // end of for(;;) 597 598 // At this point we have room and the lock - stick them in. 599 channel = pCh->infl.hd.i2sChannel; 600 pInsert = &pBuf[stuffIndex]; // Pointer to start of packet 601 pDest = CMD_OF(pInsert); // Pointer to start of command 602 603 // When we start counting, the block is the size of the header 604 for (blocksize = sizeof(i2CmdHeader), count = nCommands, 605 lastended = 0, ppCs = &pCs0; 606 count; 607 count--, ppCs++) 608 { 609 pCs = *ppCs; // Points to command protocol structure 610 611 // If this is a bookmark request command, post the fact that a bookmark 612 // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ 613 // has no parameters! The more general solution would be to reference 614 // pCs->cmd[0]. 615 if (pCs == CMD_BMARK_REQ) { 616 pCh->bookMarks++; 617 618 ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks ); 619 620 } 621 cnt = pCs->length; 622 623 // If this command would put us over the maximum block size or 624 // if the last command had to be at the end of a block, we end 625 // the existing block here and start a new one. 626 if ((blocksize + cnt > maxBlock) || lastended) { 627 628 ip2trace (CHANN, ITRC_QUEUE, 5, 0 ); 629 630 PTYPE_OF(pInsert) = type; 631 CHANNEL_OF(pInsert) = channel; 632 // count here does not include the header 633 CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); 634 stuffIndex += blocksize; 635 if(stuffIndex >= maxBuff) { 636 stuffIndex = 0; 637 pInsert = pBuf; 638 } 639 pInsert = &pBuf[stuffIndex]; // Pointer to start of next pkt 640 pDest = CMD_OF(pInsert); 641 blocksize = sizeof(i2CmdHeader); 642 } 643 // Now we know there is room for this one in the current block 644 645 blocksize += cnt; // Total bytes in this command 646 pSource = pCs->cmd; // Copy the command into the buffer 647 while (cnt--) { 648 *pDest++ = *pSource++; 649 } 650 // If this command had to end a block, then we will make sure to account 651 // for it should there be any more blocks. 652 lastended = pCs->flags & END; 653 } // end for 654 // Clean up the final block by writing header, etc 655 656 PTYPE_OF(pInsert) = type; 657 CHANNEL_OF(pInsert) = channel; 658 // count here does not include the header 659 CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); 660 stuffIndex += blocksize; 661 if(stuffIndex >= maxBuff) { 662 stuffIndex = 0; 663 pInsert = pBuf; 664 } 665 // Updates the index, and post the need for service. When adding these to 666 // the queue of channels, we turn off the interrupt while doing so, 667 // because at interrupt level we might want to push a channel back to the 668 // end of the queue. 669 switch(type) 670 { 671 case PTYPE_INLINE: 672 pCh->Obuf_stuff = stuffIndex; // Store buffer pointer 673 WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 674 675 pB->debugInlineQueued++; 676 // Add the channel pointer to list of channels needing service (first 677 // come...), if it's not already there. 678 i2QueueNeeds(pB, pCh, NEED_INLINE); 679 break; 680 681 case PTYPE_BYPASS: 682 pCh->Cbuf_stuff = stuffIndex; // Store buffer pointer 683 WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags); 684 685 pB->debugBypassQueued++; 686 // Add the channel pointer to list of channels needing service (first 687 // come...), if it's not already there. 688 i2QueueNeeds(pB, pCh, NEED_BYPASS); 689 break; 690 } 691 692 ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands ); 693 694 return nCommands; // Good status: number of commands sent 695} 696 697//****************************************************************************** 698// Function: i2GetStatus(pCh,resetBits) 699// Parameters: Pointer to a channel structure 700// Bit map of status bits to clear 701// Returns: Bit map of current status bits 702// 703// Description: 704// Returns the state of data set signals, and whether a break has been received, 705// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status 706// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared 707// AFTER the condition is passed. If pCh does not point to a valid channel, 708// returns -1 (which would be impossible otherwise. 709//****************************************************************************** 710static int 711i2GetStatus(i2ChanStrPtr pCh, int resetBits) 712{ 713 unsigned short status; 714 i2eBordStrPtr pB; 715 716 ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits ); 717 718 // Make sure the channel exists, otherwise do nothing */ 719 if ( !i2Validate ( pCh ) ) 720 return -1; 721 722 pB = pCh->pMyBord; 723 724 status = pCh->dataSetIn; 725 726 // Clear any specified error bits: but note that only actual error bits can 727 // be cleared, regardless of the value passed. 728 if (resetBits) 729 { 730 pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR)); 731 pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI); 732 } 733 734 ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn ); 735 736 return status; 737} 738 739//****************************************************************************** 740// Function: i2Input(pChpDest,count) 741// Parameters: Pointer to a channel structure 742// Pointer to data buffer 743// Number of bytes to read 744// Returns: Number of bytes read, or -1 for error 745// 746// Description: 747// Strips data from the input buffer and writes it to pDest. If there is a 748// collosal blunder, (invalid structure pointers or the like), returns -1. 749// Otherwise, returns the number of bytes read. 750//****************************************************************************** 751static int 752i2Input(i2ChanStrPtr pCh) 753{ 754 int amountToMove; 755 unsigned short stripIndex; 756 int count; 757 unsigned long flags = 0; 758 759 ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0); 760 761 // Ensure channel structure seems real 762 if ( !i2Validate( pCh ) ) { 763 count = -1; 764 goto i2Input_exit; 765 } 766 WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags); 767 768 // initialize some accelerators and private copies 769 stripIndex = pCh->Ibuf_strip; 770 771 count = pCh->Ibuf_stuff - stripIndex; 772 773 // If buffer is empty or requested data count was 0, (trivial case) return 774 // without any further thought. 775 if ( count == 0 ) { 776 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags); 777 goto i2Input_exit; 778 } 779 // Adjust for buffer wrap 780 if ( count < 0 ) { 781 count += IBUF_SIZE; 782 } 783 // Don't give more than can be taken by the line discipline 784 amountToMove = pCh->pTTY->receive_room; 785 if (count > amountToMove) { 786 count = amountToMove; 787 } 788 // How much could we copy without a wrap? 789 amountToMove = IBUF_SIZE - stripIndex; 790 791 if (amountToMove > count) { 792 amountToMove = count; 793 } 794 // Move the first block 795 pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 796 &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); 797 // If we needed to wrap, do the second data move 798 if (count > amountToMove) { 799 pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 800 pCh->Ibuf, NULL, count - amountToMove ); 801 } 802 // Bump and wrap the stripIndex all at once by the amount of data read. This 803 // method is good regardless of whether the data was in one or two pieces. 804 stripIndex += count; 805 if (stripIndex >= IBUF_SIZE) { 806 stripIndex -= IBUF_SIZE; 807 } 808 pCh->Ibuf_strip = stripIndex; 809 810 // Update our flow control information and possibly queue ourselves to send 811 // it, depending on how much data has been stripped since the last time a 812 // packet was sent. 813 pCh->infl.asof += count; 814 815 if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) { 816 pCh->sinceLastFlow -= pCh->whenSendFlow; 817 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags); 818 i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); 819 } else { 820 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags); 821 } 822 823i2Input_exit: 824 825 ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count); 826 827 return count; 828} 829 830//****************************************************************************** 831// Function: i2InputFlush(pCh) 832// Parameters: Pointer to a channel structure 833// Returns: Number of bytes stripped, or -1 for error 834// 835// Description: 836// Strips any data from the input buffer. If there is a collosal blunder, 837// (invalid structure pointers or the like), returns -1. Otherwise, returns the 838// number of bytes stripped. 839//****************************************************************************** 840static int 841i2InputFlush(i2ChanStrPtr pCh) 842{ 843 int count; 844 unsigned long flags; 845 846 // Ensure channel structure seems real 847 if ( !i2Validate ( pCh ) ) 848 return -1; 849 850 ip2trace (CHANN, ITRC_INPUT, 10, 0); 851 852 WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags); 853 count = pCh->Ibuf_stuff - pCh->Ibuf_strip; 854 855 // Adjust for buffer wrap 856 if (count < 0) { 857 count += IBUF_SIZE; 858 } 859 860 // Expedient way to zero out the buffer 861 pCh->Ibuf_strip = pCh->Ibuf_stuff; 862 863 864 // Update our flow control information and possibly queue ourselves to send 865 // it, depending on how much data has been stripped since the last time a 866 // packet was sent. 867 868 pCh->infl.asof += count; 869 870 if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow ) 871 { 872 pCh->sinceLastFlow -= pCh->whenSendFlow; 873 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags); 874 i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); 875 } else { 876 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags); 877 } 878 879 ip2trace (CHANN, ITRC_INPUT, 19, 1, count); 880 881 return count; 882} 883 884//****************************************************************************** 885// Function: i2InputAvailable(pCh) 886// Parameters: Pointer to a channel structure 887// Returns: Number of bytes available, or -1 for error 888// 889// Description: 890// If there is a collosal blunder, (invalid structure pointers or the like), 891// returns -1. Otherwise, returns the number of bytes stripped. Otherwise, 892// returns the number of bytes available in the buffer. 893//****************************************************************************** 894 895//****************************************************************************** 896// Function: i2Output(pCh, pSource, count) 897// Parameters: Pointer to channel structure 898// Pointer to source data 899// Number of bytes to send 900// Returns: Number of bytes sent, or -1 for error 901// 902// Description: 903// Queues the data at pSource to be sent as data packets to the board. If there 904// is a collosal blunder, (invalid structure pointers or the like), returns -1. 905// Otherwise, returns the number of bytes written. What if there is not enough 906// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then 907// we transfer as many characters as we can now, then return. If this bit is 908// clear (default), routine will spin along until all the data is buffered. 909// Should this occur, the 1-ms delay routine is called while waiting to avoid 910// applications that one cannot break out of. 911//****************************************************************************** 912static int 913i2Output(i2ChanStrPtr pCh, const char *pSource, int count) 914{ 915 i2eBordStrPtr pB; 916 unsigned char *pInsert; 917 int amountToMove; 918 int countOriginal = count; 919 unsigned short channel; 920 unsigned short stuffIndex; 921 unsigned long flags; 922 923 int bailout = 10; 924 925 ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); 926 927 // Ensure channel structure seems real 928 if ( !i2Validate ( pCh ) ) 929 return -1; 930 931 // initialize some accelerators and private copies 932 pB = pCh->pMyBord; 933 channel = pCh->infl.hd.i2sChannel; 934 935 // If the board has gone fatal, return bad, and also hit the trap routine if 936 // it exists. 937 if (pB->i2eFatal) { 938 if (pB->i2eFatalTrap) { 939 (*(pB)->i2eFatalTrap)(pB); 940 } 941 return -1; 942 } 943 // Proceed as though we would do everything 944 while ( count > 0 ) { 945 946 // How much room in output buffer is there? 947 READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); 948 amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; 949 READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 950 if (amountToMove < 0) { 951 amountToMove += OBUF_SIZE; 952 } 953 // Subtract off the headers size and see how much room there is for real 954 // data. If this is negative, we will discover later. 955 amountToMove -= sizeof (i2DataHeader); 956 957 // Don't move more (now) than can go in a single packet 958 if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) { 959 amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader); 960 } 961 // Don't move more than the count we were given 962 if (amountToMove > count) { 963 amountToMove = count; 964 } 965 // Now we know how much we must move: NB because the ring buffers have 966 // an overflow area at the end, we needn't worry about wrapping in the 967 // middle of a packet. 968 969// Small WINDOW here with no LOCK but I can't call Flush with LOCK 970// We would be flushing (or ending flush) anyway 971 972 ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove ); 973 974 if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 975 && amountToMove > 0 ) 976 { 977 WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); 978 stuffIndex = pCh->Obuf_stuff; 979 980 // Had room to move some data: don't know whether the block size, 981 // buffer space, or what was the limiting factor... 982 pInsert = &(pCh->Obuf[stuffIndex]); 983 984 // Set up the header 985 CHANNEL_OF(pInsert) = channel; 986 PTYPE_OF(pInsert) = PTYPE_DATA; 987 TAG_OF(pInsert) = 0; 988 ID_OF(pInsert) = ID_ORDINARY_DATA; 989 DATA_COUNT_OF(pInsert) = amountToMove; 990 991 // Move the data 992 memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); 993 // Adjust pointers and indices 994 pSource += amountToMove; 995 pCh->Obuf_char_count += amountToMove; 996 stuffIndex += amountToMove + sizeof(i2DataHeader); 997 count -= amountToMove; 998 999 if (stuffIndex >= OBUF_SIZE) { 1000 stuffIndex = 0; 1001 } 1002 pCh->Obuf_stuff = stuffIndex; 1003 1004 WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 1005 1006 ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex ); 1007 1008 } else { 1009 1010 // Cannot move data 1011 // becuz we need to stuff a flush 1012 // or amount to move is <= 0 1013 1014 ip2trace(CHANN, ITRC_OUTPUT, 14, 3, 1015 amountToMove, pB->i2eFifoRemains, 1016 pB->i2eWaitingForEmptyFifo ); 1017 1018 // Put this channel back on queue 1019 // this ultimatly gets more data or wakes write output 1020 i2QueueNeeds(pB, pCh, NEED_INLINE); 1021 1022 if ( pB->i2eWaitingForEmptyFifo ) { 1023 1024 ip2trace (CHANN, ITRC_OUTPUT, 16, 0 ); 1025 1026 // or schedule 1027 if (!in_interrupt()) { 1028 1029 ip2trace (CHANN, ITRC_OUTPUT, 61, 0 ); 1030 1031 schedule_timeout_interruptible(2); 1032 if (signal_pending(current)) { 1033 break; 1034 } 1035 continue; 1036 } else { 1037 1038 ip2trace (CHANN, ITRC_OUTPUT, 62, 0 ); 1039 1040 // let interrupt in = WAS restore_flags() 1041 // We hold no lock nor is irq off anymore??? 1042 1043 break; 1044 } 1045 break; // from while(count) 1046 } 1047 else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) ) 1048 { 1049 ip2trace (CHANN, ITRC_OUTPUT, 19, 2, 1050 pB->i2eFifoRemains, 1051 pB->i2eTxMailEmpty ); 1052 1053 break; // from while(count) 1054 } else if ( pCh->channelNeeds & NEED_CREDIT ) { 1055 1056 ip2trace (CHANN, ITRC_OUTPUT, 22, 0 ); 1057 1058 break; // from while(count) 1059 } else if ( --bailout) { 1060 1061 // Try to throw more things (maybe not us) in the fifo if we're 1062 // not already waiting for it. 1063 1064 ip2trace (CHANN, ITRC_OUTPUT, 20, 0 ); 1065 1066 serviceOutgoingFifo(pB); 1067 //break; CONTINUE; 1068 } else { 1069 ip2trace (CHANN, ITRC_OUTPUT, 21, 3, 1070 pB->i2eFifoRemains, 1071 pB->i2eOutMailWaiting, 1072 pB->i2eWaitingForEmptyFifo ); 1073 1074 break; // from while(count) 1075 } 1076 } 1077 } // End of while(count) 1078 1079 i2QueueNeeds(pB, pCh, NEED_INLINE); 1080 1081 // We drop through either when the count expires, or when there is some 1082 // count left, but there was a non-blocking write. 1083 if (countOriginal > count) { 1084 1085 ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count ); 1086 1087 serviceOutgoingFifo( pB ); 1088 } 1089 1090 ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count ); 1091 1092 return countOriginal - count; 1093} 1094 1095//****************************************************************************** 1096// Function: i2FlushOutput(pCh) 1097// Parameters: Pointer to a channel structure 1098// Returns: Nothing 1099// 1100// Description: 1101// Sends bypass command to start flushing (waiting possibly forever until there 1102// is room), then sends inline command to stop flushing output, (again waiting 1103// possibly forever). 1104//****************************************************************************** 1105static inline void 1106i2FlushOutput(i2ChanStrPtr pCh) 1107{ 1108 1109 ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags ); 1110 1111 if (pCh->flush_flags) 1112 return; 1113 1114 if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { 1115 pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later 1116 1117 ip2trace (CHANN, ITRC_FLUSH, 2, 0 ); 1118 1119 } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) { 1120 pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later 1121 1122 ip2trace (CHANN, ITRC_FLUSH, 3, 0 ); 1123 } 1124} 1125 1126static int 1127i2RetryFlushOutput(i2ChanStrPtr pCh) 1128{ 1129 int old_flags = pCh->flush_flags; 1130 1131 ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags ); 1132 1133 pCh->flush_flags = 0; // Clear flag so we can avoid recursion 1134 // and queue the commands 1135 1136 if ( old_flags & STARTFL_FLAG ) { 1137 if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { 1138 old_flags = STOPFL_FLAG; //Success - send stop flush 1139 } else { 1140 old_flags = STARTFL_FLAG; //Failure - Flag for retry later 1141 } 1142 1143 ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags ); 1144 1145 } 1146 if ( old_flags & STOPFL_FLAG ) { 1147 if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) { 1148 old_flags = 0; // Success - clear flags 1149 } 1150 1151 ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags ); 1152 } 1153 pCh->flush_flags = old_flags; 1154 1155 ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags ); 1156 1157 return old_flags; 1158} 1159 1160//****************************************************************************** 1161// Function: i2DrainOutput(pCh,timeout) 1162// Parameters: Pointer to a channel structure 1163// Maximum period to wait 1164// Returns: ? 1165// 1166// Description: 1167// Uses the bookmark request command to ask the board to send a bookmark back as 1168// soon as all the data is completely sent. 1169//****************************************************************************** 1170static void 1171i2DrainWakeup(unsigned long d) 1172{ 1173 i2ChanStrPtr pCh = (i2ChanStrPtr)d; 1174 1175 ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); 1176 1177 pCh->BookmarkTimer.expires = 0; 1178 wake_up_interruptible( &pCh->pBookmarkWait ); 1179} 1180 1181static void 1182i2DrainOutput(i2ChanStrPtr pCh, int timeout) 1183{ 1184 wait_queue_t wait; 1185 i2eBordStrPtr pB; 1186 1187 ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires); 1188 1189 pB = pCh->pMyBord; 1190 // If the board has gone fatal, return bad, 1191 // and also hit the trap routine if it exists. 1192 if (pB->i2eFatal) { 1193 if (pB->i2eFatalTrap) { 1194 (*(pB)->i2eFatalTrap)(pB); 1195 } 1196 return; 1197 } 1198 if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { 1199 // One per customer (channel) 1200 setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, 1201 (unsigned long)pCh); 1202 1203 ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); 1204 1205 mod_timer(&pCh->BookmarkTimer, jiffies + timeout); 1206 } 1207 1208 i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); 1209 1210 init_waitqueue_entry(&wait, current); 1211 add_wait_queue(&(pCh->pBookmarkWait), &wait); 1212 set_current_state( TASK_INTERRUPTIBLE ); 1213 1214 serviceOutgoingFifo( pB ); 1215 1216 schedule(); // Now we take our interruptible sleep on 1217 1218 // Clean up the queue 1219 set_current_state( TASK_RUNNING ); 1220 remove_wait_queue(&(pCh->pBookmarkWait), &wait); 1221 1222 // if expires == 0 then timer poped, then do not need to del_timer 1223 if ((timeout > 0) && pCh->BookmarkTimer.expires && 1224 time_before(jiffies, pCh->BookmarkTimer.expires)) { 1225 del_timer( &(pCh->BookmarkTimer) ); 1226 pCh->BookmarkTimer.expires = 0; 1227 1228 ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires ); 1229 1230 } 1231 ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires ); 1232 return; 1233} 1234 1235//****************************************************************************** 1236// Function: i2OutputFree(pCh) 1237// Parameters: Pointer to a channel structure 1238// Returns: Space in output buffer 1239// 1240// Description: 1241// Returns -1 if very gross error. Otherwise returns the amount of bytes still 1242// free in the output buffer. 1243//****************************************************************************** 1244static int 1245i2OutputFree(i2ChanStrPtr pCh) 1246{ 1247 int amountToMove; 1248 unsigned long flags; 1249 1250 // Ensure channel structure seems real 1251 if ( !i2Validate ( pCh ) ) { 1252 return -1; 1253 } 1254 READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); 1255 amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; 1256 READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 1257 1258 if (amountToMove < 0) { 1259 amountToMove += OBUF_SIZE; 1260 } 1261 // If this is negative, we will discover later 1262 amountToMove -= sizeof(i2DataHeader); 1263 1264 return (amountToMove < 0) ? 0 : amountToMove; 1265} 1266static void 1267 1268ip2_owake( PTTY tp) 1269{ 1270 i2ChanStrPtr pCh; 1271 1272 if (tp == NULL) return; 1273 1274 pCh = tp->driver_data; 1275 1276 ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, 1277 (1 << TTY_DO_WRITE_WAKEUP) ); 1278 1279 tty_wakeup(tp); 1280} 1281 1282static inline void 1283set_baud_params(i2eBordStrPtr pB) 1284{ 1285 int i,j; 1286 i2ChanStrPtr *pCh; 1287 1288 pCh = (i2ChanStrPtr *) pB->i2eChannelPtr; 1289 1290 for (i = 0; i < ABS_MAX_BOXES; i++) { 1291 if (pB->channelBtypes.bid_value[i]) { 1292 if (BID_HAS_654(pB->channelBtypes.bid_value[i])) { 1293 for (j = 0; j < ABS_BIGGEST_BOX; j++) { 1294 if (pCh[i*16+j] == NULL) 1295 break; 1296 (pCh[i*16+j])->BaudBase = 921600; // MAX for ST654 1297 (pCh[i*16+j])->BaudDivisor = 96; 1298 } 1299 } else { // has cirrus cd1400 1300 for (j = 0; j < ABS_BIGGEST_BOX; j++) { 1301 if (pCh[i*16+j] == NULL) 1302 break; 1303 (pCh[i*16+j])->BaudBase = 115200; // MAX for CD1400 1304 (pCh[i*16+j])->BaudDivisor = 12; 1305 } 1306 } 1307 } 1308 } 1309} 1310 1311//****************************************************************************** 1312// Function: i2StripFifo(pB) 1313// Parameters: Pointer to a board structure 1314// Returns: ? 1315// 1316// Description: 1317// Strips all the available data from the incoming FIFO, identifies the type of 1318// packet, and either buffers the data or does what needs to be done. 1319// 1320// Note there is no overflow checking here: if the board sends more data than it 1321// ought to, we will not detect it here, but blindly overflow... 1322//****************************************************************************** 1323 1324// A buffer for reading in blocks for unknown channels 1325static unsigned char junkBuffer[IBUF_SIZE]; 1326 1327// A buffer to read in a status packet. Because of the size of the count field 1328// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE 1329static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4]; 1330 1331// This table changes the bit order from MSR order given by STAT_MODEM packet to 1332// status bits used in our library. 1333static char xlatDss[16] = { 13340 | 0 | 0 | 0 , 13350 | 0 | 0 | I2_CTS , 13360 | 0 | I2_DSR | 0 , 13370 | 0 | I2_DSR | I2_CTS , 13380 | I2_RI | 0 | 0 , 13390 | I2_RI | 0 | I2_CTS , 13400 | I2_RI | I2_DSR | 0 , 13410 | I2_RI | I2_DSR | I2_CTS , 1342I2_DCD | 0 | 0 | 0 , 1343I2_DCD | 0 | 0 | I2_CTS , 1344I2_DCD | 0 | I2_DSR | 0 , 1345I2_DCD | 0 | I2_DSR | I2_CTS , 1346I2_DCD | I2_RI | 0 | 0 , 1347I2_DCD | I2_RI | 0 | I2_CTS , 1348I2_DCD | I2_RI | I2_DSR | 0 , 1349I2_DCD | I2_RI | I2_DSR | I2_CTS }; 1350 1351static inline void 1352i2StripFifo(i2eBordStrPtr pB) 1353{ 1354 i2ChanStrPtr pCh; 1355 int channel; 1356 int count; 1357 unsigned short stuffIndex; 1358 int amountToRead; 1359 unsigned char *pc, *pcLimit; 1360 unsigned char uc; 1361 unsigned char dss_change; 1362 unsigned long bflags,cflags; 1363 1364// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 ); 1365 1366 while (HAS_INPUT(pB)) { 1367// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 ); 1368 1369 // Process packet from fifo a one atomic unit 1370 WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock,bflags); 1371 1372 // The first word (or two bytes) will have channel number and type of 1373 // packet, possibly other information 1374 pB->i2eLeadoffWord[0] = iiReadWord(pB); 1375 1376 switch(PTYPE_OF(pB->i2eLeadoffWord)) 1377 { 1378 case PTYPE_DATA: 1379 pB->got_input = 1; 1380 1381// ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 ); 1382 1383 channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */ 1384 count = iiReadWord(pB); /* Count is in the next word */ 1385 1386// NEW: Check the count for sanity! Should the hardware fail, our death 1387// is more pleasant. While an oversize channel is acceptable (just more 1388// than the driver supports), an over-length count clearly means we are 1389// sick! 1390 if ( ((unsigned int)count) > IBUF_SIZE ) { 1391 pB->i2eFatal = 2; 1392 WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags); 1393 return; /* Bail out ASAP */ 1394 } 1395 // Channel is illegally big ? 1396 if ((channel >= pB->i2eChannelCnt) || 1397 (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel]))) 1398 { 1399 iiReadBuf(pB, junkBuffer, count); 1400 WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags); 1401 break; /* From switch: ready for next packet */ 1402 } 1403 1404 // Channel should be valid, then 1405 1406 // If this is a hot-key, merely post its receipt for now. These are 1407 // always supposed to be 1-byte packets, so we won't even check the 1408 // count. Also we will post an acknowledgement to the board so that 1409 // more data can be forthcoming. Note that we are not trying to use 1410 // these sequences in this driver, merely to robustly ignore them. 1411 if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY) 1412 { 1413 pCh->hotKeyIn = iiReadWord(pB) & 0xff; 1414 WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags); 1415 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK); 1416 break; /* From the switch: ready for next packet */ 1417 } 1418 1419 // Normal data! We crudely assume there is room for the data in our 1420 // buffer because the board wouldn't have exceeded his credit limit. 1421 WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,cflags); 1422 // We have 2 locks now 1423 stuffIndex = pCh->Ibuf_stuff; 1424 amountToRead = IBUF_SIZE - stuffIndex; 1425 if (amountToRead > count) 1426 amountToRead = count; 1427 1428 // stuffIndex would have been already adjusted so there would 1429 // always be room for at least one, and count is always at least 1430 // one. 1431 1432 iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); 1433 pCh->icount.rx += amountToRead; 1434 1435 // Update the stuffIndex by the amount of data moved. Note we could 1436 // never ask for more data than would just fit. However, we might 1437 // have read in one more byte than we wanted because the read 1438 // rounds up to even bytes. If this byte is on the end of the 1439 // packet, and is padding, we ignore it. If the byte is part of 1440 // the actual data, we need to move it. 1441 1442 stuffIndex += amountToRead; 1443 1444 if (stuffIndex >= IBUF_SIZE) { 1445 if ((amountToRead & 1) && (count > amountToRead)) { 1446 pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE]; 1447 amountToRead++; 1448 stuffIndex = 1; 1449 } else { 1450 stuffIndex = 0; 1451 } 1452 } 1453 1454 // If there is anything left over, read it as well 1455 if (count > amountToRead) { 1456 amountToRead = count - amountToRead; 1457 iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); 1458 pCh->icount.rx += amountToRead; 1459 stuffIndex += amountToRead; 1460 } 1461 1462 // Update stuff index 1463 pCh->Ibuf_stuff = stuffIndex; 1464 WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,cflags); 1465 WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags); 1466 1467#ifdef USE_IQ 1468 schedule_work(&pCh->tqueue_input); 1469#else 1470 do_input(&pCh->tqueue_input); 1471#endif 1472 1473 // Note we do not need to maintain any flow-control credits at this 1474 // time: if we were to increment .asof and decrement .room, there 1475 // would be no net effect. Instead, when we strip data, we will 1476 // increment .asof and leave .room unchanged. 1477 1478 break; // From switch: ready for next packet 1479 1480 case PTYPE_STATUS: 1481 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 ); 1482 1483 count = CMD_COUNT_OF(pB->i2eLeadoffWord); 1484 1485 iiReadBuf(pB, cmdBuffer, count); 1486 // We can release early with buffer grab 1487 WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags); 1488 1489 pc = cmdBuffer; 1490 pcLimit = &(cmdBuffer[count]); 1491 1492 while (pc < pcLimit) { 1493 channel = *pc++; 1494 1495 ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc ); 1496 1497 /* check for valid channel */ 1498 if (channel < pB->i2eChannelCnt 1499 && 1500 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL 1501 ) 1502 { 1503 dss_change = 0; 1504 1505 switch (uc = *pc++) 1506 { 1507 /* Breaks and modem signals are easy: just update status */ 1508 case STAT_CTS_UP: 1509 if ( !(pCh->dataSetIn & I2_CTS) ) 1510 { 1511 pCh->dataSetIn |= I2_DCTS; 1512 pCh->icount.cts++; 1513 dss_change = 1; 1514 } 1515 pCh->dataSetIn |= I2_CTS; 1516 break; 1517 1518 case STAT_CTS_DN: 1519 if ( pCh->dataSetIn & I2_CTS ) 1520 { 1521 pCh->dataSetIn |= I2_DCTS; 1522 pCh->icount.cts++; 1523 dss_change = 1; 1524 } 1525 pCh->dataSetIn &= ~I2_CTS; 1526 break; 1527 1528 case STAT_DCD_UP: 1529 ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn ); 1530 1531 if ( !(pCh->dataSetIn & I2_DCD) ) 1532 { 1533 ip2trace (CHANN, ITRC_MODEM, 2, 0 ); 1534 pCh->dataSetIn |= I2_DDCD; 1535 pCh->icount.dcd++; 1536 dss_change = 1; 1537 } 1538 pCh->dataSetIn |= I2_DCD; 1539 1540 ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn ); 1541 break; 1542 1543 case STAT_DCD_DN: 1544 ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn ); 1545 if ( pCh->dataSetIn & I2_DCD ) 1546 { 1547 ip2trace (channel, ITRC_MODEM, 5, 0 ); 1548 pCh->dataSetIn |= I2_DDCD; 1549 pCh->icount.dcd++; 1550 dss_change = 1; 1551 } 1552 pCh->dataSetIn &= ~I2_DCD; 1553 1554 ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn ); 1555 break; 1556 1557 case STAT_DSR_UP: 1558 if ( !(pCh->dataSetIn & I2_DSR) ) 1559 { 1560 pCh->dataSetIn |= I2_DDSR; 1561 pCh->icount.dsr++; 1562 dss_change = 1; 1563 } 1564 pCh->dataSetIn |= I2_DSR; 1565 break; 1566 1567 case STAT_DSR_DN: 1568 if ( pCh->dataSetIn & I2_DSR ) 1569 { 1570 pCh->dataSetIn |= I2_DDSR; 1571 pCh->icount.dsr++; 1572 dss_change = 1; 1573 } 1574 pCh->dataSetIn &= ~I2_DSR; 1575 break; 1576 1577 case STAT_RI_UP: 1578 if ( !(pCh->dataSetIn & I2_RI) ) 1579 { 1580 pCh->dataSetIn |= I2_DRI; 1581 pCh->icount.rng++; 1582 dss_change = 1; 1583 } 1584 pCh->dataSetIn |= I2_RI ; 1585 break; 1586 1587 case STAT_RI_DN: 1588 // to be compat with serial.c 1589 //if ( pCh->dataSetIn & I2_RI ) 1590 //{ 1591 // pCh->dataSetIn |= I2_DRI; 1592 // pCh->icount.rng++; 1593 // dss_change = 1; 1594 //} 1595 pCh->dataSetIn &= ~I2_RI ; 1596 break; 1597 1598 case STAT_BRK_DET: 1599 pCh->dataSetIn |= I2_BRK; 1600 pCh->icount.brk++; 1601 dss_change = 1; 1602 break; 1603 1604 // Bookmarks? one less request we're waiting for 1605 case STAT_BMARK: 1606 pCh->bookMarks--; 1607 if (pCh->bookMarks <= 0 ) { 1608 pCh->bookMarks = 0; 1609 wake_up_interruptible( &pCh->pBookmarkWait ); 1610 1611 ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires ); 1612 } 1613 break; 1614 1615 // Flow control packets? Update the new credits, and if 1616 // someone was waiting for output, queue him up again. 1617 case STAT_FLOW: 1618 pCh->outfl.room = 1619 ((flowStatPtr)pc)->room - 1620 (pCh->outfl.asof - ((flowStatPtr)pc)->asof); 1621 1622 ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room ); 1623 1624 if (pCh->channelNeeds & NEED_CREDIT) 1625 { 1626 ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds); 1627 1628 pCh->channelNeeds &= ~NEED_CREDIT; 1629 i2QueueNeeds(pB, pCh, NEED_INLINE); 1630 if ( pCh->pTTY ) 1631 ip2_owake(pCh->pTTY); 1632 } 1633 1634 ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds); 1635 1636 pc += sizeof(flowStat); 1637 break; 1638 1639 /* Special packets: */ 1640 /* Just copy the information into the channel structure */ 1641 1642 case STAT_STATUS: 1643 1644 pCh->channelStatus = *((debugStatPtr)pc); 1645 pc += sizeof(debugStat); 1646 break; 1647 1648 case STAT_TXCNT: 1649 1650 pCh->channelTcount = *((cntStatPtr)pc); 1651 pc += sizeof(cntStat); 1652 break; 1653 1654 case STAT_RXCNT: 1655 1656 pCh->channelRcount = *((cntStatPtr)pc); 1657 pc += sizeof(cntStat); 1658 break; 1659 1660 case STAT_BOXIDS: 1661 pB->channelBtypes = *((bidStatPtr)pc); 1662 pc += sizeof(bidStat); 1663 set_baud_params(pB); 1664 break; 1665 1666 case STAT_HWFAIL: 1667 i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST); 1668 pCh->channelFail = *((failStatPtr)pc); 1669 pc += sizeof(failStat); 1670 break; 1671 1672 /* No explicit match? then 1673 * Might be an error packet... 1674 */ 1675 default: 1676 switch (uc & STAT_MOD_ERROR) 1677 { 1678 case STAT_ERROR: 1679 if (uc & STAT_E_PARITY) { 1680 pCh->dataSetIn |= I2_PAR; 1681 pCh->icount.parity++; 1682 } 1683 if (uc & STAT_E_FRAMING){ 1684 pCh->dataSetIn |= I2_FRA; 1685 pCh->icount.frame++; 1686 } 1687 if (uc & STAT_E_OVERRUN){ 1688 pCh->dataSetIn |= I2_OVR; 1689 pCh->icount.overrun++; 1690 } 1691 break; 1692 1693 case STAT_MODEM: 1694 // the answer to DSS_NOW request (not change) 1695 pCh->dataSetIn = (pCh->dataSetIn 1696 & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) ) 1697 | xlatDss[uc & 0xf]; 1698 wake_up_interruptible ( &pCh->dss_now_wait ); 1699 default: 1700 break; 1701 } 1702 } /* End of switch on status type */ 1703 if (dss_change) { 1704#ifdef USE_IQ 1705 schedule_work(&pCh->tqueue_status); 1706#else 1707 do_status(&pCh->tqueue_status); 1708#endif 1709 } 1710 } 1711 else /* Or else, channel is invalid */ 1712 { 1713 // Even though the channel is invalid, we must test the 1714 // status to see how much additional data it has (to be 1715 // skipped) 1716 switch (*pc++) 1717 { 1718 case STAT_FLOW: 1719 pc += 4; /* Skip the data */ 1720 break; 1721 1722 default: 1723 break; 1724 } 1725 } 1726 } // End of while (there is still some status packet left) 1727 break; 1728 1729 default: // Neither packet? should be impossible 1730 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, 1731 PTYPE_OF(pB->i2eLeadoffWord) ); 1732 1733 break; 1734 } // End of switch on type of packets 1735 } //while(board HAS_INPUT) 1736 1737 ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 ); 1738 1739 // Send acknowledgement to the board even if there was no data! 1740 pB->i2eOutMailWaiting |= MB_IN_STRIPPED; 1741 return; 1742} 1743 1744//****************************************************************************** 1745// Function: i2Write2Fifo(pB,address,count) 1746// Parameters: Pointer to a board structure, source address, byte count 1747// Returns: bytes written 1748// 1749// Description: 1750// Writes count bytes to board io address(implied) from source 1751// Adjusts count, leaves reserve for next time around bypass cmds 1752//****************************************************************************** 1753static int 1754i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve) 1755{ 1756 int rc = 0; 1757 unsigned long flags; 1758 WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); 1759 if (!pB->i2eWaitingForEmptyFifo) { 1760 if (pB->i2eFifoRemains > (count+reserve)) { 1761 pB->i2eFifoRemains -= count; 1762 iiWriteBuf(pB, source, count); 1763 pB->i2eOutMailWaiting |= MB_OUT_STUFFED; 1764 rc = count; 1765 } 1766 } 1767 WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); 1768 return rc; 1769} 1770//****************************************************************************** 1771// Function: i2StuffFifoBypass(pB) 1772// Parameters: Pointer to a board structure 1773// Returns: Nothing 1774// 1775// Description: 1776// Stuffs as many bypass commands into the fifo as possible. This is simpler 1777// than stuffing data or inline commands to fifo, since we do not have 1778// flow-control to deal with. 1779//****************************************************************************** 1780static inline void 1781i2StuffFifoBypass(i2eBordStrPtr pB) 1782{ 1783 i2ChanStrPtr pCh; 1784 unsigned char *pRemove; 1785 unsigned short stripIndex; 1786 unsigned short packetSize; 1787 unsigned short paddedSize; 1788 unsigned short notClogged = 1; 1789 unsigned long flags; 1790 1791 int bailout = 1000; 1792 1793 // Continue processing so long as there are entries, or there is room in the 1794 // fifo. Each entry represents a channel with something to do. 1795 while ( --bailout && notClogged && 1796 (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS)))) 1797 { 1798 WRITE_LOCK_IRQSAVE(&pCh->Cbuf_spinlock,flags); 1799 stripIndex = pCh->Cbuf_strip; 1800 1801 // as long as there are packets for this channel... 1802 1803 while (stripIndex != pCh->Cbuf_stuff) { 1804 pRemove = &(pCh->Cbuf[stripIndex]); 1805 packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader); 1806 paddedSize = ROUNDUP(packetSize); 1807 1808 if (paddedSize > 0) { 1809 if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) { 1810 notClogged = 0; /* fifo full */ 1811 i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue 1812 break; // Break from the channel 1813 } 1814 } 1815#ifdef DEBUG_FIFO 1816WriteDBGBuf("BYPS", pRemove, paddedSize); 1817#endif /* DEBUG_FIFO */ 1818 pB->debugBypassCount++; 1819 1820 pRemove += packetSize; 1821 stripIndex += packetSize; 1822 if (stripIndex >= CBUF_SIZE) { 1823 stripIndex = 0; 1824 pRemove = pCh->Cbuf; 1825 } 1826 } 1827 // Done with this channel. Move to next, removing this one from 1828 // the queue of channels if we cleaned it out (i.e., didn't get clogged. 1829 pCh->Cbuf_strip = stripIndex; 1830 WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags); 1831 } // Either clogged or finished all the work 1832 1833#ifdef IP2DEBUG_TRACE 1834 if ( !bailout ) { 1835 ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 ); 1836 } 1837#endif 1838} 1839 1840//****************************************************************************** 1841// Function: i2StuffFifoFlow(pB) 1842// Parameters: Pointer to a board structure 1843// Returns: Nothing 1844// 1845// Description: 1846// Stuffs as many flow control packets into the fifo as possible. This is easier 1847// even than doing normal bypass commands, because there is always at most one 1848// packet, already assembled, for each channel. 1849//****************************************************************************** 1850static inline void 1851i2StuffFifoFlow(i2eBordStrPtr pB) 1852{ 1853 i2ChanStrPtr pCh; 1854 unsigned short paddedSize = ROUNDUP(sizeof(flowIn)); 1855 1856 ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2, 1857 pB->i2eFifoRemains, paddedSize ); 1858 1859 // Continue processing so long as there are entries, or there is room in the 1860 // fifo. Each entry represents a channel with something to do. 1861 while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) { 1862 pB->debugFlowCount++; 1863 1864 // NO Chan LOCK needed ??? 1865 if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) { 1866 break; 1867 } 1868#ifdef DEBUG_FIFO 1869 WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize); 1870#endif /* DEBUG_FIFO */ 1871 1872 } // Either clogged or finished all the work 1873 1874 ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 ); 1875} 1876 1877//****************************************************************************** 1878// Function: i2StuffFifoInline(pB) 1879// Parameters: Pointer to a board structure 1880// Returns: Nothing 1881// 1882// Description: 1883// Stuffs as much data and inline commands into the fifo as possible. This is 1884// the most complex fifo-stuffing operation, since there if now the channel 1885// flow-control issue to deal with. 1886//****************************************************************************** 1887static inline void 1888i2StuffFifoInline(i2eBordStrPtr pB) 1889{ 1890 i2ChanStrPtr pCh; 1891 unsigned char *pRemove; 1892 unsigned short stripIndex; 1893 unsigned short packetSize; 1894 unsigned short paddedSize; 1895 unsigned short notClogged = 1; 1896 unsigned short flowsize; 1897 unsigned long flags; 1898 1899 int bailout = 1000; 1900 int bailout2; 1901 1902 ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 1903 pB->i2Dbuf_strip, pB->i2Dbuf_stuff ); 1904 1905 // Continue processing so long as there are entries, or there is room in the 1906 // fifo. Each entry represents a channel with something to do. 1907 while ( --bailout && notClogged && 1908 (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) ) 1909 { 1910 WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags); 1911 stripIndex = pCh->Obuf_strip; 1912 1913 ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff ); 1914 1915 // as long as there are packets for this channel... 1916 bailout2 = 1000; 1917 while ( --bailout2 && stripIndex != pCh->Obuf_stuff) { 1918 pRemove = &(pCh->Obuf[stripIndex]); 1919 1920 // Must determine whether this be a data or command packet to 1921 // calculate correctly the header size and the amount of 1922 // flow-control credit this type of packet will use. 1923 if (PTYPE_OF(pRemove) == PTYPE_DATA) { 1924 flowsize = DATA_COUNT_OF(pRemove); 1925 packetSize = flowsize + sizeof(i2DataHeader); 1926 } else { 1927 flowsize = CMD_COUNT_OF(pRemove); 1928 packetSize = flowsize + sizeof(i2CmdHeader); 1929 } 1930 flowsize = CREDIT_USAGE(flowsize); 1931 paddedSize = ROUNDUP(packetSize); 1932 1933 ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize ); 1934 1935 // If we don't have enough credits from the board to send the data, 1936 // flag the channel that we are waiting for flow control credit, and 1937 // break out. This will clean up this channel and remove us from the 1938 // queue of hot things to do. 1939 1940 ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize ); 1941 1942 if (pCh->outfl.room <= flowsize) { 1943 // Do Not have the credits to send this packet. 1944 i2QueueNeeds(pB, pCh, NEED_CREDIT); 1945 notClogged = 0; 1946 break; // So to do next channel 1947 } 1948 if ( (paddedSize > 0) 1949 && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) { 1950 // Do Not have room in fifo to send this packet. 1951 notClogged = 0; 1952 i2QueueNeeds(pB, pCh, NEED_INLINE); 1953 break; // Break from the channel 1954 } 1955#ifdef DEBUG_FIFO 1956WriteDBGBuf("DATA", pRemove, paddedSize); 1957#endif /* DEBUG_FIFO */ 1958 pB->debugInlineCount++; 1959 1960 pCh->icount.tx += flowsize; 1961 // Update current credits 1962 pCh->outfl.room -= flowsize; 1963 pCh->outfl.asof += flowsize; 1964 if (PTYPE_OF(pRemove) == PTYPE_DATA) { 1965 pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove); 1966 } 1967 pRemove += packetSize; 1968 stripIndex += packetSize; 1969 1970 ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip); 1971 1972 if (stripIndex >= OBUF_SIZE) { 1973 stripIndex = 0; 1974 pRemove = pCh->Obuf; 1975 1976 ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex ); 1977 1978 } 1979 } /* while */ 1980 if ( !bailout2 ) { 1981 ip2trace (CHANN, ITRC_ERROR, 3, 0 ); 1982 } 1983 // Done with this channel. Move to next, removing this one from the 1984 // queue of channels if we cleaned it out (i.e., didn't get clogged. 1985 pCh->Obuf_strip = stripIndex; 1986 WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 1987 if ( notClogged ) 1988 { 1989 1990 ip2trace (CHANN, ITRC_SICMD, 8, 0 ); 1991 1992 if ( pCh->pTTY ) { 1993 ip2_owake(pCh->pTTY); 1994 } 1995 } 1996 } // Either clogged or finished all the work 1997 1998 if ( !bailout ) { 1999 ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 ); 2000 } 2001 2002 ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip); 2003} 2004 2005//****************************************************************************** 2006// Function: serviceOutgoingFifo(pB) 2007// Parameters: Pointer to a board structure 2008// Returns: Nothing 2009// 2010// Description: 2011// Helper routine to put data in the outgoing fifo, if we aren't already waiting 2012// for something to be there. If the fifo has only room for a very little data, 2013// go head and hit the board with a mailbox hit immediately. Otherwise, it will 2014// have to happen later in the interrupt processing. Since this routine may be 2015// called both at interrupt and foreground time, we must turn off interrupts 2016// during the entire process. 2017//****************************************************************************** 2018static void 2019serviceOutgoingFifo(i2eBordStrPtr pB) 2020{ 2021 // If we aren't currently waiting for the board to empty our fifo, service 2022 // everything that is pending, in priority order (especially, Bypass before 2023 // Inline). 2024 if ( ! pB->i2eWaitingForEmptyFifo ) 2025 { 2026 i2StuffFifoFlow(pB); 2027 i2StuffFifoBypass(pB); 2028 i2StuffFifoInline(pB); 2029 2030 iiSendPendingMail(pB); 2031 } 2032} 2033 2034//****************************************************************************** 2035// Function: i2ServiceBoard(pB) 2036// Parameters: Pointer to a board structure 2037// Returns: Nothing 2038// 2039// Description: 2040// Normally this is called from interrupt level, but there is deliberately 2041// nothing in here specific to being called from interrupt level. All the 2042// hardware-specific, interrupt-specific things happen at the outer levels. 2043// 2044// For example, a timer interrupt could drive this routine for some sort of 2045// polled operation. The only requirement is that the programmer deal with any 2046// atomiticity/concurrency issues that result. 2047// 2048// This routine responds to the board's having sent mailbox information to the 2049// host (which would normally cause an interrupt). This routine reads the 2050// incoming mailbox. If there is no data in it, this board did not create the 2051// interrupt and/or has nothing to be done to it. (Except, if we have been 2052// waiting to write mailbox data to it, we may do so. 2053// 2054// Based on the value in the mailbox, we may take various actions. 2055// 2056// No checking here of pB validity: after all, it shouldn't have been called by 2057// the handler unless pB were on the list. 2058//****************************************************************************** 2059static inline int 2060i2ServiceBoard ( i2eBordStrPtr pB ) 2061{ 2062 unsigned inmail; 2063 unsigned long flags; 2064 2065 2066 /* This should be atomic because of the way we are called... */ 2067 if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) { 2068 inmail = iiGetMail(pB); 2069 } 2070 pB->i2eStartMail = NO_MAIL_HERE; 2071 2072 ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail ); 2073 2074 if (inmail != NO_MAIL_HERE) { 2075 // If the board has gone fatal, nothing to do but hit a bit that will 2076 // alert foreground tasks to protest! 2077 if ( inmail & MB_FATAL_ERROR ) { 2078 pB->i2eFatal = 1; 2079 goto exit_i2ServiceBoard; 2080 } 2081 2082 /* Assuming no fatal condition, we proceed to do work */ 2083 if ( inmail & MB_IN_STUFFED ) { 2084 pB->i2eFifoInInts++; 2085 i2StripFifo(pB); /* There might be incoming packets */ 2086 } 2087 2088 if (inmail & MB_OUT_STRIPPED) { 2089 pB->i2eFifoOutInts++; 2090 WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags); 2091 pB->i2eFifoRemains = pB->i2eFifoSize; 2092 pB->i2eWaitingForEmptyFifo = 0; 2093 WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags); 2094 2095 ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains ); 2096 2097 } 2098 serviceOutgoingFifo(pB); 2099 } 2100 2101 ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 ); 2102 2103exit_i2ServiceBoard: 2104 2105 return 0; 2106} 2107