863 lines
24 KiB
C
863 lines
24 KiB
C
|
#if defined(__KERNEL__) && !defined(MV_UBOOT)
|
||
|
/* include file on kernel */
|
||
|
#include <linux/version.h>
|
||
|
#include <linux/if_ether.h>
|
||
|
|
||
|
#include "BuffaloGpio.h"
|
||
|
#include "eth-phy/mvEthPhy.h"
|
||
|
#include "eth-phy/mvEthPhyRegs.h"
|
||
|
#include "eth/mvEth.h"
|
||
|
#include "eth/gbe/mvEthGbe.h"
|
||
|
#include "eth/gbe/mvEthRegs.h"
|
||
|
#include "BuffaloWol.h"
|
||
|
#else
|
||
|
/* include file on u-boot */
|
||
|
#include "eth-phy/mvEthPhy.h"
|
||
|
#include "eth-phy/mvEthPhyRegs.h"
|
||
|
#include "boardEnv/mvBoardEnvLib.h"
|
||
|
#include "eth/mvEth.h"
|
||
|
#include "eth/gbe/mvEthGbe.h"
|
||
|
#include "eth/gbe/mvEthRegs.h"
|
||
|
#include "BuffaloWol.h"
|
||
|
|
||
|
#include <net.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if defined(__KERNEL__) && !defined(MV_UBOOT)
|
||
|
#define DEBUG(fmt, args...) printk(fmt, ##args)
|
||
|
typedef unsigned char uchar;
|
||
|
|
||
|
/*
|
||
|
* Ethernet header
|
||
|
*/
|
||
|
typedef struct {
|
||
|
uchar et_dest[6]; /* Destination node */
|
||
|
uchar et_src[6]; /* Source node */
|
||
|
ushort et_protlen; /* Protocol or length */
|
||
|
uchar et_dsap; /* 802 DSAP */
|
||
|
uchar et_ssap; /* 802 SSAP */
|
||
|
uchar et_ctl; /* 802 control */
|
||
|
uchar et_snap1; /* SNAP */
|
||
|
uchar et_snap2;
|
||
|
uchar et_snap3;
|
||
|
ushort et_prot; /* 802 protocol */
|
||
|
} Ethernet_t;
|
||
|
|
||
|
#define ETHER_HDR_SIZE 14 /* Ethernet header size */
|
||
|
#define E802_HDR_SIZE 22 /* 802 ethernet header size */
|
||
|
|
||
|
typedef ulong IPaddr_t;
|
||
|
|
||
|
/*
|
||
|
* Internet Protocol (IP) header.
|
||
|
*/
|
||
|
typedef struct {
|
||
|
uchar ip_hl_v; /* header length and version */
|
||
|
uchar ip_tos; /* type of service */
|
||
|
ushort ip_len; /* total length */
|
||
|
ushort ip_id; /* identification */
|
||
|
ushort ip_off; /* fragment offset field */
|
||
|
uchar ip_ttl; /* time to live */
|
||
|
uchar ip_p; /* protocol */
|
||
|
ushort ip_sum; /* checksum */
|
||
|
IPaddr_t ip_src; /* Source IP address */
|
||
|
IPaddr_t ip_dst; /* Destination IP address */
|
||
|
ushort udp_src; /* UDP source port */
|
||
|
ushort udp_dst; /* UDP destination port */
|
||
|
ushort udp_len; /* Length of UDP packet */
|
||
|
ushort udp_xsum; /* Checksum */
|
||
|
} IP_t;
|
||
|
|
||
|
#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8)
|
||
|
#define IP_HDR_SIZE (sizeof (IP_t))
|
||
|
|
||
|
#else
|
||
|
#define DEBUG(fmt, args...) printf(fmt, ##args)
|
||
|
#endif
|
||
|
|
||
|
#define FLAG_BUFFALO_WOL_UCAST (0 << 0)
|
||
|
#define FLAG_BUFFALO_WOL_BCAST (1 << 0)
|
||
|
#define FLAG_BUFFALO_WITH_UDP_H (0 << 1)
|
||
|
#define FLAG_BUFFALO_WITHOUT_UDP_H (1 << 1)
|
||
|
#define FLAG_BUFFALO_DISACTIVE_PACKET (0 << 2)
|
||
|
#define FLAG_BUFFALO_ACTIVE_PACKET (1 << 2)
|
||
|
|
||
|
struct bfWolSupportPhyList_st {
|
||
|
MV_U32 OUI;
|
||
|
MV_U16 ModelNumber;
|
||
|
};
|
||
|
|
||
|
struct bfWolInfo_st{
|
||
|
char name[32];
|
||
|
MV_U8 packet_type;
|
||
|
MV_U16 port_num;
|
||
|
};
|
||
|
|
||
|
static const struct bfWolSupportPhyList_st bfWolSupportPhyList[] = {
|
||
|
{0x005043, 0x29}, /* Marvell, 1318 */
|
||
|
};
|
||
|
|
||
|
static const struct bfWolInfo_st bfWolPacketType[] = {
|
||
|
{"active", (FLAG_BUFFALO_ACTIVE_PACKET | FLAG_BUFFALO_WOL_BCAST), 0x0009}, /* broadcast active packet */
|
||
|
{"active", (FLAG_BUFFALO_ACTIVE_PACKET), 0x0009}, /* unicast active packet */
|
||
|
{"wol", (FLAG_BUFFALO_ACTIVE_PACKET | FLAG_BUFFALO_WOL_BCAST), 0x0900}, /* broadcast wol packet */
|
||
|
{"wol", (FLAG_BUFFALO_ACTIVE_PACKET), 0x0900}, /* unicast wol packet */
|
||
|
{"wol", (FLAG_BUFFALO_ACTIVE_PACKET | FLAG_BUFFALO_WITHOUT_UDP_H), 0}, /* unicast udp header less wol packet */
|
||
|
{"wol", (FLAG_BUFFALO_ACTIVE_PACKET | FLAG_BUFFALO_WOL_BCAST | FLAG_BUFFALO_WITHOUT_UDP_H), 0}, /* broadcast udp header less wol packet */
|
||
|
};
|
||
|
|
||
|
#define MAX_WOL_PHY_LIST ((sizeof(bfWolSupportPhyList)) / (sizeof(bfWolSupportPhyList[0])))
|
||
|
#define MAX_WOL_TYPE ((sizeof(bfWolPacketType)) / (sizeof(bfWolPacketType[0])))
|
||
|
|
||
|
/* used for return buffer of bfGetWolPatternString */
|
||
|
static char bfWolPatternString[128];
|
||
|
|
||
|
#if defined(__KERNEL__) && !defined(MV_UBOOT)
|
||
|
/*******************************************************************************
|
||
|
* mvEthPhyDisableAN - Disable Phy Auto-Negotiation and set forced Speed and Duplex
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* This function disable AN and set duplex and speed.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* phyAddr - Phy address.
|
||
|
* speed - port speed. 0 - 10 Mbps, 1-100 Mbps, 2 - 1000 Mbps
|
||
|
* duplex - port duplex. 0 - Half duplex, 1 - Full duplex
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN: MV_OK - Success
|
||
|
* MV_FAIL - Failure
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvEthPhyDisableAN(MV_U32 phyAddr, int speed, int duplex)
|
||
|
{
|
||
|
MV_U16 phyRegData;
|
||
|
|
||
|
if(mvEthPhyRegRead (phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
|
||
|
return MV_FAIL;
|
||
|
|
||
|
switch(speed)
|
||
|
{
|
||
|
case 0: /* 10 Mbps */
|
||
|
phyRegData &= ~ETH_PHY_CTRL_SPEED_LSB_MASK;
|
||
|
phyRegData &= ~ETH_PHY_CTRL_SPEED_MSB_MASK;
|
||
|
break;
|
||
|
|
||
|
case 1: /* 100 Mbps */
|
||
|
phyRegData |= ETH_PHY_CTRL_SPEED_LSB_MASK;
|
||
|
phyRegData &= ~ETH_PHY_CTRL_SPEED_MSB_MASK;
|
||
|
break;
|
||
|
|
||
|
case 2: /* 1000 Mbps */
|
||
|
phyRegData &= ~ETH_PHY_CTRL_SPEED_LSB_MASK;
|
||
|
phyRegData |= ETH_PHY_CTRL_SPEED_MSB_MASK;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
mvOsOutput("Unexpected speed = %d\n", speed);
|
||
|
return MV_FAIL;
|
||
|
}
|
||
|
|
||
|
switch(duplex)
|
||
|
{
|
||
|
case 0: /* half duplex */
|
||
|
phyRegData &= ~ETH_PHY_CTRL_DUPLEX_MASK;
|
||
|
break;
|
||
|
|
||
|
case 1: /* full duplex */
|
||
|
phyRegData |= ETH_PHY_CTRL_DUPLEX_MASK;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
mvOsOutput("Unexpected duplex = %d\n", duplex);
|
||
|
}
|
||
|
/* Clear bit 12 to Disable autonegotiation of the PHY */
|
||
|
phyRegData &= ~ETH_PHY_CTRL_AN_ENABLE_MASK;
|
||
|
|
||
|
/* Clear bit 9 to DISABLE, Restart autonegotiation of the PHY */
|
||
|
phyRegData &= ~ETH_PHY_CTRL_AN_RESTART_MASK;
|
||
|
mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfIsSupportWol
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Check specified ethPortNum support WOL or not.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : port No. to check.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* MV_TRUE : Specified eth port suports WOL function.
|
||
|
* MV_FALSE : Specified eth port doesn't support WOL function.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_BOOL
|
||
|
bfIsSupportWol(MV_U32 ethPortNum)
|
||
|
{
|
||
|
MV_U8 i = 0;
|
||
|
MV_U16 old_page;
|
||
|
MV_U16 reg;
|
||
|
MV_U32 OUI = 0;
|
||
|
MV_U16 ModelNumber = 0;
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page);
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 0);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 2, ®);
|
||
|
OUI |= (MV_U32)(reg << 6);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 3, ®);
|
||
|
OUI |= ((reg & 0xFC00) >> 10);
|
||
|
ModelNumber = ((reg & 0x03F0) >> 4);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page);
|
||
|
|
||
|
for(i = 0; i < MAX_WOL_PHY_LIST; i++)
|
||
|
{
|
||
|
if(bfWolSupportPhyList[i].OUI == OUI && bfWolSupportPhyList[i].ModelNumber == ModelNumber)
|
||
|
return MV_TRUE;
|
||
|
}
|
||
|
return MV_FALSE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfResetEthPhy
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Do reset eth phy.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : port No. to to reset.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
bfResetEthPhy(MV_U32 ethPortNum)
|
||
|
{
|
||
|
DEBUG("Resetting EthPhy\n");
|
||
|
mvEthPhyReset(mvBoardPhyAddrGet(ethPortNum), 1000);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfControlWolInterrupt
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Control WOL interrupt status (to Enable / Disable).
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : port No. to control interrupt status.
|
||
|
* ope : specify operation mode to do.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
bfControlWolInterrupt(MV_U32 ethPortNum, MV_U8 ope)
|
||
|
{
|
||
|
MV_U16 reg;
|
||
|
MV_U16 old_page;
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page); /* backup present page information */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,3); /* change to Page 3 */
|
||
|
|
||
|
if(ope == FLAG_BUFFALO_WOL_INTERRUPT_ENABLE)
|
||
|
{
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),16, ®);
|
||
|
reg &= ~0x0fff;
|
||
|
reg |= 0x08AA;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16, reg); /* change led[0][1] off (force Hi-Z)*/
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),18, ®);
|
||
|
reg |= 0x0880;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),18, reg); /* change led[2] to intn pin */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),16, ®);
|
||
|
reg &= ~0x0fff;
|
||
|
reg |= 0x0911;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, reg);
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),18, ®);
|
||
|
reg &= ~0x0880;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 18, reg);
|
||
|
}
|
||
|
|
||
|
/* change to Page 0*/
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0x0);
|
||
|
/*WOL Interrupt Enable*/
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),18, ®);
|
||
|
if(ope == FLAG_BUFFALO_WOL_INTERRUPT_ENABLE)
|
||
|
reg |= 0x80 ;
|
||
|
else
|
||
|
reg &= ~(0x80);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),18,reg);
|
||
|
|
||
|
if(ope == FLAG_BUFFALO_WOL_INTERRUPT_ENABLE)
|
||
|
mvEthPhyDisableAN(mvBoardPhyAddrGet(ethPortNum), 0, 0);
|
||
|
else
|
||
|
mvEthPhyRestartAN(mvBoardPhyAddrGet(ethPortNum), 1000);
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page); /* restore previous page */
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfSetPowerSaveMode
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Do settings to reduce power consumption during WOL mode.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : port No. to set to WOL mode.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
bfSetPowerSaveMode(MV_U32 ethPortNum)
|
||
|
{
|
||
|
MV_U16 reg;
|
||
|
|
||
|
/*RGMII BUS treansistor OFF*/
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,0x2); /* change to Page 2 */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum),24, ®);
|
||
|
reg &= ~(BIT8 | BIT9 | BIT10 | BIT2 | BIT1 | BIT0);
|
||
|
reg |= BIT6 ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),24,reg);
|
||
|
|
||
|
/*STOP CLK125 OUTPUT */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 16, ®);
|
||
|
reg |= ( BIT2 | BIT1 | BIT11| BIT12);
|
||
|
reg &= ~BIT3 ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, reg);
|
||
|
/* change to Page 0*/
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 0);
|
||
|
|
||
|
#if defined(energy_detect)
|
||
|
/*RGMII STOP for Power Saving */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 16, ®);
|
||
|
reg |= (BIT2 | BIT8 | BIT9) ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, reg);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfSetWolMagicWaitMode
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set specified ethernet port to Wake on Lan waiting mode.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : port No. to set to WOL mode.
|
||
|
* phyAddr : Phy address.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_BOOL
|
||
|
bfSetWolMagicWaitMode(MV_U32 ethPortNum)
|
||
|
{
|
||
|
MV_U16 reg ;
|
||
|
unsigned char MacAddr[6];
|
||
|
|
||
|
if(bfIsSupportWol(ethPortNum) == MV_FALSE)
|
||
|
return MV_FALSE;
|
||
|
|
||
|
memset(MacAddr, 0, sizeof(MacAddr));
|
||
|
mvEthMacAddrGet(ethPortNum, MacAddr);
|
||
|
|
||
|
/* Set WOL mode */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,17); /* change to Page 17 */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,0x5500); /* 0101 0101 0000 0000 */
|
||
|
|
||
|
/* set wol mac address from env data */
|
||
|
reg = (MacAddr[4]) | (MacAddr[5] << 8) ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),23,reg);
|
||
|
reg = (MacAddr[2]) | (MacAddr[3] << 8) ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),24,reg);
|
||
|
reg = (MacAddr[0]) | (MacAddr[1] << 8) ;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),25,reg);
|
||
|
|
||
|
/*Enable Magic Packet*/
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),16,0x5500);
|
||
|
|
||
|
bfControlWolInterrupt(ethPortNum, FLAG_BUFFALO_WOL_INTERRUPT_ENABLE);
|
||
|
bfSetPowerSaveMode(ethPortNum);
|
||
|
return MV_TRUE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfSetFrameEventWol
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* generate frame pattern used to matching.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* frame : buffer to store generated frame pattern.
|
||
|
* mask : buffer to stora generated mask pattern.
|
||
|
* pmacAddr : MAC address to generate frame pattern.
|
||
|
* bfWPT : flags to generate frame pattern.
|
||
|
* debug : debug flag.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
static MV_U8
|
||
|
bfSetFrameEventWol(MV_U8 *frame, MV_U8 *mask, MV_U8 *pMacAddr, const struct bfWolInfo_st *bfWPT, int debug)
|
||
|
{
|
||
|
MV_U8 i;
|
||
|
MV_U8 magic_len = 0;
|
||
|
MV_U8 frame_match_len = 0;
|
||
|
|
||
|
Ethernet_t *eth_h = (Ethernet_t *)&frame[0];
|
||
|
Ethernet_t *eth_h_mask = (Ethernet_t *)&mask[0];
|
||
|
|
||
|
IP_t *ip_h = (IP_t *)&frame[ETHER_HDR_SIZE];
|
||
|
IP_t *ip_h_mask = (IP_t *)&mask[ETHER_HDR_SIZE];
|
||
|
|
||
|
MV_U8 *data = NULL;
|
||
|
MV_U8 *data_mask = NULL;
|
||
|
|
||
|
for(i = 0; i < 6; i++)
|
||
|
{
|
||
|
if(bfWPT->packet_type & FLAG_BUFFALO_WOL_BCAST)
|
||
|
eth_h->et_dest[i] = 0xFF;
|
||
|
else
|
||
|
eth_h->et_dest[i] = pMacAddr[i];
|
||
|
memset(&(eth_h_mask->et_dest[i]), 0xFF, sizeof(eth_h_mask->et_dest[i]));
|
||
|
}
|
||
|
|
||
|
if(bfWPT->packet_type & FLAG_BUFFALO_WITHOUT_UDP_H)
|
||
|
{
|
||
|
data = &frame[ETHER_HDR_SIZE];
|
||
|
data_mask = &mask[ETHER_HDR_SIZE];
|
||
|
magic_len = 128 - ETHER_HDR_SIZE;
|
||
|
frame_match_len = ETHER_HDR_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
data = &frame[ETHER_HDR_SIZE + IP_HDR_SIZE];
|
||
|
data_mask = &mask[ETHER_HDR_SIZE + IP_HDR_SIZE];
|
||
|
ip_h->udp_dst = htons(bfWPT->port_num);
|
||
|
memset(&(ip_h_mask->udp_dst), 0xFF, sizeof(ip_h_mask->udp_dst));
|
||
|
magic_len = 128 - ETHER_HDR_SIZE - IP_HDR_SIZE;
|
||
|
frame_match_len = ETHER_HDR_SIZE + IP_HDR_SIZE;
|
||
|
}
|
||
|
if(magic_len > 6 * 17) magic_len = 6*17;
|
||
|
frame_match_len += magic_len - 1;
|
||
|
|
||
|
if(debug) DEBUG("matching len = %d\n", magic_len);
|
||
|
for(i = 0; i < magic_len ; i ++)
|
||
|
{
|
||
|
if((i < 6) && (bfWPT->packet_type & FLAG_BUFFALO_ACTIVE_PACKET))
|
||
|
data[i] = 0xFF;
|
||
|
else
|
||
|
data[i] = pMacAddr[i % 6];
|
||
|
memset(&(data_mask[i]), -1, sizeof(data_mask[i]));
|
||
|
}
|
||
|
|
||
|
return frame_match_len;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfDumpSramData
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set matching frame pattern and mask information to SRAM of EthPhy.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : No. of target ethernet port.
|
||
|
* num_frame_pattern: No. of frame pattern to display dump result.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* SRAM dump result.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
bfDumpSramData(MV_U32 ethPortNum, MV_U8 num_frame_pattern)
|
||
|
{
|
||
|
MV_U8 i;
|
||
|
MV_U16 old_page;
|
||
|
MV_U16 reg;
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page); /* backup present page status */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum),22,17); /* change to Page 17 */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 16, ®);
|
||
|
|
||
|
DEBUG("verifying SRAM value. pattern=%d\n", num_frame_pattern);
|
||
|
if(reg & (1 << num_frame_pattern))
|
||
|
DEBUG("patern %d is Enabled\n", num_frame_pattern);
|
||
|
else
|
||
|
DEBUG("patern %d is Disabled\n", num_frame_pattern);
|
||
|
|
||
|
switch(num_frame_pattern)
|
||
|
{
|
||
|
case 0:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 21, ®);
|
||
|
break;
|
||
|
case 1:
|
||
|
case 2:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 20, ®);
|
||
|
break;
|
||
|
case 3:
|
||
|
case 4:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 19, ®);
|
||
|
break;
|
||
|
case 5:
|
||
|
case 6:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 18, ®);
|
||
|
break;
|
||
|
default:
|
||
|
return ;
|
||
|
}
|
||
|
if(num_frame_pattern == 0 || num_frame_pattern == 1 || num_frame_pattern == 3 || num_frame_pattern == 5)
|
||
|
DEBUG("Matching frame pattern length = %d Bytes\n", (reg & 0x007F) + 1);
|
||
|
else if(num_frame_pattern == 2 || num_frame_pattern == 4 || num_frame_pattern == 6)
|
||
|
DEBUG("Matching frame pattern length = %d Bytes\n", (((reg >> 7) & 0x007F) + 1));
|
||
|
|
||
|
for(i = 0; i < 128; i++)
|
||
|
{
|
||
|
if((i!= 0) && ((i % 0x10) == 0))
|
||
|
DEBUG("\n0x%02x : ", (i / 0x10) * 0x10);
|
||
|
else if (((i % 0x10) != 0) && ((i % 0x08) ==0))
|
||
|
DEBUG(" ");
|
||
|
else if(i == 0)
|
||
|
DEBUG("\n0x%02x : ", 0);
|
||
|
|
||
|
/* read data from SRAM */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 26, 0x0800 | i | (num_frame_pattern << 7)); /* 0000 0100 0000 0000 | i */
|
||
|
|
||
|
/* read value recorded in SRAM */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 28, ®);
|
||
|
if(reg & 0x0100)
|
||
|
{
|
||
|
DEBUG("%02x ", reg & 0xFF);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DEBUG("-- ");
|
||
|
}
|
||
|
}
|
||
|
DEBUG("\n");
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page); /* restore previous page status */
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfWriteFramePaternToSram
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set matching frame pattern and mask information to SRAM of EthPhy.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : No. of target ethernet port.
|
||
|
* frame : 128 byte frame pattern
|
||
|
* mask : 128 byte mask information. which frame byte is used to matching.
|
||
|
* num_frame_pattern: No. of frame pattern to set frame pattern.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
static void
|
||
|
bfWriteFramePaternToSram(MV_U32 ethPortNum, MV_U8 *frame, MV_U8 *mask, MV_U8 num_frame_pattern)
|
||
|
{
|
||
|
MV_U16 i;
|
||
|
MV_U16 reg;
|
||
|
MV_U16 old_page;
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 17);
|
||
|
|
||
|
for(i = 0; i < 128; i++)
|
||
|
{
|
||
|
/* set value to 17.27 */
|
||
|
reg = ((mask[i] > 0)? 1:0) << 8 | frame[i];
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 27, reg);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 26, 0x0400 | i | (num_frame_pattern << 7)); /* 0000 0100 0000 0000 | i */
|
||
|
}
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfWriteWolFrameMatchingLen
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set wol frame matching length to 17.18, 17.19, 17.20 or 17.21
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : No. of target ethernet port.
|
||
|
* num_frame_patern : No. of frame patern to set matching length.
|
||
|
* matching_len : matching length to set.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* None.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
void
|
||
|
bfWriteWolFrameMatchingLen(MV_U32 ethPortNum, MV_U8 num_frame_pattern, MV_U8 matching_len)
|
||
|
{
|
||
|
MV_U16 reg;
|
||
|
MV_U16 old_page;
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 17);
|
||
|
|
||
|
switch(num_frame_pattern)
|
||
|
{
|
||
|
case 0:
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 21, matching_len);
|
||
|
break;
|
||
|
case 1:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 20, ®);
|
||
|
reg &= ~(0x007F);
|
||
|
reg |= matching_len;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 20, reg);
|
||
|
break;
|
||
|
case 2:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 20, ®);
|
||
|
reg &= ~(0x3F80);
|
||
|
reg |= (matching_len << 7);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 20, reg);
|
||
|
break;
|
||
|
case 3:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 19, ®);
|
||
|
reg &= ~(0x007F);
|
||
|
reg |= matching_len;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 19, reg);
|
||
|
break;
|
||
|
case 4:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 19, ®);
|
||
|
reg &= ~(0x3F80);
|
||
|
reg |= (matching_len << 7);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 19, reg);
|
||
|
break;
|
||
|
case 5:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 18, ®);
|
||
|
reg &= ~(0x007F);
|
||
|
reg |= matching_len;
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 18, reg);
|
||
|
break;
|
||
|
case 6:
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 18, ®);
|
||
|
reg &= ~(0x3F80);
|
||
|
reg |= (matching_len << 7);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 18, reg);
|
||
|
break;
|
||
|
}
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfSetWolFrameWaitMode
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set wol frame wait mode.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : No. of target ethernet port.
|
||
|
* pMacAddr : MAC address to set.
|
||
|
* debug : debug flag(for verbose output)
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* MV_TRUE : success to set wol mode.
|
||
|
* MV_FALSE : failed to set wol mode.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_BOOL
|
||
|
bfSetWolFrameWaitMode(MV_U32 ethPortNum, int debug)
|
||
|
{
|
||
|
MV_U16 old_page;
|
||
|
MV_U16 reg;
|
||
|
MV_U16 enabling_pattern = 0;
|
||
|
MV_U8 i;
|
||
|
MV_U8 frame[128];
|
||
|
MV_U8 mask[128];
|
||
|
MV_U8 matching_len = 128;
|
||
|
unsigned char MacAddr[6];
|
||
|
|
||
|
if(bfIsSupportWol(ethPortNum) == MV_FALSE)
|
||
|
return MV_FALSE;
|
||
|
|
||
|
#if defined(__KERNEL__) && !defined(MV_UBOOT)
|
||
|
DEBUG("Setting WOL ... ");
|
||
|
if(!bfGppInRegBitTest(BIT_PWRAUTO_SW))
|
||
|
{
|
||
|
DEBUG("Switch status is not AUTO\n");
|
||
|
return MV_FALSE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
memset(MacAddr, 0, sizeof(MacAddr));
|
||
|
mvEthMacAddrGet(ethPortNum, MacAddr);
|
||
|
|
||
|
bfControlWolInterrupt(ethPortNum, FLAG_BUFFALO_WOL_INTERRUPT_DISABLE);
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page); /* backup present page status */
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 17); /* change to Page 17 */
|
||
|
/* Disabling WOL Match Enable flags */
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 16, ®);
|
||
|
reg &= ~(0xC07F);
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, reg);
|
||
|
|
||
|
for(i = 0; i < MAX_WOL_TYPE; i++)
|
||
|
{
|
||
|
memset(frame, 0, sizeof(frame));
|
||
|
memset(mask, 0, sizeof(mask));
|
||
|
matching_len = bfSetFrameEventWol(frame, mask, MacAddr, &(bfWolPacketType[i]), debug);
|
||
|
bfWriteFramePaternToSram(ethPortNum, frame, mask, i);
|
||
|
bfWriteWolFrameMatchingLen(ethPortNum, i, matching_len);
|
||
|
enabling_pattern |= (1 << i);
|
||
|
}
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, enabling_pattern); /* 1001 0000 0000 0011 */
|
||
|
|
||
|
if(debug)
|
||
|
for (i = 0; i < 7; i++)
|
||
|
bfDumpSramData(ethPortNum, i);
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 16, 0x9000 | enabling_pattern); /* 1001 0000 0000 0011 */
|
||
|
|
||
|
bfControlWolInterrupt(ethPortNum, FLAG_BUFFALO_WOL_INTERRUPT_ENABLE);
|
||
|
bfSetPowerSaveMode(ethPortNum);
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page); /* restore previous page status */
|
||
|
#if defined(__KERNEL__) && !defined(MV_UBOOT)
|
||
|
DEBUG("Success\n");
|
||
|
#endif
|
||
|
return MV_TRUE;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfGetWolPatternString
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* generate string to send kernel from the information of which frame pattern matched.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* wol_stat : register value of 17.17
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* pointer to string.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
char *bfGetWolPatternString(MV_U16 wol_stat)
|
||
|
{
|
||
|
MV_U8 i;
|
||
|
|
||
|
memset(bfWolPatternString, 0, sizeof(bfWolPatternString));
|
||
|
for(i = 0; i < MAX_WOL_TYPE; i++)
|
||
|
{
|
||
|
if(wol_stat & (1 << i) && (strstr(bfWolPatternString, bfWolPacketType[i].name) == 0)) {
|
||
|
if(strlen(bfWolPatternString) == 0)
|
||
|
sprintf(bfWolPatternString, "%s", bfWolPacketType[i].name);
|
||
|
else
|
||
|
sprintf(bfWolPatternString, ",%s", bfWolPacketType[i].name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (bfWolPatternString[0])? bfWolPatternString : NULL;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* bfGetWolInterruptStatus
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Get interrupt status
|
||
|
*
|
||
|
* INPUT:
|
||
|
* ethPortNum : No. of target ethernet port.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* register value of 17.17(which frame pattern received)
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_U16 bfGetWolInterruptStatus(MV_U32 ethPortNum, int debug)
|
||
|
{
|
||
|
MV_U16 old_page;
|
||
|
MV_U16 reg;
|
||
|
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 22, &old_page); /* backup present page status */
|
||
|
|
||
|
if(debug)
|
||
|
{
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 17);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 17, ®);
|
||
|
DEBUG("WOL status(17.17)=0x%04x\n", reg);
|
||
|
}
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 0);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 19, ®);
|
||
|
if(debug)
|
||
|
{
|
||
|
DEBUG("WOL status(0.19)=0x%04x\n", reg);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 23, ®);
|
||
|
DEBUG("Global Interrupt Status(0.23)=0x%04x\n", reg);
|
||
|
}
|
||
|
|
||
|
if(reg & 0x0080)
|
||
|
{
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, 17);
|
||
|
mvEthPhyRegRead(mvBoardPhyAddrGet(ethPortNum), 17, ®);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
reg = 0;
|
||
|
}
|
||
|
|
||
|
mvEthPhyRegWrite(mvBoardPhyAddrGet(ethPortNum), 22, old_page); /* restore previous page status */
|
||
|
|
||
|
return (reg & 0x003F);
|
||
|
}
|
||
|
|
||
|
|