io.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 740 行 · 第 1/2 页

C
740
字号
	xwidgetnum_t widget = xwidget_info_id_get(widget_info);	vertex_hdl_t hubv = xwidget_info_master_get(widget_info);	hub_piomap_t hub_piomap;	hubinfo_t hubinfo;	caddr_t addr;	hubinfo_get(hubv, &hubinfo);	if (xtalk_addr + byte_count <= SWIN_SIZE) {		hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);		addr = hub_piomap_addr(hub_piomap, xtalk_addr, byte_count);#ifdef PIOMAP_UNC_ACC_SPACE		if (flags & PIOMAP_UNC_ACC) {			uint64_t iaddr;			iaddr = (uint64_t)addr;			iaddr |= PIOMAP_UNC_ACC_SPACE;			addr = (caddr_t)iaddr;		}#endif		return addr;	} else		return 0;}/* DMA MANAGEMENT *//* Mapping from crosstalk space to system physical space *//* * Allocate resources needed to set up DMA mappings up to a specified size * on a specified adapter. *  * We don't actually use the adapter ID for anything.  It's just the adapter * that the lower level driver plans to use for DMA. *//* ARGSUSED */hub_dmamap_thub_dmamap_alloc(	vertex_hdl_t dev,	/* set up mappings for this device */			device_desc_t dev_desc,	/* device descriptor */			size_t byte_count_max, 	/* max size of a mapping */			unsigned flags)		/* defined in dma.h */{	hub_dmamap_t dmamap;	xwidget_info_t widget_info = xwidget_info_get(dev);	xwidgetnum_t widget = xwidget_info_id_get(widget_info);	vertex_hdl_t hubv = xwidget_info_master_get(widget_info);	dmamap = kmalloc(sizeof(struct hub_dmamap_s), GFP_ATOMIC);	dmamap->hdma_xtalk_info.xd_dev = dev;	dmamap->hdma_xtalk_info.xd_target = widget;	dmamap->hdma_hub = hubv;	dmamap->hdma_flags = HUB_DMAMAP_IS_VALID; 	if (flags & XTALK_FIXED)		dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED;	return dmamap;}/* * Destroy a DMA mapping from crosstalk space to system address space. * There is no actual mapping hardware to destroy, but we at least mark * the dmamap INVALID and free the space that it took. */voidhub_dmamap_free(hub_dmamap_t hub_dmamap){	hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;	kfree(hub_dmamap);}/* * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc. * Return an appropriate crosstalk address range that maps to the specified physical  * address range. *//* ARGSUSED */extern iopaddr_thub_dmamap_addr(	hub_dmamap_t dmamap,	/* use these mapping resources */			paddr_t paddr,		/* map for this address */			size_t byte_count)	/* map this many bytes */{	vertex_hdl_t vhdl;	ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);	if (dmamap->hdma_flags & HUB_DMAMAP_USED) {	    /* If the map is FIXED, re-use is OK. */	    if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {		char name[MAXDEVNAME];		vhdl = dmamap->hdma_xtalk_info.xd_dev;		printk(KERN_WARNING  "%s: hub_dmamap_addr re-uses dmamap.\n", vertex_to_name(vhdl, name, MAXDEVNAME));	    }	} else {		dmamap->hdma_flags |= HUB_DMAMAP_USED;	}	/* There isn't actually any DMA mapping hardware on the hub. */        return (PHYS_TO_DMA(paddr));}/* * Driver indicates that it has completed whatever DMA it may have started * after an earlier dmamap_addr call. */voidhub_dmamap_done(hub_dmamap_t hub_dmamap)	/* done with these mapping resources */{	vertex_hdl_t vhdl;	if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {		hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED;	} else {	    /* If the map is FIXED, re-done is OK. */	    if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {		char name[MAXDEVNAME];		vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;		printk(KERN_WARNING  "%s: hub_dmamap_done already done with dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));	    }	}}/* * Translate a single system physical address into a crosstalk address. *//* ARGSUSED */iopaddr_thub_dmatrans_addr(	vertex_hdl_t dev,	/* translate for this device */			device_desc_t dev_desc,	/* device descriptor */			paddr_t paddr,		/* system physical address */			size_t byte_count,	/* length */			unsigned flags)		/* defined in dma.h */{	return (PHYS_TO_DMA(paddr));}/*ARGSUSED*/voidhub_dmamap_drain(	hub_dmamap_t map){    /* XXX- flush caches, if cache coherency WAR is needed */}/*ARGSUSED*/voidhub_dmaaddr_drain(	vertex_hdl_t vhdl,			paddr_t addr,			size_t bytes){    /* XXX- flush caches, if cache coherency WAR is needed */}/* CONFIGURATION MANAGEMENT *//* * Perform initializations that allow this hub to start crosstalk support. */voidhub_provider_startup(vertex_hdl_t hubv){	hubinfo_t       hubinfo;	hubinfo_get(hubv, &hubinfo);	hub_pio_init(hubv);	intr_init_vecblk(nasid_to_cnodeid(hubinfo->h_nasid));}/* * Shutdown crosstalk support from a hub. */voidhub_provider_shutdown(vertex_hdl_t hub){	/* TBD */	xtalk_provider_unregister(hub);}/* * Check that an address is in the real small window widget 0 space * or else in the big window we're using to emulate small window 0 * in the kernel. */inthub_check_is_widget0(void *addr){	nasid_t nasid = NASID_GET(addr);	if (((unsigned long)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) &&	    ((unsigned long)addr < RAW_NODE_SWIN_BASE(nasid, 1)))		return 1;	return 0;}/* * Check that two addresses use the same widget */inthub_check_window_equiv(void *addra, void *addrb){	if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb))		return 1;	/* XXX - Assume this is really a small window address */	if (WIDGETID_GET((unsigned long)addra) ==	    WIDGETID_GET((unsigned long)addrb))		return 1;	return 0;}/* * hub_setup_prb(nasid, prbnum, credits, conveyor) * * 	Put a PRB into fire-and-forget mode if conveyor isn't set.  Otherwise, * 	put it into conveyor belt mode with the specified number of credits. */voidhub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor){	iprb_t prb;	int prb_offset;	if (force_fire_and_forget && !ignore_conveyor_override)	    if (conveyor == HUB_PIO_CONVEYOR)		conveyor = HUB_PIO_FIRE_N_FORGET;	/*	 * Get the current register value.	 */	prb_offset = IIO_IOPRB(prbnum);	prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);	/*	 * Clear out some fields.	 */	prb.iprb_ovflow = 1;	prb.iprb_bnakctr = 0;	prb.iprb_anakctr = 0;	/*	 * Enable or disable fire-and-forget mode.	 */	prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);	/*	 * Set the appropriate number of PIO cresits for the widget.	 */	prb.iprb_xtalkctr = credits;	/*	 * Store the new value to the register.	 */	REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);}/* * hub_set_piomode() * * 	Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" * 	mode.  To do this, we have to make absolutely sure that no PIOs *	are in progress so we turn off access to all widgets for the duration *	of the function. *  * XXX - This code should really check what kind of widget we're talking * to.  Bridges can only handle three requests, but XG will do more. * How many can crossbow handle to widget 0?  We're assuming 1. * * XXX - There is a bug in the crossbow that link reset PIOs do not * return write responses.  The easiest solution to this problem is to * leave widget 0 (xbow) in fire-and-forget mode at all times.  This * only affects pio's to xbow registers, which should be rare. */voidhub_set_piomode(nasid_t nasid, int conveyor){	hubreg_t ii_iowa;	int direct_connect;	hubii_wcr_t ii_wcr;	int prbnum;	ASSERT(nasid_to_cnodeid(nasid) != INVALID_CNODEID);	ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);	REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);	ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);	direct_connect = ii_wcr.iwcr_dir_con;	if (direct_connect) {		/* 		 * Assume a bridge here.		 */		hub_setup_prb(nasid, 0, 3, conveyor);	} else {		/* 		 * Assume a crossbow here.		 */		hub_setup_prb(nasid, 0, 1, conveyor);	}	for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {		/*		 * XXX - Here's where we should take the widget type into		 * when account assigning credits.		 */		/* Always set the PRBs in fire-and-forget mode */		hub_setup_prb(nasid, prbnum, 3, conveyor);	}	REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);}/* Interface to allow special drivers to set hub specific * device flags. * Return 0 on failure , 1 on success */inthub_widget_flags_set(nasid_t		nasid,		     xwidgetnum_t	widget_num,		     hub_widget_flags_t	flags){	ASSERT((flags & HUB_WIDGET_FLAGS) == flags);	if (flags & HUB_PIO_CONVEYOR) {		hub_setup_prb(nasid,widget_num,			      3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor 						    * belt mode with 3 credits						    */	} else if (flags & HUB_PIO_FIRE_N_FORGET) {		hub_setup_prb(nasid,widget_num,			      3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire							 *  and forget mode 							 */	}	return 1;}/* * A pointer to this structure hangs off of every hub hwgraph vertex. * The generic xtalk layer may indirect through it to get to this specific * crosstalk bus provider. */xtalk_provider_t hub_provider = {	.piomap_alloc	= (xtalk_piomap_alloc_f *) hub_piomap_alloc,	.piomap_free	= (xtalk_piomap_free_f *) hub_piomap_free,	.piomap_addr	= (xtalk_piomap_addr_f *) hub_piomap_addr,	.piomap_done	= (xtalk_piomap_done_f *) hub_piomap_done,	.piotrans_addr	= (xtalk_piotrans_addr_f *) hub_piotrans_addr,	.dmamap_alloc	= (xtalk_dmamap_alloc_f *) hub_dmamap_alloc,	.dmamap_free	= (xtalk_dmamap_free_f *) hub_dmamap_free,	.dmamap_addr	= (xtalk_dmamap_addr_f *) hub_dmamap_addr,	.dmamap_done	= (xtalk_dmamap_done_f *) hub_dmamap_done,	.dmatrans_addr	= (xtalk_dmatrans_addr_f *) hub_dmatrans_addr,	.dmamap_drain	= (xtalk_dmamap_drain_f *) hub_dmamap_drain,	.dmaaddr_drain	= (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain,	.intr_alloc	= (xtalk_intr_alloc_f *) hub_intr_alloc,	.intr_alloc_nothd = (xtalk_intr_alloc_f *) hub_intr_alloc_nothd,	.intr_free	= (xtalk_intr_free_f *)	hub_intr_free,	.intr_connect	= (xtalk_intr_connect_f *) hub_intr_connect,	.intr_disconnect = (xtalk_intr_disconnect_f *) hub_intr_disconnect,	.provider_startup = (xtalk_provider_startup_f *) hub_provider_startup,	.provider_shutdown = (xtalk_provider_shutdown_f *) hub_provider_shutdown,};

⌨️ 快捷键说明

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