Add NetXen 1G/10G ethernet driver.
[safe/jmp/linux-2.6] / drivers / net / netxen / netxen_nic_hw.c
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
54 unsigned long netxen_nic_pci_set_window(void __iomem * pci_base,
55                                         unsigned long long addr);
56 void netxen_free_hw_resources(struct netxen_adapter *adapter);
57
58 int 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  */
82 void 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  */
138 int 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  */
161 int 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
306 void 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
346 void 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
369 int 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
391 static 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
416 int 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  */
444 void 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
482 void 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
515 int
516 netxen_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
560 int
561 netxen_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
601 void 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
612 int 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. */
627 void 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. */
638 void 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
649 int netxen_pci_set_window_warning_count = 0;
650
651 unsigned long
652 netxen_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
707 int 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
768 int 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
777 int 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
785 void 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
792 void 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
804 void
805 netxen_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
820 void 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
876 void 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
931 int 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 }