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

📄 ml_sn_intr.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* Try to reserve an interrupt bit on the hub 		 * corresponding to the canidate cnode. If we		 * are successful then we got a cpu which can		 * act as an interrupt target for the io device.		 * Otherwise we need to continue the search		 * further.		 */		*resp_bit = do_intr_reserve_level(cpuid, 						  req_bit,						  intr_resflags,						  II_RESERVE,						  owner_dev, 						  intr_name);		if (*resp_bit >= 0)			/* The interrupt target  specified was fine */			return(cpuid);	}	return(CPU_NONE);}/* * intr_heuristic(dev_t dev,device_desc_t dev_desc, *		  int req_bit,int intr_resflags,dev_t owner_dev, *		  char *intr_name,int *resp_bit) * * Choose an interrupt destination for an interrupt. *	dev is the device for which the interrupt is being set up *	dev_desc is a description of hardware and policy that could *		help determine where this interrupt should go *	req_bit is the interrupt bit requested  *		(can be INTRCONNECT_ANY_BIT in which the first available * 		 interrupt bit is used) *	intr_resflags indicates whether we want to (un)reserve bit *	owner_dev is the owner device *	intr_name is the readable interrupt name	 * 	resp_bit indicates whether we succeeded in getting the required *		 action  { (un)reservation} done	 *		 negative value indicates failure * *//* ARGSUSED */cpuid_tintr_heuristic(devfs_handle_t 		dev,	       device_desc_t 	dev_desc,	       int		req_bit,	       int 		intr_resflags,	       devfs_handle_t 		owner_dev,	       char		*intr_name,	       int		*resp_bit){	cpuid_t		cpuid;				/* possible intr targ*/	cnodeid_t 	candidate;			/* possible canidate */	int		which_subnode = SUBNODE_ANY;/* SN1 + pcibr Addressing Limitation */	{	devfs_handle_t pconn_vhdl;	pcibr_soft_t pcibr_soft;	/*	 * This combination of SN1 and Bridge hardware has an odd "limitation".	 * Due to the choice of addresses for PI0 and PI1 registers on SN1	 * and historical limitations in Bridge, Bridge is unable to	 * send interrupts to both PI0 CPUs and PI1 CPUs -- we have	 * to choose one set or the other.  That choice is implicitly	 * made when Bridge first attaches its error interrupt.  After	 * that point, all subsequent interrupts are restricted to the	 * same PI number (though it's possible to send interrupts to	 * the same PI number on a different node).	 *	 * Since neither SN1 nor Bridge designers are willing to admit a	 * bug, we can't really call this a "workaround".  It's a permanent	 * solution for an SN1-specific and Bridge-specific hardware	 * limitation that won't ever be lifted.	 */        if ((hwgraph_edge_get(dev, EDGE_LBL_PCI, &pconn_vhdl) == GRAPH_SUCCESS) &&	   ((pcibr_soft = pcibr_soft_get(pconn_vhdl)) != NULL)) {		/*		 * We "know" that the error interrupt is the first		 * interrupt set up by pcibr_attach.  Send all interrupts		 * on this bridge to the same subnode number.		 */		if (pcibr_soft->bsi_err_intr) {			which_subnode = cpuid_to_subnode(((hub_intr_t) pcibr_soft->bsi_err_intr)->i_cpuid);		}	}	}	/* Check if we can find a valid interrupt target candidate on	 * the master node for the device.	 */	cpuid = intr_bit_reserve_test(CPU_NONE,				      which_subnode,					      master_node_get(dev),				      req_bit,				      intr_resflags,				      owner_dev,				      intr_name,				      resp_bit);	if (cpuid != CPU_NONE) {		if (cpu_on_subnode(cpuid, which_subnode))			return(cpuid);	/* got a valid interrupt target */		else			intr_unreserve_level(cpuid, *resp_bit);	}	printk(KERN_WARNING  "Cannot target interrupts to closest node(%d): (0x%lx)\n",		master_node_get(dev),(unsigned long)owner_dev);	/* Fall through into the default algorithm	 * (exhaustive-search-for-the-nearest-possible-interrupt-target)	 * for finding the interrupt target	 */	{	/*	 * Do a stupid round-robin assignment of the node.	 *  (Should do a "nearest neighbor" but not for SN1.	 */		static cnodeid_t last_node = -1;		if (last_node >= numnodes) last_node = 0;		for (candidate = last_node + 1; candidate != last_node; candidate++) {			if (candidate == numnodes) candidate = 0;			cpuid = intr_bit_reserve_test(CPU_NONE,					      which_subnode,					      candidate,					      req_bit,					      intr_resflags,					      owner_dev,					      intr_name,					      resp_bit);			if (cpuid != CPU_NONE) {				if (cpu_on_subnode(cpuid, which_subnode)) {					last_node = candidate;					return(cpuid);	/* got a valid interrupt target */				}				else					intr_unreserve_level(cpuid, *resp_bit);			}		}		last_node = candidate;	}	printk(KERN_WARNING  "Cannot target interrupts to any close node: %ld (0x%lx)\n",		(long)owner_dev, (unsigned long)owner_dev);	/* In the worst case try to allocate interrupt bits on the	 * master processor's node. We may get here during error interrupt	 * allocation phase when the topology matrix is not yet setup	 * and hence cannot do an exhaustive search.	 */	ASSERT(cpu_allows_intr(master_procid));	cpuid = intr_bit_reserve_test(master_procid,				      which_subnode,				      CNODEID_NONE,				      req_bit,				      intr_resflags,				      owner_dev,				      intr_name,				      resp_bit);	if (cpuid != CPU_NONE) {		if (cpu_on_subnode(cpuid, which_subnode))			return(cpuid);		else			intr_unreserve_level(cpuid, *resp_bit);	}	printk(KERN_WARNING  "Cannot target interrupts: (0x%lx)\n",		(unsigned long)owner_dev);	return(CPU_NONE);	/* Should never get here */}struct hardwired_intr_s {	signed char level;	int flags;	char *name;} const hardwired_intr[] = {	{ INT_PEND0_BASELVL + RESERVED_INTR,	0,	"Reserved" },	{ INT_PEND0_BASELVL + GFX_INTR_A,	0, 	"Gfx A" },	{ INT_PEND0_BASELVL + GFX_INTR_B,	0, 	"Gfx B" },	{ INT_PEND0_BASELVL + PG_MIG_INTR,	II_THREADED, "Migration" },	{ INT_PEND0_BASELVL + UART_INTR,	II_THREADED, "Bedrock/L1" },	{ INT_PEND0_BASELVL + CC_PEND_A,	0,	"Crosscall A" },	{ INT_PEND0_BASELVL + CC_PEND_B,	0,	"Crosscall B" },	{ INT_PEND1_BASELVL + CLK_ERR_INTR,	II_ERRORINT, "Clock Error" },	{ INT_PEND1_BASELVL + COR_ERR_INTR_A,	II_ERRORINT, "Correctable Error A" },	{ INT_PEND1_BASELVL + COR_ERR_INTR_B,	II_ERRORINT, "Correctable Error B" },	{ INT_PEND1_BASELVL + MD_COR_ERR_INTR,	II_ERRORINT, "MD Correct. Error" },	{ INT_PEND1_BASELVL + NI_ERROR_INTR,	II_ERRORINT, "NI Error" },	{ INT_PEND1_BASELVL + NI_BRDCAST_ERR_A,	II_ERRORINT, "Remote NI Error"},	{ INT_PEND1_BASELVL + NI_BRDCAST_ERR_B,	II_ERRORINT, "Remote NI Error"},	{ INT_PEND1_BASELVL + MSC_PANIC_INTR,	II_ERRORINT, "MSC Panic" },	{ INT_PEND1_BASELVL + LLP_PFAIL_INTR_A,	II_ERRORINT, "LLP Pfail WAR" },	{ INT_PEND1_BASELVL + LLP_PFAIL_INTR_B,	II_ERRORINT, "LLP Pfail WAR" },	{ INT_PEND1_BASELVL + NACK_INT_A,	0, "CPU A Nack count == NACK_CMP" },	{ INT_PEND1_BASELVL + NACK_INT_B,	0, "CPU B Nack count == NACK_CMP" },	{ INT_PEND1_BASELVL + LB_ERROR,		0, "Local Block Error" },	{ INT_PEND1_BASELVL + XB_ERROR,		0, "Local XBar Error" },	{ -1, 0, (char *)NULL},};/* * Reserve all of the hardwired interrupt levels so they're not used as * general purpose bits later. */voidintr_reserve_hardwired(cnodeid_t cnode){	cpuid_t cpu;	int level;	int i;	char subnode_done[NUM_SUBNODES];	// cpu = cnodetocpu(cnode);	for (cpu = 0; cpu < smp_num_cpus; cpu++) {		if (cpuid_to_cnodeid(cpu) == cnode) {			break;		}	}	if (cpu == smp_num_cpus) cpu = CPU_NONE;	if (cpu == CPU_NONE) {		printk("Node %d has no CPUs", cnode);		return;	}	for (i=0; i<NUM_SUBNODES; i++)		subnode_done[i] = 0;	for (; cpu<smp_num_cpus && cpu_enabled(cpu) && cpuid_to_cnodeid(cpu) == cnode; cpu++) {		int which_subnode = cpuid_to_subnode(cpu);		if (subnode_done[which_subnode])			continue;		subnode_done[which_subnode] = 1;		for (i = 0; hardwired_intr[i].level != -1; i++) {			level = hardwired_intr[i].level;			if (level != intr_reserve_level(cpu, level,						hardwired_intr[i].flags,						(devfs_handle_t) NULL,						hardwired_intr[i].name))				panic("intr_reserve_hardwired: Can't reserve level %d, cpu %ld.", level, cpu);		}	}}/* * Check and clear interrupts. *//*ARGSUSED*/static voidintr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,		char *name){	volatile hubreg_t bits;	int i;	/* Check pending interrupts */	if ((bits = HUB_L(pend)) != 0) {		for (i = 0; i < N_INTPEND_BITS; i++) {			if (bits & (1 << i)) {#ifdef INTRDEBUG				printk(KERN_WARNING  "Nasid %d interrupt bit %d set in %s",					nasid, i, name);#endif				LOCAL_HUB_CLR_INTR(base_level + i);			}		}	}}/* * Clear out our interrupt registers. */voidintr_clear_all(nasid_t nasid){	int	sn;	for(sn=0; sn<NUM_SUBNODES; sn++) {		REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK0_A, 0);		REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK0_B, 0);		REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK1_A, 0);		REMOTE_HUB_PI_S(nasid, sn, PI_INT_MASK1_B, 0);			intr_clear_bits(nasid, REMOTE_HUB_PI_ADDR(nasid, sn, PI_INT_PEND0),				INT_PEND0_BASELVL, "INT_PEND0");		intr_clear_bits(nasid, REMOTE_HUB_PI_ADDR(nasid, sn, PI_INT_PEND1),				INT_PEND1_BASELVL, "INT_PEND1");	}}/*  * Dump information about a particular interrupt vector. */static voiddump_vector(intr_info_t *info, intr_vector_t *vector, int bit, hubreg_t ip,		hubreg_t ima, hubreg_t imb, void (*pf)(char *, ...)){	hubreg_t value = 1LL << bit;	pf("  Bit %02d: %s: func 0x%x arg 0x%x prefunc 0x%x\n",		bit, info->ii_name,		vector->iv_func, vector->iv_arg, vector->iv_prefunc);	pf("   vertex 0x%x %s%s",		info->ii_owner_dev,		((info->ii_flags) & II_RESERVE) ? "R" : "U",		((info->ii_flags) & II_INUSE) ? "C" : "-");	pf("%s%s%s%s",		ip & value ? "P" : "-",		ima & value ? "A" : "-",		imb & value ? "B" : "-",		((info->ii_flags) & II_ERRORINT) ? "E" : "-");	pf("\n");}/* * Dump information about interrupt vector assignment. */voidintr_dumpvec(cnodeid_t cnode, void (*pf)(char *, ...)){	nodepda_t *npda;	int ip, sn, bit;	intr_vecblk_t *dispatch;	hubreg_t ipr, ima, imb;	nasid_t nasid;	if ((cnode < 0) || (cnode >= numnodes)) {		pf("intr_dumpvec: cnodeid out of range: %d\n", cnode);		return ;	}	nasid = COMPACT_TO_NASID_NODEID(cnode);	if (nasid == INVALID_NASID) {		pf("intr_dumpvec: Bad cnodeid: %d\n", cnode);		return ;	}			npda = NODEPDA(cnode);	for (sn = 0; sn < NUM_SUBNODES; sn++) {		for (ip = 0; ip < 2; ip++) {			dispatch = ip ? &(SNPDA(npda,sn)->intr_dispatch1) : &(SNPDA(npda,sn)->intr_dispatch0);			ipr = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_PEND1 : PI_INT_PEND0);			ima = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_A : PI_INT_MASK0_A);			imb = REMOTE_HUB_PI_L(nasid, sn, ip ? PI_INT_MASK1_B : PI_INT_MASK0_B);				pf("Node %d INT_PEND%d:\n", cnode, ip);				if (dispatch->ithreads_enabled)				pf(" Ithreads enabled\n");			else				pf(" Ithreads disabled\n");			pf(" vector_count = %d, vector_state = %d\n",				dispatch->vector_count,				dispatch->vector_state);			pf(" CPU A count %d, CPU B count %d\n", 		   	dispatch->cpu_count[0], 		   	dispatch->cpu_count[1]);			pf(" &vector_lock = 0x%x\n",				&(dispatch->vector_lock));			for (bit = 0; bit < N_INTPEND_BITS; bit++) {				if ((dispatch->info[bit].ii_flags & II_RESERVE) ||			    	(ipr & (1L << bit))) {					dump_vector(&(dispatch->info[bit]),					    	&(dispatch->vectors[bit]),					    	bit, ipr, ima, imb, pf);				}			}			pf("\n");		}	}}

⌨️ 快捷键说明

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