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

📄 pcibr_dvr.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER    /* This may be a loadable driver so lock out any pciconfig actions */    mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif    pcibr_info->f_att_det_error = error;    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;    if (error) {        pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT;    } else {        pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;    }        #ifdef PIC_LATER    /* Release the bus lock */    mrunlock(pcibr_soft->bs_bus_lock);#endif}/* * pcibr_driver_unreg_callback *      CDL will call this function for each device found in the PCI *      registry that matches the vendor/device IDs supported by  *      the driver being unregistered.  The device's connection vertex *      and the driver's detach function return status enable the *      slot's device status to be set. */voidpcibr_driver_unreg_callback(vertex_hdl_t pconn_vhdl,                             int key1, int key2, int error){    pciio_info_t	 pciio_info;    pcibr_info_t         pcibr_info;    vertex_hdl_t	 pcibr_vhdl;    pciio_slot_t	 slot;    pcibr_soft_t	 pcibr_soft;    /* Do not set slot status for vendor/device ID wildcard drivers */    if ((key1 == -1) || (key2 == -1))        return;    pciio_info = pciio_info_get(pconn_vhdl);    pcibr_info = pcibr_info_get(pconn_vhdl);    pcibr_vhdl = pciio_info_master_get(pciio_info);    slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);    pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER    /* This may be a loadable driver so lock out any pciconfig actions */    mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif    pcibr_info->f_att_det_error = error;    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;    if (error) {        pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT;    } else {        pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;    }#ifdef PIC_LATER    /* Release the bus lock */    mrunlock(pcibr_soft->bs_bus_lock);#endif}/*  * build a convenience link path in the * form of ".../<iobrick>/bus/<busnum>" *  * returns 1 on success, 0 otherwise * * depends on hwgraph separator == '/' */intpcibr_bus_cnvlink(vertex_hdl_t f_c){        char dst[MAXDEVNAME];	char *dp = dst;        char *cp, *xp;        int widgetnum;        char pcibus[8];	vertex_hdl_t nvtx, svtx;	int rv;	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n"));	if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME)) {		return 0;	}	/* dst example == /hw/module/001c02/Pbrick/xtalk/8/pci/direct */	/* find the widget number */	xp = strstr(dst, "/"EDGE_LBL_XTALK"/");	if (xp == NULL) {		return 0;	}	widgetnum = simple_strtoul(xp+7, NULL, 0);	if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) {		return 0;	}	/* remove "/pci/direct" from path */	cp = strstr(dst, "/" EDGE_LBL_PCI "/" EDGE_LBL_DIRECT);	if (cp == NULL) {		return 0;	}	*cp = (char)NULL;	/* get the vertex for the widget */	if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx))	{		return 0;	}	*xp = (char)NULL;		/* remove "/xtalk/..." from path */	/* dst example now == /hw/module/001c02/Pbrick */	/* get the bus number */        strcat(dst, "/");        strcat(dst, EDGE_LBL_BUS);        sprintf(pcibus, "%d", p_busnum[widgetnum]);	/* link to bus to widget */	rv = hwgraph_path_add(NULL, dp, &nvtx);	if (GRAPH_SUCCESS == rv)		rv = hwgraph_edge_add(nvtx, svtx, pcibus);	return (rv == GRAPH_SUCCESS);}/* *    pcibr_attach: called every time the crosstalk *      infrastructure is asked to initialize a widget *      that matches the part number we handed to the *      registration routine above. *//*ARGSUSED */intpcibr_attach(vertex_hdl_t xconn_vhdl){    /* REFERENCED */    graph_error_t           rc;    vertex_hdl_t            pcibr_vhdl;    bridge_t               *bridge;    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, xconn_vhdl, "pcibr_attach\n"));    bridge = (bridge_t *)	xtalk_piotrans_addr(xconn_vhdl, NULL,			    0, sizeof(bridge_t), 0);    /*     * Create the vertex for the PCI bus, which we     * will also use to hold the pcibr_soft and     * which will be the "master" vertex for all the     * pciio connection points we will hang off it.     * This needs to happen before we call nic_bridge_vertex_info     * as we are some of the *_vmc functions need access to the edges.     *     * Opening this vertex will provide access to     * the Bridge registers themselves.     */    rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl);    ASSERT(rc == GRAPH_SUCCESS);    pciio_provider_register(pcibr_vhdl, &pcibr_provider);    pciio_provider_startup(pcibr_vhdl);    return pcibr_attach2(xconn_vhdl, bridge, pcibr_vhdl, 0, NULL);}/*ARGSUSED */intpcibr_attach2(vertex_hdl_t xconn_vhdl, bridge_t *bridge, 	      vertex_hdl_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp){    /* REFERENCED */    vertex_hdl_t            ctlr_vhdl;    bridgereg_t             id;    int                     rev;    pcibr_soft_t            pcibr_soft;    pcibr_info_t            pcibr_info;    xwidget_info_t          info;    xtalk_intr_t            xtalk_intr;    int                     slot;    int                     ibit;    vertex_hdl_t            noslot_conn;    char                    devnm[MAXDEVNAME], *s;    pcibr_hints_t           pcibr_hints;    uint64_t                int_enable;    picreg_t                int_enable_64;    unsigned                rrb_fixed = 0;#if PCI_FBBE    int                     fast_back_to_back_enable;#endif    nasid_t		    nasid;    int	                    iobrick_type_get_nasid(nasid_t nasid);    int                     iobrick_module_get_nasid(nasid_t nasid);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,	        "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum));    ctlr_vhdl = NULL;    ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER, 0,                 DEVFS_FL_AUTO_DEVNUM, 0, 0,		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, 		(struct file_operations *)&pcibr_fops, (void *)pcibr_vhdl);    ASSERT(ctlr_vhdl != NULL);    /*     * Get the hint structure; if some NIC callback     * marked this vertex as "hands-off" then we     * just return here, before doing anything else.     */    pcibr_hints = pcibr_hints_get(xconn_vhdl, 0);    if (pcibr_hints && pcibr_hints->ph_hands_off)	return -1;			/* generic operations disabled */    id = bridge->b_wid_id;    rev = XWIDGET_PART_REV_NUM(id);    hwgraph_info_add_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, (arbitrary_info_t) rev);    /*     * allocate soft state structure, fill in some     * fields, and hook it up to our vertex.     */    NEW(pcibr_soft);    if (ret_softp)	*ret_softp = pcibr_soft;    memset(pcibr_soft, 0, sizeof *pcibr_soft);    pcibr_soft_set(pcibr_vhdl, pcibr_soft);    pcibr_soft->bs_conn = xconn_vhdl;    pcibr_soft->bs_vhdl = pcibr_vhdl;    pcibr_soft->bs_base = bridge;    pcibr_soft->bs_rev_num = rev;    pcibr_soft->bs_intr_bits = (pcibr_intr_bits_f *)pcibr_intr_bits;    pcibr_soft->bs_min_slot = 0;		/* lowest possible slot# */    pcibr_soft->bs_max_slot = 7;		/* highest possible slot# */    pcibr_soft->bs_busnum = busnum;    pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC;    switch(pcibr_soft->bs_bridge_type) {    case PCIBR_BRIDGETYPE_BRIDGE:	pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES;	pcibr_soft->bs_bridge_mode = 0;	/* speed is not available in bridge */	break;    case PCIBR_BRIDGETYPE_PIC:        pcibr_soft->bs_min_slot = 0;	pcibr_soft->bs_max_slot = 3;	pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;	pcibr_soft->bs_bridge_mode = 	   (((bridge->p_wid_stat_64 & PIC_STAT_PCIX_SPEED) >> 33) |	    ((bridge->p_wid_stat_64 & PIC_STAT_PCIX_ACTIVE) >> 33));	/* We have to clear PIC's write request buffer to avoid parity	 * errors.  See PV#854845.	 */	{	int i;	for (i=0; i < PIC_WR_REQ_BUFSIZE; i++) {		bridge->p_wr_req_lower[i] = 0;		bridge->p_wr_req_upper[i] = 0;		bridge->p_wr_req_parity[i] = 0;	}	}	break;    case PCIBR_BRIDGETYPE_XBRIDGE:	pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;	pcibr_soft->bs_bridge_mode = 	   ((bridge->b_wid_control & BRIDGE_CTRL_PCI_SPEED) >> 3);	break;    }    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,		"pcibr_attach2: pcibr_soft=0x%x, mode=0x%x\n",                pcibr_soft, pcibr_soft->bs_bridge_mode));    pcibr_soft->bsi_err_intr = 0;    /* Bridges up through REV C     * are unable to set the direct     * byteswappers to BYTE_STREAM.     */    if (pcibr_soft->bs_rev_num <= BRIDGE_PART_REV_C) {	pcibr_soft->bs_pio_end_io = PCIIO_WORD_VALUES;	pcibr_soft->bs_pio_end_mem = PCIIO_WORD_VALUES;    }#if PCIBR_SOFT_LIST    /*     * link all the pcibr_soft structs     */    {	pcibr_list_p            self;	NEW(self);	self->bl_soft = pcibr_soft;	self->bl_vhdl = pcibr_vhdl;	self->bl_next = pcibr_list;	pcibr_list = self;    }#endif /* PCIBR_SOFT_LIST */    /*     * get the name of this bridge vertex and keep the info. Use this     * only where it is really needed now: like error interrupts.     */    s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME);    pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL);    strcpy(pcibr_soft->bs_name, s);    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,		"pcibr_attach2: %s ASIC: rev %s (code=0x%x)\n",		IS_XBRIDGE_SOFT(pcibr_soft) ? "XBridge" :			IS_PIC_SOFT(pcibr_soft) ? "PIC" : "Bridge", 		(rev == BRIDGE_PART_REV_A) ? "A" :                 (rev == BRIDGE_PART_REV_B) ? "B" :                (rev == BRIDGE_PART_REV_C) ? "C" :                (rev == BRIDGE_PART_REV_D) ? "D" :                (rev == XBRIDGE_PART_REV_A) ? "A" :                (rev == XBRIDGE_PART_REV_B) ? "B" :                (IS_PIC_PART_REV_A(rev)) ? "A" :                 "unknown", rev, pcibr_soft->bs_name));    info = xwidget_info_get(xconn_vhdl);    pcibr_soft->bs_xid = xwidget_info_id_get(info);    pcibr_soft->bs_master = xwidget_info_master_get(info);    pcibr_soft->bs_mxid = xwidget_info_masterid_get(info);    pcibr_soft->bs_first_slot = pcibr_soft->bs_min_slot;    pcibr_soft->bs_last_slot = pcibr_soft->bs_max_slot;    /*     * Bridge can only reset slots 0, 1, 2, and 3.  Ibrick internal     * slots 4, 5, 6, and 7 must be reset as a group, so do not     * reset them.     */    pcibr_soft->bs_last_reset = 3;    nasid = NASID_GET(bridge);    if ((pcibr_soft->bs_bricktype = iobrick_type_get_nasid(nasid)) < 0)	printk(KERN_WARNING "0x%p: Unknown bricktype : 0x%x\n", (void *)xconn_vhdl,				(unsigned int)pcibr_soft->bs_bricktype);    pcibr_soft->bs_moduleid = iobrick_module_get_nasid(nasid);    if (pcibr_soft->bs_bricktype > 0) {	switch (pcibr_soft->bs_bricktype) {	case MODULE_PXBRICK:	case MODULE_IXBRICK:	case MODULE_OPUSBRICK:	    pcibr_soft->bs_first_slot = 0;	    pcibr_soft->bs_last_slot = 1;	    pcibr_soft->bs_last_reset = 1;	    /* If Bus 1 has IO9 then there are 4 devices in that bus.  Note	     * we figure this out from klconfig since the kernel has yet to 	     * probe	     */	    if (pcibr_widget_to_bus(pcibr_vhdl) == 1) {		lboard_t *brd = (lboard_t *)KL_CONFIG_INFO(nasid);		while (brd) {		    if (brd->brd_flags & LOCAL_MASTER_IO6) {			pcibr_soft->bs_last_slot = 3;			pcibr_soft->bs_last_reset = 3;		    }		    brd = KLCF_NEXT(brd);		}	    }	    break;	case MODULE_PBRICK:            pcibr_soft->bs_first_slot = 1;            pcibr_soft->bs_last_slot = 2;            pcibr_soft->bs_last_reset = 2;            break;        case MODULE_IBRICK:	    /*	     * Here's the current baseio layout for SN1 style systems:	     *

⌨️ 快捷键说明

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