/*******************************************************************************
* 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 functions that handle power management and WOL
* functionality
*
******************************************************************************/
#include "lm5710.h"
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
{
{
return 0 ;
}
// Write the size + crc32 of the patterns
{
// find NIG registers names
switch( idx )
{ /* TBD - E1H: currenlty assuming split registers in NIG */
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
DbgBreakMsg("Invalid index\n") ;
return 0 ;
} // switch idx
// write pattern length
DbgMessage(pdev, VERBOSE, "init_nwuf_57710: idx[%d] crc_mask=0x%08x size=%d\n", idx, nwuf->crc32, val );
// Init NIG registers
if (0)
{
{
DbgMessage(pdev, WARN, "init_nwuf_57710: idx[%d] Updated size=%03d-->%03d\n", idx, nwuf->size * 8, val ) ;
}
}
#endif
// write crc value
} // LM_MAX_NWUF_CNT loop
// byte enable mask
// create a matrix following LLH_vlsi_spec_rev4.doc document:
//
// 63 56 7 0
// +------------------------------------------------------------------------------------------------------------------------+
//word 0 |Pattern 7 bit 0 | Pattern 6 bit 0 |....|Pattern 0 bit 0|..... |Pattern 7 bit 7 | Pattern 6 bit 7 |....|Pattern 0 bit 7 |
// +------------------------------------------------------------------------------------------------------------------------+
//word 1 |Pattern 7 bit 8 | Pattern 6 bit 8 |....|Pattern 0 bit 8|..... |Pattern 7 bit 15| Pattern 6 bit 15|....|Pattern 0 bit 15 |
// +------------------------------------------------------------------------------------------------------------------------+
// | .......... |
// +------------------------------------------------------------------------------------------------------------------------+
// | .......... |
// +------------------------------------------------------------------------------------------------------------------------+
// | |
// +------------------------------------------------------------------------------------------------------------------------+
// | .......... |
// +------------------------------------------------------------------------------------------------------------------------+
//word 15 |Pattern 7bit 120| Pattern6 bit120 |....|Pattern0 bit120|..... |Pattern7 bit 127| Pattern6 bit 127|....|Pattern0 bit 127 |
// +------------------------------------------------------------------------------------------------------------------------+
{
{
// write to the registers, WB (write using DMAE)
// For yet to be explained reasons, using WR_DMAE write it to the opposite port.
// We'll always use indirect writes
if( 0 )//pdev->vars.b_is_dmae_ready )
{
}
else
{
}
// reset for next 8 iterations
val_64 = 0 ;
}
// after write - nothing to do!
if( LM_NWUF_PATTERN_SIZE == offset )
{
break ;
}
{
{
continue;
}
{
}
} // LM_MAX_NWUF_CNT
if( mod != 7 )
{
}
} // LM_NWUF_PATTERN_SIZE
nwuf_cnt = 0;
// count total items
{
{
continue;
}
nwuf_cnt++ ;
}
return nwuf_cnt;
} /* init_nwuf_57510 */
/*******************************************************************************
* Description:
* Configures nwuf packets.
* (for wide bus)
* Return:
******************************************************************************/
const lm_wake_up_mode_t wake_up_mode )
{
/* Set up interesting packet detection. */
{
// This comment - from TETON
/* Also need to be documented in the prm - to prevent a false
* detection, we need to disable ACP_EN if there is no pattern
* programmed. There is no way of preventing false detection
* by intializing the pattern buffer a certain way. */
{
nwuf_reg_value = 1 ;
}
else
{
nwuf_reg_value = 0 ;
}
// Enable ACPI register (split)
if( !CHIP_IS_E1(pdev) )
{
// mark function for enablement in nig
// for E2 and above, we need to set also NIG_REG_PX_ACPI_MF_GLOBAL_EN to 1
// This register is global per port.
// The "algorithm" will be - if ANY of the vnic is enabled - we enable ACPI for the port (logic OR)
// The patterns themselves should prevent a "false positive" wake up for a function
// All the above is relevant for MF SI mode!
if ( !CHIP_IS_E1x(pdev) &&
( IS_MF_SI_MODE(pdev) ) )
{
// TODO - NIV (T7.0) should be different behaviour!
DbgBreakIf( !nwuf_reg_value );
}
}
}
else
{
}
} /* lm_set_d3_nwuf */
/*******************************************************************************
* Description:
* Configures magic packets.
* Return:
******************************************************************************/
const lm_wake_up_mode_t wake_up_mode )
{
{
DbgBreakIf(!pdev) ;
return;
}
/* Set up magic packet detection. */
if( b_enable_mpkt )
{
}
else
{
}
/* The mac address is written to entries 1-5 to
preserve entry 0 which is used by the PMF */
offset+= 4;
}
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
STATIC void
{
#if 0
/* This step should be done by the OS or the caller. Windows is
* already doing this. */
if(set_pci_pm)
{
/* Set the device to D0 state. If a device is already in D3 state,
* we will not be able to read the PCICFG_PM_CSR register using the
* PCI memory command, we need to use config access here. */
pdev,
&val);
/* Set the device to D0 state. This may be already done by the OS. */
val &= ~PCICFG_PM_CSR_STATE;
pdev,
val);
}
#endif
/* With 5706_A1, the chip gets a reset coming out of D3. Wait
* for the boot to code finish running before we continue. Without
* this wait, we could run into lockup or the PHY may not work. */
{
{
}
}
#if 0 // PWR_TODO - WOL wait for spec
/* Clear the ACPI_RCVD and MPKT_RCVD bits and disable magic packet. */
val &= ~EMAC_MODE_MPKT;
/* Disable interesting packet detection. */
val &= ~RPM_CONFIG_ACPI_ENA;
#endif // if 0
} /* set_d0_power_state */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
switch( power_state )
{
case LM_POWER_STATE_D0:
break;
default:
//set_d3_power_state(pdev, wake_up_mode, set_pci_pm);
break;
}
} /* lm_set_power_state */
{
{
}
}
{
{
}
return 0;
}
#define DEFINITIVE_PF_FOR_MPS 0 //PF0 defines the MPS value for all PFs when the device is in ARI mode.
{
//save PF0's PCIE_REG_PCIER_DEVICE_STATUS_CONTROL, since Windows does not restore the MPS value properly when resuming from
//D3. See CQ57271.
if (DEFINITIVE_PF_FOR_MPS != abs_func_id)
{
pdev->hw_info.saved_pf0_pcie_mps = GET_FLAGS(pf0_pcie_status_control, PCICFG_DEVICE_CONTROL_MPS_MASK);
}
}
{
//restore PF0's PCIE_REG_PCIER_DEVICE_STATUS_CONTROL, since Windows does not restore the MPS value properly when resuming from
//D3. See CQ57271.
{
//read current MPS value of PF0
//if it's different than the value we saved when going down to D3, and it's different then
//current PF's MPS - restore it
{
}
}
}
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
{
u32_t j;
u32_t k;
{
{
continue;
}
{
{
break;
}
for(k = 0; k < 8; k++)
{
if((byte_mask[j] & (1 << k)) &&
{
break;
}
}
}
if(found)
{
return nwuf;
}
}
return NULL;
} /* find_nwuf */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
{
u32_t j = 0 ;
u32_t k = 0 ;
{
DbgBreakMsg("Invalid byte mask size\n");
return LM_STATUS_FAILURE;
}
/* If this is a duplicate entry, we are done. */
// according to DTM test (WHQL) we should fail duplicate adding
{
return LM_STATUS_EXISTING_OBJECT;
}
/* Find an empty slot. */
{
{
break;
}
}
{
return LM_STATUS_RESOURCE;
}
/* Save nwuf data. */
// apply the mask on the pattern
for(j = 0; j < mask_size; j++)
{
for(k = 0; k < 8; k++)
{
if(byte_mask[j] & (1 << k))
{
zero_serial = 0;
}
else
{
++zero_serial;
}
}
}
// Decrement from pattern size last bits that are not enabled (revresed)
// TODO: When pattern size will be added to the interface, this calculation (zero_serial) is not needed, and
// pattern size would be the original pattern size as recieved from OS
{
j++;
}
j*= 8;
// TODO: when patter size will be added to the interface, j should be: mask_size*8
// calc the CRC using the same NIG algorithem and save it
#define WOL_DBG_PRINT 0
#if (WOL_DBG_PRINT) // this is to debug wolpattern WHQL test
{
printk("lm_add_nwuf: pattern[%u] mask_size=%03u pattern_size=%03u (%03u) crc calc size=%03u\n",
idx,
j );
//printk("Pattern (original) size=%03u\n", nwuf->pattern_size ) ;
{
{
printk("-") ;
}
{
printk("\n") ;
}
}
printk("\nPattern (masked):\n");
{
{
printk("-") ;
}
{
printk("\n") ;
}
}
{
{
printk("-") ;
}
}
printk("\n") ;
}
#endif // WOL_DBG_PRINT
{
DbgBreakMsg("Invalid crc32\n") ;
}
return LM_STATUS_SUCCESS;
} /* lm_add_nwuf */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
{
u32_t k;
{
DbgBreakMsg("Invalid byte mask size\n");
return LM_STATUS_FAILURE;
}
/* Look for a matching pattern. */
if(nwuf)
{
/*
printk("lm_del_nwuf: pattern[?] mask_size=%03u(%03u) cnt=%u crc32=0x%08x %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X....\n",
nwuf->size, nwuf->size*8, pdev->nwuf_list.cnt-1, nwuf->crc32,
nwuf->pattern[0], nwuf->pattern[1], nwuf->pattern[2], nwuf->pattern[3],
nwuf->pattern[4], nwuf->pattern[5], nwuf->pattern[6], nwuf->pattern[7],
nwuf->pattern[8], nwuf->pattern[9], nwuf->pattern[10], nwuf->pattern[11],
nwuf->pattern[12], nwuf->pattern[13], nwuf->pattern[14], nwuf->pattern[15] ) ;
*/
for(k = 0; k < LM_NWUF_PATTERN_MASK_SIZE; k++)
{
}
for(k = 0; k < LM_NWUF_PATTERN_SIZE; k++)
{
}
}
else
{
// according to DTM test (WHQL) we should fail non exists delete
return LM_STATUS_OBJECT_NOT_FOUND;
}
return LM_STATUS_SUCCESS;
} /* lm_del_nwuf */
/*******************************************************************************
* Description:
*
* Return:
******************************************************************************/
void
{
u32_t j;
u32_t k;
for(j = 0; j < LM_MAX_NWUF_CNT; j++)
{
for(k = 0; k < LM_NWUF_PATTERN_MASK_SIZE; k++)
{
}
for(k = 0; k < LM_NWUF_PATTERN_SIZE; k++)
{
}
}
} /* lm_clear_nwuf */