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

📄 pcibr_dvr.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
     * above.     *     * Need to set the D_INTR_ISERR flag     * in the dev_desc used for allocating the     * error interrupt, so our interrupt will     * be properly routed and prioritized.     *     * If our crosstalk provider wants to     * fix widget error interrupts to specific     * destinations, D_INTR_ISERR is how it     * knows to do this.     */    xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, pcibr_vhdl);    ASSERT(xtalk_intr != NULL);    pcibr_soft->bsi_err_intr = xtalk_intr;    /*     * On IP35 with XBridge, we do some extra checks in pcibr_setwidint     * in order to work around some addressing limitations.  In order     * for that fire wall to work properly, we need to make sure we     * start from a known clean state.     */    pcibr_clearwidint(bridge);    xtalk_intr_connect(xtalk_intr, (xtalk_intr_setfunc_t)pcibr_setwidint, (void *)bridge);    /*     * now we can start handling error interrupts;     * enable all of them.     * NOTE: some PCI ints may already be enabled.     */    b_int_enable = bridge->b_int_enable | BRIDGE_ISR_ERRORS;    bridge->b_int_enable = b_int_enable;    bridge->b_int_mode = 0;		/* do not send "clear interrupt" packets */    bridge->b_wid_tflush;		/* wait until Bridge PIO complete */    /*     * Depending on the rev of bridge, disable certain features.     * Easiest way seems to be to force the PCIBR_NOwhatever     * flag to be on for all DMA calls, which overrides any     * PCIBR_whatever flag or even the setting of whatever     * from the PCIIO_DMA_class flags (or even from the other     * PCIBR flags, since NO overrides YES).     */    pcibr_soft->bs_dma_flags = 0;    /* PREFETCH:     * Always completely disabled for REV.A;     * at "pcibr_prefetch_enable_rev", anyone     * asking for PCIIO_PREFETCH gets it.     * Between these two points, you have to ask     * for PCIBR_PREFETCH, which promises that     * your driver knows about known Bridge WARs.     */    if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_B)	pcibr_soft->bs_dma_flags |= PCIBR_NOPREFETCH;    else if (pcibr_soft->bs_rev_num < 		(BRIDGE_WIDGET_PART_NUM << 4 | pcibr_prefetch_enable_rev))	pcibr_soft->bs_dma_flags |= PCIIO_NOPREFETCH;    /* WRITE_GATHER:     * Disabled up to but not including the     * rev number in pcibr_wg_enable_rev. There     * is no "WAR range" as with prefetch.     */    if (pcibr_soft->bs_rev_num < 		(BRIDGE_WIDGET_PART_NUM << 4 | pcibr_wg_enable_rev))	pcibr_soft->bs_dma_flags |= PCIBR_NOWRITE_GATHER;    pciio_provider_register(pcibr_vhdl, &pcibr_provider);    pciio_provider_startup(pcibr_vhdl);    pci_io_fb = 0x00000004;		/* I/O FreeBlock Base */    pci_io_fl = 0xFFFFFFFF;		/* I/O FreeBlock Last */    pci_lo_fb = 0x00000010;		/* Low Memory FreeBlock Base */    pci_lo_fl = 0x001FFFFF;		/* Low Memory FreeBlock Last */    pci_hi_fb = 0x00200000;		/* High Memory FreeBlock Base */    pci_hi_fl = 0x3FFFFFFF;		/* High Memory FreeBlock Last */    PCI_ADDR_SPACE_LIMITS_STORE();    /* build "no-slot" connection point     */    pcibr_info = pcibr_device_info_new	(pcibr_soft, PCIIO_SLOT_NONE, PCIIO_FUNC_NONE,	 PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE);    noslot_conn = pciio_device_info_register	(pcibr_vhdl, &pcibr_info->f_c);    /* Remember the no slot connection point info for tearing it     * down during detach.     */    pcibr_soft->bs_noslot_conn = noslot_conn;    pcibr_soft->bs_noslot_info = pcibr_info;#if PCI_FBBE    fast_back_to_back_enable = 1;#endif#if PCI_FBBE    if (fast_back_to_back_enable) {	/*	 * All devices on the bus are capable of fast back to back, so	 * we need to set the fast back to back bit in all devices on	 * the bus that are capable of doing such accesses.	 */    }#endif#ifdef LATER    /* If the bridge has been reset then there is no need to reset     * the individual PCI slots.     */    for (slot = 0; slot < 8; ++slot)  	/* Reset all the slots */	(void)pcibr_slot_reset(pcibr_vhdl, slot);#endif    for (slot = 0; slot < 8; ++slot)	/* Find out what is out there */	(void)pcibr_slot_info_init(pcibr_vhdl,slot);    for (slot = 0; slot < 8; ++slot)  	/* Set up the address space for this slot in the pci land */	(void)pcibr_slot_addr_space_init(pcibr_vhdl,slot);    for (slot = 0; slot < 8; ++slot)  	/* Setup the device register */	(void)pcibr_slot_device_init(pcibr_vhdl, slot);    for (slot = 0; slot < 8; ++slot)  	/* Setup host/guest relations */	(void)pcibr_slot_guest_info_init(pcibr_vhdl,slot);    for (slot = 0; slot < 8; ++slot)  	/* Initial RRB management */	(void)pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot);    /* driver attach routines should be called out from generic linux code */    for (slot = 0; slot < 8; ++slot)  	/* Call the device attach */	(void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0);    /*     * Each Pbrick PCI bus only has slots 1 and 2.   Similarly for     * widget 0xe on Ibricks.  Allocate RRB's accordingly.     */    if (pcibr_soft->bs_moduleid > 0) {	switch (MODULE_GET_BTCHAR(pcibr_soft->bs_moduleid)) {	case 'p':		/* Pbrick */		do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);		do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);		break;	case 'i':		/* Ibrick */	  	/* port 0xe on the Ibrick only has slots 1 and 2 */		if (pcibr_soft->bs_xid == 0xe) {			do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);			do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);		}		else {		    	/* allocate one RRB for the serial port */			do_pcibr_rrb_autoalloc(pcibr_soft, 0, 1);		}		break;	} /* switch */    }#ifdef LATER    if (strstr(nicinfo, XTALK_PCI_PART_NUM)) {	do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);#if PCIBR_RRB_DEBUG	printf("\n\nFound XTALK_PCI (030-1275) at %v\n", xconn_vhdl);	printf("pcibr_attach: %v Shoebox RRB MANAGEMENT: %d+%d free\n",		pcibr_vhdl,		pcibr_soft->bs_rrb_avail[0],		pcibr_soft->bs_rrb_avail[1]);	for (slot = 0; slot < 8; ++slot)	    printf("\t%d+%d+%d",	    0xFFF & pcibr_soft->bs_rrb_valid[slot],	    0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],	    pcibr_soft->bs_rrb_res[slot]);	printf("\n");#endif    }#else	FIXME("pcibr_attach: Call do_pcibr_rrb_autoalloc nicinfo\n");#endif    if (aa)	    async_attach_add_info(noslot_conn, aa);    pciio_device_attach(noslot_conn, 0);    /*      * Tear down pointer to async attach info -- async threads for     * bridge's descendants may be running but the bridge's work is done.     */    if (aa)	    async_attach_del_info(xconn_vhdl);    return 0;}/* * pcibr_detach: *	Detach the bridge device from the hwgraph after cleaning out all the  *	underlying vertices. */intpcibr_detach(devfs_handle_t xconn){    pciio_slot_t	slot;    devfs_handle_t	pcibr_vhdl;    pcibr_soft_t	pcibr_soft;    bridge_t		*bridge;    /* Get the bridge vertex from its xtalk connection point */    if (hwgraph_traverse(xconn, EDGE_LBL_PCI, &pcibr_vhdl) != GRAPH_SUCCESS)	return(1);    pcibr_soft = pcibr_soft_get(pcibr_vhdl);    bridge = pcibr_soft->bs_base;    /* Disable the interrupts from the bridge */    bridge->b_int_enable = 0;    /* Detach all the PCI devices talking to this bridge */    for(slot = 0; slot < 8; slot++) {#ifdef DEBUG	printk("pcibr_device_detach called for %p/%d\n",		pcibr_vhdl,slot);#endif	pcibr_slot_detach(pcibr_vhdl, slot, 0);    }    /* Unregister the no-slot connection point */    pciio_device_info_unregister(pcibr_vhdl,				 &(pcibr_soft->bs_noslot_info->f_c));    spin_lock_destroy(&pcibr_soft->bs_lock);    kfree(pcibr_soft->bs_name);        /* Error handler gets unregistered when the widget info is      * cleaned      */    /* Free the soft ATE maps */    if (pcibr_soft->bs_int_ate_map)	rmfreemap(pcibr_soft->bs_int_ate_map);    if (pcibr_soft->bs_ext_ate_map)	rmfreemap(pcibr_soft->bs_ext_ate_map);    /* Disconnect the error interrupt and free the xtalk resources      * associated with it.     */    xtalk_intr_disconnect(pcibr_soft->bsi_err_intr);    xtalk_intr_free(pcibr_soft->bsi_err_intr);    /* Clear the software state maintained by the bridge driver for this     * bridge.     */    DEL(pcibr_soft);    /* Remove the Bridge revision labelled info */    (void)hwgraph_info_remove_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, NULL);    /* Remove the character device associated with this bridge */    (void)hwgraph_edge_remove(pcibr_vhdl, EDGE_LBL_CONTROLLER, NULL);    /* Remove the PCI bridge vertex */    (void)hwgraph_edge_remove(xconn, EDGE_LBL_PCI, NULL);    return(0);}intpcibr_asic_rev(devfs_handle_t pconn_vhdl){    devfs_handle_t            pcibr_vhdl;    arbitrary_info_t        ainfo;    if (GRAPH_SUCCESS !=	hwgraph_traverse(pconn_vhdl, EDGE_LBL_MASTER, &pcibr_vhdl))	return -1;    if (GRAPH_SUCCESS !=	hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &ainfo))	return -1;    return (int) ainfo;}intpcibr_write_gather_flush(devfs_handle_t pconn_vhdl){    pciio_info_t  pciio_info = pciio_info_get(pconn_vhdl);    pcibr_soft_t  pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    pciio_slot_t  slot;    slot = pciio_info_slot_get(pciio_info);    pcibr_device_write_gather_flush(pcibr_soft, slot);    return 0;}/* ===================================================================== *    PIO MANAGEMENT */static iopaddr_tpcibr_addr_pci_to_xio(devfs_handle_t pconn_vhdl,		      pciio_slot_t slot,		      pciio_space_t space,		      iopaddr_t pci_addr,		      size_t req_size,		      unsigned flags){    pcibr_info_t            pcibr_info = pcibr_info_get(pconn_vhdl);    pciio_info_t            pciio_info = &pcibr_info->f_c;    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    unsigned                bar;	/* which BASE reg on device is decoding */    iopaddr_t               xio_addr = XIO_NOWHERE;    pciio_space_t           wspace;	/* which space device is decoding */    iopaddr_t               wbase;	/* base of device decode on PCI */    size_t                  wsize;	/* size of device decode on PCI */    int                     try;	/* DevIO(x) window scanning order control */    int                     win;	/* which DevIO(x) window is being used */    pciio_space_t           mspace;	/* target space for devio(x) register */    iopaddr_t               mbase;	/* base of devio(x) mapped area on PCI */    size_t                  msize;	/* size of devio(x) mapped area on PCI */    size_t                  mmask;	/* addr bits stored in Device(x) */    unsigned long           s;    s = pcibr_lock(pcibr_soft);    if (pcibr_soft->bs_slot[slot].has_host) {	slot = pcibr_soft->bs_slot[slot].host_slot;	pcibr_info = pcibr_soft->bs_slot[slot].bss_infos[0];    }    if (space == PCIIO_SPACE_NONE)	goto done;    if (space == PCIIO_SPACE_CFG) {	/*	 * Usually, the first mapping	 * established to a PCI device	 * is to its config space.	 *	 * In any case, we definitely	 * do NOT need to worry about	 * PCI BASE registers, and	 * MUST NOT attempt to point	 * the DevIO(x) window at	 * this access ...	 */	if (((flags & PCIIO_BYTE_STREAM) == 0) &&	    ((pci_addr + req_size) <= BRIDGE_TYPE0_CFG_FUNC_OFF))	    xio_addr = pci_addr + BRIDGE_TYPE0_CFG_DEV(slot);	goto done;    }    if (space == PCIIO_SPACE_ROM) {	/* PIO to the Expansion Rom.	 * Driver is responsible for	 * enabling and disabling	 * decodes properly.	 */	wbase = pcibr_info->f_rbase;	wsize = pcibr_info->f_rsize;	/*	 * While the driver should know better	 * than to attempt to map more space	 * than the device is decoding, he might	 * do it; better to bail out here.	 */	if ((pci_addr + req_size) > wsize)	    goto done;	pci_addr += wbase;	space = PCIIO_SPACE_MEM;    }    /*     * reduce window mappings to raw     * space mappings (maybe allocating     * windows), and try for DevIO(x)     * usage (setting it if it is available).     */    bar = space - PCIIO_SPACE_WIN0;    if (bar < 6) {	wspace = pcibr_info->f_window[bar].w_space;	if (wspace == PCIIO_SPACE_NONE)	    goto done;	/* get PCI base and size */	wbase = pcibr_info->f_window[bar].w_base;	wsize = pcibr_info->f_window[bar].w_size;	/*	 * While the driver should know better	 * than to attempt to map more space	 * than the device is decoding, he might	 * do it; better to bail out here.	 */	if ((pci_addr + req_size) > wsize)	    goto done;	/* shift from window relative to	 * decoded space relative.	 */	pci_addr += wbase;	space = wspace;    } else	bar = -1;    /* Scan all the DevIO(x) windows twice looking for one     * that can satisfy our request. The first time through,     * only look at assigned windows; the second time, also     * look at PCIIO_SPACE_NON

⌨️ 快捷键说明

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