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

📄 i2lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	stripIndex += count;	if (stripIndex >= IBUF_SIZE) {		stripIndex -= IBUF_SIZE;	}	pCh->Ibuf_strip = stripIndex;	// Update our flow control information and possibly queue ourselves to send	// it, depending on how much data has been stripped since the last time a	// packet was sent.	pCh->infl.asof += count;	if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {		pCh->sinceLastFlow -= pCh->whenSendFlow;		WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);	} else {		WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);	}i2Input_exit:	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);	return count;}//******************************************************************************// Function:   i2InputFlush(pCh)// Parameters: Pointer to a channel structure// Returns:    Number of bytes stripped, or -1 for error//// Description:// Strips any data from the input buffer. If there is a collosal blunder,// (invalid structure pointers or the like), returns -1. Otherwise, returns the// number of bytes stripped.//******************************************************************************static inti2InputFlush(i2ChanStrPtr pCh){	int count;	unsigned long flags;	// Ensure channel structure seems real	if ( !i2Validate ( pCh ) )		return -1;	ip2trace (CHANN, ITRC_INPUT, 10, 0);	WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;	// Adjust for buffer wrap	if (count < 0) {		count += IBUF_SIZE;	}	// Expedient way to zero out the buffer	pCh->Ibuf_strip = pCh->Ibuf_stuff;	// Update our flow control information and possibly queue ourselves to send	// it, depending on how much data has been stripped since the last time a	// packet was sent.	pCh->infl.asof += count;	if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )	{		pCh->sinceLastFlow -= pCh->whenSendFlow;		WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);	} else {		WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);	}	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);	return count;}//******************************************************************************// Function:   i2InputAvailable(pCh)// Parameters: Pointer to a channel structure// Returns:    Number of bytes available, or -1 for error//// Description:// If there is a collosal blunder, (invalid structure pointers or the like),// returns -1. Otherwise, returns the number of bytes stripped. Otherwise,// returns the number of bytes available in the buffer.//******************************************************************************#if 0static inti2InputAvailable(i2ChanStrPtr pCh){	int count;	// Ensure channel structure seems real	if ( !i2Validate ( pCh ) ) return -1;	// initialize some accelerators and private copies	READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;	READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);	// Adjust for buffer wrap	if (count < 0)	{		count += IBUF_SIZE;	}	return count;}#endif //******************************************************************************// Function:   i2Output(pCh, pSource, count)// Parameters: Pointer to channel structure//             Pointer to source data//             Number of bytes to send// Returns:    Number of bytes sent, or -1 for error//// Description:// Queues the data at pSource to be sent as data packets to the board. If there// is a collosal blunder, (invalid structure pointers or the like), returns -1.// Otherwise, returns the number of bytes written. What if there is not enough// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then// we transfer as many characters as we can now, then return. If this bit is// clear (default), routine will spin along until all the data is buffered.// Should this occur, the 1-ms delay routine is called while waiting to avoid// applications that one cannot break out of.//******************************************************************************static inti2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user ){	i2eBordStrPtr pB;	unsigned char *pInsert;	int amountToMove;	int countOriginal = count;	unsigned short channel;	unsigned short stuffIndex;	unsigned long flags;	int rc = 0;	int bailout = 10;	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, user );	// Ensure channel structure seems real	if ( !i2Validate ( pCh ) ) 		return -1;	// initialize some accelerators and private copies	pB = pCh->pMyBord;	channel = pCh->infl.hd.i2sChannel;	// If the board has gone fatal, return bad, and also hit the trap routine if	// it exists.	if (pB->i2eFatal) {		if (pB->i2eFatalTrap) {			(*(pB)->i2eFatalTrap)(pB);		}		return -1;	}	// Proceed as though we would do everything	while ( count > 0 ) {		// How much room in output buffer is there?		READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);		amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;		READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);		if (amountToMove < 0) {			amountToMove += OBUF_SIZE;		}		// Subtract off the headers size and see how much room there is for real		// data. If this is negative, we will discover later.		amountToMove -= sizeof (i2DataHeader);		// Don't move more (now) than can go in a single packet		if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {			amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);		}		// Don't move more than the count we were given		if (amountToMove > count) {			amountToMove = count;		}		// Now we know how much we must move: NB because the ring buffers have		// an overflow area at the end, we needn't worry about wrapping in the		// middle of a packet.// Small WINDOW here with no LOCK but I can't call Flush with LOCK// We would be flushing (or ending flush) anyway		ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );		if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 				&& amountToMove > 0 )		{			WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);			stuffIndex = pCh->Obuf_stuff;      			// Had room to move some data: don't know whether the block size,			// buffer space, or what was the limiting factor...			pInsert = &(pCh->Obuf[stuffIndex]);			// Set up the header			CHANNEL_OF(pInsert)     = channel;			PTYPE_OF(pInsert)       = PTYPE_DATA;			TAG_OF(pInsert)         = 0;			ID_OF(pInsert)          = ID_ORDINARY_DATA;			DATA_COUNT_OF(pInsert)  = amountToMove;			// Move the data			if ( user ) {				rc = copy_from_user((char*)(DATA_OF(pInsert)), pSource,						amountToMove );			} else {				memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );			}			// Adjust pointers and indices			pSource					+= amountToMove;			pCh->Obuf_char_count	+= amountToMove;			stuffIndex 				+= amountToMove + sizeof(i2DataHeader);			count 					-= amountToMove;			if (stuffIndex >= OBUF_SIZE) {				stuffIndex = 0;			}			pCh->Obuf_stuff = stuffIndex;			WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );		} else {			// Cannot move data			// becuz we need to stuff a flush 			// or amount to move is <= 0			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,				amountToMove,  pB->i2eFifoRemains,				pB->i2eWaitingForEmptyFifo );			// Put this channel back on queue			// this ultimatly gets more data or wakes write output			i2QueueNeeds(pB, pCh, NEED_INLINE);			if ( pB->i2eWaitingForEmptyFifo ) {				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );				// or schedule				if (!in_interrupt()) {					ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );					schedule_timeout_interruptible(2);					if (signal_pending(current)) {						break;					}					continue;				} else {					ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );					// let interrupt in = WAS restore_flags()					// We hold no lock nor is irq off anymore???										break;				}				break;   // from while(count)			}			else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )			{				ip2trace (CHANN, ITRC_OUTPUT, 19, 2,					pB->i2eFifoRemains,					pB->i2eTxMailEmpty );				break;   // from while(count)			} else if ( pCh->channelNeeds & NEED_CREDIT ) {				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );				break;   // from while(count)			} else if ( --bailout) {				// Try to throw more things (maybe not us) in the fifo if we're				// not already waiting for it.					ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );				serviceOutgoingFifo(pB);				//break;  CONTINUE;			} else {				ip2trace (CHANN, ITRC_OUTPUT, 21, 3,					pB->i2eFifoRemains,					pB->i2eOutMailWaiting,					pB->i2eWaitingForEmptyFifo );				break;   // from while(count)			}		}	} // End of while(count)	i2QueueNeeds(pB, pCh, NEED_INLINE);	// We drop through either when the count expires, or when there is some	// count left, but there was a non-blocking write.	if (countOriginal > count) {		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );		serviceOutgoingFifo( pB );	}	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );	return countOriginal - count;}//******************************************************************************// Function:   i2FlushOutput(pCh)// Parameters: Pointer to a channel structure// Returns:    Nothing//// Description:// Sends bypass command to start flushing (waiting possibly forever until there// is room), then sends inline command to stop flushing output, (again waiting// possibly forever).//******************************************************************************static inline voidi2FlushOutput(i2ChanStrPtr pCh){	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );	if (pCh->flush_flags)		return;	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );	}}static int i2RetryFlushOutput(i2ChanStrPtr pCh){	int old_flags = pCh->flush_flags;	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );	pCh->flush_flags = 0;	// Clear flag so we can avoid recursion									// and queue the commands	if ( old_flags & STARTFL_FLAG ) {		if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {			old_flags = STOPFL_FLAG;	//Success - send stop flush		} else {			old_flags = STARTFL_FLAG;	//Failure - Flag for retry later		}		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );	}	if ( old_flags & STOPFL_FLAG ) {		if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {			old_flags = 0;	// Success - clear flags		}		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );	}	pCh->flush_flags = old_flags;	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );	return old_flags;}//******************************************************************************// Function:   i2DrainOutput(pCh,timeout)// Parameters: Pointer to a channel structure//             Maximum period to wait// Returns:    ?//// Description:// Uses the bookmark request command to ask the board to send a bookmark back as// soon as all the data is completely sent.//******************************************************************************static voidi2DrainWakeup(i2ChanStrPtr pCh){	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );	pCh->BookmarkTimer.expires = 0;	wake_up_interruptible( &pCh->pBookmarkWait );}static voidi2DrainOutput(i2ChanStrPtr pCh, int timeout){	wait_queue_t wait;	i2eBordStrPtr pB;	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);	pB = pCh->pMyBord;	// If the board has gone fatal, return bad, 	// and also hit the trap routine if it exists.	if (pB->i2eFatal) {		if (pB->i2eFatalTrap) {			(*(pB)->i2eFatalTrap)(pB);		}		return;	}	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {		// One per customer (channel)		init_timer( &(pCh->BookmarkTimer) );		pCh->BookmarkTimer.expires  = jiffies + timeout;		pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup;		pCh->BookmarkTimer.data     = (unsigned long)pCh;		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );		add_timer( &(pCh->BookmarkTimer) );	}		i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );	init_waitqueue_entry(&wait, current);	add_wait_queue(&(pCh->pBookmarkWait), &wait);

⌨️ 快捷键说明

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