/*******************************************************************************
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2014 QLogic Corporation
* The contents of this file are subject to the terms of the
* QLogic End User License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing permissions
* and limitations under the License.
*
*
* Module Description:
* This file contains general LM utility functions
*
******************************************************************************/
#include "lm5710.h"
#ifdef _VBD_CMD_
#include "everest_sim.h"
#endif
{
return n % 255 ;
}
unsigned long log2_align(unsigned long n)
{
while (_n)
{
_n >>= 1;
ret <<= 1;
}
if (ret < n)
ret <<= 1;
return ret;
}
/**
* @description
* Should be moved to a common file.
* Calculates the lower align of power 2.
* Values lower than 0 are returned directly.
* @param n
*
* @return unsigned long
* lower align of power 2.
*/
unsigned long power2_lower_align(unsigned long n)
{
unsigned long ret = 0;
if(0 == n)
{
return 0;
}
if(TRUE == POWER_OF_2(n))
{
// The number is already a power of 2.
return n;
}
//Calculates the lower align of power 2.
ret = log2_align(n);
ret >>= 1;
return ret;
}
/*
Log2
this function calculates rounded LOG2 of a certain number
e.g.: LOG2(1080) = 10 (2^10=1024)
*/
u32_t r=0;
while (v >>= 1) {
r++;
}
return r;
}
/**
* @description
* Should be moved to a common place.
* Find the next power of 2 that is larger than "num".
* @param num - The variable to find a power of 2 that is
* larger.
* @param num_bits_supported - The largest number of bits
* supported
*
* @return u32_t - The next power of 2 that is larger than
* "num".
*/
{
u8_t i = 0;
//This is not realy needed (the for also handles this case) but to avoide confusing
if(num >= largest_power_of_2)
{
DbgBreakMsg("num is larger than num_bits_supported");
return largest_power_of_2;
}
// Exception case
if(0 == num)
{
return 1;
}
// Look for a value that is smaller than prev_power_of_2 and bigger than cur_power_of_2
for (i = (num_bits_supported - 1) ; i != 0 ;i--)
{
cur_power_of_2 = 1 << (i);
if(num > cur_power_of_2)
{
break;
}
}
return prev_power_of_2;
}
/**
* General function that waits for a certain state to change,
* not protocol specific. It takes into account vbd-commander
* and reset-is-in-progress
*
* @param pdev
* @param curr_state -> what to poll on
* @param new_state -> what we're waiting for
*
* @return lm_status_t TIMEOUT if state didn't change, SUCCESS
* otherwise
*/
/**
* @param pdev
*
* @return 0 if device is ASIC.
*/
{
if (val > CHIP_REV_Cx) {
return 1;
} else {
return 0;
}
}
lm_status_t lm_wait_state_change(struct _lm_device_t *pdev, volatile u32_t * curr_state, u32_t new_state)
{
u32_t to_cnt = 10000 + 2360; // We'll wait 10,000 times 100us (1 second) + 2360 times 25000us (59sec) = total 60 sec
// (Winodws only note) the 25000 wait will cause wait to be without CPU stall (look in win_util.c)
#ifdef _VBD_CMD_
{
*curr_state = new_state;
return lm_status;
}
#endif
/* wait for state change */
{
#ifdef DOS
sleep(0); // rescheduling threads, since we don't have a memory barrier.
mm_read_barrier(); // synchronize on eth_con->con_state
#endif
// in case reset in progress
// we won't get completion so no need to wait
if( lm_reset_is_inprogress(pdev) )
{
break;
}
}
if ( *curr_state != new_state)
{
"lm_wait_state_change: state change timeout, curr state=%d, expected new state=%d!\n",
*curr_state, new_state);
if (!lm_reset_is_inprogress(pdev)) {
#if defined(_VBD_)
DbgBreak();
#endif
}
}
return lm_status;
}
/*******************************************************************************
* Description:
* Calculates crc 32 on a buffer
* Note: crc32_length MUST be aligned to 8
* Return:
******************************************************************************/
{
{
return crc32_result ;
}
{
{
{
}
}
}
// Last step is to "mirror" every bit, swap the 4 bytes, and then complement each bit.
//
// Mirror:
temp = crc32_result ;
{
temp <<= 1;
shft-- ;
}
//temp[31-bit] = crc32_result[bit];
// Swap:
// crc32_result = {temp[7:0], temp[15:8], temp[23:16], temp[31:24]};
{
}
// Complement:
if (complement)
{
crc32_result = ~crc32_result ;
}
return crc32_result ;
}
/**
* @brief: convert 4 bytes version into 32 bit BCD formatted version
*
* 1. Format the product_version string:
* a. The "Major, "Minor, "Build and "Sub build" bytes are BCD-encoded, and each byte holds two BCD digits.
* b. The semantics of these fields follow the semantics specified in DSP4004.
* c. The value 0xF in the most-significant nibble of a BCD-encoded value indicates that the most significant nibble should be ignored and the overall field treated as a single digit value.
* d. A value of 0xFF indicates that the entire field is not present. 0xFF is not allowed as a value for the fields.
* Example: Version 3.7.10.FF --> 0xF3F710FF
*
* @param[in] CONST u8_t IN ver_arr[4]
*
* @return u32_t value
*/
{
if ( ver_arr )
{
ver_32 = 0;
// convert to BCD format
// We have for sure 4 digits only
// ARRSIZE(ver_arr) won't work here since in non x86 compile it is NOT 4....
{
if ( 0 == ( ver_current & 0xf0 ) )
{
ver_current |= 0xf0 ;
}
}
}
return ver_32;
}