📄 io.c
字号:
* 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)) );}/* * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc. * Return an appropriate crosstalk address list that maps to the specified physical * address list. *//* ARGSUSED */alenlist_thub_dmamap_list(hub_dmamap_t hub_dmamap, /* use these mapping resources */ alenlist_t palenlist, /* map this area of memory */ unsigned flags){ vertex_hdl_t vhdl; ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID); if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) { /* If the map is FIXED, re-use 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_list re-uses dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME)); } } else { hub_dmamap->hdma_flags |= HUB_DMAMAP_USED; } /* There isn't actually any DMA mapping hardware on the hub. */ return(palenlist);}/* * Driver indicates that it has completed whatever DMA it may have started * after an earlier dmamap_addr or dmamap_list 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)) );}/* * Translate a list of IP27 addresses and lengths into a list of crosstalk * addresses and lengths. No actual hardware mapping takes place; the hub * has no DMA mapping registers -- crosstalk addresses map directly. *//* ARGSUSED */alenlist_thub_dmatrans_list( vertex_hdl_t dev, /* translate for this device */ device_desc_t dev_desc, /* device descriptor */ alenlist_t palenlist, /* system address/length list */ unsigned flags) /* defined in dma.h */{ BUG(); /* no translation needed */ return(palenlist);}/*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 */}/*ARGSUSED*/voidhub_dmalist_drain( vertex_hdl_t vhdl, alenlist_t list){ /* XXX- flush caches, if cache coherency WAR is needed */}inthub_dma_enabled(vertex_hdl_t xconn_vhdl){ return(0);}inthub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code){ return(0);}/* CONFIGURATION MANAGEMENT *//* * Perform initializations that allow this hub to start crosstalk support. */voidhub_provider_startup(vertex_hdl_t hubv){ hub_pio_init(hubv); hub_intr_init(hubv);}/* * 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 (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) && ((__psunsigned_t)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((__psunsigned_t)addra) == WIDGETID_GET((__psunsigned_t)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_COMPACT_NODEID(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 = { (xtalk_piomap_alloc_f *) hub_piomap_alloc, (xtalk_piomap_free_f *) hub_piomap_free, (xtalk_piomap_addr_f *) hub_piomap_addr, (xtalk_piomap_done_f *) hub_piomap_done, (xtalk_piotrans_addr_f *) hub_piotrans_addr, (xtalk_dmamap_alloc_f *) hub_dmamap_alloc, (xtalk_dmamap_free_f *) hub_dmamap_free, (xtalk_dmamap_addr_f *) hub_dmamap_addr, (xtalk_dmamap_list_f *) hub_dmamap_list, (xtalk_dmamap_done_f *) hub_dmamap_done, (xtalk_dmatrans_addr_f *) hub_dmatrans_addr, (xtalk_dmatrans_list_f *) hub_dmatrans_list, (xtalk_dmamap_drain_f *) hub_dmamap_drain, (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain, (xtalk_dmalist_drain_f *) hub_dmalist_drain, (xtalk_intr_alloc_f *) hub_intr_alloc, (xtalk_intr_alloc_f *) hub_intr_alloc_nothd, (xtalk_intr_free_f *) hub_intr_free, (xtalk_intr_connect_f *) hub_intr_connect, (xtalk_intr_disconnect_f *) hub_intr_disconnect, (xtalk_provider_startup_f *) hub_provider_startup, (xtalk_provider_shutdown_f *) hub_provider_shutdown,};/* * per_ice_init * * This code is executed once for each Ice chip. */voidper_ice_init(cnodeid_t cnode){ /* Initialize error interrupts for this ice. */ printk("per_ice_init: We need to init ice here ....!\n"); /* ice_error_init(cnode); */}/* * per_hub_init * * This code is executed once for each Hub chip. */voidper_hub_init(cnodeid_t cnode){ nasid_t nasid; nodepda_t *npdap; ii_icmr_u_t ii_icmr; ii_ibcr_u_t ii_ibcr; ii_ilcsr_u_t ii_ilcsr; nasid = COMPACT_TO_NASID_NODEID(cnode); ASSERT(nasid != INVALID_NASID); ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode); npdap = NODEPDA(cnode); /* Disable the request and reply errors. */ REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000); /* * Set the total number of CRBs that can be used. */ ii_icmr.ii_icmr_regval= 0x0; ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf; if (enable_shub_wars_1_1() ) { // Set bit one of ICMR to prevent II from sending interrupt for II bug. ii_icmr.ii_icmr_regval |= 0x1; } REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); /* * Set the number of CRBs that both of the BTEs combined * can use minus 1. */ ii_ibcr.ii_ibcr_regval= 0x0; ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) { ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; } else { /* * if the LLP is down, there is no attached I/O, so * give BTE all the CRBs. */ ii_ibcr.ii_ibcr_fld_s.i_count = 0x14; } REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); /* * Set CRB timeout to be 10ms. */ REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff ); REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); /* Initialize error interrupts for this hub. */ hub_error_init(cnode);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -