netxen_nic_niu.c 7.5 KB
Newer Older
A
Amit S. Kale 已提交
1
/*
D
Dhananjay Phadke 已提交
2
 * Copyright (C) 2003 - 2009 NetXen, Inc.
A
Amit S. Kale 已提交
3
 * All rights reserved.
4
 *
A
Amit S. Kale 已提交
5 6 7 8
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
9
 *
A
Amit S. Kale 已提交
10 11 12 13
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14
 *
A
Amit S. Kale 已提交
15 16 17 18
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA  02111-1307, USA.
19
 *
A
Amit S. Kale 已提交
20 21
 * The full GNU General Public License is included in this distribution
 * in the file called LICENSE.
22
 *
A
Amit S. Kale 已提交
23 24
 * Contact Information:
 *    info@netxen.com
D
Dhananjay Phadke 已提交
25 26 27
 * NetXen Inc,
 * 18922 Forge Drive
 * Cupertino, CA 95014-0701
A
Amit S. Kale 已提交
28 29 30 31
 *
 */

#include "netxen_nic.h"
32 33 34

static long phy_lock_timeout = 100000000;

A
Adrian Bunk 已提交
35
static int phy_lock(struct netxen_adapter *adapter)
36 37 38 39 40
{
	int i;
	int done = 0, timeout = 0;

	while (!done) {
41
		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
42 43 44 45 46 47 48 49 50 51 52 53 54 55
		if (done == 1)
			break;
		if (timeout >= phy_lock_timeout) {
			return -1;
		}
		timeout++;
		if (!in_atomic())
			schedule();
		else {
			for (i = 0; i < 20; i++)
				cpu_relax();
		}
	}

56
	NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
57 58 59
	return 0;
}

A
Adrian Bunk 已提交
60
static int phy_unlock(struct netxen_adapter *adapter)
61
{
62
	adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
63

64 65
	return 0;
}
A
Amit S. Kale 已提交
66

67
/*
A
Amit S. Kale 已提交
68 69 70 71
 * netxen_niu_gbe_phy_read - read a register from the GbE PHY via
 * mii management interface.
 *
 * Note: The MII management interface goes through port 0.
72
 *	Individual phys are addressed as follows:
A
Amit S. Kale 已提交
73 74 75 76
 * @param phy  [15:8]  phy id
 * @param reg  [7:0]   register number
 *
 * @returns  0 on success
77
 *	  -1 on error
A
Amit S. Kale 已提交
78 79
 *
 */
80
int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
81
				__u32 * readval)
A
Amit S. Kale 已提交
82 83 84 85
{
	long timeout = 0;
	long result = 0;
	long restore = 0;
86
	long phy = adapter->physical_port;
A
Al Viro 已提交
87 88 89 90
	__u32 address;
	__u32 command;
	__u32 status;
	__u32 mac_cfg0;
A
Amit S. Kale 已提交
91

92
	if (phy_lock(adapter) != 0) {
93 94 95 96 97 98 99 100
		return -1;
	}

	/*
	 * MII mgmt all goes through port 0 MAC interface,
	 * so it cannot be in reset
	 */

101
	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
A
Amit S. Kale 已提交
102
	if (netxen_gb_get_soft_reset(mac_cfg0)) {
A
Al Viro 已提交
103
		__u32 temp;
A
Amit S. Kale 已提交
104 105 106 107 108
		temp = 0;
		netxen_gb_tx_reset_pb(temp);
		netxen_gb_rx_reset_pb(temp);
		netxen_gb_tx_reset_mac(temp);
		netxen_gb_rx_reset_mac(temp);
109
		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
A
Amit S. Kale 已提交
110 111 112 113 114 115 116
			return -EIO;
		restore = 1;
	}

	address = 0;
	netxen_gb_mii_mgmt_reg_addr(address, reg);
	netxen_gb_mii_mgmt_phy_addr(address, phy);
117
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
A
Amit S. Kale 已提交
118 119
		return -EIO;
	command = 0;		/* turn off any prior activity */
120
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
A
Amit S. Kale 已提交
121 122 123
		return -EIO;
	/* send read command */
	netxen_gb_mii_mgmt_set_read_cycle(command);
124
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
A
Amit S. Kale 已提交
125 126 127 128
		return -EIO;

	status = 0;
	do {
129
		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
A
Amit S. Kale 已提交
130 131 132 133 134 135
		timeout++;
	} while ((netxen_get_gb_mii_mgmt_busy(status)
		  || netxen_get_gb_mii_mgmt_notvalid(status))
		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));

	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
136
		*readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0));
A
Amit S. Kale 已提交
137 138 139 140 141
		result = 0;
	} else
		result = -1;

	if (restore)
142
		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
A
Amit S. Kale 已提交
143
			return -EIO;
144
	phy_unlock(adapter);
A
Amit S. Kale 已提交
145 146 147
	return result;
}

