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

📄 pcibr_intr.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 3 页
字号:
		    		"bridge intr bit %d clears my wrb\n",				pcibr_int_bit));		} else {		    /* someone else got one allocated first;		     * free the one we just created, and		     * retrieve the one they allocated.		     */		    xtalk_intr_free(xtalk_intr);		    xtalk_intr = *xtalk_intr_p;#if PARANOID		    /* once xtalk_intr is set, we never clear it,		     * so if the CAS fails above, this condition		     * can "never happen" ...		     */		    if (!xtalk_intr) {			printk(KERN_ALERT  				"pcibr_intr_alloc %v: unable to set xtalk interrupt resources",				xconn_vhdl);			/* yes, we leak resources here. */			return 0;		    }#endif		}	    }	    pcibr_intr->bi_ibits |= 1 << pcibr_int_bit;	    NEW(intr_entry);	    intr_entry->il_next = NULL;	    intr_entry->il_intr = pcibr_intr;	    intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg);	    intr_list_p = 		&pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;	    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,			"Bridge bit 0x%x wrap=0x%x\n", pcibr_int_bit,			pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap));	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {		/* we are the first interrupt on this bridge bit.		 */		PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,			    "INT 0x%x (bridge bit %d) allocated [FIRST]\n",			    pcibr_int_bits, pcibr_int_bit));		continue;	    }	    intr_list = *intr_list_p;	    pcibr_intr_p = &intr_list->il_intr;	    if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) {		/* first entry on list was erased,		 * and we replaced it, so we		 * don't need our intr_entry.		 */		DEL(intr_entry);		PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,			    "INT 0x%x (bridge bit %d) replaces erased first\n",			    pcibr_int_bits, pcibr_int_bit));		continue;	    }	    intr_list_p = &intr_list->il_next;	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {		/* we are the new second interrupt on this bit.		 */		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared = 1;		PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,			    "INT 0x%x (bridge bit %d) is new SECOND\n",			    pcibr_int_bits, pcibr_int_bit));		continue;	    }	    while (1) {		pcibr_intr_p = &intr_list->il_intr;		if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) {		    /* an entry on list was erased,		     * and we replaced it, so we		     * don't need our intr_entry.		     */		    DEL(intr_entry);		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,				"INT 0x%x (bridge bit %d) replaces erase Nth\n",				pcibr_int_bits, pcibr_int_bit));		    break;		}		intr_list_p = &intr_list->il_next;		if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {		    /* entry appended to share list		     */		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl,				"INT 0x%x (bridge bit %d) is new Nth\n",				pcibr_int_bits, pcibr_int_bit));		    break;		}		/* step to next record in chain		 */		intr_list = *intr_list_p;	    }	}    }#if DEBUG && INTR_DEBUG    printk("%v pcibr_intr_alloc complete\n", pconn_vhdl);#endif    hub_intr = (hub_intr_t)xtalk_intr;    pcibr_intr->bi_irq = hub_intr->i_bit;    pcibr_intr->bi_cpu = hub_intr->i_cpuid;    return pcibr_intr;}/*ARGSUSED */voidpcibr_intr_free(pcibr_intr_t pcibr_intr){    unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;    pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;    unsigned                pcibr_int_bit;    pcibr_intr_list_t       intr_list;    int			    intr_shared;    xtalk_intr_t	    *xtalk_intrp;    for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) {	if (pcibr_int_bits & (1 << pcibr_int_bit)) {	    for (intr_list = 		     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;		 intr_list != NULL;		 intr_list = intr_list->il_next)		if (compare_and_swap_ptr((void **) &intr_list->il_intr, 					 pcibr_intr, 					 NULL)) {		    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, 				pcibr_intr->bi_dev,		    		"pcibr_intr_free: cleared hdlr from bit 0x%x\n",				pcibr_int_bit));		}	    /* If this interrupt line is not being shared between multiple	     * devices release the xtalk interrupt resources.	     */	    intr_shared = 		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared;	    xtalk_intrp = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;	    if ((!intr_shared) && (*xtalk_intrp)) {		bridge_t 	*bridge = pcibr_soft->bs_base;		bridgereg_t	int_dev;		xtalk_intr_free(*xtalk_intrp);		*xtalk_intrp = 0;		/* Clear the PCI device interrupt to bridge interrupt pin		 * mapping.		 */		int_dev = bridge->b_int_device;		int_dev &= ~BRIDGE_INT_DEV_MASK(pcibr_int_bit);		bridge->b_int_device = int_dev;	    }	}    }    DEL(pcibr_intr);}voidpcibr_setpciint(xtalk_intr_t xtalk_intr){    iopaddr_t		 addr;    xtalk_intr_vector_t	 vect;    devfs_handle_t	 vhdl;    bridge_t		*bridge;    addr = xtalk_intr_addr_get(xtalk_intr);    vect = xtalk_intr_vector_get(xtalk_intr);    vhdl = xtalk_intr_dev_get(xtalk_intr);    bridge = (bridge_t *)xtalk_piotrans_addr(vhdl, 0, 0, sizeof(bridge_t), 0);    if (is_pic(bridge)) {	picreg_t	*int_addr;	int_addr = (picreg_t *)xtalk_intr_sfarg_get(xtalk_intr);	*int_addr = ((PIC_INT_ADDR_FLD & ((uint64_t)vect << 48)) |		     (PIC_INT_ADDR_HOST & addr));    } else {	bridgereg_t	*int_addr;	int_addr = (bridgereg_t *)xtalk_intr_sfarg_get(xtalk_intr);	*int_addr = ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) |		     (BRIDGE_INT_ADDR_FLD & vect));    }}/*ARGSUSED */intpcibr_intr_connect(pcibr_intr_t pcibr_intr, intr_func_t intr_func, intr_arg_t intr_arg){    pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;    bridge_t               *bridge = pcibr_soft->bs_base;    unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;    unsigned                pcibr_int_bit;    uint64_t		    int_enable;    unsigned long           s;    if (pcibr_intr == NULL)	return -1;    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev,		"pcibr_intr_connect: intr_func=0x%x\n",		pcibr_intr));    pcibr_intr->bi_func = intr_func;    pcibr_intr->bi_arg = intr_arg;    *((volatile unsigned *)&pcibr_intr->bi_flags) |= PCIIO_INTR_CONNECTED;    /*     * For each PCI interrupt line requested, figure     * out which Bridge PCI Interrupt Line it maps     * to, and make sure there are xtalk resources     * allocated for it.     */    for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)	if (pcibr_int_bits & (1 << pcibr_int_bit)) {            pcibr_intr_wrap_t       intr_wrap;	    xtalk_intr_t            xtalk_intr;            void                   *int_addr;	    xtalk_intr = pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;	    intr_wrap = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;	    /*	     * If this interrupt line is being shared and the connect has	     * already been done, no need to do it again.	     */	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected)		continue;	    /*	     * Use the pcibr wrapper function to handle all Bridge interrupts	     * regardless of whether the interrupt line is shared or not.	     */	    if (IS_PIC_SOFT(pcibr_soft)) 		int_addr = (void *)&(bridge->p_int_addr_64[pcibr_int_bit]);	    else		int_addr = (void *)&(bridge->b_int_addr[pcibr_int_bit].addr);	    xtalk_intr_connect(xtalk_intr, pcibr_intr_func, (intr_arg_t) intr_wrap,					(xtalk_intr_setfunc_t) pcibr_setpciint,			       			(void *)int_addr);	    pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 1;	    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev,			"pcibr_setpciint: int_addr=0x%x, *int_addr=0x%x, "			"pcibr_int_bit=0x%x\n", int_addr,			(is_pic(bridge) ? 			 *(picreg_t *)int_addr : *(bridgereg_t *)int_addr),			pcibr_int_bit));	}	/* PIC WAR. PV# 854697	 * On PIC we must write 64-bit MMRs with 64-bit stores	 */	s = pcibr_lock(pcibr_soft);	if (IS_PIC_SOFT(pcibr_soft) &&			PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) {	    int_enable = bridge->p_int_enable_64;	    int_enable |= pcibr_int_bits;	    bridge->p_int_enable_64 = int_enable;	} else {	    bridgereg_t int_enable;	    int_enable = bridge->b_int_enable;	    int_enable |= pcibr_int_bits;	    bridge->b_int_enable = int_enable;	}	bridge->b_wid_tflush;	/* wait until Bridge PIO complete */	pcibr_unlock(pcibr_soft, s);    return 0;}/*ARGSUSED */voidpcibr_intr_disconnect(pcibr_intr_t pcibr_intr){    pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;    bridge_t               *bridge = pcibr_soft->bs_base;    unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;    unsigned                pcibr_int_bit;    pcibr_intr_wrap_t       intr_wrap;    uint64_t                int_enable;    unsigned long           s;    /* Stop calling the function. Now.     */    *((volatile unsigned *)&pcibr_intr->bi_flags) &= ~PCIIO_INTR_CONNECTED;    pcibr_intr->bi_func = 0;    pcibr_intr->bi_arg = 0;    /*     * For each PCI interrupt line requested, figure     * out which Bridge PCI Interrupt Line it maps     * to, and disconnect the interrupt.     */    /* don't disable interrupts for lines that     * are shared between devices.     */    for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)	if ((pcibr_int_bits & (1 << pcibr_int_bit)) &&	    (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared))	    pcibr_int_bits &= ~(1 << pcibr_int_bit);    if (!pcibr_int_bits)	return;    /* PIC WAR. PV# 854697     * On PIC we must write 64-bit MMRs with 64-bit stores     */    s = pcibr_lock(pcibr_soft);    if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) {	int_enable = bridge->p_int_enable_64;	int_enable &= ~pcibr_int_bits;	bridge->p_int_enable_64 = int_enable;    } else {	int_enable = (uint64_t)bridge->b_int_enable;	int_enable &= ~pcibr_int_bits;	bridge->b_int_enable = (bridgereg_t)int_enable;    }    bridge->b_wid_tflush;		/* wait until Bridge PIO complete */    pcibr_unlock(pcibr_soft, s);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev,		"pcibr_intr_disconnect: disabled int_bits=0x%x\n", 		pcibr_int_bits));    for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)	if (pcibr_int_bits & (1 << pcibr_int_bit)) {

⌨️ 快捷键说明

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