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

📄 i2lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidi2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type){	unsigned short queueIndex;	unsigned long flags;	// We turn off all the interrupts during this brief process, since the	// interrupt-level code might want to put things on the queue as well.	switch (type) {	case NEED_INLINE:		WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags);		if ( !(pCh->channelNeeds & NEED_INLINE) )		{			pCh->channelNeeds |= NEED_INLINE;			queueIndex = pB->i2Dbuf_stuff;			pB->i2Dbuf[queueIndex++] = pCh;			if (queueIndex >= CH_QUEUE_SIZE)				queueIndex = 0;			pB->i2Dbuf_stuff = queueIndex;		}		WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 		break;	case NEED_BYPASS:		WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags);		if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))		{			pCh->channelNeeds |= NEED_BYPASS;			queueIndex = pB->i2Bbuf_stuff;			pB->i2Bbuf[queueIndex++] = pCh;			if (queueIndex >= CH_QUEUE_SIZE)				queueIndex = 0;			pB->i2Bbuf_stuff = queueIndex;		} 		WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 		break;	case NEED_FLOW:		WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags);		if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))		{			pCh->channelNeeds |= NEED_FLOW;			queueIndex = pB->i2Fbuf_stuff;			pB->i2Fbuf[queueIndex++] = pCh;			if (queueIndex >= CH_QUEUE_SIZE)				queueIndex = 0;			pB->i2Fbuf_stuff = queueIndex;		}		WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 		break;	case NEED_CREDIT:		pCh->channelNeeds |= NEED_CREDIT;		break;	default:		printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);		break;	}	return;}//******************************************************************************// Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE//             pointer to the channel structure//             maximum period to wait//             number of commands (n)//             n commands// Returns:    Number of commands sent, or -1 for error//// get board lock before calling//// Description:// Queues up some commands to be sent to a channel. To send possibly several// bypass or inline commands to the given channel. The timeout parameter// indicates how many HUNDREDTHS OF SECONDS to wait until there is room:// 0 = return immediately if no room, -ive  = wait forever, +ive = number of// 1/100 seconds to wait. Return values:// -1 Some kind of nasty error: bad channel structure or invalid arguments.//  0 No room to send all the commands// (+)   Number of commands sent//******************************************************************************static inti2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,					 cmdSyntaxPtr pCs0,...){	int totalsize = 0;	int blocksize;	int lastended;	cmdSyntaxPtr *ppCs;	cmdSyntaxPtr pCs;	int count;	int flag;	i2eBordStrPtr pB;	unsigned short maxBlock;	unsigned short maxBuff;	short bufroom;	unsigned short stuffIndex;	unsigned char *pBuf;	unsigned char *pInsert;	unsigned char *pDest, *pSource;	unsigned short channel;	int cnt;	unsigned long flags = 0;	rwlock_t *lock_var_p = NULL;	// Make sure the channel exists, otherwise do nothing	if ( !i2Validate ( pCh ) ) {		return -1;	}	ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );	pB = pCh->pMyBord;	// Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT	if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == IRQ_UNDEFINED) {		return -2;	}	// 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 -3;	}	// Set up some variables, Which buffers are we using?  How big are they?	switch(type)	{	case PTYPE_INLINE:		flag = INL;		maxBlock = MAX_OBUF_BLOCK;		maxBuff = OBUF_SIZE;		pBuf = pCh->Obuf;		break;	case PTYPE_BYPASS:		flag = BYP;		maxBlock = MAX_CBUF_BLOCK;		maxBuff = CBUF_SIZE;		pBuf = pCh->Cbuf;		break;	default:		return -4;	}	// Determine the total size required for all the commands	totalsize = blocksize = sizeof(i2CmdHeader);	lastended = 0;	ppCs = &pCs0;	for ( count = nCommands; count; count--, ppCs++)	{		pCs = *ppCs;		cnt = pCs->length;		// Will a new block be needed for this one? 		// Two possible reasons: too		// big or previous command has to be at the end of a packet.		if ((blocksize + cnt > maxBlock) || lastended) {			blocksize = sizeof(i2CmdHeader);			totalsize += sizeof(i2CmdHeader);		}		totalsize += cnt;		blocksize += cnt;		// If this command had to end a block, then we will make sure to		// account for it should there be any more blocks.		lastended = pCs->flags & END;	}	for (;;) {		// Make sure any pending flush commands go out before we add more data.		if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {			// How much room (this time through) ?			switch(type) {			case PTYPE_INLINE:				lock_var_p = &pCh->Obuf_spinlock;				WRITE_LOCK_IRQSAVE(lock_var_p,flags);				stuffIndex = pCh->Obuf_stuff;				bufroom = pCh->Obuf_strip - stuffIndex;				break;			case PTYPE_BYPASS:				lock_var_p = &pCh->Cbuf_spinlock;				WRITE_LOCK_IRQSAVE(lock_var_p,flags);				stuffIndex = pCh->Cbuf_stuff;				bufroom = pCh->Cbuf_strip - stuffIndex;				break;			default:				return -5;			}			if (--bufroom < 0) {				bufroom += maxBuff;			}			ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );			// Check for overflow			if (totalsize <= bufroom) {				// Normal Expected path - We still hold LOCK				break; /* from for()- Enough room: goto proceed */			}		}		ip2trace (CHANN, ITRC_QUEUE, 3, 1, totalsize );		// Prepare to wait for buffers to empty		WRITE_UNLOCK_IRQRESTORE(lock_var_p,flags); 		serviceOutgoingFifo(pB);	// Dump what we got		if (timeout == 0) {			return 0;   // Tired of waiting		}		if (timeout > 0)			timeout--;   // So negative values == forever				if (!in_interrupt()) {			schedule_timeout_interruptible(1);	// short nap		} else {			// we cannot sched/sleep in interrrupt silly			return 0;   		}		if (signal_pending(current)) {			return 0;   // Wake up! Time to die!!!		}		ip2trace (CHANN, ITRC_QUEUE, 4, 0 );	}	// end of for(;;)	// At this point we have room and the lock - stick them in.	channel = pCh->infl.hd.i2sChannel;	pInsert = &pBuf[stuffIndex];     // Pointer to start of packet	pDest = CMD_OF(pInsert);         // Pointer to start of command	// When we start counting, the block is the size of the header	for (blocksize = sizeof(i2CmdHeader), count = nCommands,			lastended = 0, ppCs = &pCs0;		count;		count--, ppCs++)	{		pCs = *ppCs;         // Points to command protocol structure		// If this is a bookmark request command, post the fact that a bookmark		// request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ		// has no parameters!  The more general solution would be to reference		// pCs->cmd[0].		if (pCs == CMD_BMARK_REQ) {			pCh->bookMarks++;			ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );		}		cnt = pCs->length;		// If this command would put us over the maximum block size or 		// if the last command had to be at the end of a block, we end		// the existing block here and start a new one.		if ((blocksize + cnt > maxBlock) || lastended) {			ip2trace (CHANN, ITRC_QUEUE, 5, 0 );			PTYPE_OF(pInsert) = type;			CHANNEL_OF(pInsert) = channel;			// count here does not include the header			CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);			stuffIndex += blocksize;			if(stuffIndex >= maxBuff) {				stuffIndex = 0;				pInsert = pBuf;			}			pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt			pDest = CMD_OF(pInsert);			blocksize = sizeof(i2CmdHeader);		}		// Now we know there is room for this one in the current block		blocksize += cnt;       // Total bytes in this command		pSource = pCs->cmd;     // Copy the command into the buffer		while (cnt--) {			*pDest++ = *pSource++;		}		// If this command had to end a block, then we will make sure to account		// for it should there be any more blocks.		lastended = pCs->flags & END;	}	// end for	// Clean up the final block by writing header, etc	PTYPE_OF(pInsert) = type;	CHANNEL_OF(pInsert) = channel;	// count here does not include the header	CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);	stuffIndex += blocksize;	if(stuffIndex >= maxBuff) {		stuffIndex = 0;		pInsert = pBuf;	}	// Updates the index, and post the need for service. When adding these to	// the queue of channels, we turn off the interrupt while doing so,	// because at interrupt level we might want to push a channel back to the	// end of the queue.	switch(type)	{	case PTYPE_INLINE:		pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer		WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 		pB->debugInlineQueued++;		// Add the channel pointer to list of channels needing service (first		// come...), if it's not already there.		i2QueueNeeds(pB, pCh, NEED_INLINE);		break;	case PTYPE_BYPASS:		pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer		WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags); 		pB->debugBypassQueued++;		// Add the channel pointer to list of channels needing service (first		// come...), if it's not already there.		i2QueueNeeds(pB, pCh, NEED_BYPASS);		break;	}	ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );	return nCommands; // Good status: number of commands sent}//******************************************************************************// Function:   i2GetStatus(pCh,resetBits)// Parameters: Pointer to a channel structure//             Bit map of status bits to clear// Returns:    Bit map of current status bits//// Description:// Returns the state of data set signals, and whether a break has been received,// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared// AFTER the condition is passed. If pCh does not point to a valid channel,// returns -1 (which would be impossible otherwise.//******************************************************************************static inti2GetStatus(i2ChanStrPtr pCh, int resetBits){	unsigned short status;	i2eBordStrPtr pB;	ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );	// Make sure the channel exists, otherwise do nothing */	if ( !i2Validate ( pCh ) )		return -1;	pB = pCh->pMyBord;	status = pCh->dataSetIn;	// Clear any specified error bits: but note that only actual error bits can	// be cleared, regardless of the value passed.	if (resetBits)	{		pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));		pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);	}	ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );	return status;}//******************************************************************************// Function:   i2Input(pChpDest,count)// Parameters: Pointer to a channel structure//             Pointer to data buffer//             Number of bytes to read// Returns:    Number of bytes read, or -1 for error//// Description:// Strips data from the input buffer and writes it to pDest. If there is a// collosal blunder, (invalid structure pointers or the like), returns -1.// Otherwise, returns the number of bytes read.//******************************************************************************static inti2Input(i2ChanStrPtr pCh){	int amountToMove;	unsigned short stripIndex;	int count;	unsigned long flags = 0;	ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);	// Ensure channel structure seems real	if ( !i2Validate( pCh ) ) {		count = -1;		goto i2Input_exit;	}	WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);	// initialize some accelerators and private copies	stripIndex = pCh->Ibuf_strip;	count = pCh->Ibuf_stuff - stripIndex;	// If buffer is empty or requested data count was 0, (trivial case) return	// without any further thought.	if ( count == 0 ) {		WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);		goto i2Input_exit;	}	// Adjust for buffer wrap	if ( count < 0 ) {		count += IBUF_SIZE;	}	// Don't give more than can be taken by the line discipline	amountToMove = pCh->pTTY->ldisc.receive_room( pCh->pTTY );	if (count > amountToMove) {		count = amountToMove;	}	// How much could we copy without a wrap?	amountToMove = IBUF_SIZE - stripIndex;	if (amountToMove > count) {		amountToMove = count;	}	// Move the first block	pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 		 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );	// If we needed to wrap, do the second data move	if (count > amountToMove) {		pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 		 pCh->Ibuf, NULL, count - amountToMove );	}	// Bump and wrap the stripIndex all at once by the amount of data read. This	// method is good regardless of whether the data was in one or two pieces.

⌨️ 快捷键说明

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