]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/netxen/netxen_nic_hw.c
NetXen: driver reload fix for newer firmware.
[mirror_ubuntu-artful-kernel.git] / drivers / net / netxen / netxen_nic_hw.c
CommitLineData
3d396eb1
AK
1/*
2 * Copyright (C) 2003 - 2006 NetXen, Inc.
3 * All rights reserved.
80922fbc 4 *
3d396eb1
AK
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
cb8011ad 9 *
3d396eb1
AK
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
cb8011ad 14 *
3d396eb1
AK
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
80922fbc 19 *
3d396eb1
AK
20 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
80922fbc 22 *
3d396eb1
AK
23 * 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)
ed25ffa1 45#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
cb8011ad 46#define NETXEN_MIN_MTU 64
3d396eb1
AK
47#define NETXEN_ETH_FCS_SIZE 4
48#define NETXEN_ENET_HEADER_SIZE 14
cb8011ad 49#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
3d396eb1
AK
50#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
51#define NETXEN_NIU_HDRSIZE (0x1 << 6)
52#define NETXEN_NIU_TLRSIZE (0x1 << 5)
53
cb8011ad
AK
54#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,
3d396eb1
AK
66 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
80922fbc
AK
84 if (adapter->macaddr_set)
85 adapter->macaddr_set(port, addr->sa_data);
3d396eb1
AK
86
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) {
80922fbc
AK
102 if (adapter->set_promisc)
103 adapter->set_promisc(adapter,
104 port->portnum,
105 NETXEN_NIU_PROMISC_MODE);
3d396eb1 106 } else {
80922fbc 107 if (adapter->unset_promisc &&
cb8011ad
AK
108 adapter->ahw.boardcfg.board_type
109 != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ)
80922fbc
AK
110 adapter->unset_promisc(adapter,
111 port->portnum,
112 NETXEN_NIU_NON_PROMISC_MODE);
3d396eb1
AK
113 }
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
80922fbc
AK
163 if (adapter->set_mtu)
164 adapter->set_mtu(port, mtu);
3d396eb1
AK
165 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;
3d396eb1
AK
177 u32 state = 0;
178 void *addr;
179 int loops = 0, err = 0;
180 int ctx, ring;
181 u32 card_cmdring = 0;
3d396eb1
AK
182 struct netxen_recv_context *recv_ctx;
183 struct netxen_rcv_desc_ctx *rcv_desc;
3d396eb1 184
80922fbc 185 DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
cb8011ad 186 PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
80922fbc 187 DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
cb8011ad 188 pci_base_offset(adapter, NETXEN_CRB_CAM));
80922fbc 189 DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
cb8011ad 190 pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
3d396eb1
AK
191
192 /* Window 1 call */
193 card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
194
195 DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
196 card_cmdring);
197
198 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
199 DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
200 loops = 0;
201 state = 0;
202 /* Window 1 call */
203 state = readl(NETXEN_CRB_NORMALIZE(adapter,
204 recv_crb_registers[ctx].
205 crb_rcvpeg_state));
206 while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
207 udelay(100);
208 /* Window 1 call */
209 state = readl(NETXEN_CRB_NORMALIZE(adapter,
210 recv_crb_registers
211 [ctx].
212 crb_rcvpeg_state));
213 loops++;
214 }
215 if (loops >= 20) {
216 printk(KERN_ERR "Rcv Peg initialization not complete:"
217 "%x.\n", state);
218 err = -EIO;
219 return err;
220 }
221 }
222 DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
223
cb8011ad 224 addr = netxen_alloc(adapter->ahw.pdev,
ed25ffa1
AK
225 sizeof(struct netxen_ring_ctx) +
226 sizeof(uint32_t),
227 (dma_addr_t *) & adapter->ctx_desc_phys_addr,
228 &adapter->ctx_desc_pdev);
cb8011ad 229
ed25ffa1
AK
230 printk("ctx_desc_phys_addr: 0x%llx\n",
231 (u64) adapter->ctx_desc_phys_addr);
3d396eb1
AK
232 if (addr == NULL) {
233 DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
ed25ffa1
AK
234 err = -ENOMEM;
235 return err;
cb8011ad 236 }
ed25ffa1
AK
237 memset(addr, 0, sizeof(struct netxen_ring_ctx));
238 adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
239 adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr
240 + sizeof(struct netxen_ring_ctx);
241 adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
242 sizeof(struct netxen_ring_ctx));
243
244 addr = pci_alloc_consistent(adapter->ahw.pdev,
245 sizeof(struct cmd_desc_type0) *
246 adapter->max_tx_desc_count,
247 (dma_addr_t *) & hw->cmd_desc_phys_addr);
248 printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr);
cb8011ad 249
ed25ffa1
AK
250 if (addr == NULL) {
251 DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
252 netxen_free_hw_resources(adapter);
cb8011ad 253 return -ENOMEM;
3d396eb1
AK
254 }
255
ed25ffa1
AK
256 adapter->ctx_desc->cmd_ring_addr_lo =
257 hw->cmd_desc_phys_addr & 0xffffffffUL;
258 adapter->ctx_desc->cmd_ring_addr_hi =
259 ((u64) hw->cmd_desc_phys_addr >> 32);
260 adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count;
3d396eb1
AK
261
262 hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
263
264 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
265 recv_ctx = &adapter->recv_ctx[ctx];
266
267 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
268 rcv_desc = &recv_ctx->rcv_desc[ring];
cb8011ad
AK
269 addr = netxen_alloc(adapter->ahw.pdev,
270 RCV_DESC_RINGSIZE,
271 &rcv_desc->phys_addr,
272 &rcv_desc->phys_pdev);
3d396eb1
AK
273 if (addr == NULL) {
274 DPRINTK(ERR, "bad return from "
275 "pci_alloc_consistent\n");
276 netxen_free_hw_resources(adapter);
277 err = -ENOMEM;
278 return err;
279 }
280 rcv_desc->desc_head = (struct rcv_desc *)addr;
ed25ffa1
AK
281 adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo =
282 rcv_desc->phys_addr & 0xffffffffUL;
283 adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi =
284 ((u64) rcv_desc->phys_addr >> 32);
285 adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
286 rcv_desc->max_rx_desc_count;
3d396eb1
AK
287 }
288
71bd7877
AK
289 addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
290 &recv_ctx->rcv_status_desc_phys_addr,
cb8011ad 291 &recv_ctx->rcv_status_desc_pdev);
3d396eb1
AK
292 if (addr == NULL) {
293 DPRINTK(ERR, "bad return from"
294 " pci_alloc_consistent\n");
295 netxen_free_hw_resources(adapter);
296 err = -ENOMEM;
297 return err;
298 }
299 recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
ed25ffa1
AK
300 adapter->ctx_desc->sts_ring_addr_lo =
301 recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL;
302 adapter->ctx_desc->sts_ring_addr_hi =
303 ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32);
304 adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count;
3d396eb1 305
3d396eb1
AK
306 }
307 /* Window = 1 */
ed25ffa1
AK
308
309 writel(lower32(adapter->ctx_desc_phys_addr),
310 NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO));
311 writel(upper32(adapter->ctx_desc_phys_addr),
312 NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI));
313 writel(NETXEN_CTX_SIGNATURE,
314 NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG));
3d396eb1
AK
315 return err;
316}
317
318void netxen_free_hw_resources(struct netxen_adapter *adapter)
319{
320 struct netxen_recv_context *recv_ctx;
321 struct netxen_rcv_desc_ctx *rcv_desc;
322 int ctx, ring;
323
ed25ffa1
AK
324 if (adapter->ctx_desc != NULL) {
325 pci_free_consistent(adapter->ctx_desc_pdev,
326 sizeof(struct netxen_ring_ctx) +
327 sizeof(uint32_t),
328 adapter->ctx_desc,
329 adapter->ctx_desc_phys_addr);
330 adapter->ctx_desc = NULL;
331 }
332
3d396eb1 333 if (adapter->ahw.cmd_desc_head != NULL) {
cb8011ad 334 pci_free_consistent(adapter->ahw.cmd_desc_pdev,
3d396eb1
AK
335 sizeof(struct cmd_desc_type0) *
336 adapter->max_tx_desc_count,
337 adapter->ahw.cmd_desc_head,
338 adapter->ahw.cmd_desc_phys_addr);
339 adapter->ahw.cmd_desc_head = NULL;
340 }
ed25ffa1
AK
341 /* Special handling: there are 2 ports on this board */
342 if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
343 adapter->ahw.max_ports = 2;
cb8011ad 344 }
3d396eb1
AK
345
346 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
347 recv_ctx = &adapter->recv_ctx[ctx];
348 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
349 rcv_desc = &recv_ctx->rcv_desc[ring];
350
351 if (rcv_desc->desc_head != NULL) {
cb8011ad 352 pci_free_consistent(rcv_desc->phys_pdev,
3d396eb1
AK
353 RCV_DESC_RINGSIZE,
354 rcv_desc->desc_head,
355 rcv_desc->phys_addr);
356 rcv_desc->desc_head = NULL;
357 }
358 }
359
360 if (recv_ctx->rcv_status_desc_head != NULL) {
cb8011ad 361 pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
3d396eb1
AK
362 STATUS_DESC_RINGSIZE,
363 recv_ctx->rcv_status_desc_head,
364 recv_ctx->
365 rcv_status_desc_phys_addr);
366 recv_ctx->rcv_status_desc_head = NULL;
367 }
368 }
369}
370
371void netxen_tso_check(struct netxen_adapter *adapter,
372 struct cmd_desc_type0 *desc, struct sk_buff *skb)
373{
374 if (desc->mss) {
375 desc->total_hdr_length = sizeof(struct ethhdr) +
376 ((skb->nh.iph)->ihl * sizeof(u32)) +
377 ((skb->h.th)->doff * sizeof(u32));
ed25ffa1 378 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
1494a814 379 } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
3d396eb1 380 if (skb->nh.iph->protocol == IPPROTO_TCP) {
ed25ffa1 381 netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
3d396eb1 382 } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
ed25ffa1 383 netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
3d396eb1
AK
384 } else {
385 return;
386 }
387 }
cb8011ad 388 adapter->stats.xmitcsummed++;
ed25ffa1
AK
389 desc->tcp_hdr_offset = skb->h.raw - skb->data;
390 netxen_set_cmd_desc_totallength(desc,
391 cpu_to_le32
392 (netxen_get_cmd_desc_totallength
393 (desc)));
3d396eb1 394 desc->ip_hdr_offset = skb->nh.raw - skb->data;
3d396eb1
AK
395}
396
397int netxen_is_flash_supported(struct netxen_adapter *adapter)
398{
399 const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
400 int addr, val01, val02, i, j;
401
402 /* if the flash size less than 4Mb, make huge war cry and die */
403 for (j = 1; j < 4; j++) {
cb8011ad 404 addr = j * NETXEN_NIC_WINDOW_MARGIN;
3d396eb1
AK
405 for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
406 if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
407 && netxen_rom_fast_read(adapter, (addr + locs[i]),
408 &val02) == 0) {
409 if (val01 == val02)
410 return -1;
411 } else
412 return -1;
413 }
414 }
415
416 return 0;
417}
418
419static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
420 int size, u32 * buf)
421{
422 int i, addr;
423 u32 *ptr32;
424
425 addr = base;
426 ptr32 = buf;
427 for (i = 0; i < size / sizeof(u32); i++) {
428 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
429 return -1;
430 ptr32++;
431 addr += sizeof(u32);
432 }
433 if ((char *)buf + size > (char *)ptr32) {
434 u32 local;
435
436 if (netxen_rom_fast_read(adapter, addr, &local) == -1)
437 return -1;
438 memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
439 }
440
441 return 0;
442}
443
444int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
445{
446 u32 *pmac = (u32 *) & mac[0];
447
448 if (netxen_get_flash_block(adapter,
449 USER_START +
450 offsetof(struct netxen_new_user_info,
451 mac_addr),
452 FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
453 return -1;
454 }
455 if (*mac == ~0ULL) {
456 if (netxen_get_flash_block(adapter,
457 USER_START_OLD +
458 offsetof(struct netxen_user_old_info,
459 mac_addr),
460 FLASH_NUM_PORTS * sizeof(u64),
461 pmac) == -1)
462 return -1;
463 if (*mac == ~0ULL)
464 return -1;
465 }
466 return 0;
467}
468
469/*
470 * Changes the CRB window to the specified window.
471 */
472void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
473{
474 void __iomem *offset;
475 u32 tmp;
476 int count = 0;
477
478 if (adapter->curr_window == wndw)
479 return;
480
481 /*
482 * Move the CRB window.
483 * We need to write to the "direct access" region of PCI
484 * to avoid a race condition where the window register has
485 * not been successfully written across CRB before the target
486 * register address is received by PCI. The direct region bypasses
487 * the CRB bus.
488 */
cb8011ad
AK
489 offset =
490 PCI_OFFSET_SECOND_RANGE(adapter,
491 NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
3d396eb1
AK
492
493 if (wndw & 0x1)
494 wndw = NETXEN_WINDOW_ONE;
495
496 writel(wndw, offset);
497
498 /* MUST make sure window is set before we forge on... */
499 while ((tmp = readl(offset)) != wndw) {
500 printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
501 "registered properly: 0x%08x.\n",
502 netxen_nic_driver_name, __FUNCTION__, tmp);
503 mdelay(1);
504 if (count >= 10)
505 break;
506 count++;
507 }
508
509 adapter->curr_window = wndw;
510}
511
512void netxen_load_firmware(struct netxen_adapter *adapter)
513{
514 int i;
515 long data, size = 0;
516 long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
517 u64 off;
518 void __iomem *addr;
519
520 size = NETXEN_FIRMWARE_LEN;
521 writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
522
523 for (i = 0; i < size; i++) {
524 if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
525 DPRINTK(ERR,
526 "Error in netxen_rom_fast_read(). Will skip"
527 "loading flash image\n");
528 return;
529 }
cb8011ad
AK
530 off = netxen_nic_pci_set_window(adapter, memaddr);
531 addr = pci_base_offset(adapter, off);
3d396eb1
AK
532 writel(data, addr);
533 flashaddr += 4;
534 memaddr += 4;
535 }
536 udelay(100);
537 /* make sure Casper is powered on */
538 writel(0x3fff,
539 NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
540 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
541
542 udelay(100);
543}
544
545int
546netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
547 int len)
548{
549 void __iomem *addr;
550
551 if (ADDR_IN_WINDOW1(off)) {
552 addr = NETXEN_CRB_NORMALIZE(adapter, off);
553 } else { /* Window 0 */
cb8011ad 554 addr = pci_base_offset(adapter, off);
3d396eb1
AK
555 netxen_nic_pci_change_crbwindow(adapter, 0);
556 }
557
558 DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
559 " data %llx len %d\n",
cb8011ad 560 pci_base(adapter, off), off, addr,
3d396eb1 561 *(unsigned long long *)data, len);
cb8011ad
AK
562 if (!addr) {
563 netxen_nic_pci_change_crbwindow(adapter, 1);
564 return 1;
565 }
566
3d396eb1
AK
567 switch (len) {
568 case 1:
569 writeb(*(u8 *) data, addr);
570 break;
571 case 2:
572 writew(*(u16 *) data, addr);
573 break;
574 case 4:
575 writel(*(u32 *) data, addr);
576 break;
577 case 8:
578 writeq(*(u64 *) data, addr);
579 break;
580 default:
581 DPRINTK(INFO,
582 "writing data %lx to offset %llx, num words=%d\n",
583 *(unsigned long *)data, off, (len >> 3));
584
585 netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
586 (len >> 3));
587 break;
588 }
589 if (!ADDR_IN_WINDOW1(off))
590 netxen_nic_pci_change_crbwindow(adapter, 1);
591
592 return 0;
593}
594
595int
596netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
597 int len)
598{
599 void __iomem *addr;
600
601 if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
602 addr = NETXEN_CRB_NORMALIZE(adapter, off);
603 } else { /* Window 0 */
cb8011ad 604 addr = pci_base_offset(adapter, off);
3d396eb1
AK
605 netxen_nic_pci_change_crbwindow(adapter, 0);
606 }
607
608 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
cb8011ad
AK
609 pci_base(adapter, off), off, addr);
610 if (!addr) {
611 netxen_nic_pci_change_crbwindow(adapter, 1);
612 return 1;
613 }
3d396eb1
AK
614 switch (len) {
615 case 1:
616 *(u8 *) data = readb(addr);
617 break;
618 case 2:
619 *(u16 *) data = readw(addr);
620 break;
621 case 4:
622 *(u32 *) data = readl(addr);
623 break;
624 case 8:
625 *(u64 *) data = readq(addr);
626 break;
627 default:
628 netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
629 (len >> 3));
630 break;
631 }
632 DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
633
634 if (!ADDR_IN_WINDOW1(off))
635 netxen_nic_pci_change_crbwindow(adapter, 1);
636
637 return 0;
638}
639
640void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
641{ /* Only for window 1 */
642 void __iomem *addr;
643
644 addr = NETXEN_CRB_NORMALIZE(adapter, off);
645 DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
80922fbc 646 pci_base(adapter, off), off, addr, val);
3d396eb1
AK
647 writel(val, addr);
648
649}
650
651int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
652{ /* Only for window 1 */
653 void __iomem *addr;
654 int val;
655
656 addr = NETXEN_CRB_NORMALIZE(adapter, off);
657 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
80922fbc 658 pci_base(adapter, off), off, addr);
3d396eb1
AK
659 val = readl(addr);
660 writel(val, addr);
661
662 return val;
663}
664
665/* Change the window to 0, write and change back to window 1. */
666void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
667{
668 void __iomem *addr;
669
670 netxen_nic_pci_change_crbwindow(adapter, 0);
71bd7877 671 addr = pci_base_offset(adapter, index);
3d396eb1
AK
672 writel(value, addr);
673 netxen_nic_pci_change_crbwindow(adapter, 1);
674}
675
676/* Change the window to 0, read and change back to window 1. */
677void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
678{
679 void __iomem *addr;
680
71bd7877 681 addr = pci_base_offset(adapter, index);
3d396eb1
AK
682
683 netxen_nic_pci_change_crbwindow(adapter, 0);
684 *value = readl(addr);
685 netxen_nic_pci_change_crbwindow(adapter, 1);
686}
687
688int netxen_pci_set_window_warning_count = 0;
689
690unsigned long
cb8011ad
AK
691netxen_nic_pci_set_window(struct netxen_adapter *adapter,
692 unsigned long long addr)
3d396eb1
AK
693{
694 static int ddr_mn_window = -1;
695 static int qdr_sn_window = -1;
696 int window;
697
698 if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
699 /* DDR network side */
700 addr -= NETXEN_ADDR_DDR_NET;
701 window = (addr >> 25) & 0x3ff;
702 if (ddr_mn_window != window) {
703 ddr_mn_window = window;
cb8011ad
AK
704 writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
705 NETXEN_PCIX_PH_REG
706 (PCIX_MN_WINDOW)));
3d396eb1 707 /* MUST make sure window is set before we forge on... */
cb8011ad
AK
708 readl(PCI_OFFSET_SECOND_RANGE(adapter,
709 NETXEN_PCIX_PH_REG
710 (PCIX_MN_WINDOW)));
3d396eb1 711 }
cb8011ad 712 addr -= (window * NETXEN_WINDOW_ONE);
3d396eb1
AK
713 addr += NETXEN_PCI_DDR_NET;
714 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
715 addr -= NETXEN_ADDR_OCM0;
716 addr += NETXEN_PCI_OCM0;
717 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
718 addr -= NETXEN_ADDR_OCM1;
719 addr += NETXEN_PCI_OCM1;
720 } else
721 if (ADDR_IN_RANGE
722 (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
723 /* QDR network side */
724 addr -= NETXEN_ADDR_QDR_NET;
725 window = (addr >> 22) & 0x3f;
726 if (qdr_sn_window != window) {
727 qdr_sn_window = window;
cb8011ad
AK
728 writel((window << 22),
729 PCI_OFFSET_SECOND_RANGE(adapter,
730 NETXEN_PCIX_PH_REG
731 (PCIX_SN_WINDOW)));
3d396eb1 732 /* MUST make sure window is set before we forge on... */
cb8011ad
AK
733 readl(PCI_OFFSET_SECOND_RANGE(adapter,
734 NETXEN_PCIX_PH_REG
735 (PCIX_SN_WINDOW)));
3d396eb1
AK
736 }
737 addr -= (window * 0x400000);
738 addr += NETXEN_PCI_QDR_NET;
739 } else {
740 /*
741 * peg gdb frequently accesses memory that doesn't exist,
742 * this limits the chit chat so debugging isn't slowed down.
743 */
744 if ((netxen_pci_set_window_warning_count++ < 8)
745 || (netxen_pci_set_window_warning_count % 64 == 0))
746 printk("%s: Warning:netxen_nic_pci_set_window()"
747 " Unknown address range!\n",
748 netxen_nic_driver_name);
749
750 }
751 return addr;
752}
753
754int netxen_nic_get_board_info(struct netxen_adapter *adapter)
755{
756 int rv = 0;
757 int addr = BRDCFG_START;
758 struct netxen_board_info *boardinfo;
759 int index;
760 u32 *ptr32;
761
762 boardinfo = &adapter->ahw.boardcfg;
763 ptr32 = (u32 *) boardinfo;
764
765 for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
766 index++) {
767 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
768 return -EIO;
769 }
770 ptr32++;
771 addr += sizeof(u32);
772 }
773 if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
774 printk("%s: ERROR reading %s board config."
775 " Read %x, expected %x\n", netxen_nic_driver_name,
776 netxen_nic_driver_name,
777 boardinfo->magic, NETXEN_BDINFO_MAGIC);
778 rv = -1;
779 }
780 if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
781 printk("%s: Unknown board config version."
782 " Read %x, expected %x\n", netxen_nic_driver_name,
783 boardinfo->header_version, NETXEN_BDINFO_VERSION);
784 rv = -1;
785 }
786
787 DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
788 switch ((netxen_brdtype_t) boardinfo->board_type) {
789 case NETXEN_BRDTYPE_P2_SB35_4G:
790 adapter->ahw.board_type = NETXEN_NIC_GBE;
791 break;
792 case NETXEN_BRDTYPE_P2_SB31_10G:
793 case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
794 case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
795 case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
796 adapter->ahw.board_type = NETXEN_NIC_XGBE;
797 break;
798 case NETXEN_BRDTYPE_P1_BD:
799 case NETXEN_BRDTYPE_P1_SB:
800 case NETXEN_BRDTYPE_P1_SMAX:
801 case NETXEN_BRDTYPE_P1_SOCK:
802 adapter->ahw.board_type = NETXEN_NIC_GBE;
803 break;
804 default:
805 printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
806 boardinfo->board_type);
807 break;
808 }
809
810 return rv;
811}
812
813/* NIU access sections */
814
815int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu)
816{
817 struct netxen_adapter *adapter = port->adapter;
818 netxen_nic_write_w0(adapter,
819 NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
820 new_mtu);
821 return 0;
822}
823
824int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu)
825{
826 struct netxen_adapter *adapter = port->adapter;
827 new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
828 netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
829 return 0;
830}
831
832void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
833{
834 int portno;
835 for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
836 netxen_niu_gbe_init_port(adapter, portno);
837}
838
839void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
840{
841 int port_nr;
842 struct netxen_port *port;
843
844 for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
845 port = adapter->port[port_nr];
80922fbc
AK
846 if (adapter->stop_port)
847 adapter->stop_port(adapter, port->portnum);
3d396eb1
AK
848 }
849}
850
851void
852netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
853 int data)
854{
855 void __iomem *addr;
856
857 if (ADDR_IN_WINDOW1(off)) {
858 writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
859 } else {
860 netxen_nic_pci_change_crbwindow(adapter, 0);
71bd7877 861 addr = pci_base_offset(adapter, off);
3d396eb1
AK
862 writel(data, addr);
863 netxen_nic_pci_change_crbwindow(adapter, 1);
864 }
865}
866
867void netxen_nic_set_link_parameters(struct netxen_port *port)
868{
869 struct netxen_adapter *adapter = port->adapter;
870 __le32 status;
ed25ffa1 871 __le32 autoneg;
3d396eb1
AK
872 __le32 mode;
873
874 netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
875 if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
80922fbc
AK
876 if (adapter->phy_read
877 && adapter->
3d396eb1
AK
878 phy_read(adapter, port->portnum,
879 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
880 &status) == 0) {
881 if (netxen_get_phy_link(status)) {
882 switch (netxen_get_phy_speed(status)) {
883 case 0:
884 port->link_speed = SPEED_10;
885 break;
886 case 1:
887 port->link_speed = SPEED_100;
888 break;
889 case 2:
890 port->link_speed = SPEED_1000;
891 break;
892 default:
893 port->link_speed = -1;
894 break;
895 }
896 switch (netxen_get_phy_duplex(status)) {
897 case 0:
898 port->link_duplex = DUPLEX_HALF;
899 break;
900 case 1:
901 port->link_duplex = DUPLEX_FULL;
902 break;
903 default:
904 port->link_duplex = -1;
905 break;
906 }
80922fbc
AK
907 if (adapter->phy_read
908 && adapter->
3d396eb1
AK
909 phy_read(adapter, port->portnum,
910 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
ed25ffa1 911 &autoneg) != 0)
3d396eb1
AK
912 port->link_autoneg = autoneg;
913 } else
914 goto link_down;
915 } else {
916 link_down:
917 port->link_speed = -1;
918 port->link_duplex = -1;
919 }
920 }
921}
922
923void netxen_nic_flash_print(struct netxen_adapter *adapter)
924{
925 int valid = 1;
926 u32 fw_major = 0;
927 u32 fw_minor = 0;
928 u32 fw_build = 0;
cb8011ad
AK
929 char brd_name[NETXEN_MAX_SHORT_NAME];
930 struct netxen_new_user_info user_info;
931 int i, addr = USER_START;
932 u32 *ptr32;
3d396eb1
AK
933
934 struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
935 if (board_info->magic != NETXEN_BDINFO_MAGIC) {
936 printk
937 ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
938 board_info->magic, NETXEN_BDINFO_MAGIC);
939 valid = 0;
940 }
941 if (board_info->header_version != NETXEN_BDINFO_VERSION) {
942 printk("NetXen Unknown board config version."
943 " Read %x, expected %x\n",
944 board_info->header_version, NETXEN_BDINFO_VERSION);
945 valid = 0;
946 }
947 if (valid) {
cb8011ad
AK
948 ptr32 = (u32 *) & user_info;
949 for (i = 0;
950 i < sizeof(struct netxen_new_user_info) / sizeof(u32);
951 i++) {
952 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
953 printk("%s: ERROR reading %s board userarea.\n",
954 netxen_nic_driver_name,
955 netxen_nic_driver_name);
956 return;
957 }
958 ptr32++;
959 addr += sizeof(u32);
960 }
961 get_brd_name_by_type(board_info->board_type, brd_name);
962
963 printk("NetXen %s Board S/N %s Chip id 0x%x\n",
964 brd_name, user_info.serial_num, board_info->chip_id);
965
3d396eb1
AK
966 printk("NetXen %s Board #%d, Chip id 0x%x\n",
967 board_info->board_type == 0x0b ? "XGB" : "GBE",
968 board_info->board_num, board_info->chip_id);
969 fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
970 NETXEN_FW_VERSION_MAJOR));
971 fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
972 NETXEN_FW_VERSION_MINOR));
973 fw_build =
974 readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
975
976 printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
977 fw_build);
978 }
979 if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
980 printk(KERN_ERR "The mismatch in driver version and firmware "
981 "version major number\n"
982 "Driver version major number = %d \t"
983 "Firmware version major number = %d \n",
984 _NETXEN_NIC_LINUX_MAJOR, fw_major);
985 adapter->driver_mismatch = 1;
986 }
987 if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
988 printk(KERN_ERR "The mismatch in driver version and firmware "
989 "version minor number\n"
990 "Driver version minor number = %d \t"
991 "Firmware version minor number = %d \n",
992 _NETXEN_NIC_LINUX_MINOR, fw_minor);
993 adapter->driver_mismatch = 1;
994 }
995 if (adapter->driver_mismatch)
996 printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
997 fw_major, fw_minor);
998}
999
1000int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
1001{
1002 int data;
1003 netxen_nic_hw_read_wx(adapter, off, &data, 4);
1004 return data;
1005}
ed25ffa1
AK
1006
1007int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off,
1008 void *data, int len)
1009{
1010 void *addr;
1011 u64 offset = off;
1012 u8 *mem_ptr = NULL;
1013 unsigned long mem_base;
1014 unsigned long mem_page;
1015
1016 if (ADDR_IN_WINDOW1(off)) {
1017 addr = NETXEN_CRB_NORMALIZE(adapter, off);
1018 if (!addr) {
1019 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1020 offset = NETXEN_CRB_NORMAL(off);
1021 mem_page = offset & PAGE_MASK;
1022 if (mem_page != ((offset + len - 1) & PAGE_MASK))
1023 mem_ptr =
1024 ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1025 else
1026 mem_ptr =
1027 ioremap(mem_base + mem_page, PAGE_SIZE);
1028 if (mem_ptr == 0UL) {
1029 return 1;
1030 }
1031 addr = mem_ptr;
1032 addr += offset & (PAGE_SIZE - 1);
1033 }
1034 } else {
1035 addr = pci_base_offset(adapter, off);
1036 if (!addr) {
1037 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1038 mem_page = off & PAGE_MASK;
1039 if (mem_page != ((off + len - 1) & PAGE_MASK))
1040 mem_ptr =
1041 ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1042 else
1043 mem_ptr =
1044 ioremap(mem_base + mem_page, PAGE_SIZE);
1045 if (mem_ptr == 0UL) {
1046 return 1;
1047 }
1048 addr = mem_ptr;
1049 addr += off & (PAGE_SIZE - 1);
1050 }
1051 netxen_nic_pci_change_crbwindow(adapter, 0);
1052 }
1053 switch (len) {
1054 case 1:
1055 writeb(*(u8 *) data, addr);
1056 break;
1057 case 2:
1058 writew(*(u16 *) data, addr);
1059 break;
1060 case 4:
1061 writel(*(u32 *) data, addr);
1062 break;
1063 case 8:
1064 writeq(*(u64 *) data, addr);
1065 break;
1066 default:
1067 DPRINTK(INFO,
1068 "writing data %lx to offset %llx, num words=%d\n",
1069 *(unsigned long *)data, off, (len >> 3));
1070
1071 netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
1072 (len >> 3));
1073 break;
1074 }
1075
1076 if (!ADDR_IN_WINDOW1(off))
1077 netxen_nic_pci_change_crbwindow(adapter, 1);
1078 if (mem_ptr)
1079 iounmap(mem_ptr);
1080 return 0;
1081}
1082
1083int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off,
1084 void *data, int len)
1085{
1086 void *addr;
1087 u64 offset;
1088 u8 *mem_ptr = NULL;
1089 unsigned long mem_base;
1090 unsigned long mem_page;
1091
1092 if (ADDR_IN_WINDOW1(off)) {
1093 addr = NETXEN_CRB_NORMALIZE(adapter, off);
1094 if (!addr) {
1095 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1096 offset = NETXEN_CRB_NORMAL(off);
1097 mem_page = offset & PAGE_MASK;
1098 if (mem_page != ((offset + len - 1) & PAGE_MASK))
1099 mem_ptr =
1100 ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1101 else
1102 mem_ptr =
1103 ioremap(mem_base + mem_page, PAGE_SIZE);
1104 if (mem_ptr == 0UL) {
1105 *(u8 *) data = 0;
1106 return 1;
1107 }
1108 addr = mem_ptr;
1109 addr += offset & (PAGE_SIZE - 1);
1110 }
1111 } else {
1112 addr = pci_base_offset(adapter, off);
1113 if (!addr) {
1114 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1115 mem_page = off & PAGE_MASK;
1116 if (mem_page != ((off + len - 1) & PAGE_MASK))
1117 mem_ptr =
1118 ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1119 else
1120 mem_ptr =
1121 ioremap(mem_base + mem_page, PAGE_SIZE);
1122 if (mem_ptr == 0UL)
1123 return 1;
1124 addr = mem_ptr;
1125 addr += off & (PAGE_SIZE - 1);
1126 }
1127 netxen_nic_pci_change_crbwindow(adapter, 0);
1128 }
1129 switch (len) {
1130 case 1:
1131 *(u8 *) data = readb(addr);
1132 break;
1133 case 2:
1134 *(u16 *) data = readw(addr);
1135 break;
1136 case 4:
1137 *(u32 *) data = readl(addr);
1138 break;
1139 case 8:
1140 *(u64 *) data = readq(addr);
1141 break;
1142 default:
1143 netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
1144 (len >> 3));
1145 break;
1146 }
1147 if (!ADDR_IN_WINDOW1(off))
1148 netxen_nic_pci_change_crbwindow(adapter, 1);
1149 if (mem_ptr)
1150 iounmap(mem_ptr);
1151 return 0;
1152}
1153
1154int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter, u64 off,
1155 void *data, int size)
1156{
1157 void *addr;
1158 int ret = 0;
1159 u8 *mem_ptr = NULL;
1160 unsigned long mem_base;
1161 unsigned long mem_page;
1162
1163 if (data == NULL || off > (128 * 1024 * 1024)) {
1164 printk(KERN_ERR "%s: data: %p off:%llx\n",
1165 netxen_nic_driver_name, data, off);
1166 return 1;
1167 }
1168 off = netxen_nic_pci_set_window(adapter, off);
1169 /* Corner case : Malicious user tried to break the driver by reading
1170 last few bytes in ranges and tries to read further addresses.
1171 */
1172 if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
1173 printk(KERN_ERR "%s: Invalid access to memory address range"
1174 " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
1175 off + size);
1176 return 1;
1177 }
1178 addr = pci_base_offset(adapter, off);
1179 DPRINTK(INFO, "writing data %llx to offset %llx\n",
1180 *(unsigned long long *)data, off);
1181 if (!addr) {
1182 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1183 mem_page = off & PAGE_MASK;
1184 /* Map two pages whenever user tries to access addresses in two
1185 consecutive pages.
1186 */
1187 if (mem_page != ((off + size - 1) & PAGE_MASK))
1188 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1189 else
1190 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
1191 if (mem_ptr == 0UL) {
1192 return 1;
1193 }
1194 addr = mem_ptr;
1195 addr += off & (PAGE_SIZE - 1);
1196 }
1197 switch (size) {
1198 case 1:
1199 writeb(*(u8 *) data, addr);
1200 break;
1201 case 2:
1202 writew(*(u16 *) data, addr);
1203 break;
1204 case 4:
1205 writel(*(u32 *) data, addr);
1206 break;
1207 case 8:
1208 writeq(*(u64 *) data, addr);
1209 break;
1210 default:
1211 DPRINTK(INFO,
1212 "writing data %lx to offset %llx, num words=%d\n",
1213 *(unsigned long *)data, off, (size >> 3));
1214
1215 netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
1216 (size >> 3));
1217 break;
1218 }
1219
1220 if (mem_ptr)
1221 iounmap(mem_ptr);
1222 DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data);
1223
1224 return ret;
1225}
1226
1227int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter,
1228 u64 off, void *data, int size)
1229{
1230 void *addr;
1231 int ret = 0;
1232 u8 *mem_ptr = NULL;
1233 unsigned long mem_base;
1234 unsigned long mem_page;
1235
1236 if (data == NULL || off > (128 * 1024 * 1024)) {
1237 printk(KERN_ERR "%s: data: %p off:%llx\n",
1238 netxen_nic_driver_name, data, off);
1239 return 1;
1240 }
1241 off = netxen_nic_pci_set_window(adapter, off);
1242 /* Corner case : Malicious user tried to break the driver by reading
1243 last few bytes in ranges and tries to read further addresses.
1244 */
1245 if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) {
1246 printk(KERN_ERR "%s: Invalid access to memory address range"
1247 " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off,
1248 off + size);
1249 return 1;
1250 }
1251 addr = pci_base_offset(adapter, off);
1252 if (!addr) {
1253 mem_base = pci_resource_start(adapter->ahw.pdev, 0);
1254 mem_page = off & PAGE_MASK;
1255 /* Map two pages whenever user tries to access addresses in two
1256 consecutive pages.
1257 */
1258 if (mem_page != ((off + size - 1) & PAGE_MASK))
1259 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
1260 else
1261 mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
1262 if (mem_ptr == 0UL) {
1263 *(u8 *) data = 0;
1264 return 1;
1265 }
1266 addr = mem_ptr;
1267 addr += off & (PAGE_SIZE - 1);
1268 }
1269 switch (size) {
1270 case 1:
1271 *(u8 *) data = readb(addr);
1272 break;
1273 case 2:
1274 *(u16 *) data = readw(addr);
1275 break;
1276 case 4:
1277 *(u32 *) data = readl(addr);
1278 break;
1279 case 8:
1280 *(u64 *) data = readq(addr);
1281 break;
1282 default:
1283 netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
1284 (size >> 3));
1285 break;
1286 }
1287
1288 if (mem_ptr)
1289 iounmap(mem_ptr);
1290 DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data);
1291
1292 return ret;
1293}