148
/*
A
Amit S. Kale 已提交
149 150 151 152
 * netxen_niu_gbe_phy_write - write a register to the GbE PHY via
 * mii management interface.
 *
 * Note: The MII management interface goes through port 0.
153
 *	Individual phys are addressed as follows:
A
Amit S. Kale 已提交
154 155 156 157
 * @param phy      [15:8]  phy id
 * @param reg      [7:0]   register number
 *
 * @returns  0 on success
158
 *	  -1 on error
A
Amit S. Kale 已提交
159 160
 *
 */
161
int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
162
				__u32 val)
A
Amit S. Kale 已提交
163 164 165 166
{
	long timeout = 0;
	long result = 0;
	long restore = 0;
167
	long phy = adapter->physical_port;
A
Al Viro 已提交
168 169 170 171
	__u32 address;
	__u32 command;
	__u32 status;
	__u32 mac_cfg0;
A
Amit S. Kale 已提交
172

173 174 175 176 177
	/*
	 * MII mgmt all goes through port 0 MAC interface, so it
	 * cannot be in reset
	 */

178
	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
A
Amit S. Kale 已提交
179
	if (netxen_gb_get_soft_reset(mac_cfg0)) {
A
Al Viro 已提交
180
		__u32 temp;
A
Amit S. Kale 已提交
181 182 183 184 185 186
		temp = 0;
		netxen_gb_tx_reset_pb(temp);
		netxen_gb_rx_reset_pb(temp);
		netxen_gb_tx_reset_mac(temp);
		netxen_gb_rx_reset_mac(temp);

187
		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
A
Amit S. Kale 已提交
188 189 190 191 192
			return -EIO;
		restore = 1;
	}

	command = 0;		/* turn off any prior activity */
193
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
A
Amit S. Kale 已提交
194 195 196 197 198
		return -EIO;

	address = 0;
	netxen_gb_mii_mgmt_reg_addr(address, reg);
	netxen_gb_mii_mgmt_phy_addr(address, phy);
199
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
A
Amit S. Kale 已提交
200 201
		return -EIO;

202
	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val))
A
Amit S. Kale 已提交
203 204 205 206
		return -EIO;

	status = 0;
	do {
207
		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
A
Amit S. Kale 已提交
208 209 210 211 212 213 214 215 216 217 218
		timeout++;
	} while ((netxen_get_gb_mii_mgmt_busy(status))
		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));

	if (timeout < NETXEN_NIU_PHY_WAITMAX)
		result = 0;
	else
		result = -EIO;

	/* restore the state of port 0 MAC in case we tampered with it */
	if (restore)
219
		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
A
Amit S. Kale 已提交
220 221 222 223 224
			return -EIO;

	return result;
}

225 226
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
227
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
228 229
		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
230
	}
231

232
	return 0;
233 234
}

A
Amit S. Kale 已提交
235
/* Disable an XG interface */
236
int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
A
Amit S. Kale 已提交
237
{
A
Al Viro 已提交
238
	__u32 mac_cfg;
239
	u32 port = adapter->physical_port;
A
Amit S. Kale 已提交
240

241 242 243
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		return 0;

244
	if (port > NETXEN_NIU_MAX_XG_PORTS)
245
		return -EINVAL;
246

A
Amit S. Kale 已提交
247
	mac_cfg = 0;
248 249
	if (NXWR32(adapter,
			NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg))
A
Amit S. Kale 已提交
250 251 252 253 254
		return -EIO;
	return 0;
}

int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
255
		u32 mode)
A
Amit S. Kale 已提交
256
{
A
Al Viro 已提交
257
	__u32 reg;
258
	u32 port = adapter->physical_port;
A
Amit S. Kale 已提交
259

260
	if (port > NETXEN_NIU_MAX_XG_PORTS)
A
Amit S. Kale 已提交
261 262
		return -EINVAL;

263
	reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port));
A
Amit S. Kale 已提交
264 265 266 267 268
	if (mode == NETXEN_NIU_PROMISC_MODE)
		reg = (reg | 0x2000UL);
	else
		reg = (reg & ~0x2000UL);

269 270 271 272 273
	if (mode == NETXEN_NIU_ALLMULTI_MODE)
		reg = (reg | 0x1000UL);
	else
		reg = (reg & ~0x1000UL);

274
	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
A
Amit S. Kale 已提交
275 276 277

	return 0;
}
D
Dhananjay Phadke 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
{
	u32 mac_hi, mac_lo;
	u32 reg_hi, reg_lo;

	u8 phy = adapter->physical_port;
	u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ?
		NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS;

	if (phy >= phy_count)
		return -EINVAL;

	mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);
	mac_hi = addr[2] | ((u32)addr[3] << 8) |
		((u32)addr[4] << 16) | ((u32)addr[5] << 24);

	if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
		reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);
		reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);
	} else {
		reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy);
		reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy);
	}

	/* write twice to flush */
	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
		return -EIO;
	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
		return -EIO;

	return 0;
}