2 * Copyright (C) 2003 - 2006 NetXen, Inc.
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.
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.
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,
20 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
23 * Contact Information:
26 * 3965 Freedom Circle, Fourth floor,
27 * Santa Clara, CA 95054
30 * Provides access to the Network Interface Unit h/w block.
34 #include "netxen_nic.h"
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
41 static long phy_lock_timeout = 100000000;
43 static int phy_lock(struct netxen_adapter *adapter)
46 int done = 0, timeout = 0;
49 done = netxen_nic_reg_read(adapter,
50 NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
53 if (timeout >= phy_lock_timeout) {
60 for (i = 0; i < 20; i++)
65 netxen_crb_writelit_adapter(adapter,
66 NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
70 static int phy_unlock(struct netxen_adapter *adapter)
72 adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
78 * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
79 * mii management interface.
81 * Note: The MII management interface goes through port 0.
82 * Individual phys are addressed as follows:
83 * @param phy [15:8] phy id
84 * @param reg [7:0] register number
86 * @returns 0 on success
90 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
96 long phy = adapter->physical_port;
102 if (phy_lock(adapter) != 0) {
107 * MII mgmt all goes through port 0 MAC interface,
108 * so it cannot be in reset
111 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
114 if (netxen_gb_get_soft_reset(mac_cfg0)) {
117 netxen_gb_tx_reset_pb(temp);
118 netxen_gb_rx_reset_pb(temp);
119 netxen_gb_tx_reset_mac(temp);
120 netxen_gb_rx_reset_mac(temp);
121 if (adapter->hw_write_wx(adapter,
122 NETXEN_NIU_GB_MAC_CONFIG_0(0),
129 netxen_gb_mii_mgmt_reg_addr(address, reg);
130 netxen_gb_mii_mgmt_phy_addr(address, phy);
131 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
134 command = 0; /* turn off any prior activity */
135 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
138 /* send read command */
139 netxen_gb_mii_mgmt_set_read_cycle(command);
140 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
146 if (adapter->hw_read_wx(adapter,
147 NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
151 } while ((netxen_get_gb_mii_mgmt_busy(status)
152 || netxen_get_gb_mii_mgmt_notvalid(status))
153 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
155 if (timeout < NETXEN_NIU_PHY_WAITMAX) {
156 if (adapter->hw_read_wx(adapter,
157 NETXEN_NIU_GB_MII_MGMT_STATUS(0),
165 if (adapter->hw_write_wx(adapter,
166 NETXEN_NIU_GB_MAC_CONFIG_0(0),
174 * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
175 * mii management interface.
177 * Note: The MII management interface goes through port 0.
178 * Individual phys are addressed as follows:
179 * @param phy [15:8] phy id
180 * @param reg [7:0] register number
182 * @returns 0 on success
186 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
192 long phy = adapter->physical_port;
199 * MII mgmt all goes through port 0 MAC interface, so it
203 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
206 if (netxen_gb_get_soft_reset(mac_cfg0)) {
209 netxen_gb_tx_reset_pb(temp);
210 netxen_gb_rx_reset_pb(temp);
211 netxen_gb_tx_reset_mac(temp);
212 netxen_gb_rx_reset_mac(temp);
214 if (adapter->hw_write_wx(adapter,
215 NETXEN_NIU_GB_MAC_CONFIG_0(0),
221 command = 0; /* turn off any prior activity */
222 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
227 netxen_gb_mii_mgmt_reg_addr(address, reg);
228 netxen_gb_mii_mgmt_phy_addr(address, phy);
229 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
233 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
239 if (adapter->hw_read_wx(adapter,
240 NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
244 } while ((netxen_get_gb_mii_mgmt_busy(status))
245 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
247 if (timeout < NETXEN_NIU_PHY_WAITMAX)
252 /* restore the state of port 0 MAC in case we tampered with it */
254 if (adapter->hw_write_wx(adapter,
255 NETXEN_NIU_GB_MAC_CONFIG_0(0),
262 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter)
264 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
268 int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter)
272 netxen_set_phy_int_link_status_changed(enable);
273 netxen_set_phy_int_autoneg_completed(enable);
274 netxen_set_phy_int_speed_changed(enable);
277 netxen_niu_gbe_phy_write(adapter,
278 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE,
285 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter)
287 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
291 int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter)
295 netxen_niu_gbe_phy_write(adapter,
296 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0))
302 static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter)
306 netxen_niu_gbe_phy_write(adapter,
307 NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
315 * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
318 static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
319 int port, long enable)
321 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
322 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
324 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
326 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
328 netxen_crb_writelit_adapter(adapter,
329 NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
330 netxen_crb_writelit_adapter(adapter,
331 NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
332 netxen_crb_writelit_adapter(adapter,
333 (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
334 netxen_crb_writelit_adapter(adapter,
335 NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
339 * Do NOT enable flow control until a suitable solution for
340 * shutting down pause frames is found.
342 netxen_crb_writelit_adapter(adapter,
343 NETXEN_NIU_GB_MAC_CONFIG_0(port),
347 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
348 printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
349 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
350 printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
354 * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC
356 static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
357 int port, long enable)
359 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
360 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
362 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
364 netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
366 netxen_crb_writelit_adapter(adapter,
367 NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
368 netxen_crb_writelit_adapter(adapter,
369 NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
370 netxen_crb_writelit_adapter(adapter,
371 (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
372 netxen_crb_writelit_adapter(adapter,
373 NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
377 * Do NOT enable flow control until a suitable solution for
378 * shutting down pause frames is found.
380 netxen_crb_writelit_adapter(adapter,
381 NETXEN_NIU_GB_MAC_CONFIG_0(port),
385 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
386 printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
387 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
388 printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
391 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
396 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
399 if (adapter->disable_phy_interrupts)
400 adapter->disable_phy_interrupts(adapter);
403 if (0 == netxen_niu_gbe_phy_read(adapter,
404 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) {
405 if (netxen_get_phy_link(status)) {
406 if (netxen_get_phy_speed(status) == 2) {
407 netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
408 } else if ((netxen_get_phy_speed(status) == 1)
409 || (netxen_get_phy_speed(status) == 0)) {
410 netxen_niu_gbe_set_mii_mode(adapter, port, 1);
417 * We don't have link. Cable must be unconnected.
418 * Enable phy interrupts so we take action when
422 netxen_crb_writelit_adapter(adapter,
423 NETXEN_NIU_GB_MAC_CONFIG_0
425 NETXEN_GB_MAC_SOFT_RESET);
426 netxen_crb_writelit_adapter(adapter,
427 NETXEN_NIU_GB_MAC_CONFIG_0
429 NETXEN_GB_MAC_RESET_PROT_BLK
430 | NETXEN_GB_MAC_ENABLE_TX_RX
432 NETXEN_GB_MAC_PAUSED_FRMS);
433 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
435 "ERROR clearing PHY interrupts\n");
436 if (netxen_niu_gbe_enable_phy_interrupts(adapter))
438 "ERROR enabling PHY interrupts\n");
439 if (netxen_niu_gbe_clear_phy_interrupts(adapter))
441 "ERROR clearing PHY interrupts\n");
450 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
452 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
453 netxen_crb_writelit_adapter(adapter,
454 NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
455 netxen_crb_writelit_adapter(adapter,
456 NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
463 * Return the current station MAC address.
464 * Note that the passed-in value must already be in network byte order.
466 static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
467 netxen_ethernet_macaddr_t * addr)
471 int phy = adapter->physical_port;
476 if ((phy < 0) || (phy > 3))
479 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
482 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
485 ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
486 ((__le32 *)val)[0] = cpu_to_le32(stationlow);
488 memcpy(addr, val + 2, 6);
494 * Set the station MAC address.
495 * Note that the passed-in value must already be in network byte order.
497 int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
498 netxen_ethernet_macaddr_t addr)
502 int phy = adapter->physical_port;
503 unsigned char mac_addr[6];
506 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
509 for (i = 0; i < 10; i++) {
510 temp[0] = temp[1] = 0;
511 memcpy(temp + 2, addr, 2);
512 val = le32_to_cpu(*(__le32 *)temp);
513 if (adapter->hw_write_wx(adapter,
514 NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
517 memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
518 val = le32_to_cpu(*(__le32 *)temp);
519 if (adapter->hw_write_wx(adapter,
520 NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
523 netxen_niu_macaddr_get(adapter,
524 (netxen_ethernet_macaddr_t *) mac_addr);
525 if (memcmp(mac_addr, addr, 6) == 0)
530 printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
531 netxen_nic_driver_name, adapter->netdev->name);
532 printk(KERN_ERR "MAC address set: %pM.\n", addr);
533 printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
538 /* Disable a GbE interface */
539 int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
542 u32 port = adapter->physical_port;
544 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
547 if (port > NETXEN_NIU_MAX_GBE_PORTS)
550 netxen_gb_soft_reset(mac_cfg0);
551 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
557 /* Disable an XG interface */
558 int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
561 u32 port = adapter->physical_port;
563 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
566 if (port > NETXEN_NIU_MAX_XG_PORTS)
570 if (adapter->hw_write_wx(adapter,
571 NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
576 /* Set promiscuous mode for a GbE interface */
577 int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
581 u32 port = adapter->physical_port;
583 if (port > NETXEN_NIU_MAX_GBE_PORTS)
586 /* save previous contents */
587 if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
590 if (mode == NETXEN_NIU_PROMISC_MODE) {
593 netxen_clear_gb_drop_gb0(reg);
596 netxen_clear_gb_drop_gb1(reg);
599 netxen_clear_gb_drop_gb2(reg);
602 netxen_clear_gb_drop_gb3(reg);
610 netxen_set_gb_drop_gb0(reg);
613 netxen_set_gb_drop_gb1(reg);
616 netxen_set_gb_drop_gb2(reg);
619 netxen_set_gb_drop_gb3(reg);
625 if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
632 * Set the MAC address for an XG port
633 * Note that the passed-in value must already be in network byte order.
635 int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
636 netxen_ethernet_macaddr_t addr)
638 int phy = adapter->physical_port;
642 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
645 if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
648 temp[0] = temp[1] = 0;
651 memcpy(temp + 2, addr, 2);
652 val = le32_to_cpu(*(__le32 *)temp);
653 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
657 memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
658 val = le32_to_cpu(*(__le32 *)temp);
659 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
665 memcpy(temp + 2, addr, 2);
666 val = le32_to_cpu(*(__le32 *)temp);
667 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
671 memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
672 val = le32_to_cpu(*(__le32 *)temp);
673 if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
679 printk(KERN_ERR "Unknown port %d\n", phy);
686 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
690 u32 port = adapter->physical_port;
692 if (port > NETXEN_NIU_MAX_XG_PORTS)
695 if (adapter->hw_read_wx(adapter,
696 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), ®, 4))
698 if (mode == NETXEN_NIU_PROMISC_MODE)
699 reg = (reg | 0x2000UL);
701 reg = (reg & ~0x2000UL);
703 if (mode == NETXEN_NIU_ALLMULTI_MODE)
704 reg = (reg | 0x1000UL);
706 reg = (reg & ~0x1000UL);
708 netxen_crb_writelit_adapter(adapter,
709 NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);