1/*
2 * Copyright (C) 2003 - 2009 NetXen, Inc.
3 * Copyright (C) 2009 - QLogic Corporation.
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * The full GNU General Public License is included in this distribution
20 * in the file called "COPYING".
21 *
22 */
23
24#include <linux/slab.h>
25#include "netxen_nic.h"
26#include "netxen_nic_hw.h"
27
28#include <net/ip.h>
29
30#define MASK(n) ((1ULL<<(n))-1)
31#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
32#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
33#define MS_WIN(addr) (addr & 0x0ffc0000)
34
35#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
36
37#define CRB_BLK(off)	((off >> 20) & 0x3f)
38#define CRB_SUBBLK(off)	((off >> 16) & 0xf)
39#define CRB_WINDOW_2M	(0x130060)
40#define CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
41#define CRB_INDIRECT_2M	(0x1e0000UL)
42
43static void netxen_nic_io_write_128M(struct netxen_adapter *adapter,
44		void __iomem *addr, u32 data);
45static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter,
46		void __iomem *addr);
47#ifndef readq
48static inline u64 readq(void __iomem *addr)
49{
50	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
51}
52#endif
53
54#ifndef writeq
55static inline void writeq(u64 val, void __iomem *addr)
56{
57	writel(((u32) (val)), (addr));
58	writel(((u32) (val >> 32)), (addr + 4));
59}
60#endif
61
62#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
63	((adapter)->ahw.pci_base0 + (off))
64#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \
65	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
66#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \
67	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
68
69static void __iomem *pci_base_offset(struct netxen_adapter *adapter,
70					    unsigned long off)
71{
72	if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END))
73		return PCI_OFFSET_FIRST_RANGE(adapter, off);
74
75	if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END))
76		return PCI_OFFSET_SECOND_RANGE(adapter, off);
77
78	if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END))
79		return PCI_OFFSET_THIRD_RANGE(adapter, off);
80
81	return NULL;
82}
83
84static crb_128M_2M_block_map_t
85crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
86    {{{0, 0,         0,         0} } },		/* 0: PCI */
87    {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */
88	  {1, 0x0110000, 0x0120000, 0x130000},
89	  {1, 0x0120000, 0x0122000, 0x124000},
90	  {1, 0x0130000, 0x0132000, 0x126000},
91	  {1, 0x0140000, 0x0142000, 0x128000},
92	  {1, 0x0150000, 0x0152000, 0x12a000},
93	  {1, 0x0160000, 0x0170000, 0x110000},
94	  {1, 0x0170000, 0x0172000, 0x12e000},
95	  {0, 0x0000000, 0x0000000, 0x000000},
96	  {0, 0x0000000, 0x0000000, 0x000000},
97	  {0, 0x0000000, 0x0000000, 0x000000},
98	  {0, 0x0000000, 0x0000000, 0x000000},
99	  {0, 0x0000000, 0x0000000, 0x000000},
100	  {0, 0x0000000, 0x0000000, 0x000000},
101	  {1, 0x01e0000, 0x01e0800, 0x122000},
102	  {0, 0x0000000, 0x0000000, 0x000000} } },
103	{{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
104    {{{0, 0,         0,         0} } },	    /* 3: */
105    {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
106    {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE   */
107    {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU   */
108    {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM    */
109    {{{1, 0x0800000, 0x0802000, 0x170000},  /* 8: SQM0  */
110      {0, 0x0000000, 0x0000000, 0x000000},
111      {0, 0x0000000, 0x0000000, 0x000000},
112      {0, 0x0000000, 0x0000000, 0x000000},
113      {0, 0x0000000, 0x0000000, 0x000000},
114      {0, 0x0000000, 0x0000000, 0x000000},
115      {0, 0x0000000, 0x0000000, 0x000000},
116      {0, 0x0000000, 0x0000000, 0x000000},
117      {0, 0x0000000, 0x0000000, 0x000000},
118      {0, 0x0000000, 0x0000000, 0x000000},
119      {0, 0x0000000, 0x0000000, 0x000000},
120      {0, 0x0000000, 0x0000000, 0x000000},
121      {0, 0x0000000, 0x0000000, 0x000000},
122      {0, 0x0000000, 0x0000000, 0x000000},
123      {0, 0x0000000, 0x0000000, 0x000000},
124      {1, 0x08f0000, 0x08f2000, 0x172000} } },
125    {{{1, 0x0900000, 0x0902000, 0x174000},	/* 9: SQM1*/
126      {0, 0x0000000, 0x0000000, 0x000000},
127      {0, 0x0000000, 0x0000000, 0x000000},
128      {0, 0x0000000, 0x0000000, 0x000000},
129      {0, 0x0000000, 0x0000000, 0x000000},
130      {0, 0x0000000, 0x0000000, 0x000000},
131      {0, 0x0000000, 0x0000000, 0x000000},
132      {0, 0x0000000, 0x0000000, 0x000000},
133      {0, 0x0000000, 0x0000000, 0x000000},
134      {0, 0x0000000, 0x0000000, 0x000000},
135      {0, 0x0000000, 0x0000000, 0x000000},
136      {0, 0x0000000, 0x0000000, 0x000000},
137      {0, 0x0000000, 0x0000000, 0x000000},
138      {0, 0x0000000, 0x0000000, 0x000000},
139      {0, 0x0000000, 0x0000000, 0x000000},
140      {1, 0x09f0000, 0x09f2000, 0x176000} } },
141    {{{0, 0x0a00000, 0x0a02000, 0x178000},	/* 10: SQM2*/
142      {0, 0x0000000, 0x0000000, 0x000000},
143      {0, 0x0000000, 0x0000000, 0x000000},
144      {0, 0x0000000, 0x0000000, 0x000000},
145      {0, 0x0000000, 0x0000000, 0x000000},
146      {0, 0x0000000, 0x0000000, 0x000000},
147      {0, 0x0000000, 0x0000000, 0x000000},
148      {0, 0x0000000, 0x0000000, 0x000000},
149      {0, 0x0000000, 0x0000000, 0x000000},
150      {0, 0x0000000, 0x0000000, 0x000000},
151      {0, 0x0000000, 0x0000000, 0x000000},
152      {0, 0x0000000, 0x0000000, 0x000000},
153      {0, 0x0000000, 0x0000000, 0x000000},
154      {0, 0x0000000, 0x0000000, 0x000000},
155      {0, 0x0000000, 0x0000000, 0x000000},
156      {1, 0x0af0000, 0x0af2000, 0x17a000} } },
157    {{{0, 0x0b00000, 0x0b02000, 0x17c000},	/* 11: SQM3*/
158      {0, 0x0000000, 0x0000000, 0x000000},
159      {0, 0x0000000, 0x0000000, 0x000000},
160      {0, 0x0000000, 0x0000000, 0x000000},
161      {0, 0x0000000, 0x0000000, 0x000000},
162      {0, 0x0000000, 0x0000000, 0x000000},
163      {0, 0x0000000, 0x0000000, 0x000000},
164      {0, 0x0000000, 0x0000000, 0x000000},
165      {0, 0x0000000, 0x0000000, 0x000000},
166      {0, 0x0000000, 0x0000000, 0x000000},
167      {0, 0x0000000, 0x0000000, 0x000000},
168      {0, 0x0000000, 0x0000000, 0x000000},
169      {0, 0x0000000, 0x0000000, 0x000000},
170      {0, 0x0000000, 0x0000000, 0x000000},
171      {0, 0x0000000, 0x0000000, 0x000000},
172      {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
173	{{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
174	{{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
175	{{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
176	{{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
177	{{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
178	{{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
179	{{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
180	{{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
181	{{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
182	{{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
183	{{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
184	{{{0, 0,         0,         0} } },	/* 23: */
185	{{{0, 0,         0,         0} } },	/* 24: */
186	{{{0, 0,         0,         0} } },	/* 25: */
187	{{{0, 0,         0,         0} } },	/* 26: */
188	{{{0, 0,         0,         0} } },	/* 27: */
189	{{{0, 0,         0,         0} } },	/* 28: */
190	{{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
191    {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
192    {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
193	{{{0} } },				/* 32: PCI */
194	{{{1, 0x2100000, 0x2102000, 0x120000},	/* 33: PCIE */
195	  {1, 0x2110000, 0x2120000, 0x130000},
196	  {1, 0x2120000, 0x2122000, 0x124000},
197	  {1, 0x2130000, 0x2132000, 0x126000},
198	  {1, 0x2140000, 0x2142000, 0x128000},
199	  {1, 0x2150000, 0x2152000, 0x12a000},
200	  {1, 0x2160000, 0x2170000, 0x110000},
201	  {1, 0x2170000, 0x2172000, 0x12e000},
202	  {0, 0x0000000, 0x0000000, 0x000000},
203	  {0, 0x0000000, 0x0000000, 0x000000},
204	  {0, 0x0000000, 0x0000000, 0x000000},
205	  {0, 0x0000000, 0x0000000, 0x000000},
206	  {0, 0x0000000, 0x0000000, 0x000000},
207	  {0, 0x0000000, 0x0000000, 0x000000},
208	  {0, 0x0000000, 0x0000000, 0x000000},
209	  {0, 0x0000000, 0x0000000, 0x000000} } },
210	{{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
211	{{{0} } },				/* 35: */
212	{{{0} } },				/* 36: */
213	{{{0} } },				/* 37: */
214	{{{0} } },				/* 38: */
215	{{{0} } },				/* 39: */
216	{{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
217	{{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
218	{{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
219	{{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
220	{{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
221	{{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
222	{{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
223	{{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
224	{{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
225	{{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
226	{{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
227	{{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
228	{{{0} } },				/* 52: */
229	{{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
230	{{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
231	{{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
232	{{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
233	{{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
234	{{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
235	{{{0} } },				/* 59: I2C0 */
236	{{{0} } },				/* 60: I2C1 */
237	{{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
238	{{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
239	{{{1, 0x3f00000, 0x3f01000, 0x168000} } }	/* 63: P2NR0 */
240};
241
242/*
243 * top 12 bits of crb internal address (hub, agent)
244 */
245static unsigned crb_hub_agt[64] =
246{
247	0,
248	NETXEN_HW_CRB_HUB_AGT_ADR_PS,
249	NETXEN_HW_CRB_HUB_AGT_ADR_MN,
250	NETXEN_HW_CRB_HUB_AGT_ADR_MS,
251	0,
252	NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
253	NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
254	NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
255	NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
256	NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
257	NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
258	NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
259	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
260	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
261	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
262	NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
263	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
264	NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
265	NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
266	NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
267	NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
268	NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
269	NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
270	NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
271	NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
272	NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
273	NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
274	0,
275	NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
276	NETXEN_HW_CRB_HUB_AGT_ADR_SN,
277	0,
278	NETXEN_HW_CRB_HUB_AGT_ADR_EG,
279	0,
280	NETXEN_HW_CRB_HUB_AGT_ADR_PS,
281	NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
282	0,
283	0,
284	0,
285	0,
286	0,
287	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
288	0,
289	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
290	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
291	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
292	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
293	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
294	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
295	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
296	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
297	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
298	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
299	0,
300	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
301	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
302	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
303	NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
304	0,
305	NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
306	NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
307	NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
308	0,
309	NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
310	0,
311};
312
313/*  PCI Windowing for DDR regions.  */
314
315#define NETXEN_WINDOW_ONE 	0x2000000 /*CRB Window: bit 25 of CRB address */
316
317#define NETXEN_PCIE_SEM_TIMEOUT	10000
318
319static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
320
321int
322netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg)
323{
324	int done = 0, timeout = 0;
325
326	while (!done) {
327		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_LOCK(sem)));
328		if (done == 1)
329			break;
330		if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT)
331			return -EIO;
332		msleep(1);
333	}
334
335	if (id_reg)
336		NXWR32(adapter, id_reg, adapter->portnum);
337
338	return 0;
339}
340
341void
342netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem)
343{
344	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
345}
346
347static int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
348{
349	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
350		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
351		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
352	}
353
354	return 0;
355}
356
357/* Disable an XG interface */
358static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
359{
360	__u32 mac_cfg;
361	u32 port = adapter->physical_port;
362
363	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
364		return 0;
365
366	if (port >= NETXEN_NIU_MAX_XG_PORTS)
367		return -EINVAL;
368
369	mac_cfg = 0;
370	if (NXWR32(adapter,
371			NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg))
372		return -EIO;
373	return 0;
374}
375
376#define NETXEN_UNICAST_ADDR(port, index) \
377	(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
378#define NETXEN_MCAST_ADDR(port, index) \
379	(NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
380#define MAC_HI(addr) \
381	((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
382#define MAC_LO(addr) \
383	((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
384
385static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
386{
387	u32 mac_cfg;
388	u32 cnt = 0;
389	__u32 reg = 0x0200;
390	u32 port = adapter->physical_port;
391	u16 board_type = adapter->ahw.board_type;
392
393	if (port >= NETXEN_NIU_MAX_XG_PORTS)
394		return -EINVAL;
395
396	mac_cfg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port));
397	mac_cfg &= ~0x4;
398	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg);
399
400	if ((board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) ||
401			(board_type == NETXEN_BRDTYPE_P2_SB31_10G_HMEZ))
402		reg = (0x20 << port);
403
404	NXWR32(adapter, NETXEN_NIU_FRAME_COUNT_SELECT, reg);
405
406	mdelay(10);
407
408	while (NXRD32(adapter, NETXEN_NIU_FRAME_COUNT) && ++cnt < 20)
409		mdelay(10);
410
411	if (cnt < 20) {
412
413		reg = NXRD32(adapter,
414			NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port));
415
416		if (mode == NETXEN_NIU_PROMISC_MODE)
417			reg = (reg | 0x2000UL);
418		else
419			reg = (reg & ~0x2000UL);
420
421		if (mode == NETXEN_NIU_ALLMULTI_MODE)
422			reg = (reg | 0x1000UL);
423		else
424			reg = (reg & ~0x1000UL);
425
426		NXWR32(adapter,
427			NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
428	}
429
430	mac_cfg |= 0x4;
431	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg);
432
433	return 0;
434}
435
436static int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
437{
438	u32 mac_hi, mac_lo;
439	u32 reg_hi, reg_lo;
440
441	u8 phy = adapter->physical_port;
442
443	if (phy >= NETXEN_NIU_MAX_XG_PORTS)
444		return -EINVAL;
445
446	mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);
447	mac_hi = addr[2] | ((u32)addr[3] << 8) |
448		((u32)addr[4] << 16) | ((u32)addr[5] << 24);
449
450	reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);
451	reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);
452
453	/* write twice to flush */
454	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
455		return -EIO;
456	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
457		return -EIO;
458
459	return 0;
460}
461
462static int
463netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
464{
465	u32	val = 0;
466	u16 port = adapter->physical_port;
467	u8 *addr = adapter->mac_addr;
468
469	if (adapter->mc_enabled)
470		return 0;
471
472	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
473	val |= (1UL << (28+port));
474	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
475
476	/* add broadcast addr to filter */
477	val = 0xffffff;
478	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
479	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
480
481	/* add station addr to filter */
482	val = MAC_HI(addr);
483	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
484	val = MAC_LO(addr);
485	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val);
486
487	adapter->mc_enabled = 1;
488	return 0;
489}
490
491static int
492netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
493{
494	u32	val = 0;
495	u16 port = adapter->physical_port;
496	u8 *addr = adapter->mac_addr;
497
498	if (!adapter->mc_enabled)
499		return 0;
500
501	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
502	val &= ~(1UL << (28+port));
503	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
504
505	val = MAC_HI(addr);
506	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
507	val = MAC_LO(addr);
508	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
509
510	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
511	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
512
513	adapter->mc_enabled = 0;
514	return 0;
515}
516
517static int
518netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
519		int index, u8 *addr)
520{
521	u32 hi = 0, lo = 0;
522	u16 port = adapter->physical_port;
523
524	lo = MAC_LO(addr);
525	hi = MAC_HI(addr);
526
527	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi);
528	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo);
529
530	return 0;
531}
532
533static void netxen_p2_nic_set_multi(struct net_device *netdev)
534{
535	struct netxen_adapter *adapter = netdev_priv(netdev);
536	struct netdev_hw_addr *ha;
537	u8 null_addr[ETH_ALEN];
538	int i;
539
540	eth_zero_addr(null_addr);
541
542	if (netdev->flags & IFF_PROMISC) {
543
544		adapter->set_promisc(adapter,
545				NETXEN_NIU_PROMISC_MODE);
546
547		/* Full promiscuous mode */
548		netxen_nic_disable_mcast_filter(adapter);
549
550		return;
551	}
552
553	if (netdev_mc_empty(netdev)) {
554		adapter->set_promisc(adapter,
555				NETXEN_NIU_NON_PROMISC_MODE);
556		netxen_nic_disable_mcast_filter(adapter);
557		return;
558	}
559
560	adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
561	if (netdev->flags & IFF_ALLMULTI ||
562			netdev_mc_count(netdev) > adapter->max_mc_count) {
563		netxen_nic_disable_mcast_filter(adapter);
564		return;
565	}
566
567	netxen_nic_enable_mcast_filter(adapter);
568
569	i = 0;
570	netdev_for_each_mc_addr(ha, netdev)
571		netxen_nic_set_mcast_addr(adapter, i++, ha->addr);
572
573	/* Clear out remaining addresses */
574	while (i < adapter->max_mc_count)
575		netxen_nic_set_mcast_addr(adapter, i++, null_addr);
576}
577
578static int
579netxen_send_cmd_descs(struct netxen_adapter *adapter,
580		struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
581{
582	u32 i, producer, consumer;
583	struct netxen_cmd_buffer *pbuf;
584	struct cmd_desc_type0 *cmd_desc;
585	struct nx_host_tx_ring *tx_ring;
586
587	i = 0;
588
589	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
590		return -EIO;
591
592	tx_ring = adapter->tx_ring;
593	__netif_tx_lock_bh(tx_ring->txq);
594
595	producer = tx_ring->producer;
596	consumer = tx_ring->sw_consumer;
597
598	if (nr_desc >= netxen_tx_avail(tx_ring)) {
599		netif_tx_stop_queue(tx_ring->txq);
600		smp_mb();
601		if (netxen_tx_avail(tx_ring) > nr_desc) {
602			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
603				netif_tx_wake_queue(tx_ring->txq);
604		} else {
605			__netif_tx_unlock_bh(tx_ring->txq);
606			return -EBUSY;
607		}
608	}
609
610	do {
611		cmd_desc = &cmd_desc_arr[i];
612
613		pbuf = &tx_ring->cmd_buf_arr[producer];
614		pbuf->skb = NULL;
615		pbuf->frag_count = 0;
616
617		memcpy(&tx_ring->desc_head[producer],
618			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
619
620		producer = get_next_index(producer, tx_ring->num_desc);
621		i++;
622
623	} while (i != nr_desc);
624
625	tx_ring->producer = producer;
626
627	netxen_nic_update_cmd_producer(adapter, tx_ring);
628
629	__netif_tx_unlock_bh(tx_ring->txq);
630
631	return 0;
632}
633
634static int
635nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)
636{
637	nx_nic_req_t req;
638	nx_mac_req_t *mac_req;
639	u64 word;
640
641	memset(&req, 0, sizeof(nx_nic_req_t));
642	req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
643
644	word = NX_MAC_EVENT | ((u64)adapter->portnum << 16);
645	req.req_hdr = cpu_to_le64(word);
646
647	mac_req = (nx_mac_req_t *)&req.words[0];
648	mac_req->op = op;
649	memcpy(mac_req->mac_addr, addr, ETH_ALEN);
650
651	return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
652}
653
654static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
655		const u8 *addr, struct list_head *del_list)
656{
657	struct list_head *head;
658	nx_mac_list_t *cur;
659
660	/* look up if already exists */
661	list_for_each(head, del_list) {
662		cur = list_entry(head, nx_mac_list_t, list);
663
664		if (ether_addr_equal(addr, cur->mac_addr)) {
665			list_move_tail(head, &adapter->mac_list);
666			return 0;
667		}
668	}
669
670	cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);
671	if (cur == NULL)
672		return -ENOMEM;
673
674	memcpy(cur->mac_addr, addr, ETH_ALEN);
675	list_add_tail(&cur->list, &adapter->mac_list);
676	return nx_p3_sre_macaddr_change(adapter,
677				cur->mac_addr, NETXEN_MAC_ADD);
678}
679
680static void netxen_p3_nic_set_multi(struct net_device *netdev)
681{
682	struct netxen_adapter *adapter = netdev_priv(netdev);
683	struct netdev_hw_addr *ha;
684	static const u8 bcast_addr[ETH_ALEN] = {
685		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
686	};
687	u32 mode = VPORT_MISS_MODE_DROP;
688	LIST_HEAD(del_list);
689	struct list_head *head;
690	nx_mac_list_t *cur;
691
692	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
693		return;
694
695	list_splice_tail_init(&adapter->mac_list, &del_list);
696
697	nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list);
698	nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);
699
700	if (netdev->flags & IFF_PROMISC) {
701		mode = VPORT_MISS_MODE_ACCEPT_ALL;
702		goto send_fw_cmd;
703	}
704
705	if ((netdev->flags & IFF_ALLMULTI) ||
706			(netdev_mc_count(netdev) > adapter->max_mc_count)) {
707		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
708		goto send_fw_cmd;
709	}
710
711	if (!netdev_mc_empty(netdev)) {
712		netdev_for_each_mc_addr(ha, netdev)
713			nx_p3_nic_add_mac(adapter, ha->addr, &del_list);
714	}
715
716send_fw_cmd:
717	adapter->set_promisc(adapter, mode);
718	head = &del_list;
719	while (!list_empty(head)) {
720		cur = list_entry(head->next, nx_mac_list_t, list);
721
722		nx_p3_sre_macaddr_change(adapter,
723				cur->mac_addr, NETXEN_MAC_DEL);
724		list_del(&cur->list);
725		kfree(cur);
726	}
727}
728
729static int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
730{
731	nx_nic_req_t req;
732	u64 word;
733
734	memset(&req, 0, sizeof(nx_nic_req_t));
735
736	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
737
738	word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |
739			((u64)adapter->portnum << 16);
740	req.req_hdr = cpu_to_le64(word);
741
742	req.words[0] = cpu_to_le64(mode);
743
744	return netxen_send_cmd_descs(adapter,
745				(struct cmd_desc_type0 *)&req, 1);
746}
747
748void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
749{
750	nx_mac_list_t *cur;
751	struct list_head *head = &adapter->mac_list;
752
753	while (!list_empty(head)) {
754		cur = list_entry(head->next, nx_mac_list_t, list);
755		nx_p3_sre_macaddr_change(adapter,
756				cur->mac_addr, NETXEN_MAC_DEL);
757		list_del(&cur->list);
758		kfree(cur);
759	}
760}
761
762static int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
763{
764	/* assuming caller has already copied new addr to netdev */
765	netxen_p3_nic_set_multi(adapter->netdev);
766	return 0;
767}
768
769#define	NETXEN_CONFIG_INTR_COALESCE	3
770
771/*
772 * Send the interrupt coalescing parameter set by ethtool to the card.
773 */
774int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
775{
776	nx_nic_req_t req;
777	u64 word[6];
778	int rv, i;
779
780	memset(&req, 0, sizeof(nx_nic_req_t));
781	memset(word, 0, sizeof(word));
782
783	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
784
785	word[0] = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);
786	req.req_hdr = cpu_to_le64(word[0]);
787
788	memcpy(&word[0], &adapter->coal, sizeof(adapter->coal));
789	for (i = 0; i < 6; i++)
790		req.words[i] = cpu_to_le64(word[i]);
791
792	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
793	if (rv != 0) {
794		printk(KERN_ERR "ERROR. Could not send "
795			"interrupt coalescing parameters\n");
796	}
797
798	return rv;
799}
800
801int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable)
802{
803	nx_nic_req_t req;
804	u64 word;
805	int rv = 0;
806
807	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
808		return 0;
809
810	memset(&req, 0, sizeof(nx_nic_req_t));
811
812	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
813
814	word = NX_NIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16);
815	req.req_hdr = cpu_to_le64(word);
816
817	req.words[0] = cpu_to_le64(enable);
818
819	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
820	if (rv != 0) {
821		printk(KERN_ERR "ERROR. Could not send "
822			"configure hw lro request\n");
823	}
824
825	return rv;
826}
827
828int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable)
829{
830	nx_nic_req_t req;
831	u64 word;
832	int rv = 0;
833
834	if (!!(adapter->flags & NETXEN_NIC_BRIDGE_ENABLED) == enable)
835		return rv;
836
837	memset(&req, 0, sizeof(nx_nic_req_t));
838
839	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
840
841	word = NX_NIC_H2C_OPCODE_CONFIG_BRIDGING |
842		((u64)adapter->portnum << 16);
843	req.req_hdr = cpu_to_le64(word);
844
845	req.words[0] = cpu_to_le64(enable);
846
847	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
848	if (rv != 0) {
849		printk(KERN_ERR "ERROR. Could not send "
850				"configure bridge mode request\n");
851	}
852
853	adapter->flags ^= NETXEN_NIC_BRIDGE_ENABLED;
854
855	return rv;
856}
857
858
859#define RSS_HASHTYPE_IP_TCP	0x3
860
861int netxen_config_rss(struct netxen_adapter *adapter, int enable)
862{
863	nx_nic_req_t req;
864	u64 word;
865	int i, rv;
866
867	static const u64 key[] = {
868		0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
869		0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
870		0x255b0ec26d5a56daULL
871	};
872
873
874	memset(&req, 0, sizeof(nx_nic_req_t));
875	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
876
877	word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);
878	req.req_hdr = cpu_to_le64(word);
879
880	/*
881	 * RSS request:
882	 * bits 3-0: hash_method
883	 *      5-4: hash_type_ipv4
884	 *	7-6: hash_type_ipv6
885	 *	  8: enable
886	 *        9: use indirection table
887	 *    47-10: reserved
888	 *    63-48: indirection table mask
889	 */
890	word =  ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
891		((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
892		((u64)(enable & 0x1) << 8) |
893		((0x7ULL) << 48);
894	req.words[0] = cpu_to_le64(word);
895	for (i = 0; i < ARRAY_SIZE(key); i++)
896		req.words[i+1] = cpu_to_le64(key[i]);
897
898
899	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
900	if (rv != 0) {
901		printk(KERN_ERR "%s: could not configure RSS\n",
902				adapter->netdev->name);
903	}
904
905	return rv;
906}
907
908int netxen_config_ipaddr(struct netxen_adapter *adapter, __be32 ip, int cmd)
909{
910	nx_nic_req_t req;
911	u64 word;
912	int rv;
913
914	memset(&req, 0, sizeof(nx_nic_req_t));
915	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
916
917	word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16);
918	req.req_hdr = cpu_to_le64(word);
919
920	req.words[0] = cpu_to_le64(cmd);
921	memcpy(&req.words[1], &ip, sizeof(u32));
922
923	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
924	if (rv != 0) {
925		printk(KERN_ERR "%s: could not notify %s IP 0x%x request\n",
926				adapter->netdev->name,
927				(cmd == NX_IP_UP) ? "Add" : "Remove", ip);
928	}
929	return rv;
930}
931
932int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
933{
934	nx_nic_req_t req;
935	u64 word;
936	int rv;
937
938	memset(&req, 0, sizeof(nx_nic_req_t));
939	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
940
941	word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
942	req.req_hdr = cpu_to_le64(word);
943	req.words[0] = cpu_to_le64(enable | (enable << 8));
944
945	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
946	if (rv != 0) {
947		printk(KERN_ERR "%s: could not configure link notification\n",
948				adapter->netdev->name);
949	}
950
951	return rv;
952}
953
954int netxen_send_lro_cleanup(struct netxen_adapter *adapter)
955{
956	nx_nic_req_t req;
957	u64 word;
958	int rv;
959
960	if (!test_bit(__NX_FW_ATTACHED, &adapter->state))
961		return 0;
962
963	memset(&req, 0, sizeof(nx_nic_req_t));
964	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
965
966	word = NX_NIC_H2C_OPCODE_LRO_REQUEST |
967		((u64)adapter->portnum << 16) |
968		((u64)NX_NIC_LRO_REQUEST_CLEANUP << 56) ;
969
970	req.req_hdr = cpu_to_le64(word);
971
972	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
973	if (rv != 0) {
974		printk(KERN_ERR "%s: could not cleanup lro flows\n",
975				adapter->netdev->name);
976	}
977	return rv;
978}
979
980/*
981 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
982 * @returns 0 on success, negative on failure
983 */
984
985#define MTU_FUDGE_FACTOR	100
986
987int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
988{
989	struct netxen_adapter *adapter = netdev_priv(netdev);
990	int max_mtu;
991	int rc = 0;
992
993	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
994		max_mtu = P3_MAX_MTU;
995	else
996		max_mtu = P2_MAX_MTU;
997
998	if (mtu > max_mtu) {
999		printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
1000				netdev->name, max_mtu);
1001		return -EINVAL;
1002	}
1003
1004	if (adapter->set_mtu)
1005		rc = adapter->set_mtu(adapter, mtu);
1006
1007	if (!rc)
1008		netdev->mtu = mtu;
1009
1010	return rc;
1011}
1012
1013static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
1014				  int size, __le32 * buf)
1015{
1016	int i, v, addr;
1017	__le32 *ptr32;
1018
1019	addr = base;
1020	ptr32 = buf;
1021	for (i = 0; i < size / sizeof(u32); i++) {
1022		if (netxen_rom_fast_read(adapter, addr, &v) == -1)
1023			return -1;
1024		*ptr32 = cpu_to_le32(v);
1025		ptr32++;
1026		addr += sizeof(u32);
1027	}
1028	if ((char *)buf + size > (char *)ptr32) {
1029		__le32 local;
1030		if (netxen_rom_fast_read(adapter, addr, &v) == -1)
1031			return -1;
1032		local = cpu_to_le32(v);
1033		memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
1034	}
1035
1036	return 0;
1037}
1038
1039int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac)
1040{
1041	__le32 *pmac = (__le32 *) mac;
1042	u32 offset;
1043
1044	offset = NX_FW_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64));
1045
1046	if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1)
1047		return -1;
1048
1049	if (*mac == ~0ULL) {
1050
1051		offset = NX_OLD_MAC_ADDR_OFFSET +
1052			(adapter->portnum * sizeof(u64));
1053
1054		if (netxen_get_flash_block(adapter,
1055					offset, sizeof(u64), pmac) == -1)
1056			return -1;
1057
1058		if (*mac == ~0ULL)
1059			return -1;
1060	}
1061	return 0;
1062}
1063
1064int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac)
1065{
1066	uint32_t crbaddr, mac_hi, mac_lo;
1067	int pci_func = adapter->ahw.pci_func;
1068
1069	crbaddr = CRB_MAC_BLOCK_START +
1070		(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
1071
1072	mac_lo = NXRD32(adapter, crbaddr);
1073	mac_hi = NXRD32(adapter, crbaddr+4);
1074
1075	if (pci_func & 1)
1076		*mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
1077	else
1078		*mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));
1079
1080	return 0;
1081}
1082
1083/*
1084 * Changes the CRB window to the specified window.
1085 */
1086static void
1087netxen_nic_pci_set_crbwindow_128M(struct netxen_adapter *adapter,
1088		u32 window)
1089{
1090	void __iomem *offset;
1091	int count = 10;
1092	u8 func = adapter->ahw.pci_func;
1093
1094	if (adapter->ahw.crb_win == window)
1095		return;
1096
1097	offset = PCI_OFFSET_SECOND_RANGE(adapter,
1098			NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
1099
1100	writel(window, offset);
1101	do {
1102		if (window == readl(offset))
1103			break;
1104
1105		if (printk_ratelimit())
1106			dev_warn(&adapter->pdev->dev,
1107					"failed to set CRB window to %d\n",
1108					(window == NETXEN_WINDOW_ONE));
1109		udelay(1);
1110
1111	} while (--count > 0);
1112
1113	if (count > 0)
1114		adapter->ahw.crb_win = window;
1115}
1116
1117/*
1118 * Returns < 0 if off is not valid,
1119 *	 1 if window access is needed. 'off' is set to offset from
1120 *	   CRB space in 128M pci map
1121 *	 0 if no window access is needed. 'off' is set to 2M addr
1122 * In: 'off' is offset from base in 128M pci map
1123 */
1124static int
1125netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
1126		ulong off, void __iomem **addr)
1127{
1128	crb_128M_2M_sub_block_map_t *m;
1129
1130
1131	if ((off >= NETXEN_CRB_MAX) || (off < NETXEN_PCI_CRBSPACE))
1132		return -EINVAL;
1133
1134	off -= NETXEN_PCI_CRBSPACE;
1135
1136	/*
1137	 * Try direct map
1138	 */
1139	m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
1140
1141	if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
1142		*addr = adapter->ahw.pci_base0 + m->start_2M +
1143			(off - m->start_128M);
1144		return 0;
1145	}
1146
1147	/*
1148	 * Not in direct map, use crb window
1149	 */
1150	*addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M +
1151		(off & MASK(16));
1152	return 1;
1153}
1154
1155/*
1156 * In: 'off' is offset from CRB space in 128M pci map
1157 * Out: 'off' is 2M pci map addr
1158 * side effect: lock crb window
1159 */
1160static void
1161netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
1162{
1163	u32 window;
1164	void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M;
1165
1166	off -= NETXEN_PCI_CRBSPACE;
1167
1168	window = CRB_HI(off);
1169
1170	writel(window, addr);
1171	if (readl(addr) != window) {
1172		if (printk_ratelimit())
1173			dev_warn(&adapter->pdev->dev,
1174				"failed to set CRB window to %d off 0x%lx\n",
1175				window, off);
1176	}
1177}
1178
1179static void __iomem *
1180netxen_nic_map_indirect_address_128M(struct netxen_adapter *adapter,
1181		ulong win_off, void __iomem **mem_ptr)
1182{
1183	ulong off = win_off;
1184	void __iomem *addr;
1185	resource_size_t mem_base;
1186
1187	if (ADDR_IN_WINDOW1(win_off))
1188		off = NETXEN_CRB_NORMAL(win_off);
1189
1190	addr = pci_base_offset(adapter, off);
1191	if (addr)
1192		return addr;
1193
1194	if (adapter->ahw.pci_len0 == 0)
1195		off -= NETXEN_PCI_CRBSPACE;
1196
1197	mem_base = pci_resource_start(adapter->pdev, 0);
1198	*mem_ptr = ioremap(mem_base + (off & PAGE_MASK), PAGE_SIZE);
1199	if (*mem_ptr)
1200		addr = *mem_ptr + (off & (PAGE_SIZE - 1));
1201
1202	return addr;
1203}
1204
1205static int
1206netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
1207{
1208	unsigned long flags;
1209	void __iomem *addr, *mem_ptr = NULL;
1210
1211	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);
1212	if (!addr)
1213		return -EIO;
1214
1215	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
1216		netxen_nic_io_write_128M(adapter, addr, data);
1217	} else {        /* Window 0 */
1218		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
1219		netxen_nic_pci_set_crbwindow_128M(adapter, 0);
1220		writel(data, addr);
1221		netxen_nic_pci_set_crbwindow_128M(adapter,
1222				NETXEN_WINDOW_ONE);
1223		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
1224	}
1225
1226	if (mem_ptr)
1227		iounmap(mem_ptr);
1228
1229	return 0;
1230}
1231
1232static u32
1233netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)
1234{
1235	unsigned long flags;
1236	void __iomem *addr, *mem_ptr = NULL;
1237	u32 data;
1238
1239	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);
1240	if (!addr)
1241		return -EIO;
1242
1243	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
1244		data = netxen_nic_io_read_128M(adapter, addr);
1245	} else {        /* Window 0 */
1246		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
1247		netxen_nic_pci_set_crbwindow_128M(adapter, 0);
1248		data = readl(addr);
1249		netxen_nic_pci_set_crbwindow_128M(adapter,
1250				NETXEN_WINDOW_ONE);
1251		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
1252	}
1253
1254	if (mem_ptr)
1255		iounmap(mem_ptr);
1256
1257	return data;
1258}
1259
1260static int
1261netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data)
1262{
1263	unsigned long flags;
1264	int rv;
1265	void __iomem *addr = NULL;
1266
1267	rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr);
1268
1269	if (rv == 0) {
1270		writel(data, addr);
1271		return 0;
1272	}
1273
1274	if (rv > 0) {
1275		/* indirect access */
1276		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
1277		crb_win_lock(adapter);
1278		netxen_nic_pci_set_crbwindow_2M(adapter, off);
1279		writel(data, addr);
1280		crb_win_unlock(adapter);
1281		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
1282		return 0;
1283	}
1284
1285	dev_err(&adapter->pdev->dev,
1286			"%s: invalid offset: 0x%016lx\n", __func__, off);
1287	dump_stack();
1288	return -EIO;
1289}
1290
1291static u32
1292netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off)
1293{
1294	unsigned long flags;
1295	int rv;
1296	u32 data;
1297	void __iomem *addr = NULL;
1298
1299	rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr);
1300
1301	if (rv == 0)
1302		return readl(addr);
1303
1304	if (rv > 0) {
1305		/* indirect access */
1306		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
1307		crb_win_lock(adapter);
1308		netxen_nic_pci_set_crbwindow_2M(adapter, off);
1309		data = readl(addr);
1310		crb_win_unlock(adapter);
1311		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
1312		return data;
1313	}
1314
1315	dev_err(&adapter->pdev->dev,
1316			"%s: invalid offset: 0x%016lx\n", __func__, off);
1317	dump_stack();
1318	return -1;
1319}
1320
1321/* window 1 registers only */
1322static void netxen_nic_io_write_128M(struct netxen_adapter *adapter,
1323		void __iomem *addr, u32 data)
1324{
1325	read_lock(&adapter->ahw.crb_lock);
1326	writel(data, addr);
1327	read_unlock(&adapter->ahw.crb_lock);
1328}
1329
1330static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter,
1331		void __iomem *addr)
1332{
1333	u32 val;
1334
1335	read_lock(&adapter->ahw.crb_lock);
1336	val = readl(addr);
1337	read_unlock(&adapter->ahw.crb_lock);
1338
1339	return val;
1340}
1341
1342static void netxen_nic_io_write_2M(struct netxen_adapter *adapter,
1343		void __iomem *addr, u32 data)
1344{
1345	writel(data, addr);
1346}
1347
1348static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter,
1349		void __iomem *addr)
1350{
1351	return readl(addr);
1352}
1353
1354void __iomem *
1355netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset)
1356{
1357	void __iomem *addr = NULL;
1358
1359	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1360		if ((offset < NETXEN_CRB_PCIX_HOST2) &&
1361				(offset > NETXEN_CRB_PCIX_HOST))
1362			addr = PCI_OFFSET_SECOND_RANGE(adapter, offset);
1363		else
1364			addr = NETXEN_CRB_NORMALIZE(adapter, offset);
1365	} else {
1366		WARN_ON(netxen_nic_pci_get_crb_addr_2M(adapter,
1367					offset, &addr));
1368	}
1369
1370	return addr;
1371}
1372
1373static int
1374netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
1375		u64 addr, u32 *start)
1376{
1377	if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
1378		*start = (addr - NETXEN_ADDR_OCM0  + NETXEN_PCI_OCM0);
1379		return 0;
1380	} else if (ADDR_IN_RANGE(addr,
1381				NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
1382		*start = (addr - NETXEN_ADDR_OCM1 + NETXEN_PCI_OCM1);
1383		return 0;
1384	}
1385
1386	return -EIO;
1387}
1388
1389static int
1390netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
1391		u64 addr, u32 *start)
1392{
1393	u32 window;
1394
1395	window = OCM_WIN(addr);
1396
1397	writel(window, adapter->ahw.ocm_win_crb);
1398	/* read back to flush */
1399	readl(adapter->ahw.ocm_win_crb);
1400
1401	adapter->ahw.ocm_win = window;
1402	*start = NETXEN_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);
1403	return 0;
1404}
1405
1406static int
1407netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off,
1408		u64 *data, int op)
1409{
1410	void __iomem *addr, *mem_ptr = NULL;
1411	resource_size_t mem_base;
1412	int ret;
1413	u32 start;
1414
1415	spin_lock(&adapter->ahw.mem_lock);
1416
1417	ret = adapter->pci_set_window(adapter, off, &start);
1418	if (ret != 0)
1419		goto unlock;
1420
1421	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
1422		addr = adapter->ahw.pci_base0 + start;
1423	} else {
1424		addr = pci_base_offset(adapter, start);
1425		if (addr)
1426			goto noremap;
1427
1428		mem_base = pci_resource_start(adapter->pdev, 0) +
1429					(start & PAGE_MASK);
1430		mem_ptr = ioremap(mem_base, PAGE_SIZE);
1431		if (mem_ptr == NULL) {
1432			ret = -EIO;
1433			goto unlock;
1434		}
1435
1436		addr = mem_ptr + (start & (PAGE_SIZE-1));
1437	}
1438noremap:
1439	if (op == 0)	/* read */
1440		*data = readq(addr);
1441	else		/* write */
1442		writeq(*data, addr);
1443
1444unlock:
1445	spin_unlock(&adapter->ahw.mem_lock);
1446
1447	if (mem_ptr)
1448		iounmap(mem_ptr);
1449	return ret;
1450}
1451
1452void
1453netxen_pci_camqm_read_2M(struct netxen_adapter *adapter, u64 off, u64 *data)
1454{
1455	void __iomem *addr = adapter->ahw.pci_base0 +
1456		NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM);
1457
1458	spin_lock(&adapter->ahw.mem_lock);
1459	*data = readq(addr);
1460	spin_unlock(&adapter->ahw.mem_lock);
1461}
1462
1463void
1464netxen_pci_camqm_write_2M(struct netxen_adapter *adapter, u64 off, u64 data)
1465{
1466	void __iomem *addr = adapter->ahw.pci_base0 +
1467		NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM);
1468
1469	spin_lock(&adapter->ahw.mem_lock);
1470	writeq(data, addr);
1471	spin_unlock(&adapter->ahw.mem_lock);
1472}
1473
1474#define MAX_CTL_CHECK   1000
1475
1476static int
1477netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
1478		u64 off, u64 data)
1479{
1480	int j, ret;
1481	u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;
1482	void __iomem *mem_crb;
1483
1484	/* Only 64-bit aligned access */
1485	if (off & 7)
1486		return -EIO;
1487
1488	/* P2 has different SIU and MIU test agent base addr */
1489	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
1490				NETXEN_ADDR_QDR_NET_MAX_P2)) {
1491		mem_crb = pci_base_offset(adapter,
1492				NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);
1493		addr_hi = SIU_TEST_AGT_ADDR_HI;
1494		data_lo = SIU_TEST_AGT_WRDATA_LO;
1495		data_hi = SIU_TEST_AGT_WRDATA_HI;
1496		off_lo = off & SIU_TEST_AGT_ADDR_MASK;
1497		off_hi = SIU_TEST_AGT_UPPER_ADDR(off);
1498		goto correct;
1499	}
1500
1501	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1502		mem_crb = pci_base_offset(adapter,
1503				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
1504		addr_hi = MIU_TEST_AGT_ADDR_HI;
1505		data_lo = MIU_TEST_AGT_WRDATA_LO;
1506		data_hi = MIU_TEST_AGT_WRDATA_HI;
1507		off_lo = off & MIU_TEST_AGT_ADDR_MASK;
1508		off_hi = 0;
1509		goto correct;
1510	}
1511
1512	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) ||
1513		ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
1514		if (adapter->ahw.pci_len0 != 0) {
1515			return netxen_nic_pci_mem_access_direct(adapter,
1516					off, &data, 1);
1517		}
1518	}
1519
1520	return -EIO;
1521
1522correct:
1523	spin_lock(&adapter->ahw.mem_lock);
1524	netxen_nic_pci_set_crbwindow_128M(adapter, 0);
1525
1526	writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));
1527	writel(off_hi, (mem_crb + addr_hi));
1528	writel(data & 0xffffffff, (mem_crb + data_lo));
1529	writel((data >> 32) & 0xffffffff, (mem_crb + data_hi));
1530	writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
1531	writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
1532			(mem_crb + TEST_AGT_CTRL));
1533
1534	for (j = 0; j < MAX_CTL_CHECK; j++) {
1535		temp = readl((mem_crb + TEST_AGT_CTRL));
1536		if ((temp & TA_CTL_BUSY) == 0)
1537			break;
1538	}
1539
1540	if (j >= MAX_CTL_CHECK) {
1541		if (printk_ratelimit())
1542			dev_err(&adapter->pdev->dev,
1543					"failed to write through agent\n");
1544		ret = -EIO;
1545	} else
1546		ret = 0;
1547
1548	netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE);
1549	spin_unlock(&adapter->ahw.mem_lock);
1550	return ret;
1551}
1552
1553static int
1554netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
1555		u64 off, u64 *data)
1556{
1557	int j, ret;
1558	u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo;
1559	u64 val;
1560	void __iomem *mem_crb;
1561
1562	/* Only 64-bit aligned access */
1563	if (off & 7)
1564		return -EIO;
1565
1566	/* P2 has different SIU and MIU test agent base addr */
1567	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
1568				NETXEN_ADDR_QDR_NET_MAX_P2)) {
1569		mem_crb = pci_base_offset(adapter,
1570				NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE);
1571		addr_hi = SIU_TEST_AGT_ADDR_HI;
1572		data_lo = SIU_TEST_AGT_RDDATA_LO;
1573		data_hi = SIU_TEST_AGT_RDDATA_HI;
1574		off_lo = off & SIU_TEST_AGT_ADDR_MASK;
1575		off_hi = SIU_TEST_AGT_UPPER_ADDR(off);
1576		goto correct;
1577	}
1578
1579	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1580		mem_crb = pci_base_offset(adapter,
1581				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
1582		addr_hi = MIU_TEST_AGT_ADDR_HI;
1583		data_lo = MIU_TEST_AGT_RDDATA_LO;
1584		data_hi = MIU_TEST_AGT_RDDATA_HI;
1585		off_lo = off & MIU_TEST_AGT_ADDR_MASK;
1586		off_hi = 0;
1587		goto correct;
1588	}
1589
1590	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) ||
1591		ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
1592		if (adapter->ahw.pci_len0 != 0) {
1593			return netxen_nic_pci_mem_access_direct(adapter,
1594					off, data, 0);
1595		}
1596	}
1597
1598	return -EIO;
1599
1600correct:
1601	spin_lock(&adapter->ahw.mem_lock);
1602	netxen_nic_pci_set_crbwindow_128M(adapter, 0);
1603
1604	writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO));
1605	writel(off_hi, (mem_crb + addr_hi));
1606	writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
1607	writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
1608
1609	for (j = 0; j < MAX_CTL_CHECK; j++) {
1610		temp = readl(mem_crb + TEST_AGT_CTRL);
1611		if ((temp & TA_CTL_BUSY) == 0)
1612			break;
1613	}
1614
1615	if (j >= MAX_CTL_CHECK) {
1616		if (printk_ratelimit())
1617			dev_err(&adapter->pdev->dev,
1618					"failed to read through agent\n");
1619		ret = -EIO;
1620	} else {
1621
1622		temp = readl(mem_crb + data_hi);
1623		val = ((u64)temp << 32);
1624		val |= readl(mem_crb + data_lo);
1625		*data = val;
1626		ret = 0;
1627	}
1628
1629	netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE);
1630	spin_unlock(&adapter->ahw.mem_lock);
1631
1632	return ret;
1633}
1634
1635static int
1636netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
1637		u64 off, u64 data)
1638{
1639	int j, ret;
1640	u32 temp, off8;
1641	void __iomem *mem_crb;
1642
1643	/* Only 64-bit aligned access */
1644	if (off & 7)
1645		return -EIO;
1646
1647	/* P3 onward, test agent base for MIU and SIU is same */
1648	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
1649				NETXEN_ADDR_QDR_NET_MAX_P3)) {
1650		mem_crb = netxen_get_ioaddr(adapter,
1651				NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);
1652		goto correct;
1653	}
1654
1655	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1656		mem_crb = netxen_get_ioaddr(adapter,
1657				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
1658		goto correct;
1659	}
1660
1661	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX))
1662		return netxen_nic_pci_mem_access_direct(adapter, off, &data, 1);
1663
1664	return -EIO;
1665
1666correct:
1667	off8 = off & 0xfffffff8;
1668
1669	spin_lock(&adapter->ahw.mem_lock);
1670
1671	writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
1672	writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
1673
1674	writel(data & 0xffffffff,
1675			mem_crb + MIU_TEST_AGT_WRDATA_LO);
1676	writel((data >> 32) & 0xffffffff,
1677			mem_crb + MIU_TEST_AGT_WRDATA_HI);
1678
1679	writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
1680	writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
1681			(mem_crb + TEST_AGT_CTRL));
1682
1683	for (j = 0; j < MAX_CTL_CHECK; j++) {
1684		temp = readl(mem_crb + TEST_AGT_CTRL);
1685		if ((temp & TA_CTL_BUSY) == 0)
1686			break;
1687	}
1688
1689	if (j >= MAX_CTL_CHECK) {
1690		if (printk_ratelimit())
1691			dev_err(&adapter->pdev->dev,
1692					"failed to write through agent\n");
1693		ret = -EIO;
1694	} else
1695		ret = 0;
1696
1697	spin_unlock(&adapter->ahw.mem_lock);
1698
1699	return ret;
1700}
1701
1702static int
1703netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
1704		u64 off, u64 *data)
1705{
1706	int j, ret;
1707	u32 temp, off8;
1708	u64 val;
1709	void __iomem *mem_crb;
1710
1711	/* Only 64-bit aligned access */
1712	if (off & 7)
1713		return -EIO;
1714
1715	/* P3 onward, test agent base for MIU and SIU is same */
1716	if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET,
1717				NETXEN_ADDR_QDR_NET_MAX_P3)) {
1718		mem_crb = netxen_get_ioaddr(adapter,
1719				NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE);
1720		goto correct;
1721	}
1722
1723	if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
1724		mem_crb = netxen_get_ioaddr(adapter,
1725				NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE);
1726		goto correct;
1727	}
1728
1729	if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
1730		return netxen_nic_pci_mem_access_direct(adapter,
1731				off, data, 0);
1732	}
1733
1734	return -EIO;
1735
1736correct:
1737	off8 = off & 0xfffffff8;
1738
1739	spin_lock(&adapter->ahw.mem_lock);
1740
1741	writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
1742	writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
1743	writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
1744	writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
1745
1746	for (j = 0; j < MAX_CTL_CHECK; j++) {
1747		temp = readl(mem_crb + TEST_AGT_CTRL);
1748		if ((temp & TA_CTL_BUSY) == 0)
1749			break;
1750	}
1751
1752	if (j >= MAX_CTL_CHECK) {
1753		if (printk_ratelimit())
1754			dev_err(&adapter->pdev->dev,
1755					"failed to read through agent\n");
1756		ret = -EIO;
1757	} else {
1758		val = (u64)(readl(mem_crb + MIU_TEST_AGT_RDDATA_HI)) << 32;
1759		val |= readl(mem_crb + MIU_TEST_AGT_RDDATA_LO);
1760		*data = val;
1761		ret = 0;
1762	}
1763
1764	spin_unlock(&adapter->ahw.mem_lock);
1765
1766	return ret;
1767}
1768
1769void
1770netxen_setup_hwops(struct netxen_adapter *adapter)
1771{
1772	adapter->init_port = netxen_niu_xg_init_port;
1773	adapter->stop_port = netxen_niu_disable_xg_port;
1774
1775	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
1776		adapter->crb_read = netxen_nic_hw_read_wx_128M,
1777		adapter->crb_write = netxen_nic_hw_write_wx_128M,
1778		adapter->pci_set_window = netxen_nic_pci_set_window_128M,
1779		adapter->pci_mem_read = netxen_nic_pci_mem_read_128M,
1780		adapter->pci_mem_write = netxen_nic_pci_mem_write_128M,
1781		adapter->io_read = netxen_nic_io_read_128M,
1782		adapter->io_write = netxen_nic_io_write_128M,
1783
1784		adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
1785		adapter->set_multi = netxen_p2_nic_set_multi;
1786		adapter->set_mtu = netxen_nic_set_mtu_xgb;
1787		adapter->set_promisc = netxen_p2_nic_set_promisc;
1788
1789	} else {
1790		adapter->crb_read = netxen_nic_hw_read_wx_2M,
1791		adapter->crb_write = netxen_nic_hw_write_wx_2M,
1792		adapter->pci_set_window = netxen_nic_pci_set_window_2M,
1793		adapter->pci_mem_read = netxen_nic_pci_mem_read_2M,
1794		adapter->pci_mem_write = netxen_nic_pci_mem_write_2M,
1795		adapter->io_read = netxen_nic_io_read_2M,
1796		adapter->io_write = netxen_nic_io_write_2M,
1797
1798		adapter->set_mtu = nx_fw_cmd_set_mtu;
1799		adapter->set_promisc = netxen_p3_nic_set_promisc;
1800		adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
1801		adapter->set_multi = netxen_p3_nic_set_multi;
1802
1803		adapter->phy_read = nx_fw_cmd_query_phy;
1804		adapter->phy_write = nx_fw_cmd_set_phy;
1805	}
1806}
1807
1808int netxen_nic_get_board_info(struct netxen_adapter *adapter)
1809{
1810	int offset, board_type, magic;
1811	struct pci_dev *pdev = adapter->pdev;
1812
1813	offset = NX_FW_MAGIC_OFFSET;
1814	if (netxen_rom_fast_read(adapter, offset, &magic))
1815		return -EIO;
1816
1817	if (magic != NETXEN_BDINFO_MAGIC) {
1818		dev_err(&pdev->dev, "invalid board config, magic=%08x\n",
1819			magic);
1820		return -EIO;
1821	}
1822
1823	offset = NX_BRDTYPE_OFFSET;
1824	if (netxen_rom_fast_read(adapter, offset, &board_type))
1825		return -EIO;
1826
1827	if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
1828		u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);
1829		if ((gpio & 0x8000) == 0)
1830			board_type = NETXEN_BRDTYPE_P3_10G_TP;
1831	}
1832
1833	adapter->ahw.board_type = board_type;
1834
1835	switch (board_type) {
1836	case NETXEN_BRDTYPE_P2_SB35_4G:
1837		adapter->ahw.port_type = NETXEN_NIC_GBE;
1838		break;
1839	case NETXEN_BRDTYPE_P2_SB31_10G:
1840	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
1841	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
1842	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
1843	case NETXEN_BRDTYPE_P3_HMEZ:
1844	case NETXEN_BRDTYPE_P3_XG_LOM:
1845	case NETXEN_BRDTYPE_P3_10G_CX4:
1846	case NETXEN_BRDTYPE_P3_10G_CX4_LP:
1847	case NETXEN_BRDTYPE_P3_IMEZ:
1848	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
1849	case NETXEN_BRDTYPE_P3_10G_SFP_CT:
1850	case NETXEN_BRDTYPE_P3_10G_SFP_QT:
1851	case NETXEN_BRDTYPE_P3_10G_XFP:
1852	case NETXEN_BRDTYPE_P3_10000_BASE_T:
1853		adapter->ahw.port_type = NETXEN_NIC_XGBE;
1854		break;
1855	case NETXEN_BRDTYPE_P1_BD:
1856	case NETXEN_BRDTYPE_P1_SB:
1857	case NETXEN_BRDTYPE_P1_SMAX:
1858	case NETXEN_BRDTYPE_P1_SOCK:
1859	case NETXEN_BRDTYPE_P3_REF_QG:
1860	case NETXEN_BRDTYPE_P3_4_GB:
1861	case NETXEN_BRDTYPE_P3_4_GB_MM:
1862		adapter->ahw.port_type = NETXEN_NIC_GBE;
1863		break;
1864	case NETXEN_BRDTYPE_P3_10G_TP:
1865		adapter->ahw.port_type = (adapter->portnum < 2) ?
1866			NETXEN_NIC_XGBE : NETXEN_NIC_GBE;
1867		break;
1868	default:
1869		dev_err(&pdev->dev, "unknown board type %x\n", board_type);
1870		adapter->ahw.port_type = NETXEN_NIC_XGBE;
1871		break;
1872	}
1873
1874	return 0;
1875}
1876
1877/* NIU access sections */
1878static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
1879{
1880	new_mtu += MTU_FUDGE_FACTOR;
1881	if (adapter->physical_port == 0)
1882		NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
1883	else
1884		NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu);
1885	return 0;
1886}
1887
1888void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
1889{
1890	__u32 status;
1891	__u32 autoneg;
1892	__u32 port_mode;
1893
1894	if (!netif_carrier_ok(adapter->netdev)) {
1895		adapter->link_speed   = 0;
1896		adapter->link_duplex  = -1;
1897		adapter->link_autoneg = AUTONEG_ENABLE;
1898		return;
1899	}
1900
1901	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
1902		port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
1903		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
1904			adapter->link_speed   = SPEED_1000;
1905			adapter->link_duplex  = DUPLEX_FULL;
1906			adapter->link_autoneg = AUTONEG_DISABLE;
1907			return;
1908		}
1909
1910		if (adapter->phy_read &&
1911		    adapter->phy_read(adapter,
1912				      NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
1913				      &status) == 0) {
1914			if (netxen_get_phy_link(status)) {
1915				switch (netxen_get_phy_speed(status)) {
1916				case 0:
1917					adapter->link_speed = SPEED_10;
1918					break;
1919				case 1:
1920					adapter->link_speed = SPEED_100;
1921					break;
1922				case 2:
1923					adapter->link_speed = SPEED_1000;
1924					break;
1925				default:
1926					adapter->link_speed = 0;
1927					break;
1928				}
1929				switch (netxen_get_phy_duplex(status)) {
1930				case 0:
1931					adapter->link_duplex = DUPLEX_HALF;
1932					break;
1933				case 1:
1934					adapter->link_duplex = DUPLEX_FULL;
1935					break;
1936				default:
1937					adapter->link_duplex = -1;
1938					break;
1939				}
1940				if (adapter->phy_read &&
1941				    adapter->phy_read(adapter,
1942						      NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
1943						      &autoneg) != 0)
1944					adapter->link_autoneg = autoneg;
1945			} else
1946				goto link_down;
1947		} else {
1948		      link_down:
1949			adapter->link_speed = 0;
1950			adapter->link_duplex = -1;
1951		}
1952	}
1953}
1954
1955int
1956netxen_nic_wol_supported(struct netxen_adapter *adapter)
1957{
1958	u32 wol_cfg;
1959
1960	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
1961		return 0;
1962
1963	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
1964	if (wol_cfg & (1UL << adapter->portnum)) {
1965		wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
1966		if (wol_cfg & (1 << adapter->portnum))
1967			return 1;
1968	}
1969
1970	return 0;
1971}
1972
1973static u32 netxen_md_cntrl(struct netxen_adapter *adapter,
1974			struct netxen_minidump_template_hdr *template_hdr,
1975			struct netxen_minidump_entry_crb *crtEntry)
1976{
1977	int loop_cnt, i, rv = 0, timeout_flag;
1978	u32 op_count, stride;
1979	u32 opcode, read_value, addr;
1980	unsigned long timeout, timeout_jiffies;
1981	addr = crtEntry->addr;
1982	op_count = crtEntry->op_count;
1983	stride = crtEntry->addr_stride;
1984
1985	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
1986		for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) {
1987			opcode = (crtEntry->opcode & (0x1 << i));
1988			if (opcode) {
1989				switch (opcode) {
1990				case NX_DUMP_WCRB:
1991					NX_WR_DUMP_REG(addr,
1992						adapter->ahw.pci_base0,
1993							crtEntry->value_1);
1994					break;
1995				case NX_DUMP_RWCRB:
1996					NX_RD_DUMP_REG(addr,
1997						adapter->ahw.pci_base0,
1998								&read_value);
1999					NX_WR_DUMP_REG(addr,
2000						adapter->ahw.pci_base0,
2001								read_value);
2002					break;
2003				case NX_DUMP_ANDCRB:
2004					NX_RD_DUMP_REG(addr,
2005						adapter->ahw.pci_base0,
2006								&read_value);
2007					read_value &= crtEntry->value_2;
2008					NX_WR_DUMP_REG(addr,
2009						adapter->ahw.pci_base0,
2010								read_value);
2011					break;
2012				case NX_DUMP_ORCRB:
2013					NX_RD_DUMP_REG(addr,
2014						adapter->ahw.pci_base0,
2015								&read_value);
2016					read_value |= crtEntry->value_3;
2017					NX_WR_DUMP_REG(addr,
2018						adapter->ahw.pci_base0,
2019								read_value);
2020					break;
2021				case NX_DUMP_POLLCRB:
2022					timeout = crtEntry->poll_timeout;
2023					NX_RD_DUMP_REG(addr,
2024						adapter->ahw.pci_base0,
2025								&read_value);
2026					timeout_jiffies =
2027					msecs_to_jiffies(timeout) + jiffies;
2028					for (timeout_flag = 0;
2029						!timeout_flag
2030					&& ((read_value & crtEntry->value_2)
2031					!= crtEntry->value_1);) {
2032						if (time_after(jiffies,
2033							timeout_jiffies))
2034							timeout_flag = 1;
2035					NX_RD_DUMP_REG(addr,
2036							adapter->ahw.pci_base0,
2037								&read_value);
2038					}
2039
2040					if (timeout_flag) {
2041						dev_err(&adapter->pdev->dev, "%s : "
2042							"Timeout in poll_crb control operation.\n"
2043								, __func__);
2044						return -1;
2045					}
2046					break;
2047				case NX_DUMP_RD_SAVE:
2048					/* Decide which address to use */
2049					if (crtEntry->state_index_a)
2050						addr =
2051						template_hdr->saved_state_array
2052						[crtEntry->state_index_a];
2053					NX_RD_DUMP_REG(addr,
2054						adapter->ahw.pci_base0,
2055								&read_value);
2056					template_hdr->saved_state_array
2057					[crtEntry->state_index_v]
2058						= read_value;
2059					break;
2060				case NX_DUMP_WRT_SAVED:
2061					/* Decide which value to use */
2062					if (crtEntry->state_index_v)
2063						read_value =
2064						template_hdr->saved_state_array
2065						[crtEntry->state_index_v];
2066					else
2067						read_value = crtEntry->value_1;
2068
2069					/* Decide which address to use */
2070					if (crtEntry->state_index_a)
2071						addr =
2072						template_hdr->saved_state_array
2073						[crtEntry->state_index_a];
2074
2075					NX_WR_DUMP_REG(addr,
2076						adapter->ahw.pci_base0,
2077								read_value);
2078					break;
2079				case NX_DUMP_MOD_SAVE_ST:
2080					read_value =
2081					template_hdr->saved_state_array
2082						[crtEntry->state_index_v];
2083					read_value <<= crtEntry->shl;
2084					read_value >>= crtEntry->shr;
2085					if (crtEntry->value_2)
2086						read_value &=
2087						crtEntry->value_2;
2088					read_value |= crtEntry->value_3;
2089					read_value += crtEntry->value_1;
2090					/* Write value back to state area.*/
2091					template_hdr->saved_state_array
2092						[crtEntry->state_index_v]
2093							= read_value;
2094					break;
2095				default:
2096					rv = 1;
2097					break;
2098				}
2099			}
2100		}
2101		addr = addr + stride;
2102	}
2103	return rv;
2104}
2105
2106/* Read memory or MN */
2107static u32
2108netxen_md_rdmem(struct netxen_adapter *adapter,
2109		struct netxen_minidump_entry_rdmem
2110			*memEntry, u64 *data_buff)
2111{
2112	u64 addr, value = 0;
2113	int i = 0, loop_cnt;
2114
2115	addr = (u64)memEntry->read_addr;
2116	loop_cnt = memEntry->read_data_size;    /* This is size in bytes */
2117	loop_cnt /= sizeof(value);
2118
2119	for (i = 0; i < loop_cnt; i++) {
2120		if (netxen_nic_pci_mem_read_2M(adapter, addr, &value))
2121			goto out;
2122		*data_buff++ = value;
2123		addr += sizeof(value);
2124	}
2125out:
2126	return i * sizeof(value);
2127}
2128
2129/* Read CRB operation */
2130static u32 netxen_md_rd_crb(struct netxen_adapter *adapter,
2131			struct netxen_minidump_entry_crb
2132				*crbEntry, u32 *data_buff)
2133{
2134	int loop_cnt;
2135	u32 op_count, addr, stride, value;
2136
2137	addr = crbEntry->addr;
2138	op_count = crbEntry->op_count;
2139	stride = crbEntry->addr_stride;
2140
2141	for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
2142		NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value);
2143		*data_buff++ = addr;
2144		*data_buff++ = value;
2145		addr = addr + stride;
2146	}
2147	return loop_cnt * (2 * sizeof(u32));
2148}
2149
2150/* Read ROM */
2151static u32
2152netxen_md_rdrom(struct netxen_adapter *adapter,
2153			struct netxen_minidump_entry_rdrom
2154				*romEntry, __le32 *data_buff)
2155{
2156	int i, count = 0;
2157	u32 size, lck_val;
2158	u32 val;
2159	u32 fl_addr, waddr, raddr;
2160	fl_addr = romEntry->read_addr;
2161	size = romEntry->read_data_size/4;
2162lock_try:
2163	lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 +
2164							NX_FLASH_SEM2_LK));
2165	if (!lck_val && count < MAX_CTL_CHECK) {
2166		msleep(20);
2167		count++;
2168		goto lock_try;
2169	}
2170	writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 +
2171							NX_FLASH_LOCK_ID));
2172	for (i = 0; i < size; i++) {
2173		waddr = fl_addr & 0xFFFF0000;
2174		NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr);
2175		raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF);
2176		NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val);
2177		*data_buff++ = cpu_to_le32(val);
2178		fl_addr += sizeof(val);
2179	}
2180	readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK));
2181	return romEntry->read_data_size;
2182}
2183
2184/* Handle L2 Cache */
2185static u32
2186netxen_md_L2Cache(struct netxen_adapter *adapter,
2187				struct netxen_minidump_entry_cache
2188					*cacheEntry, u32 *data_buff)
2189{
2190	int loop_cnt, i, k, timeout_flag = 0;
2191	u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;
2192	u32 tag_value, read_cnt;
2193	u8 cntl_value_w, cntl_value_r;
2194	unsigned long timeout, timeout_jiffies;
2195
2196	loop_cnt = cacheEntry->op_count;
2197	read_addr = cacheEntry->read_addr;
2198	cntrl_addr = cacheEntry->control_addr;
2199	cntl_value_w = (u32) cacheEntry->write_value;
2200	tag_reg_addr = cacheEntry->tag_reg_addr;
2201	tag_value = cacheEntry->init_tag_value;
2202	read_cnt = cacheEntry->read_addr_cnt;
2203
2204	for (i = 0; i < loop_cnt; i++) {
2205		NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);
2206		if (cntl_value_w)
2207			NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
2208					(u32)cntl_value_w);
2209		if (cacheEntry->poll_mask) {
2210			timeout = cacheEntry->poll_wait;
2211			NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
2212							&cntl_value_r);
2213			timeout_jiffies = msecs_to_jiffies(timeout) + jiffies;
2214			for (timeout_flag = 0; !timeout_flag &&
2215			((cntl_value_r & cacheEntry->poll_mask) != 0);) {
2216				if (time_after(jiffies, timeout_jiffies))
2217					timeout_flag = 1;
2218				NX_RD_DUMP_REG(cntrl_addr,
2219					adapter->ahw.pci_base0,
2220							&cntl_value_r);
2221			}
2222			if (timeout_flag) {
2223				dev_err(&adapter->pdev->dev,
2224						"Timeout in processing L2 Tag poll.\n");
2225				return -1;
2226			}
2227		}
2228		addr = read_addr;
2229		for (k = 0; k < read_cnt; k++) {
2230			NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0,
2231					&read_value);
2232			*data_buff++ = read_value;
2233			addr += cacheEntry->read_addr_stride;
2234		}
2235		tag_value += cacheEntry->tag_value_stride;
2236	}
2237	return read_cnt * loop_cnt * sizeof(read_value);
2238}
2239
2240
2241/* Handle L1 Cache */
2242static u32 netxen_md_L1Cache(struct netxen_adapter *adapter,
2243				struct netxen_minidump_entry_cache
2244					*cacheEntry, u32 *data_buff)
2245{
2246	int i, k, loop_cnt;
2247	u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr;
2248	u32 tag_value, read_cnt;
2249	u8 cntl_value_w;
2250
2251	loop_cnt = cacheEntry->op_count;
2252	read_addr = cacheEntry->read_addr;
2253	cntrl_addr = cacheEntry->control_addr;
2254	cntl_value_w = (u32) cacheEntry->write_value;
2255	tag_reg_addr = cacheEntry->tag_reg_addr;
2256	tag_value = cacheEntry->init_tag_value;
2257	read_cnt = cacheEntry->read_addr_cnt;
2258
2259	for (i = 0; i < loop_cnt; i++) {
2260		NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value);
2261		NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0,
2262						(u32) cntl_value_w);
2263		addr = read_addr;
2264		for (k = 0; k < read_cnt; k++) {
2265			NX_RD_DUMP_REG(addr,
2266				adapter->ahw.pci_base0,
2267						&read_value);
2268			*data_buff++ = read_value;
2269			addr += cacheEntry->read_addr_stride;
2270		}
2271		tag_value += cacheEntry->tag_value_stride;
2272	}
2273	return read_cnt * loop_cnt * sizeof(read_value);
2274}
2275
2276/* Reading OCM memory */
2277static u32
2278netxen_md_rdocm(struct netxen_adapter *adapter,
2279				struct netxen_minidump_entry_rdocm
2280					*ocmEntry, u32 *data_buff)
2281{
2282	int i, loop_cnt;
2283	u32 value;
2284	void __iomem *addr;
2285	addr = (ocmEntry->read_addr + adapter->ahw.pci_base0);
2286	loop_cnt = ocmEntry->op_count;
2287
2288	for (i = 0; i < loop_cnt; i++) {
2289		value = readl(addr);
2290		*data_buff++ = value;
2291		addr += ocmEntry->read_addr_stride;
2292	}
2293	return i * sizeof(u32);
2294}
2295
2296/* Read MUX data */
2297static u32
2298netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux
2299					*muxEntry, u32 *data_buff)
2300{
2301	int loop_cnt = 0;
2302	u32 read_addr, read_value, select_addr, sel_value;
2303
2304	read_addr = muxEntry->read_addr;
2305	sel_value = muxEntry->select_value;
2306	select_addr = muxEntry->select_addr;
2307
2308	for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
2309		NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value);
2310		NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value);
2311		*data_buff++ = sel_value;
2312		*data_buff++ = read_value;
2313		sel_value += muxEntry->select_value_stride;
2314	}
2315	return loop_cnt * (2 * sizeof(u32));
2316}
2317
2318/* Handling Queue State Reads */
2319static u32
2320netxen_md_rdqueue(struct netxen_adapter *adapter,
2321				struct netxen_minidump_entry_queue
2322					*queueEntry, u32 *data_buff)
2323{
2324	int loop_cnt, k;
2325	u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt;
2326
2327	read_cnt = queueEntry->read_addr_cnt;
2328	read_stride = queueEntry->read_addr_stride;
2329	select_addr = queueEntry->select_addr;
2330
2331	for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
2332				 loop_cnt++) {
2333		NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id);
2334		read_addr = queueEntry->read_addr;
2335		for (k = 0; k < read_cnt; k--) {
2336			NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0,
2337							&read_value);
2338			*data_buff++ = read_value;
2339			read_addr += read_stride;
2340		}
2341		queue_id += queueEntry->queue_id_stride;
2342	}
2343	return loop_cnt * (read_cnt * sizeof(read_value));
2344}
2345
2346
2347/*
2348* We catch an error where driver does not read
2349* as much data as we expect from the entry.
2350*/
2351
2352static int netxen_md_entry_err_chk(struct netxen_adapter *adapter,
2353				struct netxen_minidump_entry *entry, int esize)
2354{
2355	if (esize < 0) {
2356		entry->hdr.driver_flags |= NX_DUMP_SKIP;
2357		return esize;
2358	}
2359	if (esize != entry->hdr.entry_capture_size) {
2360		entry->hdr.entry_capture_size = esize;
2361		entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR;
2362		dev_info(&adapter->pdev->dev,
2363			"Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
2364			entry->hdr.entry_type, entry->hdr.entry_capture_mask,
2365			esize, entry->hdr.entry_capture_size);
2366		dev_info(&adapter->pdev->dev, "Aborting further dump capture\n");
2367	}
2368	return 0;
2369}
2370
2371static int netxen_parse_md_template(struct netxen_adapter *adapter)
2372{
2373	int num_of_entries, buff_level, e_cnt, esize;
2374	int end_cnt = 0, rv = 0, sane_start = 0, sane_end = 0;
2375	char *dbuff;
2376	void *template_buff = adapter->mdump.md_template;
2377	char *dump_buff = adapter->mdump.md_capture_buff;
2378	int capture_mask = adapter->mdump.md_capture_mask;
2379	struct netxen_minidump_template_hdr *template_hdr;
2380	struct netxen_minidump_entry *entry;
2381
2382	if ((capture_mask & 0x3) != 0x3) {
2383		dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed "
2384			"for valid firmware dump\n", capture_mask);
2385		return -EINVAL;
2386	}
2387	template_hdr = (struct netxen_minidump_template_hdr *) template_buff;
2388	num_of_entries = template_hdr->num_of_entries;
2389	entry = (struct netxen_minidump_entry *) ((char *) template_buff +
2390				template_hdr->first_entry_offset);
2391	memcpy(dump_buff, template_buff, adapter->mdump.md_template_size);
2392	dump_buff = dump_buff + adapter->mdump.md_template_size;
2393
2394	if (template_hdr->entry_type == TLHDR)
2395		sane_start = 1;
2396
2397	for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) {
2398		if (!(entry->hdr.entry_capture_mask & capture_mask)) {
2399			entry->hdr.driver_flags |= NX_DUMP_SKIP;
2400			entry = (struct netxen_minidump_entry *)
2401				((char *) entry + entry->hdr.entry_size);
2402			continue;
2403		}
2404		switch (entry->hdr.entry_type) {
2405		case RDNOP:
2406			entry->hdr.driver_flags |= NX_DUMP_SKIP;
2407			break;
2408		case RDEND:
2409			entry->hdr.driver_flags |= NX_DUMP_SKIP;
2410			if (!sane_end)
2411				end_cnt = e_cnt;
2412			sane_end += 1;
2413			break;
2414		case CNTRL:
2415			rv = netxen_md_cntrl(adapter,
2416				template_hdr, (void *)entry);
2417			if (rv)
2418				entry->hdr.driver_flags |= NX_DUMP_SKIP;
2419			break;
2420		case RDCRB:
2421			dbuff = dump_buff + buff_level;
2422			esize = netxen_md_rd_crb(adapter,
2423					(void *) entry, (void *) dbuff);
2424			rv = netxen_md_entry_err_chk
2425				(adapter, entry, esize);
2426			if (rv < 0)
2427				break;
2428			buff_level += esize;
2429			break;
2430		case RDMN:
2431		case RDMEM:
2432			dbuff = dump_buff + buff_level;
2433			esize = netxen_md_rdmem(adapter,
2434				(void *) entry, (void *) dbuff);
2435			rv = netxen_md_entry_err_chk
2436				(adapter, entry, esize);
2437			if (rv < 0)
2438				break;
2439			buff_level += esize;
2440			break;
2441		case BOARD:
2442		case RDROM:
2443			dbuff = dump_buff + buff_level;
2444			esize = netxen_md_rdrom(adapter,
2445				(void *) entry, (void *) dbuff);
2446			rv = netxen_md_entry_err_chk
2447				(adapter, entry, esize);
2448			if (rv < 0)
2449				break;
2450			buff_level += esize;
2451			break;
2452		case L2ITG:
2453		case L2DTG:
2454		case L2DAT:
2455		case L2INS:
2456			dbuff = dump_buff + buff_level;
2457			esize = netxen_md_L2Cache(adapter,
2458				(void *) entry, (void *) dbuff);
2459			rv = netxen_md_entry_err_chk
2460				(adapter, entry, esize);
2461			if (rv < 0)
2462				break;
2463			buff_level += esize;
2464			break;
2465		case L1DAT:
2466		case L1INS:
2467			dbuff = dump_buff + buff_level;
2468			esize = netxen_md_L1Cache(adapter,
2469				(void *) entry, (void *) dbuff);
2470			rv = netxen_md_entry_err_chk
2471				(adapter, entry, esize);
2472			if (rv < 0)
2473				break;
2474			buff_level += esize;
2475			break;
2476		case RDOCM:
2477			dbuff = dump_buff + buff_level;
2478			esize = netxen_md_rdocm(adapter,
2479				(void *) entry, (void *) dbuff);
2480			rv = netxen_md_entry_err_chk
2481				(adapter, entry, esize);
2482			if (rv < 0)
2483				break;
2484			buff_level += esize;
2485			break;
2486		case RDMUX:
2487			dbuff = dump_buff + buff_level;
2488			esize = netxen_md_rdmux(adapter,
2489				(void *) entry, (void *) dbuff);
2490			rv = netxen_md_entry_err_chk
2491				(adapter, entry, esize);
2492			if (rv < 0)
2493				break;
2494			buff_level += esize;
2495			break;
2496		case QUEUE:
2497			dbuff = dump_buff + buff_level;
2498			esize = netxen_md_rdqueue(adapter,
2499				(void *) entry, (void *) dbuff);
2500			rv = netxen_md_entry_err_chk
2501				(adapter, entry, esize);
2502			if (rv  < 0)
2503				break;
2504			buff_level += esize;
2505			break;
2506		default:
2507			entry->hdr.driver_flags |= NX_DUMP_SKIP;
2508			break;
2509		}
2510		/* Next entry in the template */
2511		entry = (struct netxen_minidump_entry *)
2512			((char *) entry + entry->hdr.entry_size);
2513	}
2514	if (!sane_start || sane_end > 1) {
2515		dev_err(&adapter->pdev->dev,
2516				"Firmware minidump template configuration error.\n");
2517	}
2518	return 0;
2519}
2520
2521static int
2522netxen_collect_minidump(struct netxen_adapter *adapter)
2523{
2524	int ret = 0;
2525	struct netxen_minidump_template_hdr *hdr;
2526	struct timespec val;
2527	hdr = (struct netxen_minidump_template_hdr *)
2528				adapter->mdump.md_template;
2529	hdr->driver_capture_mask = adapter->mdump.md_capture_mask;
2530	jiffies_to_timespec(jiffies, &val);
2531	hdr->driver_timestamp = (u32) val.tv_sec;
2532	hdr->driver_info_word2 = adapter->fw_version;
2533	hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION);
2534	ret = netxen_parse_md_template(adapter);
2535	if (ret)
2536		return ret;
2537
2538	return ret;
2539}
2540
2541
2542void
2543netxen_dump_fw(struct netxen_adapter *adapter)
2544{
2545	struct netxen_minidump_template_hdr *hdr;
2546	int i, k, data_size = 0;
2547	u32 capture_mask;
2548	hdr = (struct netxen_minidump_template_hdr *)
2549				adapter->mdump.md_template;
2550	capture_mask = adapter->mdump.md_capture_mask;
2551
2552	for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) {
2553		if (i & capture_mask)
2554			data_size += hdr->capture_size_array[k];
2555	}
2556	if (!data_size) {
2557		dev_err(&adapter->pdev->dev,
2558				"Invalid cap sizes for capture_mask=0x%x\n",
2559			adapter->mdump.md_capture_mask);
2560		return;
2561	}
2562	adapter->mdump.md_capture_size = data_size;
2563	adapter->mdump.md_dump_size = adapter->mdump.md_template_size +
2564					adapter->mdump.md_capture_size;
2565	if (!adapter->mdump.md_capture_buff) {
2566		adapter->mdump.md_capture_buff =
2567				vzalloc(adapter->mdump.md_dump_size);
2568		if (!adapter->mdump.md_capture_buff)
2569			return;
2570
2571		if (netxen_collect_minidump(adapter)) {
2572			adapter->mdump.has_valid_dump = 0;
2573			adapter->mdump.md_dump_size = 0;
2574			vfree(adapter->mdump.md_capture_buff);
2575			adapter->mdump.md_capture_buff = NULL;
2576			dev_err(&adapter->pdev->dev,
2577				"Error in collecting firmware minidump.\n");
2578		} else {
2579			adapter->mdump.md_timestamp = jiffies;
2580			adapter->mdump.has_valid_dump = 1;
2581			adapter->fw_mdump_rdy = 1;
2582			dev_info(&adapter->pdev->dev, "%s Successfully "
2583				"collected fw dump.\n", adapter->netdev->name);
2584		}
2585
2586	} else {
2587		dev_info(&adapter->pdev->dev,
2588					"Cannot overwrite previously collected "
2589							"firmware minidump.\n");
2590		adapter->fw_mdump_rdy = 1;
2591		return;
2592	}
2593}
2594