FreeBSD/sys/dev/ntb/ntb_hw/ntb_hw.c
/*
 * ntb_mw_set_trans() - set the translation of a memory window
 * @ntb:        NTB device context
 * @idx:        Memory window number
 * @addr:       The dma address local memory to expose to the peer
 * @size:       The size of the local memory to expose to the peer
 *
 * Set the translation of a memory window.  The peer may access local memory
 * through the window starting at the address, up to the size.  The address
 * must be aligned to the alignment specified by ntb_mw_get_range().  The size
 * must be aligned to the size alignment specified by ntb_mw_get_range().  The
 * address must be below the plimit specified by ntb_mw_get_range() (i.e. for
 * 32-bit BARs).
 *
 * Return: Zero on success, otherwise an error number.
 */
set the translation of a memory window
@ntb:        NTB device context
@idx:        Memory window number
@addr:       The dma address local memory to expose to the peer
@size:       The size of the local memory to expose to the peer

Set the translation of a memory window.  The peer may access local memory
through the window starting at the address, up to the size.  The address
must be aligned to the alignment specified by ntb_mw_get_range().  The size
must be aligned to the size alignment specified by ntb_mw_get_range().  The
address must be below the plimit specified by ntb_mw_get_range() .

Zero on success, otherwise an error number.
set the translation of a memory window @ntb : NTB device context @idx : Memory window number @addr : The dma address local memory to expose to the peer @size : The size of the local memory to expose to the peer Set the translation of a memory window . The peer may access local memory through the window starting at the address up to the size . The address must be aligned to the alignment specified by ntb_mw_get_range () . The size must be aligned to the size alignment specified by ntb_mw_get_range () . The address must be below the plimit specified by ntb_mw_get_range () . Zero on success otherwise an error number .
int
ntb_mw_set_trans(struct ntb_softc *ntb, unsigned idx, bus_addr_t addr,
    size_t size)
{
	struct ntb_pci_bar_info *bar;
	uint64_t base, limit, reg_val;
	size_t bar_size, mw_size;
	uint32_t base_reg, xlat_reg, limit_reg;
	enum ntb_bar bar_num;
	if (idx >= ntb_mw_count(ntb))
		return (EINVAL);
	idx = ntb_user_mw_to_idx(ntb, idx);
	bar_num = ntb_mw_to_bar(ntb, idx);
	bar = &ntb->bar_info[bar_num];
	bar_size = bar->size;
	if (idx == ntb->b2b_mw_idx)
		mw_size = bar_size - ntb->b2b_off;
	else
		mw_size = bar_size;
	if ((addr & (bar_size - 1)) != 0)
		return (EINVAL);
	if (size > mw_size)
		return (EINVAL);
	bar_get_xlat_params(ntb, bar_num, &base_reg, &xlat_reg, &limit_reg);
	limit = 0;
	if (bar_is_64bit(ntb, bar_num)) {
		base = ntb_reg_read(8, base_reg) & BAR_HIGH_MASK;
		if (limit_reg != 0 && size != mw_size)
			limit = base + size;
		ntb_reg_write(8, xlat_reg, addr);
		reg_val = ntb_reg_read(8, xlat_reg) & BAR_HIGH_MASK;
		if (reg_val != addr) {
			ntb_reg_write(8, xlat_reg, 0);
			return (EIO);
		}
		ntb_reg_write(8, limit_reg, limit);
		reg_val = ntb_reg_read(8, limit_reg) & BAR_HIGH_MASK;
		if (reg_val != limit) {
			ntb_reg_write(8, limit_reg, base);
			ntb_reg_write(8, xlat_reg, 0);
			return (EIO);
		}
	} else {
		if ((addr & UINT32_MAX) != addr)
			return (ERANGE);
		if (((addr + size) & UINT32_MAX) != (addr + size))
			return (ERANGE);
		base = ntb_reg_read(4, base_reg) & BAR_HIGH_MASK;
		if (limit_reg != 0 && size != mw_size)
			limit = base + size;
		ntb_reg_write(4, xlat_reg, addr);
		reg_val = ntb_reg_read(4, xlat_reg) & BAR_HIGH_MASK;
		if (reg_val != addr) {
			ntb_reg_write(4, xlat_reg, 0);
			return (EIO);
		}
		ntb_reg_write(4, limit_reg, limit);
		reg_val = ntb_reg_read(4, limit_reg) & BAR_HIGH_MASK;
		if (reg_val != limit) {
			ntb_reg_write(4, limit_reg, base);
			ntb_reg_write(4, xlat_reg, 0);
			return (EIO);
		}
	}
	return (0);
}
int ntb_mw_set_trans ( struct ntb_softc * ntb , unsigned idx , bus_addr_t addr , size_t size ) { struct ntb_pci_bar_info * bar ; uint64_t base , limit , reg_val ; size_t bar_size , mw_size ; uint32_t base_reg , xlat_reg , limit_reg ; enum ntb_bar bar_num ; if ( idx >= ntb_mw_count ( ntb ) ) return ( EINVAL ) ; idx = ntb_user_mw_to_idx ( ntb , idx ) ; bar_num = ntb_mw_to_bar ( ntb , idx ) ; bar = & ntb -> bar_info [ bar_num ] ; bar_size = bar -> size ; if ( idx == ntb -> b2b_mw_idx ) mw_size = bar_size - ntb -> b2b_off ; else mw_size = bar_size ; if ( ( addr & ( bar_size - 1 ) ) != 0 ) return ( EINVAL ) ; if ( size > mw_size ) return ( EINVAL ) ; bar_get_xlat_params ( ntb , bar_num , & base_reg , & xlat_reg , & limit_reg ) ; limit = 0 ; if ( bar_is_64bit ( ntb , bar_num ) ) { base = ntb_reg_read ( 8 , base_reg ) & BAR_HIGH_MASK ; if ( limit_reg != 0 && size != mw_size ) limit = base + size ; ntb_reg_write ( 8 , xlat_reg , addr ) ; reg_val = ntb_reg_read ( 8 , xlat_reg ) & BAR_HIGH_MASK ; if ( reg_val != addr ) { ntb_reg_write ( 8 , xlat_reg , 0 ) ; return ( EIO ) ; } ntb_reg_write ( 8 , limit_reg , limit ) ; reg_val = ntb_reg_read ( 8 , limit_reg ) & BAR_HIGH_MASK ; if ( reg_val != limit ) { ntb_reg_write ( 8 , limit_reg , base ) ; ntb_reg_write ( 8 , xlat_reg , 0 ) ; return ( EIO ) ; } } else { if ( ( addr & UINT32_MAX ) != addr ) return ( ERANGE ) ; if ( ( ( addr + size ) & UINT32_MAX ) != ( addr + size ) ) return ( ERANGE ) ; base = ntb_reg_read ( 4 , base_reg ) & BAR_HIGH_MASK ; if ( limit_reg != 0 && size != mw_size ) limit = base + size ; ntb_reg_write ( 4 , xlat_reg , addr ) ; reg_val = ntb_reg_read ( 4 , xlat_reg ) & BAR_HIGH_MASK ; if ( reg_val != addr ) { ntb_reg_write ( 4 , xlat_reg , 0 ) ; return ( EIO ) ; } ntb_reg_write ( 4 , limit_reg , limit ) ; reg_val = ntb_reg_read ( 4 , limit_reg ) & BAR_HIGH_MASK ; if ( reg_val != limit ) { ntb_reg_write ( 4 , limit_reg , base ) ; ntb_reg_write ( 4 , xlat_reg , 0 ) ; return ( EIO ) ; } } return ( 0 ) ; }
ntb_mw_set_trans() - set the translation of a memory window
 @ntb:        NTB device context
 @idx:        Memory window number
 @addr:       The dma address local memory to expose to the peer
 @size:       The size of the local memory to expose to the peer
ntb_mw_set_trans () - set the translation of a memory window @ntb : NTB device context @idx : Memory window number @addr : The dma address local memory to expose to the peer @size : The size of the local memory to expose to the peer
/* Hardware requires that addr is aligned to bar size */ /* Set and verify translation address */ /* Set and verify the limit */ /* Configure 32-bit (split) BAR MW */ /* Set and verify translation address */ /* Set and verify the limit */