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

📄 itlpqueue.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
字号:
/* * ItLpQueue.c * Copyright (C) 2001 Mike Corrigan  IBM Corporation *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#include <linux/stddef.h>#include <linux/kernel.h>#include <linux/sched.h>#include <asm/system.h>#include <asm/paca.h>#include <linux/random.h>#include <asm/time.h>#include <asm/iSeries/ItLpQueue.h>#include <asm/iSeries/HvLpEvent.h>#include <asm/iSeries/HvCallEvent.h>#include <asm/iSeries/LparData.h>static __inline__ int set_inUse( struct ItLpQueue * lpQueue ){	int t;	u32 * inUseP = &(lpQueue->xInUseWord);	__asm__ __volatile__("\n\1:	lwarx	%0,0,%2		\n\	cmpi	0,%0,0		\n\	li	%0,0		\n\	bne-	2f		\n\	addi	%0,%0,1		\n\	stwcx.	%0,0,%2		\n\	bne-	1b		\n\2:	eieio"	: "=&r" (t), "=m" (lpQueue->xInUseWord)	: "r" (inUseP), "m" (lpQueue->xInUseWord)	: "cc");	return t;}static __inline__ void clear_inUse( struct ItLpQueue * lpQueue ){	lpQueue->xInUseWord = 0;}/* Array of LpEvent handler functions */extern LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];unsigned long ItLpQueueInProcess = 0;struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * lpQueue ){	struct HvLpEvent * nextLpEvent = 		(struct HvLpEvent *)lpQueue->xSlicCurEventPtr;	if ( nextLpEvent->xFlags.xValid ) {		/* rmb() needed only for weakly consistent machines (regatta) */		rmb();		/* Set pointer to next potential event */		lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +				      LpEventAlign ) /				      LpEventAlign ) *				      LpEventAlign;		/* Wrap to beginning if no room at end */		if (lpQueue->xSlicCurEventPtr > lpQueue->xSlicLastValidEventPtr)			lpQueue->xSlicCurEventPtr = lpQueue->xSlicEventStackPtr;	}	else 		nextLpEvent = NULL;	return nextLpEvent;}int ItLpQueue_isLpIntPending( struct ItLpQueue * lpQueue ){	int retval = 0;	struct HvLpEvent * nextLpEvent;	if ( lpQueue ) {		nextLpEvent = (struct HvLpEvent *)lpQueue->xSlicCurEventPtr;		retval = nextLpEvent->xFlags.xValid | lpQueue->xPlicOverflowIntPending;	}	return retval;}void ItLpQueue_clearValid( struct HvLpEvent * event ){	/* Clear the valid bit of the event	 * Also clear bits within this event that might	 * look like valid bits (on 64-byte boundaries)   	 */	unsigned extra = (( event->xSizeMinus1 + LpEventAlign ) /						 LpEventAlign ) - 1;	switch ( extra ) {	  case 3:	   ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0;	  case 2:	   ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0;	  case 1:	   ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0;	  case 0:	   ;		}	mb();	event->xFlags.xValid = 0;}unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs ){	unsigned numIntsProcessed = 0;	struct HvLpEvent * nextLpEvent;	/* If we have recursed, just return */	if ( !set_inUse( lpQueue ) )		return 0;		if (ItLpQueueInProcess == 0)		ItLpQueueInProcess = 1;	else		BUG();	for (;;) {		nextLpEvent = ItLpQueue_getNextLpEvent( lpQueue );		if ( nextLpEvent ) {			/* Count events to return to caller			 * and count processed events in lpQueue 			 */			++numIntsProcessed;			lpQueue->xLpIntCount++;					/* Call appropriate handler here, passing 			 * a pointer to the LpEvent.  The handler			 * must make a copy of the LpEvent if it			 * needs it in a bottom half. (perhaps for			 * an ACK)			 *				 *  Handlers are responsible for ACK processing 			 *			 * The Hypervisor guarantees that LpEvents will			 * only be delivered with types that we have			 * registered for, so no type check is necessary			 * here!  			 */			if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes )				lpQueue->xLpIntCountByType[nextLpEvent->xType]++;			if ( nextLpEvent->xType < HvLpEvent_Type_NumTypes &&			     lpEventHandler[nextLpEvent->xType] ) 				lpEventHandler[nextLpEvent->xType](nextLpEvent, regs);			else				printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );						ItLpQueue_clearValid( nextLpEvent );		}		else 	/* No more valid events			 * If overflow events are pending			 * process them			 */			if ( lpQueue->xPlicOverflowIntPending ) {				HvCallEvent_getOverflowLpEvents( 						lpQueue->xIndex);			}			else	/* If nothing left then we are done */				break;	}	ItLpQueueInProcess = 0;	mb();	clear_inUse( lpQueue );	get_paca()->lpEvent_count += numIntsProcessed;	/* Use LPEvents as a source of randomness.  Since there	 * Isn't an LPEvent Randomness call, pretend these are	 * mouse events (which is fair since we don't have mice	 * on the iSeries)	 */	add_mouse_randomness(get_tb());	return numIntsProcessed;}

⌨️ 快捷键说明

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