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

📄 pcibr.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
LOCAL iopaddr_t         pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned);pcibr_piomap_t          pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);void                    pcibr_piomap_free(pcibr_piomap_t);caddr_t                 pcibr_piomap_addr(pcibr_piomap_t, iopaddr_t, size_t);void                    pcibr_piomap_done(pcibr_piomap_t);caddr_t                 pcibr_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned);iopaddr_t               pcibr_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t);void                    pcibr_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t);LOCAL iopaddr_t         pcibr_flags_to_d64(unsigned, pcibr_soft_t);LOCAL bridge_ate_t      pcibr_flags_to_ate(unsigned);pcibr_dmamap_t          pcibr_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);void                    pcibr_dmamap_free(pcibr_dmamap_t);LOCAL bridge_ate_p      pcibr_ate_addr(pcibr_soft_t, int);LOCAL iopaddr_t         pcibr_addr_xio_to_pci(pcibr_soft_t, iopaddr_t, size_t);iopaddr_t               pcibr_dmamap_addr(pcibr_dmamap_t, paddr_t, size_t);alenlist_t              pcibr_dmamap_list(pcibr_dmamap_t, alenlist_t, unsigned);void                    pcibr_dmamap_done(pcibr_dmamap_t);cnodeid_t		pcibr_get_dmatrans_node(devfs_handle_t);iopaddr_t               pcibr_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);alenlist_t              pcibr_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);void                    pcibr_dmamap_drain(pcibr_dmamap_t);void                    pcibr_dmaaddr_drain(devfs_handle_t, paddr_t, size_t);void                    pcibr_dmalist_drain(devfs_handle_t, alenlist_t);iopaddr_t               pcibr_dmamap_pciaddr_get(pcibr_dmamap_t);static unsigned		pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines);pcibr_intr_t            pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);void                    pcibr_intr_free(pcibr_intr_t);LOCAL void              pcibr_setpciint(xtalk_intr_t);int                     pcibr_intr_connect(pcibr_intr_t, intr_func_t, intr_arg_t, void *);void                    pcibr_intr_disconnect(pcibr_intr_t);devfs_handle_t            pcibr_intr_cpu_get(pcibr_intr_t);void                    pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);void                    pcibr_intr_func(intr_arg_t);LOCAL void              print_bridge_errcmd(uint32_t, char *);void                    pcibr_error_dump(pcibr_soft_t);uint32_t              pcibr_errintr_group(uint32_t);LOCAL void		pcibr_pioerr_check(pcibr_soft_t);LOCAL void              pcibr_error_intr_handler(intr_arg_t);LOCAL int               pcibr_addr_toslot(pcibr_soft_t, iopaddr_t, pciio_space_t *, iopaddr_t *, pciio_function_t *);LOCAL void              pcibr_error_cleanup(pcibr_soft_t, int);void                    pcibr_device_disable(pcibr_soft_t, int);LOCAL int               pcibr_pioerror(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);int                     pcibr_dmard_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);int                     pcibr_dmawr_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);LOCAL int               pcibr_error_handler(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *);int                     pcibr_error_devenable(devfs_handle_t, int);void                    pcibr_provider_startup(devfs_handle_t);void                    pcibr_provider_shutdown(devfs_handle_t);int                     pcibr_reset(devfs_handle_t);pciio_endian_t          pcibr_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t);int                     pcibr_priority_bits_set(pcibr_soft_t, pciio_slot_t, pciio_priority_t);pciio_priority_t        pcibr_priority_set(devfs_handle_t, pciio_priority_t);int                     pcibr_device_flags_set(devfs_handle_t, pcibr_device_flags_t);LOCAL cfg_p             pcibr_config_addr(devfs_handle_t, unsigned);uint64_t                pcibr_config_get(devfs_handle_t, unsigned, unsigned);LOCAL uint64_t          do_pcibr_config_get(cfg_p, unsigned, unsigned);void                    pcibr_config_set(devfs_handle_t, unsigned, unsigned, uint64_t);LOCAL void              do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);LOCAL pcibr_hints_t     pcibr_hints_get(devfs_handle_t, int);void                    pcibr_hints_fix_rrbs(devfs_handle_t);void                    pcibr_hints_dualslot(devfs_handle_t, pciio_slot_t, pciio_slot_t);void			pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *);void                    pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t);void                    pcibr_hints_handsoff(devfs_handle_t);void                    pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, ulong);LOCAL int		pcibr_slot_info_init(devfs_handle_t,pciio_slot_t);LOCAL int		pcibr_slot_info_free(devfs_handle_t,pciio_slot_t);#ifdef LATERLOCAL int	        pcibr_slot_info_return(pcibr_soft_t, pciio_slot_t,                                               pcibr_slot_info_resp_t);LOCAL void       	pcibr_slot_func_info_return(pcibr_info_h, int,                                                    pcibr_slot_func_info_resp_t);#endif	/* LATER */LOCAL int		pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t);LOCAL int		pcibr_slot_device_init(devfs_handle_t, pciio_slot_t);LOCAL int		pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t);LOCAL int		pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t);LOCAL int		pcibr_slot_call_device_attach(devfs_handle_t,						      pciio_slot_t, int);LOCAL int		pcibr_slot_call_device_detach(devfs_handle_t,						      pciio_slot_t, int);LOCAL int               pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int);LOCAL int 		pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);#ifdef LATERLOCAL int		pcibr_slot_query(devfs_handle_t, pcibr_slot_info_req_t);#endif/* ===================================================================== *    RRB management */#define LSBIT(word)		((word) &~ ((word)-1))#define PCIBR_RRB_SLOT_VIRTUAL	8LOCAL voiddo_pcibr_rrb_clear(bridge_t *bridge, int rrb){    bridgereg_t             status;    /* bridge_lock must be held;     * this RRB must be disabled.     */    /* wait until RRB has no outstanduing XIO packets. */    while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) {	;				/* XXX- beats on bridge. bad idea? */    }    /* if the RRB has data, drain it. */    if (status & BRIDGE_RRB_VALID(rrb)) {	bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb);	/* wait until RRB is no longer valid. */	while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) {	    ;				/* XXX- beats on bridge. bad idea? */	}    }}LOCAL voiddo_pcibr_rrb_flush(bridge_t *bridge, int rrbn){    reg_p                   rrbp = &bridge->b_rrb_map[rrbn & 1].reg;    bridgereg_t             rrbv;    int                     shft = 4 * (rrbn >> 1);    unsigned                ebit = BRIDGE_RRB_EN << shft;    rrbv = *rrbp;    if (rrbv & ebit)	*rrbp = rrbv & ~ebit;    do_pcibr_rrb_clear(bridge, rrbn);    if (rrbv & ebit)	*rrbp = rrbv;}/* *    pcibr_rrb_count_valid: count how many RRBs are *      marked valid for the specified PCI slot on this *      bridge. * *      NOTE: The "slot" parameter for all pcibr_rrb *      management routines must include the "virtual" *      bit; when manageing both the normal and the *      virtual channel, separate calls to these *      routines must be made. To denote the virtual *      channel, add PCIBR_RRB_SLOT_VIRTUAL to the slot *      number. * *      IMPL NOTE: The obvious algorithm is to iterate *      through the RRB fields, incrementing a count if *      the RRB is valid and matches the slot. However, *      it is much simpler to use an algorithm derived *      from the "partitioned add" idea. First, XOR in a *      pattern such that the fields that match this *      slot come up "all ones" and all other fields *      have zeros in the mismatching bits. Then AND *      together the bits in the field, so we end up *      with one bit turned on for each field that *      matched. Now we need to count these bits. This *      can be done either with a series of shift/add *      instructions or by using "tmp % 15"; I expect *      that the cascaded shift/add will be faster. */LOCAL intdo_pcibr_rrb_count_valid(bridge_t *bridge,			 pciio_slot_t slot){    bridgereg_t             tmp;    tmp = bridge->b_rrb_map[slot & 1].reg;    tmp ^= 0x11111111 * (7 - slot / 2);    tmp &= (0xCCCCCCCC & tmp) >> 2;    tmp &= (0x22222222 & tmp) >> 1;    tmp += tmp >> 4;    tmp += tmp >> 8;    tmp += tmp >> 16;    return tmp & 15;}/* *    do_pcibr_rrb_count_avail: count how many RRBs are *      available to be allocated for the specified slot. * *      IMPL NOTE: similar to the above, except we are *      just counting how many fields have the valid bit *      turned off. */LOCAL intdo_pcibr_rrb_count_avail(bridge_t *bridge,			 pciio_slot_t slot){    bridgereg_t             tmp;    tmp = bridge->b_rrb_map[slot & 1].reg;    tmp = (0x88888888 & ~tmp) >> 3;    tmp += tmp >> 4;    tmp += tmp >> 8;    tmp += tmp >> 16;    return tmp & 15;}/* *    do_pcibr_rrb_alloc: allocate some additional RRBs *      for the specified slot. Returns -1 if there were *      insufficient free RRBs to satisfy the request, *      or 0 if the request was fulfilled. * *      Note that if a request can be partially filled, *      it will be, even if we return failure. * *      IMPL NOTE: again we avoid iterating across all *      the RRBs; instead, we form up a word containing *      one bit for each free RRB, then peel the bits *      off from the low end. */LOCAL intdo_pcibr_rrb_alloc(bridge_t *bridge,		   pciio_slot_t slot,		   int more){    int                     rv = 0;    bridgereg_t             reg, tmp, bit;    reg = bridge->b_rrb_map[slot & 1].reg;    tmp = (0x88888888 & ~reg) >> 3;    while (more-- > 0) {	bit = LSBIT(tmp);	if (!bit) {	    rv = -1;	    break;	}	tmp &= ~bit;	reg = ((reg & ~(bit * 15)) | (bit * (8 + slot / 2)));    }    bridge->b_rrb_map[slot & 1].reg = reg;    return rv;}/* *    do_pcibr_rrb_free: release some of the RRBs that *      have been allocated for the specified *      slot. Returns zero for success, or negative if *      it was unable to free that many RRBs. * *      IMPL NOTE: We form up a bit for each RRB *      allocated to the slot, aligned with the VALID *      bitfield this time; then we peel bits off one at *      a time, releasing the corresponding RRB. */LOCAL intdo_pcibr_rrb_free(bridge_t *bridge,		  pciio_slot_t slot,		  int less){    int                     rv = 0;    bridgereg_t             reg, tmp, clr, bit;    int                     i;    clr = 0;    reg = bridge->b_rrb_map[slot & 1].reg;    /* This needs to be done otherwise the rrb's on the virtual channel     * for this slot won't be freed !!     */    tmp = reg & 0xbbbbbbbb;    tmp ^= (0x11111111 * (7 - slot / 2));    tmp &= (0x33333333 & tmp) << 2;    tmp &= (0x44444444 & tmp) << 1;    while (less-- > 0) {	bit = LSBIT(tmp);	if (!bit) {	    rv = -1;	    break;	}	tmp &= ~bit;	reg &= ~bit;	clr |= bit;    }    bridge->b_rrb_map[slot & 1].reg = reg;    for (i = 0; i < 8; i++)	if (clr & (8 << (4 * i)))	    do_pcibr_rrb_clear(bridge, (2 * i) + (slot & 1));    return rv;}LOCAL voiddo_pcibr_rrb_autoalloc(pcibr_soft_t pcibr_soft,		       int slot,		       int more_rrbs){    bridge_t               *bridge = pcibr_soft->bs_base;    int                     got;    for (got = 0; got < more_rrbs; ++got) {	if (pcibr_soft->bs_rrb_res[slot & 7] > 0)	    pcibr_soft->bs_rrb_res[slot & 7]--;	else if (pcibr_soft->bs_rrb_avail[slot & 1] > 0)	    pcibr_soft->bs_rrb_avail[slot & 1]--;	else	    break;	if (do_pcibr_rrb_alloc(bridge, slot, 1) < 0)	    break;#if PCIBR_RRB_DEBUG	printk( "do_pcibr_rrb_autoalloc: add one to slot %d%s\n",		slot & 7, slot & 8 ? "v" : "");#endif	pcibr_soft->bs_rrb_valid[slot]++;    }#if PCIBR_RRB_DEBUG    printk("%s: %d+%d free RRBs. Allocation list:\n", pcibr_soft->bs_name,	    pcibr_soft->bs_rrb_avail[0],	    pcibr_soft->bs_rrb_avail[1]);    for (slot = 0; slot < 8; ++slot)	printk("\t%d+%d+%d",		0xFFF & pcibr_soft->bs_rrb_valid[slot],		0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],		pcibr_soft->bs_rrb_res[slot]);	printk("\n");#endif}/* * Device driver interface to flush the write buffers for a specified * device hanging off the bridge. */intpcibr_wrb_flush(devfs_handle_t pconn_vhdl){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    volatile bridgereg_t   *wrb_flush;    wrb_flush = &(bridge->b_wr_req_buf[pciio_slot].reg);    while (*wrb_flush);    return(0);}/* * Device driver interface to request RRBs for a specified device * hanging off a Bridge.  The driver requests the total number of * RRBs it would like for the normal channel (vchan0) and for the * "virtual channel" (vchan1).  The actual number allocated to each * channel is returned. * * If we cannot allocate at least one RRB to a channel that needs * at least one, return -1 (failure).  Otherwise, satisfy the request * as best we can and return 0. */intpcibr_rrb_alloc(devfs_handle_t pconn_vhdl,		int *count_vchan0,		int *count_vchan1){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);    bridge_t               *bridge = pcibr_soft->bs_base;    int                     desired_vchan0;    int                     desired_vchan1;    int                     orig_vchan0;    int                     orig_vchan1;    int                     delta_vchan0;    int                     delta_vchan1;    int                     final_vchan0;    int                     final_vchan1;    int                     avail_rrbs;    unsigned long           s;    int                     error;    /*     * TBD: temper request with admin info about RRB allocation,     * and according to demand from other devices on this Bridge.     *     * One way of doing this would be to allocate two RRBs     * for each device on the bus, before any drivers start     * asking for extras. This has the weakness that one     * driver might not give back an "extra" RRB until after     * another driver has already failed to get one that     * it wanted.     */    s = pcibr_lock(pcibr_soft);    /* How many RRBs do we own? */    orig_vchan0 = pcibr_soft->bs_rrb_valid[pciio_slot];    orig_vchan1 = pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL];    /* How many RRBs do we want? */    desired_vchan0 = count_vchan0 ? *count_vchan0 : orig_vchan0;    desired_vchan1 = count_vchan1 ? *count_vchan1 : orig_vchan1;    /* How many RRBs are free? */    avail_rrbs = pcibr_soft->bs_rrb_avail[pciio_slot & 1]	+ pcibr_soft->bs_rrb_res[pciio_slot];    /* Figure desired deltas */    delta_vchan0 = desired_vchan0 - orig_vchan0;    delta_vchan1 = desired_vchan1 - orig_vchan1;    /* Trim back deltas to something

⌨️ 快捷键说明

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