aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sk98lin
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sk98lin')
-rw-r--r--drivers/net/sk98lin/Makefile5
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h4
-rw-r--r--drivers/net/sk98lin/skcsum.c871
-rw-r--r--drivers/net/sk98lin/skethtool.c2
-rw-r--r--drivers/net/sk98lin/skge.c174
5 files changed, 45 insertions, 1011 deletions
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
index 6783039ffb75..7653d6e33aa2 100644
--- a/drivers/net/sk98lin/Makefile
+++ b/drivers/net/sk98lin/Makefile
@@ -27,8 +27,7 @@ sk98lin-objs := \
27 sktimer.o \ 27 sktimer.o \
28 skvpd.o \ 28 skvpd.o \
29 skxmac2.o \ 29 skxmac2.o \
30 skproc.o \ 30 skproc.o
31 skcsum.o
32 31
33# DBGDEF = \ 32# DBGDEF = \
34# -DDEBUG 33# -DDEBUG
@@ -77,7 +76,7 @@ endif
77# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources 76# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
78# SK_DBGCAT_DRV_EVENT 0x08000000 driver events 77# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
79 78
80EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DSK_USE_CSUM -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM) 79EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
81 80
82clean: 81clean:
83 rm -f core *.o *.a *.s 82 rm -f core *.o *.a *.s
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index c0bfce5a4656..9bdfde80c30b 100644
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -424,10 +424,6 @@ struct s_AC {
424 TX_PORT TxPort[SK_MAX_MACS][2]; 424 TX_PORT TxPort[SK_MAX_MACS][2];
425 RX_PORT RxPort[SK_MAX_MACS]; 425 RX_PORT RxPort[SK_MAX_MACS];
426 426
427 unsigned int CsOfs1; /* for checksum calculation */
428 unsigned int CsOfs2; /* for checksum calculation */
429 SK_U32 CsOfs; /* for checksum calculation */
430
431 SK_BOOL CheckQueue; /* check event queue soon */ 427 SK_BOOL CheckQueue; /* check event queue soon */
432 SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */ 428 SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
433 DIM_INFO DynIrqModInfo; /* all data related to DIM */ 429 DIM_INFO DynIrqModInfo; /* all data related to DIM */
diff --git a/drivers/net/sk98lin/skcsum.c b/drivers/net/sk98lin/skcsum.c
deleted file mode 100644
index 38a6e7a631f3..000000000000
--- a/drivers/net/sk98lin/skcsum.c
+++ /dev/null
@@ -1,871 +0,0 @@
1/******************************************************************************
2 *
3 * Name: skcsum.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.12 $
6 * Date: $Date: 2003/08/20 13:55:53 $
7 * Purpose: Store/verify Internet checksum in send/receive packets.
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * The information in this file is provided "AS IS" without warranty.
21 *
22 ******************************************************************************/
23
24#ifdef SK_USE_CSUM /* Check if CSUM is to be used. */
25
26#ifndef lint
27static const char SysKonnectFileId[] =
28 "@(#) $Id: skcsum.c,v 1.12 2003/08/20 13:55:53 mschmid Exp $ (C) SysKonnect.";
29#endif /* !lint */
30
31/******************************************************************************
32 *
33 * Description:
34 *
35 * This is the "GEnesis" common module "CSUM".
36 *
37 * This module contains the code necessary to calculate, store, and verify the
38 * Internet Checksum of IP, TCP, and UDP frames.
39 *
40 * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
41 * and is the code name of this SysKonnect project.
42 *
43 * Compilation Options:
44 *
45 * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
46 * empty module.
47 *
48 * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
49 * definitions. In this case, all SKCS_PROTO_xxx definitions must be made
50 * external.
51 *
52 * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
53 * definitions. In this case, all SKCS_STATUS_xxx definitions must be made
54 * external.
55 *
56 * Include File Hierarchy:
57 *
58 * "h/skdrv1st.h"
59 * "h/skcsum.h"
60 * "h/sktypes.h"
61 * "h/skqueue.h"
62 * "h/skdrv2nd.h"
63 *
64 ******************************************************************************/
65
66#include "h/skdrv1st.h"
67#include "h/skcsum.h"
68#include "h/skdrv2nd.h"
69
70/* defines ********************************************************************/
71
72/* The size of an Ethernet MAC header. */
73#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2)
74
75/* The size of the used topology's MAC header. */
76#define SKCS_MAC_HEADER_SIZE SKCS_ETHERNET_MAC_HEADER_SIZE
77
78/* The size of the IP header without any option fields. */
79#define SKCS_IP_HEADER_SIZE 20
80
81/*
82 * Field offsets within the IP header.
83 */
84
85/* "Internet Header Version" and "Length". */
86#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH 0
87
88/* "Total Length". */
89#define SKCS_OFS_IP_TOTAL_LENGTH 2
90
91/* "Flags" "Fragment Offset". */
92#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET 6
93
94/* "Next Level Protocol" identifier. */
95#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9
96
97/* Source IP address. */
98#define SKCS_OFS_IP_SOURCE_ADDRESS 12
99
100/* Destination IP address. */
101#define SKCS_OFS_IP_DESTINATION_ADDRESS 16
102
103
104/*
105 * Field offsets within the UDP header.
106 */
107
108/* UDP checksum. */
109#define SKCS_OFS_UDP_CHECKSUM 6
110
111/* IP "Next Level Protocol" identifiers (see RFC 790). */
112#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */
113#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */
114
115/* IP "Don't Fragment" bit. */
116#define SKCS_IP_DONT_FRAGMENT SKCS_HTON16(0x4000)
117
118/* Add a byte offset to a pointer. */
119#define SKCS_IDX(pPtr, Ofs) ((void *) ((char *) (pPtr) + (Ofs)))
120
121/*
122 * Macros that convert host to network representation and vice versa, i.e.
123 * little/big endian conversion on little endian machines only.
124 */
125#ifdef SK_LITTLE_ENDIAN
126#define SKCS_HTON16(Val16) (((unsigned) (Val16) >> 8) | (((Val16) & 0xff) << 8))
127#endif /* SK_LITTLE_ENDIAN */
128#ifdef SK_BIG_ENDIAN
129#define SKCS_HTON16(Val16) (Val16)
130#endif /* SK_BIG_ENDIAN */
131#define SKCS_NTOH16(Val16) SKCS_HTON16(Val16)
132
133/* typedefs *******************************************************************/
134
135/* function prototypes ********************************************************/
136
137/******************************************************************************
138 *
139 * SkCsGetSendInfo - get checksum information for a send packet
140 *
141 * Description:
142 * Get all checksum information necessary to send a TCP or UDP packet. The
143 * function checks the IP header passed to it. If the high-level protocol
144 * is either TCP or UDP the pseudo header checksum is calculated and
145 * returned.
146 *
147 * The function returns the total length of the IP header (including any
148 * IP option fields), which is the same as the start offset of the IP data
149 * which in turn is the start offset of the TCP or UDP header.
150 *
151 * The function also returns the TCP or UDP pseudo header checksum, which
152 * should be used as the start value for the hardware checksum calculation.
153 * (Note that any actual pseudo header checksum can never calculate to
154 * zero.)
155 *
156 * Note:
157 * There is a bug in the GENESIS ASIC which may lead to wrong checksums.
158 *
159 * Arguments:
160 * pAc - A pointer to the adapter context struct.
161 *
162 * pIpHeader - Pointer to IP header. Must be at least the IP header *not*
163 * including any option fields, i.e. at least 20 bytes.
164 *
165 * Note: This pointer will be used to address 8-, 16-, and 32-bit
166 * variables with the respective alignment offsets relative to the pointer.
167 * Thus, the pointer should point to a 32-bit aligned address. If the
168 * target system cannot address 32-bit variables on non 32-bit aligned
169 * addresses, then the pointer *must* point to a 32-bit aligned address.
170 *
171 * pPacketInfo - A pointer to the packet information structure for this
172 * packet. Before calling this SkCsGetSendInfo(), the following field must
173 * be initialized:
174 *
175 * ProtocolFlags - Initialize with any combination of
176 * SKCS_PROTO_XXX bit flags. SkCsGetSendInfo() will only work on
177 * the protocols specified here. Any protocol(s) not specified
178 * here will be ignored.
179 *
180 * Note: Only one checksum can be calculated in hardware. Thus, if
181 * SKCS_PROTO_IP is specified in the 'ProtocolFlags',
182 * SkCsGetSendInfo() must calculate the IP header checksum in
183 * software. It might be a better idea to have the calling
184 * protocol stack calculate the IP header checksum.
185 *
186 * Returns: N/A
187 * On return, the following fields in 'pPacketInfo' may or may not have
188 * been filled with information, depending on the protocol(s) found in the
189 * packet:
190 *
191 * ProtocolFlags - Returns the SKCS_PROTO_XXX bit flags of the protocol(s)
192 * that were both requested by the caller and actually found in the packet.
193 * Protocol(s) not specified by the caller and/or not found in the packet
194 * will have their respective SKCS_PROTO_XXX bit flags reset.
195 *
196 * Note: For IP fragments, TCP and UDP packet information is ignored.
197 *
198 * IpHeaderLength - The total length in bytes of the complete IP header
199 * including any option fields is returned here. This is the start offset
200 * of the IP data, i.e. the TCP or UDP header if present.
201 *
202 * IpHeaderChecksum - If IP has been specified in the 'ProtocolFlags', the
203 * 16-bit Internet Checksum of the IP header is returned here. This value
204 * is to be stored into the packet's 'IP Header Checksum' field.
205 *
206 * PseudoHeaderChecksum - If this is a TCP or UDP packet and if TCP or UDP
207 * has been specified in the 'ProtocolFlags', the 16-bit Internet Checksum
208 * of the TCP or UDP pseudo header is returned here.
209 */
210void SkCsGetSendInfo(
211SK_AC *pAc, /* Adapter context struct. */
212void *pIpHeader, /* IP header. */
213SKCS_PACKET_INFO *pPacketInfo, /* Packet information struct. */
214int NetNumber) /* Net number */
215{
216 /* Internet Header Version found in IP header. */
217 unsigned InternetHeaderVersion;
218
219 /* Length of the IP header as found in IP header. */
220 unsigned IpHeaderLength;
221
222 /* Bit field specifiying the desired/found protocols. */
223 unsigned ProtocolFlags;
224
225 /* Next level protocol identifier found in IP header. */
226 unsigned NextLevelProtocol;
227
228 /* Length of IP data portion. */
229 unsigned IpDataLength;
230
231 /* TCP/UDP pseudo header checksum. */
232 unsigned long PseudoHeaderChecksum;
233
234 /* Pointer to next level protocol statistics structure. */
235 SKCS_PROTO_STATS *NextLevelProtoStats;
236
237 /* Temporary variable. */
238 unsigned Tmp;
239
240 Tmp = *(SK_U8 *)
241 SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
242
243 /* Get the Internet Header Version (IHV). */
244 /* Note: The IHV is stored in the upper four bits. */
245
246 InternetHeaderVersion = Tmp >> 4;
247
248 /* Check the Internet Header Version. */
249 /* Note: We currently only support IP version 4. */
250
251 if (InternetHeaderVersion != 4) { /* IPv4? */
252 SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
253 ("Tx: Unknown Internet Header Version %u.\n",
254 InternetHeaderVersion));
255 pPacketInfo->ProtocolFlags = 0;
256 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
257 return;
258 }
259
260 /* Get the IP header length (IHL). */
261 /*
262 * Note: The IHL is stored in the lower four bits as the number of
263 * 4-byte words.
264 */
265
266 IpHeaderLength = (Tmp & 0xf) * 4;
267 pPacketInfo->IpHeaderLength = IpHeaderLength;
268
269 /* Check the IP header length. */
270
271 /* 04-Aug-1998 sw - Really check the IHL? Necessary? */
272
273 if (IpHeaderLength < 5*4) {
274 SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_TX,
275 ("Tx: Invalid IP Header Length %u.\n", IpHeaderLength));
276 pPacketInfo->ProtocolFlags = 0;
277 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxUnableCts++;
278 return;
279 }
280
281 /* This is an IPv4 frame with a header of valid length. */
282
283 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].TxOkCts++;
284
285 /* Check if we should calculate the IP header checksum. */
286
287 ProtocolFlags = pPacketInfo->ProtocolFlags;
288
289 if (ProtocolFlags & SKCS_PROTO_IP) {
290 pPacketInfo->IpHeaderChecksum =
291 SkCsCalculateChecksum(pIpHeader, IpHeaderLength);
292 }
293
294 /* Get the next level protocol identifier. */
295
296 NextLevelProtocol =
297 *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
298
299 /*
300 * Check if this is a TCP or UDP frame and if we should calculate the
301 * TCP/UDP pseudo header checksum.
302 *
303 * Also clear all protocol bit flags of protocols not present in the
304 * frame.
305 */
306
307 if ((ProtocolFlags & SKCS_PROTO_TCP) != 0 &&
308 NextLevelProtocol == SKCS_PROTO_ID_TCP) {
309 /* TCP/IP frame. */
310 ProtocolFlags &= SKCS_PROTO_TCP | SKCS_PROTO_IP;
311 NextLevelProtoStats =
312 &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
313 }
314 else if ((ProtocolFlags & SKCS_PROTO_UDP) != 0 &&
315 NextLevelProtocol == SKCS_PROTO_ID_UDP) {
316 /* UDP/IP frame. */
317 ProtocolFlags &= SKCS_PROTO_UDP | SKCS_PROTO_IP;
318 NextLevelProtoStats =
319 &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
320 }
321 else {
322 /*
323 * Either not a TCP or UDP frame and/or TCP/UDP processing not
324 * specified.
325 */
326 pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
327 return;
328 }
329
330 /* Check if this is an IP fragment. */
331
332 /*
333 * Note: An IP fragment has a non-zero "Fragment Offset" field and/or
334 * the "More Fragments" bit set. Thus, if both the "Fragment Offset"
335 * and the "More Fragments" are zero, it is *not* a fragment. We can
336 * easily check both at the same time since they are in the same 16-bit
337 * word.
338 */
339
340 if ((*(SK_U16 *)
341 SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
342 ~SKCS_IP_DONT_FRAGMENT) != 0) {
343 /* IP fragment; ignore all other protocols. */
344 pPacketInfo->ProtocolFlags = ProtocolFlags & SKCS_PROTO_IP;
345 NextLevelProtoStats->TxUnableCts++;
346 return;
347 }
348
349 /*
350 * Calculate the TCP/UDP pseudo header checksum.
351 */
352
353 /* Get total length of IP header and data. */
354
355 IpDataLength =
356 *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
357
358 /* Get length of IP data portion. */
359
360 IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
361
362 /* Calculate the sum of all pseudo header fields (16-bit). */
363
364 PseudoHeaderChecksum =
365 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
366 SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
367 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
368 SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
369 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
370 SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
371 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
372 SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
373 (unsigned long) SKCS_HTON16(NextLevelProtocol) +
374 (unsigned long) SKCS_HTON16(IpDataLength);
375
376 /* Add-in any carries. */
377
378 SKCS_OC_ADD(PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
379
380 /* Add-in any new carry. */
381
382 SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
383
384 pPacketInfo->ProtocolFlags = ProtocolFlags;
385 NextLevelProtoStats->TxOkCts++; /* Success. */
386} /* SkCsGetSendInfo */
387
388
389/******************************************************************************
390 *
391 * SkCsGetReceiveInfo - verify checksum information for a received packet
392 *
393 * Description:
394 * Verify a received frame's checksum. The function returns a status code
395 * reflecting the result of the verification.
396 *
397 * Note:
398 * Before calling this function you have to verify that the frame is
399 * not padded and Checksum1 and Checksum2 are bigger than 1.
400 *
401 * Arguments:
402 * pAc - Pointer to adapter context struct.
403 *
404 * pIpHeader - Pointer to IP header. Must be at least the length in bytes
405 * of the received IP header including any option fields. For UDP packets,
406 * 8 additional bytes are needed to access the UDP checksum.
407 *
408 * Note: The actual length of the IP header is stored in the lower four
409 * bits of the first octet of the IP header as the number of 4-byte words,
410 * so it must be multiplied by four to get the length in bytes. Thus, the
411 * maximum IP header length is 15 * 4 = 60 bytes.
412 *
413 * Checksum1 - The first 16-bit Internet Checksum calculated by the
414 * hardware starting at the offset returned by SkCsSetReceiveFlags().
415 *
416 * Checksum2 - The second 16-bit Internet Checksum calculated by the
417 * hardware starting at the offset returned by SkCsSetReceiveFlags().
418 *
419 * Returns:
420 * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
421 * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
422 * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
423 * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
424 * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
425 * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
426 * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
427 * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
428 * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
429 * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
430 * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
431 *
432 * Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values
433 * returned here can be defined in some header file by the module using CSUM.
434 * In this way, the calling module can assign return values for its own needs,
435 * e.g. by assigning bit flags to the individual protocols.
436 */
437SKCS_STATUS SkCsGetReceiveInfo(
438SK_AC *pAc, /* Adapter context struct. */
439void *pIpHeader, /* IP header. */
440unsigned Checksum1, /* Hardware checksum 1. */
441unsigned Checksum2, /* Hardware checksum 2. */
442int NetNumber) /* Net number */
443{
444 /* Internet Header Version found in IP header. */
445 unsigned InternetHeaderVersion;
446
447 /* Length of the IP header as found in IP header. */
448 unsigned IpHeaderLength;
449
450 /* Length of IP data portion. */
451 unsigned IpDataLength;
452
453 /* IP header checksum. */
454 unsigned IpHeaderChecksum;
455
456 /* IP header options checksum, if any. */
457 unsigned IpOptionsChecksum;
458
459 /* IP data checksum, i.e. TCP/UDP checksum. */
460 unsigned IpDataChecksum;
461
462 /* Next level protocol identifier found in IP header. */
463 unsigned NextLevelProtocol;
464
465 /* The checksum of the "next level protocol", i.e. TCP or UDP. */
466 unsigned long NextLevelProtocolChecksum;
467
468 /* Pointer to next level protocol statistics structure. */
469 SKCS_PROTO_STATS *NextLevelProtoStats;
470
471 /* Temporary variable. */
472 unsigned Tmp;
473
474 Tmp = *(SK_U8 *)
475 SKCS_IDX(pIpHeader, SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH);
476
477 /* Get the Internet Header Version (IHV). */
478 /* Note: The IHV is stored in the upper four bits. */
479
480 InternetHeaderVersion = Tmp >> 4;
481
482 /* Check the Internet Header Version. */
483 /* Note: We currently only support IP version 4. */
484
485 if (InternetHeaderVersion != 4) { /* IPv4? */
486 SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
487 ("Rx: Unknown Internet Header Version %u.\n",
488 InternetHeaderVersion));
489 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxUnableCts++;
490 return (SKCS_STATUS_UNKNOWN_IP_VERSION);
491 }
492
493 /* Get the IP header length (IHL). */
494 /*
495 * Note: The IHL is stored in the lower four bits as the number of
496 * 4-byte words.
497 */
498
499 IpHeaderLength = (Tmp & 0xf) * 4;
500
501 /* Check the IP header length. */
502
503 /* 04-Aug-1998 sw - Really check the IHL? Necessary? */
504
505 if (IpHeaderLength < 5*4) {
506 SK_DBG_MSG(pAc, SK_DBGMOD_CSUM, SK_DBGCAT_ERR | SK_DBGCAT_RX,
507 ("Rx: Invalid IP Header Length %u.\n", IpHeaderLength));
508 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
509 return (SKCS_STATUS_IP_CSUM_ERROR);
510 }
511
512 /* This is an IPv4 frame with a header of valid length. */
513
514 /* Get the IP header and data checksum. */
515
516 IpDataChecksum = Checksum2;
517
518 /*
519 * The IP header checksum is calculated as follows:
520 *
521 * IpHeaderChecksum = Checksum1 - Checksum2
522 */
523
524 SKCS_OC_SUB(IpHeaderChecksum, Checksum1, Checksum2);
525
526 /* Check if any IP header options. */
527
528 if (IpHeaderLength > SKCS_IP_HEADER_SIZE) {
529
530 /* Get the IP options checksum. */
531
532 IpOptionsChecksum = SkCsCalculateChecksum(
533 SKCS_IDX(pIpHeader, SKCS_IP_HEADER_SIZE),
534 IpHeaderLength - SKCS_IP_HEADER_SIZE);
535
536 /* Adjust the IP header and IP data checksums. */
537
538 SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum);
539
540 SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum);
541 }
542
543 /*
544 * Check if the IP header checksum is ok.
545 *
546 * NOTE: We must check the IP header checksum even if the caller just wants
547 * us to check upper-layer checksums, because we cannot do any further
548 * processing of the packet without a valid IP checksum.
549 */
550
551 /* Get the next level protocol identifier. */
552
553 NextLevelProtocol = *(SK_U8 *)
554 SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
555
556 if (IpHeaderChecksum != 0xffff) {
557 pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_IP].RxErrCts++;
558 /* the NDIS tester wants to know the upper level protocol too */
559 if (NextLevelProtocol == SKCS_PROTO_ID_TCP) {
560 return(SKCS_STATUS_IP_CSUM_ERROR_TCP);
561 }
562 else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) {
563 return(SKCS_STATUS_IP_CSUM_ERROR_UDP);
564 }
565 return (SKCS_STATUS_IP_CSUM_ERROR);
566 }
567
568 /*
569 * Check if this is a TCP or UDP frame and if we should calculate the
570 * TCP/UDP pseudo header checksum.
571 *
572 * Also clear all protocol bit flags of protocols not present in the
573 * frame.
574 */
575
576 if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_TCP) != 0 &&
577 NextLevelProtocol == SKCS_PROTO_ID_TCP) {
578 /* TCP/IP frame. */
579 NextLevelProtoStats =
580 &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_TCP];
581 }
582 else if ((pAc->Csum.ReceiveFlags[NetNumber] & SKCS_PROTO_UDP) != 0 &&
583 NextLevelProtocol == SKCS_PROTO_ID_UDP) {
584 /* UDP/IP frame. */
585 NextLevelProtoStats =
586 &pAc->Csum.ProtoStats[NetNumber][SKCS_PROTO_STATS_UDP];
587 }
588 else {
589 /*
590 * Either not a TCP or UDP frame and/or TCP/UDP processing not
591 * specified.
592 */
593 return (SKCS_STATUS_IP_CSUM_OK);
594 }
595
596 /* Check if this is an IP fragment. */
597
598 /*
599 * Note: An IP fragment has a non-zero "Fragment Offset" field and/or
600 * the "More Fragments" bit set. Thus, if both the "Fragment Offset"
601 * and the "More Fragments" are zero, it is *not* a fragment. We can
602 * easily check both at the same time since they are in the same 16-bit
603 * word.
604 */
605
606 if ((*(SK_U16 *)
607 SKCS_IDX(pIpHeader, SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET) &
608 ~SKCS_IP_DONT_FRAGMENT) != 0) {
609 /* IP fragment; ignore all other protocols. */
610 NextLevelProtoStats->RxUnableCts++;
611 return (SKCS_STATUS_IP_FRAGMENT);
612 }
613
614 /*
615 * 08-May-2000 ra
616 *
617 * From RFC 768 (UDP)
618 * If the computed checksum is zero, it is transmitted as all ones (the
619 * equivalent in one's complement arithmetic). An all zero transmitted
620 * checksum value means that the transmitter generated no checksum (for
621 * debugging or for higher level protocols that don't care).
622 */
623
624 if (NextLevelProtocol == SKCS_PROTO_ID_UDP &&
625 *(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) {
626
627 NextLevelProtoStats->RxOkCts++;
628
629 return (SKCS_STATUS_IP_CSUM_OK_NO_UDP);
630 }
631
632 /*
633 * Calculate the TCP/UDP checksum.
634 */
635
636 /* Get total length of IP header and data. */
637
638 IpDataLength =
639 *(SK_U16 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_TOTAL_LENGTH);
640
641 /* Get length of IP data portion. */
642
643 IpDataLength = SKCS_NTOH16(IpDataLength) - IpHeaderLength;
644
645 NextLevelProtocolChecksum =
646
647 /* Calculate the pseudo header checksum. */
648
649 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
650 SKCS_OFS_IP_SOURCE_ADDRESS + 0) +
651 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
652 SKCS_OFS_IP_SOURCE_ADDRESS + 2) +
653 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
654 SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
655 (unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
656 SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
657 (unsigned long) SKCS_HTON16(NextLevelProtocol) +
658 (unsigned long) SKCS_HTON16(IpDataLength) +
659
660 /* Add the TCP/UDP header checksum. */
661
662 (unsigned long) IpDataChecksum;
663
664 /* Add-in any carries. */
665
666 SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
667
668 /* Add-in any new carry. */
669
670 SKCS_OC_ADD(NextLevelProtocolChecksum, NextLevelProtocolChecksum, 0);
671
672 /* Check if the TCP/UDP checksum is ok. */
673
674 if ((unsigned) NextLevelProtocolChecksum == 0xffff) {
675
676 /* TCP/UDP checksum ok. */
677
678 NextLevelProtoStats->RxOkCts++;
679
680 return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
681 SKCS_STATUS_TCP_CSUM_OK : SKCS_STATUS_UDP_CSUM_OK);
682 }
683
684 /* TCP/UDP checksum error. */
685
686 NextLevelProtoStats->RxErrCts++;
687
688 return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
689 SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR);
690} /* SkCsGetReceiveInfo */
691
692
693/******************************************************************************
694 *
695 * SkCsSetReceiveFlags - set checksum receive flags
696 *
697 * Description:
698 * Use this function to set the various receive flags. According to the
699 * protocol flags set by the caller, the start offsets within received
700 * packets of the two hardware checksums are returned. These offsets must
701 * be stored in all receive descriptors.
702 *
703 * Arguments:
704 * pAc - Pointer to adapter context struct.
705 *
706 * ReceiveFlags - Any combination of SK_PROTO_XXX flags of the protocols
707 * for which the caller wants checksum information on received frames.
708 *
709 * pChecksum1Offset - The start offset of the first receive descriptor
710 * hardware checksum to be calculated for received frames is returned
711 * here.
712 *
713 * pChecksum2Offset - The start offset of the second receive descriptor
714 * hardware checksum to be calculated for received frames is returned
715 * here.
716 *
717 * Returns: N/A
718 * Returns the two hardware checksum start offsets.
719 */
720void SkCsSetReceiveFlags(
721SK_AC *pAc, /* Adapter context struct. */
722unsigned ReceiveFlags, /* New receive flags. */
723unsigned *pChecksum1Offset, /* Offset for hardware checksum 1. */
724unsigned *pChecksum2Offset, /* Offset for hardware checksum 2. */
725int NetNumber)
726{
727 /* Save the receive flags. */
728
729 pAc->Csum.ReceiveFlags[NetNumber] = ReceiveFlags;
730
731 /* First checksum start offset is the IP header. */
732 *pChecksum1Offset = SKCS_MAC_HEADER_SIZE;
733
734 /*
735 * Second checksum start offset is the IP data. Note that this may vary
736 * if there are any IP header options in the actual packet.
737 */
738 *pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE;
739} /* SkCsSetReceiveFlags */
740
741#ifndef SK_CS_CALCULATE_CHECKSUM
742
743/******************************************************************************
744 *
745 * SkCsCalculateChecksum - calculate checksum for specified data
746 *
747 * Description:
748 * Calculate and return the 16-bit Internet Checksum for the specified
749 * data.
750 *
751 * Arguments:
752 * pData - Pointer to data for which the checksum shall be calculated.
753 * Note: The pointer should be aligned on a 16-bit boundary.
754 *
755 * Length - Length in bytes of data to checksum.
756 *
757 * Returns:
758 * The 16-bit Internet Checksum for the specified data.
759 *
760 * Note: The checksum is calculated in the machine's natural byte order,
761 * i.e. little vs. big endian. Thus, the resulting checksum is different
762 * for the same input data on little and big endian machines.
763 *
764 * However, when written back to the network packet, the byte order is
765 * always in correct network order.
766 */
767unsigned SkCsCalculateChecksum(
768void *pData, /* Data to checksum. */
769unsigned Length) /* Length of data. */
770{
771 SK_U16 *pU16; /* Pointer to the data as 16-bit words. */
772 unsigned long Checksum; /* Checksum; must be at least 32 bits. */
773
774 /* Sum up all 16-bit words. */
775
776 pU16 = (SK_U16 *) pData;
777 for (Checksum = 0; Length > 1; Length -= 2) {
778 Checksum += *pU16++;
779 }
780
781 /* If this is an odd number of bytes, add-in the last byte. */
782
783 if (Length > 0) {
784#ifdef SK_BIG_ENDIAN
785 /* Add the last byte as the high byte. */
786 Checksum += ((unsigned) *(SK_U8 *) pU16) << 8;
787#else /* !SK_BIG_ENDIAN */
788 /* Add the last byte as the low byte. */
789 Checksum += *(SK_U8 *) pU16;
790#endif /* !SK_BIG_ENDIAN */
791 }
792
793 /* Add-in any carries. */
794
795 SKCS_OC_ADD(Checksum, Checksum, 0);
796
797 /* Add-in any new carry. */
798
799 SKCS_OC_ADD(Checksum, Checksum, 0);
800
801 /* Note: All bits beyond the 16-bit limit are now zero. */
802
803 return ((unsigned) Checksum);
804} /* SkCsCalculateChecksum */
805
806#endif /* SK_CS_CALCULATE_CHECKSUM */
807
808/******************************************************************************
809 *
810 * SkCsEvent - the CSUM event dispatcher
811 *
812 * Description:
813 * This is the event handler for the CSUM module.
814 *
815 * Arguments:
816 * pAc - Pointer to adapter context.
817 *
818 * Ioc - I/O context.
819 *
820 * Event - Event id.
821 *
822 * Param - Event dependent parameter.
823 *
824 * Returns:
825 * The 16-bit Internet Checksum for the specified data.
826 *
827 * Note: The checksum is calculated in the machine's natural byte order,
828 * i.e. little vs. big endian. Thus, the resulting checksum is different
829 * for the same input data on little and big endian machines.
830 *
831 * However, when written back to the network packet, the byte order is
832 * always in correct network order.
833 */
834int SkCsEvent(
835SK_AC *pAc, /* Pointer to adapter context. */
836SK_IOC Ioc, /* I/O context. */
837SK_U32 Event, /* Event id. */
838SK_EVPARA Param) /* Event dependent parameter. */
839{
840 int ProtoIndex;
841 int NetNumber;
842
843 switch (Event) {
844 /*
845 * Clear protocol statistics.
846 *
847 * Param - Protocol index, or -1 for all protocols.
848 * - Net number.
849 */
850 case SK_CSUM_EVENT_CLEAR_PROTO_STATS:
851
852 ProtoIndex = (int)Param.Para32[1];
853 NetNumber = (int)Param.Para32[0];
854 if (ProtoIndex < 0) { /* Clear for all protocols. */
855 if (NetNumber >= 0) {
856 SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][0], 0,
857 sizeof(pAc->Csum.ProtoStats[NetNumber]));
858 }
859 }
860 else { /* Clear for individual protocol. */
861 SK_MEMSET(&pAc->Csum.ProtoStats[NetNumber][ProtoIndex], 0,
862 sizeof(pAc->Csum.ProtoStats[NetNumber][ProtoIndex]));
863 }
864 break;
865 default:
866 break;
867 }
868 return (0); /* Success. */
869} /* SkCsEvent */
870
871#endif /* SK_USE_CSUM */
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
index fb639959292b..b71769ae4603 100644
--- a/drivers/net/sk98lin/skethtool.c
+++ b/drivers/net/sk98lin/skethtool.c
@@ -549,4 +549,6 @@ struct ethtool_ops SkGeEthtoolOps = {
549 .phys_id = locateDevice, 549 .phys_id = locateDevice,
550 .get_pauseparam = getPauseParams, 550 .get_pauseparam = getPauseParams,
551 .set_pauseparam = setPauseParams, 551 .set_pauseparam = setPauseParams,
552 .get_link = ethtool_op_get_link,
553 .get_perm_addr = ethtool_op_get_perm_addr,
552}; 554};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 08906ef3ff7e..107c5d97546c 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -101,7 +101,6 @@
101 * "h/skgeinit.h" 101 * "h/skgeinit.h"
102 * "h/skaddr.h" 102 * "h/skaddr.h"
103 * "h/skgesirq.h" 103 * "h/skgesirq.h"
104 * "h/skcsum.h"
105 * "h/skrlmt.h" 104 * "h/skrlmt.h"
106 * 105 *
107 ******************************************************************************/ 106 ******************************************************************************/
@@ -113,6 +112,7 @@
113#include <linux/init.h> 112#include <linux/init.h>
114#include <linux/proc_fs.h> 113#include <linux/proc_fs.h>
115#include <linux/dma-mapping.h> 114#include <linux/dma-mapping.h>
115#include <linux/ip.h>
116 116
117#include "h/skdrv1st.h" 117#include "h/skdrv1st.h"
118#include "h/skdrv2nd.h" 118#include "h/skdrv2nd.h"
@@ -622,11 +622,6 @@ SK_BOOL DualNet;
622 return(-EAGAIN); 622 return(-EAGAIN);
623 } 623 }
624 624
625 SkCsSetReceiveFlags(pAC,
626 SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP,
627 &pAC->CsOfs1, &pAC->CsOfs2, 0);
628 pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
629
630 BoardInitMem(pAC); 625 BoardInitMem(pAC);
631 /* tschilling: New common function with minimum size check. */ 626 /* tschilling: New common function with minimum size check. */
632 DualNet = SK_FALSE; 627 DualNet = SK_FALSE;
@@ -844,7 +839,7 @@ uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */
844 /* set the pointers right */ 839 /* set the pointers right */
845 pDescr->VNextRxd = VNextDescr & 0xffffffffULL; 840 pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
846 pDescr->pNextRxd = pNextDescr; 841 pDescr->pNextRxd = pNextDescr;
847 pDescr->TcpSumStarts = pAC->CsOfs; 842 pDescr->TcpSumStarts = 0;
848 843
849 /* advance one step */ 844 /* advance one step */
850 pPrevDescr = pDescr; 845 pPrevDescr = pDescr;
@@ -1526,8 +1521,6 @@ struct sk_buff *pMessage) /* pointer to send-message */
1526 TXD *pOldTxd; 1521 TXD *pOldTxd;
1527 unsigned long Flags; 1522 unsigned long Flags;
1528 SK_U64 PhysAddr; 1523 SK_U64 PhysAddr;
1529 int Protocol;
1530 int IpHeaderLength;
1531 int BytesSend = pMessage->len; 1524 int BytesSend = pMessage->len;
1532 1525
1533 SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); 1526 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 */
1600 pTxd->pMBuf = pMessage; 1593 pTxd->pMBuf = pMessage;
1601 1594
1602 if (pMessage->ip_summed == CHECKSUM_HW) { 1595 if (pMessage->ip_summed == CHECKSUM_HW) {
1603 Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); 1596 u16 hdrlen = pMessage->h.raw - pMessage->data;
1604 if ((Protocol == C_PROTO_ID_UDP) && 1597 u16 offset = hdrlen + pMessage->csum;
1598
1599 if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
1605 (pAC->GIni.GIChipRev == 0) && 1600 (pAC->GIni.GIChipRev == 0) &&
1606 (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { 1601 (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
1607 pTxd->TBControl = BMU_TCP_CHECK; 1602 pTxd->TBControl = BMU_TCP_CHECK;
@@ -1609,14 +1604,9 @@ struct sk_buff *pMessage) /* pointer to send-message */
1609 pTxd->TBControl = BMU_UDP_CHECK; 1604 pTxd->TBControl = BMU_UDP_CHECK;
1610 } 1605 }
1611 1606
1612 IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER]; 1607 pTxd->TcpSumOfs = 0;
1613 IpHeaderLength = (IpHeaderLength & 0xf) * 4; 1608 pTxd->TcpSumSt = hdrlen;
1614 pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */ 1609 pTxd->TcpSumWr = offset;
1615 pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength +
1616 (Protocol == C_PROTO_ID_UDP ?
1617 C_OFFSET_UDPHEADER_UDPCS :
1618 C_OFFSET_TCPHEADER_TCPCS);
1619 pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength;
1620 1610
1621 pTxd->TBControl |= BMU_OWN | BMU_STF | 1611 pTxd->TBControl |= BMU_OWN | BMU_STF |
1622 BMU_SW | BMU_EOF | 1612 BMU_SW | BMU_EOF |
@@ -1679,11 +1669,10 @@ struct sk_buff *pMessage) /* pointer to send-message */
1679 TXD *pTxdLst; 1669 TXD *pTxdLst;
1680 int CurrFrag; 1670 int CurrFrag;
1681 int BytesSend; 1671 int BytesSend;
1682 int IpHeaderLength;
1683 int Protocol;
1684 skb_frag_t *sk_frag; 1672 skb_frag_t *sk_frag;
1685 SK_U64 PhysAddr; 1673 SK_U64 PhysAddr;
1686 unsigned long Flags; 1674 unsigned long Flags;
1675 SK_U32 Control;
1687 1676
1688 spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); 1677 spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
1689#ifndef USE_TX_COMPLETE 1678#ifndef USE_TX_COMPLETE
@@ -1706,7 +1695,6 @@ struct sk_buff *pMessage) /* pointer to send-message */
1706 pTxdFst = pTxd; 1695 pTxdFst = pTxd;
1707 pTxdLst = pTxd; 1696 pTxdLst = pTxd;
1708 BytesSend = 0; 1697 BytesSend = 0;
1709 Protocol = 0;
1710 1698
1711 /* 1699 /*
1712 ** Map the first fragment (header) into the DMA-space 1700 ** Map the first fragment (header) into the DMA-space
@@ -1724,32 +1712,31 @@ struct sk_buff *pMessage) /* pointer to send-message */
1724 ** Does the HW need to evaluate checksum for TCP or UDP packets? 1712 ** Does the HW need to evaluate checksum for TCP or UDP packets?
1725 */ 1713 */
1726 if (pMessage->ip_summed == CHECKSUM_HW) { 1714 if (pMessage->ip_summed == CHECKSUM_HW) {
1727 pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage); 1715 u16 hdrlen = pMessage->h.raw - pMessage->data;
1716 u16 offset = hdrlen + pMessage->csum;
1717
1718 Control = BMU_STFWD;
1719
1728 /* 1720 /*
1729 ** We have to use the opcode for tcp here, because the 1721 ** We have to use the opcode for tcp here, because the
1730 ** opcode for udp is not working in the hardware yet 1722 ** opcode for udp is not working in the hardware yet
1731 ** (Revision 2.0) 1723 ** (Revision 2.0)
1732 */ 1724 */
1733 Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); 1725 if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) &&
1734 if ((Protocol == C_PROTO_ID_UDP) &&
1735 (pAC->GIni.GIChipRev == 0) && 1726 (pAC->GIni.GIChipRev == 0) &&
1736 (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { 1727 (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
1737 pTxd->TBControl |= BMU_TCP_CHECK; 1728 Control |= BMU_TCP_CHECK;
1738 } else { 1729 } else {
1739 pTxd->TBControl |= BMU_UDP_CHECK; 1730 Control |= BMU_UDP_CHECK;
1740 } 1731 }
1741 1732
1742 IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4; 1733 pTxd->TcpSumOfs = 0;
1743 pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ 1734 pTxd->TcpSumSt = hdrlen;
1744 pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength + 1735 pTxd->TcpSumWr = offset;
1745 (Protocol == C_PROTO_ID_UDP ? 1736 } else
1746 C_OFFSET_UDPHEADER_UDPCS : 1737 Control = BMU_CHECK | BMU_SW;
1747 C_OFFSET_TCPHEADER_TCPCS); 1738
1748 pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength; 1739 pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
1749 } else {
1750 pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF |
1751 skb_headlen(pMessage);
1752 }
1753 1740
1754 pTxd = pTxd->pNextTxd; 1741 pTxd = pTxd->pNextTxd;
1755 pTxPort->TxdRingFree--; 1742 pTxPort->TxdRingFree--;
@@ -1773,40 +1760,18 @@ struct sk_buff *pMessage) /* pointer to send-message */
1773 pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); 1760 pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
1774 pTxd->pMBuf = pMessage; 1761 pTxd->pMBuf = pMessage;
1775 1762
1776 /* 1763 pTxd->TBControl = Control | BMU_OWN | sk_frag->size;;
1777 ** Does the HW need to evaluate checksum for TCP or UDP packets?
1778 */
1779 if (pMessage->ip_summed == CHECKSUM_HW) {
1780 pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD;
1781 /*
1782 ** We have to use the opcode for tcp here because the
1783 ** opcode for udp is not working in the hardware yet
1784 ** (revision 2.0)
1785 */
1786 if ((Protocol == C_PROTO_ID_UDP) &&
1787 (pAC->GIni.GIChipRev == 0) &&
1788 (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
1789 pTxd->TBControl |= BMU_TCP_CHECK;
1790 } else {
1791 pTxd->TBControl |= BMU_UDP_CHECK;
1792 }
1793 } else {
1794 pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN;
1795 }
1796 1764
1797 /* 1765 /*
1798 ** Do we have the last fragment? 1766 ** Do we have the last fragment?
1799 */ 1767 */
1800 if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) { 1768 if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
1801#ifdef USE_TX_COMPLETE 1769#ifdef USE_TX_COMPLETE
1802 pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size; 1770 pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
1803#else 1771#else
1804 pTxd->TBControl |= BMU_EOF | sk_frag->size; 1772 pTxd->TBControl |= BMU_EOF;
1805#endif 1773#endif
1806 pTxdFst->TBControl |= BMU_OWN | BMU_SW; 1774 pTxdFst->TBControl |= BMU_OWN | BMU_SW;
1807
1808 } else {
1809 pTxd->TBControl |= sk_frag->size;
1810 } 1775 }
1811 pTxdLst = pTxd; 1776 pTxdLst = pTxd;
1812 pTxd = pTxd->pNextTxd; 1777 pTxd = pTxd->pNextTxd;
@@ -2053,7 +2018,6 @@ SK_U32 Control; /* control field of descriptor */
2053struct sk_buff *pMsg; /* pointer to message holding frame */ 2018struct sk_buff *pMsg; /* pointer to message holding frame */
2054struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ 2019struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
2055int FrameLength; /* total length of received frame */ 2020int FrameLength; /* total length of received frame */
2056int IpFrameLength;
2057SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ 2021SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
2058SK_EVPARA EvPara; /* an event parameter union */ 2022SK_EVPARA EvPara; /* an event parameter union */
2059unsigned long Flags; /* for spin lock */ 2023unsigned long Flags; /* for spin lock */
@@ -2066,10 +2030,6 @@ SK_BOOL IsMc;
2066SK_BOOL IsBadFrame; /* Bad frame */ 2030SK_BOOL IsBadFrame; /* Bad frame */
2067 2031
2068SK_U32 FrameStat; 2032SK_U32 FrameStat;
2069unsigned short Csum1;
2070unsigned short Csum2;
2071unsigned short Type;
2072int Result;
2073SK_U64 PhysAddr; 2033SK_U64 PhysAddr;
2074 2034
2075rx_start: 2035rx_start:
@@ -2198,8 +2158,8 @@ rx_start:
2198 (dma_addr_t) PhysAddr, 2158 (dma_addr_t) PhysAddr,
2199 FrameLength, 2159 FrameLength,
2200 PCI_DMA_FROMDEVICE); 2160 PCI_DMA_FROMDEVICE);
2201 eth_copy_and_sum(pNewMsg, pMsg->data, 2161 memcpy(pNewMsg->data, pMsg, FrameLength);
2202 FrameLength, 0); 2162
2203 pci_dma_sync_single_for_device(pAC->PciDev, 2163 pci_dma_sync_single_for_device(pAC->PciDev,
2204 (dma_addr_t) PhysAddr, 2164 (dma_addr_t) PhysAddr,
2205 FrameLength, 2165 FrameLength,
@@ -2227,69 +2187,16 @@ rx_start:
2227 2187
2228 /* set length in message */ 2188 /* set length in message */
2229 skb_put(pMsg, FrameLength); 2189 skb_put(pMsg, FrameLength);
2230 /* hardware checksum */ 2190 } /* frame > SK_COPY_TRESHOLD */
2231 Type = ntohs(*((short*)&pMsg->data[12]));
2232 2191
2233#ifdef USE_SK_RX_CHECKSUM 2192#ifdef USE_SK_RX_CHECKSUM
2234 if (Type == 0x800) { 2193 pMsg->csum = pRxd->TcpSums;
2235 Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); 2194 pMsg->ip_summed = CHECKSUM_HW;
2236 Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
2237 IpFrameLength = (int) ntohs((unsigned short)
2238 ((unsigned short *) pMsg->data)[8]);
2239
2240 /*
2241 * Test: If frame is padded, a check is not possible!
2242 * Frame not padded? Length difference must be 14 (0xe)!
2243 */
2244 if ((FrameLength - IpFrameLength) != 0xe) {
2245 /* Frame padded => TCP offload not possible! */
2246 pMsg->ip_summed = CHECKSUM_NONE;
2247 } else {
2248 /* Frame not padded => TCP offload! */
2249 if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
2250 (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
2251 (pAC->ChipsetType)) {
2252 Result = SkCsGetReceiveInfo(pAC,
2253 &pMsg->data[14],
2254 Csum1, Csum2, pRxPort->PortIndex);
2255 if (Result ==
2256 SKCS_STATUS_IP_FRAGMENT ||
2257 Result ==
2258 SKCS_STATUS_IP_CSUM_OK ||
2259 Result ==
2260 SKCS_STATUS_TCP_CSUM_OK ||
2261 Result ==
2262 SKCS_STATUS_UDP_CSUM_OK) {
2263 pMsg->ip_summed =
2264 CHECKSUM_UNNECESSARY;
2265 }
2266 else if (Result ==
2267 SKCS_STATUS_TCP_CSUM_ERROR ||
2268 Result ==
2269 SKCS_STATUS_UDP_CSUM_ERROR ||
2270 Result ==
2271 SKCS_STATUS_IP_CSUM_ERROR_UDP ||
2272 Result ==
2273 SKCS_STATUS_IP_CSUM_ERROR_TCP ||
2274 Result ==
2275 SKCS_STATUS_IP_CSUM_ERROR ) {
2276 /* HW Checksum error */
2277 SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
2278 SK_DBGCAT_DRV_RX_PROGRESS,
2279 ("skge: CRC error. Frame dropped!\n"));
2280 goto rx_failed;
2281 } else {
2282 pMsg->ip_summed =
2283 CHECKSUM_NONE;
2284 }
2285 }/* checksumControl calculation valid */
2286 } /* Frame length check */
2287 } /* IP frame */
2288#else 2195#else
2289 pMsg->ip_summed = CHECKSUM_NONE; 2196 pMsg->ip_summed = CHECKSUM_NONE;
2290#endif 2197#endif
2291 } /* frame > SK_COPY_TRESHOLD */ 2198
2292 2199
2293 SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); 2200 SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
2294 ForRlmt = SK_RLMT_RX_PROTOCOL; 2201 ForRlmt = SK_RLMT_RX_PROTOCOL;
2295#if 0 2202#if 0
@@ -4945,7 +4852,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
4945 dev->irq = pdev->irq; 4852 dev->irq = pdev->irq;
4946 error = SkGeInitPCI(pAC); 4853 error = SkGeInitPCI(pAC);
4947 if (error) { 4854 if (error) {
4948 printk("SKGE: PCI setup failed: %i\n", error); 4855 printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
4949 goto out_free_netdev; 4856 goto out_free_netdev;
4950 } 4857 }
4951 4858
@@ -4981,7 +4888,7 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
4981 4888
4982 /* Register net device */ 4889 /* Register net device */
4983 if (register_netdev(dev)) { 4890 if (register_netdev(dev)) {
4984 printk(KERN_ERR "SKGE: Could not register device.\n"); 4891 printk(KERN_ERR "sk98lin: Could not register device.\n");
4985 goto out_free_resources; 4892 goto out_free_resources;
4986 } 4893 }
4987 4894
@@ -5000,8 +4907,8 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
5000 4907
5001 SkGeYellowLED(pAC, pAC->IoBase, 1); 4908 SkGeYellowLED(pAC, pAC->IoBase, 1);
5002 4909
5003
5004 memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); 4910 memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
4911 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
5005 4912
5006 SkGeProcCreate(dev); 4913 SkGeProcCreate(dev);
5007 4914
@@ -5047,13 +4954,14 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
5047#endif 4954#endif
5048 4955
5049 if (register_netdev(dev)) { 4956 if (register_netdev(dev)) {
5050 printk(KERN_ERR "SKGE: Could not register device.\n"); 4957 printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n");
5051 free_netdev(dev); 4958 free_netdev(dev);
5052 pAC->dev[1] = pAC->dev[0]; 4959 pAC->dev[1] = pAC->dev[0];
5053 } else { 4960 } else {
5054 SkGeProcCreate(dev); 4961 SkGeProcCreate(dev);
5055 memcpy(&dev->dev_addr, 4962 memcpy(&dev->dev_addr,
5056 &pAC->Addr.Net[1].CurrentMacAddress, 6); 4963 &pAC->Addr.Net[1].CurrentMacAddress, 6);
4964 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
5057 4965
5058 printk("%s: %s\n", dev->name, pAC->DeviceStr); 4966 printk("%s: %s\n", dev->name, pAC->DeviceStr);
5059 printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); 4967 printk(" PrefPort:B RlmtMode:Dual Check Link State\n");