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

📄 i2lib.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		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:#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);#endif	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;#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_INPUT, 10, 0);#endif	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);	}#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);#endif	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;#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, user );#endif	// 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#ifdef IP2DEBUG_TRACE			ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );#endif		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 ) {				COPY_FROM_USER(rc, (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);#ifdef IP2DEBUG_TRACE			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );#endif		} else {			// Cannot move data			// becuz we need to stuff a flush 			// or amount to move is <= 0#ifdef IP2DEBUG_TRACE			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,				amountToMove,  pB->i2eFifoRemains, pB->i2eWaitingForEmptyFifo );#endif			// Put this channel back on queue			// this ultimatly gets more data or wakes write output			i2QueueNeeds(pB, pCh, NEED_INLINE);			if ( pB->i2eWaitingForEmptyFifo ) {#ifdef IP2DEBUG_TRACE				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );#endif				// or schedule				if (!in_interrupt()) {#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );#endif					current->state = TASK_INTERRUPTIBLE;					schedule_timeout(2);					if (signal_pending(current)) {						break;					}					continue;				} else {#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );#endif					// 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 ) )			{#ifdef IP2DEBUG_TRACE				ip2trace (CHANN, ITRC_OUTPUT, 19, 2, pB->i2eFifoRemains,									pB->i2eTxMailEmpty );#endif				break;   // from while(count)			} else if ( pCh->channelNeeds & NEED_CREDIT ) {#ifdef IP2DEBUG_TRACE				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );#endif				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.	#ifdef IP2DEBUG_TRACE				ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );#endif				serviceOutgoingFifo(pB);				//break;  CONTINUE;			} else {#ifdef IP2DEBUG_TRACE				ip2trace (CHANN, ITRC_OUTPUT, 21, 3, pB->i2eFifoRemains,							pB->i2eOutMailWaiting, pB->i2eWaitingForEmptyFifo );#endif				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) {#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );#endif		serviceOutgoingFifo( pB );	}#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );#endif	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){#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );#endif	if (pCh->flush_flags)		return;	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );#endif	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );#endif	}}static int i2RetryFlushOutput(i2ChanStrPtr pCh){	int old_flags = pCh->flush_flags;#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );#endif	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		}#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );#endif	}	if ( old_flags & STOPFL_FLAG ) {		if ( 1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) > 0 ) {			old_flags = 0;	// Success - clear flags		}#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );#endif	}   pCh->flush_flags = old_flags;#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );#endif	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){#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );#endif	pCh->BookmarkTimer.expires = 0;	wake_up_interruptible( &pCh->pBookmarkWait );}static voidi2DrainOutput(i2ChanStrPtr pCh, int timeout){	i2eBordStrPtr pB;#ifdef IP2DEBUG_TRACE	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);#endif	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;#ifdef IP2DEBUG_TRACE		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );#endif

⌨️ 快捷键说明

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