aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_hw.c
diff options
context:
space:
mode:
authorAmit S. Kale <amitkale@netxen.com>2006-10-21 15:33:03 -0400
committerJeff Garzik <jeff@garzik.org>2006-12-02 00:11:58 -0500
commit3d396eb17e9f8c5f59314078b45b88647591378d (patch)
treed0c54e4555c1bee13d403f6dad36b40ae26d74a2 /drivers/net/netxen/netxen_nic_hw.c
parentf3d1fca3eb05cf6ff3879a385a15d24fbf556c57 (diff)
Add NetXen 1G/10G ethernet driver.
Signed-off-by: Amit S. Kale <amitkale@netxen.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c936
1 files changed, 936 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
new file mode 100644
index 000000000000..c7d97054d05c
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -0,0 +1,936 @@
1/*
2 * Copyright (C) 2003 - 2006 NetXen, Inc.
3 * All rights reserved.
4 *
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.
9 *
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.
14 *
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.
19 *
20 * The full GNU General Public License is included in this distribution
21 * in the file called LICENSE.
22 *
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)
45#define NETXEN_MAX_MTU 8000
46#define NETXEN_MIN_MTU 64
47#define NETXEN_ETH_FCS_SIZE 4
48#define NETXEN_ENET_HEADER_SIZE 14
49#define NETXEN_WINDOW_ONE 0x2000000 /* CRB Window: bit 25 of CRB address */
50#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
51#define NETXEN_NIU_HDRSIZE (0x1 << 6)
52#define NETXEN_NIU_TLRSIZE (0x1 << 5)
53
54unsigned long netxen_nic_pci_set_window(void __iomem * pci_base,
55 unsigned long long addr);
56void netxen_free_hw_resources(struct netxen_adapter *adapter);
57
58int netxen_nic_set_mac(struct net_device *netdev, void *p)
59{
60 struct netxen_port *port = netdev_priv(netdev);
61 struct netxen_adapter *adapter = port->adapter;
62 struct sockaddr *addr = p;
63
64 if (netif_running(netdev))
65 return -EBUSY;
66
67 if (!is_valid_ether_addr(addr->sa_data))
68 return -EADDRNOTAVAIL;
69
70 DPRINTK(INFO, "valid ether addr\n");
71 memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
72
73 if (adapter->ops->macaddr_set)
74 adapter->ops->macaddr_set(port, addr->sa_data);
75
76 return 0;
77}
78
79/*
80 * netxen_nic_set_multi - Multicast
81 */
82void netxen_nic_set_multi(struct net_device *netdev)
83{
84 struct netxen_port *port = netdev_priv(netdev);
85 struct netxen_adapter *adapter = port->adapter;
86 struct dev_mc_list *mc_ptr;
87 __le32 netxen_mac_addr_cntl_data = 0;
88
89 mc_ptr = netdev->mc_list;
90 if (netdev->flags & IFF_PROMISC) {
91 if (adapter->ops->set_promisc)
92 adapter->ops->set_promisc(adapter,
93 port->portnum,
94 NETXEN_NIU_PROMISC_MODE);
95 } else {
96 if (adapter->ops->unset_promisc)
97 adapter->ops->unset_promisc(adapter,
98 port->portnum,
99 NETXEN_NIU_NON_PROMISC_MODE);
100 }
101 if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
102 netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03);
103 netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
104 netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x00);
105 netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x00);
106 netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x00);
107 netxen_nic_mcr_set_enable_xtnd0(netxen_mac_addr_cntl_data);
108 netxen_nic_mcr_set_enable_xtnd1(netxen_mac_addr_cntl_data);
109 netxen_nic_mcr_set_enable_xtnd2(netxen_mac_addr_cntl_data);
110 netxen_nic_mcr_set_enable_xtnd3(netxen_mac_addr_cntl_data);
111 } else {
112 netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x00);
113 netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
114 netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x01);
115 netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x02);
116 netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x03);
117 }
118 writel(netxen_mac_addr_cntl_data,
119 NETXEN_CRB_NORMALIZE(adapter, NETXEN_MAC_ADDR_CNTL_REG));
120 if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
121 writel(netxen_mac_addr_cntl_data,
122 NETXEN_CRB_NORMALIZE(adapter,
123 NETXEN_MULTICAST_ADDR_HI_0));
124 } else {
125 writel(netxen_mac_addr_cntl_data,
126 NETXEN_CRB_NORMALIZE(adapter,
127 NETXEN_MULTICAST_ADDR_HI_1));
128 }
129 netxen_mac_addr_cntl_data = 0;
130 writel(netxen_mac_addr_cntl_data,
131 NETXEN_CRB_NORMALIZE(adapter, NETXEN_NIU_GB_DROP_WRONGADDR));
132}
133
134/*
135 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
136 * @returns 0 on success, negative on failure
137 */
138int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
139{
140 struct netxen_port *port = netdev_priv(netdev);
141 struct netxen_adapter *adapter = port->adapter;
142 int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
143
144 if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
145 printk(KERN_ERR "%s: %s %d is not supported.\n",
146 netxen_nic_driver_name, netdev->name, mtu);
147 return -EINVAL;
148 }
149
150 if (adapter->ops->set_mtu)
151 adapter->ops->set_mtu(port, mtu);
152 netdev->mtu = mtu;
153
154 return 0;
155}
156
157/*
158 * check if the firmware has been downloaded and ready to run and
159 * setup the address for the descriptors in the adapter
160 */
161int netxen_nic_hw_resources(struct netxen_adapter *adapter)
162{
163 struct netxen_hardware_context *hw = &adapter->ahw;
164 int i;
165 u32 state = 0;
166 void *addr;
167 int loops = 0, err = 0;
168 int ctx, ring;
169 u32 card_cmdring = 0;
170 struct netxen_rcv_desc_crb *rcv_desc_crb = NULL;
171 struct netxen_recv_context *recv_ctx;
172 struct netxen_rcv_desc_ctx *rcv_desc;
173 struct cmd_desc_type0 *pcmd;
174
175 DPRINTK(INFO, "pci_base: %lx\n", adapter->ahw.pci_base);
176 DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE,
177 adapter->ahw.pci_base + NETXEN_PCI_CRBSPACE);
178 DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM,
179 adapter->ahw.pci_base + NETXEN_CRB_CAM);
180 DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE,
181 adapter->ahw.pci_base + NETXEN_CAM_RAM_BASE);
182 DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1,
183 adapter->ahw.pci_base + NIC_CRB_BASE_PORT1);
184
185 /* Window 1 call */
186 card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));
187
188 DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
189 card_cmdring);
190
191 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
192 DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
193 loops = 0;
194 state = 0;
195 /* Window 1 call */
196 state = readl(NETXEN_CRB_NORMALIZE(adapter,
197 recv_crb_registers[ctx].
198 crb_rcvpeg_state));
199 while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
200 udelay(100);
201 /* Window 1 call */
202 state = readl(NETXEN_CRB_NORMALIZE(adapter,
203 recv_crb_registers
204 [ctx].
205 crb_rcvpeg_state));
206 loops++;
207 }
208 if (loops >= 20) {
209 printk(KERN_ERR "Rcv Peg initialization not complete:"
210 "%x.\n", state);
211 err = -EIO;
212 return err;
213 }
214 }
215 DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
216
217 addr = pci_alloc_consistent(adapter->ahw.pdev,
218 sizeof(struct cmd_desc_type0) *
219 adapter->max_tx_desc_count,
220 &hw->cmd_desc_phys_addr);
221 if (addr == NULL) {
222 DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
223 err = -ENOMEM;
224 return err;
225 }
226
227 /* we need to prelink all of the cmd descriptors */
228 pcmd = (struct cmd_desc_type0 *)addr;
229 for (i = 1; i < adapter->max_tx_desc_count; i++) {
230 pcmd->netxen_next =
231 (card_cmdring + i * sizeof(struct cmd_desc_type0));
232 pcmd++;
233 }
234 /* fill in last link (point to first) */
235 pcmd->netxen_next = card_cmdring;
236
237 hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
238
239 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
240 recv_ctx = &adapter->recv_ctx[ctx];
241
242 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
243 rcv_desc = &recv_ctx->rcv_desc[ring];
244 addr = pci_alloc_consistent(adapter->ahw.pdev,
245 RCV_DESC_RINGSIZE,
246 &rcv_desc->phys_addr);
247 if (addr == NULL) {
248 DPRINTK(ERR, "bad return from "
249 "pci_alloc_consistent\n");
250 netxen_free_hw_resources(adapter);
251 err = -ENOMEM;
252 return err;
253 }
254 rcv_desc->desc_head = (struct rcv_desc *)addr;
255 }
256
257 addr = pci_alloc_consistent(adapter->ahw.pdev,
258 STATUS_DESC_RINGSIZE,
259 &recv_ctx->
260 rcv_status_desc_phys_addr);
261 if (addr == NULL) {
262 DPRINTK(ERR, "bad return from"
263 " pci_alloc_consistent\n");
264 netxen_free_hw_resources(adapter);
265 err = -ENOMEM;
266 return err;
267 }
268 recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
269 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
270 rcv_desc = &recv_ctx->rcv_desc[ring];
271 rcv_desc_crb =
272 &recv_crb_registers[ctx].rcv_desc_crb[ring];
273 DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n",
274 ring, rcv_desc_crb->crb_globalrcv_ring);
275 /* Window = 1 */
276 writel(rcv_desc->phys_addr,
277 NETXEN_CRB_NORMALIZE(adapter,
278 rcv_desc_crb->
279 crb_globalrcv_ring));
280 DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x"
281 " val 0x%x,"
282 " virt %p\n", ctx,
283 rcv_desc_crb->crb_globalrcv_ring,
284 rcv_desc->phys_addr, rcv_desc->desc_head);
285 }
286
287 /* Window = 1 */
288 writel(recv_ctx->rcv_status_desc_phys_addr,
289 NETXEN_CRB_NORMALIZE(adapter,
290 recv_crb_registers[ctx].
291 crb_rcvstatus_ring));
292 DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x,"
293 " val 0x%x,virt%p\n",
294 ctx,
295 recv_crb_registers[ctx].crb_rcvstatus_ring,
296 recv_ctx->rcv_status_desc_phys_addr,
297 recv_ctx->rcv_status_desc_head);
298 }
299 /* Window = 1 */
300 writel(hw->cmd_desc_phys_addr,
301 NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
302
303 return err;
304}
305
306void netxen_free_hw_resources(struct netxen_adapter *adapter)
307{
308 struct netxen_recv_context *recv_ctx;
309 struct netxen_rcv_desc_ctx *rcv_desc;
310 int ctx, ring;
311
312 if (adapter->ahw.cmd_desc_head != NULL) {
313 pci_free_consistent(adapter->ahw.pdev,
314 sizeof(struct cmd_desc_type0) *
315 adapter->max_tx_desc_count,
316 adapter->ahw.cmd_desc_head,
317 adapter->ahw.cmd_desc_phys_addr);
318 adapter->ahw.cmd_desc_head = NULL;
319 }
320
321 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
322 recv_ctx = &adapter->recv_ctx[ctx];
323 for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
324 rcv_desc = &recv_ctx->rcv_desc[ring];
325
326 if (rcv_desc->desc_head != NULL) {
327 pci_free_consistent(adapter->ahw.pdev,
328 RCV_DESC_RINGSIZE,
329 rcv_desc->desc_head,
330 rcv_desc->phys_addr);
331 rcv_desc->desc_head = NULL;
332 }
333 }
334
335 if (recv_ctx->rcv_status_desc_head != NULL) {
336 pci_free_consistent(adapter->ahw.pdev,
337 STATUS_DESC_RINGSIZE,
338 recv_ctx->rcv_status_desc_head,
339 recv_ctx->
340 rcv_status_desc_phys_addr);
341 recv_ctx->rcv_status_desc_head = NULL;
342 }
343 }
344}
345
346void netxen_tso_check(struct netxen_adapter *adapter,
347 struct cmd_desc_type0 *desc, struct sk_buff *skb)
348{
349 if (desc->mss) {
350 desc->total_hdr_length = sizeof(struct ethhdr) +
351 ((skb->nh.iph)->ihl * sizeof(u32)) +
352 ((skb->h.th)->doff * sizeof(u32));
353 desc->opcode = TX_TCP_LSO;
354 } else if (skb->ip_summed == CHECKSUM_HW) {
355 if (skb->nh.iph->protocol == IPPROTO_TCP) {
356 desc->opcode = TX_TCP_PKT;
357 } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
358 desc->opcode = TX_UDP_PKT;
359 } else {
360 return;
361 }
362 }
363 CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data);
364 desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr);
365 desc->ip_hdr_offset = skb->nh.raw - skb->data;
366 adapter->stats.xmitcsummed++;
367}
368
369int netxen_is_flash_supported(struct netxen_adapter *adapter)
370{
371 const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
372 int addr, val01, val02, i, j;
373
374 /* if the flash size less than 4Mb, make huge war cry and die */
375 for (j = 1; j < 4; j++) {
376 addr = j * 0x100000;
377 for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
378 if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
379 && netxen_rom_fast_read(adapter, (addr + locs[i]),
380 &val02) == 0) {
381 if (val01 == val02)
382 return -1;
383 } else
384 return -1;
385 }
386 }
387
388 return 0;
389}
390
391static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
392 int size, u32 * buf)
393{
394 int i, addr;
395 u32 *ptr32;
396
397 addr = base;
398 ptr32 = buf;
399 for (i = 0; i < size / sizeof(u32); i++) {
400 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
401 return -1;
402 ptr32++;
403 addr += sizeof(u32);
404 }
405 if ((char *)buf + size > (char *)ptr32) {
406 u32 local;
407
408 if (netxen_rom_fast_read(adapter, addr, &local) == -1)
409 return -1;
410 memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
411 }
412
413 return 0;
414}
415
416int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
417{
418 u32 *pmac = (u32 *) & mac[0];
419
420 if (netxen_get_flash_block(adapter,
421 USER_START +
422 offsetof(struct netxen_new_user_info,
423 mac_addr),
424 FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
425 return -1;
426 }
427 if (*mac == ~0ULL) {
428 if (netxen_get_flash_block(adapter,
429 USER_START_OLD +
430 offsetof(struct netxen_user_old_info,
431 mac_addr),
432 FLASH_NUM_PORTS * sizeof(u64),
433 pmac) == -1)
434 return -1;
435 if (*mac == ~0ULL)
436 return -1;
437 }
438 return 0;
439}
440
441/*
442 * Changes the CRB window to the specified window.
443 */
444void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
445{
446 void __iomem *offset;
447 u32 tmp;
448 int count = 0;
449
450 if (adapter->curr_window == wndw)
451 return;
452
453 /*
454 * Move the CRB window.
455 * We need to write to the "direct access" region of PCI
456 * to avoid a race condition where the window register has
457 * not been successfully written across CRB before the target
458 * register address is received by PCI. The direct region bypasses
459 * the CRB bus.
460 */
461 offset = adapter->ahw.pci_base + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW);
462
463 if (wndw & 0x1)
464 wndw = NETXEN_WINDOW_ONE;
465
466 writel(wndw, offset);
467
468 /* MUST make sure window is set before we forge on... */
469 while ((tmp = readl(offset)) != wndw) {
470 printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
471 "registered properly: 0x%08x.\n",
472 netxen_nic_driver_name, __FUNCTION__, tmp);
473 mdelay(1);
474 if (count >= 10)
475 break;
476 count++;
477 }
478
479 adapter->curr_window = wndw;
480}
481
482void netxen_load_firmware(struct netxen_adapter *adapter)
483{
484 int i;
485 long data, size = 0;
486 long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
487 u64 off;
488 void __iomem *addr;
489
490 size = NETXEN_FIRMWARE_LEN;
491 writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
492
493 for (i = 0; i < size; i++) {
494 if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
495 DPRINTK(ERR,
496 "Error in netxen_rom_fast_read(). Will skip"
497 "loading flash image\n");
498 return;
499 }
500 off = netxen_nic_pci_set_window(adapter->ahw.pci_base, memaddr);
501 addr = (adapter->ahw.pci_base + off);
502 writel(data, addr);
503 flashaddr += 4;
504 memaddr += 4;
505 }
506 udelay(100);
507 /* make sure Casper is powered on */
508 writel(0x3fff,
509 NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
510 writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
511
512 udelay(100);
513}
514
515int
516netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
517 int len)
518{
519 void __iomem *addr;
520
521 if (ADDR_IN_WINDOW1(off)) {
522 addr = NETXEN_CRB_NORMALIZE(adapter, off);
523 } else { /* Window 0 */
524 addr = adapter->ahw.pci_base + off;
525 netxen_nic_pci_change_crbwindow(adapter, 0);
526 }
527
528 DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
529 " data %llx len %d\n",
530 adapter->ahw.pci_base, off, addr,
531 *(unsigned long long *)data, len);
532 switch (len) {
533 case 1:
534 writeb(*(u8 *) data, addr);
535 break;
536 case 2:
537 writew(*(u16 *) data, addr);
538 break;
539 case 4:
540 writel(*(u32 *) data, addr);
541 break;
542 case 8:
543 writeq(*(u64 *) data, addr);
544 break;
545 default:
546 DPRINTK(INFO,
547 "writing data %lx to offset %llx, num words=%d\n",
548 *(unsigned long *)data, off, (len >> 3));
549
550 netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
551 (len >> 3));
552 break;
553 }
554 if (!ADDR_IN_WINDOW1(off))
555 netxen_nic_pci_change_crbwindow(adapter, 1);
556
557 return 0;
558}
559
560int
561netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
562 int len)
563{
564 void __iomem *addr;
565
566 if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
567 addr = NETXEN_CRB_NORMALIZE(adapter, off);
568 } else { /* Window 0 */
569 addr = adapter->ahw.pci_base + off;
570 netxen_nic_pci_change_crbwindow(adapter, 0);
571 }
572
573 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
574 adapter->ahw.pci_base, off, addr);
575 switch (len) {
576 case 1:
577 *(u8 *) data = readb(addr);
578 break;
579 case 2:
580 *(u16 *) data = readw(addr);
581 break;
582 case 4:
583 *(u32 *) data = readl(addr);
584 break;
585 case 8:
586 *(u64 *) data = readq(addr);
587 break;
588 default:
589 netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
590 (len >> 3));
591 break;
592 }
593 DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
594
595 if (!ADDR_IN_WINDOW1(off))
596 netxen_nic_pci_change_crbwindow(adapter, 1);
597
598 return 0;
599}
600
601void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
602{ /* Only for window 1 */
603 void __iomem *addr;
604
605 addr = NETXEN_CRB_NORMALIZE(adapter, off);
606 DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
607 adapter->ahw.pci_base, off, addr, val);
608 writel(val, addr);
609
610}
611
612int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
613{ /* Only for window 1 */
614 void __iomem *addr;
615 int val;
616
617 addr = NETXEN_CRB_NORMALIZE(adapter, off);
618 DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
619 adapter->ahw.pci_base, off, addr);
620 val = readl(addr);
621 writel(val, addr);
622
623 return val;
624}
625
626/* Change the window to 0, write and change back to window 1. */
627void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
628{
629 void __iomem *addr;
630
631 netxen_nic_pci_change_crbwindow(adapter, 0);
632 addr = (void __iomem *)(adapter->ahw.pci_base + index);
633 writel(value, addr);
634 netxen_nic_pci_change_crbwindow(adapter, 1);
635}
636
637/* Change the window to 0, read and change back to window 1. */
638void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
639{
640 void __iomem *addr;
641
642 addr = (void __iomem *)(adapter->ahw.pci_base + index);
643
644 netxen_nic_pci_change_crbwindow(adapter, 0);
645 *value = readl(addr);
646 netxen_nic_pci_change_crbwindow(adapter, 1);
647}
648
649int netxen_pci_set_window_warning_count = 0;
650
651unsigned long
652netxen_nic_pci_set_window(void __iomem * pci_base, unsigned long long addr)
653{
654 static int ddr_mn_window = -1;
655 static int qdr_sn_window = -1;
656 int window;
657
658 if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
659 /* DDR network side */
660 addr -= NETXEN_ADDR_DDR_NET;
661 window = (addr >> 25) & 0x3ff;
662 if (ddr_mn_window != window) {
663 ddr_mn_window = window;
664 writel(window, pci_base +
665 NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW));
666 /* MUST make sure window is set before we forge on... */
667 readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW));
668 }
669 addr -= (window * 0x2000000);
670 addr += NETXEN_PCI_DDR_NET;
671 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
672 addr -= NETXEN_ADDR_OCM0;
673 addr += NETXEN_PCI_OCM0;
674 } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
675 addr -= NETXEN_ADDR_OCM1;
676 addr += NETXEN_PCI_OCM1;
677 } else
678 if (ADDR_IN_RANGE
679 (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
680 /* QDR network side */
681 addr -= NETXEN_ADDR_QDR_NET;
682 window = (addr >> 22) & 0x3f;
683 if (qdr_sn_window != window) {
684 qdr_sn_window = window;
685 writel((window << 22), pci_base +
686 NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW));
687 /* MUST make sure window is set before we forge on... */
688 readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW));
689 }
690 addr -= (window * 0x400000);
691 addr += NETXEN_PCI_QDR_NET;
692 } else {
693 /*
694 * peg gdb frequently accesses memory that doesn't exist,
695 * this limits the chit chat so debugging isn't slowed down.
696 */
697 if ((netxen_pci_set_window_warning_count++ < 8)
698 || (netxen_pci_set_window_warning_count % 64 == 0))
699 printk("%s: Warning:netxen_nic_pci_set_window()"
700 " Unknown address range!\n",
701 netxen_nic_driver_name);
702
703 }
704 return addr;
705}
706
707int netxen_nic_get_board_info(struct netxen_adapter *adapter)
708{
709 int rv = 0;
710 int addr = BRDCFG_START;
711 struct netxen_board_info *boardinfo;
712 int index;
713 u32 *ptr32;
714
715 boardinfo = &adapter->ahw.boardcfg;
716 ptr32 = (u32 *) boardinfo;
717
718 for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
719 index++) {
720 if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
721 return -EIO;
722 }
723 ptr32++;
724 addr += sizeof(u32);
725 }
726 if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
727 printk("%s: ERROR reading %s board config."
728 " Read %x, expected %x\n", netxen_nic_driver_name,
729 netxen_nic_driver_name,
730 boardinfo->magic, NETXEN_BDINFO_MAGIC);
731 rv = -1;
732 }
733 if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
734 printk("%s: Unknown board config version."
735 " Read %x, expected %x\n", netxen_nic_driver_name,
736 boardinfo->header_version, NETXEN_BDINFO_VERSION);
737 rv = -1;
738 }
739
740 DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
741 switch ((netxen_brdtype_t) boardinfo->board_type) {
742 case NETXEN_BRDTYPE_P2_SB35_4G:
743 adapter->ahw.board_type = NETXEN_NIC_GBE;
744 break;
745 case NETXEN_BRDTYPE_P2_SB31_10G:
746 case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
747 case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
748 case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
749 adapter->ahw.board_type = NETXEN_NIC_XGBE;
750 break;
751 case NETXEN_BRDTYPE_P1_BD:
752 case NETXEN_BRDTYPE_P1_SB:
753 case NETXEN_BRDTYPE_P1_SMAX:
754 case NETXEN_BRDTYPE_P1_SOCK:
755 adapter->ahw.board_type = NETXEN_NIC_GBE;
756 break;
757 default:
758 printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
759 boardinfo->board_type);
760 break;
761 }
762
763 return rv;
764}
765
766/* NIU access sections */
767
768int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu)
769{
770 struct netxen_adapter *adapter = port->adapter;
771 netxen_nic_write_w0(adapter,
772 NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum),
773 new_mtu);
774 return 0;
775}
776
777int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu)
778{
779 struct netxen_adapter *adapter = port->adapter;
780 new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
781 netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
782 return 0;
783}
784
785void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
786{
787 int portno;
788 for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++)
789 netxen_niu_gbe_init_port(adapter, portno);
790}
791
792void netxen_nic_stop_all_ports(struct netxen_adapter *adapter)
793{
794 int port_nr;
795 struct netxen_port *port;
796
797 for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) {
798 port = adapter->port[port_nr];
799 if (adapter->ops->stop_port)
800 adapter->ops->stop_port(adapter, port->portnum);
801 }
802}
803
804void
805netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
806 int data)
807{
808 void __iomem *addr;
809
810 if (ADDR_IN_WINDOW1(off)) {
811 writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
812 } else {
813 netxen_nic_pci_change_crbwindow(adapter, 0);
814 addr = (void __iomem *)(adapter->ahw.pci_base + off);
815 writel(data, addr);
816 netxen_nic_pci_change_crbwindow(adapter, 1);
817 }
818}
819
820void netxen_nic_set_link_parameters(struct netxen_port *port)
821{
822 struct netxen_adapter *adapter = port->adapter;
823 __le32 status;
824 u16 autoneg;
825 __le32 mode;
826
827 netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
828 if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
829 if (adapter->ops->phy_read
830 && adapter->ops->
831 phy_read(adapter, port->portnum,
832 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
833 &status) == 0) {
834 if (netxen_get_phy_link(status)) {
835 switch (netxen_get_phy_speed(status)) {
836 case 0:
837 port->link_speed = SPEED_10;
838 break;
839 case 1:
840 port->link_speed = SPEED_100;
841 break;
842 case 2:
843 port->link_speed = SPEED_1000;
844 break;
845 default:
846 port->link_speed = -1;
847 break;
848 }
849 switch (netxen_get_phy_duplex(status)) {
850 case 0:
851 port->link_duplex = DUPLEX_HALF;
852 break;
853 case 1:
854 port->link_duplex = DUPLEX_FULL;
855 break;
856 default:
857 port->link_duplex = -1;
858 break;
859 }
860 if (adapter->ops->phy_read
861 && adapter->ops->
862 phy_read(adapter, port->portnum,
863 NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
864 (__le32 *) & autoneg) != 0)
865 port->link_autoneg = autoneg;
866 } else
867 goto link_down;
868 } else {
869 link_down:
870 port->link_speed = -1;
871 port->link_duplex = -1;
872 }
873 }
874}
875
876void netxen_nic_flash_print(struct netxen_adapter *adapter)
877{
878 int valid = 1;
879 u32 fw_major = 0;
880 u32 fw_minor = 0;
881 u32 fw_build = 0;
882
883 struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
884 if (board_info->magic != NETXEN_BDINFO_MAGIC) {
885 printk
886 ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n",
887 board_info->magic, NETXEN_BDINFO_MAGIC);
888 valid = 0;
889 }
890 if (board_info->header_version != NETXEN_BDINFO_VERSION) {
891 printk("NetXen Unknown board config version."
892 " Read %x, expected %x\n",
893 board_info->header_version, NETXEN_BDINFO_VERSION);
894 valid = 0;
895 }
896 if (valid) {
897 printk("NetXen %s Board #%d, Chip id 0x%x\n",
898 board_info->board_type == 0x0b ? "XGB" : "GBE",
899 board_info->board_num, board_info->chip_id);
900 fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
901 NETXEN_FW_VERSION_MAJOR));
902 fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
903 NETXEN_FW_VERSION_MINOR));
904 fw_build =
905 readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
906
907 printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor,
908 fw_build);
909 }
910 if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
911 printk(KERN_ERR "The mismatch in driver version and firmware "
912 "version major number\n"
913 "Driver version major number = %d \t"
914 "Firmware version major number = %d \n",
915 _NETXEN_NIC_LINUX_MAJOR, fw_major);
916 adapter->driver_mismatch = 1;
917 }
918 if (fw_minor != _NETXEN_NIC_LINUX_MINOR) {
919 printk(KERN_ERR "The mismatch in driver version and firmware "
920 "version minor number\n"
921 "Driver version minor number = %d \t"
922 "Firmware version minor number = %d \n",
923 _NETXEN_NIC_LINUX_MINOR, fw_minor);
924 adapter->driver_mismatch = 1;
925 }
926 if (adapter->driver_mismatch)
927 printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n",
928 fw_major, fw_minor);
929}
930
931int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off)
932{
933 int data;
934 netxen_nic_hw_read_wx(adapter, off, &data, 4);
935 return data;
936}