1/*
2 * Copyright (C) 2003 - 2006 NetXen, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA  02111-1307, USA.
19 *
20 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
22 *
23 * Contact Information:
24 *    info@netxen.com
25 * NetXen,
26 * 3965 Freedom Circle, Fourth floor,
27 * Santa Clara, CA 95054
28 *
29 *
30 * Provides access to the Network Interface Unit h/w block.
31 *
32 */
33
34#include "netxen_nic.h"
35
36#define NETXEN_GB_MAC_SOFT_RESET	0x80000000
37#define NETXEN_GB_MAC_RESET_PROT_BLK   0x000F0000
38#define NETXEN_GB_MAC_ENABLE_TX_RX     0x00000005
39#define NETXEN_GB_MAC_PAUSED_FRMS      0x00000020
40
41static long phy_lock_timeout = 100000000;
42
43static inline int phy_lock(struct netxen_adapter *adapter)
44{
45	int i;
46	int done = 0, timeout = 0;
47
48	while (!done) {
49		done =
50		    readl(pci_base_offset
51			  (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
52		if (done == 1)
53			break;
54		if (timeout >= phy_lock_timeout) {
55			return -1;
56		}
57		timeout++;
58		if (!in_atomic())
59			schedule();
60		else {
61			for (i = 0; i < 20; i++)
62				cpu_relax();
63		}
64	}
65
66	writel(PHY_LOCK_DRIVER,
67	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
68	return 0;
69}
70
71static inline int phy_unlock(struct netxen_adapter *adapter)
72{
73	readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
74
75	return 0;
76}
77
78/*
79 * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
80 * mii management interface.
81 *
82 * Note: The MII management interface goes through port 0.
83 *	Individual phys are addressed as follows:
84 * @param phy  [15:8]  phy id
85 * @param reg  [7:0]   register number
86 *
87 * @returns  0 on success
88 *	  -1 on error
89 *
90 */
91int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
92				__u32 * readval)
93{
94	long timeout = 0;
95	long result = 0;
96	long restore = 0;
97	long phy = physical_port[adapter->portnum];
98	__u32 address;
99	__u32 command;
100	__u32 status;
101	__u32 mac_cfg0;
102
103	if (phy_lock(adapter) != 0) {
104		return -1;
105	}
106
107	/*
108	 * MII mgmt all goes through port 0 MAC interface,
109	 * so it cannot be in reset
110	 */
111
112	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
113				  &mac_cfg0, 4))
114		return -EIO;
115	if (netxen_gb_get_soft_reset(mac_cfg0)) {
116		__u32 temp;
117		temp = 0;
118		netxen_gb_tx_reset_pb(temp);
119		netxen_gb_rx_reset_pb(temp);
120		netxen_gb_tx_reset_mac(temp);
121		netxen_gb_rx_reset_mac(temp);
122		if (netxen_nic_hw_write_wx(adapter,
123					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
124					   &temp, 4))
125			return -EIO;
126		restore = 1;
127	}
128
129	address = 0;
130	netxen_gb_mii_mgmt_reg_addr(address, reg);
131	netxen_gb_mii_mgmt_phy_addr(address, phy);
132	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
133				   &address, 4))
134		return -EIO;
135	command = 0;		/* turn off any prior activity */
136	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
137				   &command, 4))
138		return -EIO;
139	/* send read command */
140	netxen_gb_mii_mgmt_set_read_cycle(command);
141	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
142				   &command, 4))
143		return -EIO;
144
145	status = 0;
146	do {
147		if (netxen_nic_hw_read_wx(adapter,
148					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
149					  &status, 4))
150			return -EIO;
151		timeout++;
152	} while ((netxen_get_gb_mii_mgmt_busy(status)
153		  || netxen_get_gb_mii_mgmt_notvalid(status))
154		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
155
156	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
157		if (netxen_nic_hw_read_wx(adapter,
158					  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
159					  readval, 4))
160			return -EIO;
161		result = 0;
162	} else
163		result = -1;
164
165	if (restore)
166		if (netxen_nic_hw_write_wx(adapter,
167					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
168					   &mac_cfg0, 4))
169			return -EIO;
170	phy_unlock(adapter);
171	return result;
172}
173
174/*
175 * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
176 * mii management interface.
177 *
178 * Note: The MII management interface goes through port 0.
179 *	Individual phys are addressed as follows:
180 * @param phy      [15:8]  phy id
181 * @param reg      [7:0]   register number
182 *
183 * @returns  0 on success
184 *	  -1 on error
185 *
186 */
187int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
188				__u32 val)
189{
190	long timeout = 0;
191	long result = 0;
192	long restore = 0;
193	long phy = physical_port[adapter->portnum];
194	__u32 address;
195	__u32 command;
196	__u32 status;
197	__u32 mac_cfg0;
198
199	/*
200	 * MII mgmt all goes through port 0 MAC interface, so it
201	 * cannot be in reset
202	 */
203
204	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
205				  &mac_cfg0, 4))
206		return -EIO;
207	if (netxen_gb_get_soft_reset(mac_cfg0)) {
208		__u32 temp;
209		temp = 0;
210		netxen_gb_tx_reset_pb(temp);
211		netxen_gb_rx_reset_pb(temp);
212		netxen_gb_tx_reset_mac(temp);
213		netxen_gb_rx_reset_mac(temp);
214
215		if (netxen_nic_hw_write_wx(adapter,
216					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
217					   &temp, 4))
218			return -EIO;
219		restore = 1;
220	}
221
222	command = 0;		/* turn off any prior activity */
223	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
224				   &command, 4))
225		return -EIO;
226
227	address = 0;
228	netxen_gb_mii_mgmt_reg_addr(address, reg);
229	netxen_gb_mii_mgmt_phy_addr(address, phy);
230	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
231				   &address, 4))
232		return -EIO;
233
234	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
235				   &val, 4))
236		return -EIO;
237
238	status = 0;
239	do {
240		if (netxen_nic_hw_read_wx(adapter,
241					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
242					  &status, 4))
243			return -EIO;
244		timeout++;
245	} while ((netxen_get_gb_mii_mgmt_busy(status))
246		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
247
248	if (timeout < NETXEN_NIU_PHY_WAITMAX)
249		result = 0;
250	else
251		result = -EIO;
252
253	/* restore the state of port 0 MAC in case we tampered with it */
254	if (restore)
255		if (netxen_nic_hw_write_wx(adapter,
256					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
257					   &mac_cfg0, 4))
258			return -EIO;
259
260	return result;
261}
262
263int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter)
264{
265	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
266	return 0;
267}
268
269int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter)
270{
271	int result = 0;
272	__u32 enable = 0;
273	netxen_set_phy_int_link_status_changed(enable);
274	netxen_set_phy_int_autoneg_completed(enable);
275	netxen_set_phy_int_speed_changed(enable);
276
277	if (0 !=
278	    netxen_niu_gbe_phy_write(adapter,
279				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,
280				     enable))
281		result = -EIO;
282
283	return result;
284}
285
286int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter)
287{
288	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
289	return 0;
290}
291
292int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter)
293{
294	int result = 0;
295	if (0 !=
296	    netxen_niu_gbe_phy_write(adapter,
297				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0))
298		result = -EIO;
299
300	return result;
301}
302
303int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter)
304{
305	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1);
306	return 0;
307}
308
309int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter)
310{
311	int result = 0;
312	if (0 !=
313	    netxen_niu_gbe_phy_write(adapter,
314				     NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
315				     -EIO))
316		result = -EIO;
317
318	return result;
319}
320
321/*
322 * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
323 *
324 */
325void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
326				 int port, long enable)
327{
328	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
329	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
330				    0x80000000);
331	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
332				    0x0000f0025);
333	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
334				    0xf1ff);
335	netxen_crb_writelit_adapter(adapter,
336				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
337	netxen_crb_writelit_adapter(adapter,
338				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
339	netxen_crb_writelit_adapter(adapter,
340				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
341	netxen_crb_writelit_adapter(adapter,
342				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
343
344	if (enable) {
345		/*
346		 * Do NOT enable flow control until a suitable solution for
347		 *  shutting down pause frames is found.
348		 */
349		netxen_crb_writelit_adapter(adapter,
350					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
351					    0x5);
352	}
353
354	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
355		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
356	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
357		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
358}
359
360/*
361 * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
362 */
363void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
364				  int port, long enable)
365{
366	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
367	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
368				    0x80000000);
369	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
370				    0x0000f0025);
371	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
372				    0xf2ff);
373	netxen_crb_writelit_adapter(adapter,
374				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
375	netxen_crb_writelit_adapter(adapter,
376				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
377	netxen_crb_writelit_adapter(adapter,
378				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
379	netxen_crb_writelit_adapter(adapter,
380				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
381
382	if (enable) {
383		/*
384		 * Do NOT enable flow control until a suitable solution for
385		 *  shutting down pause frames is found.
386		 */
387		netxen_crb_writelit_adapter(adapter,
388					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
389					    0x5);
390	}
391
392	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
393		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
394	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
395		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
396}
397
398int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
399{
400	int result = 0;
401	__u32 status;
402	if (adapter->disable_phy_interrupts)
403		adapter->disable_phy_interrupts(adapter);
404	mdelay(2);
405
406	if (0 ==
407	    netxen_niu_gbe_phy_read(adapter,
408				    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
409				    &status)) {
410		if (netxen_get_phy_link(status)) {
411			if (netxen_get_phy_speed(status) == 2) {
412				netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
413			} else if ((netxen_get_phy_speed(status) == 1)
414				   || (netxen_get_phy_speed(status) == 0)) {
415				netxen_niu_gbe_set_mii_mode(adapter, port, 1);
416			} else {
417				result = -1;
418			}
419
420		} else {
421			/*
422			 * We don't have link. Cable  must be unconnected.
423			 * Enable phy interrupts so we take action when
424			 * plugged in.
425			 */
426
427			netxen_crb_writelit_adapter(adapter,
428						    NETXEN_NIU_GB_MAC_CONFIG_0
429						    (port),
430						    NETXEN_GB_MAC_SOFT_RESET);
431			netxen_crb_writelit_adapter(adapter,
432						    NETXEN_NIU_GB_MAC_CONFIG_0
433						    (port),
434						    NETXEN_GB_MAC_RESET_PROT_BLK
435						    | NETXEN_GB_MAC_ENABLE_TX_RX
436						    |
437						    NETXEN_GB_MAC_PAUSED_FRMS);
438			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
439				printk(KERN_ERR PFX
440				       "ERROR clearing PHY interrupts\n");
441			if (netxen_niu_gbe_enable_phy_interrupts(adapter))
442				printk(KERN_ERR PFX
443				       "ERROR enabling PHY interrupts\n");
444			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
445				printk(KERN_ERR PFX
446				       "ERROR clearing PHY interrupts\n");
447			result = -1;
448		}
449	} else {
450		result = -EIO;
451	}
452	return result;
453}
454
455int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
456{
457	u32 portnum = physical_port[adapter->portnum];
458
459	netxen_crb_writelit_adapter(adapter,
460		NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
461	netxen_crb_writelit_adapter(adapter,
462		NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
463
464	return 0;
465}
466
467/*
468 * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
469 * @param enable 0 means don't enable the port
470 *		 1 means enable (or re-enable) the port
471 */
472int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
473					int port, long enable)
474{
475	int result = 0;
476	__u32 int_src;
477
478	printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
479	       " (device enable = %d)\n", (int)port, (int)enable);
480
481	/*
482	 * The read of the PHY INT status will clear the pending
483	 * interrupt status
484	 */
485	if (netxen_niu_gbe_phy_read(adapter,
486				    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
487				    &int_src) != 0)
488		result = -EINVAL;
489	else {
490		printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n", int_src);
491		if (netxen_get_phy_int_jabber(int_src))
492			printk(KERN_INFO PFX "jabber Interrupt ");
493		if (netxen_get_phy_int_polarity_changed(int_src))
494			printk(KERN_INFO PFX "polarity changed ");
495		if (netxen_get_phy_int_energy_detect(int_src))
496			printk(KERN_INFO PFX "energy detect \n");
497		if (netxen_get_phy_int_downshift(int_src))
498			printk(KERN_INFO PFX "downshift \n");
499		if (netxen_get_phy_int_mdi_xover_changed(int_src))
500			printk(KERN_INFO PFX "mdi_xover_changed ");
501		if (netxen_get_phy_int_fifo_over_underflow(int_src))
502			printk(KERN_INFO PFX "fifo_over_underflow ");
503		if (netxen_get_phy_int_false_carrier(int_src))
504			printk(KERN_INFO PFX "false_carrier ");
505		if (netxen_get_phy_int_symbol_error(int_src))
506			printk(KERN_INFO PFX "symbol_error ");
507		if (netxen_get_phy_int_autoneg_completed(int_src))
508			printk(KERN_INFO PFX "autoneg_completed ");
509		if (netxen_get_phy_int_page_received(int_src))
510			printk(KERN_INFO PFX "page_received ");
511		if (netxen_get_phy_int_duplex_changed(int_src))
512			printk(KERN_INFO PFX "duplex_changed ");
513		if (netxen_get_phy_int_autoneg_error(int_src))
514			printk(KERN_INFO PFX "autoneg_error ");
515		if ((netxen_get_phy_int_speed_changed(int_src))
516		    || (netxen_get_phy_int_link_status_changed(int_src))) {
517			__u32 status;
518
519			printk(KERN_INFO PFX
520			       "speed_changed or link status changed");
521			if (netxen_niu_gbe_phy_read
522			    (adapter,
523			     NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
524			     &status) == 0) {
525				if (netxen_get_phy_speed(status) == 2) {
526					printk
527					    (KERN_INFO PFX "Link speed changed"
528					     " to 1000 Mbps\n");
529					netxen_niu_gbe_set_gmii_mode(adapter,
530								     port,
531								     enable);
532				} else if (netxen_get_phy_speed(status) == 1) {
533					printk
534					    (KERN_INFO PFX "Link speed changed"
535					     " to 100 Mbps\n");
536					netxen_niu_gbe_set_mii_mode(adapter,
537								    port,
538								    enable);
539				} else if (netxen_get_phy_speed(status) == 0) {
540					printk
541					    (KERN_INFO PFX "Link speed changed"
542					     " to 10 Mbps\n");
543					netxen_niu_gbe_set_mii_mode(adapter,
544								    port,
545								    enable);
546				} else {
547					printk(KERN_ERR PFX "ERROR reading"
548					       "PHY status. Illegal speed.\n");
549					result = -1;
550				}
551			} else {
552				printk(KERN_ERR PFX
553				       "ERROR reading PHY status.\n");
554				result = -1;
555			}
556
557		}
558		printk(KERN_INFO "\n");
559	}
560	return result;
561}
562
563/*
564 * Return the current station MAC address.
565 * Note that the passed-in value must already be in network byte order.
566 */
567int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
568			   netxen_ethernet_macaddr_t * addr)
569{
570	u32 stationhigh;
571	u32 stationlow;
572	int phy = physical_port[adapter->portnum];
573	u8 val[8];
574
575	if (addr == NULL)
576		return -EINVAL;
577	if ((phy < 0) || (phy > 3))
578		return -EINVAL;
579
580	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
581				  &stationhigh, 4))
582		return -EIO;
583	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
584				  &stationlow, 4))
585		return -EIO;
586	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
587	((__le32 *)val)[0] = cpu_to_le32(stationlow);
588
589	memcpy(addr, val + 2, 6);
590
591	return 0;
592}
593
594/*
595 * Set the station MAC address.
596 * Note that the passed-in value must already be in network byte order.
597 */
598int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
599			   netxen_ethernet_macaddr_t addr)
600{
601	u8 temp[4];
602	u32 val;
603	int phy = physical_port[adapter->portnum];
604	unsigned char mac_addr[6];
605	int i;
606
607	for (i = 0; i < 10; i++) {
608		temp[0] = temp[1] = 0;
609		memcpy(temp + 2, addr, 2);
610		val = le32_to_cpu(*(__le32 *)temp);
611		if (netxen_nic_hw_write_wx
612		    (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
613			return -EIO;
614
615		memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
616		val = le32_to_cpu(*(__le32 *)temp);
617		if (netxen_nic_hw_write_wx
618		    (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
619			return -2;
620
621		netxen_niu_macaddr_get(adapter,
622				       (netxen_ethernet_macaddr_t *) mac_addr);
623		if (memcmp(mac_addr, addr, 6) == 0)
624			break;
625	}
626
627	if (i == 10) {
628		printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
629		       netxen_nic_driver_name, adapter->netdev->name);
630		printk(KERN_ERR "MAC address set: "
631		       "%02x:%02x:%02x:%02x:%02x:%02x.\n",
632		       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
633
634		printk(KERN_ERR "MAC address get: "
635		       "%02x:%02x:%02x:%02x:%02x:%02x.\n",
636		       mac_addr[0],
637		       mac_addr[1],
638		       mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
639	}
640	return 0;
641}
642
643/* Enable a GbE interface */
644int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
645			       int port, netxen_niu_gbe_ifmode_t mode)
646{
647	__u32 mac_cfg0;
648	__u32 mac_cfg1;
649	__u32 mii_cfg;
650
651	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
652		return -EINVAL;
653
654	mac_cfg0 = 0;
655	netxen_gb_soft_reset(mac_cfg0);
656	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
657				   &mac_cfg0, 4))
658		return -EIO;
659	mac_cfg0 = 0;
660	netxen_gb_enable_tx(mac_cfg0);
661	netxen_gb_enable_rx(mac_cfg0);
662	netxen_gb_unset_rx_flowctl(mac_cfg0);
663	netxen_gb_tx_reset_pb(mac_cfg0);
664	netxen_gb_rx_reset_pb(mac_cfg0);
665	netxen_gb_tx_reset_mac(mac_cfg0);
666	netxen_gb_rx_reset_mac(mac_cfg0);
667
668	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
669				   &mac_cfg0, 4))
670		return -EIO;
671	mac_cfg1 = 0;
672	netxen_gb_set_preamblelen(mac_cfg1, 0xf);
673	netxen_gb_set_duplex(mac_cfg1);
674	netxen_gb_set_crc_enable(mac_cfg1);
675	netxen_gb_set_padshort(mac_cfg1);
676	netxen_gb_set_checklength(mac_cfg1);
677	netxen_gb_set_hugeframes(mac_cfg1);
678
679	if (mode == NETXEN_NIU_10_100_MB) {
680		netxen_gb_set_intfmode(mac_cfg1, 1);
681		if (netxen_nic_hw_write_wx(adapter,
682					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
683					   &mac_cfg1, 4))
684			return -EIO;
685
686		/* set mii mode */
687		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
688					    (port << 3), 0);
689		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
690					    (port << 3), 1);
691
692	} else if (mode == NETXEN_NIU_1000_MB) {
693		netxen_gb_set_intfmode(mac_cfg1, 2);
694		if (netxen_nic_hw_write_wx(adapter,
695					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
696					   &mac_cfg1, 4))
697			return -EIO;
698		/* set gmii mode */
699		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
700					    (port << 3), 0);
701		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
702					    (port << 3), 1);
703	}
704	mii_cfg = 0;
705	netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
706	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
707				   &mii_cfg, 4))
708		return -EIO;
709	mac_cfg0 = 0;
710	netxen_gb_enable_tx(mac_cfg0);
711	netxen_gb_enable_rx(mac_cfg0);
712	netxen_gb_unset_rx_flowctl(mac_cfg0);
713	netxen_gb_unset_tx_flowctl(mac_cfg0);
714
715	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
716				   &mac_cfg0, 4))
717		return -EIO;
718	return 0;
719}
720
721/* Disable a GbE interface */
722int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
723{
724	__u32 mac_cfg0;
725	u32 port = physical_port[adapter->portnum];
726
727	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
728		return -EINVAL;
729	mac_cfg0 = 0;
730	netxen_gb_soft_reset(mac_cfg0);
731	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
732				   &mac_cfg0, 4))
733		return -EIO;
734	return 0;
735}
736
737/* Disable an XG interface */
738int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
739{
740	__u32 mac_cfg;
741	u32 port = physical_port[adapter->portnum];
742
743	if (port != 0)
744		return -EINVAL;
745	mac_cfg = 0;
746	netxen_xg_soft_reset(mac_cfg);
747	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0,
748				   &mac_cfg, 4))
749		return -EIO;
750	return 0;
751}
752
753/* Set promiscuous mode for a GbE interface */
754int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
755				    netxen_niu_prom_mode_t mode)
756{
757	__u32 reg;
758	u32 port = physical_port[adapter->portnum];
759
760	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
761		return -EINVAL;
762
763	/* save previous contents */
764	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
765				  &reg, 4))
766		return -EIO;
767	if (mode == NETXEN_NIU_PROMISC_MODE) {
768		switch (port) {
769		case 0:
770			netxen_clear_gb_drop_gb0(reg);
771			break;
772		case 1:
773			netxen_clear_gb_drop_gb1(reg);
774			break;
775		case 2:
776			netxen_clear_gb_drop_gb2(reg);
777			break;
778		case 3:
779			netxen_clear_gb_drop_gb3(reg);
780			break;
781		default:
782			return -EIO;
783		}
784	} else {
785		switch (port) {
786		case 0:
787			netxen_set_gb_drop_gb0(reg);
788			break;
789		case 1:
790			netxen_set_gb_drop_gb1(reg);
791			break;
792		case 2:
793			netxen_set_gb_drop_gb2(reg);
794			break;
795		case 3:
796			netxen_set_gb_drop_gb3(reg);
797			break;
798		default:
799			return -EIO;
800		}
801	}
802	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
803				   &reg, 4))
804		return -EIO;
805	return 0;
806}
807
808/*
809 * Set the MAC address for an XG port
810 * Note that the passed-in value must already be in network byte order.
811 */
812int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
813			      netxen_ethernet_macaddr_t addr)
814{
815	int phy = physical_port[adapter->portnum];
816	u8 temp[4];
817	u32 val;
818
819	if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
820		return -EIO;
821
822	temp[0] = temp[1] = 0;
823	switch (phy) {
824	case 0:
825	    memcpy(temp + 2, addr, 2);
826	    val = le32_to_cpu(*(__le32 *)temp);
827	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
828				&val, 4))
829		return -EIO;
830
831	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
832	    val = le32_to_cpu(*(__le32 *)temp);
833	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
834				&val, 4))
835		return -EIO;
836	    break;
837
838	case 1:
839	    memcpy(temp + 2, addr, 2);
840	    val = le32_to_cpu(*(__le32 *)temp);
841	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
842				&val, 4))
843		return -EIO;
844
845	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
846	    val = le32_to_cpu(*(__le32 *)temp);
847	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
848				&val, 4))
849		return -EIO;
850	    break;
851
852	default:
853	    printk(KERN_ERR "Unknown port %d\n", phy);
854	    break;
855	}
856
857	return 0;
858}
859
860/*
861 * Return the current station MAC address.
862 * Note that the passed-in value must already be in network byte order.
863 */
864int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
865			      netxen_ethernet_macaddr_t * addr)
866{
867	int phy = physical_port[adapter->portnum];
868	u32 stationhigh;
869	u32 stationlow;
870	u8 val[8];
871
872	if (addr == NULL)
873		return -EINVAL;
874	if (phy != 0)
875		return -EINVAL;
876
877	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
878				  &stationhigh, 4))
879		return -EIO;
880	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
881				  &stationlow, 4))
882		return -EIO;
883	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
884	((__le32 *)val)[0] = cpu_to_le32(stationlow);
885
886	memcpy(addr, val + 2, 6);
887
888	return 0;
889}
890
891int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
892				       netxen_niu_prom_mode_t mode)
893{
894	__u32 reg;
895	u32 port = physical_port[adapter->portnum];
896
897	if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
898		return -EINVAL;
899
900	if (netxen_nic_hw_read_wx(adapter,
901		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
902			return -EIO;
903	if (mode == NETXEN_NIU_PROMISC_MODE)
904		reg = (reg | 0x2000UL);
905	else
906		reg = (reg & ~0x2000UL);
907
908	netxen_crb_writelit_adapter(adapter,
909		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
910
911	return 0;
912}
913