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

📄 pcibr_dvr.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (flags & PCIBR_BARRIER)	new |= BRIDGE_DEV_BARRIER;    if (flags & PCIBR_NOBARRIER)	new &= ~BRIDGE_DEV_BARRIER;    if (flags & PCIBR_64BIT)	new |= BRIDGE_DEV_DEV_SIZE;    if (flags & PCIBR_NO64BIT)	new &= ~BRIDGE_DEV_DEV_SIZE;    /*     * PIC BRINGUP WAR (PV# 855271):     * Allow setting BRIDGE_DEV_VIRTUAL_EN on PIC iff we're a 64-bit     * device.  The bit is only intended for 64-bit devices and, on     * PIC, can cause problems for 32-bit devices.     */    if (IS_PIC_SOFT(pcibr_soft) && mask == BRIDGE_DEV_D64_BITS &&                                PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) {        if (flags & PCIBR_VCHAN1) {                new |= BRIDGE_DEV_VIRTUAL_EN;                xmask |= BRIDGE_DEV_VIRTUAL_EN;        }    }    chg = old ^ new;				/* what are we changing, */    chg &= xmask;				/* of the interesting bits */    if (chg) {	badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0;	if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {		badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0;		badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0;	} else {		badpmu = slotp->bss_pmu_uctr ? (BRIDGE_DEV_PMU_BITS & chg) : 0;		badd64 = slotp->bss_d64_uctr ? (BRIDGE_DEV_D64_BITS & chg) : 0;	}	bad = badpmu | badd32 | badd64;	if (bad) {	    /* some conflicts can be resolved by	     * forcing the bit on. this may cause	     * some performance degredation in	     * the stream(s) that want the bit off,	     * but the alternative is not allowing	     * the new stream at all.	     */            if ( (fix = bad & (BRIDGE_DEV_PRECISE |                             BRIDGE_DEV_BARRIER)) ) {		bad &= ~fix;		/* don't change these bits if		 * they are already set in "old"		 */		chg &= ~(fix & old);	    }	    /* some conflicts can be resolved by	     * forcing the bit off. this may cause	     * some performance degredation in	     * the stream(s) that want the bit on,	     * but the alternative is not allowing	     * the new stream at all.	     */	    if ( (fix = bad & (BRIDGE_DEV_WRGA_BITS |			     BRIDGE_DEV_PREF)) ) {		bad &= ~fix;		/* don't change these bits if		 * we wanted to turn them on.		 */		chg &= ~(fix & new);	    }	    /* conflicts in other bits mean	     * we can not establish this DMA	     * channel while the other(s) are	     * still present.	     */	    if (bad) {		pcibr_unlock(pcibr_soft, s);#ifdef PIC_LATER		PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl,			    "pcibr_try_set_device: mod blocked by %x\n",			    bad, device_bits));#endif		return bad;	    }	}    }    if (mask == BRIDGE_DEV_PMU_BITS)	slotp->bss_pmu_uctr++;    if (mask == BRIDGE_DEV_D32_BITS)	slotp->bss_d32_uctr++;    if (mask == BRIDGE_DEV_D64_BITS)	slotp->bss_d64_uctr++;    /* the value we want to write is the     * original value, with the bits for     * our selected changes flipped, and     * with any disabled features turned off.     */    new = old ^ chg;			/* only change what we want to change */    if (slotp->bss_device == new) {	pcibr_unlock(pcibr_soft, s);	return 0;    }    if ( IS_PIC_SOFT(pcibr_soft) ) {	bridge->b_device[slot].reg = new;	slotp->bss_device = new;	bridge->b_wid_tflush;		/* wait until Bridge PIO complete */    }    pcibr_unlock(pcibr_soft, s);#ifdef PIC_LATER    PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl,		"pcibr_try_set_device: Device(%d): %x\n",		slot, new, device_bits));#else    printk("pcibr_try_set_device: Device(%d): %x\n", slot, new);#endif    return 0;}voidpcibr_release_device(pcibr_soft_t pcibr_soft,		     pciio_slot_t slot,		     bridgereg_t mask){    pcibr_soft_slot_t       slotp;    unsigned long           s;    slotp = &pcibr_soft->bs_slot[slot];    s = pcibr_lock(pcibr_soft);    if (mask == BRIDGE_DEV_PMU_BITS)	slotp->bss_pmu_uctr--;    if (mask == BRIDGE_DEV_D32_BITS)	slotp->bss_d32_uctr--;    if (mask == BRIDGE_DEV_D64_BITS)	slotp->bss_d64_uctr--;    pcibr_unlock(pcibr_soft, s);}/* ===================================================================== *    Bridge (pcibr) "Device Driver" entry points */static intpcibr_mmap(struct file * file, struct vm_area_struct * vma){	vertex_hdl_t		pcibr_vhdl;	pcibr_soft_t            pcibr_soft;	bridge_t               *bridge;	unsigned long		phys_addr;	int			error = 0;#ifdef CONFIG_HWGFS_FS	pcibr_vhdl = (vertex_hdl_t) file->f_dentry->d_fsdata;#else	pcibr_vhdl = (vertex_hdl_t) file->private_data;#endif	pcibr_soft = pcibr_soft_get(pcibr_vhdl);	bridge = pcibr_soft->bs_base;	phys_addr = (unsigned long)bridge & ~0xc000000000000000; /* Mask out the Uncache bits */        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);        vma->vm_flags |= VM_NONCACHED | VM_RESERVED | VM_IO;        error = io_remap_page_range(vma->vm_start, phys_addr,                                   vma->vm_end-vma->vm_start,                                   vma->vm_page_prot);	return(error);}/* * This is the file operation table for the pcibr driver. * As each of the functions are implemented, put the * appropriate function name below. */static int pcibr_mmap(struct file * file, struct vm_area_struct * vma);struct file_operations pcibr_fops = {	.owner		= THIS_MODULE,	.mmap		= pcibr_mmap,};/* This is special case code used by grio. There are plans to make * this a bit more general in the future, but till then this should * be sufficient. */pciio_slot_tpcibr_device_slot_get(vertex_hdl_t dev_vhdl){    char                    devname[MAXDEVNAME];    vertex_hdl_t            tdev;    pciio_info_t            pciio_info;    pciio_slot_t            slot = PCIIO_SLOT_NONE;    vertex_to_name(dev_vhdl, devname, MAXDEVNAME);    /* run back along the canonical path     * until we find a PCI connection point.     */    tdev = hwgraph_connectpt_get(dev_vhdl);    while (tdev != GRAPH_VERTEX_NONE) {	pciio_info = pciio_info_chk(tdev);	if (pciio_info) {	    slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);	    break;	}	hwgraph_vertex_unref(tdev);	tdev = hwgraph_connectpt_get(tdev);    }    hwgraph_vertex_unref(tdev);    return slot;}pcibr_info_tpcibr_info_get(vertex_hdl_t vhdl){    return (pcibr_info_t) pciio_info_get(vhdl);}pcibr_info_tpcibr_device_info_new(			 pcibr_soft_t pcibr_soft,			 pciio_slot_t slot,			 pciio_function_t rfunc,			 pciio_vendor_id_t vendor,			 pciio_device_id_t device){    pcibr_info_t            pcibr_info;    pciio_function_t        func;    int                     ibit;    func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc;    /*     * Create a pciio_info_s for this device.  pciio_device_info_new()     * will set the c_slot (which is suppose to represent the external     * slot (i.e the slot number silk screened on the back of the I/O     * brick)).  So for PIC we need to adjust this "internal slot" num     * passed into us, into its external representation.  See comment     * for the PCIBR_DEVICE_TO_SLOT macro for more information.     */    NEW(pcibr_info);    pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl,			  PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot),			  rfunc, vendor, device);    pcibr_info->f_dev = slot;    /* Set PCI bus number */    pcibr_info->f_bus = pcibr_widget_to_bus(pcibr_soft->bs_vhdl);    if (slot != PCIIO_SLOT_NONE) {	/*	 * Currently favored mapping from PCI	 * slot number and INTA/B/C/D to Bridge	 * PCI Interrupt Bit Number:	 *	 *     SLOT     A B C D	 *      0       0 4 0 4	 *      1       1 5 1 5	 *      2       2 6 2 6	 *      3       3 7 3 7	 *      4       4 0 4 0	 *      5       5 1 5 1	 *      6       6 2 6 2	 *      7       7 3 7 3	 *	 * XXX- allow pcibr_hints to override default	 * XXX- allow ADMIN to override pcibr_hints	 */	for (ibit = 0; ibit < 4; ++ibit)	    pcibr_info->f_ibit[ibit] =		(slot + 4 * ibit) & 7;	/*	 * Record the info in the sparse func info space.	 */	if (func < pcibr_soft->bs_slot[slot].bss_ninfo)	    pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info;    }    return pcibr_info;}/* * pcibr_device_unregister *	This frees up any hardware resources reserved for this PCI device * 	and removes any PCI infrastructural information setup for it. *	This is usually used at the time of shutting down of the PCI card. */intpcibr_device_unregister(vertex_hdl_t pconn_vhdl){    pciio_info_t	 pciio_info;    vertex_hdl_t	 pcibr_vhdl;    pciio_slot_t	 slot;    pcibr_soft_t	 pcibr_soft;    bridge_t		*bridge;    int                  count_vchan0, count_vchan1;    unsigned             s;    int			 error_call;    int			 error = 0;    pciio_info = pciio_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);    bridge = pcibr_soft->bs_base;    /* Clear all the hardware xtalk resources for this device */    xtalk_widgetdev_shutdown(pcibr_soft->bs_conn, slot);    /* Flush all the rrbs */    pcibr_rrb_flush(pconn_vhdl);    /*     * If the RRB configuration for this slot has changed, set it      * back to the boot-time default     */    if (pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] >= 0) {        s = pcibr_lock(pcibr_soft);	/* PIC NOTE: If this is a BRIDGE, VCHAN2 & VCHAN3 will be zero so	 * no need to conditionalize this (ie. "if (IS_PIC_SOFT())" ).	 */        pcibr_soft->bs_rrb_res[slot] = pcibr_soft->bs_rrb_res[slot] +                                       pcibr_soft->bs_rrb_valid[slot][VCHAN0] +                                       pcibr_soft->bs_rrb_valid[slot][VCHAN1] +                                       pcibr_soft->bs_rrb_valid[slot][VCHAN2] +                                       pcibr_soft->bs_rrb_valid[slot][VCHAN3];        /* Free the rrbs allocated to this slot, both the normal & virtual */	do_pcibr_rrb_free_all(pcibr_soft, bridge, slot);        count_vchan0 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0];        count_vchan1 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN1];        pcibr_unlock(pcibr_soft, s);        pcibr_rrb_alloc(pconn_vhdl, &count_vchan0, &count_vchan1);    }    /* Flush the write buffers !! */    error_call = pcibr_wrb_flush(pconn_vhdl);    if (error_call)        error = error_call;    /* Clear the information specific to the slot */    error_call = pcibr_slot_info_free(pcibr_vhdl, slot);    if (error_call)        error = error_call;    return(error);    }/* * pcibr_driver_reg_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 registered.  The device's connection vertex *      and the driver's attach function return status enable the *      slot's device status to be set. */voidpcibr_driver_reg_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);

⌨️ 快捷键说明

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