⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
					case STAT_STATUS:						pCh->channelStatus = *((debugStatPtr)pc);						pc += sizeof(debugStat);						break;					case STAT_TXCNT:						pCh->channelTcount = *((cntStatPtr)pc);						pc += sizeof(cntStat);						break;					case STAT_RXCNT:						pCh->channelRcount = *((cntStatPtr)pc);						pc += sizeof(cntStat);						break;					case STAT_BOXIDS:						pB->channelBtypes = *((bidStatPtr)pc);						pc += sizeof(bidStat);						set_baud_params(pB);						break;					case STAT_HWFAIL:						i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);						pCh->channelFail = *((failStatPtr)pc);						pc += sizeof(failStat);						break;					/* No explicit match? then					 * Might be an error packet...					 */					default:						switch (uc & STAT_MOD_ERROR)						{						case STAT_ERROR:							if (uc & STAT_E_PARITY) {								pCh->dataSetIn |= I2_PAR;								pCh->icount.parity++;							}							if (uc & STAT_E_FRAMING){								pCh->dataSetIn |= I2_FRA;								pCh->icount.frame++;							}							if (uc & STAT_E_OVERRUN){								pCh->dataSetIn |= I2_OVR;								pCh->icount.overrun++;							}							break;						case STAT_MODEM:							// the answer to DSS_NOW request (not change)							pCh->dataSetIn = (pCh->dataSetIn								& ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )								| xlatDss[uc & 0xf];							wake_up_interruptible ( &pCh->dss_now_wait );						default:							break;						}					}  /* End of switch on status type */					if (dss_change) {#ifdef USE_IQ						schedule_work(&pCh->tqueue_status);#else						do_status(pCh);#endif					}				}				else  /* Or else, channel is invalid */				{					// Even though the channel is invalid, we must test the					// status to see how much additional data it has (to be					// skipped)					switch (*pc++)					{					case STAT_FLOW:						pc += 4;    /* Skip the data */						break;					default:						break;					}				}			}  // End of while (there is still some status packet left)			break;		default: // Neither packet? should be impossible			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,				PTYPE_OF(pB->i2eLeadoffWord) );			break;		}  // End of switch on type of packets	}	//while(board HAS_INPUT)	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );	// Send acknowledgement to the board even if there was no data!	pB->i2eOutMailWaiting |= MB_IN_STRIPPED;	return;}//******************************************************************************// Function:   i2Write2Fifo(pB,address,count)// Parameters: Pointer to a board structure, source address, byte count// Returns:    bytes written//// Description://  Writes count bytes to board io address(implied) from source//  Adjusts count, leaves reserve for next time around bypass cmds//******************************************************************************static inti2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve){	int rc = 0;	unsigned long flags;	WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);	if (!pB->i2eWaitingForEmptyFifo) {		if (pB->i2eFifoRemains > (count+reserve)) {			pB->i2eFifoRemains -= count;			iiWriteBuf(pB, source, count);			pB->i2eOutMailWaiting |= MB_OUT_STUFFED;			rc =  count;		}	}	WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);	return rc;}//******************************************************************************// Function:   i2StuffFifoBypass(pB)// Parameters: Pointer to a board structure// Returns:    Nothing//// Description:// Stuffs as many bypass commands into the fifo as possible. This is simpler// than stuffing data or inline commands to fifo, since we do not have// flow-control to deal with.//******************************************************************************static inline voidi2StuffFifoBypass(i2eBordStrPtr pB){	i2ChanStrPtr pCh;	unsigned char *pRemove;	unsigned short stripIndex;	unsigned short packetSize;	unsigned short paddedSize;	unsigned short notClogged = 1;	unsigned long flags;	int bailout = 1000;	// Continue processing so long as there are entries, or there is room in the	// fifo. Each entry represents a channel with something to do.	while ( --bailout && notClogged && 			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))	{		WRITE_LOCK_IRQSAVE(&pCh->Cbuf_spinlock,flags);		stripIndex = pCh->Cbuf_strip;		// as long as there are packets for this channel...		while (stripIndex != pCh->Cbuf_stuff) {			pRemove = &(pCh->Cbuf[stripIndex]);			packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);			paddedSize = ROUNDUP(packetSize);			if (paddedSize > 0) {				if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {					notClogged = 0;	/* fifo full */					i2QueueNeeds(pB, pCh, NEED_BYPASS);	// Put back on queue					break;   // Break from the channel				} 			}#ifdef DEBUG_FIFOWriteDBGBuf("BYPS", pRemove, paddedSize);#endif	/* DEBUG_FIFO */			pB->debugBypassCount++;			pRemove += packetSize;			stripIndex += packetSize;			if (stripIndex >= CBUF_SIZE) {				stripIndex = 0;				pRemove = pCh->Cbuf;			}		}		// Done with this channel. Move to next, removing this one from 		// the queue of channels if we cleaned it out (i.e., didn't get clogged.		pCh->Cbuf_strip = stripIndex;		WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags);	}  // Either clogged or finished all the work#ifdef IP2DEBUG_TRACE	if ( !bailout ) {		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );	}#endif}//******************************************************************************// Function:   i2StuffFifoFlow(pB)// Parameters: Pointer to a board structure// Returns:    Nothing//// Description:// Stuffs as many flow control packets into the fifo as possible. This is easier// even than doing normal bypass commands, because there is always at most one// packet, already assembled, for each channel.//******************************************************************************static inline voidi2StuffFifoFlow(i2eBordStrPtr pB){	i2ChanStrPtr pCh;	unsigned short paddedSize		= ROUNDUP(sizeof(flowIn));	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,		pB->i2eFifoRemains, paddedSize );	// Continue processing so long as there are entries, or there is room in the	// fifo. Each entry represents a channel with something to do.	while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {		pB->debugFlowCount++;		// NO Chan LOCK needed ???		if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {			break;		}#ifdef DEBUG_FIFO		WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);#endif /* DEBUG_FIFO */	}  // Either clogged or finished all the work	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );}//******************************************************************************// Function:   i2StuffFifoInline(pB)// Parameters: Pointer to a board structure// Returns:    Nothing//// Description:// Stuffs as much data and inline commands into the fifo as possible. This is// the most complex fifo-stuffing operation, since there if now the channel// flow-control issue to deal with.//******************************************************************************static inline voidi2StuffFifoInline(i2eBordStrPtr pB){	i2ChanStrPtr pCh;	unsigned char *pRemove;	unsigned short stripIndex;	unsigned short packetSize;	unsigned short paddedSize;	unsigned short notClogged = 1;	unsigned short flowsize;	unsigned long flags;	int bailout  = 1000;	int bailout2;	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 			pB->i2Dbuf_strip, pB->i2Dbuf_stuff );	// Continue processing so long as there are entries, or there is room in the	// fifo. Each entry represents a channel with something to do.	while ( --bailout && notClogged && 			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )	{		WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);		stripIndex = pCh->Obuf_strip;		ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );		// as long as there are packets for this channel...		bailout2 = 1000;		while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {			pRemove = &(pCh->Obuf[stripIndex]);			// Must determine whether this be a data or command packet to			// calculate correctly the header size and the amount of			// flow-control credit this type of packet will use.			if (PTYPE_OF(pRemove) == PTYPE_DATA) {				flowsize = DATA_COUNT_OF(pRemove);				packetSize = flowsize + sizeof(i2DataHeader);			} else {				flowsize = CMD_COUNT_OF(pRemove);				packetSize = flowsize + sizeof(i2CmdHeader);			}			flowsize = CREDIT_USAGE(flowsize);			paddedSize = ROUNDUP(packetSize);			ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );			// If we don't have enough credits from the board to send the data,			// flag the channel that we are waiting for flow control credit, and			// break out. This will clean up this channel and remove us from the			// queue of hot things to do.				ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );			if (pCh->outfl.room <= flowsize)	{				// Do Not have the credits to send this packet.				i2QueueNeeds(pB, pCh, NEED_CREDIT);				notClogged = 0;				break;   // So to do next channel			}			if ( (paddedSize > 0) 				&& ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {				// Do Not have room in fifo to send this packet.				notClogged = 0;				i2QueueNeeds(pB, pCh, NEED_INLINE);					break;   // Break from the channel			}#ifdef DEBUG_FIFOWriteDBGBuf("DATA", pRemove, paddedSize);#endif /* DEBUG_FIFO */			pB->debugInlineCount++;			pCh->icount.tx += flowsize;			// Update current credits			pCh->outfl.room -= flowsize;			pCh->outfl.asof += flowsize;			if (PTYPE_OF(pRemove) == PTYPE_DATA) {				pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);			}			pRemove += packetSize;			stripIndex += packetSize;			ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);			if (stripIndex >= OBUF_SIZE) {				stripIndex = 0;				pRemove = pCh->Obuf;				ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );			}		}	/* while */		if ( !bailout2 ) {			ip2trace (CHANN, ITRC_ERROR, 3, 0 );		}		// Done with this channel. Move to next, removing this one from the		// queue of channels if we cleaned it out (i.e., didn't get clogged.		pCh->Obuf_strip = stripIndex;		WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);		if ( notClogged )		{			ip2trace (CHANN, ITRC_SICMD, 8, 0 );			if ( pCh->pTTY ) {				ip2_owake(pCh->pTTY);			}		}	}  // Either clogged or finished all the work	if ( !bailout ) {		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );	}	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);}//******************************************************************************// Function:   serviceOutgoingFifo(pB)// Parameters: Pointer to a board structure// Returns:    Nothing//// Description:// Helper routine to put data in the outgoing fifo, if we aren't already waiting// for something to be there. If the fifo has only room for a very little data,// go head and hit the board with a mailbox hit immediately. Otherwise, it will// have to happen later in the interrupt processing. Since this routine may be// called both at interrupt and foreground time, we must turn off interrupts// during the entire process.//******************************************************************************static voidserviceOutgoingFifo(i2eBordStrPtr pB){	// If we aren't currently waiting for the board to empty our fifo, service	// everything that is pending, in priority order (especially, Bypass before	// Inline).	if ( ! pB->i2eWaitingForEmptyFifo )	{		i2StuffFifoFlow(pB);		i2StuffFifoBypass(pB);		i2StuffFifoInline(pB);		iiSendPendingMail(pB);	} }//******************************************************************************// Function:   i2ServiceBoard(pB)// Parameters: Pointer to a board structure// Returns:    Nothing//// Description:// Normally this is called from interrupt level, but there is deliberately// nothing in here specific to being called from interrupt level. All the// hardware-specific, interrupt-specific things happen at the outer levels.//// For example, a timer interrupt could drive this routine for some sort of// polled operation. The only requirement is that the programmer deal with any// atomiticity/concurrency issues that result.//// This routine responds to the board's having sent mailbox information to the// host (which would normally cause an interrupt). This routine reads the// incoming mailbox. If there is no data in it, this board did not create the// interrupt and/or has nothing to be done to it. (Except, if we have been// waiting to write mailbox data to it, we may do so.//// Based on the value in the mailbox, we may take various actions.//// No checking here of pB validity: after all, it shouldn't have been called by// the handler unless pB were on the list.//******************************************************************************static inline inti2ServiceBoard ( i2eBordStrPtr pB ){	unsigned inmail;	unsigned long flags;	/* This should be atomic because of the way we are called... */	if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {		inmail = iiGetMail(pB);	}	pB->i2eStartMail = NO_MAIL_HERE;	ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );	if (inmail != NO_MAIL_HERE) {		// If the board has gone fatal, nothing to do but hit a bit that will		// aler

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -