/*******************************************************************************
* bd_chain.h - bd chain interface
*******************************************************************************/
#ifndef _BD_CHAIN_H
#define _BD_CHAIN_H
/* The number of bd's per page including the last bd which is used as
* a pointer to the next bd page. */
/* Number of bds that are used for the 'next' prt. The next ptr is constant size (sizeof lm_bd_chain_next). however,
* we will always work with 'full' bds. So if the bd-size is smaller than the next-ptr, we will use several, if it is
* larger, we will use a full one (no partial bds...) The equation 1+((next_bd_size-1)/bd_size) gives us the number of bds
* we need for this purpose. */
#define NUM_BDS_USED_FOR_NEXT_PTR(bd_size,is_chain_mode) ((is_chain_mode)? (1 + ((sizeof(lm_bd_chain_next)-1) / (bd_size))): 0)
/* The number of useable bd's per page. This number does not include the bds at the end of the page used for the 'next-bd' */
#define USABLE_BDS_PER_PAGE(bd_size,is_chain_mode) ((u32_t) (BD_PER_PAGE(bd_size)-NUM_BDS_USED_FOR_NEXT_PTR(bd_size,is_chain_mode)))
/* return number of available bds, i.e. _usable_ not produced bds */
{
}
/* return the cyclic prod idx */
{
}
/* return the cyclic cons idx */
{
}
/* return the usable_bds_per_page */
{
return bd_chain->usable_bds_per_page;
}
/* return the page_cnt */
{
}
/* return the bds_per_page */
{
return bd_chain->bds_per_page;
}
/* return the bds_per_page_mask */
{
return bd_chain->bds_per_page_mask;
}
/* return the bds_skip_eop */
{
return bd_chain->bds_skip_eop;
}
/* return empty state */
{
}
/* return full state */
{
}
/* returns the phys addr of the page of given page_idx. (page_idx >= 0) */
{
if (bd_chain->b_is_chain_mode)
{
/* TODO: assumption that memory is contiguous.. */
{
/* Increment mem_phy to the next page. */
}
}
else
{
}
return mem_phys;
}
/*******************************************************************************
* Description:
* afrer allocating the ring, this func fixes the last BD pointers at the
* end of a page to point to the first BD in the next page.
* Return:
******************************************************************************/
{
/* make sure all known bds structure equals to lm_bd_chain_next structure before */
/* tx bd */
/* rx bd */
ASSERT_STATIC(OFFSETOF(struct eth_rx_bd_next_page, addr_hi) == OFFSETOF(lm_bd_chain_next, addr_hi)) ;
ASSERT_STATIC(OFFSETOF(struct eth_rx_bd_next_page, addr_lo) == OFFSETOF(lm_bd_chain_next, addr_lo)) ;
ASSERT_STATIC(OFFSETOF(struct eth_rx_bd_next_page, reserved)== OFFSETOF(lm_bd_chain_next, reserved) ) ;
/* rcq */
ASSERT_STATIC(OFFSETOF(struct eth_rx_cqe_next_page, addr_hi) == OFFSETOF(lm_bd_chain_next, addr_hi)) ;
ASSERT_STATIC(OFFSETOF(struct eth_rx_cqe_next_page, addr_lo) == OFFSETOF(lm_bd_chain_next, addr_lo)) ;
ASSERT_STATIC(OFFSETOF(struct eth_rx_cqe_next_page, reserved)== OFFSETOF(lm_bd_chain_next, reserved) ) ;
/* Toe stuff */
ASSERT_STATIC(OFFSETOF(struct toe_page_addr_bd, reserved)== OFFSETOF(lm_bd_chain_next, reserved) ) ;
{
{
return ;
}
/* Increment mem_phy to the next page. */
/* Initialize the physical address of the next bd chain. */
/* Initialize the virtual address of the next bd chain. */
/* Move to the next bd chain. */
mem_virt += LM_PAGE_SIZE;
}
} /* lm_bd_chain_set_next_ptrs */
/* setup bd chain.
* - currently only physically contiguous chain format is supported
* - */
unsigned long log2_align(unsigned long n);
struct _lm_device_t *pdev,
void *mem_virt, /* ptr to caller pre-allocated buffer */
{
if (is_chain_mode)
{
next_bd = (lm_bd_chain_next *)((u8_t*)bd_chain->bd_chain_virt + (bd_chain->bd_size) * (bd_chain->usable_bds_per_page));
next_bd = (lm_bd_chain_next *)((u8_t*)(*(void **)(next_bd->reserved)) + (bd_chain->bd_size) * (bd_chain->usable_bds_per_page));
}
next_bd = (lm_bd_chain_next *)((u8_t*)mem_virt + (bd_chain->bd_size) * (bd_chain->usable_bds_per_page));
} else {
bd_chain->num_bd_to_sub = 0;
/* we assume power of 2 for bd_chain->bds_per_page */
/* Initialize the physical address of the next bd chain. */
next_bd = (lm_bd_chain_next *)((u8_t*)mem_virt + (bd_chain->bd_size) * (bd_chain->usable_bds_per_page));
/* Initialize the virtual address of the next bd chain. */
}
}
else
{
//TODO: currently TOE only, implement for PBL
// add the physical address of the page to the next pbl_page_idx
// ensure that the pbl_virt in this case is valid..
DbgBreak();
}
return LM_STATUS_SUCCESS;
}
struct _lm_device_t *pdev,
void *mem_virt, /* ptr to caller pre-allocated buffer */
{
/* we assume power of 2 for bd_chain->bds_per_page */
#ifdef __SunOS
/*
* This minor code change fixes a compiler error in SunStudio 12u1. The
* bug is that an "imulw $-0x80,..." is generated which wrecks the capacity
* value specifically when initializing the FCoE EQ chain. Shifting code
* the issue but would be a kludge. Note that I've created this ifdef to
* ensure someone doesn't come in later and merge these two lines together
* thereby reverting it to what it was before.
*/
#else
#endif
if(is_full) {
} else {
/* Don't count the last bd of a BD page. A full BD chain must
* have at least one empty entry. */
}
if(is_chain_mode)
{
bd_chain->num_bd_to_sub = 0;
}
return LM_STATUS_SUCCESS;
}
)
{
u32_t i;
if (CHK_NULL(buf_base_virt) ||
(pbl_entries == 0))
{
return LM_STATUS_INVALID_PARAMETER;
}
/* fill page table elements */
for (i = 0; i < pbl_entries; i++)
{
#ifdef BIG_ENDIAN
#else // LITTLE_ENDIAN
#endif
/* Increment mem_phy to the next page. */
/* TODO: assumption that memory is contiguous.. */
}
return LM_STATUS_SUCCESS;
}
struct _lm_device_t *pdev,
void *mem_virt, /* ptr to caller pre-allocated buffer */
void *pbl_virt_table, /* ptr to caller pre-allocated buffer of virt pbl */
{
FALSE);
if (lm_status != LM_STATUS_SUCCESS)
{
return lm_status;
}
//assign additional pbl members
// Upon first be consume or produce, page will be advanced,
// so set the initial page index to the last one
page_cnt);
if (lm_status != LM_STATUS_SUCCESS)
{
return lm_status;
}
return LM_STATUS_SUCCESS;
}
/** Description
* Function resets a bd chain: initializes the bds to 'all zeros'
* chain remains valid though, (last bd points to the next page of the bd chain)
*/
{
/* FIXME: assumption that memory is contiguous.. */
if (bd_chain->b_is_chain_mode)
{
}
else
{
FALSE);
}
}
/* Receives a bd_idx, pointer to bd and increases them.
* the physical address is the physical address of the base of the page
* Assumptions:
* - virt is initialized with the virtual address of the current bd
* - phys is initialized with the physical address of the current page
*/
lm_address_t * phys,
void ** virt,
{
(*bd_idx)++;
if (bd_chain->b_is_chain_mode) {
} else {
//TODO: currently TOE only, implement for PBL
DbgBreak();
}
}
}
{
if (bd_chain->b_is_chain_mode)
{
}
else
{
}
bd_chain->next_bd = *(void **)((u8_t *)bd_chain->pbl_virt_addr_table + (sizeof(void *) * bd_chain->pbe_idx));
}
}
/*******************************************************************************
* API For a bd-chain that the driver "Produces"
*******************************************************************************/
/* update bds availabily.
* - nbds - number of _usable_ consumed bds
* - NOTE: the chain consumer idx+pointer are not maintained! */
{
}
/* returns ptr to next _usable_ bd to be produced,
* decreases bds availability by 1, and updates prod idx.
* NOTE: special case for TOE: prod idx jumps to the next page only when the first bd of the next page is produced */
{
}
return ret_bd;
}
/* returns ptr to next _usable_ bd to be produced,
* decreases bds availability by 1, and updates prod idx.
*/
{
}
return ret_bd;
}
/*******************************************************************************
* API For a bd-chain that the driver "Consumes"
*******************************************************************************/
/* returns ptr to next _usable_ bd to be consume,
* increases bds availability by 1, and updates cons idx.
* NOTE: cons idx jumps to the next page only when the first bd of the next page is consumed */
{
}
return ret_bd;
}
{
}
return ret_bd;
}
/* returns a bd only if it is contiguous to the previously requested bd... otherwise NULL.
* The algorithm is based on the fact that we don't double-increase a consumer if we've reached the
* end of the page. we have one call that is called when the next_bd points to the last_bd, in which case
* we recognize that the next_bd is no longer contiguous, return NULL and move forward. The next call will
* return the next bd...
*/
{
return NULL; /* we've just skipped the last bd... */
}
return ret_bd;
}
/* update bds availabily and prod idx.
* - nbds - number of _usable_ produced bds
* Special case for TOE, they need producer increased only if we've moved to the next page... */
{
/* perform the operation "nbds % bd_chain->usable_bds_per_page" manually
(in order to avoid explicit modulo instruction that lead to very
expensive IDIV asm instruction) */
{
}
/* calculate the number of _next_ bds passed */
next_bds--; /* special care here, this next bd will be counted only next time bds are produced */
}
if((bd_chain->prod_idx & bd_chain->bds_per_page_mask) + nbds_mod_usable_bds > bd_chain->usable_bds_per_page) {
next_bds++;
}
/* update prod idx */
DbgBreakIfFastPath((bd_chain->prod_idx & bd_chain->bds_per_page_mask) > bd_chain->usable_bds_per_page); /* assertion relevant to 8b bd chain */
DbgBreakIfFastPath((bd_chain->prod_idx & bd_chain->bds_per_page_mask) == 0); /* GilR 5/13/2006 - this is currently the agreement with FW */
}
/* update bds availabily and prod idx.
* - nbds - number of _usable_ produced bds */
{
/* perform the operation "nbds % bd_chain->usable_bds_per_page" manually
(in order to avoid explicit modulo instruction that lead to very
expensive IDIV asm instruction) */
{
}
/* calculate the number of _next_ bds passed */
if((bd_chain->prod_idx & bd_chain->bds_per_page_mask) + nbds_mod_usable_bds > bd_chain->usable_bds_per_page) {
next_bds++;
}
/* update prod idx */
}
/* lm_bd_chain_bd_produced -
a performance optimated version of lm_bd_chain_bds_produced:
update bds availabily and prod idx, when only one bd is produced.
*/
{
/* if we passed a _next_ bd, increase prod_idx accordingly */
}
/* update prod idx for the produced bd */
}
/* TRUE if all params in bd_chains are equal but the pointers */
{
cmp_size );
return b_ret;
}
#endif /* _BD_CHAIN_H */