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 + -
显示快捷键?