1/*******************************************************************************
2
3
4  Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
5
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the Free
8  Software Foundation; either version 2 of the License, or (at your option)
9  any later version.
10
11  This program is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  more details.
15
16  You should have received a copy of the GNU General Public License along with
17  this program; if not, write to the Free Software Foundation, Inc., 59
18  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20  The full GNU General Public License is included in this distribution in the
21  file called LICENSE.
22
23  Contact Information:
24  Linux NICS <linux.nics@intel.com>
25  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26*******************************************************************************/
27
28/**********************************************************************
29*                                                                     *
30* INTEL CORPORATION                                                   *
31*                                                                     *
32* This software is supplied under the terms of the license included   *
33* above.  All use of this driver must be in accordance with the terms *
34* of that license.                                                    *
35*                                                                     *
36* Module Name:  e100_config.c                                         *
37*                                                                     *
38* Abstract:     Functions for configuring the network adapter.        *
39*                                                                     *
40* Environment:  This file is intended to be specific to the Linux     *
41*               operating system.                                     *
42*                                                                     *
43**********************************************************************/
44#include "e100_config.h"
45
46static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable);
47
48static const u8 def_config[] = {
49	CB_CFIG_BYTE_COUNT,
50	0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01,
51	0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00,
52	0x40, 0xf2, 0x80, 0x3f, 0x05
53};
54
55/**
56 * e100_config_init_82557 - config the 82557 adapter
57 * @bdp: atapter's private data struct
58 *
59 * This routine will initialize the 82557 configure block.
60 * All other init functions will only set values that are
61 * different from the 82557 default.
62 */
63static void __devinit
64e100_config_init_82557(struct e100_private *bdp)
65{
66	/* initialize config block */
67	memcpy(bdp->config, def_config, sizeof (def_config));
68	bdp->config[0] = CB_CFIG_BYTE_COUNT;	/* just in case */
69
70	e100_config_ifs(bdp);
71
72	/*
73	 * Enable extended statistical counters (82558 and up) and TCO counters
74	 * (82559 and up) and set the statistical counters' mode in bdp
75	 *
76	 *  stat. mode      |    TCO stat. bit (2)  |  Extended stat. bit (5)
77	 * ------------------------------------------------------------------
78	 *  Basic (557)     |       0               |         1
79	 * ------------------------------------------------------------------
80	 *  Extended (558)  |       0               |         0
81	 * ------------------------------------------------------------------
82	 *  TCO (559)       |       1               |         1
83	 * ------------------------------------------------------------------
84	 *  Reserved        |       1               |         0
85	 * ------------------------------------------------------------------
86	 */
87	bdp->config[6] &= ~CB_CFIG_TCO_STAT;
88	bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
89	bdp->stat_mode = E100_BASIC_STATS;
90
91	/* Setup for MII or 503 operation.  The CRS+CDT bit should only be set */
92	/* when operating in 503 mode. */
93	if (bdp->phy_addr == 32) {
94		bdp->config[8] &= ~CB_CFIG_503_MII;
95		bdp->config[15] |= CB_CFIG_CRS_OR_CDT;
96	} else {
97		bdp->config[8] |= CB_CFIG_503_MII;
98		bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT;
99	}
100
101	e100_config_fc(bdp);
102	e100_config_force_dplx(bdp);
103	e100_config_promisc(bdp, false);
104	e100_config_mulcast_enbl(bdp, false);
105}
106
107static void __devinit
108e100_config_init_82558(struct e100_private *bdp)
109{
110	/* MWI enable. This should be turned on only if the adapter is a 82558/9
111	 * and if the PCI command reg. has enabled the MWI bit. */
112	bdp->config[3] |= CB_CFIG_MWI_EN;
113
114	bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS;
115
116	if (bdp->rev_id >= D101MA_REV_ID) {
117		/* this is 82559 and up - enable TCO counters */
118		bdp->config[6] |= CB_CFIG_TCO_STAT;
119		bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
120		bdp->stat_mode = E100_TCO_STATS;
121
122		if ((bdp->rev_id < D102_REV_ID) &&
123		    (bdp->params.b_params & PRM_XSUMRX) &&
124		    (bdp->pdev->device != 0x1209)) {
125
126			bdp->flags |= DF_CSUM_OFFLOAD;
127			bdp->config[9] |= 1;
128		}
129	} else {
130		/* this is 82558 */
131		bdp->config[6] &= ~CB_CFIG_TCO_STAT;
132		bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS;
133		bdp->stat_mode = E100_EXTENDED_STATS;
134	}
135
136	e100_config_long_rx(bdp, true);
137}
138
139static void __devinit
140e100_config_init_82550(struct e100_private *bdp)
141{
142	/* The D102 chip allows for 32 config bytes.  This value is
143	 * supposed to be in Byte 0.  Just add the extra bytes to
144	 * what was already setup in the block. */
145	bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
146
147	/* now we need to enable the extended RFD.  When this is
148	 * enabled, the immediated receive data buffer starts at offset
149	 * 32 from the RFD base address, instead of at offset 16. */
150	bdp->config[7] |= CB_CFIG_EXTENDED_RFD;
151
152	/* put the chip into D102 receive mode.  This is neccessary
153	 * for any parsing and offloading features. */
154	bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE;
155
156	/* set the flag if checksum offloading was enabled */
157	if (bdp->params.b_params & PRM_XSUMRX) {
158		bdp->flags |= DF_CSUM_OFFLOAD;
159	}
160}
161
162/* Initialize the adapter's configure block */
163void __devinit
164e100_config_init(struct e100_private *bdp)
165{
166	e100_config_init_82557(bdp);
167
168	if (bdp->flags & IS_BACHELOR)
169		e100_config_init_82558(bdp);
170
171	if (bdp->rev_id >= D102_REV_ID)
172		e100_config_init_82550(bdp);
173}
174
175/**
176 * e100_force_config - force a configure command
177 * @bdp: atapter's private data struct
178 *
179 * This routine will force a configure command to the adapter.
180 * The command will be executed in polled mode as interrupts
181 * are _disabled_ at this time.
182 *
183 * Returns:
184 *      true: if the configure command was successfully issued and completed
185 *      false: otherwise
186 */
187unsigned char
188e100_force_config(struct e100_private *bdp)
189{
190	spin_lock_bh(&(bdp->config_lock));
191
192	bdp->config[0] = CB_CFIG_BYTE_COUNT;
193	if (bdp->rev_id >= D102_REV_ID) {
194		/* The D102 chip allows for 32 config bytes.  This value is
195		   supposed to be in Byte 0.  Just add the extra bytes to
196		   what was already setup in the block. */
197		bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
198	}
199
200	spin_unlock_bh(&(bdp->config_lock));
201
202	// although we call config outside the lock, there is no
203	// race condition because config byte count has maximum value
204	return e100_config(bdp);
205}
206
207/**
208 * e100_config - issue a configure command
209 * @bdp: atapter's private data struct
210 *
211 * This routine will issue a configure command to the 82557.
212 * This command will be executed in polled mode as interrupts
213 * are _disabled_ at this time.
214 *
215 * Returns:
216 *      true: if the configure command was successfully issued and completed
217 *      false: otherwise
218 */
219unsigned char
220e100_config(struct e100_private *bdp)
221{
222	cb_header_t *pntcb_hdr;
223	unsigned char res = true;
224	nxmit_cb_entry_t *cmd;
225
226	if (bdp->config[0] == 0) {
227		goto exit;
228	}
229
230	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
231		res = false;
232		goto exit;
233	}
234
235	pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
236	pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE);
237
238	spin_lock_bh(&bdp->config_lock);
239
240	if (bdp->config[0] < CB_CFIG_MIN_PARAMS) {
241		bdp->config[0] = CB_CFIG_MIN_PARAMS;
242	}
243
244	/* Copy the device's config block to the device's memory */
245	memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config,
246	       bdp->config[0]);
247	/* reset number of bytes to config next time */
248	bdp->config[0] = 0;
249
250	spin_unlock_bh(&bdp->config_lock);
251
252	res = e100_exec_non_cu_cmd(bdp, cmd);
253
254exit:
255	if (netif_running(bdp->device))
256		netif_wake_queue(bdp->device);
257	return res;
258}
259
260/**
261 * e100_config_fc - config flow-control state
262 * @bdp: adapter's private data struct
263 *
264 * This routine will enable or disable flow control support in the adapter's
265 * config block. Flow control will be enable only if requested using the command
266 * line option, and if the link is flow-contorl capable (both us and the link
267 * partner). But, if link partner is capable of autoneg, but not capable of
268 * flow control, received PAUSE	frames are still honored.
269 */
270void
271e100_config_fc(struct e100_private *bdp)
272{
273	unsigned char enable = false;
274	/* 82557 doesn't support fc. Don't touch this option */
275	if (!(bdp->flags & IS_BACHELOR))
276		return;
277
278	/* Enable fc if requested and if the link supports it */
279	if ((bdp->params.b_params & PRM_FC) && (bdp->flags &
280		(DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) {
281		enable = true;
282	}
283
284	spin_lock_bh(&(bdp->config_lock));
285
286	if (enable) {
287		if (bdp->flags & DF_LINK_FC_TX_ONLY) {
288			/* If link partner is capable of autoneg, but  */
289			/* not capable of flow control, Received PAUSE */
290			/* frames are still honored, i.e.,             */
291			/* transmitted frames would be paused by       */
292			/* incoming PAUSE frames                       */
293			bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
294			bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
295			bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART);
296			bdp->config[19] |= CB_CFIG_FC_REJECT;
297			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
298		} else {
299			bdp->config[16] = DFLT_FC_DELAY_LSB;
300			bdp->config[17] = DFLT_FC_DELAY_MSB;
301			bdp->config[19] |= CB_CFIG_FC_OPTS;
302			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
303		}
304	} else {
305		bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
306		bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
307		bdp->config[19] &= ~CB_CFIG_FC_OPTS;
308		bdp->config[19] |= CB_CFIG_TX_FC_DIS;
309	}
310	E100_CONFIG(bdp, 19);
311	spin_unlock_bh(&(bdp->config_lock));
312
313	return;
314}
315
316/**
317 * e100_config_promisc - configure promiscuous mode
318 * @bdp: atapter's private data struct
319 * @enable: should we enable this option or not
320 *
321 * This routine will enable or disable promiscuous mode
322 * in the adapter's config block.
323 */
324void
325e100_config_promisc(struct e100_private *bdp, unsigned char enable)
326{
327	spin_lock_bh(&(bdp->config_lock));
328
329	/* if in promiscuous mode, save bad frames */
330	if (enable) {
331
332		if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) {
333			bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES;
334			E100_CONFIG(bdp, 6);
335		}
336
337		if (bdp->config[7] & (u8) BIT_0) {
338			bdp->config[7] &= (u8) (~BIT_0);
339			E100_CONFIG(bdp, 7);
340		}
341
342		if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) {
343			bdp->config[15] |= CB_CFIG_PROMISCUOUS;
344			E100_CONFIG(bdp, 15);
345		}
346
347	} else {		/* not in promiscuous mode */
348
349		if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) {
350			bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES;
351			E100_CONFIG(bdp, 6);
352		}
353
354		if (!(bdp->config[7] & (u8) BIT_0)) {
355			bdp->config[7] |= (u8) (BIT_0);
356			E100_CONFIG(bdp, 7);
357		}
358
359		if (bdp->config[15] & CB_CFIG_PROMISCUOUS) {
360			bdp->config[15] &= ~CB_CFIG_PROMISCUOUS;
361			E100_CONFIG(bdp, 15);
362		}
363	}
364
365	spin_unlock_bh(&(bdp->config_lock));
366}
367
368/**
369 * e100_config_mulcast_enbl - configure allmulti mode
370 * @bdp: atapter's private data struct
371 * @enable: should we enable this option or not
372 *
373 * This routine will enable or disable reception of all multicast packets
374 * in the adapter's config block.
375 */
376void
377e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable)
378{
379	spin_lock_bh(&(bdp->config_lock));
380
381	/* this flag is used to enable receiving all multicast packet */
382	if (enable) {
383		if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) {
384			bdp->config[21] |= CB_CFIG_MULTICAST_ALL;
385			E100_CONFIG(bdp, 21);
386		}
387
388	} else {
389		if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) {
390			bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL;
391			E100_CONFIG(bdp, 21);
392		}
393	}
394
395	spin_unlock_bh(&(bdp->config_lock));
396}
397
398/**
399 * e100_config_ifs - configure the IFS parameter
400 * @bdp: atapter's private data struct
401 *
402 * This routine will configure the adaptive IFS value
403 * in the adapter's config block. IFS values are only
404 * relevant in half duplex, so set to 0 in full duplex.
405 */
406void
407e100_config_ifs(struct e100_private *bdp)
408{
409	u8 value = 0;
410
411	spin_lock_bh(&(bdp->config_lock));
412
413	/* IFS value is only needed to be specified at half-duplex mode */
414	if (bdp->cur_dplx_mode == HALF_DUPLEX) {
415		value = (u8) bdp->ifs_value;
416	}
417
418	if (bdp->config[2] != value) {
419		bdp->config[2] = value;
420		E100_CONFIG(bdp, 2);
421	}
422
423	spin_unlock_bh(&(bdp->config_lock));
424}
425
426/**
427 * e100_config_force_dplx - configure the forced full duplex mode
428 * @bdp: atapter's private data struct
429 *
430 * This routine will enable or disable force full duplex
431 * in the adapter's config block. If the PHY is 503, and
432 * the duplex is full, consider the adapter forced.
433 */
434void
435e100_config_force_dplx(struct e100_private *bdp)
436{
437	spin_lock_bh(&(bdp->config_lock));
438
439	/* We must force full duplex on if we are using PHY 0, and we are */
440	/* supposed to run in FDX mode. We do this because the e100 has only */
441	/* one FDX# input pin, and that pin will be connected to PHY 1. */
442	/* Changed the 'if' condition below to fix performance problem * at 10
443	 * full. The Phy was getting forced to full duplex while the MAC * was
444	 * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. *
445	 * This is how the condition was, initially. * This has been changed so
446	 * that the MAC gets forced to full duplex * simply if the user has
447	 * forced full duplex. * * if (( bdp->phy_addr == 0 ) && (
448	 * bdp->cur_dplx_mode == 2 )) */
449	/* The rest of the fix is in the PhyDetect code. */
450	if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) ||
451	    (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) ||
452	    ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) {
453		if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) {
454			bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX;
455			E100_CONFIG(bdp, 19);
456		}
457
458	} else {
459		if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) {
460			bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX);
461			E100_CONFIG(bdp, 19);
462		}
463	}
464
465	spin_unlock_bh(&(bdp->config_lock));
466}
467
468/**
469 * e100_config_long_rx
470 * @bdp: atapter's private data struct
471 * @enable: should we enable this option or not
472 *
473 * This routine will enable or disable reception of larger packets.
474 * This is needed by VLAN implementations.
475 */
476static void
477e100_config_long_rx(struct e100_private *bdp, unsigned char enable)
478{
479	if (enable) {
480		if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
481			bdp->config[18] |= CB_CFIG_LONG_RX_OK;
482			E100_CONFIG(bdp, 18);
483		}
484
485	} else {
486		if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
487			bdp->config[18] &= ~CB_CFIG_LONG_RX_OK;
488			E100_CONFIG(bdp, 18);
489		}
490	}
491}
492
493/**
494 * e100_config_wol
495 * @bdp: atapter's private data struct
496 *
497 * This sets configuration options for Wake On LAN functionality (WOL) in the
498 * config record. WOL options are retrieved from wolinfo_wolopts in @bdp
499 */
500void
501e100_config_wol(struct e100_private *bdp)
502{
503	spin_lock_bh(&(bdp->config_lock));
504
505	if (bdp->wolopts & WAKE_PHY) {
506		bdp->config[9] |= CB_LINK_STATUS_WOL;
507		E100_CONFIG(bdp, 9);
508	}
509
510	if (!(bdp->wolopts & WAKE_MAGIC)) {
511		bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE;
512		E100_CONFIG(bdp, 19);
513	}
514
515	spin_unlock_bh(&(bdp->config_lock));
516}
517
518/**
519 * e100_config_loopback_mode
520 * @bdp: atapter's private data struct
521 * @mode: loopback mode(phy/mac/none)
522 *
523 */
524unsigned char
525e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
526{
527	unsigned char bc_changed = false;
528	u8 config_byte;
529
530	spin_lock_bh(&(bdp->config_lock));
531
532	switch (mode) {
533	case NO_LOOPBACK:
534		config_byte = CB_CFIG_LOOPBACK_NORMAL;
535		break;
536	case MAC_LOOPBACK:
537		config_byte = CB_CFIG_LOOPBACK_INTERNAL;
538		break;
539	case PHY_LOOPBACK:
540		config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
541		break;
542	default:
543		printk(KERN_NOTICE "e100: e100_config_loopback_mode: "
544		       "Invalid argument 'mode': %d\n", mode);
545		goto exit;
546	}
547
548	if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
549
550		bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
551		bdp->config[10] |= config_byte;
552		E100_CONFIG(bdp, 10);
553		bc_changed = true;
554	}
555
556exit:
557	spin_unlock_bh(&(bdp->config_lock));
558	return bc_changed;
559}
560unsigned char
561e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
562{
563        unsigned char bc_changed = false;
564
565        spin_lock_bh(&(bdp->config_lock));
566
567        if (enable) {
568                if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
569
570                        bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
571                        E100_CONFIG(bdp, 6);
572                        bc_changed = true;
573                }
574
575        } else {
576                if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
577
578                        bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
579                        E100_CONFIG(bdp, 6);
580                        bc_changed = true;
581                }
582        }
583        spin_unlock_bh(&(bdp->config_lock));
584
585        return bc_changed;
586}
587unsigned char
588e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
589{
590        unsigned char bc_changed = false;
591
592        spin_lock_bh(&(bdp->config_lock));
593
594        if (enable) {
595                if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
596
597                        bdp->config[7] |= CB_CFIG_DYNTBD_EN;
598                        E100_CONFIG(bdp, 7);
599                        bc_changed = true;
600                }
601
602        } else {
603                if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
604
605                        bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
606                        E100_CONFIG(bdp, 7);
607                        bc_changed = true;
608                }
609        }
610        spin_unlock_bh(&(bdp->config_lock));
611
612        return bc_changed;
613}
614
615