FreeBSD/sys/dev/cxgbe/t4_main.c
/*
 * Verify that the memory range specified by the addr/len pair is valid within
 * the card's address space.
 */
Verify that the memory range specified by the addr/len pair is valid within
the card's address space.
Verify that the memory range specified by the addr / len pair is valid within the card ' s address space .
static int
validate_mem_range(struct adapter *sc, uint32_t addr, int len)
{
	struct t4_range mem_ranges[4], *r, *next;
	uint32_t em, addr_len;
	int i, n, remaining;
	if (addr & 3 || len & 3 || len <= 0)
		return (EINVAL);
	em = t4_read_reg(sc, A_MA_TARGET_MEM_ENABLE);
	r = &mem_ranges[0];
	n = 0;
	bzero(r, sizeof(mem_ranges));
	if (em & F_EDRAM0_ENABLE) {
		addr_len = t4_read_reg(sc, A_MA_EDRAM0_BAR);
		r->size = G_EDRAM0_SIZE(addr_len) << 20;
		if (r->size > 0) {
			r->start = G_EDRAM0_BASE(addr_len) << 20;
			if (addr >= r->start &&
			    addr + len <= r->start + r->size)
				return (0);
			r++;
			n++;
		}
	}
	if (em & F_EDRAM1_ENABLE) {
		addr_len = t4_read_reg(sc, A_MA_EDRAM1_BAR);
		r->size = G_EDRAM1_SIZE(addr_len) << 20;
		if (r->size > 0) {
			r->start = G_EDRAM1_BASE(addr_len) << 20;
			if (addr >= r->start &&
			    addr + len <= r->start + r->size)
				return (0);
			r++;
			n++;
		}
	}
	if (em & F_EXT_MEM_ENABLE) {
		addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY_BAR);
		r->size = G_EXT_MEM_SIZE(addr_len) << 20;
		if (r->size > 0) {
			r->start = G_EXT_MEM_BASE(addr_len) << 20;
			if (addr >= r->start &&
			    addr + len <= r->start + r->size)
				return (0);
			r++;
			n++;
		}
	}
	if (is_t5(sc) && em & F_EXT_MEM1_ENABLE) {
		addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY1_BAR);
		r->size = G_EXT_MEM1_SIZE(addr_len) << 20;
		if (r->size > 0) {
			r->start = G_EXT_MEM1_BASE(addr_len) << 20;
			if (addr >= r->start &&
			    addr + len <= r->start + r->size)
				return (0);
			r++;
			n++;
		}
	}
	MPASS(n <= nitems(mem_ranges));
	if (n > 1) {
		qsort(mem_ranges, n, sizeof(struct t4_range), t4_range_cmp);
		r = &mem_ranges[0];
		for (remaining = n - 1; remaining > 0; remaining--, r++) {
			MPASS(r->size > 0);	
			next = r + 1;
			MPASS(next->size > 0);	
			while (r->start + r->size >= next->start) {
				r->size = max(r->start + r->size,
				    next->start + next->size) - r->start;
				n--;	
				if (--remaining == 0)
					goto done;	
				next++;
			}
			if (next != r + 1) {
				MPASS(next->size > 0);	
				memcpy(r + 1, next, remaining * sizeof(*r));
#ifdef INVARIANTS
				MPASS(n < nitems(mem_ranges));
				bzero(&mem_ranges[n], (nitems(mem_ranges) - n) *
				    sizeof(struct t4_range));
#endif
			}
		}
done:
		MPASS(n > 0);
		r = &mem_ranges[0];
		for (i = 0; i < n; i++, r++) {
			if (addr >= r->start &&
			    addr + len <= r->start + r->size)
				return (0);
		}
	}
	return (EFAULT);
}
static int validate_mem_range ( struct adapter * sc , uint32_t addr , int len ) { struct t4_range mem_ranges [ 4 ] , * r , * next ; uint32_t em , addr_len ; int i , n , remaining ; if ( addr & 3 || len & 3 || len <= 0 ) return ( EINVAL ) ; em = t4_read_reg ( sc , A_MA_TARGET_MEM_ENABLE ) ; r = & mem_ranges [ 0 ] ; n = 0 ; bzero ( r , sizeof ( mem_ranges ) ) ; if ( em & F_EDRAM0_ENABLE ) { addr_len = t4_read_reg ( sc , A_MA_EDRAM0_BAR ) ; r -> size = G_EDRAM0_SIZE ( addr_len ) << 20 ; if ( r -> size > 0 ) { r -> start = G_EDRAM0_BASE ( addr_len ) << 20 ; if ( addr >= r -> start && addr + len <= r -> start + r -> size ) return ( 0 ) ; r ++ ; n ++ ; } } if ( em & F_EDRAM1_ENABLE ) { addr_len = t4_read_reg ( sc , A_MA_EDRAM1_BAR ) ; r -> size = G_EDRAM1_SIZE ( addr_len ) << 20 ; if ( r -> size > 0 ) { r -> start = G_EDRAM1_BASE ( addr_len ) << 20 ; if ( addr >= r -> start && addr + len <= r -> start + r -> size ) return ( 0 ) ; r ++ ; n ++ ; } } if ( em & F_EXT_MEM_ENABLE ) { addr_len = t4_read_reg ( sc , A_MA_EXT_MEMORY_BAR ) ; r -> size = G_EXT_MEM_SIZE ( addr_len ) << 20 ; if ( r -> size > 0 ) { r -> start = G_EXT_MEM_BASE ( addr_len ) << 20 ; if ( addr >= r -> start && addr + len <= r -> start + r -> size ) return ( 0 ) ; r ++ ; n ++ ; } } if ( is_t5 ( sc ) && em & F_EXT_MEM1_ENABLE ) { addr_len = t4_read_reg ( sc , A_MA_EXT_MEMORY1_BAR ) ; r -> size = G_EXT_MEM1_SIZE ( addr_len ) << 20 ; if ( r -> size > 0 ) { r -> start = G_EXT_MEM1_BASE ( addr_len ) << 20 ; if ( addr >= r -> start && addr + len <= r -> start + r -> size ) return ( 0 ) ; r ++ ; n ++ ; } } MPASS ( n <= nitems ( mem_ranges ) ) ; if ( n > 1 ) { qsort ( mem_ranges , n , sizeof ( struct t4_range ) , t4_range_cmp ) ; r = & mem_ranges [ 0 ] ; for ( remaining = n - 1 ; remaining > 0 ; remaining -- , r ++ ) { MPASS ( r -> size > 0 ) ; next = r + 1 ; MPASS ( next -> size > 0 ) ; while ( r -> start + r -> size >= next -> start ) { r -> size = max ( r -> start + r -> size , next -> start + next -> size ) - r -> start ; n -- ; if ( -- remaining == 0 ) goto done ; next ++ ; } if ( next != r + 1 ) { MPASS ( next -> size > 0 ) ; memcpy ( r + 1 , next , remaining * sizeof ( * r ) ) ; #ifdef INVARIANTS MPASS ( n < nitems ( mem_ranges ) ) ; bzero ( & mem_ranges [ n ] , ( nitems ( mem_ranges ) - n ) * sizeof ( struct t4_range ) ) ; #endif } } done : MPASS ( n > 0 ) ; r = & mem_ranges [ 0 ] ; for ( i = 0 ; i < n ; i ++ , r ++ ) { if ( addr >= r -> start && addr + len <= r -> start + r -> size ) return ( 0 ) ; } } return ( EFAULT ) ; }
Verify that the memory range specified by the addr/len pair is valid within
 the card's address space.
Verify that the memory range specified by the addr / len pair is valid within the card ' s address space .
/* Memory can only be accessed in naturally aligned 4 byte units */ /* Enabled memories */ /* Sort and merge the ranges. */ /* Start from index 0 and examine the next n - 1 entries. */ /* r is a valid entry. */ /* and so is the next one. */ /* Merge the next one into the current entry. */ /* One fewer entry in total. */ /* short circuit */ /*
				 * Some entries were merged into r and next
				 * points to the first valid entry that couldn't
				 * be merged.
				 */ /* must be valid */ /*
				 * This so that the foo->size assertion in the
				 * next iteration of the loop do the right
				 * thing for entries that were pulled up and are
				 * no longer valid.
				 */ /* Done merging the ranges. */