Merge branch 'upstream-fixes'
This commit is contained in:
commit
e9022ee6c3
7 changed files with 55 additions and 1028 deletions
|
@ -28,8 +28,8 @@
|
||||||
|
|
||||||
#define DRV_MODULE_NAME "b44"
|
#define DRV_MODULE_NAME "b44"
|
||||||
#define PFX DRV_MODULE_NAME ": "
|
#define PFX DRV_MODULE_NAME ": "
|
||||||
#define DRV_MODULE_VERSION "0.96"
|
#define DRV_MODULE_VERSION "0.97"
|
||||||
#define DRV_MODULE_RELDATE "Nov 8, 2005"
|
#define DRV_MODULE_RELDATE "Nov 30, 2005"
|
||||||
|
|
||||||
#define B44_DEF_MSG_ENABLE \
|
#define B44_DEF_MSG_ENABLE \
|
||||||
(NETIF_MSG_DRV | \
|
(NETIF_MSG_DRV | \
|
||||||
|
@ -1417,6 +1417,7 @@ static int b44_open(struct net_device *dev)
|
||||||
add_timer(&bp->timer);
|
add_timer(&bp->timer);
|
||||||
|
|
||||||
b44_enable_ints(bp);
|
b44_enable_ints(bp);
|
||||||
|
netif_start_queue(dev);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1837,12 +1838,15 @@ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||||
{
|
{
|
||||||
struct mii_ioctl_data *data = if_mii(ifr);
|
struct mii_ioctl_data *data = if_mii(ifr);
|
||||||
struct b44 *bp = netdev_priv(dev);
|
struct b44 *bp = netdev_priv(dev);
|
||||||
int err;
|
int err = -EINVAL;
|
||||||
|
|
||||||
|
if (!netif_running(dev))
|
||||||
|
goto out;
|
||||||
|
|
||||||
spin_lock_irq(&bp->lock);
|
spin_lock_irq(&bp->lock);
|
||||||
err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
|
err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
|
||||||
spin_unlock_irq(&bp->lock);
|
spin_unlock_irq(&bp->lock);
|
||||||
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2113,6 +2117,7 @@ static int b44_resume(struct pci_dev *pdev)
|
||||||
add_timer(&bp->timer);
|
add_timer(&bp->timer);
|
||||||
|
|
||||||
b44_enable_ints(bp);
|
b44_enable_ints(bp);
|
||||||
|
netif_wake_queue(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2621,19 +2621,7 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
|
||||||
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
|
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(htons(ETH_P_IP) == skb->protocol) {
|
if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
|
||||||
const struct iphdr *ip = skb->nh.iph;
|
|
||||||
if(IPPROTO_UDP == ip->protocol) {
|
|
||||||
struct udphdr *udp = (struct udphdr *)(skb->h.uh);
|
|
||||||
if(ntohs(udp->dest) == 67) {
|
|
||||||
offset = (uint8_t *)udp + 8 - skb->data;
|
|
||||||
length = skb->len - offset;
|
|
||||||
|
|
||||||
return e1000_mng_write_dhcp_info(hw,
|
|
||||||
(uint8_t *)udp + 8, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
|
|
||||||
struct ethhdr *eth = (struct ethhdr *) skb->data;
|
struct ethhdr *eth = (struct ethhdr *) skb->data;
|
||||||
if((htons(ETH_P_IP) == eth->h_proto)) {
|
if((htons(ETH_P_IP) == eth->h_proto)) {
|
||||||
const struct iphdr *ip =
|
const struct iphdr *ip =
|
||||||
|
|
|
@ -27,8 +27,7 @@ sk98lin-objs := \
|
||||||
sktimer.o \
|
sktimer.o \
|
||||||
skvpd.o \
|
skvpd.o \
|
||||||
skxmac2.o \
|
skxmac2.o \
|
||||||
skproc.o \
|
skproc.o
|
||||||
skcsum.o
|
|
||||||
|
|
||||||
# DBGDEF = \
|
# DBGDEF = \
|
||||||
# -DDEBUG
|
# -DDEBUG
|
||||||
|
@ -77,7 +76,7 @@ endif
|
||||||
# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
|
# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
|
||||||
# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
|
# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
|
||||||
|
|
||||||
EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DSK_USE_CSUM -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
|
EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f core *.o *.a *.s
|
rm -f core *.o *.a *.s
|
||||||
|
|
|
@ -424,10 +424,6 @@ struct s_AC {
|
||||||
TX_PORT TxPort[SK_MAX_MACS][2];
|
TX_PORT TxPort[SK_MAX_MACS][2];
|
||||||
RX_PORT RxPort[SK_MAX_MACS];
|
RX_PORT RxPort[SK_MAX_MACS];
|
||||||
|
|
||||||
unsigned int CsOfs1; /* for checksum calculation */
|
|
||||||
unsigned int CsOfs2; /* for checksum calculation */
|
|
||||||
SK_U32 CsOfs; /* for checksum calculation */
|
|
||||||
|
|
||||||
SK_BOOL CheckQueue; /* check event queue soon */
|
SK_BOOL CheckQueue; /* check event queue soon */
|
||||||
SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
|
SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
|
||||||
DIM_INFO DynIrqModInfo; /* all data related to DIM */
|
DIM_INFO DynIrqModInfo; /* all data related to DIM */
|
||||||
|
|
|
@ -1,871 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* Name: skcsum.c
|
|
||||||
* Project: GEnesis, PCI Gigabit Ethernet Adapter
|
|
||||||
* Version: $Revision: 1.12 $
|
|
||||||
* Date: $Date: 2003/08/20 13:55:53 $
|
|
||||||
* Purpose: Store/verify Internet checksum in send/receive packets.
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* (C)Copyright 1998-2003 SysKonnect GmbH.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* The information in this file is provided "AS IS" without warranty.
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifdef SK_USE_CSUM /* Check if CSUM is to be used. */
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
static const char SysKonnectFileId[] =
|
|
||||||
"@(#) $Id: skcsum.c,v 1.12 2003/08/20 13:55:53 mschmid Exp $ (C) SysKonnect.";
|
|
||||||
#endif /* !lint */
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
*
|
|
||||||
* This is the "GEnesis" common module "CSUM".
|
|
||||||
*
|
|
||||||
* This module contains the code necessary to calculate, store, and verify the
|
|
||||||
* Internet Checksum of IP, TCP, and UDP frames.
|
|
||||||
*
|
|
||||||
* "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
|
|
||||||
* and is the code name of this SysKonnect project.
|
|
||||||
*
|
|
||||||
* Compilation Options:
|
|
||||||
*
|
|
||||||
* SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
|
|
||||||
* empty module.
|
|
||||||
*
|
|
||||||
* SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
|
|
||||||
* definitions. In this case, all SKCS_PROTO_xxx definitions must be made
|
|
||||||
* external.
|
|
||||||
*
|
|
||||||
* SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
|
|
||||||
* definitions. In this case, all SKCS_STATUS_xxx definitions must be made
|
|
||||||
* external.
|
|
||||||
*
|
|
||||||
* Include File Hierarchy:
|
|
||||||
*
|
|
||||||
* "h/skdrv1st.h"
|
|
||||||
* "h/skcsum.h"
|
|
||||||
* "h/sktypes.h"
|
|
||||||
* "h/skqueue.h"
|
|
||||||
* "h/skdrv2nd.h"
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "h/skdrv1st.h"
|
|
||||||
#include "h/skcsum.h"
|
|
||||||
#include "h/skdrv2nd.h"
|
|
||||||
|
|
||||||
/* defines ********************************************************************/
|
|
||||||
|
|
||||||
/* The size of an Ethernet MAC header. */
|
|
||||||
#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2)
|
|
||||||
|
|
||||||
/* The size of the used topology's MAC header. */
|
|
||||||
#define SKCS_MAC_HEADER_SIZE SKCS_ETHERNET_MAC_HEADER_SIZE
|
|
||||||
|
|
||||||
/* The size of the IP header without any option fields. */
|
|
||||||
#define SKCS_IP_HEADER_SIZE 20
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Field offsets within the IP header.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* "Internet Header Version" and "Length". */
|
|
||||||
#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH 0
|
|
||||||
|
|
||||||
/* "Total Length". */
|
|
||||||
#define SKCS_OFS_IP_TOTAL_LENGTH 2
|
|
||||||
|
|
||||||
/* "Flags" "Fragment Offset". */
|
|
||||||
#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET 6
|
|
||||||
|
|
||||||
/* "Next Level Protocol" identifier. */
|
|
||||||
#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9
|
|
||||||
|
|
||||||
/* Source IP address. */
|
|
||||||
#define SKCS_OFS_IP_SOURCE_ADDRESS 12
|
|
||||||
|
|
||||||
/* Destination IP address. */
|
|
||||||
#define SKCS_OFS_IP_DESTINATION_ADDRESS 16
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Field offsets within the UDP header.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* UDP checksum. */
|
|
||||||
#define SKCS_OFS_UDP_CHECKSUM 6
|
|
||||||
|
|
||||||
/* IP "Next Level Protocol" identifiers (see RFC 790). */
|
|
||||||
#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */
|
|
||||||
#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */
|
|
||||||
|
|
||||||
/* IP "Don't Fragment" bit. */
|
|
||||||
#define SKCS_IP_DONT_FRAGMENT SKCS_HTON16(0x4000)
|
|
||||||
|
|
||||||
/* Add a byte offset to a pointer. */
|
|
||||||
#define SKCS_IDX(pPtr, Ofs) ((void *) ((char *) (pPtr) + (Ofs)))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macros that convert host to network representation and vice versa, i.e.
|
|
||||||
* little/big endian conversion on little endian machines only.
|
|
||||||
*/
|
|
||||||
#ifdef SK_LITTLE_ENDIAN
|
|
||||||
#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xff) << 8))
|
|
||||||
#endif /* SK_LITTLE_ENDIAN */
|
|
||||||
#ifdef SK_BIG_ENDIAN
|
|
||||||
#define SKCS_HTON16(Val16) (Val16)
|
|
||||||
#endif /* SK_BIG_ENDIAN */
|
|
||||||
#define SKCS_NTOH16(Val16) SKCS_HTON16(Val16)
|
|
||||||
|
|
||||||
/* typedefs *******************************************************************/
|
|
||||||
|
|
||||||
/* function prototypes ********************************************************/
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* SkCsGetSendInfo - get checksum information for a send packet
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Get all checksum information necessary to send a TCP or UDP packet. The
|
|
||||||
* function checks the IP header passed to it. If the high-level protocol
|
|
||||||
* is either TCP or UDP the pseudo header checksum is calculated and
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
* The function returns the total length of the IP header (including any
|
|
||||||
* IP option fields), which is the same as the start offset of the IP data
|
|
||||||
* which in turn is the start offset of the TCP or UDP header.
|
|
||||||
*
|
|
||||||
* The function also returns the TCP or UDP pseudo header checksum, which
|
|
||||||
* should be used as the start value for the hardware checksum calculation.
|
|
||||||
* (Note that any actual pseudo header checksum can never calculate to
|
|
||||||
* zero.)
|
|
||||||
*
|
|
||||||
* Note:
|
|
||||||
* There is a bug in the GENESIS ASIC which may lead to wrong checksums.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* pAc - A pointer to the adapter context struct.
|
|
||||||
*
|
|
||||||
* pIpHeader - Pointer to IP header. Must be at least the IP header *not*
|
|
||||||
* including any option fields, i.e. at least 20 bytes.
|
|
||||||
*
|
|
||||||
* Note: This pointer will be used to address 8-, 16-, and 32-bit
|
|
||||||
* variables with the respective alignment offsets relative to the pointer.
|
|
||||||
* Thus, the pointer should point to a 32-bit aligned address. If the
|
|
||||||
* target system cannot address 32-bit variables on non 32-bit aligned
|
|
||||||
* addresses, then the pointer *must* point to a 32-bit aligned address.
|
|
||||||
*
|
|
||||||
* pPacketInfo - A pointer to the packet information structure for this
|
|
||||||
* packet. Before calling this SkCsGetSendInfo(), the following field must
|
|
||||||
* be initialized:
|
|
||||||
*
|
|
||||||
* ProtocolFlags - Initialize with any combination of
|
|
||||||
* SKCS_PROTO_XXX bit flags. SkCsGetSendInfo() will only work on
|
|
||||||
* the protocols specified here. Any protocol(s) not specified
|
|
||||||
* here will be ignored.
|
|
||||||
*
|
|
||||||
* Note: Only one checksum can be calculated in hardware. Thus, if
|
|
||||||
* SKCS_PROTO_IP is specified in the 'ProtocolFlags',
|
|
||||||
* SkCsGetSendInfo() must calculate the IP header checksum in
|
|
||||||
* software. It might be a better idea to have the calling
|
|
||||||
* protocol stack calculate the IP header checksum.
|
|
||||||
*
|
|
||||||
* Returns: N/A
|
|
||||||
* On return, the following fields in 'pPacketInfo' may or may not have
|
|
||||||
* been filled with information, depending on the protocol(s) found in the
|
|
||||||
* packet:
|
|
||||||
*
|
|
||||||
* ProtocolFlags - Returns the SKCS_PROTO_XXX bit flags of the protocol(s)
|
|
||||||
* that were both requested by the caller and actually found in the packet.
|
|
||||||
* Protocol(s) not specified by the caller and/or not found in the packet
|
|
||||||
* will have their respective SKCS_PROTO_XXX bit flags reset.
|
|
||||||
*
|
|
||||||
* Note: For IP fragments, TCP and UDP packet information is ignored.
|
|
||||||
*
|
|
||||||
* IpHeaderLength - The total length in bytes of the complete IP header
|
|
||||||
* including any option fields is returned here. This is the start offset
|
|
||||||
* of the IP data, i.e. the TCP or UDP header if present.
|
|
||||||
*
|
|
||||||
* IpHeaderChecksum - If IP has been specified in the 'ProtocolFlags', the
|
|
||||||
* 16-bit Internet Checksum of the IP header is returned here. This value
|
|
||||||
* is to be stored into the packet's 'IP Header Checksum' field.
|
|
||||||
*
|
|
||||||
* PseudoHeaderChecksum - If this is a TCP or UDP packet and if TCP or UDP
|
|
||||||
* has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum
|
|
||||||
* of the TCP or UDP pseudo header is returned here.
|
|
||||||
*/
|
|
||||||
void SkCsGetSendInfo(
|
|
||||||
SK_AC *pAc, /* Adapter context struct. */
|
|
||||||
void *pIpHeader, /* IP header. */
|
|
||||||
SKCS_PACKET_INFO *pPacketInfo, /* Packet information struct. */
|
|
||||||
int NetNumber) /* Net number */
|
|
||||||
{
|
|
||||||
/* Internet Header Version found in IP header. */
|
|
||||||
unsigned InternetHeaderVersion;
|
|
||||||
|
|
||||||
/* Length of the IP header as found in IP header. */
|
|
||||||
unsigned IpHeaderLength;
|
|
||||||
|
|
||||||
/* Bit field specifiying the desired/found protocols. */
|
|
||||||
unsigned ProtocolFlags;
|
|
||||||
|
|
||||||
/* Next level protocol identifier found in IP header. */
|
|
||||||
unsigned NextLevelProtocol;
|
|
||||||
|
|
||||||
/* Length of IP data portion. */
|
|
||||||
unsigned IpDataLength;
|
|
||||||
|
|
||||||
/* TCP/UDP pseudo header checksum. */
|
|
||||||
unsigned long PseudoHeaderChecksum;
|
|
||||||
|
|
||||||
/* Pointer to next level protocol statistics structure. */
|
|
||||||
SKCS_PROTO_STATS *NextLevelProtoStats;
|
|
||||||
|
|
||||||
/* Temporary variable. */
|
|
||||||
unsigned Tmp;
|
|
||||||
|
|
||||||
Tmp = *(SK_U8 *)
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
|
|
||||||
|
|
||||||
/* Get the Internet Header Version (IHV). */
|
|
||||||
/* Note: The IHV is stored in the upper four bits. */
|
|
||||||
|
|
||||||
InternetHeaderVersion = Tmp >> 4;
|
|
||||||
|
|
||||||
/* Check the Internet Header Version. */
|
|
||||||
/* Note: We currently only support IP version 4. */
|
|
||||||
|
|
||||||
if (InternetHeaderVersion != 4) { /* IPv4? */
|
|
||||||
SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
|
|
||||||
("Tx: Unknown Internet Header Version %u.\n",
|
|
||||||
InternetHeaderVersion));
|
|
||||||
pPacketInfo->ProtocolFlags = 0;
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the IP header length (IHL). */
|
|
||||||
/*
|
|
||||||
* Note: The IHL is stored in the lower four bits as the number of
|
|
||||||
* 4-byte words.
|
|
||||||
*/
|
|
||||||
|
|
||||||
IpHeaderLength = (Tmp & 0xf) * 4;
|
|
||||||
pPacketInfo->IpHeaderLength = IpHeaderLength;
|
|
||||||
|
|
||||||
/* Check the IP header length. */
|
|
||||||
|
|
||||||
/* 04-Aug-1998 sw - Really check the IHL? Necessary? */
|
|
||||||
|
|
||||||
if (IpHeaderLength < 5*4) {
|
|
||||||
SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
|
|
||||||
("Tx: Invalid IP Header Length %u.\n", IpHeaderLength));
|
|
||||||
pPacketInfo->ProtocolFlags = 0;
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is an IPv4 frame with a header of valid length. */
|
|
||||||
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxOkCts++;
|
|
||||||
|
|
||||||
/* Check if we should calculate the IP header checksum. */
|
|
||||||
|
|
||||||
ProtocolFlags = pPacketInfo->ProtocolFlags;
|
|
||||||
|
|
||||||
if (ProtocolFlags & SKCS_PROTO_IP) {
|
|
||||||
pPacketInfo->IpHeaderChecksum =
|
|
||||||
SkCsCalculateChecksum(pIpHeader, IpHeaderLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the next level protocol identifier. */
|
|
||||||
|
|
||||||
NextLevelProtocol =
|
|
||||||
*(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if this is a TCP or UDP frame and if we should calculate the
|
|
||||||
* TCP/UDP pseudo header checksum.
|
|
||||||
*
|
|
||||||
* Also clear all protocol bit flags of protocols not present in the
|
|
||||||
* frame.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((ProtocolFlags & SKCS_PROTO_TCP) != 0 &&
|
|
||||||
NextLevelProtocol == SKCS_PROTO_ID_TCP) {
|
|
||||||
/* TCP/IP frame. */
|
|
||||||
ProtocolFlags &= SKCS_PROTO_TCP | SKCS_PROTO_IP;
|
|
||||||
NextLevelProtoStats =
|
|
||||||
&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
|
|
||||||
}
|
|
||||||
else if ((ProtocolFlags & SKCS_PROTO_UDP) != 0 &&
|
|
||||||
NextLevelProtocol == SKCS_PROTO_ID_UDP) {
|
|
||||||
/* UDP/IP frame. */
|
|
||||||
ProtocolFlags &= SKCS_PROTO_UDP | SKCS_PROTO_IP;
|
|
||||||
NextLevelProtoStats =
|
|
||||||
&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* Either not a TCP or UDP frame and/or TCP/UDP processing not
|
|
||||||
* specified.
|
|
||||||
*/
|
|
||||||
pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if this is an IP fragment. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: An IP fragment has a non-zero "Fragment Offset" field and/or
|
|
||||||
* the "More Fragments" bit set. Thus, if both the "Fragment Offset"
|
|
||||||
* and the "More Fragments" are zero, it is *not* a fragment. We can
|
|
||||||
* easily check both at the same time since they are in the same 16-bit
|
|
||||||
* word.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((*(SK_U16 *)
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
|
|
||||||
~SKCS_IP_DONT_FRAGMENT) != 0) {
|
|
||||||
/* IP fragment; ignore all other protocols. */
|
|
||||||
pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
|
|
||||||
NextLevelProtoStats->TxUnableCts++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the TCP/UDP pseudo header checksum.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Get total length of IP header and data. */
|
|
||||||
|
|
||||||
IpDataLength =
|
|
||||||
*(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
|
|
||||||
|
|
||||||
/* Get length of IP data portion. */
|
|
||||||
|
|
||||||
IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
|
|
||||||
|
|
||||||
/* Calculate the sum of all pseudo header fields (16-bit). */
|
|
||||||
|
|
||||||
PseudoHeaderChecksum =
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
|
|
||||||
(unsigned long) SKCS_HTON16(NextLevelProtocol) +
|
|
||||||
(unsigned long) SKCS_HTON16(IpDataLength);
|
|
||||||
|
|
||||||
/* Add-in any carries. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
|
|
||||||
|
|
||||||
/* Add-in any new carry. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
|
|
||||||
|
|
||||||
pPacketInfo->ProtocolFlags = ProtocolFlags;
|
|
||||||
NextLevelProtoStats->TxOkCts++; /* Success. */
|
|
||||||
} /* SkCsGetSendInfo */
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* SkCsGetReceiveInfo - verify checksum information for a received packet
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Verify a received frame's checksum. The function returns a status code
|
|
||||||
* reflecting the result of the verification.
|
|
||||||
*
|
|
||||||
* Note:
|
|
||||||
* Before calling this function you have to verify that the frame is
|
|
||||||
* not padded and Checksum1 and Checksum2 are bigger than 1.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* pAc - Pointer to adapter context struct.
|
|
||||||
*
|
|
||||||
* pIpHeader - Pointer to IP header. Must be at least the length in bytes
|
|
||||||
* of the received IP header including any option fields. For UDP packets,
|
|
||||||
* 8 additional bytes are needed to access the UDP checksum.
|
|
||||||
*
|
|
||||||
* Note: The actual length of the IP header is stored in the lower four
|
|
||||||
* bits of the first octet of the IP header as the number of 4-byte words,
|
|
||||||
* so it must be multiplied by four to get the length in bytes. Thus, the
|
|
||||||
* maximum IP header length is 15 * 4 = 60 bytes.
|
|
||||||
*
|
|
||||||
* Checksum1 - The first 16-bit Internet Checksum calculated by the
|
|
||||||
* hardware starting at the offset returned by SkCsSetReceiveFlags().
|
|
||||||
*
|
|
||||||
* Checksum2 - The second 16-bit Internet Checksum calculated by the
|
|
||||||
* hardware starting at the offset returned by SkCsSetReceiveFlags().
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
|
|
||||||
* SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
|
|
||||||
* SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
|
|
||||||
* SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
|
|
||||||
* SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
|
|
||||||
* SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
|
|
||||||
* SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
|
|
||||||
* SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
|
|
||||||
* SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
|
|
||||||
* SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
|
|
||||||
* SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
|
|
||||||
*
|
|
||||||
* Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values
|
|
||||||
* returned here can be defined in some header file by the module using CSUM.
|
|
||||||
* In this way, the calling module can assign return values for its own needs,
|
|
||||||
* e.g. by assigning bit flags to the individual protocols.
|
|
||||||
*/
|
|
||||||
SKCS_STATUS SkCsGetReceiveInfo(
|
|
||||||
SK_AC *pAc, /* Adapter context struct. */
|
|
||||||
void *pIpHeader, /* IP header. */
|
|
||||||
unsigned Checksum1, /* Hardware checksum 1. */
|
|
||||||
unsigned Checksum2, /* Hardware checksum 2. */
|
|
||||||
int NetNumber) /* Net number */
|
|
||||||
{
|
|
||||||
/* Internet Header Version found in IP header. */
|
|
||||||
unsigned InternetHeaderVersion;
|
|
||||||
|
|
||||||
/* Length of the IP header as found in IP header. */
|
|
||||||
unsigned IpHeaderLength;
|
|
||||||
|
|
||||||
/* Length of IP data portion. */
|
|
||||||
unsigned IpDataLength;
|
|
||||||
|
|
||||||
/* IP header checksum. */
|
|
||||||
unsigned IpHeaderChecksum;
|
|
||||||
|
|
||||||
/* IP header options checksum, if any. */
|
|
||||||
unsigned IpOptionsChecksum;
|
|
||||||
|
|
||||||
/* IP data checksum, i.e. TCP/UDP checksum. */
|
|
||||||
unsigned IpDataChecksum;
|
|
||||||
|
|
||||||
/* Next level protocol identifier found in IP header. */
|
|
||||||
unsigned NextLevelProtocol;
|
|
||||||
|
|
||||||
/* The checksum of the "next level protocol", i.e. TCP or UDP. */
|
|
||||||
unsigned long NextLevelProtocolChecksum;
|
|
||||||
|
|
||||||
/* Pointer to next level protocol statistics structure. */
|
|
||||||
SKCS_PROTO_STATS *NextLevelProtoStats;
|
|
||||||
|
|
||||||
/* Temporary variable. */
|
|
||||||
unsigned Tmp;
|
|
||||||
|
|
||||||
Tmp = *(SK_U8 *)
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
|
|
||||||
|
|
||||||
/* Get the Internet Header Version (IHV). */
|
|
||||||
/* Note: The IHV is stored in the upper four bits. */
|
|
||||||
|
|
||||||
InternetHeaderVersion = Tmp >> 4;
|
|
||||||
|
|
||||||
/* Check the Internet Header Version. */
|
|
||||||
/* Note: We currently only support IP version 4. */
|
|
||||||
|
|
||||||
if (InternetHeaderVersion != 4) { /* IPv4? */
|
|
||||||
SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
|
|
||||||
("Rx: Unknown Internet Header Version %u.\n",
|
|
||||||
InternetHeaderVersion));
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
|
|
||||||
return (SKCS_STATUS_UNKNOWN_IP_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the IP header length (IHL). */
|
|
||||||
/*
|
|
||||||
* Note: The IHL is stored in the lower four bits as the number of
|
|
||||||
* 4-byte words.
|
|
||||||
*/
|
|
||||||
|
|
||||||
IpHeaderLength = (Tmp & 0xf) * 4;
|
|
||||||
|
|
||||||
/* Check the IP header length. */
|
|
||||||
|
|
||||||
/* 04-Aug-1998 sw - Really check the IHL? Necessary? */
|
|
||||||
|
|
||||||
if (IpHeaderLength < 5*4) {
|
|
||||||
SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
|
|
||||||
("Rx: Invalid IP Header Length %u.\n", IpHeaderLength));
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
|
|
||||||
return (SKCS_STATUS_IP_CSUM_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is an IPv4 frame with a header of valid length. */
|
|
||||||
|
|
||||||
/* Get the IP header and data checksum. */
|
|
||||||
|
|
||||||
IpDataChecksum = Checksum2;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The IP header checksum is calculated as follows:
|
|
||||||
*
|
|
||||||
* IpHeaderChecksum = Checksum1 - Checksum2
|
|
||||||
*/
|
|
||||||
|
|
||||||
SKCS_OC_SUB(IpHeaderChecksum, Checksum1, Checksum2);
|
|
||||||
|
|
||||||
/* Check if any IP header options. */
|
|
||||||
|
|
||||||
if (IpHeaderLength > SKCS_IP_HEADER_SIZE) {
|
|
||||||
|
|
||||||
/* Get the IP options checksum. */
|
|
||||||
|
|
||||||
IpOptionsChecksum = SkCsCalculateChecksum(
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_IP_HEADER_SIZE),
|
|
||||||
IpHeaderLength - SKCS_IP_HEADER_SIZE);
|
|
||||||
|
|
||||||
/* Adjust the IP header and IP data checksums. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum);
|
|
||||||
|
|
||||||
SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the IP header checksum is ok.
|
|
||||||
*
|
|
||||||
* NOTE: We must check the IP header checksum even if the caller just wants
|
|
||||||
* us to check upper-layer checksums, because we cannot do any further
|
|
||||||
* processing of the packet without a valid IP checksum.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Get the next level protocol identifier. */
|
|
||||||
|
|
||||||
NextLevelProtocol = *(SK_U8 *)
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
|
|
||||||
|
|
||||||
if (IpHeaderChecksum != 0xffff) {
|
|
||||||
pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
|
|
||||||
/* the NDIS tester wants to know the upper level protocol too */
|
|
||||||
if (NextLevelProtocol == SKCS_PROTO_ID_TCP) {
|
|
||||||
return(SKCS_STATUS_IP_CSUM_ERROR_TCP);
|
|
||||||
}
|
|
||||||
else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) {
|
|
||||||
return(SKCS_STATUS_IP_CSUM_ERROR_UDP);
|
|
||||||
}
|
|
||||||
return (SKCS_STATUS_IP_CSUM_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if this is a TCP or UDP frame and if we should calculate the
|
|
||||||
* TCP/UDP pseudo header checksum.
|
|
||||||
*
|
|
||||||
* Also clear all protocol bit flags of protocols not present in the
|
|
||||||
* frame.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCP) != 0 &&
|
|
||||||
NextLevelProtocol == SKCS_PROTO_ID_TCP) {
|
|
||||||
/* TCP/IP frame. */
|
|
||||||
NextLevelProtoStats =
|
|
||||||
&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
|
|
||||||
}
|
|
||||||
else if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDP) != 0 &&
|
|
||||||
NextLevelProtocol == SKCS_PROTO_ID_UDP) {
|
|
||||||
/* UDP/IP frame. */
|
|
||||||
NextLevelProtoStats =
|
|
||||||
&pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* Either not a TCP or UDP frame and/or TCP/UDP processing not
|
|
||||||
* specified.
|
|
||||||
*/
|
|
||||||
return (SKCS_STATUS_IP_CSUM_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if this is an IP fragment. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: An IP fragment has a non-zero "Fragment Offset" field and/or
|
|
||||||
* the "More Fragments" bit set. Thus, if both the "Fragment Offset"
|
|
||||||
* and the "More Fragments" are zero, it is *not* a fragment. We can
|
|
||||||
* easily check both at the same time since they are in the same 16-bit
|
|
||||||
* word.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((*(SK_U16 *)
|
|
||||||
SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
|
|
||||||
~SKCS_IP_DONT_FRAGMENT) != 0) {
|
|
||||||
/* IP fragment; ignore all other protocols. */
|
|
||||||
NextLevelProtoStats->RxUnableCts++;
|
|
||||||
return (SKCS_STATUS_IP_FRAGMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 08-May-2000 ra
|
|
||||||
*
|
|
||||||
* From RFC 768 (UDP)
|
|
||||||
* If the computed checksum is zero, it is transmitted as all ones (the
|
|
||||||
* equivalent in one's complement arithmetic). An all zero transmitted
|
|
||||||
* checksum value means that the transmitter generated no checksum (for
|
|
||||||
* debugging or for higher level protocols that don't care).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (NextLevelProtocol == SKCS_PROTO_ID_UDP &&
|
|
||||||
*(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) {
|
|
||||||
|
|
||||||
NextLevelProtoStats->RxOkCts++;
|
|
||||||
|
|
||||||
return (SKCS_STATUS_IP_CSUM_OK_NO_UDP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the TCP/UDP checksum.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Get total length of IP header and data. */
|
|
||||||
|
|
||||||
IpDataLength =
|
|
||||||
*(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
|
|
||||||
|
|
||||||
/* Get length of IP data portion. */
|
|
||||||
|
|
||||||
IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
|
|
||||||
|
|
||||||
NextLevelProtocolChecksum =
|
|
||||||
|
|
||||||
/* Calculate the pseudo header checksum. */
|
|
||||||
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
|
|
||||||
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
|
|
||||||
SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
|
|
||||||
(unsigned long) SKCS_HTON16(NextLevelProtocol) +
|
|
||||||
(unsigned long) SKCS_HTON16(IpDataLength) +
|
|
||||||
|
|
||||||
/* Add the TCP/UDP header checksum. */
|
|
||||||
|
|
||||||
(unsigned long) IpDataChecksum;
|
|
||||||
|
|
||||||
/* Add-in any carries. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
|
|
||||||
|
|
||||||
/* Add-in any new carry. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
|
|
||||||
|
|
||||||
/* Check if the TCP/UDP checksum is ok. */
|
|
||||||
|
|
||||||
if ((unsigned) NextLevelProtocolChecksum == 0xffff) {
|
|
||||||
|
|
||||||
/* TCP/UDP checksum ok. */
|
|
||||||
|
|
||||||
NextLevelProtoStats->RxOkCts++;
|
|
||||||
|
|
||||||
return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
|
|
||||||
SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TCP/UDP checksum error. */
|
|
||||||
|
|
||||||
NextLevelProtoStats->RxErrCts++;
|
|
||||||
|
|
||||||
return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
|
|
||||||
SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR);
|
|
||||||
} /* SkCsGetReceiveInfo */
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* SkCsSetReceiveFlags - set checksum receive flags
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Use this function to set the various receive flags. According to the
|
|
||||||
* protocol flags set by the caller, the start offsets within received
|
|
||||||
* packets of the two hardware checksums are returned. These offsets must
|
|
||||||
* be stored in all receive descriptors.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* pAc - Pointer to adapter context struct.
|
|
||||||
*
|
|
||||||
* ReceiveFlags - Any combination of SK_PROTO_XXX flags of the protocols
|
|
||||||
* for which the caller wants checksum information on received frames.
|
|
||||||
*
|
|
||||||
* pChecksum1Offset - The start offset of the first receive descriptor
|
|
||||||
* hardware checksum to be calculated for received frames is returned
|
|
||||||
* here.
|
|
||||||
*
|
|
||||||
* pChecksum2Offset - The start offset of the second receive descriptor
|
|
||||||
* hardware checksum to be calculated for received frames is returned
|
|
||||||
* here.
|
|
||||||
*
|
|
||||||
* Returns: N/A
|
|
||||||
* Returns the two hardware checksum start offsets.
|
|
||||||
*/
|
|
||||||
void SkCsSetReceiveFlags(
|
|
||||||
SK_AC *pAc, /* Adapter context struct. */
|
|
||||||
unsigned ReceiveFlags, /* New receive flags. */
|
|
||||||
unsigned *pChecksum1Offset, /* Offset for hardware checksum 1. */
|
|
||||||
unsigned *pChecksum2Offset, /* Offset for hardware checksum 2. */
|
|
||||||
int NetNumber)
|
|
||||||
{
|
|
||||||
/* Save the receive flags. */
|
|
||||||
|
|
||||||
pAc->Csum.ReceiveFlags[NetNumber] = ReceiveFlags;
|
|
||||||
|
|
||||||
/* First checksum start offset is the IP header. */
|
|
||||||
*pChecksum1Offset = SKCS_MAC_HEADER_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Second checksum start offset is the IP data. Note that this may vary
|
|
||||||
* if there are any IP header options in the actual packet.
|
|
||||||
*/
|
|
||||||
*pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE;
|
|
||||||
} /* SkCsSetReceiveFlags */
|
|
||||||
|
|
||||||
#ifndef SK_CS_CALCULATE_CHECKSUM
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* SkCsCalculateChecksum - calculate checksum for specified data
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Calculate and return the 16-bit Internet Checksum for the specified
|
|
||||||
* data.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* pData - Pointer to data for which the checksum shall be calculated.
|
|
||||||
* Note: The pointer should be aligned on a 16-bit boundary.
|
|
||||||
*
|
|
||||||
* Length - Length in bytes of data to checksum.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* The 16-bit Internet Checksum for the specified data.
|
|
||||||
*
|
|
||||||
* Note: The checksum is calculated in the machine's natural byte order,
|
|
||||||
* i.e. little vs. big endian. Thus, the resulting checksum is different
|
|
||||||
* for the same input data on little and big endian machines.
|
|
||||||
*
|
|
||||||
* However, when written back to the network packet, the byte order is
|
|
||||||
* always in correct network order.
|
|
||||||
*/
|
|
||||||
unsigned SkCsCalculateChecksum(
|
|
||||||
void *pData, /* Data to checksum. */
|
|
||||||
unsigned Length) /* Length of data. */
|
|
||||||
{
|
|
||||||
SK_U16 *pU16; /* Pointer to the data as 16-bit words. */
|
|
||||||
unsigned long Checksum; /* Checksum; must be at least 32 bits. */
|
|
||||||
|
|
||||||
/* Sum up all 16-bit words. */
|
|
||||||
|
|
||||||
pU16 = (SK_U16 *) pData;
|
|
||||||
for (Checksum = 0; Length > 1; Length -= 2) {
|
|
||||||
Checksum += *pU16++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is an odd number of bytes, add-in the last byte. */
|
|
||||||
|
|
||||||
if (Length > 0) {
|
|
||||||
#ifdef SK_BIG_ENDIAN
|
|
||||||
/* Add the last byte as the high byte. */
|
|
||||||
Checksum += ((unsigned) *(SK_U8 *) pU16) << 8;
|
|
||||||
#else /* !SK_BIG_ENDIAN */
|
|
||||||
/* Add the last byte as the low byte. */
|
|
||||||
Checksum += *(SK_U8 *) pU16;
|
|
||||||
#endif /* !SK_BIG_ENDIAN */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add-in any carries. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(Checksum, Checksum, 0);
|
|
||||||
|
|
||||||
/* Add-in any new carry. */
|
|
||||||
|
|
||||||
SKCS_OC_ADD(Checksum, Checksum, 0);
|
|
||||||
|
|
||||||
/* Note: All bits beyond the 16-bit limit are now zero. */
|
|
||||||
|
|
||||||
return ((unsigned) Checksum);
|
|
||||||
} /* SkCsCalculateChecksum */
|
|
||||||
|
|
||||||
#endif /* SK_CS_CALCULATE_CHECKSUM */
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* SkCsEvent - the CSUM event dispatcher
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This is the event handler for the CSUM module.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* pAc - Pointer to adapter context.
|
|
||||||
*
|
|
||||||
* Ioc - I/O context.
|
|
||||||
*
|
|
||||||
* Event - Event id.
|
|
||||||
*
|
|
||||||
* Param - Event dependent parameter.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* The 16-bit Internet Checksum for the specified data.
|
|
||||||
*
|
|
||||||
* Note: The checksum is calculated in the machine's natural byte order,
|
|
||||||
* i.e. little vs. big endian. Thus, the resulting checksum is different
|
|
||||||
* for the same input data on little and big endian machines.
|
|
||||||
*
|
|
||||||
* However, when written back to the network packet, the byte order is
|
|
||||||
* always in correct network order.
|
|
||||||
*/
|
|
||||||
int SkCsEvent(
|
|
||||||
SK_AC *pAc, /* Pointer to adapter context. */
|
|
||||||
SK_IOC Ioc, /* I/O context. */
|
|
||||||
SK_U32 Event, /* Event id. */
|
|
||||||
SK_EVPARA Param) /* Event dependent parameter. */
|
|
||||||
{
|
|
||||||
int ProtoIndex;
|
|
||||||
int NetNumber;
|
|
||||||
|
|
||||||
switch (Event) {
|
|
||||||
/*
|
|
||||||
* Clear protocol statistics.
|
|
||||||
*
|
|
||||||
* Param - Protocol index, or -1 for all protocols.
|
|
||||||
* - Net number.
|
|
||||||
*/
|
|
||||||
case SK_CSUM_EVENT_CLEAR_PROTO_STATS:
|
|
||||||
|
|
||||||
ProtoIndex = (int)Param.Para32[1];
|
|
||||||
NetNumber = (int)Param.Para32[0];
|
|
||||||
if (ProtoIndex < 0) { /* Clear for all protocols. */
|
|
||||||
if (NetNumber >= 0) {
|
|
||||||
SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][0], 0,
|
|
||||||
sizeof(pAc->Csum.ProtoStats[NetNumber]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { /* Clear for individual protocol. */
|
|
||||||
SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0,
|
|
||||||
sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex]));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (0); /* Success. */
|
|
||||||
} /* SkCsEvent */
|
|
||||||
|
|
||||||
#endif /* SK_USE_CSUM */
|
|
|
@ -549,4 +549,6 @@ struct ethtool_ops SkGeEthtoolOps = {
|
||||||
.phys_id = locateDevice,
|
.phys_id = locateDevice,
|
||||||
.get_pauseparam = getPauseParams,
|
.get_pauseparam = getPauseParams,
|
||||||
.set_pauseparam = setPauseParams,
|
.set_pauseparam = setPauseParams,
|
||||||
|
.get_link = ethtool_op_get_link,
|
||||||
|
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,7 +101,6 @@
|
||||||
* "h/skgeinit.h"
|
* "h/skgeinit.h"
|
||||||
* "h/skaddr.h"
|
* "h/skaddr.h"
|
||||||
* "h/skgesirq.h"
|
* "h/skgesirq.h"
|
||||||
* "h/skcsum.h"
|
|
||||||
* "h/skrlmt.h"
|
* "h/skrlmt.h"
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -113,6 +112,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
|
||||||
#include "h/skdrv1st.h"
|
#include "h/skdrv1st.h"
|
||||||
#include "h/skdrv2nd.h"
|
#include "h/skdrv2nd.h"
|
||||||
|
@ -622,11 +622,6 @@ SK_BOOL DualNet;
|
||||||
return(-EAGAIN);
|
return(-EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCsSetReceiveFlags(pAC,
|
|
||||||
SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP,
|
|
||||||
&pAC->CsOfs1, &pAC->CsOfs2, 0);
|
|
||||||
pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
|
|
||||||
|
|
||||||
BoardInitMem(pAC);
|
BoardInitMem(pAC);
|
||||||
/* tschilling: New common function with minimum size check. */
|
/* tschilling: New common function with minimum size check. */
|
||||||
DualNet = SK_FALSE;
|
DualNet = SK_FALSE;
|
||||||
|
@ -844,7 +839,7 @@ uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */
|
||||||
/* set the pointers right */
|
/* set the pointers right */
|
||||||
pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
|
pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
|
||||||
pDescr->pNextRxd = pNextDescr;
|
pDescr->pNextRxd = pNextDescr;
|
||||||
pDescr->TcpSumStarts = pAC->CsOfs;
|
pDescr->TcpSumStarts = 0;
|
||||||
|
|
||||||
/* advance one step */
|
/* advance one step */
|
||||||
pPrevDescr = pDescr;
|
pPrevDescr = pDescr;
|
||||||
|
@ -1526,8 +1521,6 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
TXD *pOldTxd;
|
TXD *pOldTxd;
|
||||||
unsigned long Flags;
|
unsigned long Flags;
|
||||||
SK_U64 PhysAddr;
|
SK_U64 PhysAddr;
|
||||||
int Protocol;
|
|
||||||
int IpHeaderLength;
|
|
||||||
int BytesSend = pMessage->len;
|
int BytesSend = pMessage->len;
|
||||||
|
|
||||||
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
|
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
|
||||||
|
@ -1600,8 +1593,10 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
pTxd->pMBuf = pMessage;
|
pTxd->pMBuf = pMessage;
|
||||||
|
|
||||||
if (pMessage->ip_summed == CHECKSUM_HW) {
|
if (pMessage->ip_summed == CHECKSUM_HW) {
|
||||||
Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
|
u16 hdrlen = pMessage->h.raw - pMessage->data;
|
||||||
if ((Protocol == C_PROTO_ID_UDP) &&
|
u16 offset = hdrlen + pMessage->csum;
|
||||||
|
|
||||||
|
if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
|
||||||
(pAC->GIni.GIChipRev == 0) &&
|
(pAC->GIni.GIChipRev == 0) &&
|
||||||
(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
|
(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
|
||||||
pTxd->TBControl = BMU_TCP_CHECK;
|
pTxd->TBControl = BMU_TCP_CHECK;
|
||||||
|
@ -1609,14 +1604,9 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
pTxd->TBControl = BMU_UDP_CHECK;
|
pTxd->TBControl = BMU_UDP_CHECK;
|
||||||
}
|
}
|
||||||
|
|
||||||
IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER];
|
pTxd->TcpSumOfs = 0;
|
||||||
IpHeaderLength = (IpHeaderLength & 0xf) * 4;
|
pTxd->TcpSumSt = hdrlen;
|
||||||
pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */
|
pTxd->TcpSumWr = offset;
|
||||||
pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
|
|
||||||
(Protocol == C_PROTO_ID_UDP ?
|
|
||||||
C_OFFSET_UDPHEADER_UDPCS :
|
|
||||||
C_OFFSET_TCPHEADER_TCPCS);
|
|
||||||
pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
|
|
||||||
|
|
||||||
pTxd->TBControl |= BMU_OWN | BMU_STF |
|
pTxd->TBControl |= BMU_OWN | BMU_STF |
|
||||||
BMU_SW | BMU_EOF |
|
BMU_SW | BMU_EOF |
|
||||||
|
@ -1679,11 +1669,10 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
TXD *pTxdLst;
|
TXD *pTxdLst;
|
||||||
int CurrFrag;
|
int CurrFrag;
|
||||||
int BytesSend;
|
int BytesSend;
|
||||||
int IpHeaderLength;
|
|
||||||
int Protocol;
|
|
||||||
skb_frag_t *sk_frag;
|
skb_frag_t *sk_frag;
|
||||||
SK_U64 PhysAddr;
|
SK_U64 PhysAddr;
|
||||||
unsigned long Flags;
|
unsigned long Flags;
|
||||||
|
SK_U32 Control;
|
||||||
|
|
||||||
spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
|
spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
|
||||||
#ifndef USE_TX_COMPLETE
|
#ifndef USE_TX_COMPLETE
|
||||||
|
@ -1706,7 +1695,6 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
pTxdFst = pTxd;
|
pTxdFst = pTxd;
|
||||||
pTxdLst = pTxd;
|
pTxdLst = pTxd;
|
||||||
BytesSend = 0;
|
BytesSend = 0;
|
||||||
Protocol = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Map the first fragment (header) into the DMA-space
|
** Map the first fragment (header) into the DMA-space
|
||||||
|
@ -1724,32 +1712,31 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
** Does the HW need to evaluate checksum for TCP or UDP packets?
|
** Does the HW need to evaluate checksum for TCP or UDP packets?
|
||||||
*/
|
*/
|
||||||
if (pMessage->ip_summed == CHECKSUM_HW) {
|
if (pMessage->ip_summed == CHECKSUM_HW) {
|
||||||
pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage);
|
u16 hdrlen = pMessage->h.raw - pMessage->data;
|
||||||
|
u16 offset = hdrlen + pMessage->csum;
|
||||||
|
|
||||||
|
Control = BMU_STFWD;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** We have to use the opcode for tcp here, because the
|
** We have to use the opcode for tcp here, because the
|
||||||
** opcode for udp is not working in the hardware yet
|
** opcode for udp is not working in the hardware yet
|
||||||
** (Revision 2.0)
|
** (Revision 2.0)
|
||||||
*/
|
*/
|
||||||
Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff);
|
if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
|
||||||
if ((Protocol == C_PROTO_ID_UDP) &&
|
|
||||||
(pAC->GIni.GIChipRev == 0) &&
|
(pAC->GIni.GIChipRev == 0) &&
|
||||||
(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
|
(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
|
||||||
pTxd->TBControl |= BMU_TCP_CHECK;
|
Control |= BMU_TCP_CHECK;
|
||||||
} else {
|
} else {
|
||||||
pTxd->TBControl |= BMU_UDP_CHECK;
|
Control |= BMU_UDP_CHECK;
|
||||||
}
|
}
|
||||||
|
|
||||||
IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4;
|
pTxd->TcpSumOfs = 0;
|
||||||
pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */
|
pTxd->TcpSumSt = hdrlen;
|
||||||
pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
|
pTxd->TcpSumWr = offset;
|
||||||
(Protocol == C_PROTO_ID_UDP ?
|
} else
|
||||||
C_OFFSET_UDPHEADER_UDPCS :
|
Control = BMU_CHECK | BMU_SW;
|
||||||
C_OFFSET_TCPHEADER_TCPCS);
|
|
||||||
pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
|
pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
|
||||||
} else {
|
|
||||||
pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
|
|
||||||
skb_headlen(pMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
pTxd = pTxd->pNextTxd;
|
pTxd = pTxd->pNextTxd;
|
||||||
pTxPort->TxdRingFree--;
|
pTxPort->TxdRingFree--;
|
||||||
|
@ -1773,40 +1760,18 @@ struct sk_buff *pMessage) /* pointer to send-message */
|
||||||
pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
|
pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
|
||||||
pTxd->pMBuf = pMessage;
|
pTxd->pMBuf = pMessage;
|
||||||
|
|
||||||
/*
|
pTxd->TBControl = Control | BMU_OWN | sk_frag->size;;
|
||||||
** Does the HW need to evaluate checksum for TCP or UDP packets?
|
|
||||||
*/
|
|
||||||
if (pMessage->ip_summed == CHECKSUM_HW) {
|
|
||||||
pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD;
|
|
||||||
/*
|
|
||||||
** We have to use the opcode for tcp here because the
|
|
||||||
** opcode for udp is not working in the hardware yet
|
|
||||||
** (revision 2.0)
|
|
||||||
*/
|
|
||||||
if ((Protocol == C_PROTO_ID_UDP) &&
|
|
||||||
(pAC->GIni.GIChipRev == 0) &&
|
|
||||||
(pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
|
|
||||||
pTxd->TBControl |= BMU_TCP_CHECK;
|
|
||||||
} else {
|
|
||||||
pTxd->TBControl |= BMU_UDP_CHECK;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Do we have the last fragment?
|
** Do we have the last fragment?
|
||||||
*/
|
*/
|
||||||
if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
|
if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
|
||||||
#ifdef USE_TX_COMPLETE
|
#ifdef USE_TX_COMPLETE
|
||||||
pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size;
|
pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
|
||||||
#else
|
#else
|
||||||
pTxd->TBControl |= BMU_EOF | sk_frag->size;
|
pTxd->TBControl |= BMU_EOF;
|
||||||
#endif
|
#endif
|
||||||
pTxdFst->TBControl |= BMU_OWN | BMU_SW;
|
pTxdFst->TBControl |= BMU_OWN | BMU_SW;
|
||||||
|
|
||||||
} else {
|
|
||||||
pTxd->TBControl |= sk_frag->size;
|
|
||||||
}
|
}
|
||||||
pTxdLst = pTxd;
|
pTxdLst = pTxd;
|
||||||
pTxd = pTxd->pNextTxd;
|
pTxd = pTxd->pNextTxd;
|
||||||
|
@ -2053,7 +2018,6 @@ SK_U32 Control; /* control field of descriptor */
|
||||||
struct sk_buff *pMsg; /* pointer to message holding frame */
|
struct sk_buff *pMsg; /* pointer to message holding frame */
|
||||||
struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
|
struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
|
||||||
int FrameLength; /* total length of received frame */
|
int FrameLength; /* total length of received frame */
|
||||||
int IpFrameLength;
|
|
||||||
SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
|
SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
|
||||||
SK_EVPARA EvPara; /* an event parameter union */
|
SK_EVPARA EvPara; /* an event parameter union */
|
||||||
unsigned long Flags; /* for spin lock */
|
unsigned long Flags; /* for spin lock */
|
||||||
|
@ -2066,10 +2030,6 @@ SK_BOOL IsMc;
|
||||||
SK_BOOL IsBadFrame; /* Bad frame */
|
SK_BOOL IsBadFrame; /* Bad frame */
|
||||||
|
|
||||||
SK_U32 FrameStat;
|
SK_U32 FrameStat;
|
||||||
unsigned short Csum1;
|
|
||||||
unsigned short Csum2;
|
|
||||||
unsigned short Type;
|
|
||||||
int Result;
|
|
||||||
SK_U64 PhysAddr;
|
SK_U64 PhysAddr;
|
||||||
|
|
||||||
rx_start:
|
rx_start:
|
||||||
|
@ -2198,8 +2158,8 @@ rx_start:
|
||||||
(dma_addr_t) PhysAddr,
|
(dma_addr_t) PhysAddr,
|
||||||
FrameLength,
|
FrameLength,
|
||||||
PCI_DMA_FROMDEVICE);
|
PCI_DMA_FROMDEVICE);
|
||||||
eth_copy_and_sum(pNewMsg, pMsg->data,
|
memcpy(pNewMsg->data, pMsg, FrameLength);
|
||||||
FrameLength, 0);
|
|
||||||
pci_dma_sync_single_for_device(pAC->PciDev,
|
pci_dma_sync_single_for_device(pAC->PciDev,
|
||||||
(dma_addr_t) PhysAddr,
|
(dma_addr_t) PhysAddr,
|
||||||
FrameLength,
|
FrameLength,
|
||||||
|
@ -2227,69 +2187,16 @@ rx_start:
|
||||||
|
|
||||||
/* set length in message */
|
/* set length in message */
|
||||||
skb_put(pMsg, FrameLength);
|
skb_put(pMsg, FrameLength);
|
||||||
/* hardware checksum */
|
} /* frame > SK_COPY_TRESHOLD */
|
||||||
Type = ntohs(*((short*)&pMsg->data[12]));
|
|
||||||
|
|
||||||
#ifdef USE_SK_RX_CHECKSUM
|
#ifdef USE_SK_RX_CHECKSUM
|
||||||
if (Type == 0x800) {
|
pMsg->csum = pRxd->TcpSums;
|
||||||
Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
|
pMsg->ip_summed = CHECKSUM_HW;
|
||||||
Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
|
|
||||||
IpFrameLength = (int) ntohs((unsigned short)
|
|
||||||
((unsigned short *) pMsg->data)[8]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test: If frame is padded, a check is not possible!
|
|
||||||
* Frame not padded? Length difference must be 14 (0xe)!
|
|
||||||
*/
|
|
||||||
if ((FrameLength - IpFrameLength) != 0xe) {
|
|
||||||
/* Frame padded => TCP offload not possible! */
|
|
||||||
pMsg->ip_summed = CHECKSUM_NONE;
|
|
||||||
} else {
|
|
||||||
/* Frame not padded => TCP offload! */
|
|
||||||
if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
|
|
||||||
(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
|
|
||||||
(pAC->ChipsetType)) {
|
|
||||||
Result = SkCsGetReceiveInfo(pAC,
|
|
||||||
&pMsg->data[14],
|
|
||||||
Csum1, Csum2, pRxPort->PortIndex);
|
|
||||||
if (Result ==
|
|
||||||
SKCS_STATUS_IP_FRAGMENT ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_IP_CSUM_OK ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_TCP_CSUM_OK ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_UDP_CSUM_OK) {
|
|
||||||
pMsg->ip_summed =
|
|
||||||
CHECKSUM_UNNECESSARY;
|
|
||||||
}
|
|
||||||
else if (Result ==
|
|
||||||
SKCS_STATUS_TCP_CSUM_ERROR ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_UDP_CSUM_ERROR ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_IP_CSUM_ERROR_UDP ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_IP_CSUM_ERROR_TCP ||
|
|
||||||
Result ==
|
|
||||||
SKCS_STATUS_IP_CSUM_ERROR ) {
|
|
||||||
/* HW Checksum error */
|
|
||||||
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
|
|
||||||
SK_DBGCAT_DRV_RX_PROGRESS,
|
|
||||||
("skge: CRC error. Frame dropped!\n"));
|
|
||||||
goto rx_failed;
|
|
||||||
} else {
|
|
||||||
pMsg->ip_summed =
|
|
||||||
CHECKSUM_NONE;
|
|
||||||
}
|
|
||||||
}/* checksumControl calculation valid */
|
|
||||||
} /* Frame length check */
|
|
||||||
} /* IP frame */
|
|
||||||
#else
|
#else
|
||||||
pMsg->ip_summed = CHECKSUM_NONE;
|
pMsg->ip_summed = CHECKSUM_NONE;
|
||||||
#endif
|
#endif
|
||||||
} /* frame > SK_COPY_TRESHOLD */
|
|
||||||
|
|
||||||
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
|
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
|
||||||
ForRlmt = SK_RLMT_RX_PROTOCOL;
|
ForRlmt = SK_RLMT_RX_PROTOCOL;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -4945,7 +4852,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
|
||||||
dev->irq = pdev->irq;
|
dev->irq = pdev->irq;
|
||||||
error = SkGeInitPCI(pAC);
|
error = SkGeInitPCI(pAC);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk("SKGE: PCI setup failed: %i\n", error);
|
printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
|
||||||
goto out_free_netdev;
|
goto out_free_netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4981,7 +4888,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
|
||||||
|
|
||||||
/* Register net device */
|
/* Register net device */
|
||||||
if (register_netdev(dev)) {
|
if (register_netdev(dev)) {
|
||||||
printk(KERN_ERR "SKGE: Could not register device.\n");
|
printk(KERN_ERR "sk98lin: Could not register device.\n");
|
||||||
goto out_free_resources;
|
goto out_free_resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5000,8 +4907,8 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
|
||||||
|
|
||||||
SkGeYellowLED(pAC, pAC->IoBase, 1);
|
SkGeYellowLED(pAC, pAC->IoBase, 1);
|
||||||
|
|
||||||
|
|
||||||
memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
|
memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
|
||||||
|
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||||
|
|
||||||
SkGeProcCreate(dev);
|
SkGeProcCreate(dev);
|
||||||
|
|
||||||
|
@ -5047,13 +4954,14 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (register_netdev(dev)) {
|
if (register_netdev(dev)) {
|
||||||
printk(KERN_ERR "SKGE: Could not register device.\n");
|
printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n");
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
pAC->dev[1] = pAC->dev[0];
|
pAC->dev[1] = pAC->dev[0];
|
||||||
} else {
|
} else {
|
||||||
SkGeProcCreate(dev);
|
SkGeProcCreate(dev);
|
||||||
memcpy(&dev->dev_addr,
|
memcpy(&dev->dev_addr,
|
||||||
&pAC->Addr.Net[1].CurrentMacAddress, 6);
|
&pAC->Addr.Net[1].CurrentMacAddress, 6);
|
||||||
|
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||||
|
|
||||||
printk("%s: %s\n", dev->name, pAC->DeviceStr);
|
printk("%s: %s\n", dev->name, pAC->DeviceStr);
|
||||||
printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
|
printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
|
||||||
|
|
Loading…
Reference in a new issue