blob: 7470852ab582e5adf26f37b8c9048d8a10cc4f59 [file] [log] [blame]
Amit S. Kale3d396eb2006-10-21 15:33:03 -04001/*
2 * Copyright (C) 2003 - 2006 NetXen, Inc.
3 * All rights reserved.
Amit S. Kale80922fb2006-12-04 09:18:00 -08004 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -04005 * 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.
Amit S. Kalecb8011a2006-11-29 09:00:10 -08009 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040010 * 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.
Amit S. Kalecb8011a2006-11-29 09:00:10 -080014 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040015 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
Amit S. Kale80922fb2006-12-04 09:18:00 -080019 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040020 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
Amit S. Kale80922fb2006-12-04 09:18:00 -080022 *
Amit S. Kale3d396eb2006-10-21 15:33:03 -040023 * Contact Information:
24 * info@netxen.com
25 * NetXen,
26 * 3965 Freedom Circle, Fourth floor,
27 * Santa Clara, CA 95054
28 *
29 *
30 * Source file for NIC routines to access the Phantom hardware
31 *
32 */
33
34#include "netxen_nic.h"
35#include "netxen_nic_hw.h"
36#include "netxen_nic_phan_reg.h"
37
38/* PCI Windowing for DDR regions. */
39
40#define ADDR_IN_RANGE(addr, low, high) \
41 (((addr) <= (high)) && ((addr) >= (low)))
42
43#define NETXEN_FLASH_BASE (BOOTLD_START)
44#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
45#define NETXEN_MAX_MTU 8000
Amit S. Kalecb8011a2006-11-29 09:00:10 -080046#define NETXEN_MIN_MTU 64
Amit S. Kale3d396eb2006-10-21 15:33:03 -040047#define NETXEN_ETH_FCS_SIZE 4
48#define NETXEN_ENET_HEADER_SIZE 14
Amit S. Kalecb8011a2006-11-29 09:00:10 -080049#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
Amit S. Kale3d396eb2006-10-21 15:33:03 -040050#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
51#define NETXEN_NIU_HDRSIZE (0x1 << 6)
52#define NETXEN_NIU_TLRSIZE (0x1 << 5)
53
Amit S. Kalecb8011a2006-11-29 09:00:10 -080054#define lower32(x) ((u32)((x) & 0xffffffff))
55#define upper32(x) \
56 ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
57
58#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
59#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
60#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
61#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL
62
63#define NETXEN_NIC_WINDOW_MARGIN 0x100000
64
65unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
Amit S. Kale3d396eb2006-10-21 15:33:03 -040066 unsigned long long addr);
67void netxen_free_hw_resources(struct netxen_adapter *adapter);
68
69int netxen_nic_set_mac(struct net_device *netdev, void *p)
70{
71 struct netxen_port *port = netdev_priv(netdev);
72 struct netxen_adapter *adapter = port->adapter;
73 struct sockaddr *addr = p;
74
75 if (netif_running(netdev))
76 return -EBUSY;
77
78 if (!is_valid_ether_addr(addr->sa_data))
79 return -EADDRNOTAVAIL;
80
81 DPRINTK(INFO, "valid ether addr\n");
82 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
83
Amit S. Kale80922fb2006-12-04 09:18:00 -080084 if (adapter->macaddr_set)
85 adapter->macaddr_set(port, addr->sa_data);
Amit S. Kale3d396eb2006-10-21 15:33:03 -040086
87 return 0;
88}
89
90/*
91 * netxen_nic_set_multi - Multicast
92 */
93void netxen_nic_set_multi(struct net_device *netdev)
94{
95 struct netxen_port *port = netdev_priv(netdev);
96 struct netxen_adapter *adapter = port->adapter;
97 struct dev_mc_list *mc_ptr;
98 __le32 netxen_mac_addr_cntl_data = 0;
99
100 mc_ptr = netdev->mc_list;
101 if (netdev->flags & IFF_PROMISC) {
Amit S. Kale80922fb2006-12-04 09:18:00 -0800102 if (adapter->set_promisc)
103 adapter->set_promisc(adapter,
104 port->portnum,
105 NETXEN_NIU_PROMISC_MODE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400106 } else {
Amit S. Kale80922fb2006-12-04 09:18:00 -0800107 if (adapter->unset_promisc &&
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800108 adapter->ahw.boardcfg.board_type
109 != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ)
Amit S. Kale80922fb2006-12-04 09:18:00 -0800110 adapter->unset_promisc(adapter,
111 port->portnum,
112 NETXEN_NIU_NON_PROMISC_MODE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400113 }
114 if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
115 netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03);
116 netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
117 netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x00);
118 netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x00);
119 netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x00);
120 netxen_nic_mcr_set_enable_xtnd0(netxen_mac_addr_cntl_data);
121 netxen_nic_mcr_set_enable_xtnd1(netxen_mac_addr_cntl_data);
122 netxen_nic_mcr_set_enable_xtnd2(netxen_mac_addr_cntl_data);
123 netxen_nic_mcr_set_enable_xtnd3(netxen_mac_addr_cntl_data);
124 } else {
125 netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x00);
126 netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
127 netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x01);
128 netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x02);
129 netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x03);
130 }
131 writel(netxen_mac_addr_cntl_data,
132 NETXEN_CRB_NORMALIZE(adapter, NETXEN_MAC_ADDR_CNTL_REG));
133 if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
134 writel(netxen_mac_addr_cntl_data,
135 NETXEN_CRB_NORMALIZE(adapter,
136 NETXEN_MULTICAST_ADDR_HI_0));
137 } else {
138 writel(netxen_mac_addr_cntl_data,
139 NETXEN_CRB_NORMALIZE(adapter,
140 NETXEN_MULTICAST_ADDR_HI_1));
141 }
142 netxen_mac_addr_cntl_data = 0;
143 writel(netxen_mac_addr_cntl_data,
144 NETXEN_CRB_NORMALIZE(adapter, NETXEN_NIU_GB_DROP_WRONGADDR));
145}
146
147/*
148 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
149 * @returns 0 on success, negative on failure
150 */
151int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
152{
153 struct netxen_port *port = netdev_priv(netdev);
154 struct netxen_adapter *adapter = port->adapter;
155 int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
156
157 if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
158 printk(KERN_ERR "%s: %s %d is not supported.\n",
159 netxen_nic_driver_name, netdev->name, mtu);
160 return -EINVAL;
161 }
162
Amit S. Kale80922fb2006-12-04 09:18:00 -0800163 if (adapter->set_mtu)
164 adapter->set_mtu(port, mtu);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400165 netdev->mtu = mtu;
166
167 return 0;
168}
169
170/*
171 * check if the firmware has been downloaded and ready to run and
172 * setup the address for the descriptors in the adapter
173 */
174int netxen_nic_hw_resources(struct netxen_adapter *adapter)
175{
176 struct netxen_hardware_context *hw = &adapter->ahw;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400177 u32 state = 0;
178 void *addr;
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800179 void *pause_addr;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400180 int loops = 0, err = 0;
181 int ctx, ring;
182 u32 card_cmdring = 0;
183 struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
184 struct netxen_recv_context *recv_ctx;
185 struct netxen_rcv_desc_ctx *rcv_desc;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400186
Amit S. Kale80922fb2006-12-04 09:18:00 -0800187 DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800188 PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
Amit S. Kale80922fb2006-12-04 09:18:00 -0800189 DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800190 pci_base_offset(adapter, NETXEN_CRB_CAM));
Amit S. Kale80922fb2006-12-04 09:18:00 -0800191 DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800192 pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400193
194 /* Window 1 call */
195 card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
196
197 DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
198 card_cmdring);
199
200 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
201 DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
202 loops = 0;
203 state = 0;
204 /* Window 1 call */
205 state = readl(NETXEN_CRB_NORMALIZE(adapter,
206 recv_crb_registers[ctx].
207 crb_rcvpeg_state));
208 while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
209 udelay(100);
210 /* Window 1 call */
211 state = readl(NETXEN_CRB_NORMALIZE(adapter,
212 recv_crb_registers
213 [ctx].
214 crb_rcvpeg_state));
215 loops++;
216 }
217 if (loops >= 20) {
218 printk(KERN_ERR "Rcv Peg initialization not complete:"
219 "%x.\n", state);
220 err = -EIO;
221 return err;
222 }
223 }
224 DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
225
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800226 addr = netxen_alloc(adapter->ahw.pdev,
227 sizeof(struct cmd_desc_type0) *
228 adapter->max_tx_desc_count,
229 &hw->cmd_desc_phys_addr, &hw->cmd_desc_pdev);
230
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400231 if (addr == NULL) {
232 DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800233 return -ENOMEM;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400234 }
235
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800236 pause_addr = netxen_alloc(adapter->ahw.pdev, 512,
237 (dma_addr_t *) & hw->pause_physaddr,
238 &hw->pause_pdev);
239 if (pause_addr == NULL) {
240 DPRINTK(1, ERR, "bad return from pci_alloc_consistent\n");
241 return -ENOMEM;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400242 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800243
244 hw->pauseaddr = (char *)pause_addr;
245 {
246 u64 *ptr = (u64 *) pause_addr;
247 *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
248 *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
249 *ptr++ = NETXEN_NIC_UNIT_PAUSE_ADDR;
250 *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR;
251 *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR1;
252 *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR2;
253 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400254
255 hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
256
257 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
258 recv_ctx = &adapter->recv_ctx[ctx];
259
260 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
261 rcv_desc = &recv_ctx->rcv_desc[ring];
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800262 addr = netxen_alloc(adapter->ahw.pdev,
263 RCV_DESC_RINGSIZE,
264 &rcv_desc->phys_addr,
265 &rcv_desc->phys_pdev);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400266 if (addr == NULL) {
267 DPRINTK(ERR, "bad return from "
268 "pci_alloc_consistent\n");
269 netxen_free_hw_resources(adapter);
270 err = -ENOMEM;
271 return err;
272 }
273 rcv_desc->desc_head = (struct rcv_desc *)addr;
274 }
275
Amit S. Kale71bd7872006-12-01 05:36:22 -0800276 addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
277 &recv_ctx->rcv_status_desc_phys_addr,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800278 &recv_ctx->rcv_status_desc_pdev);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400279 if (addr == NULL) {
280 DPRINTK(ERR, "bad return from"
281 " pci_alloc_consistent\n");
282 netxen_free_hw_resources(adapter);
283 err = -ENOMEM;
284 return err;
285 }
286 recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
287 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
288 rcv_desc = &recv_ctx->rcv_desc[ring];
289 rcv_desc_crb =
290 &recv_crb_registers[ctx].rcv_desc_crb[ring];
291 DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n",
292 ring, rcv_desc_crb->crb_globalrcv_ring);
293 /* Window = 1 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800294 writel(lower32(rcv_desc->phys_addr),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400295 NETXEN_CRB_NORMALIZE(adapter,
296 rcv_desc_crb->
297 crb_globalrcv_ring));
298 DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x"
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800299 " val 0x%llx,"
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400300 " virt %p\n", ctx,
301 rcv_desc_crb->crb_globalrcv_ring,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800302 (unsigned long long)rcv_desc->phys_addr,
303 +rcv_desc->desc_head);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400304 }
305
306 /* Window = 1 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800307 writel(lower32(recv_ctx->rcv_status_desc_phys_addr),
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400308 NETXEN_CRB_NORMALIZE(adapter,
309 recv_crb_registers[ctx].
310 crb_rcvstatus_ring));
311 DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x,"
312 " val 0x%x,virt%p\n",
313 ctx,
314 recv_crb_registers[ctx].crb_rcvstatus_ring,
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800315 (unsigned long long)recv_ctx->rcv_status_desc_phys_addr,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400316 recv_ctx->rcv_status_desc_head);
317 }
318 /* Window = 1 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800319 writel(lower32(hw->pause_physaddr),
320 NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_LO));
321 writel(upper32(hw->pause_physaddr),
322 NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_HI));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400323
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800324 writel(lower32(hw->cmd_desc_phys_addr),
325 NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
326 writel(upper32(hw->cmd_desc_phys_addr),
327 NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_HI));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400328 return err;
329}
330
331void netxen_free_hw_resources(struct netxen_adapter *adapter)
332{
333 struct netxen_recv_context *recv_ctx;
334 struct netxen_rcv_desc_ctx *rcv_desc;
335 int ctx, ring;
336
337 if (adapter->ahw.cmd_desc_head != NULL) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800338 pci_free_consistent(adapter->ahw.cmd_desc_pdev,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400339 sizeof(struct cmd_desc_type0) *
340 adapter->max_tx_desc_count,
341 adapter->ahw.cmd_desc_head,
342 adapter->ahw.cmd_desc_phys_addr);
343 adapter->ahw.cmd_desc_head = NULL;
344 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800345 if (adapter->ahw.pauseaddr != NULL) {
346 pci_free_consistent(adapter->ahw.pause_pdev, 512,
347 adapter->ahw.pauseaddr,
348 adapter->ahw.pause_physaddr);
349 adapter->ahw.pauseaddr = NULL;
350 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400351
352 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
353 recv_ctx = &adapter->recv_ctx[ctx];
354 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
355 rcv_desc = &recv_ctx->rcv_desc[ring];
356
357 if (rcv_desc->desc_head != NULL) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800358 pci_free_consistent(rcv_desc->phys_pdev,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400359 RCV_DESC_RINGSIZE,
360 rcv_desc->desc_head,
361 rcv_desc->phys_addr);
362 rcv_desc->desc_head = NULL;
363 }
364 }
365
366 if (recv_ctx->rcv_status_desc_head != NULL) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800367 pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400368 STATUS_DESC_RINGSIZE,
369 recv_ctx->rcv_status_desc_head,
370 recv_ctx->
371 rcv_status_desc_phys_addr);
372 recv_ctx->rcv_status_desc_head = NULL;
373 }
374 }
375}
376
377void netxen_tso_check(struct netxen_adapter *adapter,
378 struct cmd_desc_type0 *desc, struct sk_buff *skb)
379{
380 if (desc->mss) {
381 desc->total_hdr_length = sizeof(struct ethhdr) +
382 ((skb->nh.iph)->ihl * sizeof(u32)) +
383 ((skb->h.th)->doff * sizeof(u32));
384 desc->opcode = TX_TCP_LSO;
Jeff Garzik1494a812006-11-07 05:12:16 -0500385 } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400386 if (skb->nh.iph->protocol == IPPROTO_TCP) {
387 desc->opcode = TX_TCP_PKT;
388 } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
389 desc->opcode = TX_UDP_PKT;
390 } else {
391 return;
392 }
393 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800394 adapter->stats.xmitcsummed++;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400395 CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data);
396 desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr);
397 desc->ip_hdr_offset = skb->nh.raw - skb->data;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400398}
399
400int netxen_is_flash_supported(struct netxen_adapter *adapter)
401{
402 const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
403 int addr, val01, val02, i, j;
404
405 /* if the flash size less than 4Mb, make huge war cry and die */
406 for (j = 1; j < 4; j++) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800407 addr = j * NETXEN_NIC_WINDOW_MARGIN;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400408 for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
409 if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
410 && netxen_rom_fast_read(adapter, (addr + locs[i]),
411 &val02) == 0) {
412 if (val01 == val02)
413 return -1;
414 } else
415 return -1;
416 }
417 }
418
419 return 0;
420}
421
422static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
423 int size, u32 * buf)
424{
425 int i, addr;
426 u32 *ptr32;
427
428 addr = base;
429 ptr32 = buf;
430 for (i = 0; i < size / sizeof(u32); i++) {
431 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
432 return -1;
433 ptr32++;
434 addr += sizeof(u32);
435 }
436 if ((char *)buf + size > (char *)ptr32) {
437 u32 local;
438
439 if (netxen_rom_fast_read(adapter, addr, &local) == -1)
440 return -1;
441 memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
442 }
443
444 return 0;
445}
446
447int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
448{
449 u32 *pmac = (u32 *) & mac[0];
450
451 if (netxen_get_flash_block(adapter,
452 USER_START +
453 offsetof(struct netxen_new_user_info,
454 mac_addr),
455 FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
456 return -1;
457 }
458 if (*mac == ~0ULL) {
459 if (netxen_get_flash_block(adapter,
460 USER_START_OLD +
461 offsetof(struct netxen_user_old_info,
462 mac_addr),
463 FLASH_NUM_PORTS * sizeof(u64),
464 pmac) == -1)
465 return -1;
466 if (*mac == ~0ULL)
467 return -1;
468 }
469 return 0;
470}
471
472/*
473 * Changes the CRB window to the specified window.
474 */
475void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
476{
477 void __iomem *offset;
478 u32 tmp;
479 int count = 0;
480
481 if (adapter->curr_window == wndw)
482 return;
483
484 /*
485 * Move the CRB window.
486 * We need to write to the "direct access" region of PCI
487 * to avoid a race condition where the window register has
488 * not been successfully written across CRB before the target
489 * register address is received by PCI. The direct region bypasses
490 * the CRB bus.
491 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800492 offset =
493 PCI_OFFSET_SECOND_RANGE(adapter,
494 NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400495
496 if (wndw & 0x1)
497 wndw = NETXEN_WINDOW_ONE;
498
499 writel(wndw, offset);
500
501 /* MUST make sure window is set before we forge on... */
502 while ((tmp = readl(offset)) != wndw) {
503 printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
504 "registered properly: 0x%08x.\n",
505 netxen_nic_driver_name, __FUNCTION__, tmp);
506 mdelay(1);
507 if (count >= 10)
508 break;
509 count++;
510 }
511
512 adapter->curr_window = wndw;
513}
514
515void netxen_load_firmware(struct netxen_adapter *adapter)
516{
517 int i;
518 long data, size = 0;
519 long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
520 u64 off;
521 void __iomem *addr;
522
523 size = NETXEN_FIRMWARE_LEN;
524 writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
525
526 for (i = 0; i < size; i++) {
527 if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
528 DPRINTK(ERR,
529 "Error in netxen_rom_fast_read(). Will skip"
530 "loading flash image\n");
531 return;
532 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800533 off = netxen_nic_pci_set_window(adapter, memaddr);
534 addr = pci_base_offset(adapter, off);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400535 writel(data, addr);
536 flashaddr += 4;
537 memaddr += 4;
538 }
539 udelay(100);
540 /* make sure Casper is powered on */
541 writel(0x3fff,
542 NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
543 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
544
545 udelay(100);
546}
547
548int
549netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
550 int len)
551{
552 void __iomem *addr;
553
554 if (ADDR_IN_WINDOW1(off)) {
555 addr = NETXEN_CRB_NORMALIZE(adapter, off);
556 } else { /* Window 0 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800557 addr = pci_base_offset(adapter, off);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400558 netxen_nic_pci_change_crbwindow(adapter, 0);
559 }
560
561 DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
562 " data %llx len %d\n",
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800563 pci_base(adapter, off), off, addr,
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400564 *(unsigned long long *)data, len);
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800565 if (!addr) {
566 netxen_nic_pci_change_crbwindow(adapter, 1);
567 return 1;
568 }
569
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400570 switch (len) {
571 case 1:
572 writeb(*(u8 *) data, addr);
573 break;
574 case 2:
575 writew(*(u16 *) data, addr);
576 break;
577 case 4:
578 writel(*(u32 *) data, addr);
579 break;
580 case 8:
581 writeq(*(u64 *) data, addr);
582 break;
583 default:
584 DPRINTK(INFO,
585 "writing data %lx to offset %llx, num words=%d\n",
586 *(unsigned long *)data, off, (len >> 3));
587
588 netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
589 (len >> 3));
590 break;
591 }
592 if (!ADDR_IN_WINDOW1(off))
593 netxen_nic_pci_change_crbwindow(adapter, 1);
594
595 return 0;
596}
597
598int
599netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
600 int len)
601{
602 void __iomem *addr;
603
604 if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
605 addr = NETXEN_CRB_NORMALIZE(adapter, off);
606 } else { /* Window 0 */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800607 addr = pci_base_offset(adapter, off);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400608 netxen_nic_pci_change_crbwindow(adapter, 0);
609 }
610
611 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800612 pci_base(adapter, off), off, addr);
613 if (!addr) {
614 netxen_nic_pci_change_crbwindow(adapter, 1);
615 return 1;
616 }
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400617 switch (len) {
618 case 1:
619 *(u8 *) data = readb(addr);
620 break;
621 case 2:
622 *(u16 *) data = readw(addr);
623 break;
624 case 4:
625 *(u32 *) data = readl(addr);
626 break;
627 case 8:
628 *(u64 *) data = readq(addr);
629 break;
630 default:
631 netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
632 (len >> 3));
633 break;
634 }
635 DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
636
637 if (!ADDR_IN_WINDOW1(off))
638 netxen_nic_pci_change_crbwindow(adapter, 1);
639
640 return 0;
641}
642
643void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
644{ /* Only for window 1 */
645 void __iomem *addr;
646
647 addr = NETXEN_CRB_NORMALIZE(adapter, off);
648 DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
Amit S. Kale80922fb2006-12-04 09:18:00 -0800649 pci_base(adapter, off), off, addr, val);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400650 writel(val, addr);
651
652}
653
654int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
655{ /* Only for window 1 */
656 void __iomem *addr;
657 int val;
658
659 addr = NETXEN_CRB_NORMALIZE(adapter, off);
660 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
Amit S. Kale80922fb2006-12-04 09:18:00 -0800661 pci_base(adapter, off), off, addr);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400662 val = readl(addr);
663 writel(val, addr);
664
665 return val;
666}
667
668/* Change the window to 0, write and change back to window 1. */
669void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
670{
671 void __iomem *addr;
672
673 netxen_nic_pci_change_crbwindow(adapter, 0);
Amit S. Kale71bd7872006-12-01 05:36:22 -0800674 addr = pci_base_offset(adapter, index);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400675 writel(value, addr);
676 netxen_nic_pci_change_crbwindow(adapter, 1);
677}
678
679/* Change the window to 0, read and change back to window 1. */
680void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
681{
682 void __iomem *addr;
683
Amit S. Kale71bd7872006-12-01 05:36:22 -0800684 addr = pci_base_offset(adapter, index);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400685
686 netxen_nic_pci_change_crbwindow(adapter, 0);
687 *value = readl(addr);
688 netxen_nic_pci_change_crbwindow(adapter, 1);
689}
690
691int netxen_pci_set_window_warning_count = 0;
692
693unsigned long
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800694netxen_nic_pci_set_window(struct netxen_adapter *adapter,
695 unsigned long long addr)
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400696{
697 static int ddr_mn_window = -1;
698 static int qdr_sn_window = -1;
699 int window;
700
701 if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
702 /* DDR network side */
703 addr -= NETXEN_ADDR_DDR_NET;
704 window = (addr >> 25) & 0x3ff;
705 if (ddr_mn_window != window) {
706 ddr_mn_window = window;
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800707 writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
708 NETXEN_PCIX_PH_REG
709 (PCIX_MN_WINDOW)));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400710 /* MUST make sure window is set before we forge on... */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800711 readl(PCI_OFFSET_SECOND_RANGE(adapter,
712 NETXEN_PCIX_PH_REG
713 (PCIX_MN_WINDOW)));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400714 }
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800715 addr -= (window * NETXEN_WINDOW_ONE);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400716 addr += NETXEN_PCI_DDR_NET;
717 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
718 addr -= NETXEN_ADDR_OCM0;
719 addr += NETXEN_PCI_OCM0;
720 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
721 addr -= NETXEN_ADDR_OCM1;
722 addr += NETXEN_PCI_OCM1;
723 } else
724 if (ADDR_IN_RANGE
725 (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
726 /* QDR network side */
727 addr -= NETXEN_ADDR_QDR_NET;
728 window = (addr >> 22) & 0x3f;
729 if (qdr_sn_window != window) {
730 qdr_sn_window = window;
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800731 writel((window << 22),
732 PCI_OFFSET_SECOND_RANGE(adapter,
733 NETXEN_PCIX_PH_REG
734 (PCIX_SN_WINDOW)));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400735 /* MUST make sure window is set before we forge on... */
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800736 readl(PCI_OFFSET_SECOND_RANGE(adapter,
737 NETXEN_PCIX_PH_REG
738 (PCIX_SN_WINDOW)));
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400739 }
740 addr -= (window * 0x400000);
741 addr += NETXEN_PCI_QDR_NET;
742 } else {
743 /*
744 * peg gdb frequently accesses memory that doesn't exist,
745 * this limits the chit chat so debugging isn't slowed down.
746 */
747 if ((netxen_pci_set_window_warning_count++ < 8)
748 || (netxen_pci_set_window_warning_count % 64 == 0))
749 printk("%s: Warning:netxen_nic_pci_set_window()"
750 " Unknown address range!\n",
751 netxen_nic_driver_name);
752
753 }
754 return addr;
755}
756
757int netxen_nic_get_board_info(struct netxen_adapter *adapter)
758{
759 int rv = 0;
760 int addr = BRDCFG_START;
761 struct netxen_board_info *boardinfo;
762 int index;
763 u32 *ptr32;
764
765 boardinfo = &adapter->ahw.boardcfg;
766 ptr32 = (u32 *) boardinfo;
767
768 for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
769 index++) {
770 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
771 return -EIO;
772 }
773 ptr32++;
774 addr += sizeof(u32);
775 }
776 if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
777 printk("%s: ERROR reading %s board config."
778 " Read %x, expected %x\n", netxen_nic_driver_name,
779 netxen_nic_driver_name,
780 boardinfo->magic, NETXEN_BDINFO_MAGIC);
781 rv = -1;
782 }
783 if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
784 printk("%s: Unknown board config version."
785 " Read %x, expected %x\n", netxen_nic_driver_name,
786 boardinfo->header_version, NETXEN_BDINFO_VERSION);
787 rv = -1;
788 }
789
790 DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
791 switch ((netxen_brdtype_t) boardinfo->board_type) {
792 case NETXEN_BRDTYPE_P2_SB35_4G:
793 adapter->ahw.board_type = NETXEN_NIC_GBE;
794 break;
795 case NETXEN_BRDTYPE_P2_SB31_10G:
796 case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
797 case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
798 case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
799 adapter->ahw.board_type = NETXEN_NIC_XGBE;
800 break;
801 case NETXEN_BRDTYPE_P1_BD:
802 case NETXEN_BRDTYPE_P1_SB:
803 case NETXEN_BRDTYPE_P1_SMAX:
804 case NETXEN_BRDTYPE_P1_SOCK:
805 adapter->ahw.board_type = NETXEN_NIC_GBE;
806 break;
807 default:
808 printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
809 boardinfo->board_type);
810 break;
811 }
812
813 return rv;
814}
815
816/* NIU access sections */
817
818int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu)
819{
820 struct netxen_adapter *adapter = port->adapter;
821 netxen_nic_write_w0(adapter,
822 NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
823 new_mtu);
824 return 0;
825}
826
827int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu)
828{
829 struct netxen_adapter *adapter = port->adapter;
830 new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
831 netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
832 return 0;
833}
834
835void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
836{
837 int portno;
838 for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
839 netxen_niu_gbe_init_port(adapter, portno);
840}
841
842void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
843{
844 int port_nr;
845 struct netxen_port *port;
846
847 for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
848 port = adapter->port[port_nr];
Amit S. Kale80922fb2006-12-04 09:18:00 -0800849 if (adapter->stop_port)
850 adapter->stop_port(adapter, port->portnum);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400851 }
852}
853
854void
855netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
856 int data)
857{
858 void __iomem *addr;
859
860 if (ADDR_IN_WINDOW1(off)) {
861 writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
862 } else {
863 netxen_nic_pci_change_crbwindow(adapter, 0);
Amit S. Kale71bd7872006-12-01 05:36:22 -0800864 addr = pci_base_offset(adapter, off);
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400865 writel(data, addr);
866 netxen_nic_pci_change_crbwindow(adapter, 1);
867 }
868}
869
870void netxen_nic_set_link_parameters(struct netxen_port *port)
871{
872 struct netxen_adapter *adapter = port->adapter;
873 __le32 status;
874 u16 autoneg;
875 __le32 mode;
876
877 netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
878 if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
Amit S. Kale80922fb2006-12-04 09:18:00 -0800879 if (adapter->phy_read
880 && adapter->
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400881 phy_read(adapter, port->portnum,
882 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
883 &status) == 0) {
884 if (netxen_get_phy_link(status)) {
885 switch (netxen_get_phy_speed(status)) {
886 case 0:
887 port->link_speed = SPEED_10;
888 break;
889 case 1:
890 port->link_speed = SPEED_100;
891 break;
892 case 2:
893 port->link_speed = SPEED_1000;
894 break;
895 default:
896 port->link_speed = -1;
897 break;
898 }
899 switch (netxen_get_phy_duplex(status)) {
900 case 0:
901 port->link_duplex = DUPLEX_HALF;
902 break;
903 case 1:
904 port->link_duplex = DUPLEX_FULL;
905 break;
906 default:
907 port->link_duplex = -1;
908 break;
909 }
Amit S. Kale80922fb2006-12-04 09:18:00 -0800910 if (adapter->phy_read
911 && adapter->
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400912 phy_read(adapter, port->portnum,
913 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
914 (__le32 *) & autoneg) != 0)
915 port->link_autoneg = autoneg;
916 } else
917 goto link_down;
918 } else {
919 link_down:
920 port->link_speed = -1;
921 port->link_duplex = -1;
922 }
923 }
924}
925
926void netxen_nic_flash_print(struct netxen_adapter *adapter)
927{
928 int valid = 1;
929 u32 fw_major = 0;
930 u32 fw_minor = 0;
931 u32 fw_build = 0;
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800932 char brd_name[NETXEN_MAX_SHORT_NAME];
933 struct netxen_new_user_info user_info;
934 int i, addr = USER_START;
935 u32 *ptr32;
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400936
937 struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
938 if (board_info->magic != NETXEN_BDINFO_MAGIC) {
939 printk
940 ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
941 board_info->magic, NETXEN_BDINFO_MAGIC);
942 valid = 0;
943 }
944 if (board_info->header_version != NETXEN_BDINFO_VERSION) {
945 printk("NetXen Unknown board config version."
946 " Read %x, expected %x\n",
947 board_info->header_version, NETXEN_BDINFO_VERSION);
948 valid = 0;
949 }
950 if (valid) {
Amit S. Kalecb8011a2006-11-29 09:00:10 -0800951 ptr32 = (u32 *) & user_info;
952 for (i = 0;
953 i < sizeof(struct netxen_new_user_info) / sizeof(u32);
954 i++) {
955 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
956 printk("%s: ERROR reading %s board userarea.\n",
957 netxen_nic_driver_name,
958 netxen_nic_driver_name);
959 return;
960 }
961 ptr32++;
962 addr += sizeof(u32);
963 }
964 get_brd_name_by_type(board_info->board_type, brd_name);
965
966 printk("NetXen %s Board S/N %s Chip id 0x%x\n",
967 brd_name, user_info.serial_num, board_info->chip_id);
968
Amit S. Kale3d396eb2006-10-21 15:33:03 -0400969 printk("NetXen %s Board #%d, Chip id 0x%x\n",
970 board_info->board_type == 0x0b ? "XGB" : "GBE",
971 board_info->board_num, board_info->chip_id);
972 fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
973 NETXEN_FW_VERSION_MAJOR));
974 fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
975 NETXEN_FW_VERSION_MINOR));
976 fw_build =
977 readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
978
979 printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
980 fw_build);
981 }
982 if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
983 printk(KERN_ERR "The mismatch in driver version and firmware "
984 "version major number\n"
985 "Driver version major number = %d \t"
986 "Firmware version major number = %d \n",
987 _NETXEN_NIC_LINUX_MAJOR, fw_major);
988 adapter->driver_mismatch = 1;
989 }
990 if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
991 printk(KERN_ERR "The mismatch in driver version and firmware "
992 "version minor number\n"
993 "Driver version minor number = %d \t"
994 "Firmware version minor number = %d \n",
995 _NETXEN_NIC_LINUX_MINOR, fw_minor);
996 adapter->driver_mismatch = 1;
997 }
998 if (adapter->driver_mismatch)
999 printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
1000 fw_major, fw_minor);
1001}
1002
1003int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
1004{
1005 int data;
1006 netxen_nic_hw_read_wx(adapter, off, &data, 4);
1007 return data;
1008}