📄 io.c
字号:
/* TBD: send disconnected interrupts somewhere harmless */ if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl);#if defined(NEW_INTERRUPTS) rv = intr_disconnect_level(cpu, bit); ASSERT(rv == 0);#endif intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED;}/* * Return a hwgraph vertex that represents the CPU currently * targeted by an interrupt. */devfs_handle_thub_intr_cpu_get(hub_intr_t intr_hdl){ cpuid_t cpuid = intr_hdl->i_cpuid; ASSERT(cpuid != CPU_NONE); return(cpuid_to_vertex(cpuid));}/* CONFIGURATION MANAGEMENT *//* * Perform initializations that allow this hub to start crosstalk support. */voidhub_provider_startup(devfs_handle_t hubv){ hub_pio_init(hubv); hub_dma_init(hubv); hub_intr_init(hubv);}/* * Shutdown crosstalk support from a hub. */voidhub_provider_shutdown(devfs_handle_t hub){ /* TBD */ xtalk_provider_unregister(hub);}/* * Check that an address is in teh 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;}/* * Determine whether two PCI addresses actually refer to the same device. * This only works if both addresses are in small windows. It's used to * determine whether prom addresses refer to particular PCI devices. *//* * XXX - This won't work as written if we ever have more than two nodes * on a crossbow. In that case, we'll need an array or partners. */inthub_check_pci_equiv(void *addra, void *addrb){ nasid_t nasida, nasidb; /* * This is for a permanent workaround that causes us to use a * big window in place of small window 0. */ if (!hub_check_window_equiv(addra, addrb)) return 0; /* If the offsets aren't the same, forget it. */ if (SWIN_WIDGETADDR((__psunsigned_t)addra) != (SWIN_WIDGETADDR((__psunsigned_t)addrb))) return 0; /* Now, check the nasids */ nasida = NASID_GET(addra); nasidb = NASID_GET(addrb); ASSERT(NASID_TO_COMPACT_NODEID(nasida) != INVALID_NASID); ASSERT(NASID_TO_COMPACT_NODEID(nasidb) != INVALID_NASID); /* * Either the NASIDs must be the same or they must be crossbow * partners (on the same crossbow). */ return (check_nasid_equiv(nasida, nasidb));}/* * hub_setup_prb(nasid, prbnum, credits, conveyor) * * Put a PRB into fire-and-forget mode if conveyor isn't set. Otehrwise, * 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;#ifdef LATER extern int force_fire_and_forget; extern volatile int ignore_conveyor_override; if (force_fire_and_forget && !ignore_conveyor_override) if (conveyor == HUB_PIO_CONVEYOR) conveyor = HUB_PIO_FIRE_N_FORGET;#endif /* * 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; int cons_lock = 0; ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID); if (nasid == get_console_nasid()) { PUTBUF_LOCK(s); cons_lock = 1; } 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); if (cons_lock) PUTBUF_UNLOCK(s);}/* 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;}/* Interface to allow special drivers to set hub specific * device flags. * Return 0 on failure , 1 on success */inthub_device_flags_set(devfs_handle_t widget_vhdl, hub_widget_flags_t flags){ xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); xwidgetnum_t widget_num = xwidget_info_id_get(widget_info); devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); hubinfo_t hub_info = 0; nasid_t nasid; unsigned long s; int rv; /* Use the nasid from the hub info hanging off the hub vertex * and widget number from the widget vertex */ hubinfo_get(hub_vhdl, &hub_info); /* Being over cautious by grabbing a lock */ s = mutex_spinlock(&hub_info->h_bwlock); nasid = hub_info->h_nasid; rv = hub_widget_flags_set(nasid,widget_num,flags); mutex_spinunlock(&hub_info->h_bwlock, s); return rv;}#if ((defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && defined(BRINGUP))/* BRINGUP: This ought to be useful for IP27 too but, for now, * make it SN1 only because `ii_ixtt_u_t' is not in IP27/hubio.h * (or anywhere else :-). */inthubii_ixtt_set(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt){ xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); hubinfo_t hub_info = 0; nasid_t nasid; unsigned long s; /* Use the nasid from the hub info hanging off the hub vertex * and widget number from the widget vertex */ hubinfo_get(hub_vhdl, &hub_info); /* Being over cautious by grabbing a lock */ s = mutex_spinlock(&hub_info->h_bwlock); nasid = hub_info->h_nasid; REMOTE_HUB_S(nasid, IIO_IXTT, ixtt->ii_ixtt_regval); mutex_spinunlock(&hub_info->h_bwlock, s); return 0;}inthubii_ixtt_get(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt){ xwidget_info_t widget_info = xwidget_info_get(widget_vhdl); devfs_handle_t hub_vhdl = xwidget_info_master_get(widget_info); hubinfo_t hub_info = 0; nasid_t nasid; unsigned long s; /* Use the nasid from the hub info hanging off the hub vertex * and widget number from the widget vertex */ hubinfo_get(hub_vhdl, &hub_info); /* Being over cautious by grabbing a lock */ s = mutex_spinlock(&hub_info->h_bwlock); nasid = hub_info->h_nasid; ixtt->ii_ixtt_regval = REMOTE_HUB_L(nasid, IIO_IXTT); mutex_spinunlock(&hub_info->h_bwlock, s); return 0;}#endif /* CONFIG_IA64_SGI_SN1 *//* * hub_device_inquiry * Find out the xtalk widget related information stored in this * hub's II. */voidhub_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget){ devfs_handle_t xconn, hub_vhdl; char widget_name[8]; hubreg_t ii_iidem,ii_iiwa, ii_iowa; hubinfo_t hubinfo; nasid_t nasid; int d; sprintf(widget_name, "%d", widget); if (hwgraph_traverse(xbus_vhdl, widget_name, &xconn) != GRAPH_SUCCESS) return; hub_vhdl = device_master_get(xconn); if (hub_vhdl == GRAPH_VERTEX_NONE) return; hubinfo_get(hub_vhdl, &hubinfo); if (!hubinfo) return; nasid = hubinfo->h_nasid; ii_iidem = REMOTE_HUB_L(nasid, IIO_IIDEM); ii_iiwa = REMOTE_HUB_L(nasid, IIO_IIWA); ii_iowa = REMOTE_HUB_L(nasid, IIO_IOWA);#if defined(SUPPORT_PRINTING_V_FORMAT) printk("Inquiry Info for %v\n", xconn);#else printk("Inquiry Info for 0x%x\n", xconn);#endif printk("\tDevices shutdown [ "); for (d = 0 ; d <= 7 ; d++) if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d)))) printk(" %d", d); printk("]\n"); printk("\tInbound access ? %s\n", ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no"); printk("\tOutbound access ? %s\n", ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no");}/* * 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_intr_cpu_get_f *) hub_intr_cpu_get, (xtalk_provider_startup_f *) hub_provider_startup, (xtalk_provider_shutdown_f *) hub_provider_shutdown,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -