Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2904

kernel-2.6.18-238.el5.src.rpm

From: Marcus Barrow <mbarrow@redhat.com>
Date: Tue, 22 Sep 2009 16:25:13 -0400
Subject: [net] netxen: driver updates from 2.6.31
Message-id: <20090922162513.16918.22488.sendpatchset@file.bos.redhat.com>
Patchwork-id: 20920
O-Subject: [rhel 5.5 feat] [1/2] netxen - driver updates from 2.6.31
Bugzilla: 516833
RH-Acked-by: David S. Miller <davem@redhat.com>
RH-Acked-by: John Linville <linville@redhat.com>
RH-Acked-by: Andy Gospodarek <gospo@redhat.com>

BZ 516833 [1/2] netxen - P3+ updates

These patches bring the RHEL 5 driver up to parity with the upstream
driver. The first patch includes the changes up to 2.6.31, the second
patch includes the changes up to 2.6.32. These changes include bug fixes
and support for the P3+.

This work has been tested at QLogic. It applies and builds cleanly with
2.6.165.

commit 232e7d68d50c9ac3a55d716e5ae215ecd1e043b9
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Thu Aug 13 07:03:01 2009 +0000

    netxen: free napi resources during detach

    o Defer napi resouce allocation to device attach.

    o Free napi resources and delete napi during detach.

    This ensures right behavior across firmware reset.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit e424fa9d6a0add1a9b812b07e3607daaa5b9e53d
Author: Amit Kumar Salecha <amit@qlogic.com>
Date:   Thu Aug 13 07:03:00 2009 +0000

    netxen: remove netxen workqueue

    o Remove private workqueue in the driver, move all
      scheduled tasks to keventd workqueues. This makes
      ports (interfaces) of same / different NIC boards
      independent, in terms of their link watchdog and
      reset tasks.

    o Move quick checks for link status and temperature
      in timer callback, schedule watchdog task only if
      link status changed or temperature reached critical
      threshold.

    This also fixes deadlock when thermal panic occurs,
    watchdog work was flushing workqueue that it was
    sitting on.

    Signed-off-by: Amit Kumar Salecha <amit@qlogic.com>
    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f60f785679b507cbeeb03d2db080ab649ac86027
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Aug 4 10:39:03 2009 +0000

    netxen: fix dma mask update calculation

    Fix dma mask calculation that caps at 63-bit addressing even
    when firmware advertises full 64-bit support.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 50c643e7652458e649955408685a16e88ea6dbae
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Sat Aug 1 21:36:16 2009 +0000

    netxen: fix coherent dma mask setting

    Change default dma mask for NX3031 to 39 bit with ability
    to update it to 64-bit (if firmware indicates support). Old
    code was restricting it under 4GB (32-bit), sometimes causing
    failure to allocate descriptor rings on heavily populated
    system. NX2031 based NICs will still get 32-bit coherent mask.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit c8a5a658b826508c7c61b57e9a590f7b8760fb51
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Sun Jul 26 20:17:21 2009 -0700

    netxen: reset ring consumer during cleanup

    Reset consumer of status rings to 0 when cleaning
    up sw resources. Status rings are not deleted
    during suspend since they have napi objects.

    This ensures correct rx processing across suspen-resume.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit e4135c2da11c337e3759f98727c4819ba2a849fa
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Jul 17 15:27:08 2009 +0000

    netxen: fix thermal check and shutdown

    Check temperature for all PCI functions, that can allow
    graceful shutdown of all interfaces on the overheated card.

    Old code was only monitoring temperature for function 0 only.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit b2af9cb06d4de1b507ec0fd779ec2ecedee1480a
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Jul 17 15:27:07 2009 +0000

    netxen: fix deadlock on dev close

    netxen: fix deadlock on dev close

    The tx ring accounting fix in commit cb2107be43d2fc5eadec58b92b
    ("netxen: fix tx ring accounting") introduced intermittent
    deadlock when inteface is going down.

    This was possibly combined effect of speculative tx pause,
    calling netif_tx_lock instead of queue lock and unclean
    synchronization with napi which could end up unmasking
    interrupt.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit cf981ffb31e8f41f4899a56560f81322f94f22d1
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Jul 17 15:27:06 2009 +0000

    netxen: fix context deletion sequence

    o Use D3 reset context deletion for NX2031, it cleans up
      more resources in the firmware.
    o Release rx buffers after hardware context has been reset.
    o Delete tx context after rx context, some firmware control
      commands are sent on tx context, so it should be the last
      to go.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 67c38fc61af930fa03b042932b6b14fbf8126222
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Jul 1 11:41:43 2009 +0000

    netxen: avoid frequent firmware reset

    Restrict firmware reset to following cases -

    o chip rev is NX2031 (firmare doesn't support heartbit).
    o firmware is dead.
    o previous attempt to init firmware had failed.
    o we have got newer file firmware.

    This speeds up module load tremendously (by upto 8 sec),
    also avoids downtime for NCSI (management) pass-thru
    traffic.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 98e31bb00983a5b6d638a31e4ff77e5ca1ccf93e
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Jul 1 11:41:42 2009 +0000

    netxen: fix the version code macro

    Correct firmware encoding is 8 bit major, 8 bit minor and
    16 bit subversion. Flash has sizes rightly set, but original
    driver submission messed it leaving 16 bit major and 8 bit
    subversion.

    Also fix a infinite loop when cut-thru file firmware is
    invalid.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 96f2ebd2e10417da151202c750d8664767a2194b
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Jun 22 20:26:21 2009 +0000

    netxen: fix firmware init handshake

    Make sure all functions run firmware init handshake.

    If PCI function 0 fails to initialize firmware, mark the
    state failed so that other functions on the same board
    bail out quickly instead of waiting 30s for firmware
    handshake.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 01542cd1bbf995f951e2c2383d7911e96b12bec6
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Jun 22 20:26:20 2009 +0000

    netxen: fix build with without CONFIG_PM

    wrap pci suspend() and resume() with CONFIG_PM check.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit cb2107be43d2fc5eadec58b92b54bf32c00bfff3
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Jun 17 17:27:25 2009 +0000

    netxen: fix tx ring accounting

    This forces every update of tx ring producer to check for
    availability of space for next full TSO command. Earlier
    firmware control commands didn't care to pause tx queue.

    Stop the tx queue if there's not enough space to transmit one full
    LSO command left on the tx ring after current transmit. This avoids
    returning NETDEV_TX_BUSY after checking distance between producer
    and consumer on every cpu.

    Restart the tx queue only if we have cleaned up enough tx
    descriptors.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit d173346040af497af22818dfc48cff369e67cf50
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Jun 17 17:27:24 2009 +0000

    netxen: fix detection of cut-thru firmware mode

    Fix the detection of cut-thru mode of the hardware (direct dma
    to host) to mode configured in SRE (ingress block) rather than
    onboard memory control.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f2333a014c1e13ac8e1b73a6fd77731c524eff78
Author: Figo.zhang <figo1802@gmail.com>
Date:   Thu Jun 11 02:49:10 2009 -0700

    netxen: No need to check vfree() pointer.

    vfree() does its own 'NULL' check, so no need for check before
    calling it.

    Signed-off-by: Figo.zhang <figo1802@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f67f34084914144de55c785163d047d5d8dddd2d
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon May 18 21:46:40 2009 -0700

    netxen: fix msi irq setup

    The pdev->irq was not saved in netxen_adapter, causing request_irq()
    with invalid irq number.

    This was broken in commit be339aee634d5cb98a8df8d6febe04002ec497f3
    ("netxen: fix irq tear down and msix leak.").

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 23b6cc425d718fce2501d5f60e368cfa44ef7d86
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri May 8 22:02:30 2009 +0000

    netxen: trivial register access cleanup

    Remove unnecessary length parameter since it's always 4 bytes.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit b0b3a75b36afe3b1ed2c12b8817b6326db8ed003
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri May 8 22:02:29 2009 +0000

    netxen: disable msi-x for NC512m adapter

    This board doesn't suppot msi-x well due to msi-x table
    mapping (hardware) issue.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit be339aee634d5cb98a8df8d6febe04002ec497f3
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri May 8 22:02:28 2009 +0000

    netxen: fix irq tear down and msix leak.

    o Fix the order of irq and hardware context teardown.
      Also synchronize the interrupt in dev close() before
      releasing tx buffers.

    o Fix possible msi-x vector leak if available vectors are
      less than requested.

    o Request multiple msix vectors only if hardware supports
      multiple rx queues.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 7a2469ce4d8984722d65628969ad6f8b09da136f
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri May 8 22:02:27 2009 +0000

    netxen: cache msi register offset

    Store msi target status register offset in adapter struct.
    This avoids contention on msi_tgt_status table from interrupt
    hadlers of different pci function.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 3d0a3cc9d72047e4baa76021c897f64fc84cc543
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue May 5 19:05:08 2009 +0000

    netxen: fix bonding support

    o Pause traffic during mac addr change.
    o Enable setting mac address for NX3031.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 5cf4d323f8864dab818d500ec74f2fcb9ad5bf89
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue May 5 19:05:07 2009 +0000

    netxen: fix mac list management

    o use standard linked list api for mac addr list management
      in NX3031.
    o release mac addresses in firmware in dev close().

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 22527864ed7ee6c50f3c4d4b03c83c963caf5c0b
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue May 5 19:05:06 2009 +0000

    netxen: fix race in tx ring acccess

    Fix the distance check between tx ring producer and consumer that
    could lead to tx ring wrap around.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f7185c71234434d48b96f9a0387737df1759a4af
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 28 15:29:11 2009 +0000

    netxen: fix firmware download

    o hold the firmware in memory across suspend, since filesystem
      may not be up after resuming.
    o reset the chip after requesting firmware, to minimize downtime
      for NC-SI.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 4ea528a151549df795c984649d75860ea40390bd
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 28 15:29:10 2009 +0000

    netxen: refactor netxen_recv_context struct

    o move related fields into netxen_recv_context struct.
    o allocate rx buffer and descriptor rings dynamically.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 5103c9f7874506cb40fc3c8d3f22486d3c4d91aa
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 28 15:29:09 2009 +0000

    netxen: fix link event handling

    Firmware starting 4.0.402 started supporting link events, disable
    it for older firmwares.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit ea7eaa39ffadffaa8f1dd1a1f85fa38bf8ae9d39
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:48 2009 +0000

    netxen: cache align register map table

    Aligning register offset translation table imporves performance
    on rx side.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit a92e9e65f0068a291a677c627a747fae1f230284
Author: Amit Kumar Salecha <amit@dut4146.(none)>
Date:   Tue Apr 7 22:50:47 2009 +0000

    netxen: enable GRO support

    Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f6d21f44122630cc9549b8ffbab23ea8c68254e0
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:46 2009 +0000

    netxen: enable rss for NX2031

    Enable multiple rx rings for older NX2031 chip, firmware 3.4.336
    or newer supports this feature.

    Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit f98a9f693b5f4919d9c4085a2fd8d67c7e152f3e
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:45 2009 +0000

    netxen: sanitize function names

    Replace superfluous wrapper functions with two macros:

    NXWR32 replaces netxen_nic_reg_write, netxen_nic_write_w0,
    netxen_nic_read_w1, netxen_crb_writelit_adapter.

    NXRD32 replaces netxen_nic_reg_read, netxen_nic_read_w0,
    netxen_nic_read_w1.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 1fbe63235893e5dce28fe91d8465dd231b0cb3d9
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:44 2009 +0000

    netxen: annotate register access functions

    o remove unnecessary length parameter since register access
      width is fixed 4 byte.
    o remove superfluous pci_read_normalize and pci_write_normalize
      functions.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 71dcddbdd35487eb931aa8aab28a2df474008754
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:43 2009 +0000

    netxen: allocate status rings dynamically

    This reduces netxen_adapter footprint when rss (msi-x) is disabled.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 3bf26ce3f4cc3c9e0d0478b4016c6113a16faaf1
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:42 2009 +0000

    netxen: async link event handling

    Add support for asynchronous events from firmware,
    received over one of the rx rings.

    Add support for event based phy interrupts, enhanced links
    status reporting from firmware.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 56a007871a6689db80e19f63fe6dc3692daa2a6f
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:41 2009 +0000

    netxen: defer firmware handshake

    Removed duplicate firmware handshake, defer it until first
    port (interface) is brought up.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit d877f1e344f5515988d9dcd6db5d4285911778a3
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:40 2009 +0000

    netxen: refactor transmit code

    o move tx stuff into nx_host_tx_ring structure, this will
      help managing multiple tx rings in future.
    o sanitize some variable names

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 1b1f789818c6be9437cfe199932ee13faafca60f
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:39 2009 +0000

    netxen: refactor netxen_adapter

    Rearrange members to align them at right offset.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit e98e3350c03af4187e1d5fe007c7b460e378990c
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Apr 7 22:50:38 2009 +0000

    netxen: code cleanup

    o remove unused structure defs.
    o remove unnecessary includes.
    o replace enums with specific #defines.
    o reduce footprint of stats structure.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 6afd142fd0dfba497246d0fab236c20a7b4bf778
Author: Yang Hongyang <yanghy@cn.fujitsu.com>
Date:   Mon Apr 6 19:01:15 2009 -0700

    dma-mapping: replace all DMA_39BIT_MASK macro with DMA_BIT_MASK(39)

    Replace all DMA_39BIT_MASK macro with DMA_BIT_MASK(39)

    Signed-off-by: Yang Hongyang<yanghy@cn.fujitsu.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

commit bd257ed9f1d129b4e881f513a406b435c8852565
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Mar 17 13:14:22 2009 -0700

    netxen: fix firmware download warnings

    Fix following warnings, by using integer firmware types.

    drivers/net/netxen/netxen_nic_hw.c: In function 'netxen_load_firmware':
    drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior
    drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior
    drivers/net/netxen/netxen_nic_hw.c:1146: warning: comparison with string literal results in unspecified behavior
    drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior
    drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior
    drivers/net/netxen/netxen_nic_hw.c:1159: warning: comparison with string literal results in unspecified behavior

    Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit ff4fbd43fe82de28710761f2cc2ed122d716483a
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:06 2009 +0000

    netxen: update version to 4.0.30

    To mark all features and bugfixes submitted since 4.0.11.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit d8b100c5da003b6f8c410453e1e6e74ced8d1cc1
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:05 2009 +0000

    netxen: add receive side scaling (rss) support

    This patch enables the load balancing capability of firmware
    and hardware to spray traffic into different cpus through
    separate rx msix interrupts.

    The feature is being enabled for NX3031, NX2031 (old) will be
    enabled later. This depends on msi-x and compatibility with
    msi and legacy is maintained by enabling single rx ring.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 9b3ef55c6ddbe8c7b76707eae9a77d874fe2cec0
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:04 2009 +0000

    netxen: remove old lro code

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 438627c77b877e445a4b918a50ff910a5ea2a12d
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:03 2009 +0000

    netxen: sanitize variable names

    o remove max_ prefix from ring sizes, since they don't really
      represent max possible sizes.
    o cleanup naming of rx ring types (normal, jumbo, lro).
    o simplify logic to choose rx ring size, gig ports get half
      rx ring of 10 gig ports.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 0b72e659a10ec50acbef90756bf04177b66c8266
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:02 2009 +0000

    netxen: add suspend resume support

    Detach network interface on PCI suspend and recreate hardware
    context after resumes.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit fbb52f2272e6265295f0e5f6187b628e4c162eca
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 13 14:52:01 2009 +0000

    netxen: fix endianness in serial number

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 1e2d0059fc24c84356721c16c2ad0590c38015a0
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 9 08:50:56 2009 +0000

    netxen: annotate board_config and board_type

    Remove huge board config structure from each instance, read
    only necessary fields from flash.

    Replace board_type with port_type (1G/10G), there's another
    board_type field describing card type (SFP/XFP/CX4).

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit becf46a012db667c562bbbe589c14e100b62e5a4
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 9 08:50:55 2009 +0000

    netxen: cleanup superfluous multi-context code

    MAX_RCV_CTX was set to 1, there's only rx context per
    PCI function.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 9f5bc7f1908665d7cf379f698c7bdc53bc10da85
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 9 08:50:54 2009 +0000

    netxen: refactor netdev open close

    rearrange open and close into hardware attach(), detach() and
    nic up() and down(). this will be used for suspend/resume
    subsequently.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit d32cc3d24eace8a271a39ffe8aeae1861f400d2d
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 9 08:50:53 2009 +0000

    netxen: small xmit optimizations

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 0ddc110c6fef34c554999448cdffe9c174a15fc9
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 9 08:50:52 2009 +0000

    netxen: cleanup rx handling

    o remove unused rx fragment handling code.
    o imporove check for status descriptor ownership.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 567c6c4e2b92f4b8632b043f9395b216b7e7c3ce
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 2 16:02:17 2009 +0000

    netxen: firmware download improvements

    o set port mode after resetting device.
    o prefer cut-through firmware (doesn't require on-card memory).
    o load flashed firmware if newer.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 1f434f638457712732238329dfdf089eab25e5b3
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Mon Mar 2 16:02:16 2009 +0000

    netxen: support larger dma addressing

    Support larger dma mask if firmware indicates capability
    to handle larger addresses.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 5d242f1cee2c85721bbe9d8205e98c1c01f5d805
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Feb 25 15:57:56 2009 +0000

    netxen: update copyright

    Extend copyright into 2009 and update address.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 97daee83b0fd2361cc70be6f3d6ecda69def2103
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Feb 24 16:39:21 2009 -0800

    netxen: refactor pci probe

    Split pci probe function into smaller logical blocks.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit dbf64b10fa5b339d8b6e949f97c0d00750b08ca8
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Feb 24 16:39:03 2009 -0800

    netxen: cleanup unused code

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 4da129421f898147235a3e6b40234d789df208b7
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Feb 24 16:38:44 2009 -0800

    netxen: advertise wake-on-lan support

    Add ethtool wake on lan support.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit ba599d4f0d2071abc049cb6345eab510a8a3643e
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Feb 24 16:38:22 2009 -0800

    netxen: firmware download support

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit d8313ce0f148e648d4e515db5d2c65bbd44fe29e
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Tue Feb 17 20:26:44 2009 -0800

    netxen: fix sparse warnings

    Fix following sparse warnings (multiple instances)

    warning: restricted degrades to integer
    warning: cast to restricted type
    warning: incorrect type in argument 3 (different signedness)
    warning: context imbalance in 'netxen_nic_hw_write_wx_2M' - different
    lock contexts for basic block

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit de9307c68624b03d2922a02a661ce31e20f078cc
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Fri Mar 6 14:52:12 2009 +0000

    netxen: remove old flash check.

    Remove flash size check which made sense only for ancient
    boards with 1MB flash. The check is based on values read
    from specific locations and fails with firmware size changes.

    This prevents driver from getting right mac addresses.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 03e678ee968ae54b79c1580c2935895bd863ad95
Author: Dhananjay Phadke <dhananjay@netxen.com>
Date:   Wed Jan 14 20:49:43 2009 -0800

    netxen: hold tx lock while sending firmware commands

    Some firmware commands like mac address addition/deletion are sent
    on the transmit ring. So need to hold the tx lock before touching
    tx producer/consumer indices.

    Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 1abd266f091e4f281a7c1e8813106fdf1528bb56
Author: Stephen Hemminger <shemminger@vyatta.com>
Date:   Fri Nov 21 17:32:15 2008 -0800

    netxen: convert to net_device_ops

    Convert driver to new net_device_ops. Compile tested only.
    Had to do some refactoring on multicast_list.
    Fix ethtool restart to propogate error code.

    Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit b39d66a81fb4f5ab555f86a2e49f3714f8369a3d
Author: Harvey Harrison <harvey.harrison@gmail.com>
Date:   Wed Aug 20 16:52:04 2008 -0700

    drivers/net: replace __FUNCTION__ with __func__

    __FUNCTION__ is gcc-specific, use __func__

    Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

commit 7a8fc9b248e77a4eab0613acf30a6811799786b3
Author: Adrian Bunk <bunk@kernel.org>
Date:   Sun Aug 17 17:36:59 2008 +0300

    removed unused #include <linux/version.h>'s

    This patch lets the files using linux/version.h match the files that
    #include it.

    Signed-off-by: Adrian Bunk <bunk@kernel.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

commit aa39432326a91a7b819ec3f8d78b05e04b708ce5
Author: Adrian Bunk <bunk@kernel.org>
Date:   Mon Mar 31 02:22:14 2008 +0300

    #if 0 netxen_nic_link_ok()

    This patch #if 0's the no longer used netxen_nic_link_ok().

    Signed-off-by: Adrian Bunk <bunk@kernel.org>
    Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

commit f305f789bb96ee6e35e71f58324b72abb7bd0b13
Author: Al Viro <viro@ftp.linux.org.uk>
Date:   Sat Dec 22 19:44:00 2007 +0000

    annotate netxen

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Jeff Garzik <jeff@garzik.org>

commit 79ea13ce07c951bb4d95471e7300baa0f1be9e78
Author: Al Viro <viro@zeniv.linux.org.uk>
Date:   Thu Jan 24 02:06:46 2008 -0800

    NULL noise in drivers/net

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Jeff Garzik <jeff@garzik.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>

commit 5bc51424b4d1c1121fb8861620f14262d828d1d9
Author: Joe Perches <joe@perches.com>
Date:   Mon Nov 19 17:48:24 2007 -0800

    drivers/net/netxen: Add missing "space"

    Signed-off-by: Joe Perches <joe@perches.com>
    Signed-off-by: Jeff Garzik <jeff@garzik.org>

commit 993fb90c5b1727342362c43ed4e29c26682f54f7
Author: Adrian Bunk <bunk@kernel.org>
Date:   Mon Nov 5 18:07:31 2007 +0100

    drivers/net/netxen/: cleanups

    This patch contains the following cleanups:
    - static functions in .c files shouldn't be marked inline
    - make needlessly global code static
    - #if 0 unused code

    Signed-off-by: Adrian Bunk <bunk@kernel.org>
    Signed-off-by: Jeff Garzik <jeff@garzik.org>

Signed-off-by: Don Zickus <dzickus@redhat.com>

diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
index b756a6b..6a39d43 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/netxen/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2003 - 2006 NetXen, Inc.
+# Copyright (C) 2003 - 2009 NetXen, Inc.
 # All rights reserved.
 #
 # This program is free software; you can redistribute it and/or
@@ -21,11 +21,10 @@
 #
 # Contact Information:
 #    info@netxen.com
-# NetXen,
-# 3965 Freedom Circle, Fourth floor,
-# Santa Clara, CA 95054
+# NetXen Inc,
+# 18922 Forge Drive
+# Cupertino, CA 95014-0701
 #
-# Makefile for the NetXen NIC Driver
 #
 
 
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 1c7ac2f..b10ebdb 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,9 +22,10 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
+ *
  */
 
 #ifndef _NETXEN_NIC_H_
@@ -33,10 +34,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -45,31 +43,37 @@
 #include <linux/in.h>
 #include <linux/tcp.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
+#include <linux/firmware.h>
 
 #include <linux/ethtool.h>
 #include <linux/mii.h>
-#include <linux/interrupt.h>
 #include <linux/timer.h>
 
-#include <linux/mm.h>
-#include <linux/mman.h>
 #include <linux/vmalloc.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
 
 #include "netxen_nic_hw.h"
+#include "netxen_nic_compat.h"
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 11
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.11"
-
-#define NETXEN_VERSION_CODE(a, b, c)	(((a) << 16) + ((b) << 8) + (c))
+#define _NETXEN_NIC_LINUX_SUBVERSION 30
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.30"
+
+#define NETXEN_VERSION_CODE(a, b, c)	(((a) << 24) + ((b) << 16) + (c))
+#define _major(v)	(((v) >> 24) & 0xff)
+#define _minor(v)	(((v) >> 16) & 0xff)
+#define _build(v)	((v) & 0xffff)
+
+/* version in image has weird encoding:
+ *  7:0  - major
+ * 15:8  - minor
+ * 31:16 - build (little endian)
+ */
+#define NETXEN_DECODE_VERSION(v) \
+	NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16))
 
 #define NETXEN_NUM_FLASH_SECTORS (64)
 #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -78,19 +82,19 @@
 
 #define PHAN_VENDOR_ID 0x4040
 
-#define RCV_DESC_RINGSIZE	\
-	(sizeof(struct rcv_desc) * adapter->max_rx_desc_count)
-#define STATUS_DESC_RINGSIZE	\
-	(sizeof(struct status_desc)* adapter->max_rx_desc_count)
-#define LRO_DESC_RINGSIZE	\
-	(sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count)
-#define TX_RINGSIZE	\
-	(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
-#define RCV_BUFFSIZE	\
-	(sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count)
+#define RCV_DESC_RINGSIZE(rds_ring)	\
+	(sizeof(struct rcv_desc) * (rds_ring)->num_desc)
+#define RCV_BUFF_RINGSIZE(rds_ring)	\
+	(sizeof(struct netxen_rx_buffer) * rds_ring->num_desc)
+#define STATUS_DESC_RINGSIZE(sds_ring)	\
+	(sizeof(struct status_desc) * (sds_ring)->num_desc)
+#define TX_BUFF_RINGSIZE(tx_ring)	\
+	(sizeof(struct netxen_cmd_buffer) * tx_ring->num_desc)
+#define TX_DESC_RINGSIZE(tx_ring)	\
+	(sizeof(struct cmd_desc_type0) * tx_ring->num_desc)
+
 #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
 
-#define NETXEN_NETDEV_STATUS		0x1
 #define NETXEN_RCV_PRODUCER_OFFSET	0
 #define NETXEN_RCV_PEG_DB_ID		2
 #define NETXEN_HOST_DUMMY_DMA_SIZE 1024
@@ -118,6 +122,7 @@
 #define NX_P3_A2		0x30
 #define NX_P3_B0		0x40
 #define NX_P3_B1		0x41
+#define NX_P3_B2		0x42
 
 #define NX_IS_REVISION_P2(REVISION)     (REVISION <= NX_P2_C1)
 #define NX_IS_REVISION_P3(REVISION)     (REVISION >= NX_P3_A0)
@@ -177,6 +182,7 @@
 #define	MAX_NUM_CARDS		4
 
 #define MAX_BUFFERS_PER_CMD	32
+#define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + 4)
 
 /*
  * Following are the states of the Phantom. Phantom will set them and
@@ -189,22 +195,12 @@
 /* Host writes the following to notify that it has done the init-handshake */
 #define PHAN_INITIALIZE_ACK	0xf00f
 
-#define NUM_RCV_DESC_RINGS	3	/* No of Rcv Descriptor contexts */
+#define NUM_RCV_DESC_RINGS	3
+#define NUM_STS_DESC_RINGS	4
 
-/* descriptor types */
-#define RCV_DESC_NORMAL		0x01
-#define RCV_DESC_JUMBO		0x02
-#define RCV_DESC_LRO		0x04
-#define RCV_DESC_NORMAL_CTXID	0
-#define RCV_DESC_JUMBO_CTXID	1
-#define RCV_DESC_LRO_CTXID	2
-
-#define RCV_DESC_TYPE(ID) \
-	((ID == RCV_DESC_JUMBO_CTXID)	\
-		? RCV_DESC_JUMBO	\
-		: ((ID == RCV_DESC_LRO_CTXID)	\
-			? RCV_DESC_LRO :	\
-			(RCV_DESC_NORMAL)))
+#define RCV_RING_NORMAL	0
+#define RCV_RING_JUMBO	1
+#define RCV_RING_LRO	2
 
 #define MAX_CMD_DESCRIPTORS		4096
 #define MAX_RCV_DESCRIPTORS		16384
@@ -213,18 +209,11 @@
 #define MAX_RCV_DESCRIPTORS_10G		4096
 #define MAX_JUMBO_RCV_DESCRIPTORS	1024
 #define MAX_LRO_RCV_DESCRIPTORS		8
-#define MAX_RCVSTATUS_DESCRIPTORS	MAX_RCV_DESCRIPTORS
-#define MAX_JUMBO_RCV_DESC	MAX_JUMBO_RCV_DESCRIPTORS
-#define MAX_RCV_DESC		MAX_RCV_DESCRIPTORS
-#define MAX_RCVSTATUS_DESC	MAX_RCV_DESCRIPTORS
-#define MAX_EPG_DESCRIPTORS	(MAX_CMD_DESCRIPTORS * 8)
-#define NUM_RCV_DESC		(MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \
-				 MAX_LRO_RCV_DESCRIPTORS)
-#define MIN_TX_COUNT	4096
-#define MIN_RX_COUNT	4096
 #define NETXEN_CTX_SIGNATURE	0xdee0
+#define NETXEN_CTX_SIGNATURE_V2	0x0002dee0
+#define NETXEN_CTX_RESET	0xbad0
+#define NETXEN_CTX_D3_RESET	0xacc0
 #define NETXEN_RCV_PRODUCER(ringid)	(ringid)
-#define MAX_FRAME_SIZE	0x10000	/* 64K MAX size for LSO */
 
 #define PHAN_PEG_RCV_INITIALIZED	0xff01
 #define PHAN_PEG_RCV_START_INITIALIZE	0xff00
@@ -263,12 +252,19 @@ typedef u32 netxen_ctx_msg;
 #define netxen_set_msg_opcode(config_word, val)	\
 	((config_word) &= ~(0xf<<28), (config_word) |= (val & 0xf) << 28)
 
-struct netxen_rcv_context {
-	__le64 rcv_ring_addr;
-	__le32 rcv_ring_size;
+struct netxen_rcv_ring {
+	__le64 addr;
+	__le32 size;
 	__le32 rsrvd;
 };
 
+struct netxen_sts_ring {
+	__le64 addr;
+	__le32 size;
+	__le16 msi_index;
+	__le16 rsvd;
+} ;
+
 struct netxen_ring_ctx {
 
 	/* one command ring */
@@ -278,13 +274,18 @@ struct netxen_ring_ctx {
 	__le32 rsrvd;
 
 	/* three receive rings */
-	struct netxen_rcv_context rcv_ctx[3];
+	struct netxen_rcv_ring rcv_rings[NUM_RCV_DESC_RINGS];
 
-	/* one status ring */
 	__le64 sts_ring_addr;
 	__le32 sts_ring_size;
 
 	__le32 ctx_id;
+
+	__le64 rsrvd_2[3];
+	__le32 sts_ring_count;
+	__le32 rsrvd_3;
+	struct netxen_sts_ring sts_rings[NUM_STS_DESC_RINGS];
+
 } __attribute__ ((aligned(64)));
 
 /*
@@ -353,10 +354,7 @@ struct cmd_desc_type0 {
 		__le64 addr_buffer1;
 	};
 
-	__le16 buffer1_length;
-	__le16 buffer2_length;
-	__le16 buffer3_length;
-	__le16 buffer4_length;
+	__le16 buffer_length[4];
 
 	union {
 		struct {
@@ -381,25 +379,21 @@ struct rcv_desc {
 /* opcode field in status_desc */
 #define NETXEN_NIC_RXPKT_DESC  0x04
 #define NETXEN_OLD_RXPKT_DESC  0x3f
+#define NETXEN_NIC_RESPONSE_DESC 0x05
 
 /* for status field in status_desc */
 #define STATUS_NEED_CKSUM	(1)
 #define STATUS_CKSUM_OK		(2)
 
 /* owner bits of status_desc */
-#define STATUS_OWNER_HOST	(0x1)
-#define STATUS_OWNER_PHANTOM	(0x2)
-
-#define NETXEN_PROT_IP		(1)
-#define NETXEN_PROT_UNKNOWN	(0)
-
-/* Note: sizeof(status_desc) should always be a mutliple of 2 */
-
-#define netxen_get_sts_desc_lro_cnt(status_desc)        \
-	(((status_desc)->lro) & 0x7F)
-#define netxen_get_sts_desc_lro_last_frag(status_desc)  \
-	((((status_desc)->lro) >> 7) & 0x1)
+#define STATUS_OWNER_HOST	(0x1ULL << 56)
+#define STATUS_OWNER_PHANTOM	(0x2ULL << 56)
 
+/* Status descriptor:
+   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+   53-55 desc_cnt, 56-57 owner, 58-63 opcode
+ */
 #define netxen_get_sts_port(sts_data)	\
 	((sts_data) & 0x0F)
 #define netxen_get_sts_status(sts_data)	\
@@ -414,51 +408,15 @@ struct rcv_desc {
 	(((sts_data) >> 44) & 0x0F)
 #define netxen_get_sts_pkt_offset(sts_data)	\
 	(((sts_data) >> 48) & 0x1F)
+#define netxen_get_sts_desc_cnt(sts_data)	\
+	(((sts_data) >> 53) & 0x7)
 #define netxen_get_sts_opcode(sts_data)	\
 	(((sts_data) >> 58) & 0x03F)
 
-#define netxen_get_sts_owner(status_desc)       \
-	(((status_desc) >> 56) & 0x03)
-
-#define netxen_set_sts_owner(status_desc, val)	{ \
-	(status_desc)->status_desc_data = \
-		((status_desc)->status_desc_data & \
-		~cpu_to_le64(0x3ULL << 56)) | \
-		cpu_to_le64((u64)((val) & 0x3) << 56); \
-}
-
 struct status_desc {
-	/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
-	   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
-	   53-55 desc_cnt, 56-57 owner, 58-63 opcode
-	 */
-	__le64 status_desc_data;
-	union {
-		struct {
-			__le32 hash_value;
-			u8 hash_type;
-			u8 msg_type;
-			u8 unused;
-			union {
-				/* Bit pattern: 0-6 lro_count indicates frag
-				 * sequence, 7 last_frag indicates last frag
-				 */
-				u8 lro;
-
-				/* chained buffers */
-				u8 nr_frags;
-			};
-		};
-		struct {
-			__le16 frag_handles[4];
-		};
-	};
+	__le64 status_desc_data[2];
 } __attribute__ ((aligned(16)));
 
-enum {
-	NETXEN_RCV_PEG_0 = 0,
-	NETXEN_RCV_PEG_1
-};
 /* The version of the main data structure */
 #define	NETXEN_BDINFO_VERSION 1
 
@@ -468,85 +426,35 @@ enum {
 /* Max number of Gig ports on a Phantom board */
 #define NETXEN_MAX_PORTS 4
 
-typedef enum {
-	NETXEN_BRDTYPE_P1_BD = 0x0000,
-	NETXEN_BRDTYPE_P1_SB = 0x0001,
-	NETXEN_BRDTYPE_P1_SMAX = 0x0002,
-	NETXEN_BRDTYPE_P1_SOCK = 0x0003,
-
-	NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008,
-	NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009,
-	NETXEN_BRDTYPE_P2_SB35_4G = 0x000a,
-	NETXEN_BRDTYPE_P2_SB31_10G = 0x000b,
-	NETXEN_BRDTYPE_P2_SB31_2G = 0x000c,
-
-	NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
-	NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
-	NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
-
-	NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
-	NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
-	NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
-	NETXEN_BRDTYPE_P3_4_GB = 0x0024,
-	NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
-	NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
-	NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
-	NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
-	NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
-	NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a,
-	NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b,
-	NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
-	NETXEN_BRDTYPE_P3_10G_XFP = 0x0032,
-	NETXEN_BRDTYPE_P3_10G_TP = 0x0080
-
-} netxen_brdtype_t;
-
-typedef enum {
-	NETXEN_BRDMFG_INVENTEC = 1
-} netxen_brdmfg;
-
-typedef enum {
-	MEM_ORG_128Mbx4 = 0x0,	/* DDR1 only */
-	MEM_ORG_128Mbx8 = 0x1,	/* DDR1 only */
-	MEM_ORG_128Mbx16 = 0x2,	/* DDR1 only */
-	MEM_ORG_256Mbx4 = 0x3,
-	MEM_ORG_256Mbx8 = 0x4,
-	MEM_ORG_256Mbx16 = 0x5,
-	MEM_ORG_512Mbx4 = 0x6,
-	MEM_ORG_512Mbx8 = 0x7,
-	MEM_ORG_512Mbx16 = 0x8,
-	MEM_ORG_1Gbx4 = 0x9,
-	MEM_ORG_1Gbx8 = 0xa,
-	MEM_ORG_1Gbx16 = 0xb,
-	MEM_ORG_2Gbx4 = 0xc,
-	MEM_ORG_2Gbx8 = 0xd,
-	MEM_ORG_2Gbx16 = 0xe,
-	MEM_ORG_128Mbx32 = 0x10002,	/* GDDR only */
-	MEM_ORG_256Mbx32 = 0x10005	/* GDDR only */
-} netxen_mn_mem_org_t;
-
-typedef enum {
-	MEM_ORG_512Kx36 = 0x0,
-	MEM_ORG_1Mx36 = 0x1,
-	MEM_ORG_2Mx36 = 0x2
-} netxen_sn_mem_org_t;
-
-typedef enum {
-	MEM_DEPTH_4MB = 0x1,
-	MEM_DEPTH_8MB = 0x2,
-	MEM_DEPTH_16MB = 0x3,
-	MEM_DEPTH_32MB = 0x4,
-	MEM_DEPTH_64MB = 0x5,
-	MEM_DEPTH_128MB = 0x6,
-	MEM_DEPTH_256MB = 0x7,
-	MEM_DEPTH_512MB = 0x8,
-	MEM_DEPTH_1GB = 0x9,
-	MEM_DEPTH_2GB = 0xa,
-	MEM_DEPTH_4GB = 0xb,
-	MEM_DEPTH_8GB = 0xc,
-	MEM_DEPTH_16GB = 0xd,
-	MEM_DEPTH_32GB = 0xe
-} netxen_mem_depth_t;
+#define NETXEN_BRDTYPE_P1_BD		0x0000
+#define NETXEN_BRDTYPE_P1_SB		0x0001
+#define NETXEN_BRDTYPE_P1_SMAX		0x0002
+#define NETXEN_BRDTYPE_P1_SOCK		0x0003
+
+#define NETXEN_BRDTYPE_P2_SOCK_31	0x0008
+#define NETXEN_BRDTYPE_P2_SOCK_35	0x0009
+#define NETXEN_BRDTYPE_P2_SB35_4G	0x000a
+#define NETXEN_BRDTYPE_P2_SB31_10G	0x000b
+#define NETXEN_BRDTYPE_P2_SB31_2G	0x000c
+
+#define NETXEN_BRDTYPE_P2_SB31_10G_IMEZ		0x000d
+#define NETXEN_BRDTYPE_P2_SB31_10G_HMEZ		0x000e
+#define NETXEN_BRDTYPE_P2_SB31_10G_CX4		0x000f
+
+#define NETXEN_BRDTYPE_P3_REF_QG	0x0021
+#define NETXEN_BRDTYPE_P3_HMEZ		0x0022
+#define NETXEN_BRDTYPE_P3_10G_CX4_LP	0x0023
+#define NETXEN_BRDTYPE_P3_4_GB		0x0024
+#define NETXEN_BRDTYPE_P3_IMEZ		0x0025
+#define NETXEN_BRDTYPE_P3_10G_SFP_PLUS	0x0026
+#define NETXEN_BRDTYPE_P3_10000_BASE_T	0x0027
+#define NETXEN_BRDTYPE_P3_XG_LOM	0x0028
+#define NETXEN_BRDTYPE_P3_4_GB_MM	0x0029
+#define NETXEN_BRDTYPE_P3_10G_SFP_CT	0x002a
+#define NETXEN_BRDTYPE_P3_10G_SFP_QT	0x002b
+#define NETXEN_BRDTYPE_P3_10G_CX4	0x0031
+#define NETXEN_BRDTYPE_P3_10G_XFP	0x0032
+#define NETXEN_BRDTYPE_P3_10G_TP	0x0080
 
 struct netxen_board_info {
 	u32 header_version;
@@ -697,17 +605,25 @@ struct netxen_new_user_info {
 #define PRIMARY_IMAGE_BAD	0xffffffff
 
 /* Flash memory map */
-typedef enum {
-	NETXEN_CRBINIT_START = 0,	/* Crbinit section */
-	NETXEN_BRDCFG_START = 0x4000,	/* board config */
-	NETXEN_INITCODE_START = 0x6000,	/* pegtune code */
-	NETXEN_BOOTLD_START = 0x10000,	/* bootld */
-	NETXEN_IMAGE_START = 0x43000,	/* compressed image */
-	NETXEN_SECONDARY_START = 0x200000,	/* backup images */
-	NETXEN_PXE_START = 0x3E0000,	/* user defined region */
-	NETXEN_USER_START = 0x3E8000,	/* User defined region for new boards */
-	NETXEN_FIXED_START = 0x3F0000	/* backup of crbinit */
-} netxen_flash_map_t;
+#define NETXEN_CRBINIT_START	0	/* crbinit section */
+#define NETXEN_BRDCFG_START	0x4000	/* board config */
+#define NETXEN_INITCODE_START	0x6000	/* pegtune code */
+#define NETXEN_BOOTLD_START	0x10000	/* bootld */
+#define NETXEN_IMAGE_START	0x43000	/* compressed image */
+#define NETXEN_SECONDARY_START	0x200000	/* backup images */
+#define NETXEN_PXE_START	0x3E0000	/* PXE boot rom */
+#define NETXEN_USER_START	0x3E8000	/* Firmare info */
+#define NETXEN_FIXED_START	0x3F0000	/* backup of crbinit */
+
+#define NX_FW_VERSION_OFFSET	(NETXEN_USER_START+0x408)
+#define NX_FW_SIZE_OFFSET	(NETXEN_USER_START+0x40c)
+#define NX_BIOS_VERSION_OFFSET	(NETXEN_USER_START+0x83c)
+#define NX_FW_MAGIC_OFFSET	(NETXEN_BRDCFG_START+0x128)
+#define NX_FW_MIN_SIZE		(0x3fffff)
+#define NX_P2_MN_ROMIMAGE	0
+#define NX_P3_CT_ROMIMAGE	1
+#define NX_P3_MN_ROMIMAGE	2
+#define NX_FLASH_ROMIMAGE	3
 
 #define NETXEN_USER_START_OLD NETXEN_PXE_START	/* for backward compatibility */
 
@@ -720,23 +636,10 @@ typedef enum {
 #define NETXEN_FLASH_SECONDARY_SIZE 	(NETXEN_USER_START-NETXEN_SECONDARY_START)
 #define NETXEN_NUM_PRIMARY_SECTORS	(0x20)
 #define NETXEN_NUM_CONFIG_SECTORS 	(1)
-#define PFX "NetXen: "
 extern char netxen_nic_driver_name[];
 
-/* Note: Make sure to not call this before adapter->port is valid */
-#if !defined(NETXEN_DEBUG)
-#define DPRINTK(klevel, fmt, args...)	do { \
-	} while (0)
-#else
-#define DPRINTK(klevel, fmt, args...)	do { \
-	printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
-		(adapter != NULL && adapter->netdev != NULL) ? \
-		adapter->netdev->name : NULL, \
-		## args); } while(0)
-#endif
-
 /* Number of status descriptors to handle per interrupt */
-#define MAX_STATUS_HANDLE	(128)
+#define MAX_STATUS_HANDLE	(64)
 
 /*
  * netxen_skb_frag{} is to contain mapping info for each SG list. This
@@ -744,7 +647,7 @@ extern char netxen_nic_driver_name[];
  */
 struct netxen_skb_frag {
 	u64 dma;
-	ulong length;
+	u64 length;
 };
 
 #define _netxen_set_bits(config_word, start, bits, val)  {\
@@ -775,9 +678,6 @@ struct netxen_rx_buffer {
 	u64 dma;
 	u16 ref_handle;
 	u16 state;
-	u32 lro_expected_frags;
-	u32 lro_current_frags;
-	u32 lro_length;
 };
 
 /* Board types */
@@ -792,49 +692,35 @@ struct netxen_hardware_context {
 	void __iomem *pci_base0;
 	void __iomem *pci_base1;
 	void __iomem *pci_base2;
-	unsigned long first_page_group_end;
-	unsigned long first_page_group_start;
 	void __iomem *db_base;
 	unsigned long db_len;
 	unsigned long pci_len0;
 
-	u8 cut_through;
 	int qdr_sn_window;
 	int ddr_mn_window;
 	unsigned long mn_win_crb;
 	unsigned long ms_win_crb;
 
+	u8 cut_through;
 	u8 revision_id;
+	u8 pci_func;
+	u8 linkup;
+	u16 port_type;
 	u16 board_type;
-	struct netxen_board_info boardcfg;
-	u32 linkup;
-	/* Address of cmd ring in Phantom */
-	struct cmd_desc_type0 *cmd_desc_head;
-	dma_addr_t cmd_desc_phys_addr;
-	struct netxen_adapter *adapter;
-	int pci_func;
 };
 
-#define RCV_RING_LRO	RCV_DESC_LRO
-
 #define MINIMUM_ETHERNET_FRAME_SIZE	64	/* With FCS */
 #define ETHERNET_FCS_SIZE		4
 
 struct netxen_adapter_stats {
-	u64  rcvdbadskb;
 	u64  xmitcalled;
-	u64  xmitedframes;
 	u64  xmitfinished;
-	u64  badskblen;
-	u64  nocmddescriptor;
-	u64  polled;
 	u64  rxdropped;
 	u64  txdropped;
 	u64  csummed;
 	u64  no_rcv;
 	u64  rxbytes;
 	u64  txbytes;
-	u64  ints;
 };
 
 /*
@@ -842,16 +728,49 @@ struct netxen_adapter_stats {
  * be one Rcv Descriptor for normal packets, one for jumbo and may be others.
  */
 struct nx_host_rds_ring {
-	u32 flags;
 	u32 producer;
-	dma_addr_t phys_addr;
-	u32 crb_rcv_producer;	/* reg offset */
-	struct rcv_desc *desc_head;	/* address of rx ring in Phantom */
-	u32 max_rx_desc_count;
+	u32 crb_rcv_producer;
+	u32 num_desc;
 	u32 dma_size;
 	u32 skb_size;
-	struct netxen_rx_buffer *rx_buf_arr;	/* rx buffers for receive   */
+	u32 flags;
+	struct rcv_desc *desc_head;
+	struct netxen_rx_buffer *rx_buf_arr;
 	struct list_head free_list;
+	spinlock_t lock;
+	dma_addr_t phys_addr;
+};
+
+struct nx_host_sds_ring {
+	u32 consumer;
+	u32 crb_sts_consumer;
+	u32 crb_intr_mask;
+	u32 num_desc;
+
+	struct status_desc *desc_head;
+	struct netxen_adapter *adapter;
+	struct net_device *napi_dev;
+	struct napi_struct napi;
+	struct list_head free_list[NUM_RCV_DESC_RINGS];
+
+	int irq;
+
+	dma_addr_t phys_addr;
+	char name[IFNAMSIZ+4];
+};
+
+struct nx_host_tx_ring {
+	u32 producer;
+	__le32 *hw_consumer;
+	u32 sw_consumer;
+	u32 crb_cmd_producer;
+	u32 crb_cmd_consumer;
+	u32 num_desc;
+
+	struct netxen_cmd_buffer *cmd_buf_arr;
+	struct cmd_desc_type0 *desc_head;
+	dma_addr_t phys_addr;
+	spinlock_t lock;
 };
 
 /*
@@ -865,11 +784,11 @@ struct netxen_recv_context {
 	u16 context_id;
 	u16 virt_port;
 
-	struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
-	u32 status_rx_consumer;
-	u32 crb_sts_consumer;	/* reg offset */
-	dma_addr_t rcv_status_desc_phys_addr;
-	struct status_desc *rcv_status_desc_head;
+	struct nx_host_rds_ring *rds_rings;
+	struct nx_host_sds_ring *sds_rings;
+
+	struct netxen_ring_ctx *hwctx;
+	dma_addr_t phys_addr;
 };
 
 /* New HW context creation */
@@ -1108,8 +1027,8 @@ typedef struct {
 #define NETXEN_MAC_DEL	2
 
 typedef struct nx_mac_list_s {
-	struct nx_mac_list_s *next;
-	uint8_t mac_addr[MAX_ADDR_LEN];
+	struct list_head list;
+	uint8_t mac_addr[ETH_ALEN+2];
 } nx_mac_list_t;
 
 /*
@@ -1151,31 +1070,118 @@ typedef struct {
 
 #define NX_MAC_EVENT		0x1
 
-enum {
-	NX_NIC_H2C_OPCODE_START = 0,
-	NX_NIC_H2C_OPCODE_CONFIG_RSS,
-	NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL,
-	NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE,
-	NX_NIC_H2C_OPCODE_CONFIG_LED,
-	NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS,
-	NX_NIC_H2C_OPCODE_CONFIG_L2_MAC,
-	NX_NIC_H2C_OPCODE_LRO_REQUEST,
-	NX_NIC_H2C_OPCODE_GET_SNMP_STATS,
-	NX_NIC_H2C_OPCODE_PROXY_START_REQUEST,
-	NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST,
-	NX_NIC_H2C_OPCODE_PROXY_SET_MTU,
-	NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE,
-	NX_H2P_OPCODE_GET_FINGER_PRINT_REQUEST,
-	NX_H2P_OPCODE_INSTALL_LICENSE_REQUEST,
-	NX_H2P_OPCODE_GET_LICENSE_CAPABILITY_REQUEST,
-	NX_NIC_H2C_OPCODE_GET_NET_STATS,
-	NX_NIC_H2C_OPCODE_LAST
-};
+/*
+ * Driver --> Firmware
+ */
+#define NX_NIC_H2C_OPCODE_START				0
+#define NX_NIC_H2C_OPCODE_CONFIG_RSS			1
+#define NX_NIC_H2C_OPCODE_CONFIG_RSS_TBL		2
+#define NX_NIC_H2C_OPCODE_CONFIG_INTR_COALESCE		3
+#define NX_NIC_H2C_OPCODE_CONFIG_LED			4
+#define NX_NIC_H2C_OPCODE_CONFIG_PROMISCUOUS		5
+#define NX_NIC_H2C_OPCODE_CONFIG_L2_MAC			6
+#define NX_NIC_H2C_OPCODE_LRO_REQUEST			7
+#define NX_NIC_H2C_OPCODE_GET_SNMP_STATS		8
+#define NX_NIC_H2C_OPCODE_PROXY_START_REQUEST		9
+#define NX_NIC_H2C_OPCODE_PROXY_STOP_REQUEST		10
+#define NX_NIC_H2C_OPCODE_PROXY_SET_MTU			11
+#define NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE	12
+#define NX_NIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST	13
+#define NX_NIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST	14
+#define NX_NIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST	15
+#define NX_NIC_H2C_OPCODE_GET_NET_STATS			16
+#define NX_NIC_H2C_OPCODE_PROXY_UPDATE_P2V		17
+#define NX_NIC_H2C_OPCODE_CONFIG_IPADDR			18
+#define NX_NIC_H2C_OPCODE_CONFIG_LOOPBACK		19
+#define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE		20
+#define NX_NIC_H2C_OPCODE_GET_LINKEVENT			21
+#define NX_NIC_C2C_OPCODE				22
+#define NX_NIC_H2C_OPCODE_LAST				23
+
+/*
+ * Firmware --> Driver
+ */
+
+#define NX_NIC_C2H_OPCODE_START				128
+#define NX_NIC_C2H_OPCODE_CONFIG_RSS_RESPONSE		129
+#define NX_NIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE	130
+#define NX_NIC_C2H_OPCODE_CONFIG_MAC_RESPONSE		131
+#define NX_NIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE	132
+#define NX_NIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE	133
+#define NX_NIC_C2H_OPCODE_LRO_DELETE_RESPONSE		134
+#define NX_NIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE	135
+#define NX_NIC_C2H_OPCODE_GET_SNMP_STATS		136
+#define NX_NIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY	137
+#define NX_NIC_C2H_OPCODE_INSTALL_LICENSE_REPLY		138
+#define NX_NIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139
+#define NX_NIC_C2H_OPCODE_GET_NET_STATS_RESPONSE	140
+#define NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE	141
+#define NX_NIC_C2H_OPCODE_LAST				142
 
 #define VPORT_MISS_MODE_DROP		0 /* drop all unmatched */
 #define VPORT_MISS_MODE_ACCEPT_ALL	1 /* accept all packets */
 #define VPORT_MISS_MODE_ACCEPT_MULTI	2 /* accept unmatched multicast */
 
+#define NX_FW_CAPABILITY_LINK_NOTIFICATION	(1 << 5)
+#define NX_FW_CAPABILITY_SWITCHING		(1 << 6)
+
+/* module types */
+#define LINKEVENT_MODULE_NOT_PRESENT			1
+#define LINKEVENT_MODULE_OPTICAL_UNKNOWN		2
+#define LINKEVENT_MODULE_OPTICAL_SRLR			3
+#define LINKEVENT_MODULE_OPTICAL_LRM			4
+#define LINKEVENT_MODULE_OPTICAL_SFP_1G			5
+#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE	6
+#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN	7
+#define LINKEVENT_MODULE_TWINAX				8
+
+#define LINKSPEED_10GBPS	10000
+#define LINKSPEED_1GBPS		1000
+#define LINKSPEED_100MBPS	100
+#define LINKSPEED_10MBPS	10
+
+#define LINKSPEED_ENCODED_10MBPS	0
+#define LINKSPEED_ENCODED_100MBPS	1
+#define LINKSPEED_ENCODED_1GBPS		2
+
+#define LINKEVENT_AUTONEG_DISABLED	0
+#define LINKEVENT_AUTONEG_ENABLED	1
+
+#define LINKEVENT_HALF_DUPLEX		0
+#define LINKEVENT_FULL_DUPLEX		1
+
+#define LINKEVENT_LINKSPEED_MBPS	0
+#define LINKEVENT_LINKSPEED_ENCODED	1
+
+/* firmware response header:
+ *	63:58 - message type
+ *	57:56 - owner
+ *	55:53 - desc count
+ *	52:48 - reserved
+ *	47:40 - completion id
+ *	39:32 - opcode
+ *	31:16 - error code
+ *	15:00 - reserved
+ */
+#define netxen_get_nic_msgtype(msg_hdr)	\
+	((msg_hdr >> 58) & 0x3F)
+#define netxen_get_nic_msg_compid(msg_hdr)	\
+	((msg_hdr >> 40) & 0xFF)
+#define netxen_get_nic_msg_opcode(msg_hdr)	\
+	((msg_hdr >> 32) & 0xFF)
+#define netxen_get_nic_msg_errcode(msg_hdr)	\
+	((msg_hdr >> 16) & 0xFFFF)
+
+typedef struct {
+	union {
+		struct {
+			u64 hdr;
+			u64 body[7];
+		};
+		u64 words[8];
+	};
+} nx_fw_msg_t;
+
 typedef struct {
 	__le64 qhdr;
 	__le64 req_hdr;
@@ -1195,13 +1201,13 @@ typedef struct {
 #define NETXEN_IS_MSI_FAMILY(adapter) \
 	((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
 
-#define MSIX_ENTRIES_PER_ADAPTER	1
+#define MSIX_ENTRIES_PER_ADAPTER	NUM_STS_DESC_RINGS
 #define NETXEN_MSIX_TBL_SPACE		8192
 #define NETXEN_PCI_REG_MSIX_TBL		0x44
 
 #define NETXEN_DB_MAPSIZE_BYTES    	0x1000
 
-#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_NETDEV_WEIGHT 128
 #define NETXEN_ADAPTER_UP_MAGIC 777
 #define NETXEN_NIC_PEG_TUNE 0
 
@@ -1212,105 +1218,99 @@ struct netxen_dummy_dma {
 
 struct netxen_adapter {
 	struct netxen_hardware_context ahw;
-	struct napi_struct napi;
 
 	struct net_device *netdev;
 	struct pci_dev *pdev;
-	int pci_using_dac;
-	struct net_device_stats net_stats;
-	int mtu;
-	int portnum;
-	u8 physical_port;
-	u16 tx_context_id;
-
-	uint8_t		mc_enabled;
-	uint8_t		max_mc_count;
-	nx_mac_list_t	*mac_list;
-
-	struct netxen_legacy_intr_set legacy_intr;
-	u32	crb_intr_mask;
-
-	struct work_struct watchdog_task;
-	struct timer_list watchdog_timer;
-	struct work_struct tx_timeout_task;
+	struct list_head mac_list;
 
 	u32 curr_window;
 	u32 crb_win;
 	rwlock_t adapter_lock;
 
-	uint64_t dma_mask;
-
-	u32 cmd_producer;
-	u32 *cmd_consumer;
-	u32 last_cmd_consumer;
-	u32 crb_addr_cmd_producer;
-	u32 crb_addr_cmd_consumer;
-
-	u32 max_tx_desc_count;
-	u32 max_rx_desc_count;
-	u32 max_jumbo_rx_desc_count;
-	u32 max_lro_rx_desc_count;
-
-	int max_rds_rings;
-
-	u32 flags;
-	u32 irq;
-	int driver_mismatch;
-	u32 temp;
+	spinlock_t tx_clean_lock;
 
-	u32 fw_major;
+	u16 num_txd;
+	u16 num_rxd;
+	u16 num_jumbo_rxd;
+	u16 num_lro_rxd;
 
+	u8 max_rds_rings;
+	u8 max_sds_rings;
+	u8 driver_mismatch;
 	u8 msix_supported;
-	u8 max_possible_rss_rings;
-	struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+	u8 rx_csum;
+	u8 pci_using_dac;
+	u8 portnum;
+	u8 physical_port;
 
-	struct netxen_adapter_stats stats;
+	u8 mc_enabled;
+	u8 max_mc_count;
+	u8 rss_supported;
+	u8 link_changed;
+	u32 resv3;
+
+	u8 has_link_events;
+	u8 fw_type;
+	u16 tx_context_id;
+	u16 mtu;
+	u16 is_up;
 
 	u16 link_speed;
 	u16 link_duplex;
-	u16 state;
 	u16 link_autoneg;
-	int rx_csum;
-	int status;
+	u16 module_type;
+
+	u32 capabilities;
+	u32 flags;
+	u32 irq;
+	u32 temp;
 
-	struct netxen_cmd_buffer *cmd_buf_arr;	/* Command buffers for xmit */
+	u32 msi_tgt_status;
+	u32 resv4;
 
-	/*
-	 * Receive instances. These can be either one per port,
-	 * or one per peg, etc.
-	 */
-	struct netxen_recv_context recv_ctx[MAX_RCV_CTX];
+	struct netxen_adapter_stats stats;
 
-	int is_up;
-	struct netxen_dummy_dma dummy_dma;
-	nx_nic_intr_coalesce_t coal;
+	struct netxen_recv_context recv_ctx;
+	struct nx_host_tx_ring *tx_ring;
 
-	/* Context interface shared between card and host */
-	struct netxen_ring_ctx *ctx_desc;
-	dma_addr_t ctx_desc_phys_addr;
-	int intr_scheme;
-	int msi_mode;
 	int (*enable_phy_interrupts) (struct netxen_adapter *);
 	int (*disable_phy_interrupts) (struct netxen_adapter *);
-	int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
+	int (*macaddr_set) (struct netxen_adapter *, u8 *);
 	int (*set_mtu) (struct netxen_adapter *, int);
 	int (*set_promisc) (struct netxen_adapter *, u32);
+	void (*set_multi) (struct net_device *);
 	int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
 	int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
 	int (*init_port) (struct netxen_adapter *, int);
 	int (*stop_port) (struct netxen_adapter *);
 
-	int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
-	int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+	u32 (*hw_read_wx)(struct netxen_adapter *, ulong);
+	int (*hw_write_wx)(struct netxen_adapter *, ulong, u32);
 	int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
 	int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
 	int (*pci_write_immediate)(struct netxen_adapter *, u64, u32);
 	u32 (*pci_read_immediate)(struct netxen_adapter *, u64);
-	void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
-	u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
 	unsigned long (*pci_set_window)(struct netxen_adapter *,
 			unsigned long long);
-};				/* netxen_adapter structure */
+
+	struct netxen_legacy_intr_set legacy_intr;
+
+	struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
+	struct netxen_dummy_dma dummy_dma;
+
+	struct work_struct watchdog_task;
+	struct timer_list watchdog_timer;
+	struct work_struct  tx_timeout_task;
+
+	struct net_device_stats net_stats;
+
+	nx_nic_intr_coalesce_t coal;
+
+	u32 fw_major;
+	u32 fw_version;
+	const struct firmware *fw;
+};
 
 /*
  * NetXen dma watchdog control structure
@@ -1348,51 +1348,10 @@ struct netxen_adapter {
 #define netxen_get_dma_watchdog_disabled(config_word) \
 	(((config_word) >> 1) & 0x1)
 
-/* Max number of xmit producer threads that can run simultaneously */
-#define	MAX_XMIT_PRODUCERS		16
-
-#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
-	((adapter)->ahw.pci_base0 + (off))
-#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \
-	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
-#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \
-	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
-
-static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter,
-					    unsigned long off)
-{
-	if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base0 + off);
-	} else if ((off < SECOND_PAGE_GROUP_END) &&
-		   (off >= SECOND_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START);
-	} else if ((off < THIRD_PAGE_GROUP_END) &&
-		   (off >= THIRD_PAGE_GROUP_START)) {
-		return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START);
-	}
-	return NULL;
-}
-
-static inline void __iomem *pci_base(struct netxen_adapter *adapter,
-				     unsigned long off)
-{
-	if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base0;
-	} else if ((off < SECOND_PAGE_GROUP_END) &&
-		   (off >= SECOND_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base1;
-	} else if ((off < THIRD_PAGE_GROUP_END) &&
-		   (off >= THIRD_PAGE_GROUP_START)) {
-		return adapter->ahw.pci_base2;
-	}
-	return NULL;
-}
-
 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter);
-int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
 			    __u32 * readval);
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
@@ -1401,19 +1360,22 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
 /* Functions available from netxen_nic_hw.c */
 int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
 int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
-void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
-void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
+
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr);
+
+#define NXRD32(adapter, off) \
+	(adapter->hw_read_wx(adapter, off))
+#define NXWR32(adapter, off, val) \
+	(adapter->hw_write_wx(adapter, off, val))
 
 int netxen_nic_get_board_info(struct netxen_adapter *adapter);
+void netxen_nic_get_firmware_info(struct netxen_adapter *adapter);
+int netxen_nic_wol_supported(struct netxen_adapter *adapter);
 
-int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off);
 int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+		ulong off, u32 data);
 int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
 int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
@@ -1429,16 +1391,13 @@ unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
 void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter,
 		u32 wndw);
 
-int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off);
 int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len);
+		ulong off, u32 data);
 int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
 int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
-				 unsigned long off, int data);
 int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
 		u64 off, u32 data);
 u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off);
@@ -1452,8 +1411,10 @@ unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
-int netxen_receive_peg_ready(struct netxen_adapter *adapter);
 int netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_need_fw_reset(struct netxen_adapter *adapter);
+void netxen_request_firmware(struct netxen_adapter *adapter);
+void netxen_release_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
 
 int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
@@ -1467,16 +1428,9 @@ int netxen_flash_erase_secondary(struct netxen_adapter *adapter);
 int netxen_flash_erase_primary(struct netxen_adapter *adapter);
 void netxen_halt_pegs(struct netxen_adapter *adapter);
 
-int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data);
 int netxen_rom_se(struct netxen_adapter *adapter, int addr);
-int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
 
 /* Functions from netxen_nic_isr.c */
-int netxen_nic_link_ok(struct netxen_adapter *adapter);
-void netxen_nic_isr_other(struct netxen_adapter *adapter);
-void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link);
-void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable);
-
 int netxen_alloc_sw_resources(struct netxen_adapter *adapter);
 void netxen_free_sw_resources(struct netxen_adapter *adapter);
 
@@ -1489,15 +1443,18 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter);
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
 int netxen_init_firmware(struct netxen_adapter *adapter);
 void netxen_nic_clear_stats(struct netxen_adapter *adapter);
-void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
-			    u32 ringid);
+void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
+		struct nx_host_rds_ring *rds_ring);
 int netxen_process_cmd_ring(struct netxen_adapter *adapter);
-u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
+int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max);
 void netxen_p2_nic_set_multi(struct net_device *netdev);
 void netxen_p3_nic_set_multi(struct net_device *netdev);
 void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
 int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
 int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
+int netxen_config_rss(struct netxen_adapter *adapter, int enable);
+int netxen_linkevent_request(struct netxen_adapter *adapter, int enable);
+void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);
 
 int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
@@ -1506,7 +1463,7 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p);
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 
 void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
-		uint32_t crb_producer);
+		struct nx_host_tx_ring *tx_ring);
 
 /*
  * NetXen Board information
@@ -1514,7 +1471,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
 
 #define NETXEN_MAX_SHORT_NAME 32
 struct netxen_brdinfo {
-	netxen_brdtype_t brdtype;	/* type of board */
+	int brdtype;	/* type of board */
 	long ports;		/* max no of physical ports */
 	char short_name[NETXEN_MAX_SHORT_NAME];
 };
@@ -1564,17 +1521,15 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
 	u32 ctrl;
 
 	/* check if already inactive */
-	if (adapter->hw_read_wx(adapter,
-	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
 		return 1;
 
 	/* Send the disable request */
 	netxen_set_dma_watchdog_disable_req(ctrl);
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+	NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
 
 	return 0;
 }
@@ -1584,9 +1539,8 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
 {
 	u32 ctrl;
 
-	if (adapter->hw_read_wx(adapter,
-	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	return (netxen_get_dma_watchdog_enabled(ctrl) == 0);
 }
@@ -1596,9 +1550,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
 {
 	u32 ctrl;
 
-	if (adapter->hw_read_wx(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
-		printk(KERN_ERR "failed to read dma watchdog status\n");
+	ctrl = adapter->hw_read_wx(adapter,
+			NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL));
 
 	if (netxen_get_dma_watchdog_enabled(ctrl))
 		return 1;
@@ -1606,14 +1559,20 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
 	/* send the wakeup request */
 	netxen_set_dma_watchdog_enable_req(ctrl);
 
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+	NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
 
 	return 0;
 }
 
 
-int netxen_is_flash_supported(struct netxen_adapter *adapter);
+static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
+{
+	smp_mb();
+	return find_diff_among(tx_ring->producer,
+			tx_ring->sw_consumer, tx_ring->num_desc);
+
+}
+
 int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
 int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
 extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_compat.h b/drivers/net/netxen/netxen_nic_compat.h
new file mode 100644
index 0000000..3ea0ccf
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_compat.h
@@ -0,0 +1,8 @@
+#ifndef _NETXEN_NIC_COMPAT_H
+#define _NETXEN_NIC_COMPAT_H
+
+#ifndef list_splice_tail_init
+#define list_splice_tail_init list_splice_init
+#endif
+
+#endif
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 746bdb4..9f8ae47 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2008 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,9 +22,9 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
@@ -41,8 +41,7 @@ netxen_api_lock(struct netxen_adapter *adapter)
 
 	for (;;) {
 		/* Acquire PCIE HW semaphore5 */
-		netxen_nic_read_w0(adapter,
-			NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_LOCK));
 
 		if (done == 1)
 			break;
@@ -56,7 +55,7 @@ netxen_api_lock(struct netxen_adapter *adapter)
 	}
 
 #if 0
-	netxen_nic_write_w1(adapter,
+	NXWR32(adapter,
 		NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
 #endif
 	return 0;
@@ -65,11 +64,8 @@ netxen_api_lock(struct netxen_adapter *adapter)
 static int
 netxen_api_unlock(struct netxen_adapter *adapter)
 {
-	u32 val;
-
 	/* Release PCIE HW semaphore5 */
-	netxen_nic_read_w0(adapter,
-		NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK));
 	return 0;
 }
 
@@ -86,7 +82,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter)
 		if (++timeout > NX_OS_CRB_RETRY_COUNT)
 			return NX_CDRP_RSP_TIMEOUT;
 
-		netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp);
+		rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET);
 	} while (!NX_CDRP_IS_RSP(rsp));
 
 	return rsp;
@@ -106,16 +102,15 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
 	if (netxen_api_lock(adapter))
 		return NX_RCODE_TIMEOUT;
 
-	netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature);
+	NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);
 
-	netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1);
+	NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1);
 
-	netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2);
+	NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2);
 
-	netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3);
+	NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3);
 
-	netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
-			NX_CDRP_FORM_CMD(cmd));
+	NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd));
 
 	rsp = netxen_poll_rsp(adapter);
 
@@ -125,7 +120,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
 
 		rcode = NX_RCODE_TIMEOUT;
 	} else if (rsp == NX_CDRP_RSP_FAIL) {
-		netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+		rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
 
 		printk(KERN_ERR "%s: failed card response code:0x%x\n",
 				netxen_nic_driver_name, rcode);
@@ -141,7 +136,7 @@ int
 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
 {
 	u32 rcode = NX_RCODE_SUCCESS;
-	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
 	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
 		rcode = netxen_issue_cmd(adapter,
@@ -169,6 +164,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 	nx_cardrsp_rds_ring_t *prsp_rds;
 	nx_cardrsp_sds_ring_t *prsp_sds;
 	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_sds_ring *sds_ring;
 
 	dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
 	u64 phys_addr;
@@ -179,11 +175,10 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 
 	int err;
 
-	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
-	/* only one sds ring for now */
 	nrds_rings = adapter->max_rds_rings;
-	nsds_rings = 1;
+	nsds_rings = adapter->max_sds_rings;
 
 	rq_size =
 		SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
@@ -231,7 +226,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 		rds_ring = &recv_ctx->rds_rings[i];
 
 		prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
-		prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count);
+		prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
 		prq_rds[i].ring_kind = cpu_to_le32(i);
 		prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
 	}
@@ -239,11 +234,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 	prq_sds = (nx_hostrq_sds_ring_t *)(prq->data +
 			le32_to_cpu(prq->sds_ring_offset));
 
-	prq_sds[0].host_phys_addr =
-		cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
-	prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
-	/* only one msix vector for now */
-	prq_sds[0].msi_index = cpu_to_le16(0);
+	for (i = 0; i < nsds_rings; i++) {
+
+		sds_ring = &recv_ctx->sds_rings[i];
+
+		prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
+		prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
+		prq_sds[i].msi_index = cpu_to_le16(i);
+	}
 
 	phys_addr = hostrq_phys_addr;
 	err = netxen_issue_cmd(adapter,
@@ -272,11 +270,16 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 
 	prsp_sds = ((nx_cardrsp_sds_ring_t *)
 			&prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
-	reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
-	recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
 
-	reg = le32_to_cpu(prsp_sds[0].interrupt_crb);
-	adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+	for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) {
+		sds_ring = &recv_ctx->sds_rings[i];
+
+		reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
+		sds_ring->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
+
+		reg = le32_to_cpu(prsp_sds[i].interrupt_crb);
+		sds_ring->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+	}
 
 	recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
 	recv_ctx->context_id = le16_to_cpu(prsp->context_id);
@@ -292,7 +295,7 @@ out_free_rq:
 static void
 nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
 {
-	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
 	if (netxen_issue_cmd(adapter,
 			adapter->ahw.pci_func,
@@ -320,6 +323,8 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
 	int	err = 0;
 	u64	offset, phys_addr;
 	dma_addr_t	rq_phys_addr, rsp_phys_addr;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
 	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
 	rq_addr = pci_alloc_consistent(adapter->pdev,
@@ -354,15 +359,13 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
 
 	prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
 
-	offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+	offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx);
 	prq->cmd_cons_dma_addr = cpu_to_le64(offset);
 
 	prq_cds = &prq->cds_ring;
 
-	prq_cds->host_phys_addr =
-		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
-
-	prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count);
+	prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr);
+	prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
 
 	phys_addr = rq_phys_addr;
 	err = netxen_issue_cmd(adapter,
@@ -375,8 +378,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
 
 	if (err == NX_RCODE_SUCCESS) {
 		temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
-		adapter->crb_addr_cmd_producer =
-			NETXEN_NIC_REG(temp - 0x200);
+		tx_ring->crb_cmd_producer = NETXEN_NIC_REG(temp - 0x200);
 #if 0
 		adapter->tx_state =
 			le32_to_cpu(prsp->host_ctx_state);
@@ -440,7 +442,19 @@ static struct netxen_recv_crb recv_crb_registers[] = {
 			NETXEN_NIC_REG(0x120)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x138),
+		{
+			NETXEN_NIC_REG(0x138),
+			NETXEN_NIC_REG_2(0x000),
+			NETXEN_NIC_REG_2(0x004),
+			NETXEN_NIC_REG_2(0x008),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_0,
+			NETXEN_NIC_REG_2(0x044),
+			NETXEN_NIC_REG_2(0x048),
+			NETXEN_NIC_REG_2(0x04c),
+		},
 	},
 	/* Instance 1 */
 	{
@@ -453,7 +467,19 @@ static struct netxen_recv_crb recv_crb_registers[] = {
 			NETXEN_NIC_REG(0x164)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x17c),
+		{
+			NETXEN_NIC_REG(0x17c),
+			NETXEN_NIC_REG_2(0x020),
+			NETXEN_NIC_REG_2(0x024),
+			NETXEN_NIC_REG_2(0x028),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_1,
+			NETXEN_NIC_REG_2(0x064),
+			NETXEN_NIC_REG_2(0x068),
+			NETXEN_NIC_REG_2(0x06c),
+		},
 	},
 	/* Instance 2 */
 	{
@@ -466,7 +492,19 @@ static struct netxen_recv_crb recv_crb_registers[] = {
 			NETXEN_NIC_REG(0x208)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x220),
+		{
+			NETXEN_NIC_REG(0x220),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_2,
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
 	},
 	/* Instance 3 */
 	{
@@ -479,7 +517,19 @@ static struct netxen_recv_crb recv_crb_registers[] = {
 			NETXEN_NIC_REG(0x24c)
 		},
 		/* crb_sts_consumer: */
-		NETXEN_NIC_REG(0x264),
+		{
+			NETXEN_NIC_REG(0x264),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
+		/* sw_int_mask */
+		{
+			CRB_SW_INT_MASK_3,
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+			NETXEN_NIC_REG_2(0x03c),
+		},
 	},
 };
 
@@ -488,139 +538,144 @@ netxen_init_old_ctx(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
-	int ctx, ring;
-	int func_id = adapter->portnum;
+	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
+	int ring;
+	int port = adapter->portnum;
+	struct netxen_ring_ctx *hwctx;
+	u32 signature;
 
-	adapter->ctx_desc->cmd_ring_addr =
-		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
-	adapter->ctx_desc->cmd_ring_size =
-		cpu_to_le32(adapter->max_tx_desc_count);
+	tx_ring = adapter->tx_ring;
+	recv_ctx = &adapter->recv_ctx;
+	hwctx = recv_ctx->hwctx;
 
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		recv_ctx = &adapter->recv_ctx[ctx];
+	hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr);
+	hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc);
 
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			rds_ring = &recv_ctx->rds_rings[ring];
 
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
-				cpu_to_le64(rds_ring->phys_addr);
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
-				cpu_to_le32(rds_ring->max_rx_desc_count);
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+
+		hwctx->rcv_rings[ring].addr =
+			cpu_to_le64(rds_ring->phys_addr);
+		hwctx->rcv_rings[ring].size =
+			cpu_to_le32(rds_ring->num_desc);
+	}
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		if (ring == 0) {
+			hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr);
+			hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc);
 		}
-		adapter->ctx_desc->sts_ring_addr =
-			cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
-		adapter->ctx_desc->sts_ring_size =
-			cpu_to_le32(adapter->max_rx_desc_count);
+		hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr);
+		hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc);
+		hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring);
 	}
+	hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings);
 
-	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
-			lower32(adapter->ctx_desc_phys_addr));
-	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
-			upper32(adapter->ctx_desc_phys_addr));
-	adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
-			NETXEN_CTX_SIGNATURE | func_id);
+	signature = (adapter->max_sds_rings > 1) ?
+		NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE;
+
+	NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port),
+			lower32(recv_ctx->phys_addr));
+	NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port),
+			upper32(recv_ctx->phys_addr));
+	NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
+			signature | port);
 	return 0;
 }
 
-static uint32_t sw_int_mask[4] = {
-	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
-	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
-
 int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 {
-	struct netxen_hardware_context *hw = &adapter->ahw;
-	u32 state = 0;
 	void *addr;
 	int err = 0;
-	int ctx, ring;
+	int ring;
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 
-	err = netxen_receive_peg_ready(adapter);
-	if (err) {
-		printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
-				state);
-		return err;
-	}
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	int port = adapter->portnum;
 
-	addr = pci_alloc_consistent(adapter->pdev,
-			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
-			&adapter->ctx_desc_phys_addr);
+	recv_ctx = &adapter->recv_ctx;
+	tx_ring = adapter->tx_ring;
 
+	addr = pci_alloc_consistent(pdev,
+			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
+			&recv_ctx->phys_addr);
 	if (addr == NULL) {
-		DPRINTK(ERR, "failed to allocate hw context\n");
+		dev_err(&pdev->dev, "failed to allocate hw context\n");
 		return -ENOMEM;
 	}
+
 	memset(addr, 0, sizeof(struct netxen_ring_ctx));
-	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
-	adapter->ctx_desc->cmd_consumer_offset =
-		cpu_to_le64(adapter->ctx_desc_phys_addr +
+	recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
+	recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
+	recv_ctx->hwctx->cmd_consumer_offset =
+		cpu_to_le64(recv_ctx->phys_addr +
 			sizeof(struct netxen_ring_ctx));
-	adapter->cmd_consumer =
+	tx_ring->hw_consumer =
 		(__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
 
 	/* cmd desc ring */
-	addr = pci_alloc_consistent(adapter->pdev,
-			sizeof(struct cmd_desc_type0) *
-			adapter->max_tx_desc_count,
-			&hw->cmd_desc_phys_addr);
+	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
+			&tx_ring->phys_addr);
 
 	if (addr == NULL) {
-		printk(KERN_ERR "%s failed to allocate tx desc ring\n",
-				netxen_nic_driver_name);
+		dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
+				netdev->name);
 		return -ENOMEM;
 	}
 
-	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			/* rx desc ring */
-			rds_ring = &recv_ctx->rds_rings[ring];
-			addr = pci_alloc_consistent(adapter->pdev,
-					RCV_DESC_RINGSIZE,
-					&rds_ring->phys_addr);
-			if (addr == NULL) {
-				printk(KERN_ERR "%s failed to allocate rx "
-					"desc ring[%d]\n",
-					netxen_nic_driver_name, ring);
-				err = -ENOMEM;
-				goto err_out_free;
-			}
-			rds_ring->desc_head = (struct rcv_desc *)addr;
-
-			if (adapter->fw_major < 4)
-				rds_ring->crb_rcv_producer =
-					recv_crb_registers[adapter->portnum].
-					crb_rcv_producer[ring];
-		}
+	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
 
-		/* status desc ring */
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
 		addr = pci_alloc_consistent(adapter->pdev,
-				STATUS_DESC_RINGSIZE,
-				&recv_ctx->rcv_status_desc_phys_addr);
+				RCV_DESC_RINGSIZE(rds_ring),
+				&rds_ring->phys_addr);
 		if (addr == NULL) {
-			printk(KERN_ERR "%s failed to allocate sts desc ring\n",
-					netxen_nic_driver_name);
+			dev_err(&pdev->dev,
+				"%s: failed to allocate rds ring [%d]\n",
+				netdev->name, ring);
 			err = -ENOMEM;
 			goto err_out_free;
 		}
-		recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+		rds_ring->desc_head = (struct rcv_desc *)addr;
 
 		if (adapter->fw_major < 4)
-			recv_ctx->crb_sts_consumer =
-				recv_crb_registers[adapter->portnum].
-				crb_sts_consumer;
+			rds_ring->crb_rcv_producer =
+				recv_crb_registers[port].crb_rcv_producer[ring];
+	}
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		addr = pci_alloc_consistent(adapter->pdev,
+				STATUS_DESC_RINGSIZE(sds_ring),
+				&sds_ring->phys_addr);
+		if (addr == NULL) {
+			dev_err(&pdev->dev,
+				"%s: failed to allocate sds ring [%d]\n",
+				netdev->name, ring);
+			err = -ENOMEM;
+			goto err_out_free;
+		}
+		sds_ring->desc_head = (struct status_desc *)addr;
+
+		sds_ring->crb_sts_consumer =
+			recv_crb_registers[port].crb_sts_consumer[ring];
+
+		sds_ring->crb_intr_mask =
+			recv_crb_registers[port].sw_int_mask[ring];
 	}
 
-	if (adapter->fw_major >= 4) {
-		adapter->intr_scheme = INTR_SCHEME_PERPORT;
-		adapter->msi_mode = MSI_MODE_MULTIFUNC;
 
+	if (adapter->fw_major >= 4) {
 		err = nx_fw_cmd_create_rx_ctx(adapter);
 		if (err)
 			goto err_out_free;
@@ -628,19 +683,9 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
 		if (err)
 			goto err_out_free;
 	} else {
-
-		adapter->intr_scheme = adapter->pci_read_normalize(adapter,
-				CRB_NIC_CAPABILITIES_FW);
-		adapter->msi_mode = adapter->pci_read_normalize(adapter,
-				CRB_NIC_MSI_MODE_FW);
-		adapter->crb_intr_mask = sw_int_mask[adapter->portnum];
-
 		err = netxen_init_old_ctx(adapter);
-		if (err) {
-			netxen_free_hw_resources(adapter);
-			return err;
-		}
-
+		if (err)
+			goto err_out_free;
 	}
 
 	return 0;
@@ -654,51 +699,65 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
-	int ctx, ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
+	int ring;
+
+	int port = adapter->portnum;
 
 	if (adapter->fw_major >= 4) {
-		nx_fw_cmd_destroy_tx_ctx(adapter);
 		nx_fw_cmd_destroy_rx_ctx(adapter);
+		nx_fw_cmd_destroy_tx_ctx(adapter);
+	} else {
+		netxen_api_lock(adapter);
+		NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
+				NETXEN_CTX_D3_RESET | port);
+		netxen_api_unlock(adapter);
 	}
 
-	if (adapter->ctx_desc != NULL) {
+	/* Allow dma queues to drain after context reset */
+	msleep(20);
+
+	recv_ctx = &adapter->recv_ctx;
+
+	if (recv_ctx->hwctx != NULL) {
 		pci_free_consistent(adapter->pdev,
 				sizeof(struct netxen_ring_ctx) +
 				sizeof(uint32_t),
-				adapter->ctx_desc,
-				adapter->ctx_desc_phys_addr);
-		adapter->ctx_desc = NULL;
+				recv_ctx->hwctx,
+				recv_ctx->phys_addr);
+		recv_ctx->hwctx = NULL;
 	}
 
-	if (adapter->ahw.cmd_desc_head != NULL) {
+	tx_ring = adapter->tx_ring;
+	if (tx_ring->desc_head != NULL) {
 		pci_free_consistent(adapter->pdev,
-				sizeof(struct cmd_desc_type0) *
-				adapter->max_tx_desc_count,
-				adapter->ahw.cmd_desc_head,
-				adapter->ahw.cmd_desc_phys_addr);
-		adapter->ahw.cmd_desc_head = NULL;
+				TX_DESC_RINGSIZE(tx_ring),
+				tx_ring->desc_head, tx_ring->phys_addr);
+		tx_ring->desc_head = NULL;
 	}
 
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			rds_ring = &recv_ctx->rds_rings[ring];
-
-			if (rds_ring->desc_head != NULL) {
-				pci_free_consistent(adapter->pdev,
-						RCV_DESC_RINGSIZE,
-						rds_ring->desc_head,
-						rds_ring->phys_addr);
-				rds_ring->desc_head = NULL;
-			}
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+
+		if (rds_ring->desc_head != NULL) {
+			pci_free_consistent(adapter->pdev,
+					RCV_DESC_RINGSIZE(rds_ring),
+					rds_ring->desc_head,
+					rds_ring->phys_addr);
+			rds_ring->desc_head = NULL;
 		}
+	}
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
 
-		if (recv_ctx->rcv_status_desc_head != NULL) {
+		if (sds_ring->desc_head != NULL) {
 			pci_free_consistent(adapter->pdev,
-					STATUS_DESC_RINGSIZE,
-					recv_ctx->rcv_status_desc_head,
-					recv_ctx->rcv_status_desc_phys_addr);
-			recv_ctx->rcv_status_desc_head = NULL;
+				STATUS_DESC_RINGSIZE(sds_ring),
+				sds_ring->desc_head,
+				sds_ring->phys_addr);
+			sds_ring->desc_head = NULL;
 		}
 	}
 }
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 1d75ef0..aa761dd 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,23 +22,18 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * ethtool support for netxen nic
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
 #include <linux/types.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
-#include <linux/version.h>
 
 #include "netxen_nic.h"
 #include "netxen_nic_hw.h"
@@ -57,13 +52,9 @@ struct netxen_nic_stats {
 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
 
 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
-	{"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)},
 	{"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
-	{"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)},
 	{"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
-	{"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
-	{"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
-	{"polled", NETXEN_NIC_STAT(stats.polled)},
+	{"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
 	{"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
 	{"csummed", NETXEN_NIC_STAT(stats.csummed)},
 	{"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
@@ -101,12 +92,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 	strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
 	strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
 	write_lock_irqsave(&adapter->adapter_lock, flags);
-	fw_major = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_MAJOR);
-	fw_minor = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_MINOR);
-	fw_build = adapter->pci_read_normalize(adapter,
-					NETXEN_FW_VERSION_SUB);
+	fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+	fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+	fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
 	write_unlock_irqrestore(&adapter->adapter_lock, flags);
 	sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
 
@@ -121,10 +109,10 @@ static int
 netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
-	struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg;
+	int check_sfp_module = 0;
 
 	/* read which mode */
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		ecmd->supported = (SUPPORTED_10baseT_Half |
 				   SUPPORTED_10baseT_Full |
 				   SUPPORTED_100baseT_Half |
@@ -143,10 +131,10 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 		ecmd->duplex = adapter->link_duplex;
 		ecmd->autoneg = adapter->link_autoneg;
 
-	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		u32 val;
 
-		adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4);
+		val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 		if (val == NETXEN_PORT_MODE_802_3_AP) {
 			ecmd->supported = SUPPORTED_1000baseT_Full;
 			ecmd->advertising = ADVERTISED_1000baseT_Full;
@@ -155,13 +143,19 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 			ecmd->advertising = ADVERTISED_10000baseT_Full;
 		}
 
+		if (netif_running(dev) && adapter->has_link_events) {
+			ecmd->speed = adapter->link_speed;
+			ecmd->autoneg = adapter->link_autoneg;
+			ecmd->duplex = adapter->link_duplex;
+			goto skip;
+		}
+
 		ecmd->port = PORT_TP;
 
 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 			u16 pcifn = adapter->ahw.pci_func;
 
-			adapter->hw_read_wx(adapter,
-				P3_LINK_SPEED_REG(pcifn), &val, 4);
+			val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
 			ecmd->speed = P3_LINK_SPEED_MHZ *
 					P3_LINK_SPEED_VAL(pcifn, val);
 		} else
@@ -172,10 +166,11 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 	} else
 		return -EIO;
 
+skip:
 	ecmd->phy_address = adapter->physical_port;
 	ecmd->transceiver = XCVR_EXTERNAL;
 
-	switch ((netxen_brdtype_t) boardinfo->board_type) {
+	switch (adapter->ahw.board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
 	case NETXEN_BRDTYPE_P2_SB31_2G:
 	case NETXEN_BRDTYPE_P3_REF_QG:
@@ -191,7 +186,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 		ecmd->supported |= SUPPORTED_TP;
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->port = PORT_TP;
-		ecmd->autoneg = (boardinfo->board_type ==
+		ecmd->autoneg = (adapter->ahw.board_type ==
 				 NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
 		    (AUTONEG_DISABLE) : (adapter->link_autoneg);
 		break;
@@ -202,7 +197,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 	case NETXEN_BRDTYPE_P3_HMEZ:
 		ecmd->supported |= SUPPORTED_MII;
 		ecmd->advertising |= ADVERTISED_MII;
-		ecmd->port = PORT_FIBRE;
+		ecmd->port = PORT_MII;
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
 	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
@@ -210,6 +205,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 	case NETXEN_BRDTYPE_P3_10G_SFP_QT:
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->supported |= SUPPORTED_TP;
+		check_sfp_module = netif_running(dev) &&
+			adapter->has_link_events;
 	case NETXEN_BRDTYPE_P2_SB31_10G:
 	case NETXEN_BRDTYPE_P3_10G_XFP:
 		ecmd->supported |= SUPPORTED_FIBRE;
@@ -218,12 +215,14 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
 	case NETXEN_BRDTYPE_P3_10G_TP:
-		if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+		if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 			ecmd->autoneg = AUTONEG_DISABLE;
 			ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
 			ecmd->advertising |=
 				(ADVERTISED_FIBRE | ADVERTISED_TP);
 			ecmd->port = PORT_FIBRE;
+			check_sfp_module = netif_running(dev) &&
+				adapter->has_link_events;
 		} else {
 			ecmd->autoneg = AUTONEG_ENABLE;
 			ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
@@ -234,10 +233,28 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 		break;
 	default:
 		printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
-		       (netxen_brdtype_t) boardinfo->board_type);
+				adapter->ahw.board_type);
 		return -EIO;
 	}
 
+	if (check_sfp_module) {
+		switch (adapter->module_type) {
+		case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
+		case LINKEVENT_MODULE_OPTICAL_SRLR:
+		case LINKEVENT_MODULE_OPTICAL_LRM:
+		case LINKEVENT_MODULE_OPTICAL_SFP_1G:
+			ecmd->port = PORT_FIBRE;
+			break;
+		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
+		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
+		case LINKEVENT_MODULE_TWINAX:
+			ecmd->port = PORT_TP;
+			break;
+		default:
+			ecmd->port = -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -248,7 +265,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 	__u32 status;
 
 	/* read which mode */
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		/* autonegotiation */
 		if (adapter->phy_write
 		    && adapter->phy_write(adapter,
@@ -405,12 +422,11 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 	    (adapter->pdev)->device;
 	/* which mode */
-	adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
+	regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE);
 	mode = regs_buff[0];
 
 	/* Common registers to all the modes */
-	adapter->hw_read_wx(adapter,
-			NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
+	regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER);
 	/* GB/XGB Mode */
 	mode = (mode / 2) - 1;
 	window = 0;
@@ -421,9 +437,8 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 				window = adapter->physical_port *
 					NETXEN_NIC_PORT_WINDOW;
 
-			adapter->hw_read_wx(adapter,
-				niu_registers[mode].reg[i - 3] + window,
-				&regs_buff[i], 4);
+			regs_buff[i] = NXRD32(adapter,
+				niu_registers[mode].reg[i - 3] + window);
 		}
 
 	}
@@ -436,7 +451,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
 	int val;
 
 	/* read which mode */
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		if (adapter->phy_read
 		    && adapter->phy_read(adapter,
 					 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
@@ -446,8 +461,8 @@ static u32 netxen_nic_test_link(struct net_device *dev)
 			val = netxen_get_phy_link(status);
 			return !val;
 		}
-	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+		val = NXRD32(adapter, CRB_XG_STATE);
 		return (val == XG_LINK_UP) ? 0 : 1;
 	}
 	return -EIO;
@@ -476,95 +491,20 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 	return 0;
 }
 
-#if 0
-static int
-netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-			u8 * bytes)
-{
-	struct netxen_adapter *adapter = netdev_priv(dev);
-	int offset = eeprom->offset;
-	static int flash_start;
-	static int ready_to_flash;
-	int ret;
-
-	if (flash_start == 0) {
-		netxen_halt_pegs(adapter);
-		ret = netxen_flash_unlock(adapter);
-		if (ret < 0) {
-			printk(KERN_ERR "%s: Flash unlock failed.\n",
-				netxen_nic_driver_name);
-			return ret;
-		}
-		printk(KERN_INFO "%s: flash unlocked. \n",
-			netxen_nic_driver_name);
-		ret = netxen_flash_erase_secondary(adapter);
-		if (ret != FLASH_SUCCESS) {
-			printk(KERN_ERR "%s: Flash erase failed.\n",
-				netxen_nic_driver_name);
-			return ret;
-		}
-		printk(KERN_INFO "%s: secondary flash erased successfully.\n",
-			netxen_nic_driver_name);
-		flash_start = 1;
-		return 0;
-	}
-
-	if (offset == NETXEN_BOOTLD_START) {
-		ret = netxen_flash_erase_primary(adapter);
-		if (ret != FLASH_SUCCESS) {
-			printk(KERN_ERR "%s: Flash erase failed.\n",
-				netxen_nic_driver_name);
-			return ret;
-		}
-
-		ret = netxen_rom_se(adapter, NETXEN_USER_START);
-		if (ret != FLASH_SUCCESS)
-			return ret;
-		ret = netxen_rom_se(adapter, NETXEN_FIXED_START);
-		if (ret != FLASH_SUCCESS)
-			return ret;
-
-		printk(KERN_INFO "%s: primary flash erased successfully\n",
-			netxen_nic_driver_name);
-
-		ret = netxen_backup_crbinit(adapter);
-		if (ret != FLASH_SUCCESS) {
-			printk(KERN_ERR "%s: CRBinit backup failed.\n",
-				netxen_nic_driver_name);
-			return ret;
-		}
-		printk(KERN_INFO "%s: CRBinit backup done.\n",
-			netxen_nic_driver_name);
-		ready_to_flash = 1;
-	}
-
-	if (!ready_to_flash) {
-		printk(KERN_ERR "%s: Invalid write sequence, returning...\n",
-			netxen_nic_driver_name);
-		return -EINVAL;
-	}
-
-	return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
-}
-#endif /* 0 */
-
 static void
 netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
-	int i;
 
 	ring->rx_pending = 0;
 	ring->rx_jumbo_pending = 0;
-	for (i = 0; i < MAX_RCV_CTX; ++i) {
-		ring->rx_pending += adapter->recv_ctx[i].
-		    rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
-		ring->rx_jumbo_pending += adapter->recv_ctx[i].
-		    rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
-	}
-	ring->tx_pending = adapter->max_tx_desc_count;
+	ring->rx_pending += adapter->recv_ctx.
+		rds_rings[RCV_RING_NORMAL].num_desc;
+	ring->rx_jumbo_pending += adapter->recv_ctx.
+		rds_rings[RCV_RING_JUMBO].num_desc;
+	ring->tx_pending = adapter->num_txd;
 
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE)
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE)
 		ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
 	else
 		ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
@@ -582,14 +522,13 @@ netxen_nic_get_pauseparam(struct net_device *dev,
 	__u32 val;
 	int port = adapter->physical_port;
 
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 			return;
 		/* get flow control settings */
-		netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				&val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 		pause->rx_pause = netxen_gb_get_rx_flowctl(val);
-		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
 			case 0:
 				pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
@@ -605,18 +544,18 @@ netxen_nic_get_pauseparam(struct net_device *dev,
 				pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
 				break;
 		}
-	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 			return;
 		pause->rx_pause = 1;
-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 		if (port == 0)
 			pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
 		else
 			pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
 	} else {
 		printk(KERN_ERR"%s: Unknown board type: %x\n",
-				netxen_nic_driver_name, adapter->ahw.board_type);
+				netxen_nic_driver_name, adapter->ahw.port_type);
 	}
 }
 
@@ -628,22 +567,21 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 	__u32 val;
 	int port = adapter->physical_port;
 	/* read mode */
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
 		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
 			return -EIO;
 		/* set flow control */
-		netxen_nic_read_w0(adapter,
-					NETXEN_NIU_GB_MAC_CONFIG_0(port), &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
 
 		if (pause->rx_pause)
 			netxen_gb_rx_flowctl(val);
 		else
 			netxen_gb_unset_rx_flowctl(val);
 
-		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				val);
 		/* set autoneg */
-		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
 		switch (port) {
 			case 0:
 				if (pause->tx_pause)
@@ -671,11 +609,11 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 					netxen_gb_set_gb3_mask(val);
 				break;
 		}
-		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
-	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+		NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
+	} else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
 		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
 			return -EIO;
-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
+		val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
 		if (port == 0) {
 			if (pause->tx_pause)
 				netxen_xg_unset_xg0_mask(val);
@@ -687,11 +625,11 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 			else
 				netxen_xg_set_xg1_mask(val);
 		}
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
+		NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
 	} else {
 		printk(KERN_ERR "%s: Unknown board type: %x\n",
 				netxen_nic_driver_name,
-				adapter->ahw.board_type);
+				adapter->ahw.port_type);
 	}
 	return 0;
 }
@@ -701,14 +639,14 @@ static int netxen_nic_reg_test(struct net_device *dev)
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	u32 data_read, data_written;
 
-	netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read);
+	data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
 	if ((data_read & 0xffff) != PHAN_VENDOR_ID)
 	return 1;
 
 	data_written = (u32)0xa5a5a5a5;
 
-	netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
-	data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
+	NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
+	data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
 	if (data_written != data_read)
 		return 1;
 
@@ -811,6 +749,53 @@ static int netxen_nic_set_tso(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static void
+netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct netxen_adapter *adapter = netdev_priv(dev);
+	u32 wol_cfg = 0;
+
+	wol->supported = 0;
+	wol->wolopts = 0;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return;
+
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
+	if (wol_cfg & (1UL << adapter->portnum))
+		wol->supported |= WAKE_MAGIC;
+
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
+	if (wol_cfg & (1UL << adapter->portnum))
+		wol->wolopts |= WAKE_MAGIC;
+}
+
+static int
+netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct netxen_adapter *adapter = netdev_priv(dev);
+	u32 wol_cfg = 0;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return -EOPNOTSUPP;
+
+	if (wol->wolopts & ~WAKE_MAGIC)
+		return -EOPNOTSUPP;
+
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
+	if (!(wol_cfg & (1 << adapter->portnum)))
+		return -EOPNOTSUPP;
+
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
+	if (wol->wolopts & WAKE_MAGIC)
+		wol_cfg |= 1UL << adapter->portnum;
+	else
+		wol_cfg &= ~(1UL << adapter->portnum);
+	NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
+
+	return 0;
+}
+
 /*
  * Set the coalescing parameters. Currently only normal is supported.
  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
@@ -907,9 +892,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
 	.get_link = ethtool_op_get_link,
 	.get_eeprom_len = netxen_nic_get_eeprom_len,
 	.get_eeprom = netxen_nic_get_eeprom,
-#if 0
-	.set_eeprom = netxen_nic_set_eeprom,
-#endif
 	.get_ringparam = netxen_nic_get_ringparam,
 	.get_pauseparam = netxen_nic_get_pauseparam,
 	.set_pauseparam = netxen_nic_set_pauseparam,
@@ -919,6 +901,8 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
 	.set_sg = ethtool_op_set_sg,
 	.get_tso = netxen_nic_get_tso,
 	.set_tso = netxen_nic_set_tso,
+	.get_wol = netxen_nic_get_wol,
+	.set_wol = netxen_nic_set_wol,
 	.self_test_count = netxen_nic_diag_test_count,
 	.self_test = netxen_nic_diag_test,
 	.get_strings = netxen_nic_get_strings,
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 3467d45..8241036 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,26 +22,17 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
+ *
  */
 
 #ifndef __NETXEN_NIC_HDR_H_
 #define __NETXEN_NIC_HDR_H_
 
-#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
-
-#include <linux/spinlock.h>
-#include <asm/irq.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
 #include <linux/types.h>
-#include <asm/uaccess.h>
-#include <asm/string.h>		/* for memset */
 
 /*
  * The basic unit of access when reading/writing control registers.
@@ -364,12 +355,7 @@ enum {
 #define NETXEN_HW_CRB_HUB_AGT_ADR_LPC	\
 	((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR)
 
-/*
- * MAX_RCV_CTX : The number of receive contexts that are available on
- * the phantom.
- */
-#define MAX_RCV_CTX			1
-
+#define NETXEN_SRE_MISC			(NETXEN_CRB_SRE + 0x0002c)
 #define NETXEN_SRE_INT_STATUS		(NETXEN_CRB_SRE + 0x00034)
 #define NETXEN_SRE_PBI_ACTIVE_STATUS	(NETXEN_CRB_SRE + 0x01014)
 #define NETXEN_SRE_L1RE_CTL		(NETXEN_CRB_SRE + 0x03000)
@@ -860,9 +846,14 @@ enum {
 #define NETXEN_PORT_MODE_ADDR		(NETXEN_CAM_RAM(0x24))
 #define NETXEN_WOL_PORT_MODE		(NETXEN_CAM_RAM(0x198))
 
-#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL		(0x14)
+#define NETXEN_WOL_CONFIG_NV		(NETXEN_CAM_RAM(0x184))
+#define NETXEN_WOL_CONFIG		(NETXEN_CAM_RAM(0x188))
+
+#define NX_PEG_TUNE_MN_PRESENT		0x1
+#define NX_PEG_TUNE_CAPABILITY		(NETXEN_CAM_RAM(0x02c))
 
 #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL		(0x14)
+#define NETXEN_PEG_ALIVE_COUNTER	(NETXEN_CAM_RAM(0xb0))
 
 #define	ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
 #define ISR_LEGACY_INT_TRIGGERED(VAL)	(((VAL) & 0x300) == 0x200)
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index bace6ee..b588cd5 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,20 +22,18 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * Source file for NIC routines to access the Phantom hardware
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
 #include "netxen_nic.h"
 #include "netxen_nic_hw.h"
-#define DEFINE_GLOBAL_RECV_CRB
 #include "netxen_nic_phan_reg.h"
 
+#include <net/ip.h>
+
 #define MASK(n) ((1ULL<<(n))-1)
 #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
 #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
@@ -49,8 +47,49 @@
 #define CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
 #define CRB_INDIRECT_2M	(0x1e0000UL)
 
+#ifndef readq
+static inline u64 readq(void __iomem *addr)
+{
+	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
+}
+#endif
+
+#ifndef writeq
+static inline void writeq(u64 val, void __iomem *addr)
+{
+	writel(((u32) (val)), (addr));
+	writel(((u32) (val >> 32)), (addr + 4));
+}
+#endif
+
+#define ADDR_IN_RANGE(addr, low, high)	\
+	(((addr) < (high)) && ((addr) >= (low)))
+
+#define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
+	((adapter)->ahw.pci_base0 + (off))
+#define PCI_OFFSET_SECOND_RANGE(adapter, off)   \
+	((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START)
+#define PCI_OFFSET_THIRD_RANGE(adapter, off)    \
+	((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START)
+
+static void __iomem *pci_base_offset(struct netxen_adapter *adapter,
+					    unsigned long off)
+{
+	if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END))
+		return PCI_OFFSET_FIRST_RANGE(adapter, off);
+
+	if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END))
+		return PCI_OFFSET_SECOND_RANGE(adapter, off);
+
+	if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END))
+		return PCI_OFFSET_THIRD_RANGE(adapter, off);
+
+	return NULL;
+}
+
 #define CRB_WIN_LOCK_TIMEOUT 100000000
-static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+static crb_128M_2M_block_map_t
+crb_128M_2M_map[64] __cacheline_aligned_in_smp = {
     {{{0, 0,         0,         0} } },		/* 0: PCI */
     {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */
 	  {1, 0x0110000, 0x0120000, 0x130000},
@@ -280,39 +319,8 @@ static unsigned crb_hub_agt[64] =
 
 /*  PCI Windowing for DDR regions.  */
 
-#define ADDR_IN_RANGE(addr, low, high)	\
-	(((addr) <= (high)) && ((addr) >= (low)))
-
 #define NETXEN_WINDOW_ONE 	0x2000000 /*CRB Window: bit 25 of CRB address */
 
-#define NETXEN_NIC_ZERO_PAUSE_ADDR     0ULL
-#define NETXEN_NIC_UNIT_PAUSE_ADDR     0x200ULL
-#define NETXEN_NIC_EPG_PAUSE_ADDR1     0x2200010000c28001ULL
-#define NETXEN_NIC_EPG_PAUSE_ADDR2     0x0100088866554433ULL
-
-#define NETXEN_NIC_WINDOW_MARGIN 0x100000
-
-int netxen_nic_set_mac(struct net_device *netdev, void *p)
-{
-	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct sockaddr *addr = p;
-
-	if (netif_running(netdev))
-		return -EBUSY;
-
-	if (!is_valid_ether_addr(addr->sa_data))
-		return -EADDRNOTAVAIL;
-
-	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
-	/* For P3, MAC addr is not set in NIU */
-	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
-		if (adapter->macaddr_set)
-			adapter->macaddr_set(adapter, addr->sa_data);
-
-	return 0;
-}
-
 #define NETXEN_UNICAST_ADDR(port, index) \
 	(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
 #define NETXEN_MCAST_ADDR(port, index) \
@@ -332,22 +340,20 @@ netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
 	if (adapter->mc_enabled)
 		return 0;
 
-	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
 	val |= (1UL << (28+port));
-	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
 
 	/* add broadcast addr to filter */
 	val = 0xffffff;
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
 
 	/* add station addr to filter */
 	val = MAC_HI(addr);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
 	val = MAC_LO(addr);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 1)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val);
 
 	adapter->mc_enabled = 1;
 	return 0;
@@ -363,18 +369,17 @@ netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
 	if (!adapter->mc_enabled)
 		return 0;
 
-	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG);
 	val &= ~(1UL << (28+port));
-	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
 
 	val = MAC_HI(addr);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
 	val = MAC_LO(addr);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val);
 
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+	NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
 
 	adapter->mc_enabled = 0;
 	return 0;
@@ -390,10 +395,8 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
 	lo = MAC_LO(addr);
 	hi = MAC_HI(addr);
 
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_MCAST_ADDR(port, index), hi);
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_MCAST_ADDR(port, index)+4, lo);
+	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi);
+	NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo);
 
 	return 0;
 }
@@ -446,96 +449,59 @@ void netxen_p2_nic_set_multi(struct net_device *netdev)
 		netxen_nic_set_mcast_addr(adapter, index, null_addr);
 }
 
-static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
-		u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
-{
-	nx_mac_list_t *cur, *prev;
-
-	/* if in del_list, move it to adapter->mac_list */
-	for (cur = *del_list, prev = NULL; cur;) {
-		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
-			if (prev == NULL)
-				*del_list = cur->next;
-			else
-				prev->next = cur->next;
-			cur->next = adapter->mac_list;
-			adapter->mac_list = cur;
-			return 0;
-		}
-		prev = cur;
-		cur = cur->next;
-	}
-
-	/* make sure to add each mac address only once */
-	for (cur = adapter->mac_list; cur; cur = cur->next) {
-		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
-			return 0;
-	}
-	/* not in del_list, create new entry and add to add_list */
-	cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
-	if (cur == NULL) {
-		printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
-				"not work properly from now.\n", __func__);
-		return -1;
-	}
-
-	memcpy(cur->mac_addr, addr, ETH_ALEN);
-	cur->next = *add_list;
-	*add_list = cur;
-	return 0;
-}
-
 static int
 netxen_send_cmd_descs(struct netxen_adapter *adapter,
-		struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+		struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
 {
-	uint32_t i, producer;
+	u32 i, producer, consumer;
 	struct netxen_cmd_buffer *pbuf;
 	struct cmd_desc_type0 *cmd_desc;
-
-	if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
-		printk(KERN_WARNING "%s: Too many command descriptors in a "
-			      "request\n", __func__);
-		return -EINVAL;
-	}
+	struct nx_host_tx_ring *tx_ring;
 
 	i = 0;
 
-	producer = adapter->cmd_producer;
+	tx_ring = adapter->tx_ring;
+	spin_lock_bh(&tx_ring->lock);
+
+	producer = tx_ring->producer;
+	consumer = tx_ring->sw_consumer;
+
+	if (nr_desc >= netxen_tx_avail(tx_ring)) {
+		netif_stop_queue(adapter->netdev);
+		spin_unlock_bh(&tx_ring->lock);
+		return -EBUSY;
+	}
+
 	do {
 		cmd_desc = &cmd_desc_arr[i];
 
-		pbuf = &adapter->cmd_buf_arr[producer];
+		pbuf = &tx_ring->cmd_buf_arr[producer];
 		pbuf->skb = NULL;
 		pbuf->frag_count = 0;
 
-		/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
-		memcpy(&adapter->ahw.cmd_desc_head[producer],
+		memcpy(&tx_ring->desc_head[producer],
 			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
 
-		producer = get_next_index(producer,
-				adapter->max_tx_desc_count);
+		producer = get_next_index(producer, tx_ring->num_desc);
 		i++;
 
-	} while (i != nr_elements);
+	} while (i != nr_desc);
 
-	adapter->cmd_producer = producer;
+	tx_ring->producer = producer;
 
-	/* write producer index to start the xmit */
+	netxen_nic_update_cmd_producer(adapter, tx_ring);
 
-	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+	spin_unlock_bh(&tx_ring->lock);
 
 	return 0;
 }
 
-static int nx_p3_sre_macaddr_change(struct net_device *dev,
-		u8 *addr, unsigned op)
+static int
+nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op)
 {
-	struct netxen_adapter *adapter = netdev_priv(dev);
 	nx_nic_req_t req;
 	nx_mac_req_t *mac_req;
 	u64 word;
-	int rv;
 
 	memset(&req, 0, sizeof(nx_nic_req_t));
 	req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
@@ -547,28 +513,51 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev,
 	mac_req->op = op;
 	memcpy(mac_req->mac_addr, addr, 6);
 
-	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
-	if (rv != 0) {
-		printk(KERN_ERR "ERROR. Could not send mac update\n");
-		return rv;
+	return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+}
+
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+		u8 *addr, struct list_head *del_list)
+{
+	struct list_head *head;
+	nx_mac_list_t *cur;
+
+	/* look up if already exists */
+	list_for_each(head, del_list) {
+		cur = list_entry(head, nx_mac_list_t, list);
+
+		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+			list_move_tail(head, &adapter->mac_list);
+			return 0;
+		}
 	}
 
-	return 0;
+	cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC);
+	if (cur == NULL) {
+		printk(KERN_ERR "%s: failed to add mac address filter\n",
+				adapter->netdev->name);
+		return -ENOMEM;
+	}
+	memcpy(cur->mac_addr, addr, ETH_ALEN);
+	list_add_tail(&cur->list, &adapter->mac_list);
+	return nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_ADD);
 }
 
 void netxen_p3_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
 	struct dev_mc_list *mc_ptr;
 	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 	u32 mode = VPORT_MISS_MODE_DROP;
+	LIST_HEAD(del_list);
+	struct list_head *head;
+	nx_mac_list_t *cur;
 
-	del_list = adapter->mac_list;
-	adapter->mac_list = NULL;
+	list_splice_tail_init(&adapter->mac_list, &del_list);
 
-	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
-	nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &del_list);
+	nx_p3_nic_add_mac(adapter, bcast_addr, &del_list);
 
 	if (netdev->flags & IFF_PROMISC) {
 		mode = VPORT_MISS_MODE_ACCEPT_ALL;
@@ -584,25 +573,20 @@ void netxen_p3_nic_set_multi(struct net_device *netdev)
 	if (netdev->mc_count > 0) {
 		for (mc_ptr = netdev->mc_list; mc_ptr;
 		     mc_ptr = mc_ptr->next) {
-			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
-					  &add_list, &del_list);
+			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list);
 		}
 	}
 
 send_fw_cmd:
 	adapter->set_promisc(adapter, mode);
-	for (cur = del_list; cur;) {
-		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
-		next = cur->next;
+	head = &del_list;
+	while (!list_empty(head)) {
+		cur = list_entry(head->next, nx_mac_list_t, list);
+
+		nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_DEL);
+		list_del(&cur->list);
 		kfree(cur);
-		cur = next;
-	}
-	for (cur = add_list; cur;) {
-		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
-		next = cur->next;
-		cur->next = adapter->mac_list;
-		adapter->mac_list = cur;
-		cur = next;
 	}
 }
 
@@ -627,17 +611,25 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
 
 void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
 {
-	nx_mac_list_t *cur, *next;
-
-	cur = adapter->mac_list;
-
-	while (cur) {
-		next = cur->next;
+	nx_mac_list_t *cur;
+	struct list_head *head = &adapter->mac_list;
+
+	while (!list_empty(head)) {
+		cur = list_entry(head->next, nx_mac_list_t, list);
+		nx_p3_sre_macaddr_change(adapter,
+				cur->mac_addr, NETXEN_MAC_DEL);
+		list_del(&cur->list);
 		kfree(cur);
-		cur = next;
 	}
 }
 
+int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+	/* assuming caller has already copied new addr to netdev */
+	netxen_p3_nic_set_multi(adapter->netdev);
+	return 0;
+}
+
 #define	NETXEN_CONFIG_INTR_COALESCE	3
 
 /*
@@ -667,6 +659,75 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
 	return rv;
 }
 
+#define RSS_HASHTYPE_IP_TCP	0x3
+
+int netxen_config_rss(struct netxen_adapter *adapter, int enable)
+{
+	nx_nic_req_t req;
+	u64 word;
+	int i, rv;
+
+	u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
+			0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
+			0x255b0ec26d5a56daULL };
+
+
+	memset(&req, 0, sizeof(nx_nic_req_t));
+	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+	word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16);
+	req.req_hdr = cpu_to_le64(word);
+
+	/*
+	 * RSS request:
+	 * bits 3-0: hash_method
+	 *      5-4: hash_type_ipv4
+	 *	7-6: hash_type_ipv6
+	 *	  8: enable
+	 *        9: use indirection table
+	 *    47-10: reserved
+	 *    63-48: indirection table mask
+	 */
+	word =  ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
+		((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
+		((u64)(enable & 0x1) << 8) |
+		((0x7ULL) << 48);
+	req.words[0] = cpu_to_le64(word);
+	for (i = 0; i < 5; i++)
+		req.words[i+1] = cpu_to_le64(key[i]);
+
+
+	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0) {
+		printk(KERN_ERR "%s: could not configure RSS\n",
+				adapter->netdev->name);
+	}
+
+	return rv;
+}
+
+int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
+{
+	nx_nic_req_t req;
+	u64 word;
+	int rv;
+
+	memset(&req, 0, sizeof(nx_nic_req_t));
+	req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+	word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
+	req.req_hdr = cpu_to_le64(word);
+	req.words[0] = cpu_to_le64(enable | (enable << 8));
+
+	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0) {
+		printk(KERN_ERR "%s: could not configure link notification\n",
+				adapter->netdev->name);
+	}
+
+	return rv;
+}
+
 /*
  * netxen_nic_change_mtu - Change the Maximum Transfer Unit
  * @returns 0 on success, negative on failure
@@ -700,49 +761,26 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
 	return rc;
 }
 
-int netxen_is_flash_supported(struct netxen_adapter *adapter)
-{
-	const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
-	int addr, val01, val02, i, j;
-
-	/* if the flash size less than 4Mb, make huge war cry and die */
-	for (j = 1; j < 4; j++) {
-		addr = j * NETXEN_NIC_WINDOW_MARGIN;
-		for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) {
-			if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0
-			    && netxen_rom_fast_read(adapter, (addr + locs[i]),
-						    &val02) == 0) {
-				if (val01 == val02)
-					return -1;
-			} else
-				return -1;
-		}
-	}
-
-	return 0;
-}
-
 static int netxen_get_flash_block(struct netxen_adapter *adapter, int base,
-				  int size, u32 * buf)
+				  int size, __le32 * buf)
 {
-	int i, addr;
-	u32 *ptr32;
+	int i, v, addr;
+	__le32 *ptr32;
 
 	addr = base;
 	ptr32 = buf;
 	for (i = 0; i < size / sizeof(u32); i++) {
-		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1)
+		if (netxen_rom_fast_read(adapter, addr, &v) == -1)
 			return -1;
-		*ptr32 = cpu_to_le32(*ptr32);
+		*ptr32 = cpu_to_le32(v);
 		ptr32++;
 		addr += sizeof(u32);
 	}
 	if ((char *)buf + size > (char *)ptr32) {
-		u32 local;
-
-		if (netxen_rom_fast_read(adapter, addr, &local) == -1)
+		__le32 local;
+		if (netxen_rom_fast_read(adapter, addr, &v) == -1)
 			return -1;
-		local = cpu_to_le32(local);
+		local = cpu_to_le32(v);
 		memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32);
 	}
 
@@ -785,8 +823,8 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
 	crbaddr = CRB_MAC_BLOCK_START +
 		(4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
 
-	adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
-	adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
+	mac_lo = NXRD32(adapter, crbaddr);
+	mac_hi = NXRD32(adapter, crbaddr+4);
 
 	if (pci_func & 1)
 		*mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
@@ -804,8 +842,7 @@ static int crb_win_lock(struct netxen_adapter *adapter)
 
 	while (!done) {
 		/* acquire semaphore3 from PCI HW block */
-		adapter->hw_read_wx(adapter,
-				NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
@@ -813,8 +850,7 @@ static int crb_win_lock(struct netxen_adapter *adapter)
 		timeout++;
 		udelay(1);
 	}
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+	NXWR32(adapter, NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
 	return 0;
 }
 
@@ -822,8 +858,7 @@ static void crb_win_unlock(struct netxen_adapter *adapter)
 {
 	int val;
 
-	adapter->hw_read_wx(adapter,
-			NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+	val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK));
 }
 
 /*
@@ -880,17 +915,15 @@ netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
  * In: 'off' is offset from base in 128M pci map
  */
 static int
-netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
-		ulong *off, int len)
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off)
 {
-	unsigned long end = *off + len;
 	crb_128M_2M_sub_block_map_t *m;
 
 
 	if (*off >= NETXEN_CRB_MAX)
 		return -1;
 
-	if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+	if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) {
 		*off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
 			(ulong)adapter->ahw.pci_base0;
 		return 0;
@@ -900,14 +933,13 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
 		return -1;
 
 	*off -= NETXEN_PCI_CRBSPACE;
-	end = *off + len;
 
 	/*
 	 * Try direct map
 	 */
 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
 
-	if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
 		*off = *off + m->start_2M - m->start_128M +
 			(ulong)adapter->ahw.pci_base0;
 		return 0;
@@ -930,13 +962,12 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
 	u32 win_read;
 
 	adapter->crb_win = CRB_HI(*off);
-	writel(adapter->crb_win, (void *)(CRB_WINDOW_2M +
-		adapter->ahw.pci_base0));
+	writel(adapter->crb_win, (adapter->ahw.pci_base0 + CRB_WINDOW_2M));
 	/*
 	 * Read back value to make sure write has gone through before trying
 	 * to use it.
 	 */
-	win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0));
+	win_read = readl(adapter->ahw.pci_base0 + CRB_WINDOW_2M);
 	if (win_read != adapter->crb_win) {
 		printk(KERN_ERR "%s: Written crbwin (0x%x) != "
 				"Read crbwin (0x%x), off=0x%lx\n",
@@ -946,43 +977,8 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
 		(ulong)adapter->ahw.pci_base0;
 }
 
-int netxen_load_firmware(struct netxen_adapter *adapter)
-{
-	int i;
-	u32 data, size = 0;
-	u32 flashaddr = NETXEN_BOOTLD_START;
-
-	size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
-
-	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CAS_RST, 1);
-
-	for (i = 0; i < size; i++) {
-		if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
-			return -EIO;
-
-		adapter->pci_mem_write(adapter, flashaddr, &data, 4);
-		flashaddr += 4;
-	}
-	msleep(1);
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
-	else {
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_CAS_RST, 0);
-	}
-
-	return 0;
-}
-
 int
-netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
 {
 	void __iomem *addr;
 
@@ -993,48 +989,24 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
 		netxen_nic_pci_change_crbwindow_128M(adapter, 0);
 	}
 
-	DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
-		" data %llx len %d\n",
-		pci_base(adapter, off), off, addr,
-		*(unsigned long long *)data, len);
 	if (!addr) {
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 		return 1;
 	}
 
-	switch (len) {
-	case 1:
-		writeb(*(u8 *) data, addr);
-		break;
-	case 2:
-		writew(*(u16 *) data, addr);
-		break;
-	case 4:
-		writel(*(u32 *) data, addr);
-		break;
-	case 8:
-		writeq(*(u64 *) data, addr);
-		break;
-	default:
-		DPRINTK(INFO,
-			"writing data %lx to offset %llx, num words=%d\n",
-			*(unsigned long *)data, off, (len >> 3));
+	writel(data, addr);
 
-		netxen_nic_hw_block_write64((u64 __iomem *) data, addr,
-					    (len >> 3));
-		break;
-	}
 	if (!ADDR_IN_WINDOW1(off))
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 
 	return 0;
 }
 
-int
-netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+u32
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)
 {
 	void __iomem *addr;
+	u32 data;
 
 	if (ADDR_IN_WINDOW1(off)) {	/* Window 1 */
 		addr = NETXEN_CRB_NORMALIZE(adapter, off);
@@ -1043,46 +1015,26 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
 		netxen_nic_pci_change_crbwindow_128M(adapter, 0);
 	}
 
-	DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
-		pci_base(adapter, off), off, addr);
 	if (!addr) {
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 		return 1;
 	}
-	switch (len) {
-	case 1:
-		*(u8 *) data = readb(addr);
-		break;
-	case 2:
-		*(u16 *) data = readw(addr);
-		break;
-	case 4:
-		*(u32 *) data = readl(addr);
-		break;
-	case 8:
-		*(u64 *) data = readq(addr);
-		break;
-	default:
-		netxen_nic_hw_block_read64((u64 __iomem *) data, addr,
-					   (len >> 3));
-		break;
-	}
-	DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
+
+	data = readl(addr);
 
 	if (!ADDR_IN_WINDOW1(off))
 		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 
-	return 0;
+	return data;
 }
 
 int
-netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data)
 {
 	unsigned long flags = 0;
 	int rv;
 
-	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
 
 	if (rv == -1) {
 		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
@@ -1095,46 +1047,24 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
 		write_lock_irqsave(&adapter->adapter_lock, flags);
 		crb_win_lock(adapter);
 		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
-	}
-
-	DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n",
-			*(unsigned long *)data, off, len);
-
-	switch (len) {
-	case 1:
-		writeb(*(uint8_t *)data, (void *)off);
-		break;
-	case 2:
-		writew(*(uint16_t *)data, (void *)off);
-		break;
-	case 4:
-		writel(*(uint32_t *)data, (void *)off);
-		break;
-	case 8:
-		writeq(*(uint64_t *)data, (void *)off);
-		break;
-	default:
-		DPRINTK(1, INFO,
-			"writing data %lx to offset %llx, num words=%d\n",
-			*(unsigned long *)data, off, (len>>3));
-		break;
-	}
-	if (rv == 1) {
+		writel(data, (void __iomem *)off);
 		crb_win_unlock(adapter);
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
-	}
+	} else
+		writel(data, (void __iomem *)off);
+
 
 	return 0;
 }
 
-int
-netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
-		ulong off, void *data, int len)
+u32
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off)
 {
 	unsigned long flags = 0;
 	int rv;
+	u32 data;
 
-	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off);
 
 	if (rv == -1) {
 		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
@@ -1147,69 +1077,13 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
 		write_lock_irqsave(&adapter->adapter_lock, flags);
 		crb_win_lock(adapter);
 		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
-	}
-
-	DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len);
-
-	switch (len) {
-	case 1:
-		*(uint8_t *)data = readb((void *)off);
-		break;
-	case 2:
-		*(uint16_t *)data = readw((void *)off);
-		break;
-	case 4:
-		*(uint32_t *)data = readl((void *)off);
-		break;
-	case 8:
-		*(uint64_t *)data = readq((void *)off);
-		break;
-	default:
-		break;
-	}
-
-	DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data);
-
-	if (rv == 1) {
+		data = readl((void __iomem *)off);
 		crb_win_unlock(adapter);
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
-	}
+	} else
+		data = readl((void __iomem *)off);
 
-	return 0;
-}
-
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{
-	adapter->hw_write_wx(adapter, off, &val, 4);
-}
-
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{
-	int val;
-	adapter->hw_read_wx(adapter, off, &val, 4);
-	return val;
-}
-
-/* Change the window to 0, write and change back to window 1. */
-void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
-{
-	adapter->hw_write_wx(adapter, index, &value, 4);
-}
-
-/* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
-{
-	adapter->hw_read_wx(adapter, index, value, 4);
-}
-
-void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
-{
-	adapter->hw_write_wx(adapter, index, &value, 4);
-}
-
-void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
-{
-	adapter->hw_read_wx(adapter, index, value, 4);
+	return data;
 }
 
 /*
@@ -1312,17 +1186,6 @@ u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
 	return readl((void __iomem *)(pci_base_offset(adapter, off)));
 }
 
-void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
-		u64 off, u32 data)
-{
-	writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
-}
-
-u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
-{
-	return readl(NETXEN_CRB_NORMALIZE(adapter, off));
-}
-
 unsigned long
 netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 		unsigned long long addr)
@@ -1334,12 +1197,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 		/* DDR network side */
 		window = MN_WIN(addr);
 		adapter->ahw.ddr_mn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE);
 		if ((win_read << 17) != window) {
 			printk(KERN_INFO "Written MNwin (0x%x) != "
 				"Read MNwin (0x%x)\n", window, win_read);
@@ -1354,12 +1215,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 
 		window = OCM_WIN(addr);
 		adapter->ahw.ddr_mn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE);
 		if ((win_read >> 7) != window) {
 			printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
 					"Read OCMwin (0x%x)\n",
@@ -1372,12 +1231,10 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
 		/* QDR network side */
 		window = MS_WIN(addr);
 		adapter->ahw.qdr_sn_window = window;
-		adapter->hw_write_wx(adapter,
-				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
-				&window, 4);
-		adapter->hw_read_wx(adapter,
-				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
-				&win_read, 4);
+		NXWR32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+				window);
+		win_read = NXRD32(adapter,
+				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE);
 		if (win_read != window) {
 			printk(KERN_INFO "%s: Written MSwin (0x%x) != "
 					"Read MSwin (0x%x)\n",
@@ -1435,10 +1292,9 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
 			u64 off, void *data, int size)
 {
 	unsigned long flags;
-	void *addr;
+	void __iomem *addr, *mem_ptr = NULL;
 	int ret = 0;
 	u64 start;
-	uint8_t *mem_ptr = NULL;
 	unsigned long mem_base;
 	unsigned long mem_page;
 
@@ -1458,7 +1314,7 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
 		return -1;
 	}
 
-	addr = (void *)(pci_base_offset(adapter, start));
+	addr = pci_base_offset(adapter, start);
 	if (!addr) {
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
 		mem_base = pci_resource_start(adapter->pdev, 0);
@@ -1497,7 +1353,6 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
 		break;
 	}
 	write_unlock_irqrestore(&adapter->adapter_lock, flags);
-	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
 
 	if (mem_ptr)
 		iounmap(mem_ptr);
@@ -1509,10 +1364,9 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
 		void *data, int size)
 {
 	unsigned long flags;
-	void *addr;
+	void __iomem *addr, *mem_ptr = NULL;
 	int ret = 0;
 	u64 start;
-	uint8_t *mem_ptr = NULL;
 	unsigned long mem_base;
 	unsigned long mem_page;
 
@@ -1532,7 +1386,7 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
 		return -1;
 	}
 
-	addr = (void *)(pci_base_offset(adapter, start));
+	addr = pci_base_offset(adapter, start);
 	if (!addr) {
 		write_unlock_irqrestore(&adapter->adapter_lock, flags);
 		mem_base = pci_resource_start(adapter->pdev, 0);
@@ -1569,8 +1423,6 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
 		break;
 	}
 	write_unlock_irqrestore(&adapter->adapter_lock, flags);
-	DPRINTK(1, INFO, "writing data %llx to offset %llx\n",
-			*(unsigned long long *)data, start);
 	if (mem_ptr)
 		iounmap(mem_ptr);
 	return ret;
@@ -1582,10 +1434,11 @@ int
 netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size)
 {
-	unsigned long   flags, mem_crb;
+	unsigned long   flags;
 	int	     i, j, ret = 0, loop, sz[2], off0;
 	uint32_t      temp;
 	uint64_t      off8, tmpw, word[2] = {0, 0};
+	void __iomem *mem_crb;
 
 	/*
 	 * If not MN, go check for MS or invalid.
@@ -1599,7 +1452,7 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
 	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
 	sz[1] = size - sz[0];
 	loop = ((off0 + size - 1) >> 3) + 1;
-	mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+	mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
 
 	if ((size != 8) || (off0 != 0))  {
 		for (i = 0; i < loop; i++) {
@@ -1637,21 +1490,21 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
 
 	for (i = 0; i < loop; i++) {
 		writel((uint32_t)(off8 + (i << 3)),
-			(void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+			(mem_crb+MIU_TEST_AGT_ADDR_LO));
 		writel(0,
-			(void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+			(mem_crb+MIU_TEST_AGT_ADDR_HI));
 		writel(word[i] & 0xffffffff,
-			(void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+			(mem_crb+MIU_TEST_AGT_WRDATA_LO));
 		writel((word[i] >> 32) & 0xffffffff,
-			(void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+			(mem_crb+MIU_TEST_AGT_WRDATA_HI));
 		writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
-			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			(mem_crb+MIU_TEST_AGT_CTRL));
 		writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
-			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			(mem_crb+MIU_TEST_AGT_CTRL));
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
 			temp = readl(
-			     (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			     (mem_crb+MIU_TEST_AGT_CTRL));
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -1674,10 +1527,11 @@ int
 netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 		u64 off, void *data, int size)
 {
-	unsigned long   flags, mem_crb;
+	unsigned long   flags;
 	int	     i, j = 0, k, start, end, loop, sz[2], off0[2];
 	uint32_t      temp;
 	uint64_t      off8, val, word[2] = {0, 0};
+	void __iomem *mem_crb;
 
 
 	/*
@@ -1692,24 +1546,24 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 	sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
 	sz[1] = size - sz[0];
 	loop = ((off0[0] + size - 1) >> 3) + 1;
-	mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+	mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
 
 	write_lock_irqsave(&adapter->adapter_lock, flags);
 	netxen_nic_pci_change_crbwindow_128M(adapter, 0);
 
 	for (i = 0; i < loop; i++) {
 		writel((uint32_t)(off8 + (i << 3)),
-			(void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+			(mem_crb+MIU_TEST_AGT_ADDR_LO));
 		writel(0,
-			(void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+			(mem_crb+MIU_TEST_AGT_ADDR_HI));
 		writel(MIU_TA_CTL_ENABLE,
-			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			(mem_crb+MIU_TEST_AGT_CTRL));
 		writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
-			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			(mem_crb+MIU_TEST_AGT_CTRL));
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
 			temp = readl(
-			      (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			      (mem_crb+MIU_TEST_AGT_CTRL));
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -1725,7 +1579,7 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 		end   = (off0[i] + sz[i] - 1) >> 2;
 		for (k = start; k <= end; k++) {
 			word[i] |= ((uint64_t) readl(
-				    (void *)(mem_crb +
+				    (mem_crb +
 				    MIU_TEST_AGT_RDDATA(k))) << (32*k));
 		}
 	}
@@ -1757,7 +1611,6 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
 		*(uint64_t *)data = val;
 		break;
 	}
-	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
 	return 0;
 }
 
@@ -1827,27 +1680,20 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
 
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << 3);
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_LO, temp);
 		temp = 0;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_HI, temp);
 		temp = word[i] & 0xffffffff;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp);
 		temp = (word[i] >> 32) & 0xffffffff;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp);
 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp);
 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
-		adapter->hw_write_wx(adapter,
-				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp);
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			adapter->hw_read_wx(adapter,
-					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL);
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -1904,21 +1750,16 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 
 	for (i = 0; i < loop; i++) {
 		temp = off8 + (i << 3);
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
 		temp = 0;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
 		temp = MIU_TA_CTL_ENABLE;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp);
 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
-		adapter->hw_write_wx(adapter,
-				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+		NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp);
 
 		for (j = 0; j < MAX_CTL_CHECK; j++) {
-			adapter->hw_read_wx(adapter,
-					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL);
 			if ((temp & MIU_TA_CTL_BUSY) == 0)
 				break;
 		}
@@ -1933,8 +1774,8 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 		start = off0[i] >> 2;
 		end   = (off0[i] + sz[i] - 1) >> 2;
 		for (k = start; k <= end; k++) {
-			adapter->hw_read_wx(adapter,
-				mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+			temp = NXRD32(adapter,
+				mem_crb + MIU_TEST_AGT_RDDATA(k));
 			word[i] |= ((uint64_t)temp << (32 * k));
 		}
 	}
@@ -1968,7 +1809,6 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 		*(uint64_t *)data = val;
 		break;
 	}
-	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
 	return 0;
 }
 
@@ -1978,87 +1818,55 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
 int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
 		u64 off, u32 data)
 {
-	adapter->hw_write_wx(adapter, off, &data, 4);
+	NXWR32(adapter, off, data);
 
 	return 0;
 }
 
 u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
 {
-	u32 temp;
-	adapter->hw_read_wx(adapter, off, &temp, 4);
-	return temp;
+	return NXRD32(adapter, off);
 }
 
-void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
-		u64 off, u32 data)
+int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 {
-	adapter->hw_write_wx(adapter, off, &data, 4);
-}
+	int offset, board_type, magic, header_version;
+	struct pci_dev *pdev = adapter->pdev;
 
-u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
-{
-	u32 temp;
-	adapter->hw_read_wx(adapter, off, &temp, 4);
-	return temp;
-}
+	offset = NETXEN_BRDCFG_START +
+		offsetof(struct netxen_board_info, magic);
+	if (netxen_rom_fast_read(adapter, offset, &magic))
+		return -EIO;
 
-#if 0
-int
-netxen_nic_erase_pxe(struct netxen_adapter *adapter)
-{
-	if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) {
-		printk(KERN_ERR "%s: erase pxe failed\n",
-			netxen_nic_driver_name);
-		return -1;
-	}
-	return 0;
-}
-#endif
+	offset = NETXEN_BRDCFG_START +
+		offsetof(struct netxen_board_info, header_version);
+	if (netxen_rom_fast_read(adapter, offset, &header_version))
+		return -EIO;
 
-int netxen_nic_get_board_info(struct netxen_adapter *adapter)
-{
-	int rv = 0;
-	int addr = NETXEN_BRDCFG_START;
-	struct netxen_board_info *boardinfo;
-	int index;
-	u32 *ptr32;
-
-	boardinfo = &adapter->ahw.boardcfg;
-	ptr32 = (u32 *) boardinfo;
-
-	for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32);
-	     index++) {
-		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
-			return -EIO;
-		}
-		ptr32++;
-		addr += sizeof(u32);
-	}
-	if (boardinfo->magic != NETXEN_BDINFO_MAGIC) {
-		printk("%s: ERROR reading %s board config."
-		       " Read %x, expected %x\n", netxen_nic_driver_name,
-		       netxen_nic_driver_name,
-		       boardinfo->magic, NETXEN_BDINFO_MAGIC);
-		rv = -1;
-	}
-	if (boardinfo->header_version != NETXEN_BDINFO_VERSION) {
-		printk("%s: Unknown board config version."
-		       " Read %x, expected %x\n", netxen_nic_driver_name,
-		       boardinfo->header_version, NETXEN_BDINFO_VERSION);
-		rv = -1;
+	if (magic != NETXEN_BDINFO_MAGIC ||
+			header_version != NETXEN_BDINFO_VERSION) {
+		dev_err(&pdev->dev,
+			"invalid board config, magic=%08x, version=%08x\n",
+			magic, header_version);
+		return -EIO;
 	}
 
-	if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
-		u32 gpio = netxen_nic_reg_read(adapter,
-				NETXEN_ROMUSB_GLB_PAD_GPIO_I);
+	offset = NETXEN_BRDCFG_START +
+		offsetof(struct netxen_board_info, board_type);
+	if (netxen_rom_fast_read(adapter, offset, &board_type))
+		return -EIO;
+
+	adapter->ahw.board_type = board_type;
+
+	if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
+		u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I);
 		if ((gpio & 0x8000) == 0)
-			boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP;
+			board_type = NETXEN_BRDTYPE_P3_10G_TP;
 	}
 
-	switch ((netxen_brdtype_t) boardinfo->board_type) {
+	switch (board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
-		adapter->ahw.board_type = NETXEN_NIC_GBE;
+		adapter->ahw.port_type = NETXEN_NIC_GBE;
 		break;
 	case NETXEN_BRDTYPE_P2_SB31_10G:
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -2074,7 +1882,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 	case NETXEN_BRDTYPE_P3_10G_SFP_QT:
 	case NETXEN_BRDTYPE_P3_10G_XFP:
 	case NETXEN_BRDTYPE_P3_10000_BASE_T:
-		adapter->ahw.board_type = NETXEN_NIC_XGBE;
+		adapter->ahw.port_type = NETXEN_NIC_XGBE;
 		break;
 	case NETXEN_BRDTYPE_P1_BD:
 	case NETXEN_BRDTYPE_P1_SB:
@@ -2083,20 +1891,19 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 	case NETXEN_BRDTYPE_P3_REF_QG:
 	case NETXEN_BRDTYPE_P3_4_GB:
 	case NETXEN_BRDTYPE_P3_4_GB_MM:
-		adapter->ahw.board_type = NETXEN_NIC_GBE;
+		adapter->ahw.port_type = NETXEN_NIC_GBE;
 		break;
 	case NETXEN_BRDTYPE_P3_10G_TP:
-		adapter->ahw.board_type = (adapter->portnum < 2) ?
+		adapter->ahw.port_type = (adapter->portnum < 2) ?
 			NETXEN_NIC_XGBE : NETXEN_NIC_GBE;
 		break;
 	default:
-		printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
-		       boardinfo->board_type);
-		rv = -ENODEV;
+		dev_err(&pdev->dev, "unknown board type %x\n", board_type);
+		adapter->ahw.port_type = NETXEN_NIC_XGBE;
 		break;
 	}
 
-	return rv;
+	return 0;
 }
 
 /* NIU access sections */
@@ -2104,8 +1911,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
 int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
 {
 	new_mtu += MTU_FUDGE_FACTOR;
-	netxen_nic_write_w0(adapter,
-		NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
+	NXWR32(adapter, NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->physical_port),
 		new_mtu);
 	return 0;
 }
@@ -2114,21 +1920,12 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
 {
 	new_mtu += MTU_FUDGE_FACTOR;
 	if (adapter->physical_port == 0)
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE,
-				new_mtu);
+		NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu);
 	else
-		netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE,
-				new_mtu);
+		NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu);
 	return 0;
 }
 
-void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
-		unsigned long off, int data)
-{
-	adapter->hw_write_wx(adapter, off, &data, 4);
-}
-
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
 {
 	__u32 status;
@@ -2142,9 +1939,8 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
 		return;
 	}
 
-	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &port_mode, 4);
+	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+		port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
 		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
 			adapter->link_speed   = SPEED_1000;
 			adapter->link_duplex  = DUPLEX_FULL;
@@ -2197,57 +1993,76 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
 	}
 }
 
-void netxen_nic_flash_print(struct netxen_adapter *adapter)
+void netxen_nic_get_firmware_info(struct netxen_adapter *adapter)
 {
-	u32 fw_major = 0;
-	u32 fw_minor = 0;
-	u32 fw_build = 0;
+	u32 fw_major, fw_minor, fw_build;
 	char brd_name[NETXEN_MAX_SHORT_NAME];
 	char serial_num[32];
-	int i, addr;
-	__le32 *ptr32;
-
-	struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
+	int i, addr, val;
+	int *ptr32;
+	struct pci_dev *pdev = adapter->pdev;
 
 	adapter->driver_mismatch = 0;
 
-	ptr32 = (u32 *)&serial_num;
+	ptr32 = (int *)&serial_num;
 	addr = NETXEN_USER_START +
 	       offsetof(struct netxen_new_user_info, serial_num);
 	for (i = 0; i < 8; i++) {
-		if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) {
-			printk("%s: ERROR reading %s board userarea.\n",
-			       netxen_nic_driver_name,
-			       netxen_nic_driver_name);
+		if (netxen_rom_fast_read(adapter, addr, &val) == -1) {
+			dev_err(&pdev->dev, "error reading board info\n");
 			adapter->driver_mismatch = 1;
 			return;
 		}
-		ptr32++;
+		ptr32[i] = cpu_to_le32(val);
 		addr += sizeof(u32);
 	}
 
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
-	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+	fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+	fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+	fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
 
 	adapter->fw_major = fw_major;
+	adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
 
 	if (adapter->portnum == 0) {
-		get_brd_name_by_type(board_info->board_type, brd_name);
+		get_brd_name_by_type(adapter->ahw.board_type, brd_name);
 
 		printk(KERN_INFO "NetXen %s Board S/N %s  Chip rev 0x%x\n",
 				brd_name, serial_num, adapter->ahw.revision_id);
-		printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n",
-				fw_major, fw_minor, fw_build);
 	}
 
-	if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
-			NETXEN_VERSION_CODE(3, 4, 216)) {
+	if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) {
 		adapter->driver_mismatch = 1;
-		printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
-				netxen_nic_driver_name,
+		dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n",
 				fw_major, fw_minor, fw_build);
 		return;
 	}
+
+	dev_info(&pdev->dev, "firmware version %d.%d.%d\n",
+			fw_major, fw_minor, fw_build);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		i = NXRD32(adapter, NETXEN_SRE_MISC);
+		adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0;
+		dev_info(&pdev->dev, "firmware running in %s mode\n",
+		adapter->ahw.cut_through ? "cut-through" : "legacy");
+	}
 }
 
+int
+netxen_nic_wol_supported(struct netxen_adapter *adapter)
+{
+	u32 wol_cfg;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return 0;
+
+	wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
+	if (wol_cfg & (1UL << adapter->portnum)) {
+		wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
+		if (wol_cfg & (1 << adapter->portnum))
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index 1a21bed..3e13fb7 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,12 +22,9 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * Structures, enums, and macros for the MAC
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
@@ -39,60 +36,13 @@
 /* Hardware memory size of 128 meg */
 #define NETXEN_MEMADDR_MAX (128 * 1024 * 1024)
 
-#ifndef readq
-static inline u64 readq(void __iomem * addr)
-{
-	return readl(addr) | (((u64) readl(addr + 4)) << 32LL);
-}
-#endif
-
-#ifndef writeq
-static inline void writeq(u64 val, void __iomem * addr)
-{
-	writel(((u32) (val)), (addr));
-	writel(((u32) (val >> 32)), (addr + 4));
-}
-#endif
-
-static inline void netxen_nic_hw_block_write64(u64 __iomem * data_ptr,
-					       u64 __iomem * addr,
-					       int num_words)
-{
-	int num;
-	for (num = 0; num < num_words; num++) {
-		writeq(readq((void __iomem *)data_ptr), addr);
-		addr++;
-		data_ptr++;
-	}
-}
-
-static inline void netxen_nic_hw_block_read64(u64 __iomem * data_ptr,
-					      u64 __iomem * addr, int num_words)
-{
-	int num;
-	for (num = 0; num < num_words; num++) {
-		writeq(readq((void __iomem *)addr), data_ptr);
-		addr++;
-		data_ptr++;
-	}
-
-}
-
 struct netxen_adapter;
 
 #define NETXEN_PCI_MAPSIZE_BYTES  (NETXEN_PCI_MAPSIZE << 20)
 
-struct netxen_port;
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
-void netxen_nic_flash_print(struct netxen_adapter *adapter);
-
-typedef u8 netxen_ethernet_macaddr_t[6];
 
 /* Nibble or Byte mode for phy interface (GbE mode only) */
-typedef enum {
-	NETXEN_NIU_10_100_MB = 0,
-	NETXEN_NIU_1000_MB
-} netxen_niu_gbe_ifmode_t;
 
 #define _netxen_crb_get_bit(var, bit)  ((var >> bit) & 0x1)
 
@@ -148,33 +98,6 @@ typedef enum {
 #define netxen_gb_get_soft_reset(config_word)	\
 		_netxen_crb_get_bit((config_word), 31)
 
-/*
- * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3)
- *
- *	Bit 0	    : duplex => 1:full duplex mode, 0:half duplex
- *	Bit 1	    : crc_enable => 1:append CRC to xmit frames, 0:dont append
- *	Bit 2	    : padshort => 1:pad short frames and add CRC, 0:dont pad
- *	Bit 4	    : checklength => 1:check framelen with actual,0:dont check
- *	Bit 5	    : hugeframes => 1:allow oversize xmit frames, 0:dont allow
- *	Bits 8-9    : intfmode => 01:nibble (10/100), 10:byte (1000)
- *	Bits 12-15  : preamblelen => preamble field length in bytes, default 7
- */
-
-#define netxen_gb_set_duplex(config_word)	\
-		((config_word) |= 1 << 0)
-#define netxen_gb_set_crc_enable(config_word)	\
-		((config_word) |= 1 << 1)
-#define netxen_gb_set_padshort(config_word)	\
-		((config_word) |= 1 << 2)
-#define netxen_gb_set_checklength(config_word)	\
-		((config_word) |= 1 << 4)
-#define netxen_gb_set_hugeframes(config_word)	\
-		((config_word) |= 1 << 5)
-#define netxen_gb_set_preamblelen(config_word, val)	\
-		((config_word) &= ~(0xf<<12), (config_word) |= (val & 0xf)<< 12)
-#define netxen_gb_set_intfmode(config_word, val)		\
-		((config_word) &= ~(0x3<<8), (config_word) |= (val & 0x3) << 8)
-
 #define netxen_gb_get_stationaddress_low(config_word) ((config_word) >> 16)
 
 #define netxen_gb_set_mii_mgmt_clockselect(config_word, val)	\
@@ -277,30 +200,28 @@ typedef enum {
 /*
  * PHY-Specific MII control/status registers.
  */
-typedef enum {
-	NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26,
-	NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27
-} netxen_niu_phy_register_t;
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL		0
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS		1
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0		2
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1		3
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG		4
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART		5
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE	6
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT	7
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE	8
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL	9
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS	10
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS	15
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL		16
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS		17
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE		18
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS		19
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE	20
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT	21
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL		24
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE	25
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET	26
+#define NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE	27
 
 /*
  * PHY-Specific Status Register (reg 17).
@@ -473,16 +394,6 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 				       u32 mode);
 
-/* get/set the MAC address for a given MAC */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
-			   netxen_ethernet_macaddr_t addr);
-
-/* XG versons */
-int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t * addr);
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t addr);
-
 /* Generic enable for GbE ports. Will detect the speed of the link. */
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port);
 
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index dc1092f..7440bef 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,12 +22,9 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * Source file for NIC routines to initialize the Phantom Hardware
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
@@ -37,8 +34,9 @@
 #include "netxen_nic_hw.h"
 #include "netxen_nic_phan_reg.h"
 
-static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
-	u32 ctx, u32 ringid);
+static void
+netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+		struct nx_host_rds_ring *rds_ring);
 
 struct crb_addr_pair {
 	u32 addr;
@@ -55,16 +53,6 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
 
 #define NETXEN_NIC_XDMA_RESET 0x8000ff
 
-#if 0
-static inline void
-netxen_nic_locked_write_reg(struct netxen_adapter *adapter,
-			    unsigned long off, int *data)
-{
-	void __iomem *addr = pci_base_offset(adapter, off);
-	writel(*data, addr);
-}
-#endif /* 0 */
-
 static void crb_addr_transform_setup(void)
 {
 	crb_addr_transform(XDMA);
@@ -120,64 +108,26 @@ static void crb_addr_transform_setup(void)
 	crb_addr_transform(I2C0);
 }
 
-int netxen_init_firmware(struct netxen_adapter *adapter)
-{
-	u32 state = 0, loops = 0, err = 0;
-
-	/* Window 1 call */
-	state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
-
-	if (state == PHAN_INITIALIZE_ACK)
-		return 0;
-
-	while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
-		msleep(1);
-		/* Window 1 call */
-		state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
-
-		loops++;
-	}
-	if (loops >= 2000) {
-		printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n",
-		       state);
-		err = -EIO;
-		return err;
-	}
-	/* Window 1 call */
-	adapter->pci_write_normalize(adapter,
-			CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
-	adapter->pci_write_normalize(adapter,
-			CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
-	adapter->pci_write_normalize(adapter,
-			CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
-	adapter->pci_write_normalize(adapter,
-			CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
-
-	return err;
-}
-
 void netxen_release_rx_buffers(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
 	struct netxen_rx_buffer *rx_buf;
-	int i, ctxid, ring;
-
-	for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
-		recv_ctx = &adapter->recv_ctx[ctxid];
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			rds_ring = &recv_ctx->rds_rings[ring];
-			for (i = 0; i < rds_ring->max_rx_desc_count; ++i) {
-				rx_buf = &(rds_ring->rx_buf_arr[i]);
-				if (rx_buf->state == NETXEN_BUFFER_FREE)
-					continue;
-				pci_unmap_single(adapter->pdev,
-						rx_buf->dma,
-						rds_ring->dma_size,
-						PCI_DMA_FROMDEVICE);
-				if (rx_buf->skb != NULL)
-					dev_kfree_skb_any(rx_buf->skb);
-			}
+	int i, ring;
+
+	recv_ctx = &adapter->recv_ctx;
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+		for (i = 0; i < rds_ring->num_desc; ++i) {
+			rx_buf = &(rds_ring->rx_buf_arr[i]);
+			if (rx_buf->state == NETXEN_BUFFER_FREE)
+				continue;
+			pci_unmap_single(adapter->pdev,
+					rx_buf->dma,
+					rds_ring->dma_size,
+					PCI_DMA_FROMDEVICE);
+			if (rx_buf->skb != NULL)
+				dev_kfree_skb_any(rx_buf->skb);
 		}
 	}
 }
@@ -187,9 +137,10 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
 	struct netxen_cmd_buffer *cmd_buf;
 	struct netxen_skb_frag *buffrag;
 	int i, j;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
-	cmd_buf = adapter->cmd_buf_arr;
-	for (i = 0; i < adapter->max_tx_desc_count; i++) {
+	cmd_buf = tx_ring->cmd_buf_arr;
+	for (i = 0; i < tx_ring->num_desc; i++) {
 		buffrag = cmd_buf->frag_array;
 		if (buffrag->dma) {
 			pci_unmap_single(adapter->pdev, buffrag->dma,
@@ -205,7 +156,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
 				buffrag->dma = 0ULL;
 			}
 		}
-		/* Free the skb we received in netxen_nic_xmit_frame */
 		if (cmd_buf->skb) {
 			dev_kfree_skb_any(cmd_buf->skb);
 			cmd_buf->skb = NULL;
@@ -218,111 +168,144 @@ void netxen_free_sw_resources(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
-	int ctx, ring;
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			rds_ring = &recv_ctx->rds_rings[ring];
-			if (rds_ring->rx_buf_arr) {
-				vfree(rds_ring->rx_buf_arr);
-				rds_ring->rx_buf_arr = NULL;
-			}
-		}
+	struct nx_host_tx_ring *tx_ring;
+	int ring;
+
+	recv_ctx = &adapter->recv_ctx;
+
+	if (recv_ctx->rds_rings == NULL)
+		goto skip_rds;
+
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+		vfree(rds_ring->rx_buf_arr);
+		rds_ring->rx_buf_arr = NULL;
 	}
-	if (adapter->cmd_buf_arr)
-		vfree(adapter->cmd_buf_arr);
-	return;
+	kfree(recv_ctx->rds_rings);
+
+skip_rds:
+	if (adapter->tx_ring == NULL)
+		return;
+
+	tx_ring = adapter->tx_ring;
+	vfree(tx_ring->cmd_buf_arr);
 }
 
 int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
 {
 	struct netxen_recv_context *recv_ctx;
 	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct nx_host_tx_ring *tx_ring;
 	struct netxen_rx_buffer *rx_buf;
-	int ctx, ring, i, num_rx_bufs;
+	int ring, i, size;
 
 	struct netxen_cmd_buffer *cmd_buf_arr;
 	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
 
-	cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+	size = sizeof(struct nx_host_tx_ring);
+	tx_ring = kzalloc(size, GFP_KERNEL);
+	if (tx_ring == NULL) {
+		dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n",
+		       netdev->name);
+		return -ENOMEM;
+	}
+	adapter->tx_ring = tx_ring;
+
+	tx_ring->num_desc = adapter->num_txd;
+
+	cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
 	if (cmd_buf_arr == NULL) {
-		printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+		dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
 		       netdev->name);
 		return -ENOMEM;
 	}
-	memset(cmd_buf_arr, 0, TX_RINGSIZE);
-	adapter->cmd_buf_arr = cmd_buf_arr;
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-			rds_ring = &recv_ctx->rds_rings[ring];
-			switch (RCV_DESC_TYPE(ring)) {
-			case RCV_DESC_NORMAL:
-				rds_ring->max_rx_desc_count =
-					adapter->max_rx_desc_count;
-				rds_ring->flags = RCV_DESC_NORMAL;
-				if (adapter->ahw.cut_through) {
-					rds_ring->dma_size =
-						NX_CT_DEFAULT_RX_BUF_LEN;
-					rds_ring->skb_size =
-						NX_CT_DEFAULT_RX_BUF_LEN;
-				} else {
-					rds_ring->dma_size = RX_DMA_MAP_LEN;
-					rds_ring->skb_size =
-						MAX_RX_BUFFER_LENGTH;
-				}
-				break;
+	memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
+	tx_ring->cmd_buf_arr = cmd_buf_arr;
+	spin_lock_init(&tx_ring->lock);
 
-			case RCV_DESC_JUMBO:
-				rds_ring->max_rx_desc_count =
-					adapter->max_jumbo_rx_desc_count;
-				rds_ring->flags = RCV_DESC_JUMBO;
-				if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-					rds_ring->dma_size =
-						NX_P3_RX_JUMBO_BUF_MAX_LEN;
-				else
-					rds_ring->dma_size =
-						NX_P2_RX_JUMBO_BUF_MAX_LEN;
+	recv_ctx = &adapter->recv_ctx;
+
+	size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring);
+	rds_ring = kzalloc(size, GFP_KERNEL);
+	if (rds_ring == NULL) {
+		dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
+		       netdev->name);
+		return -ENOMEM;
+	}
+	recv_ctx->rds_rings = rds_ring;
+
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &recv_ctx->rds_rings[ring];
+		switch (ring) {
+		case RCV_RING_NORMAL:
+			rds_ring->num_desc = adapter->num_rxd;
+			if (adapter->ahw.cut_through) {
+				rds_ring->dma_size =
+					NX_CT_DEFAULT_RX_BUF_LEN;
 				rds_ring->skb_size =
-					rds_ring->dma_size + NET_IP_ALIGN;
-				break;
+					NX_CT_DEFAULT_RX_BUF_LEN;
+			} else {
+				rds_ring->dma_size = RX_DMA_MAP_LEN;
+				rds_ring->skb_size =
+					MAX_RX_BUFFER_LENGTH;
+			}
+			break;
 
-			case RCV_RING_LRO:
-				rds_ring->max_rx_desc_count =
-					adapter->max_lro_rx_desc_count;
-				rds_ring->flags = RCV_DESC_LRO;
-				rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
-				rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
-				break;
+		case RCV_RING_JUMBO:
+			rds_ring->num_desc = adapter->num_jumbo_rxd;
+			if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+				rds_ring->dma_size =
+					NX_P3_RX_JUMBO_BUF_MAX_LEN;
+			else
+				rds_ring->dma_size =
+					NX_P2_RX_JUMBO_BUF_MAX_LEN;
+			rds_ring->skb_size =
+				rds_ring->dma_size + NET_IP_ALIGN;
+			break;
 
-			}
-			rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
-				vmalloc(RCV_BUFFSIZE);
-			if (rds_ring->rx_buf_arr == NULL) {
-				printk(KERN_ERR "%s: Failed to allocate "
-					"rx buffer ring %d\n",
-					netdev->name, ring);
-				/* free whatever was already allocated */
-				goto err_out;
-			}
-			memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
-			INIT_LIST_HEAD(&rds_ring->free_list);
-			/*
-			 * Now go through all of them, set reference handles
-			 * and put them in the queues.
-			 */
-			num_rx_bufs = rds_ring->max_rx_desc_count;
-			rx_buf = rds_ring->rx_buf_arr;
-			for (i = 0; i < num_rx_bufs; i++) {
-				list_add_tail(&rx_buf->list,
-						&rds_ring->free_list);
-				rx_buf->ref_handle = i;
-				rx_buf->state = NETXEN_BUFFER_FREE;
-				rx_buf++;
-			}
+		case RCV_RING_LRO:
+			rds_ring->num_desc = adapter->num_lro_rxd;
+			rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+			rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+			break;
+
+		}
+		rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+			vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
+		if (rds_ring->rx_buf_arr == NULL) {
+			printk(KERN_ERR "%s: Failed to allocate "
+				"rx buffer ring %d\n",
+				netdev->name, ring);
+			/* free whatever was already allocated */
+			goto err_out;
 		}
+		memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
+		INIT_LIST_HEAD(&rds_ring->free_list);
+		/*
+		 * Now go through all of them, set reference handles
+		 * and put them in the queues.
+		 */
+		rx_buf = rds_ring->rx_buf_arr;
+		for (i = 0; i < rds_ring->num_desc; i++) {
+			list_add_tail(&rx_buf->list,
+					&rds_ring->free_list);
+			rx_buf->ref_handle = i;
+			rx_buf->state = NETXEN_BUFFER_FREE;
+			rx_buf++;
+		}
+		spin_lock_init(&rds_ring->lock);
+	}
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		sds_ring->irq = adapter->msix_entries[ring].vector;
+		sds_ring->adapter = adapter;
+		sds_ring->num_desc = adapter->num_rxd;
+
+		for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
+			INIT_LIST_HEAD(&sds_ring->free_list[i]);
 	}
 
 	return 0;
@@ -334,13 +317,15 @@ err_out:
 
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 {
-	switch (adapter->ahw.board_type) {
+	adapter->macaddr_set = netxen_p2_nic_set_mac_addr;
+	adapter->set_multi = netxen_p2_nic_set_multi;
+
+	switch (adapter->ahw.port_type) {
 	case NETXEN_NIC_GBE:
 		adapter->enable_phy_interrupts =
 		    netxen_niu_gbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_gbe_disable_phy_interrupts;
-		adapter->macaddr_set = netxen_niu_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_gb;
 		adapter->set_promisc = netxen_niu_set_promiscuous_mode;
 		adapter->phy_read = netxen_niu_gbe_phy_read;
@@ -354,7 +339,6 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 		    netxen_niu_xgbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_xgbe_disable_phy_interrupts;
-		adapter->macaddr_set = netxen_niu_xg_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_xgb;
 		adapter->init_port = netxen_niu_xg_init_port;
 		adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
@@ -368,6 +352,8 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		adapter->set_mtu = nx_fw_cmd_set_mtu;
 		adapter->set_promisc = netxen_p3_nic_set_promisc;
+		adapter->macaddr_set = netxen_p3_nic_set_mac_addr;
+		adapter->set_multi = netxen_p3_nic_set_multi;
 	}
 }
 
@@ -400,11 +386,8 @@ static u32 netxen_decode_crb_addr(u32 addr)
 
 static long rom_max_timeout = 100;
 static long rom_lock_timeout = 10000;
-#if 0
-static long rom_write_timeout = 700;
-#endif
 
-static inline int rom_lock(struct netxen_adapter *adapter)
+static int rom_lock(struct netxen_adapter *adapter)
 {
 	int iter;
 	u32 done = 0;
@@ -412,8 +395,7 @@ static inline int rom_lock(struct netxen_adapter *adapter)
 
 	while (!done) {
 		/* acquire semaphore2 from PCI HW block */
-		netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK),
-				   &done);
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= rom_lock_timeout)
@@ -430,7 +412,7 @@ static inline int rom_lock(struct netxen_adapter *adapter)
 				cpu_relax();	/*This a nop instr on i386 */
 		}
 	}
-	netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
+	NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER);
 	return 0;
 }
 
@@ -442,7 +424,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
 	cond_resched();
 
 	while (done == 0) {
-		done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
+		done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS);
 		done &= 2;
 		timeout++;
 		if (timeout >= rom_max_timeout) {
@@ -453,117 +435,45 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
 	return 0;
 }
 
-#if 0
-static inline int netxen_rom_wren(struct netxen_adapter *adapter)
-{
-	/* Set write enable latch in ROM status register */
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-			     M25P_INSTR_WREN);
-	if (netxen_wait_rom_done(adapter)) {
-		return -1;
-	}
-	return 0;
-}
-
-static inline unsigned int netxen_rdcrbreg(struct netxen_adapter *adapter,
-					   unsigned int addr)
-{
-	unsigned int data = 0xdeaddead;
-	data = netxen_nic_reg_read(adapter, addr);
-	return data;
-}
-
-static inline int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
-{
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-			     M25P_INSTR_RDSR);
-	if (netxen_wait_rom_done(adapter)) {
-		return -1;
-	}
-	return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
-}
-#endif
-
-static inline void netxen_rom_unlock(struct netxen_adapter *adapter)
+static void netxen_rom_unlock(struct netxen_adapter *adapter)
 {
-	u32 val;
-
 	/* release semaphore2 */
-	netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
+	NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK));
 
 }
 
-#if 0
-static int netxen_rom_wip_poll(struct netxen_adapter *adapter)
+static int do_rom_fast_read(struct netxen_adapter *adapter,
+			    int addr, int *valp)
 {
-	long timeout = 0;
-	long wip = 1;
-	int val;
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-	while (wip != 0) {
-		val = netxen_do_rom_rdsr(adapter);
-		wip = val & 1;
-		timeout++;
-		if (timeout > rom_max_timeout) {
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
-				    int data)
-{
-	if (netxen_rom_wren(adapter)) {
-		return -1;
-	}
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_WDATA, data);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-			     M25P_INSTR_PP);
-	if (netxen_wait_rom_done(adapter)) {
-		netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-		return -1;
-	}
-
-	return netxen_rom_wip_poll(adapter);
-}
-#endif
-
-static inline int
-do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
-{
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
 	if (netxen_wait_rom_done(adapter)) {
 		printk("Error waiting for rom done\n");
 		return -EIO;
 	}
 	/* reset abyte_cnt and dummy_byte_cnt */
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
 	udelay(10);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+	NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
 
-	*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
+	*valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA);
 	return 0;
 }
 
-static inline int
-do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
-			u8 *bytes, size_t size)
+static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
+				  u8 *bytes, size_t size)
 {
 	int addridx;
 	int ret = 0;
 
 	for (addridx = addr; addridx < (addr + size); addridx += 4) {
-		ret = do_rom_fast_read(adapter, addridx, (int *)bytes);
+		int v;
+		ret = do_rom_fast_read(adapter, addridx, &v);
 		if (ret != 0)
 			break;
-		*(int *)bytes = cpu_to_le32(*(int *)bytes);
+		*(__le32 *)bytes = cpu_to_le32(v);
 		bytes += 4;
 	}
 
@@ -598,286 +508,6 @@ int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
 	return ret;
 }
 
-#if 0
-int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
-{
-	int ret = 0;
-
-	if (rom_lock(adapter) != 0) {
-		return -1;
-	}
-	ret = do_rom_fast_write(adapter, addr, data);
-	netxen_rom_unlock(adapter);
-	return ret;
-}
-
-static inline int do_rom_fast_write_words(struct netxen_adapter *adapter,
-						int addr, u8 *bytes, size_t size)
-{
-	int addridx = addr;
-	int ret = 0;
-
-	while (addridx < (addr + size)) {
-		int last_attempt = 0;
-		int timeout = 0;
-		int data;
-
-		data = le32_to_cpu((*(u32*)bytes));
-		ret = do_rom_fast_write(adapter, addridx, data);
-		if (ret < 0)
-			return ret;
-
-		while(1) {
-			int data1;
-
-			ret = do_rom_fast_read(adapter, addridx, &data1);
-			if (ret < 0)
-				return ret;
-
-			if (data1 == data)
-				break;
-
-			if (timeout++ >= rom_write_timeout) {
-				if (last_attempt++ < 4) {
-					ret = do_rom_fast_write(adapter,
-								addridx, data);
-					if (ret < 0)
-						return ret;
-				}
-				else {
-					printk(KERN_INFO "Data write did not "
-					   "succeed at address 0x%x\n", addridx);
-					break;
-				}
-			}
-		}
-
-		bytes += 4;
-		addridx += 4;
-	}
-
-	return ret;
-}
-
-int netxen_rom_fast_write_words(struct netxen_adapter *adapter, int addr,
-					u8 *bytes, size_t size)
-{
-	int ret = 0;
-
-	ret = rom_lock(adapter);
-	if (ret < 0)
-		return ret;
-
-	ret = do_rom_fast_write_words(adapter, addr, bytes, size);
-	netxen_rom_unlock(adapter);
-
-	return ret;
-}
-
-static int netxen_rom_wrsr(struct netxen_adapter *adapter, int data)
-{
-	int ret;
-
-	ret = netxen_rom_wren(adapter);
-	if (ret < 0)
-		return ret;
-
-	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_ROM_WDATA, data);
-	netxen_crb_writelit_adapter(adapter,
-					NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0x1);
-
-	ret = netxen_wait_rom_done(adapter);
-	if (ret < 0)
-		return ret;
-
-	return netxen_rom_wip_poll(adapter);
-}
-
-static int netxen_rom_rdsr(struct netxen_adapter *adapter)
-{
-	int ret;
-
-	ret = rom_lock(adapter);
-	if (ret < 0)
-		return ret;
-
-	ret = netxen_do_rom_rdsr(adapter);
-	netxen_rom_unlock(adapter);
-	return ret;
-}
-
-int netxen_backup_crbinit(struct netxen_adapter *adapter)
-{
-	int ret = FLASH_SUCCESS;
-	int val;
-	char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL);
-
-	if (!buffer)
-		return -ENOMEM;
-	/* unlock sector 63 */
-	val = netxen_rom_rdsr(adapter);
-	val = val & 0xe3;
-	ret = netxen_rom_wrsr(adapter, val);
-	if (ret != FLASH_SUCCESS)
-		goto out_kfree;
-
-	ret = netxen_rom_wip_poll(adapter);
-	if (ret != FLASH_SUCCESS)
-		goto out_kfree;
-
-	/* copy  sector 0 to sector 63 */
-	ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START,
-						buffer, 
-						NETXEN_FLASH_SECTOR_SIZE);
-	if (ret != FLASH_SUCCESS)
-		goto out_kfree;
-
-	ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START,
-						buffer, 
-						NETXEN_FLASH_SECTOR_SIZE);
-	if (ret != FLASH_SUCCESS)
-		goto out_kfree;
-
-	/* lock sector 63 */
-	val = netxen_rom_rdsr(adapter);
-	if (!(val & 0x8)) {
-		val |= (0x1 << 2);
-		/* lock sector 63 */
-		if (netxen_rom_wrsr(adapter, val) == 0) {
-			ret = netxen_rom_wip_poll(adapter);
-			if (ret != FLASH_SUCCESS)
-				goto out_kfree;
-
-			/* lock SR writes */
-			ret = netxen_rom_wip_poll(adapter);
-			if (ret != FLASH_SUCCESS)
-				goto out_kfree;
-		}
-	}
-
-out_kfree:
-	kfree(buffer);
-	return ret;
-}
-
-static int netxen_do_rom_se(struct netxen_adapter *adapter, int addr)
-{
-	netxen_rom_wren(adapter);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
-	netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE,
-			     M25P_INSTR_SE);
-	if (netxen_wait_rom_done(adapter)) {
-		netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
-		return -1;
-	}
-	return netxen_rom_wip_poll(adapter);
-}
-
-static void check_erased_flash(struct netxen_adapter *adapter, int addr)
-{
-	int i;
-	int val;
-	int count = 0, erased_errors = 0;
-	int range;
-
-	range = (addr == NETXEN_USER_START) ? 
-		NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE;
-
-	for (i = addr; i < range; i += 4) {
-		netxen_rom_fast_read(adapter, i, &val);
-		if (val != 0xffffffff)
-			erased_errors++;
-		count++;
-	}
-
-	if (erased_errors)
-		printk(KERN_INFO "0x%x out of 0x%x words fail to be erased "
-			"for sector address: %x\n", erased_errors, count, addr);
-}
-
-int netxen_rom_se(struct netxen_adapter *adapter, int addr)
-{
-	int ret = 0;
-	if (rom_lock(adapter) != 0) {
-		return -1;
-	}
-	ret = netxen_do_rom_se(adapter, addr);
-	netxen_rom_unlock(adapter);
-	msleep(30);
-	check_erased_flash(adapter, addr);
-
-	return ret;
-}
-
-static int
-netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end)
-{
-	int ret = FLASH_SUCCESS;
-	int i;
-
-	for (i = start; i < end; i++) {
-		ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE);
-		if (ret)
-			break;
-		ret = netxen_rom_wip_poll(adapter);
-		if (ret < 0)
-			return ret;
-	}
-
-	return ret;
-}
-
-int
-netxen_flash_erase_secondary(struct netxen_adapter *adapter)
-{
-	int ret = FLASH_SUCCESS;
-	int start, end;
-
-	start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
-	end   = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE;
-	ret = netxen_flash_erase_sections(adapter, start, end);
-
-	return ret;
-}
-
-int
-netxen_flash_erase_primary(struct netxen_adapter *adapter)
-{
-	int ret = FLASH_SUCCESS;
-	int start, end;
-
-	start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE;
-	end   = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
-	ret = netxen_flash_erase_sections(adapter, start, end);
-
-	return ret;
-}
-
-void netxen_halt_pegs(struct netxen_adapter *adapter)
-{
-	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1);
-	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1);
-	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1);
-	 netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1);
-}
-
-int netxen_flash_unlock(struct netxen_adapter *adapter)
-{
-	int ret = 0;
-
-	ret = netxen_rom_wrsr(adapter, 0);
-	if (ret < 0)
-		return ret;
-
-	ret = netxen_rom_wren(adapter);
-	if (ret < 0)
-		return ret;
-
-	return ret;
-}
-#endif  /*  0  */
-
 #define NETXEN_BOARDTYPE		0x4008
 #define NETXEN_BOARDNUM 		0x400c
 #define NETXEN_CHIPNUM			0x4010
@@ -892,8 +522,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
 
 	/* resetall */
 	rom_lock(adapter);
-	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-				    0xffffffff);
+	NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff);
 	netxen_rom_unlock(adapter);
 
 	if (verbose) {
@@ -1017,7 +646,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
 			}
 		}
 
-		adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
+		NXWR32(adapter, off, buf[i].data);
 
 		msleep(init_delay);
 	}
@@ -1027,36 +656,303 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
 
 	/* unreset_net_cache */
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
-		netxen_crb_writelit_adapter(adapter,
-				NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
+		val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
 	}
 
 	/* p2dn replyCount */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
 	/* disable_peg_cache 0 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
 	/* disable_peg_cache 1 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
 
 	/* peg_clr_all */
 
 	/* peg_clr 0 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
 	/* peg_clr 1 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
 	/* peg_clr 2 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
 	/* peg_clr 3 */
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
-	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+	NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
 	return 0;
 }
 
+int
+netxen_need_fw_reset(struct netxen_adapter *adapter)
+{
+	u32 count, old_count;
+	u32 val, version, major, minor, build;
+	int i, timeout;
+	u8 fw_type;
+
+	/* NX2031 firmware doesn't support heartbit */
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		return 1;
+
+	/* last attempt had failed */
+	if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
+		return 1;
+
+	old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+
+	for (i = 0; i < 10; i++) {
+
+		timeout = msleep_interruptible(200);
+		if (timeout) {
+			NXWR32(adapter, CRB_CMDPEG_STATE,
+					PHAN_INITIALIZE_FAILED);
+			return -EINTR;
+		}
+
+		count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+		if (count != old_count)
+			break;
+	}
+
+	/* firmware is dead */
+	if (count == old_count)
+		return 1;
+
+	/* check if we have got newer or different file firmware */
+	if (adapter->fw) {
+
+		const struct firmware *fw = adapter->fw;
+
+		val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+		version = NETXEN_DECODE_VERSION(val);
+
+		major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+		minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+		build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
+
+		if (version > NETXEN_VERSION_CODE(major, minor, build))
+			return 1;
+
+		if (version == NETXEN_VERSION_CODE(major, minor, build)) {
+
+			val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
+			fw_type = (val & 0x4) ?
+				NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;
+
+			if (adapter->fw_type != fw_type)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static char *fw_name[] = {
+	"nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
+};
+
+int
+netxen_load_firmware(struct netxen_adapter *adapter)
+{
+	u64 *ptr64;
+	u32 i, flashaddr, size;
+	const struct firmware *fw = adapter->fw;
+	struct pci_dev *pdev = adapter->pdev;
+
+	dev_info(&pdev->dev, "loading firmware from %s\n",
+			fw_name[adapter->fw_type]);
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
+
+	if (fw) {
+		__le64 data;
+
+		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8;
+
+		ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START];
+		flashaddr = NETXEN_BOOTLD_START;
+
+		for (i = 0; i < size; i++) {
+			data = cpu_to_le64(ptr64[i]);
+			adapter->pci_mem_write(adapter, flashaddr, &data, 8);
+			flashaddr += 8;
+		}
+
+		size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET];
+		size = (__force u32)cpu_to_le32(size) / 8;
+
+		ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START];
+		flashaddr = NETXEN_IMAGE_START;
+
+		for (i = 0; i < size; i++) {
+			data = cpu_to_le64(ptr64[i]);
+
+			if (adapter->pci_mem_write(adapter,
+						flashaddr, &data, 8))
+				return -EIO;
+
+			flashaddr += 8;
+		}
+	} else {
+		u32 data;
+
+		size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4;
+		flashaddr = NETXEN_BOOTLD_START;
+
+		for (i = 0; i < size; i++) {
+			if (netxen_rom_fast_read(adapter,
+					flashaddr, (int *)&data) != 0)
+				return -EIO;
+
+			if (adapter->pci_mem_write(adapter,
+						flashaddr, &data, 4))
+				return -EIO;
+
+			flashaddr += 4;
+		}
+	}
+	msleep(1);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+	else {
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0);
+	}
+
+	return 0;
+}
+
+static int
+netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
+{
+	__le32 val;
+	u32 ver, min_ver, bios;
+	struct pci_dev *pdev = adapter->pdev;
+	const struct firmware *fw = adapter->fw;
+
+	if (fw->size < NX_FW_MIN_SIZE)
+		return -EINVAL;
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
+	if ((__force u32)val != NETXEN_BDINFO_MAGIC)
+		return -EINVAL;
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		min_ver = NETXEN_VERSION_CODE(4, 0, 216);
+	else
+		min_ver = NETXEN_VERSION_CODE(3, 4, 216);
+
+	ver = NETXEN_DECODE_VERSION(val);
+
+	if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+		dev_err(&pdev->dev,
+				"%s: firmware version %d.%d.%d unsupported\n",
+				fwname, _major(ver), _minor(ver), _build(ver));
+		return -EINVAL;
+	}
+
+	val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]);
+	netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
+	if ((__force u32)val != bios) {
+		dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
+				fwname);
+		return -EINVAL;
+	}
+
+	/* check if flashed firmware is newer */
+	if (netxen_rom_fast_read(adapter,
+			NX_FW_VERSION_OFFSET, (int *)&val))
+		return -EIO;
+	val = NETXEN_DECODE_VERSION(val);
+	if (val > ver) {
+		dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+				fwname);
+		return -EINVAL;
+	}
+
+	NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+	return 0;
+}
+
+void netxen_request_firmware(struct netxen_adapter *adapter)
+{
+	u32 capability, flashed_ver;
+	u8 fw_type;
+	struct pci_dev *pdev = adapter->pdev;
+	int rc = 0;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		fw_type = NX_P2_MN_ROMIMAGE;
+		goto request_fw;
+	} else {
+		fw_type = NX_P3_CT_ROMIMAGE;
+		goto request_fw;
+	}
+
+request_mn:
+	capability = 0;
+
+	netxen_rom_fast_read(adapter,
+			NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
+	flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
+
+	if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
+		capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
+		if (capability & NX_PEG_TUNE_MN_PRESENT) {
+			fw_type = NX_P3_MN_ROMIMAGE;
+			goto request_fw;
+		}
+	}
+
+	fw_type = NX_FLASH_ROMIMAGE;
+	adapter->fw = NULL;
+	goto done;
+
+request_fw:
+	rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
+	if (rc != 0) {
+		if (fw_type == NX_P3_CT_ROMIMAGE) {
+			msleep(1);
+			goto request_mn;
+		}
+
+		fw_type = NX_FLASH_ROMIMAGE;
+		adapter->fw = NULL;
+		goto done;
+	}
+
+	rc = netxen_validate_firmware(adapter, fw_name[fw_type]);
+	if (rc != 0) {
+		release_firmware(adapter->fw);
+
+		if (fw_type == NX_P3_CT_ROMIMAGE) {
+			msleep(1);
+			goto request_mn;
+		}
+
+		fw_type = NX_FLASH_ROMIMAGE;
+		adapter->fw = NULL;
+		goto done;
+	}
+
+done:
+	adapter->fw_type = fw_type;
+}
+
+
+void
+netxen_release_firmware(struct netxen_adapter *adapter)
+{
+	if (adapter->fw)
+		release_firmware(adapter->fw);
+}
+
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 {
 	uint64_t addr;
@@ -1077,12 +973,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
 	hi = (addr >> 32) & 0xffffffff;
 	lo = addr & 0xffffffff;
 
-	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
-	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+	NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
 
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		uint32_t temp = 0;
-		adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+		NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp);
 	}
 
 	return 0;
@@ -1122,40 +1018,41 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
 	u32 val = 0;
 	int retries = 60;
 
-	if (!pegtune_val) {
- 		do {
-			val = adapter->pci_read_normalize(adapter,
-					CRB_CMDPEG_STATE);
+	if (pegtune_val)
+		return 0;
 
- 			if (val == PHAN_INITIALIZE_COMPLETE ||
- 				val == PHAN_INITIALIZE_ACK)
- 				return 0;
+	do {
+		val = NXRD32(adapter, CRB_CMDPEG_STATE);
+
+		switch (val) {
+		case PHAN_INITIALIZE_COMPLETE:
+		case PHAN_INITIALIZE_ACK:
+			return 0;
+		case PHAN_INITIALIZE_FAILED:
+			goto out_err;
+		default:
+			break;
+		}
 
-			msleep(500);
+		msleep(500);
 
- 		} while (--retries);
+	} while (--retries);
 
-		if (!retries) {
-			pegtune_val = adapter->pci_read_normalize(adapter,
-					NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
- 			printk(KERN_WARNING "netxen_phantom_init: init failed, "
- 					"pegtune_val=%x\n", pegtune_val);
- 			return -1;
-		}
-		if (val != PHAN_INITIALIZE_COMPLETE)
-			printk("WARNING: Initial boot wait loop failed...\n");
-	}
+	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
 
- 	return 0;
+out_err:
+	dev_warn(&adapter->pdev->dev, "firmware init failed\n");
+	return -EIO;
 }
 
-int netxen_receive_peg_ready(struct netxen_adapter *adapter)
+static int
+netxen_receive_peg_ready(struct netxen_adapter *adapter)
 {
 	u32 val = 0;
 	int retries = 2000;
 
 	do {
-		val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+		val = NXRD32(adapter, CRB_RCVPEG_STATE);
 
 		if (val == PHAN_PEG_RCV_INITIALIZED)
 			return 0;
@@ -1173,6 +1070,127 @@ int netxen_receive_peg_ready(struct netxen_adapter *adapter)
 	return 0;
 }
 
+int netxen_init_firmware(struct netxen_adapter *adapter)
+{
+	int err;
+
+	err = netxen_receive_peg_ready(adapter);
+	if (err)
+		return err;
+
+	NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+	NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+	NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+	NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+	if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) {
+		adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
+	}
+
+	return err;
+}
+
+static void
+netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg)
+{
+	u32 cable_OUI;
+	u16 cable_len;
+	u16 link_speed;
+	u8  link_status, module, duplex, autoneg;
+	struct net_device *netdev = adapter->netdev;
+
+	adapter->has_link_events = 1;
+
+	cable_OUI = msg->body[1] & 0xffffffff;
+	cable_len = (msg->body[1] >> 32) & 0xffff;
+	link_speed = (msg->body[1] >> 48) & 0xffff;
+
+	link_status = msg->body[2] & 0xff;
+	duplex = (msg->body[2] >> 16) & 0xff;
+	autoneg = (msg->body[2] >> 24) & 0xff;
+
+	module = (msg->body[2] >> 8) & 0xff;
+	if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) {
+		printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n",
+				netdev->name, cable_OUI, cable_len);
+	} else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) {
+		printk(KERN_INFO "%s: unsupported cable length %d\n",
+				netdev->name, cable_len);
+	}
+
+	netxen_advert_link_change(adapter, link_status);
+
+	/* update link parameters */
+	if (duplex == LINKEVENT_FULL_DUPLEX)
+		adapter->link_duplex = DUPLEX_FULL;
+	else
+		adapter->link_duplex = DUPLEX_HALF;
+	adapter->module_type = module;
+	adapter->link_autoneg = autoneg;
+	adapter->link_speed = link_speed;
+}
+
+static void
+netxen_handle_fw_message(int desc_cnt, int index,
+		struct nx_host_sds_ring *sds_ring)
+{
+	nx_fw_msg_t msg;
+	struct status_desc *desc;
+	int i = 0, opcode;
+
+	while (desc_cnt > 0 && i < 8) {
+		desc = &sds_ring->desc_head[index];
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+		msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+		index = get_next_index(index, sds_ring->num_desc);
+		desc_cnt--;
+	}
+
+	opcode = netxen_get_nic_msg_opcode(msg.body[0]);
+	switch (opcode) {
+	case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+		netxen_handle_linkevent(sds_ring->adapter, &msg);
+		break;
+	default:
+		break;
+	}
+}
+
+static int
+netxen_alloc_rx_skb(struct netxen_adapter *adapter,
+		struct nx_host_rds_ring *rds_ring,
+		struct netxen_rx_buffer *buffer)
+{
+	struct sk_buff *skb;
+	dma_addr_t dma;
+	struct pci_dev *pdev = adapter->pdev;
+
+	buffer->skb = dev_alloc_skb(rds_ring->skb_size);
+	if (!buffer->skb)
+		return 1;
+
+	skb = buffer->skb;
+
+	if (!adapter->ahw.cut_through)
+		skb_reserve(skb, 2);
+
+	dma = pci_map_single(pdev, skb->data,
+			rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+
+	if (pci_dma_mapping_error(dma)) {
+		dev_kfree_skb_any(skb);
+		buffer->skb = NULL;
+		return 1;
+	}
+
+	buffer->skb = skb;
+	buffer->dma = dma;
+	buffer->state = NETXEN_BUFFER_BUSY;
+
+	return 0;
+}
+
 static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
 		struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
 {
@@ -1197,169 +1215,140 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
 	skb->dev = adapter->netdev;
 
 	buffer->skb = NULL;
-
 no_skb:
 	buffer->state = NETXEN_BUFFER_FREE;
-	buffer->lro_current_frags = 0;
-	buffer->lro_expected_frags = 0;
-	list_add_tail(&buffer->list, &rds_ring->free_list);
 	return skb;
 }
 
-/*
- * netxen_process_rcv() send the received packet to the protocol stack.
- * and if the number of receives exceeds RX_BUFFERS_REFILL, then we
- * invoke the routine to send more rx buffers to the Phantom...
- */
-void
-netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
-		struct status_desc *desc, struct status_desc *frag_desc)
+static struct netxen_rx_buffer *
+netxen_process_rcv(struct netxen_adapter *adapter,
+		int ring, int index, int length, int cksum, int pkt_offset,
+		struct nx_host_sds_ring *sds_ring)
 {
 	struct net_device *netdev = adapter->netdev;
-	u64 sts_data = le64_to_cpu(desc->status_desc_data);
-	int index = netxen_get_sts_refhandle(sts_data);
-	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 	struct netxen_rx_buffer *buffer;
 	struct sk_buff *skb;
-	u32 length = netxen_get_sts_totallength(sts_data);
-	u32 desc_ctx;
-	u16 pkt_offset = 0, cksum;
-	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
 
-	desc_ctx = netxen_get_sts_type(sts_data);
-	if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
-		printk("%s: %s Bad Rcv descriptor ring\n",
-		       netxen_nic_driver_name, netdev->name);
-		return;
-	}
+	if (unlikely(index > rds_ring->num_desc))
+		return NULL;
 
-	rds_ring = &recv_ctx->rds_rings[desc_ctx];
-	if (unlikely(index > rds_ring->max_rx_desc_count)) {
-		DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
-			index, rds_ring->max_rx_desc_count);
-		return;
-	}
 	buffer = &rds_ring->rx_buf_arr[index];
-	if (desc_ctx == RCV_DESC_LRO_CTXID) {
-		buffer->lro_current_frags++;
-		if (netxen_get_sts_desc_lro_last_frag(desc)) {
-			buffer->lro_expected_frags =
-			    netxen_get_sts_desc_lro_cnt(desc);
-			buffer->lro_length = length;
-		}
-		if (buffer->lro_current_frags != buffer->lro_expected_frags) {
-			if (buffer->lro_expected_frags != 0) {
-				printk("LRO: (refhandle:%x) recv frag."
-				       "wait for last. flags: %x expected:%d"
-				       "have:%d\n", index,
-				       netxen_get_sts_desc_lro_last_frag(desc),
-				       buffer->lro_expected_frags,
-				       buffer->lro_current_frags);
-			}
-			return;
-		}
-	}
-
-	cksum = netxen_get_sts_status(sts_data);
 
 	skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
 	if (!skb)
-		return;
+		return buffer;
 
-	if (desc_ctx == RCV_DESC_LRO_CTXID) {
-		/* True length was only available on the last pkt */
-		skb_put(skb, buffer->lro_length);
-	} else {
-		if (length > rds_ring->skb_size)
-			skb_put(skb, rds_ring->skb_size);
-		else
-			skb_put(skb, length);
+	if (length > rds_ring->skb_size)
+		skb_put(skb, rds_ring->skb_size);
+	else
+		skb_put(skb, length);
 
-		pkt_offset = netxen_get_sts_pkt_offset(sts_data);
-		if (pkt_offset)
-			skb_pull(skb, pkt_offset);
-	}
+
+	if (pkt_offset)
+		skb_pull(skb, pkt_offset);
 
 	skb->protocol = eth_type_trans(skb, netdev);
 
-	/*
-	 * rx buffer chaining is disabled, walk and free
-	 * any spurious rx buffer chain.
-	 */
-	if (frag_desc) {
-		u16 i, nr_frags = desc->nr_frags;
+	napi_gro_receive(&sds_ring->napi, skb);
+	netdev->last_rx = jiffies;
 
-		dev_kfree_skb_any(skb);
-		for (i = 0; i < nr_frags; i++) {
-			index = le16_to_cpu(frag_desc->frag_handles[i]);
-			skb = netxen_process_rxbuf(adapter,
-					rds_ring, index, cksum);
-			if (skb)
-				dev_kfree_skb_any(skb);
-		}
-		adapter->stats.rxdropped++;
-	} else {
+	adapter->stats.no_rcv++;
+	adapter->stats.rxbytes += length;
 
-		napi_gro_receive(&adapter->napi, skb);
-		netdev->last_rx = jiffies;
-
-		adapter->stats.no_rcv++;
-		adapter->stats.rxbytes += length;
-	}
+	return buffer;
 }
 
-/* Process Receive status ring */
-u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+#define netxen_merge_rx_buffers(list, head) \
+	do { list_splice_tail_init(list, head); } while (0);
+
+int
+netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
 {
-	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
-	struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
-	struct status_desc *desc, *frag_desc;
-	u32 consumer = recv_ctx->status_rx_consumer;
-	int count = 0, ring;
+	struct netxen_adapter *adapter = sds_ring->adapter;
+
+	struct list_head *cur;
+
+	struct status_desc *desc;
+	struct netxen_rx_buffer *rxbuf;
+
+	u32 consumer = sds_ring->consumer;
+
+	int count = 0;
 	u64 sts_data;
-	u16 opcode;
+	int opcode, ring, index, length, cksum, pkt_offset, desc_cnt;
 
 	while (count < max) {
-		desc = &desc_head[consumer];
-		if (!
-		   ((netxen_get_sts_owner(le64_to_cpu(desc->status_desc_data)))
-			   & STATUS_OWNER_HOST)) {
-			DPRINTK(ERR, "desc %p ownedby %x\n", desc,
-				netxen_get_sts_owner(status_desc));
+		desc = &sds_ring->desc_head[consumer];
+		sts_data = le64_to_cpu(desc->status_desc_data[0]);
+
+		if (!(sts_data & STATUS_OWNER_HOST))
 			break;
-		}
 
-		sts_data = le64_to_cpu(desc->status_desc_data);
+		desc_cnt = netxen_get_sts_desc_cnt(sts_data);
+		ring   = netxen_get_sts_type(sts_data);
+
+		if (ring > RCV_RING_JUMBO)
+			goto skip;
+
 		opcode = netxen_get_sts_opcode(sts_data);
-		frag_desc = NULL;
-		if (opcode == NETXEN_NIC_RXPKT_DESC) {
-			if (desc->nr_frags) {
-				consumer = get_next_index(consumer,
-						adapter->max_rx_desc_count);
-				frag_desc = &desc_head[consumer];
-				netxen_set_sts_owner(frag_desc,
-						STATUS_OWNER_PHANTOM);
-			}
+
+		switch (opcode) {
+		case NETXEN_NIC_RXPKT_DESC:
+		case NETXEN_OLD_RXPKT_DESC:
+			break;
+		case NETXEN_NIC_RESPONSE_DESC:
+			netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
+		default:
+			goto skip;
 		}
 
-		netxen_process_rcv(adapter, ctxid, desc, frag_desc);
+		WARN_ON(desc_cnt > 1);
+
+		index  = netxen_get_sts_refhandle(sts_data);
+		length = netxen_get_sts_totallength(sts_data);
+		cksum  = netxen_get_sts_status(sts_data);
+		pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+
+		rxbuf = netxen_process_rcv(adapter, ring, index,
+				length, cksum, pkt_offset, sds_ring);
 
-		netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
+		if (rxbuf)
+			list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
 
-		consumer = get_next_index(consumer,
-				adapter->max_rx_desc_count);
+skip:
+		for (; desc_cnt > 0; desc_cnt--) {
+			desc = &sds_ring->desc_head[consumer];
+			desc->status_desc_data[0] =
+				cpu_to_le64(STATUS_OWNER_PHANTOM);
+			consumer = get_next_index(consumer, sds_ring->num_desc);
+		}
 		count++;
 	}
-	for (ring = 0; ring < adapter->max_rds_rings; ring++)
-		netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
 
-	/* update the consumer index in phantom */
-	if (count) {
-		recv_ctx->status_rx_consumer = consumer;
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		struct nx_host_rds_ring *rds_ring =
+			&adapter->recv_ctx.rds_rings[ring];
+
+		if (!list_empty(&sds_ring->free_list[ring])) {
+			list_for_each(cur, &sds_ring->free_list[ring]) {
+				rxbuf = list_entry(cur,
+						struct netxen_rx_buffer, list);
+				netxen_alloc_rx_skb(adapter, rds_ring, rxbuf);
+			}
+			spin_lock(&rds_ring->lock);
+			netxen_merge_rx_buffers(&sds_ring->free_list[ring],
+						&rds_ring->free_list);
+			spin_unlock(&rds_ring->lock);
+		}
+
+		netxen_post_rx_buffers_nodb(adapter, rds_ring);
+	}
 
-		/* Window = 1 */
-		adapter->pci_write_normalize(adapter,
-				recv_ctx->crb_sts_consumer, consumer);
+	if (count) {
+		sds_ring->consumer = consumer;
+		NXWR32(adapter, sds_ring->crb_sts_consumer, consumer);
 	}
 
 	return count;
@@ -1368,19 +1357,23 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
 /* Process Command status ring */
 int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 {
-	u32 last_consumer, consumer;
+	u32 sw_consumer, hw_consumer;
 	int count = 0, i;
 	struct netxen_cmd_buffer *buffer;
 	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
 	struct netxen_skb_frag *frag;
 	int done = 0;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
-	last_consumer = adapter->last_cmd_consumer;
-	consumer = le32_to_cpu(*(adapter->cmd_consumer));
+	if (!spin_trylock(&adapter->tx_clean_lock))
+		return 1;
 
-	while (last_consumer != consumer) {
-		buffer = &adapter->cmd_buf_arr[last_consumer];
+	sw_consumer = tx_ring->sw_consumer;
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+	while (sw_consumer != hw_consumer) {
+		buffer = &tx_ring->cmd_buf_arr[sw_consumer];
 		if (buffer->skb) {
 			frag = &buffer->frag_array[0];
 			pci_unmap_single(pdev, frag->dma, frag->length,
@@ -1398,20 +1391,21 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 			buffer->skb = NULL;
 		}
 
-		last_consumer = get_next_index(last_consumer,
-					       adapter->max_tx_desc_count);
+		sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
 		if (++count >= MAX_STATUS_HANDLE)
 			break;
 	}
 
-	if (count) {
-		adapter->last_cmd_consumer = last_consumer;
+	if (count && netif_running(netdev)) {
+		tx_ring->sw_consumer = sw_consumer;
+
 		smp_mb();
-		if (netif_queue_stopped(netdev) && netif_running(netdev)) {
-			netif_tx_lock(netdev);
-			netif_wake_queue(netdev);
-			smp_mb();
-			netif_tx_unlock(netdev);
+
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+			spin_lock(&tx_ring->lock);
+			if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+				netif_wake_queue(netdev);
+			spin_unlock(&tx_ring->lock);
 		}
 	}
 	/*
@@ -1427,75 +1421,53 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
 	 * There is still a possible race condition and the host could miss an
 	 * interrupt. The card has to take care of this.
 	 */
-	consumer = le32_to_cpu(*(adapter->cmd_consumer));
-	done = (last_consumer == consumer);
+	hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+	done = (sw_consumer == hw_consumer);
+	spin_unlock(&adapter->tx_clean_lock);
 
 	return (done);
 }
 
-/*
- * netxen_post_rx_buffers puts buffer in the Phantom memory
- */
-void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
+void
+netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
+	struct nx_host_rds_ring *rds_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	struct sk_buff *skb;
-	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-	struct nx_host_rds_ring *rds_ring = NULL;
-	uint producer;
 	struct rcv_desc *pdesc;
 	struct netxen_rx_buffer *buffer;
-	int count = 0;
+	int producer, count = 0;
 	netxen_ctx_msg msg = 0;
-	dma_addr_t dma;
 	struct list_head *head;
 
-	rds_ring = &recv_ctx->rds_rings[ringid];
-
 	producer = rds_ring->producer;
-	head = &rds_ring->free_list;
 
-	/* We can start writing rx descriptors into the phantom memory. */
+	spin_lock(&rds_ring->lock);
+	head = &rds_ring->free_list;
 	while (!list_empty(head)) {
 
-		skb = dev_alloc_skb(rds_ring->skb_size);
-		if (unlikely(!skb)) {
-			break;
-		}
-
-		if (!adapter->ahw.cut_through)
-			skb_reserve(skb, 2);
+		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
 
-		dma = pci_map_single(pdev, skb->data,
-				rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-		if (pci_dma_mapping_error(dma)) {
-			dev_kfree_skb_any(skb);
-			break;
+		if (!buffer->skb) {
+			if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
+				break;
 		}
 
 		count++;
-		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
 		list_del(&buffer->list);
 
-		buffer->skb = skb;
-		buffer->state = NETXEN_BUFFER_BUSY;
-		buffer->dma = dma;
-
 		/* make a rcv descriptor  */
 		pdesc = &rds_ring->desc_head[producer];
-		pdesc->addr_buffer = cpu_to_le64(dma);
+		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
 		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
 
-		producer = get_next_index(producer, rds_ring->max_rx_desc_count);
+		producer = get_next_index(producer, rds_ring->num_desc);
 	}
-	/* if we did allocate buffers, then write the count to Phantom */
+	spin_unlock(&rds_ring->lock);
+
 	if (count) {
 		rds_ring->producer = producer;
-			/* Window = 1 */
-		adapter->pci_write_normalize(adapter,
-				rds_ring->crb_rcv_producer,
-				(producer-1) & (rds_ring->max_rx_desc_count-1));
+		NXWR32(adapter, rds_ring->crb_rcv_producer,
+				(producer-1) & (rds_ring->num_desc-1));
 
 		if (adapter->fw_major < 4) {
 			/*
@@ -1506,9 +1478,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
 			netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
 			netxen_set_msg_privid(msg);
 			netxen_set_msg_count(msg,
-					     ((producer -
-					       1) & (rds_ring->
-						     max_rx_desc_count - 1)));
+					     ((producer - 1) &
+					      (rds_ring->num_desc - 1)));
 			netxen_set_msg_ctxid(msg, adapter->portnum);
 			netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
 			writel(msg,
@@ -1518,68 +1489,47 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
 	}
 }
 
-static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
-	uint32_t ctx, uint32_t ringid)
+static void
+netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+		struct nx_host_rds_ring *rds_ring)
 {
-	struct pci_dev *pdev = adapter->pdev;
-	struct sk_buff *skb;
-	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-	struct nx_host_rds_ring *rds_ring = NULL;
-	u32 producer;
 	struct rcv_desc *pdesc;
 	struct netxen_rx_buffer *buffer;
-	int count = 0;
+	int producer, count = 0;
 	struct list_head *head;
-	dma_addr_t dma;
-
-	rds_ring = &recv_ctx->rds_rings[ringid];
 
 	producer = rds_ring->producer;
+	if (!spin_trylock(&rds_ring->lock))
+		return;
+
 	head = &rds_ring->free_list;
-	/* We can start writing rx descriptors into the phantom memory. */
 	while (!list_empty(head)) {
 
-		skb = dev_alloc_skb(rds_ring->skb_size);
-		if (unlikely(!skb)) {
-			break;
-		}
-
-		if (!adapter->ahw.cut_through)
-			skb_reserve(skb, 2);
+		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
 
-		dma = pci_map_single(pdev, skb->data,
-				rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-		if (pci_dma_mapping_error(dma)) {
-			dev_kfree_skb_any(skb);
-			break;
+		if (!buffer->skb) {
+			if (netxen_alloc_rx_skb(adapter, rds_ring, buffer))
+				break;
 		}
 
 		count++;
-		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
 		list_del(&buffer->list);
 
-		buffer->skb = skb;
-		buffer->state = NETXEN_BUFFER_BUSY;
-		buffer->dma = dma;
-
 		/* make a rcv descriptor  */
 		pdesc = &rds_ring->desc_head[producer];
 		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
 		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
 
-		producer = get_next_index(producer, rds_ring->max_rx_desc_count);
+		producer = get_next_index(producer, rds_ring->num_desc);
 	}
 
-	/* if we did allocate buffers, then write the count to Phantom */
 	if (count) {
 		rds_ring->producer = producer;
-			/* Window = 1 */
-		adapter->pci_write_normalize(adapter,
-			rds_ring->crb_rcv_producer,
-				(producer-1) & (rds_ring->max_rx_desc_count-1));
-			wmb();
+		NXWR32(adapter, rds_ring->crb_rcv_producer,
+				(producer - 1) & (rds_ring->num_desc - 1));
 	}
+	spin_unlock(&rds_ring->lock);
 }
 
 void netxen_nic_clear_stats(struct netxen_adapter *adapter)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 05a3396..7f88089 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,17 +22,14 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- *  Main source file for NetXen NIC Driver on Linux
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
 #include <linux/vmalloc.h>
-#include <linux/highmem.h>
+#include <linux/interrupt.h>
 #include "netxen_nic_hw.h"
 
 #include "netxen_nic.h"
@@ -63,9 +60,6 @@ static int use_msi_x = 1;
 
 u8 nx_p2_id = NX_P2_C0;
 
-#define DMA_32BIT_MASK	0x00000000ffffffffULL
-#define DMA_35BIT_MASK	0x00000007ffffffffULL
-
 /* Local functions to NetXen NIC driver */
 static int __devinit netxen_nic_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
@@ -104,24 +98,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
 
-/*
- * In netxen_nic_down(), we must wait for any pending callback requests into
- * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be
- * reenabled right after it is deleted in netxen_nic_down().
- * FLUSH_SCHEDULED_WORK()  does this synchronization.
- *
- * Normally, schedule_work()/flush_scheduled_work() could have worked, but
- * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off()
- * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a
- * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause
- * linkwatch_event() to be executed which also attempts to acquire the rtnl
- * lock thus causing a deadlock.
- */
-
-static struct workqueue_struct *netxen_workq;
-#define SCHEDULE_WORK(tp)	queue_work(netxen_workq, tp)
-#define FLUSH_SCHEDULED_WORK()	flush_workqueue(netxen_workq)
-
 static void netxen_watchdog(unsigned long);
 
 static uint32_t crb_cmd_producer[4] = {
@@ -131,10 +107,14 @@ static uint32_t crb_cmd_producer[4] = {
 
 void
 netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
-		uint32_t crb_producer)
+		struct nx_host_tx_ring *tx_ring)
 {
-	adapter->pci_write_normalize(adapter,
-			adapter->crb_addr_cmd_producer, crb_producer);
+	NXWR32(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
+
+	if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
+		netif_stop_queue(adapter->netdev);
+		smp_mb();
+	}
 }
 
 static uint32_t crb_cmd_consumer[4] = {
@@ -144,10 +124,9 @@ static uint32_t crb_cmd_consumer[4] = {
 
 static inline void
 netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
-		u32 crb_consumer)
+		struct nx_host_tx_ring *tx_ring)
 {
-	adapter->pci_write_normalize(adapter,
-			adapter->crb_addr_cmd_consumer, crb_consumer);
+	NXWR32(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer);
 }
 
 static uint32_t msi_tgt_status[8] = {
@@ -159,130 +138,216 @@ static uint32_t msi_tgt_status[8] = {
 
 static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
 
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring)
 {
-	adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0);
+	struct netxen_adapter *adapter = sds_ring->adapter;
+
+	NXWR32(adapter, sds_ring->crb_intr_mask, 0);
 }
 
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring)
 {
-	adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
+	struct netxen_adapter *adapter = sds_ring->adapter;
+
+	NXWR32(adapter, sds_ring->crb_intr_mask, 0x1);
 
 	if (!NETXEN_IS_MSI_FAMILY(adapter))
 		adapter->pci_write_immediate(adapter,
 				adapter->legacy_intr.tgt_mask_reg, 0xfbff);
 }
 
-static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+static int
+netxen_alloc_sds_rings(struct netxen_recv_context *recv_ctx, int count)
+{
+	int size = sizeof(struct nx_host_sds_ring) * count;
+
+	recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL);
+
+	return (recv_ctx->sds_rings == NULL);
+}
+
+static void
+netxen_free_sds_rings(struct netxen_recv_context *recv_ctx)
+{
+	if (recv_ctx->sds_rings != NULL)
+		kfree(recv_ctx->sds_rings);
+
+	recv_ctx->sds_rings = NULL;
+}
+
+static int
+netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+		return 1;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		sds_ring->adapter = adapter;
+		sds_ring->napi_dev = alloc_netdev(0, "", ether_setup);
+		sds_ring->napi_dev->priv = sds_ring;
+		sds_ring->napi_dev->weight = NETXEN_NETDEV_WEIGHT;
+		sds_ring->napi_dev->poll = netxen_nic_poll;
+		set_bit(__LINK_STATE_START, &sds_ring->napi_dev->state);
+	}
+
+	return 0;
+}
+
+static void
+netxen_napi_del(struct netxen_adapter *adapter)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	for (ring = 1; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+
+		if (sds_ring->napi_dev) {
+			free_netdev(sds_ring->napi_dev);
+			sds_ring->napi_dev = NULL;
+		}
+	}
+
+	netxen_free_sds_rings(&adapter->recv_ctx);
+}
+
+static void
+netxen_napi_enable(struct netxen_adapter *adapter)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		netif_poll_enable(sds_ring->napi_dev);
+		netxen_nic_enable_int(sds_ring);
+	}
+}
+
+static void
+netxen_napi_disable(struct netxen_adapter *adapter)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		netxen_nic_disable_int(sds_ring);
+		synchronize_irq(sds_ring->irq);
+		netif_poll_disable(sds_ring->napi_dev);
+	}
+}
+
+static int nx_set_dma_mask(struct netxen_adapter *adapter)
 {
 	struct pci_dev *pdev = adapter->pdev;
-	int err;
-	uint64_t mask;
-
-#ifdef CONFIG_IA64
-	adapter->dma_mask = DMA_32BIT_MASK;
-#else
-	if (revision_id >= NX_P3_B0) {
-		/* should go to DMA_64BIT_MASK */
-		adapter->dma_mask = DMA_39BIT_MASK;
-		mask = DMA_39BIT_MASK;
-	} else if (revision_id == NX_P3_A2) {
-		adapter->dma_mask = DMA_39BIT_MASK;
-		mask = DMA_39BIT_MASK;
-	} else if (revision_id == NX_P2_C1) {
-		adapter->dma_mask = DMA_35BIT_MASK;
-		mask = DMA_35BIT_MASK;
+	uint64_t mask, cmask;
+
+	adapter->pci_using_dac = 0;
+
+	mask = DMA_BIT_MASK(32);
+	cmask = DMA_BIT_MASK(32);
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+#ifndef CONFIG_IA64
+		mask = DMA_BIT_MASK(35);
+#endif
 	} else {
-		adapter->dma_mask = DMA_32BIT_MASK;
-		mask = DMA_32BIT_MASK;
-		goto set_32_bit_mask;
+		mask = DMA_BIT_MASK(39);
+		cmask = mask;
 	}
 
-	/*
-	 * Consistent DMA mask is set to 32 bit because it cannot be set to
-	 * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
-	 * come off this pool.
-	 */
 	if (pci_set_dma_mask(pdev, mask) == 0 &&
-		pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) {
+		pci_set_consistent_dma_mask(pdev, cmask) == 0) {
 		adapter->pci_using_dac = 1;
 		return 0;
 	}
-set_32_bit_mask:
-#endif /* CONFIG_IA64 */
 
-	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-	if (err) {
-		DPRINTK(ERR, "No usable DMA configuration, aborting:%d\n", err);
-		return err;
-	}
-
-	adapter->pci_using_dac = 0;
-	return 0;
+	return -EIO;
 }
 
-static void netxen_check_options(struct netxen_adapter *adapter)
+/* Update addressable range if firmware supports it */
+static int
+nx_update_dma_mask(struct netxen_adapter *adapter)
 {
-	switch (adapter->ahw.boardcfg.board_type) {
-	case NETXEN_BRDTYPE_P3_HMEZ:
-	case NETXEN_BRDTYPE_P3_XG_LOM:
-	case NETXEN_BRDTYPE_P3_10G_CX4:
-	case NETXEN_BRDTYPE_P3_10G_CX4_LP:
-	case NETXEN_BRDTYPE_P3_IMEZ:
-	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
-	case NETXEN_BRDTYPE_P3_10G_SFP_QT:
-	case NETXEN_BRDTYPE_P3_10G_SFP_CT:
-	case NETXEN_BRDTYPE_P3_10G_XFP:
-	case NETXEN_BRDTYPE_P3_10000_BASE_T:
-		adapter->msix_supported = !!use_msi_x;
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-		break;
+	int change, shift, err;
+	uint64_t mask, old_mask, old_cmask;
+	struct pci_dev *pdev = adapter->pdev;
 
-	case NETXEN_BRDTYPE_P2_SB31_10G:
-	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
-	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
-	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
-		adapter->msix_supported = 0;
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-		break;
+	change = 0;
 
-	case NETXEN_BRDTYPE_P3_REF_QG:
-	case NETXEN_BRDTYPE_P3_4_GB:
-	case NETXEN_BRDTYPE_P3_4_GB_MM:
-		adapter->msix_supported = 0;
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-		break;
+	shift = NXRD32(adapter, CRB_DMA_SHIFT);
+	if (shift > 32)
+		return 0;
 
-	case NETXEN_BRDTYPE_P2_SB35_4G:
-	case NETXEN_BRDTYPE_P2_SB31_2G:
-		adapter->msix_supported = 0;
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-		break;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9))
+		change = 1;
+	else if ((adapter->ahw.revision_id == NX_P2_C1) && (shift <= 4))
+		change = 1;
 
-	case NETXEN_BRDTYPE_P3_10G_TP:
-		adapter->msix_supported = !!use_msi_x;
-		if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
-			adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-		else
-			adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-		break;
+	if (change) {
+		old_mask = pdev->dma_mask;
+		old_cmask = pdev->dev.coherent_dma_mask;
 
-	default:
-		adapter->msix_supported = 0;
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+		mask = DMA_BIT_MASK(32+shift);
 
-		printk(KERN_WARNING "Unknown board type(0x%x)\n",
-				adapter->ahw.boardcfg.board_type);
-		break;
+		err = pci_set_dma_mask(pdev, mask);
+		if (err)
+			goto err_out;
+
+		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+
+			err = pci_set_consistent_dma_mask(pdev, mask);
+			if (err)
+				goto err_out;
+		}
+		dev_info(&pdev->dev, "using %d-bit dma mask\n", 32+shift);
+	}
+
+	return 0;
+
+err_out:
+	pci_set_dma_mask(pdev, old_mask);
+	pci_set_consistent_dma_mask(pdev, old_cmask);
+	return err;
+}
+
+static void netxen_check_options(struct netxen_adapter *adapter)
+{
+	if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
+		adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G;
+	else if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+		adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G;
+
+	adapter->msix_supported = 0;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		adapter->msix_supported = !!use_msi_x;
+		adapter->rss_supported = !!use_msi_x;
+	} else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) {
+		switch (adapter->ahw.board_type) {
+		case NETXEN_BRDTYPE_P2_SB31_10G:
+		case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+			adapter->msix_supported = !!use_msi_x;
+			adapter->rss_supported = !!use_msi_x;
+			break;
+		default:
+			break;
+		}
 	}
 
-	adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
-	adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
-	adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
+	adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST;
+	adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
+	adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
 
-	adapter->max_possible_rss_rings = 1;
 	return;
 }
 
@@ -293,43 +358,34 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
 
 	if (first_boot == 0x55555555) {
 		/* This is the first boot after power up */
-		adapter->pci_write_normalize(adapter,
-			NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+		NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
 
 		if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
 			return 0;
 
 		/* PCI bus master workaround */
-		adapter->hw_read_wx(adapter,
-			NETXEN_PCIE_REG(0x4), &first_boot, 4);
+		first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4));
 		if (!(first_boot & 0x4)) {
 			first_boot |= 0x4;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PCIE_REG(0x4), &first_boot, 4);
-			adapter->hw_read_wx(adapter,
-				NETXEN_PCIE_REG(0x4), &first_boot, 4);
+			NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot);
+			first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4));
 		}
 
 		/* This is the first boot after power up */
-		adapter->hw_read_wx(adapter,
-			NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+		first_boot = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET);
 		if (first_boot != 0x80000f) {
 			/* clear the register for future unloads/loads */
-			adapter->pci_write_normalize(adapter,
-					NETXEN_CAM_RAM(0x1fc), 0);
+			NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), 0);
 			return -EIO;
 		}
 
 		/* Start P2 boot loader */
-		val = adapter->pci_read_normalize(adapter,
-				NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
-		adapter->pci_write_normalize(adapter,
-				NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
+		val = NXRD32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
+		NXWR32(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
 		timeout = 0;
 		do {
 			msleep(1);
-			val = adapter->pci_read_normalize(adapter,
-					NETXEN_CAM_RAM(0x1fc));
+			val = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
 
 			if (++timeout > 5000)
 				return -EIO;
@@ -343,29 +399,24 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter)
 {
 	u32 val, data;
 
-	val = adapter->ahw.boardcfg.board_type;
+	val = adapter->ahw.board_type;
 	if ((val == NETXEN_BRDTYPE_P3_HMEZ) ||
 		(val == NETXEN_BRDTYPE_P3_XG_LOM)) {
 		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
 			data = NETXEN_PORT_MODE_802_3_AP;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_XG) {
 			data = NETXEN_PORT_MODE_XG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
 			data = NETXEN_PORT_MODE_AUTO_NEG_1G;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
 			data = NETXEN_PORT_MODE_AUTO_NEG_XG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		} else {
 			data = NETXEN_PORT_MODE_AUTO_NEG;
-			adapter->hw_write_wx(adapter,
-				NETXEN_PORT_MODE_ADDR, &data, 4);
+			NXWR32(adapter, NETXEN_PORT_MODE_ADDR, data);
 		}
 
 		if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
@@ -374,8 +425,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter)
 			(wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
 			wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
 		}
-		adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
-			&wol_port_mode, 4);
+		NXWR32(adapter, NETXEN_WOL_PORT_MODE, wol_port_mode);
 	}
 }
 
@@ -395,11 +445,11 @@ static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
 	}
 }
 
-static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+static void netxen_init_msix_entries(struct netxen_adapter *adapter, int count)
 {
 	int i;
 
-	for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+	for (i = 0; i < count; i++)
 		adapter->msix_entries[i].entry = i;
 }
 
@@ -411,9 +461,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
 	__le64 mac_addr;
 	struct net_device *netdev = adapter->netdev;
 
-	if (netxen_is_flash_supported(adapter) != 0)
-		return -EIO;
-
 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
 		if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0)
 			return -EIO;
@@ -430,7 +477,7 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
 
 	/* set station address */
 
-	if (!is_valid_ether_addr(netdev->perm_addr)) {
+	if (!is_valid_ether_addr(netdev->perm_addr))
 		dev_warn(&adapter->pdev->dev, "%s: Bad MAC address "
 			"%02x:%02x:%02x:%02x:%02x:%02x.\n",
 			netxen_nic_driver_name,
@@ -440,101 +487,144 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
 			netdev->dev_addr[3],
 			netdev->dev_addr[4],
 			netdev->dev_addr[5]);
-	} else
-		adapter->macaddr_set(adapter, netdev->dev_addr);
 
 	return 0;
 }
 
-/*
- * netxen_nic_probe()
- *
- * The Linux system will invoke this after identifying the vendor ID and
- * device Id in the pci_tbl supported by this module.
- *
- * A quad port card has one operational PCI config space, (function 0),
- * which is used to access all four ports.
- *
- * This routine will initialize the adapter, and setup the global parameters
- * along with the port's specific structure.
- */
-static int __devinit
-netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+int netxen_nic_set_mac(struct net_device *netdev, void *p)
 {
-	struct net_device *netdev = NULL;
-	struct netxen_adapter *adapter = NULL;
-	void __iomem *mem_ptr0 = NULL;
-	void __iomem *mem_ptr1 = NULL;
-	void __iomem *mem_ptr2 = NULL;
-	unsigned long first_page_group_end;
-	unsigned long first_page_group_start;
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
 
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
 
-	u8 __iomem *db_ptr = NULL;
-	unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0;
-	int i = 0, err;
-	int first_driver, first_boot;
-	u32 val;
-	int pci_func_id = PCI_FUNC(pdev->devfn);
-	struct netxen_legacy_intr_set *legacy_intrp;
-	uint8_t revision_id;
+	if (netif_running(netdev)) {
+		netif_device_detach(netdev);
+		netxen_napi_disable(adapter);
+	}
 
-	if (pci_func_id == 0)
-		printk(KERN_INFO "%s\n", netxen_nic_driver_string);
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	adapter->macaddr_set(adapter, addr->sa_data);
 
-	if (pdev->class != 0x020000) {
-		printk(KERN_DEBUG "NetXen function %d, class %x will not "
-				"be enabled.\n",pci_func_id, pdev->class);
-		return -ENODEV;
+	if (netif_running(netdev)) {
+		netif_device_attach(netdev);
+		netxen_napi_enable(adapter);
 	}
+	return 0;
+}
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
-	revision_id = nx_p2_id;
+static void netxen_set_multicast_list(struct net_device *dev)
+{
+	struct netxen_adapter *adapter = netdev_priv(dev);
 
-	if ((revision_id >= NX_P3_A0) && (revision_id < NX_P3_B1)) {
-		printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x"
-				"will not be enabled.\n",
-				NX_P3_A0, NX_P3_B1);
-		return -ENODEV;
-	}
+	adapter->set_multi(dev);
+}
 
-	if ((err = pci_enable_device(pdev)))
-		return err;
+static void
+netxen_setup_intr(struct netxen_adapter *adapter)
+{
+	struct netxen_legacy_intr_set *legacy_intrp;
+	struct pci_dev *pdev = adapter->pdev;
+	int err, num_msix;
 
-	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		err = -ENODEV;
-		goto err_out_disable_pdev;
-	}
+	if (adapter->rss_supported) {
+		num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
+			MSIX_ENTRIES_PER_ADAPTER : 2;
+	} else
+		num_msix = 1;
 
-	if ((err = pci_request_regions(pdev, netxen_nic_driver_name)))
-		goto err_out_disable_pdev;
+	adapter->max_sds_rings = 1;
 
-	pci_set_master(pdev);
+	adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
 
-	netdev = alloc_etherdev(sizeof(struct netxen_adapter));
-	if(!netdev) {
-		printk(KERN_ERR"%s: Failed to allocate memory for the "
-				"device block.Check system memory resource"
-				" usage.\n", netxen_nic_driver_name);
-		goto err_out_free_res;
+	if (adapter->ahw.revision_id >= NX_P3_B0)
+		legacy_intrp = &legacy_intr[adapter->ahw.pci_func];
+	else
+		legacy_intrp = &legacy_intr[0];
+	adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
+	adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
+	adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
+	adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
+
+	netxen_set_msix_bit(pdev, 0);
+
+	if (adapter->msix_supported) {
+
+		netxen_init_msix_entries(adapter, num_msix);
+		err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
+		if (err == 0) {
+			adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+			netxen_set_msix_bit(pdev, 1);
+
+			if (adapter->rss_supported)
+				adapter->max_sds_rings = num_msix;
+
+			dev_info(&pdev->dev, "using msi-x interrupts\n");
+			return;
+		}
+
+		if (err > 0)
+			pci_disable_msix(pdev);
+
+		/* fall through for msi */
 	}
 
-	SET_MODULE_OWNER(netdev);
-	SET_NETDEV_DEV(netdev, &pdev->dev);
+	if (use_msi && !pci_enable_msi(pdev)) {
+		adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+		adapter->msi_tgt_status =
+			msi_tgt_status[adapter->ahw.pci_func];
+		dev_info(&pdev->dev, "using msi interrupts\n");
+		adapter->msix_entries[0].vector = pdev->irq;
+		return;
+	}
 
- 	adapter = netdev_priv(netdev);
-	memset(adapter, 0 , sizeof(struct netxen_adapter));
+	dev_info(&pdev->dev, "using legacy interrupts\n");
+	adapter->msix_entries[0].vector = pdev->irq;
+}
 
-	adapter->netdev  = netdev;
-	adapter->pdev    = pdev;
-	adapter->ahw.pci_func  = pci_func_id;
-	adapter->ahw.revision_id = revision_id;
+static void
+netxen_teardown_intr(struct netxen_adapter *adapter)
+{
+	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+		pci_disable_msix(adapter->pdev);
+	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+		pci_disable_msi(adapter->pdev);
+}
 
-	err = nx_set_dma_mask(adapter, revision_id);
-	if (err)
-		goto err_out_free_netdev;
+static void
+netxen_cleanup_pci_map(struct netxen_adapter *adapter)
+{
+	if (adapter->ahw.db_base != NULL)
+		iounmap(adapter->ahw.db_base);
+	if (adapter->ahw.pci_base0 != NULL)
+		iounmap(adapter->ahw.pci_base0);
+	if (adapter->ahw.pci_base1 != NULL)
+		iounmap(adapter->ahw.pci_base1);
+	if (adapter->ahw.pci_base2 != NULL)
+		iounmap(adapter->ahw.pci_base2);
+}
 
-	rwlock_init(&adapter->adapter_lock);
+static int
+netxen_setup_pci_map(struct netxen_adapter *adapter)
+{
+	void __iomem *mem_ptr0 = NULL;
+	void __iomem *mem_ptr1 = NULL;
+	void __iomem *mem_ptr2 = NULL;
+	void __iomem *db_ptr = NULL;
+
+	unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0;
+
+	struct pci_dev *pdev = adapter->pdev;
+	int pci_func = adapter->ahw.pci_func;
+
+	int err = 0;
+
+	/*
+	 * Set the CRB window to invalid. If any register in window 0 is
+	 * accessed it should set the window to 0 and then reset it to 1.
+	 */
+	adapter->curr_window = 255;
 	adapter->ahw.qdr_sn_window = -1;
 	adapter->ahw.ddr_mn_window = -1;
 
@@ -547,8 +637,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	adapter->hw_read_wx = netxen_nic_hw_read_wx_128M;
 	adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M;
 	adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M;
-	adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M;
-	adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M;
 	adapter->pci_set_window = netxen_nic_pci_set_window_128M;
 	adapter->pci_mem_read = netxen_nic_pci_mem_read_128M;
 	adapter->pci_mem_write = netxen_nic_pci_mem_write_128M;
@@ -560,23 +648,16 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 				SECOND_PAGE_GROUP_SIZE);
 		mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START,
 				THIRD_PAGE_GROUP_SIZE);
-		first_page_group_start = FIRST_PAGE_GROUP_START;
-		first_page_group_end   = FIRST_PAGE_GROUP_END;
 	} else if (mem_len == NETXEN_PCI_32MB_SIZE) {
 		mem_ptr1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE);
 		mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START -
 			SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
-		first_page_group_start = 0;
-		first_page_group_end   = 0;
 	} else if (mem_len == NETXEN_PCI_2MB_SIZE) {
 		adapter->hw_write_wx = netxen_nic_hw_write_wx_2M;
 		adapter->hw_read_wx = netxen_nic_hw_read_wx_2M;
 		adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M;
 		adapter->pci_write_immediate =
 			netxen_nic_pci_write_immediate_2M;
-		adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M;
-		adapter->pci_write_normalize =
-			netxen_nic_pci_write_normalize_2M;
 		adapter->pci_set_window = netxen_nic_pci_set_window_2M;
 		adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
 		adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
@@ -586,30 +667,31 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			dev_err(&pdev->dev, "failed to map PCI bar 0\n");
 			return -EIO;
 		}
-
 		pci_len0 = mem_len;
-		first_page_group_start = 0;
-		first_page_group_end   = 0;
 
 		adapter->ahw.ddr_mn_window = 0;
 		adapter->ahw.qdr_sn_window = 0;
 
 		adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
-			(pci_func_id * 0x20);
+			(pci_func * 0x20);
 		adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW;
-		if (pci_func_id < 4)
-			adapter->ahw.ms_win_crb += (pci_func_id * 0x20);
+		if (pci_func < 4)
+			adapter->ahw.ms_win_crb += (pci_func * 0x20);
 		else
 			adapter->ahw.ms_win_crb +=
-					0xA0 + ((pci_func_id - 4) * 0x10);
+					0xA0 + ((pci_func - 4) * 0x10);
 	} else {
-		err = -EIO;
-		goto err_out_free_netdev;
+		return -EIO;
 	}
 
 	dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
 
-	if (NX_IS_REVISION_P3(revision_id))
+	adapter->ahw.pci_base0 = mem_ptr0;
+	adapter->ahw.pci_len0 = pci_len0;
+	adapter->ahw.pci_base1 = mem_ptr1;
+	adapter->ahw.pci_base2 = mem_ptr2;
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
 		goto skip_doorbell;
 
 	db_base = pci_resource_start(pdev, 4);	/* doorbell is on bar 4 */
@@ -619,7 +701,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		printk(KERN_ERR "%s: doorbell is disabled\n",
 				netxen_nic_driver_name);
 		err = -EIO;
-		goto err_out_iounmap;
+		goto err_out;
 	}
 
 	db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
@@ -627,36 +709,354 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		printk(KERN_ERR "%s: Failed to allocate doorbell map.",
 				netxen_nic_driver_name);
 		err = -EIO;
-		goto err_out_iounmap;
+		goto err_out;
 	}
 
 skip_doorbell:
-	adapter->ahw.pci_base0 = mem_ptr0;
-	adapter->ahw.pci_len0 = pci_len0;
-	adapter->ahw.first_page_group_start = first_page_group_start;
-	adapter->ahw.first_page_group_end   = first_page_group_end;
-	adapter->ahw.pci_base1 = mem_ptr1;
-	adapter->ahw.pci_base2 = mem_ptr2;
 	adapter->ahw.db_base = db_ptr;
 	adapter->ahw.db_len = db_len;
+	return 0;
 
-	if (revision_id >= NX_P3_B0)
-		legacy_intrp = &legacy_intr[pci_func_id];
+err_out:
+	netxen_cleanup_pci_map(adapter);
+	return err;
+}
+
+static int
+netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
+{
+	int val, err, first_boot;
+	struct pci_dev *pdev = adapter->pdev;
+
+	int first_driver = 0;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		first_driver = (adapter->portnum == 0);
 	else
-		legacy_intrp = &legacy_intr[0];
+		first_driver = (adapter->ahw.pci_func == 0);
 
-	adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
-	adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
-	adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
-	adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
+	if (!first_driver)
+		goto wait_init;
+
+	first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
+
+	err = netxen_check_hw_init(adapter, first_boot);
+	if (err) {
+		dev_err(&pdev->dev, "error in init HW init sequence\n");
+		return err;
+	}
 
-	/* this will be read from FW later */
-	adapter->intr_scheme = -1;
-	adapter->msi_mode = -1;
+	if (request_fw)
+		netxen_request_firmware(adapter);
+
+	err = netxen_need_fw_reset(adapter);
+	if (err <= 0)
+		return err;
+
+	if (first_boot != 0x55555555) {
+		NXWR32(adapter, CRB_CMDPEG_STATE, 0);
+		netxen_pinit_from_rom(adapter, 0);
+		msleep(1);
+	}
+
+	NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555);
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		netxen_set_port_mode(adapter);
+
+	netxen_load_firmware(adapter);
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+
+		/* Initialize multicast addr pool owners */
+		val = 0x7654;
+		if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
+			val |= 0x0f000000;
+		NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val);
+
+	}
+
+	err = netxen_initialize_adapter_offload(adapter);
+	if (err)
+		return err;
+
+	/*
+	 * Tell the hardware our version number.
+	 */
+	val = (_NETXEN_NIC_LINUX_MAJOR << 16)
+		| ((_NETXEN_NIC_LINUX_MINOR << 8))
+		| (_NETXEN_NIC_LINUX_SUBVERSION);
+	NXWR32(adapter, CRB_DRIVER_VERSION, val);
+
+wait_init:
+	/* Handshake with the card before we register the devices. */
+	err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+	if (err) {
+		netxen_free_adapter_offload(adapter);
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+netxen_nic_request_irq(struct netxen_adapter *adapter)
+{
+	irq_handler_t handler;
+	struct nx_host_sds_ring *sds_ring;
+	int err, ring;
+
+	unsigned long flags = IRQF_SAMPLE_RANDOM;
+	struct net_device *netdev = adapter->netdev;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+		handler = netxen_msix_intr;
+	else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+		handler = netxen_msi_intr;
+	else {
+		flags |= IRQF_SHARED;
+		handler = netxen_intr;
+	}
+	adapter->irq = netdev->irq;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		sprintf(sds_ring->name, "%s[%d]", netdev->name, ring);
+		err = request_irq(sds_ring->irq, handler,
+				  flags, sds_ring->name, sds_ring);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static void
+netxen_nic_free_irq(struct netxen_adapter *adapter)
+{
+	int ring;
+	struct nx_host_sds_ring *sds_ring;
+
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &recv_ctx->sds_rings[ring];
+		free_irq(sds_ring->irq, sds_ring);
+	}
+}
+
+static int
+netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+	int err;
+
+	err = adapter->init_port(adapter, adapter->physical_port);
+	if (err) {
+		printk(KERN_ERR "%s: Failed to initialize port %d\n",
+				netxen_nic_driver_name, adapter->portnum);
+		return err;
+	}
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		adapter->macaddr_set(adapter, netdev->dev_addr);
+
+	adapter->set_multi(netdev);
+	adapter->set_mtu(adapter, netdev->mtu);
+
+	adapter->ahw.linkup = 0;
+
+	if (adapter->max_sds_rings > 1)
+		netxen_config_rss(adapter, 1);
+
+	netxen_napi_enable(adapter);
+
+	if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
+		netxen_linkevent_request(adapter, 1);
+	else
+		netxen_nic_set_link_parameters(adapter);
+
+	mod_timer(&adapter->watchdog_timer, jiffies);
+
+	return 0;
+}
+
+static void
+netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+	spin_lock(&adapter->tx_clean_lock);
+	netif_carrier_off(netdev);
+	netif_tx_disable(netdev);
+
+	if (adapter->stop_port)
+		adapter->stop_port(adapter);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		netxen_p3_free_mac_list(adapter);
+
+	netxen_napi_disable(adapter);
+
+	netxen_release_tx_buffers(adapter);
+	spin_unlock(&adapter->tx_clean_lock);
+
+	del_timer_sync(&adapter->watchdog_timer);
+}
+
+
+static int
+netxen_nic_attach(struct netxen_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+	int err, ring;
+	struct nx_host_rds_ring *rds_ring;
+	struct nx_host_tx_ring *tx_ring;
+
+	err = netxen_init_firmware(adapter);
+	if (err)
+		return err;
+
+	err = netxen_napi_add(adapter, netdev);
+	if (err)
+		return err;
+
+	if (adapter->fw_major < 4)
+		adapter->max_rds_rings = 3;
+	else
+		adapter->max_rds_rings = 2;
+
+	err = netxen_alloc_sw_resources(adapter);
+	if (err) {
+		printk(KERN_ERR "%s: Error in setting sw resources\n",
+				netdev->name);
+		return err;
+	}
+
+	netxen_nic_clear_stats(adapter);
+
+	err = netxen_alloc_hw_resources(adapter);
+	if (err) {
+		printk(KERN_ERR "%s: Error in setting hw resources\n",
+				netdev->name);
+		goto err_out_free_sw;
+	}
+
+	if (adapter->fw_major < 4) {
+		tx_ring = adapter->tx_ring;
+		tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
+		tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
+
+		tx_ring->producer = 0;
+		tx_ring->sw_consumer = 0;
+
+		netxen_nic_update_cmd_producer(adapter, tx_ring);
+		netxen_nic_update_cmd_consumer(adapter, tx_ring);
+	}
+
+	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+		rds_ring = &adapter->recv_ctx.rds_rings[ring];
+		netxen_post_rx_buffers(adapter, ring, rds_ring);
+	}
+
+	err = netxen_nic_request_irq(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "%s: failed to setup interrupt\n",
+				netdev->name);
+		goto err_out_free_rxbuf;
+	}
+
+	adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+	return 0;
+
+err_out_free_rxbuf:
+	netxen_release_rx_buffers(adapter);
+	netxen_free_hw_resources(adapter);
+err_out_free_sw:
+	netxen_free_sw_resources(adapter);
+	return err;
+}
+
+static void
+netxen_nic_detach(struct netxen_adapter *adapter)
+{
+	netxen_free_hw_resources(adapter);
+	netxen_release_rx_buffers(adapter);
+	netxen_nic_free_irq(adapter);
+	netxen_napi_del(adapter);
+	netxen_free_sw_resources(adapter);
+
+	adapter->is_up = 0;
+}
+
+static int __devinit
+netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *netdev = NULL;
+	struct netxen_adapter *adapter = NULL;
+	int i = 0, err;
+	int pci_func_id = PCI_FUNC(pdev->devfn);
+	uint8_t revision_id;
+
+	if (pdev->class != 0x020000) {
+		printk(KERN_DEBUG "NetXen function %d, class %x will not "
+				"be enabled.\n",pci_func_id, pdev->class);
+		return -ENODEV;
+	}
+
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
+	revision_id = nx_p2_id;
+
+	if ((revision_id >= NX_P3_A0) && (revision_id < NX_P3_B1)) {
+		printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x"
+				"will not be enabled.\n",
+				NX_P3_A0, NX_P3_B1);
+		return -ENODEV;
+	}
+
+	if ((err = pci_enable_device(pdev)))
+		return err;
+
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		err = -ENODEV;
+		goto err_out_disable_pdev;
+	}
+
+	if ((err = pci_request_regions(pdev, netxen_nic_driver_name)))
+		goto err_out_disable_pdev;
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct netxen_adapter));
+	if(!netdev) {
+		printk(KERN_ERR"%s: Failed to allocate memory for the "
+				"device block.Check system memory resource"
+				" usage.\n", netxen_nic_driver_name);
+		goto err_out_free_res;
+	}
+
+	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ 	adapter = netdev_priv(netdev);
+	memset(adapter, 0 , sizeof(struct netxen_adapter));
+
+	adapter->netdev  = netdev;
+	adapter->pdev    = pdev;
+	adapter->ahw.pci_func  = pci_func_id;
+	adapter->ahw.revision_id = revision_id;
+
+	err = nx_set_dma_mask(adapter);
+	if (err)
+		goto err_out_free_netdev;
+
+	rwlock_init(&adapter->adapter_lock);
+	spin_lock_init(&adapter->tx_clean_lock);
+	INIT_LIST_HEAD(&adapter->mac_list);
+
+	err = netxen_setup_pci_map(adapter);
+	if (err)
+		goto err_out_free_netdev;
 
 	/* This will be reset for mezz cards  */
 	adapter->portnum = pci_func_id;
-	adapter->status   &= ~NETXEN_NETDEV_STATUS;
 	adapter->rx_csum = 1;
 	adapter->mc_enabled = 0;
 	if (NX_IS_REVISION_P3(revision_id))
@@ -668,10 +1068,7 @@ skip_doorbell:
 	netdev->stop		   = netxen_nic_close;
 	netdev->hard_start_xmit    = netxen_nic_xmit_frame;
 	netdev->get_stats	   = netxen_nic_get_stats;
-	if (NX_IS_REVISION_P3(revision_id))
-		netdev->set_multicast_list = netxen_p3_nic_set_multi;
-	else
-		netdev->set_multicast_list = netxen_p2_nic_set_multi;
+	netdev->set_multicast_list = netxen_set_multicast_list;
 	netdev->set_mac_address    = netxen_nic_set_mac;
 	netdev->change_mtu	   = netxen_nic_change_mtu;
 	netdev->tx_timeout	   = netxen_tx_timeout;
@@ -697,12 +1094,6 @@ skip_doorbell:
 		netdev->features |= NETIF_F_HIGHDMA;
  	}
 
-	/*
-	 * Set the CRB window to invalid. If any register in window 0 is
-	 * accessed it should set the window to 0 and then reset it to 1.
-	 */
-	adapter->curr_window = 255;
-
 	if (netxen_nic_get_board_info(adapter) != 0) {
 		printk("%s: Error getting board config info.\n",
 				netxen_nic_driver_name);
@@ -713,7 +1104,7 @@ skip_doorbell:
 	netxen_initialize_adapter_ops(adapter);
 
 	/* Mezz cards have PCI function 0,2,3 enabled */
-	switch (adapter->ahw.boardcfg.board_type) {
+	switch (adapter->ahw.board_type) {
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
 	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
 		if (pci_func_id >= 2)
@@ -723,134 +1114,29 @@ skip_doorbell:
 		break;
 	}
 
-	/*
-	 * This call will setup various max rx/tx counts.
-	 * It must be done before any buffer/ring allocations.
-	 */
-	netxen_check_options(adapter);
-
-	first_driver = 0;
-	if (NX_IS_REVISION_P3(revision_id)) {
-		if (adapter->ahw.pci_func == 0)
-			first_driver = 1;
-	} else {
-		if (adapter->portnum == 0)
-			first_driver = 1;
-	}
-
-	if (first_driver) {
-		first_boot = adapter->pci_read_normalize(adapter,
-				NETXEN_CAM_RAM(0x1fc));
-
-		err = netxen_check_hw_init(adapter, first_boot);
-		if (err) {
-			printk(KERN_ERR "%s: error in init HW init sequence\n",
-					netxen_nic_driver_name);
-			goto err_out_iounmap;
-		}
-
-		if (NX_IS_REVISION_P3(revision_id))
-			netxen_set_port_mode(adapter);
-
-		if (first_boot != 0x55555555) {
-			adapter->pci_write_normalize(adapter,
-						CRB_CMDPEG_STATE, 0);
-			netxen_pinit_from_rom(adapter, 0);
-			msleep(1);
-		}
-		netxen_load_firmware(adapter);
-
-		if (NX_IS_REVISION_P2(revision_id)) {
-
-			/* Initialize multicast addr pool owners */
-			val = 0x7654;
-
-			if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
-				val |= 0x0f000000;
-			netxen_crb_writelit_adapter(adapter,
-					NETXEN_MAC_ADDR_CNTL_REG, val);
-
-		}
-
-		err = netxen_initialize_adapter_offload(adapter);
-		if (err)
-			goto err_out_iounmap;
-
-		/*
-		 * Tell the hardware our version number.
-		 */
-		i = (_NETXEN_NIC_LINUX_MAJOR << 16)
-			| ((_NETXEN_NIC_LINUX_MINOR << 8))
-			| (_NETXEN_NIC_LINUX_SUBVERSION);
-		adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
-
-		/* Handshake with the card before we register the devices. */
-		err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
-		if (err)
-			goto err_out_free_offload;
-
-	}	/* first_driver */
+	err = netxen_start_firmware(adapter, 1);
+	if (err)
+		goto err_out_iounmap;
 
-	netxen_nic_flash_print(adapter);
+	nx_update_dma_mask(adapter);
 
-	if (NX_IS_REVISION_P3(revision_id)) {
-		adapter->hw_read_wx(adapter,
-				NETXEN_MIU_MN_CONTROL, &val, 4);
-		adapter->ahw.cut_through = (val & 0x4) ? 1 : 0;
-		dev_info(&pdev->dev, "firmware running in %s mode\n",
-		adapter->ahw.cut_through ? "cut through" : "legacy");
-	}
+	netxen_nic_get_firmware_info(adapter);
 
 	/*
 	 * See if the firmware gave us a virtual-physical port mapping.
 	 */
 	adapter->physical_port = adapter->portnum;
 	if (adapter->fw_major < 4) {
-		i = adapter->pci_read_normalize(adapter,
-				CRB_V2P(adapter->portnum));
+		i = NXRD32(adapter, CRB_V2P(adapter->portnum));
 		if (i != 0x55555555)
 			adapter->physical_port = i;
 	}
 
-	adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
-
-	netxen_set_msix_bit(pdev, 0);
-
-	if (NX_IS_REVISION_P3(revision_id)) {
-		if ((mem_len != NETXEN_PCI_128MB_SIZE) &&
-			mem_len != NETXEN_PCI_2MB_SIZE)
-			adapter->msix_supported = 0;
-	}
-
-	if (adapter->msix_supported) {
-
-		netxen_init_msix_entries(adapter);
-
-		if (pci_enable_msix(pdev, adapter->msix_entries,
-					MSIX_ENTRIES_PER_ADAPTER))
-			goto request_msi;
-
-		adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
-		netxen_set_msix_bit(pdev, 1);
-		dev_info(&pdev->dev, "using msi-x interrupts\n");
-
-	} else {
-request_msi:
-		if (use_msi && !pci_enable_msi(pdev)) {
-			adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-			dev_info(&pdev->dev, "using msi interrupts\n");
-		} else
-			dev_info(&pdev->dev, "using legacy interrupts\n");
-	}
+	netxen_check_options(adapter);
 
-	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-		netdev->irq = adapter->msix_entries[0].vector;
-	else
-		netdev->irq = pdev->irq;
+	netxen_setup_intr(adapter);
 
-	err = netxen_receive_peg_ready(adapter);
-	if (err)
-		goto err_out_disable_msi;
+	netdev->irq = adapter->msix_entries[0].vector;
 
 	init_timer(&adapter->watchdog_timer);
 	adapter->watchdog_timer.function = &netxen_watchdog;
@@ -877,7 +1163,7 @@ request_msi:
 
 	pci_set_drvdata(pdev, adapter);
 
-	switch (adapter->ahw.board_type) {
+	switch (adapter->ahw.port_type) {
 	case NETXEN_NIC_GBE:
 		dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
 				adapter->netdev->name);
@@ -891,25 +1177,12 @@ request_msi:
 	return 0;
 
 err_out_disable_msi:
-	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-		pci_disable_msix(pdev);
-	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
-		pci_disable_msi(pdev);
+	netxen_teardown_intr(adapter);
 
-err_out_free_offload:
-	if (first_driver)
-		netxen_free_adapter_offload(adapter);
+	netxen_free_adapter_offload(adapter);
 
 err_out_iounmap:
-	if (db_ptr)
-		iounmap(db_ptr);
-
-	if (mem_ptr0)
-		iounmap(mem_ptr0);
-	if (mem_ptr1)
-		iounmap(mem_ptr1);
-	if (mem_ptr2)
-		iounmap(mem_ptr2);
+	netxen_cleanup_pci_map(adapter);
 
 err_out_free_netdev:
 	free_netdev(netdev);
@@ -936,33 +1209,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
  	unregister_netdev(netdev);
 
- 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- 		netxen_free_hw_resources(adapter);
-		netxen_release_rx_buffers(adapter);
-		netxen_free_sw_resources(adapter);
+	flush_scheduled_work();
 
-		if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-			netxen_p3_free_mac_list(adapter);
+ 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+		netxen_nic_detach(adapter);
  	}
 
 	if (adapter->portnum == 0)
 		netxen_free_adapter_offload(adapter);
 
-	if (adapter->irq)
-		free_irq(adapter->irq, adapter);
+	netxen_teardown_intr(adapter);
 
-	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-		pci_disable_msix(pdev);
-	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
-		pci_disable_msi(pdev);
+	netxen_cleanup_pci_map(adapter);
 
-	iounmap(adapter->ahw.pci_base0);
-	if (adapter->ahw.db_base != NULL)
-		iounmap(adapter->ahw.db_base);
-	if (adapter->ahw.pci_base1 != NULL)
-		iounmap(adapter->ahw.pci_base1);
-	if (adapter->ahw.pci_base2 != NULL)
-		iounmap(adapter->ahw.pci_base2);
+	netxen_release_firmware(adapter);
 
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
@@ -971,124 +1231,99 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 	free_netdev(netdev);
 }
 
-/*
- * Called when a network interface is made active
- * @returns 0 on success, negative value on failure
- */
-static int netxen_nic_open(struct net_device *netdev)
+#ifdef CONFIG_PM
+static int
+netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-	struct netxen_adapter *adapter = netdev_priv(netdev);
-	int err = 0;
-	int ctx, ring;
-	irq_handler_t handler;
-	unsigned long flags = IRQF_SAMPLE_RANDOM;
 
-	if (adapter->driver_mismatch)
-		return -EIO;
+	struct netxen_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
 
-	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
-		err = netxen_init_firmware(adapter);
-		if (err != 0) {
-			printk(KERN_ERR "Failed to init firmware\n");
-			return -EIO;
-		}
+	netif_device_detach(netdev);
 
-		if (adapter->fw_major < 4)
-			adapter->max_rds_rings = 3;
-		else
-			adapter->max_rds_rings = 2;
+	if (netif_running(netdev))
+		netxen_nic_down(adapter, netdev);
 
-		err = netxen_alloc_sw_resources(adapter);
-		if (err) {
-			printk(KERN_ERR "%s: Error in setting sw resources\n",
-					netdev->name);
-			return err;
-		}
+	flush_scheduled_work();
 
-		netxen_nic_clear_stats(adapter);
+	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+		netxen_nic_detach(adapter);
 
-		err = netxen_alloc_hw_resources(adapter);
-		if (err) {
-			printk(KERN_ERR "%s: Error in setting hw resources\n",
-					netdev->name);
-			goto err_out_free_sw;
-		}
+	pci_save_state(pdev);
 
-		if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
-			(adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
-			printk(KERN_ERR "%s: Firmware interrupt scheme is "
-					"incompatible with driver\n",
-					netdev->name);
-			adapter->driver_mismatch = 1;
-			goto err_out_free_hw;
-		}
+	if (netxen_nic_wol_supported(adapter)) {
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+	}
 
-		if (adapter->fw_major < 4) {
-			adapter->crb_addr_cmd_producer =
-				crb_cmd_producer[adapter->portnum];
-			adapter->crb_addr_cmd_consumer =
-				crb_cmd_consumer[adapter->portnum];
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
-			netxen_nic_update_cmd_producer(adapter, 0);
-			netxen_nic_update_cmd_consumer(adapter, 0);
-		}
+	return 0;
+}
 
-		for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-			for (ring = 0; ring < adapter->max_rds_rings; ring++)
-				netxen_post_rx_buffers(adapter, ctx, ring);
-		}
-		if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-			handler = netxen_msix_intr;
-		else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
-			handler = netxen_msi_intr;
-		else {
-			flags |= IRQF_SHARED;
-			handler = netxen_intr;
-		}
-		adapter->irq = netdev->irq;
-		err = request_irq(adapter->irq, handler,
-				  flags, netdev->name, adapter);
-		if (err) {
-			printk(KERN_ERR "request_irq failed with: %d\n", err);
-			goto err_out_free_rxbuf;
-		}
+static int
+netxen_nic_resume(struct pci_dev *pdev)
+{
+	struct netxen_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
+	int err;
 
-		adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
-	}
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
 
-	/* Done here again so that even if phantom sw overwrote it,
-	 * we set it */
-	err = adapter->init_port(adapter, adapter->physical_port);
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	adapter->curr_window = 255;
+
+	err = netxen_start_firmware(adapter, 0);
 	if (err) {
-		printk(KERN_ERR "%s: Failed to initialize port %d\n",
-				netxen_nic_driver_name, adapter->portnum);
-		goto err_out_free_irq;
+		dev_err(&pdev->dev, "failed to start firmware\n");
+		return err;
 	}
-	adapter->macaddr_set(adapter, netdev->dev_addr);
 
-	netxen_nic_set_link_parameters(adapter);
+	if (netif_running(netdev)) {
+		err = netxen_nic_attach(adapter);
+		if (err)
+			return err;
 
-	netdev->set_multicast_list(netdev);
-	if (adapter->set_mtu)
-		adapter->set_mtu(adapter, netdev->mtu);
+		err = netxen_nic_up(adapter, netdev);
+		if (err)
+			return err;
 
-	adapter->ahw.linkup = 0;
-	mod_timer(&adapter->watchdog_timer, jiffies);
+		netif_device_attach(netdev);
+	}
 
-	netxen_nic_enable_int(adapter);
+	return 0;
+}
+#endif
+
+static int netxen_nic_open(struct net_device *netdev)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	int err = 0;
+
+	if (adapter->driver_mismatch)
+		return -EIO;
+
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
+		err = netxen_nic_attach(adapter);
+		if (err)
+			return err;
+	}
+
+	err = netxen_nic_up(adapter, netdev);
+	if (err)
+		goto err_out;
 
 	netif_start_queue(netdev);
 
 	return 0;
 
-err_out_free_irq:
-	free_irq(adapter->irq, adapter);
-err_out_free_rxbuf:
-	netxen_release_rx_buffers(adapter);
-err_out_free_hw:
-	netxen_free_hw_resources(adapter);
-err_out_free_sw:
-	netxen_free_sw_resources(adapter);
+err_out:
+	netxen_nic_detach(adapter);
 	return err;
 }
 
@@ -1099,19 +1334,7 @@ static int netxen_nic_close(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 
-	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
-
-	if (adapter->stop_port)
-		adapter->stop_port(adapter);
-
-	netxen_nic_disable_int(adapter);
-
-	netxen_release_tx_buffers(adapter);
-
-	FLUSH_SCHEDULED_WORK();
-	del_timer_sync(&adapter->watchdog_timer);
-
+	netxen_nic_down(adapter, netdev);
 	return 0;
 }
 
@@ -1183,10 +1406,19 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
 	}
 }
 
-static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static inline void
+netxen_clear_cmddesc(u64 *desc)
+{
+	int i;
+	for (i = 0; i < 8; i++)
+		desc[i] = 0ULL;
+}
+
+static int
+netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct netxen_hardware_context *hw = &adapter->ahw;
+	struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 	unsigned int first_seg_len = skb->len - skb->data_len;
 	struct netxen_cmd_buffer *pbuf;
 	struct netxen_skb_frag *buffrag;
@@ -1195,30 +1427,29 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	dma_addr_t temp_dma;
 	int i, k;
 
-	u32 producer, consumer;
+	u32 producer;
 	int frag_count, no_of_desc;
-	u32 num_txd = adapter->max_tx_desc_count;
+	u32 num_txd = tx_ring->num_desc;
 	bool is_tso = false;
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
 
-	/* There 4 fragments per descriptor */
+	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
 
-	producer = adapter->cmd_producer;
-	smp_mb();
-	consumer = adapter->last_cmd_consumer;
-	if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) {
+	spin_lock(&tx_ring->lock);
+
+	if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) {
 		netif_stop_queue(netdev);
-		smp_mb();
+		spin_unlock(&tx_ring->lock);
 		return NETDEV_TX_BUSY;
 	}
 
-	/* Copy the descriptors into the hardware    */
-	hwdesc = &hw->cmd_desc_head[producer];
-	memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
-	/* Take skb->data itself */
-	pbuf = &adapter->cmd_buf_arr[producer];
+	producer = tx_ring->producer;
+
+	hwdesc = &tx_ring->desc_head[producer];
+	netxen_clear_cmddesc((u64 *)hwdesc);
+	pbuf = &tx_ring->cmd_buf_arr[producer];
 
 	is_tso = netxen_tso_check(netdev, hwdesc, skb);
 
@@ -1235,7 +1466,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
 	netxen_set_tx_port(hwdesc, adapter->portnum);
 
-	hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
+	hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len);
 	hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
 
 	for (i = 1, k = 1; i < frag_count; i++, k++) {
@@ -1247,9 +1478,9 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		if ((i & 0x3) == 0) {
 			k = 0;
 			producer = get_next_index(producer, num_txd);
-			hwdesc = &hw->cmd_desc_head[producer];
-			memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
-			pbuf = &adapter->cmd_buf_arr[producer];
+			hwdesc = &tx_ring->desc_head[producer];
+			netxen_clear_cmddesc((u64 *)hwdesc);
+			pbuf = &tx_ring->cmd_buf_arr[producer];
 			pbuf->skb = NULL;
 		}
 		frag = &skb_shinfo(skb)->frags[i - 1];
@@ -1268,21 +1499,18 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		buffrag->dma = temp_dma;
 		buffrag->length = temp_len;
 
+		hwdesc->buffer_length[k] = cpu_to_le16(temp_len);
 		switch (k) {
 		case 0:
-			hwdesc->buffer1_length = cpu_to_le16(temp_len);
 			hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
 			break;
 		case 1:
-			hwdesc->buffer2_length = cpu_to_le16(temp_len);
 			hwdesc->addr_buffer2 = cpu_to_le64(temp_dma);
 			break;
 		case 2:
-			hwdesc->buffer3_length = cpu_to_le16(temp_len);
 			hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
 			break;
 		case 3:
-			hwdesc->buffer4_length = cpu_to_le16(temp_len);
 			hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
 			break;
 		}
@@ -1304,8 +1532,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 			more_hdr = 0;
 		}
 		/* copy the MAC/IP/TCP headers to the cmd descriptor list */
-		hwdesc = &hw->cmd_desc_head[producer];
-		pbuf = &adapter->cmd_buf_arr[producer];
+		hwdesc = &tx_ring->desc_head[producer];
+		pbuf = &tx_ring->cmd_buf_arr[producer];
 		pbuf->skb = NULL;
 
 		/* copy the first 64 bytes */
@@ -1314,8 +1542,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		producer = get_next_index(producer, num_txd);
 
 		if (more_hdr) {
-			hwdesc = &hw->cmd_desc_head[producer];
-			pbuf = &adapter->cmd_buf_arr[producer];
+			hwdesc = &tx_ring->desc_head[producer];
+			pbuf = &tx_ring->cmd_buf_arr[producer];
 			pbuf->skb = NULL;
 			/* copy the next 64 bytes - should be enough except
 			 * for pathological case
@@ -1328,19 +1556,21 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		}
 	}
 
-	adapter->cmd_producer = producer;
+	tx_ring->producer = producer;
 	adapter->stats.txbytes += skb->len;
 
-	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+	netxen_nic_update_cmd_producer(adapter, tx_ring);
 
 	adapter->stats.xmitcalled++;
 	netdev->trans_start = jiffies;
 
+	spin_unlock(&tx_ring->lock);
 	return NETDEV_TX_OK;
 
 drop_packet:
 	adapter->stats.txdropped++;
 	dev_kfree_skb_any(skb);
+	spin_unlock(&tx_ring->lock);
 	return NETDEV_TX_OK;
 }
 
@@ -1350,7 +1580,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
 	uint32_t temp, temp_state, temp_val;
 	int rv = 0;
 
-	temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+	temp = NXRD32(adapter, CRB_TEMP_STATE);
 
 	temp_state = nx_get_temp_state(temp);
 	temp_val = nx_get_temp_val(temp);
@@ -1359,10 +1589,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
 		printk(KERN_ALERT
 		       "%s: Device temperature %d degrees C exceeds"
 		       " maximum allowed. Hardware has been shut down.\n",
-		       netxen_nic_driver_name, temp_val);
-
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
+		       netdev->name, temp_val);
 		rv = 1;
 	} else if (temp_state == NX_TEMP_WARN) {
 		if (adapter->temp == NX_TEMP_NORMAL) {
@@ -1370,13 +1597,13 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
 			       "%s: Device temperature %d degrees C "
 			       "exceeds operating range."
 			       " Immediate action needed.\n",
-			       netxen_nic_driver_name, temp_val);
+			       netdev->name, temp_val);
 		}
 	} else {
 		if (adapter->temp == NX_TEMP_WARN) {
 			printk(KERN_INFO
 			       "%s: Device temperature is now %d degrees C"
-			       " in normal range.\n", netxen_nic_driver_name,
+			       " in normal range.\n", netdev->name,
 			       temp_val);
 		}
 	}
@@ -1384,26 +1611,9 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
 	return rv;
 }
 
-static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
 {
 	struct net_device *netdev = adapter->netdev;
-	u32 val, port, linkup;
-
-	port = adapter->physical_port;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3);
-		val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
-		linkup = (val == XG_LINK_UP_P3);
-	} else {
-		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
-		if (adapter->ahw.board_type == NETXEN_NIC_GBE)
-			linkup = (val >> port) & 1;
-		else {
-			val = (val >> port*8) & 0xff;
-			linkup = (val == XG_LINK_UP);
-		}
-	}
 
 	if (adapter->ahw.linkup && !linkup) {
 		printk(KERN_INFO "%s: %s NIC Link is down\n",
@@ -1413,8 +1623,7 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
 		}
-
-		netxen_nic_set_link_parameters(adapter);
+		adapter->link_changed = !adapter->has_link_events;
 	} else if (!adapter->ahw.linkup && linkup) {
 		printk(KERN_INFO "%s: %s NIC Link is up\n",
 		       netxen_nic_driver_name, netdev->name);
@@ -1423,26 +1632,76 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
 		}
+		adapter->link_changed = !adapter->has_link_events;
+	}
+}
 
-		netxen_nic_set_link_parameters(adapter);
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+	u32 val, port, linkup;
+
+	port = adapter->physical_port;
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		val = NXRD32(adapter, CRB_XG_STATE_P3);
+		val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+		linkup = (val == XG_LINK_UP_P3);
+	} else {
+		val = NXRD32(adapter, CRB_XG_STATE);
+		if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+			linkup = (val >> port) & 1;
+		else {
+			val = (val >> port*8) & 0xff;
+			linkup = (val == XG_LINK_UP);
+		}
 	}
+
+	netxen_advert_link_change(adapter, linkup);
+}
+
+static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	netif_device_detach(netdev);
+	netxen_nic_down(adapter, netdev);
+	netxen_nic_detach(adapter);
 }
 
 static void netxen_watchdog(unsigned long v)
 {
 	struct netxen_adapter *adapter = (struct netxen_adapter *)v;
 
-	SCHEDULE_WORK(&adapter->watchdog_task);
+	if (netxen_nic_check_temp(adapter))
+		goto do_sched;
+
+	if (!adapter->has_link_events) {
+		netxen_nic_handle_phy_intr(adapter);
+
+		if (adapter->link_changed)
+			goto do_sched;
+	}
+
+	if (netif_running(adapter->netdev))
+		mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+
+	return;
+
+do_sched:
+	schedule_work(&adapter->watchdog_task);
 }
 
 static void netxen_watchdog_task(unsigned long adaptid)
 {
 	struct netxen_adapter *adapter = (struct netxen_adapter *)adaptid;
 
-	if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
+	if (adapter->temp == NX_TEMP_PANIC) {
+		netxen_nic_thermal_shutdown(adapter);
 		return;
+	}
 
-	netxen_nic_handle_phy_intr(adapter);
+	if (adapter->link_changed)
+		netxen_nic_set_link_parameters(adapter);
 
 	if (netif_running(adapter->netdev))
 		mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1450,9 +1709,8 @@ static void netxen_watchdog_task(unsigned long adaptid)
 
 static void netxen_tx_timeout(struct net_device *netdev)
 {
-	struct netxen_adapter *adapter = (struct netxen_adapter *)
-						netdev_priv(netdev);
-	SCHEDULE_WORK(&adapter->tx_timeout_task);
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	schedule_work(&adapter->tx_timeout_task);
 }
 
 static void netxen_tx_timeout_task(unsigned long adapid)
@@ -1461,21 +1719,20 @@ static void netxen_tx_timeout_task(unsigned long adapid)
 	struct netxen_adapter *adapter = (struct netxen_adapter *)
 						netdev_priv(netdev);
 
+	if (!netif_running(adapter->netdev))
+		return;
+
 	printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
 	       netxen_nic_driver_name, adapter->netdev->name);
 
-	netxen_nic_disable_int(adapter);
+	netxen_napi_disable(adapter);
 
 	adapter->netdev->trans_start = jiffies;
 
-	netxen_nic_enable_int(adapter);
+	netxen_napi_enable(adapter);
 	netif_wake_queue(adapter->netdev);
 }
 
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -1483,22 +1740,11 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 
 	memset(stats, 0, sizeof(*stats));
 
-	/* total packets received   */
 	stats->rx_packets = adapter->stats.no_rcv;
-	/* total packets transmitted    */
-	stats->tx_packets = adapter->stats.xmitedframes +
-		adapter->stats.xmitfinished;
-	/* total bytes received     */
+	stats->tx_packets = adapter->stats.xmitfinished;
 	stats->rx_bytes = adapter->stats.rxbytes;
-	/* total bytes transmitted  */
 	stats->tx_bytes = adapter->stats.txbytes;
-	/* bad packets received     */
-	stats->rx_errors = adapter->stats.rcvdbadskb;
-	/* packet transmit problems */
-	stats->tx_errors = adapter->stats.nocmddescriptor;
-	/* no space in linux buffers    */
 	stats->rx_dropped = adapter->stats.rxdropped;
-	/* no space available in linux  */
 	stats->tx_dropped = adapter->stats.txdropped;
 
 	return stats;
@@ -1506,7 +1752,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 
 static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs)
 {
-  	struct netxen_adapter *adapter = data;
+	struct nx_host_sds_ring *sds_ring = data;
+	struct netxen_adapter *adapter = sds_ring->adapter;
 	u32 status = 0;
 
 	adapter = (struct netxen_adapter *)data;
@@ -1526,20 +1773,19 @@ static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs)
 	} else {
 		unsigned long our_int = 0;
 
-		our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
+		our_int = NXRD32(adapter, CRB_INT_VECTOR);
 
 		/* not our interrupt */
 		if (!test_and_clear_bit((7 + adapter->portnum), &our_int))
 			return IRQ_NONE;
 
 		/* claim interrupt */
-		adapter->pci_write_normalize(adapter,
-				CRB_INT_VECTOR, (our_int & 0xffffffff));
+		NXWR32(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff));
 	}
 
 	/* clear interrupt */
 	if (adapter->fw_major < 4)
-		netxen_nic_disable_int(adapter);
+		netxen_nic_disable_int(sds_ring);
 
 	adapter->pci_write_immediate(adapter,
 			adapter->legacy_intr.tgt_status_reg,
@@ -1548,71 +1794,55 @@ static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs)
 	adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
 	adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
 
-	netif_rx_schedule(adapter->netdev);
+	netif_rx_schedule(sds_ring->napi_dev);
 
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t netxen_msi_intr(int irq, void *data, struct pt_regs *regs)
 {
-	struct netxen_adapter *adapter = data;
+	struct nx_host_sds_ring *sds_ring = data;
+	struct netxen_adapter *adapter = sds_ring->adapter;
 
 	/* clear interrupt */
 	adapter->pci_write_immediate(adapter,
-			msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
+			adapter->msi_tgt_status, 0xffffffff);
 
-	netif_rx_schedule(adapter->netdev);
+	netif_rx_schedule(sds_ring->napi_dev);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t netxen_msix_intr(int irq, void *data, struct pt_regs *regs)
 {
-	struct netxen_adapter *adapter = data;
+	struct nx_host_sds_ring *sds_ring = data;
 
-	netif_rx_schedule(adapter->netdev);
+	netif_rx_schedule(sds_ring->napi_dev);
 	return IRQ_HANDLED;
 }
 
 static int netxen_nic_poll(struct net_device *netdev, int *budget)
 {
-	struct netxen_adapter *adapter = netdev_priv(netdev);
+	struct nx_host_sds_ring *sds_ring = netdev->priv;
+
+	struct netxen_adapter *adapter = sds_ring->adapter;
+
 	int work_to_do = min(*budget, netdev->quota);
 	int tx_complete;
-	int ctx;
-	int this_work_done;
 	int work_done = 0;
 
-	adapter->stats.polled++;
 	tx_complete = netxen_process_cmd_ring(adapter);
 
-	work_done = 0;
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		/*
-		 * Fairness issue. This will give undue weight to the
-		 * receive context 0.
-		 */
-
-		/*
-		 * To avoid starvation, we give each of our receivers,
-		 * a fraction of the quota. Sometimes, it might happen that we
-		 * have enough quota to process every packet, but since all the
-		 * packets are on one context, it gets only half of the quota,
-		 * and ends up not processing it.
-		 */
-		this_work_done = netxen_process_rcv_ring(adapter, ctx,
-							 work_to_do /
-							 MAX_RCV_CTX);
-		work_done += this_work_done;
-	}
+	work_done = netxen_process_rcv_ring(sds_ring, work_to_do);
 
 	netdev->quota -= work_done;
 	*budget -= work_done;
 
-	napi_gro_flush(&adapter->napi);
+	napi_gro_flush(&sds_ring->napi);
 
 	if ((work_done < work_to_do) && tx_complete) {
-		netif_rx_complete(adapter->netdev);
-		netxen_nic_enable_int(adapter);
+		netif_rx_complete(sds_ring->napi_dev);
+		if (netif_running(adapter->netdev))
+			netxen_nic_enable_int(sds_ring);
 		return 0;
 	}
 
@@ -1633,15 +1863,18 @@ static struct pci_driver netxen_driver = {
 	.name = netxen_nic_driver_name,
 	.id_table = netxen_pci_tbl,
 	.probe = netxen_nic_probe,
-	.remove = __devexit_p(netxen_nic_remove)
+	.remove = __devexit_p(netxen_nic_remove),
+#ifdef CONFIG_PM
+	.suspend = netxen_nic_suspend,
+	.resume = netxen_nic_resume
+#endif
 };
 
 /* Driver Registration on NetXen card    */
 
 static int __init netxen_init_module(void)
 {
-	if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0)
-		return -ENOMEM;
+	printk(KERN_INFO "%s\n", netxen_nic_driver_string);
 
 	return pci_register_driver(&netxen_driver);
 }
@@ -1651,7 +1884,6 @@ module_init(netxen_init_module);
 static void __exit netxen_exit_module(void)
 {
 	pci_unregister_driver(&netxen_driver);
-	destroy_workqueue(netxen_workq);
 }
 
 module_exit(netxen_exit_module);
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 8e53bba..0e2904c 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,12 +22,9 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- *
- *
- * Provides access to the Network Interface Unit h/w block.
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
  *
  */
 
@@ -40,14 +37,13 @@
 
 static long phy_lock_timeout = 100000000;
 
-static inline int phy_lock(struct netxen_adapter *adapter)
+static int phy_lock(struct netxen_adapter *adapter)
 {
 	int i;
 	int done = 0, timeout = 0;
 
 	while (!done) {
-		done = netxen_nic_reg_read(adapter,
-				NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
+		done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= phy_lock_timeout) {
@@ -62,12 +58,11 @@ static inline int phy_lock(struct netxen_adapter *adapter)
 		}
 	}
 
-	netxen_crb_writelit_adapter(adapter,
-			NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
+	NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
 	return 0;
 }
 
-static inline int phy_unlock(struct netxen_adapter *adapter)
+static int phy_unlock(struct netxen_adapter *adapter)
 {
 	adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
 
@@ -108,9 +103,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
 	 * so it cannot be in reset
 	 */
 
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
-				  &mac_cfg0, 4))
-		return -EIO;
+	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
 		__u32 temp;
 		temp = 0;
@@ -118,9 +111,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
 		netxen_gb_rx_reset_pb(temp);
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &temp, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
 			return -EIO;
 		restore = 1;
 	}
@@ -128,43 +119,32 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
-				   &address, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
 		return -EIO;
 	command = 0;		/* turn off any prior activity */
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 	/* send read command */
 	netxen_gb_mii_mgmt_set_read_cycle(command);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
-					  &status, 4))
-			return -EIO;
+		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
 		timeout++;
 	} while ((netxen_get_gb_mii_mgmt_busy(status)
 		  || netxen_get_gb_mii_mgmt_notvalid(status))
 		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
 
 	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
-					  readval, 4))
-			return -EIO;
+		*readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0));
 		result = 0;
 	} else
 		result = -1;
 
 	if (restore)
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &mac_cfg0, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
 			return -EIO;
 	phy_unlock(adapter);
 	return result;
@@ -200,9 +180,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
 	 * cannot be in reset
 	 */
 
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
-				  &mac_cfg0, 4))
-		return -EIO;
+	mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0));
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
 		__u32 temp;
 		temp = 0;
@@ -211,35 +189,27 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
 
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &temp, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp))
 			return -EIO;
 		restore = 1;
 	}
 
 	command = 0;		/* turn off any prior activity */
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
-				   &command, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command))
 		return -EIO;
 
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
-				   &address, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address))
 		return -EIO;
 
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
-				   &val, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (adapter->hw_read_wx(adapter,
-					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
-					  &status, 4))
-			return -EIO;
+		status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0));
 		timeout++;
 	} while ((netxen_get_gb_mii_mgmt_busy(status))
 		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
@@ -251,9 +221,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
 
 	/* restore the state of port 0 MAC in case we tampered with it */
 	if (restore)
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
-					   &mac_cfg0, 4))
+		if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0))
 			return -EIO;
 
 	return result;
@@ -261,7 +229,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
 
 int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f);
+	NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f);
 	return 0;
 }
 
@@ -284,7 +252,7 @@ int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter)
 
 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f);
+	NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f);
 	return 0;
 }
 
@@ -299,14 +267,6 @@ int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter)
 	return result;
 }
 
-#if 0
-static int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter)
-{
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1);
-	return 0;
-}
-#endif /* 0 */
-
 static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter)
 {
 	int result = 0;
@@ -326,36 +286,27 @@ static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter)
 static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
 				 int port, long enable)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x80000000);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x0000f0025);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
-				    0xf1ff);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
-	netxen_crb_writelit_adapter(adapter,
-				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+	NXWR32(adapter, NETXEN_NIU_MODE, 0x2);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff);
+	NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
+	NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
+	NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
 
 	if (enable) {
 		/*
 		 * Do NOT enable flow control until a suitable solution for
 		 *  shutting down pause frames is found.
 		 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
-					    0x5);
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5);
 	}
 
 	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+		printk(KERN_ERR "ERROR enabling PHY interrupts\n");
 	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+		printk(KERN_ERR "ERROR clearing PHY interrupts\n");
 }
 
 /*
@@ -364,36 +315,27 @@ static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
 static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
 				  int port, long enable)
 {
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x80000000);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				    0x0000f0025);
-	netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
-				    0xf2ff);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
-	netxen_crb_writelit_adapter(adapter,
-				    (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
-	netxen_crb_writelit_adapter(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+	NXWR32(adapter, NETXEN_NIU_MODE, 0x2);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025);
+	NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff);
+	NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0);
+	NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1);
+	NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+	NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
 
 	if (enable) {
 		/*
 		 * Do NOT enable flow control until a suitable solution for
 		 *  shutting down pause frames is found.
 		 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_NIU_GB_MAC_CONFIG_0(port),
-					    0x5);
+		NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5);
 	}
 
 	if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n");
+		printk(KERN_ERR "ERROR enabling PHY interrupts\n");
 	if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-		printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n");
+		printk(KERN_ERR "ERROR clearing PHY interrupts\n");
 }
 
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
@@ -427,25 +369,20 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 			 * plugged in.
 			 */
 
-			netxen_crb_writelit_adapter(adapter,
-						    NETXEN_NIU_GB_MAC_CONFIG_0
-						    (port),
+			NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 						    NETXEN_GB_MAC_SOFT_RESET);
-			netxen_crb_writelit_adapter(adapter,
-						    NETXEN_NIU_GB_MAC_CONFIG_0
-						    (port),
-						    NETXEN_GB_MAC_RESET_PROT_BLK
-						    | NETXEN_GB_MAC_ENABLE_TX_RX
-						    |
-						    NETXEN_GB_MAC_PAUSED_FRMS);
+			NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+					    NETXEN_GB_MAC_RESET_PROT_BLK |
+					    NETXEN_GB_MAC_ENABLE_TX_RX |
+					    NETXEN_GB_MAC_PAUSED_FRMS);
 			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR clearing PHY interrupts\n");
 			if (netxen_niu_gbe_enable_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR enabling PHY interrupts\n");
 			if (netxen_niu_gbe_clear_phy_interrupts(adapter))
-				printk(KERN_ERR PFX
+				printk(KERN_ERR
 				       "ERROR clearing PHY interrupts\n");
 			result = -1;
 		}
@@ -458,269 +395,10 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-		netxen_crb_writelit_adapter(adapter,
-			NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
-		netxen_crb_writelit_adapter(adapter,
-			NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
-	}
-
-	return 0;
-}
-
-/*
- * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
- * @param enable 0 means don't enable the port
- *		 1 means enable (or re-enable) the port
- */
-int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
-					int port, long enable)
-{
-	int result = 0;
-	__u32 int_src;
-
-	printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
-	       " (device enable = %d)\n", (int)port, (int)enable);
-
-	/*
-	 * The read of the PHY INT status will clear the pending
-	 * interrupt status
-	 */
-	if (netxen_niu_gbe_phy_read(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
-				    &int_src) != 0)
-		result = -EINVAL;
-	else {
-		printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n", int_src);
-		if (netxen_get_phy_int_jabber(int_src))
-			printk(KERN_INFO PFX "jabber Interrupt ");
-		if (netxen_get_phy_int_polarity_changed(int_src))
-			printk(KERN_INFO PFX "polarity changed ");
-		if (netxen_get_phy_int_energy_detect(int_src))
-			printk(KERN_INFO PFX "energy detect \n");
-		if (netxen_get_phy_int_downshift(int_src))
-			printk(KERN_INFO PFX "downshift \n");
-		if (netxen_get_phy_int_mdi_xover_changed(int_src))
-			printk(KERN_INFO PFX "mdi_xover_changed ");
-		if (netxen_get_phy_int_fifo_over_underflow(int_src))
-			printk(KERN_INFO PFX "fifo_over_underflow ");
-		if (netxen_get_phy_int_false_carrier(int_src))
-			printk(KERN_INFO PFX "false_carrier ");
-		if (netxen_get_phy_int_symbol_error(int_src))
-			printk(KERN_INFO PFX "symbol_error ");
-		if (netxen_get_phy_int_autoneg_completed(int_src))
-			printk(KERN_INFO PFX "autoneg_completed ");
-		if (netxen_get_phy_int_page_received(int_src))
-			printk(KERN_INFO PFX "page_received ");
-		if (netxen_get_phy_int_duplex_changed(int_src))
-			printk(KERN_INFO PFX "duplex_changed ");
-		if (netxen_get_phy_int_autoneg_error(int_src))
-			printk(KERN_INFO PFX "autoneg_error ");
-		if ((netxen_get_phy_int_speed_changed(int_src))
-		    || (netxen_get_phy_int_link_status_changed(int_src))) {
-			__u32 status;
-
-			printk(KERN_INFO PFX
-			       "speed_changed or link status changed");
-			if (netxen_niu_gbe_phy_read
-			    (adapter,
-			     NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-			     &status) == 0) {
-				if (netxen_get_phy_speed(status) == 2) {
-					printk
-					    (KERN_INFO PFX "Link speed changed"
-					     " to 1000 Mbps\n");
-					netxen_niu_gbe_set_gmii_mode(adapter,
-								     port,
-								     enable);
-				} else if (netxen_get_phy_speed(status) == 1) {
-					printk
-					    (KERN_INFO PFX "Link speed changed"
-					     " to 100 Mbps\n");
-					netxen_niu_gbe_set_mii_mode(adapter,
-								    port,
-								    enable);
-				} else if (netxen_get_phy_speed(status) == 0) {
-					printk
-					    (KERN_INFO PFX "Link speed changed"
-					     " to 10 Mbps\n");
-					netxen_niu_gbe_set_mii_mode(adapter,
-								    port,
-								    enable);
-				} else {
-					printk(KERN_ERR PFX "ERROR reading"
-					       "PHY status. Illegal speed.\n");
-					result = -1;
-				}
-			} else {
-				printk(KERN_ERR PFX
-				       "ERROR reading PHY status.\n");
-				result = -1;
-			}
-
-		}
-		printk(KERN_INFO "\n");
-	}
-	return result;
-}
-
-/*
- * Return the current station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
-			   netxen_ethernet_macaddr_t * addr)
-{
-	u32 stationhigh;
-	u32 stationlow;
-	int phy = adapter->physical_port;
-	u8 val[8];
-
-	if (addr == NULL)
-		return -EINVAL;
-	if ((phy < 0) || (phy > 3))
-		return -EINVAL;
-
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
-				  &stationhigh, 4))
-		return -EIO;
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
-				  &stationlow, 4))
-		return -EIO;
-	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
-	((__le32 *)val)[0] = cpu_to_le32(stationlow);
-
-	memcpy(addr, val + 2, 6);
-
-	return 0;
-}
-
-/*
- * Set the station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
-			   netxen_ethernet_macaddr_t addr)
-{
-	u8 temp[4];
-	u32 val;
-	int phy = adapter->physical_port;
-	unsigned char mac_addr[6];
-	int i;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		return 0;
-
-	for (i = 0; i < 10; i++) {
-		temp[0] = temp[1] = 0;
-		memcpy(temp + 2, addr, 2);
-		val = le32_to_cpu(*(__le32 *)temp);
-		if (adapter->hw_write_wx(adapter,
-				NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
-			return -EIO;
-
-		memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
-		val = le32_to_cpu(*(__le32 *)temp);
-		if (adapter->hw_write_wx(adapter,
-				NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
-			return -2;
-
-		netxen_niu_macaddr_get(adapter,
-				       (netxen_ethernet_macaddr_t *) mac_addr);
-		if (memcmp(mac_addr, addr, 6) == 0)
-			break;
-	}
-
-	if (i == 10) {
-		printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
-		       netxen_nic_driver_name, adapter->netdev->name);
-		printk(KERN_ERR "MAC address set: "
-		       "%02x:%02x:%02x:%02x:%02x:%02x.\n",
-		       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-
-		printk(KERN_ERR "MAC address get: "
-		       "%02x:%02x:%02x:%02x:%02x:%02x.\n",
-		       mac_addr[0],
-		       mac_addr[1],
-		       mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
-	}
-	return 0;
-}
-
-/* Enable a GbE interface */
-int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
-			       int port, netxen_niu_gbe_ifmode_t mode)
-{
-	__u32 mac_cfg0;
-	__u32 mac_cfg1;
-	__u32 mii_cfg;
-
-	if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
-		return -EINVAL;
-
-	mac_cfg0 = 0;
-	netxen_gb_soft_reset(mac_cfg0);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				   &mac_cfg0, 4))
-		return -EIO;
-	mac_cfg0 = 0;
-	netxen_gb_enable_tx(mac_cfg0);
-	netxen_gb_enable_rx(mac_cfg0);
-	netxen_gb_unset_rx_flowctl(mac_cfg0);
-	netxen_gb_tx_reset_pb(mac_cfg0);
-	netxen_gb_rx_reset_pb(mac_cfg0);
-	netxen_gb_tx_reset_mac(mac_cfg0);
-	netxen_gb_rx_reset_mac(mac_cfg0);
-
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				   &mac_cfg0, 4))
-		return -EIO;
-	mac_cfg1 = 0;
-	netxen_gb_set_preamblelen(mac_cfg1, 0xf);
-	netxen_gb_set_duplex(mac_cfg1);
-	netxen_gb_set_crc_enable(mac_cfg1);
-	netxen_gb_set_padshort(mac_cfg1);
-	netxen_gb_set_checklength(mac_cfg1);
-	netxen_gb_set_hugeframes(mac_cfg1);
-
-	if (mode == NETXEN_NIU_10_100_MB) {
-		netxen_gb_set_intfmode(mac_cfg1, 1);
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
-					   &mac_cfg1, 4))
-			return -EIO;
-
-		/* set mii mode */
-		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
-					    (port << 3), 0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
-					    (port << 3), 1);
-
-	} else if (mode == NETXEN_NIU_1000_MB) {
-		netxen_gb_set_intfmode(mac_cfg1, 2);
-		if (adapter->hw_write_wx(adapter,
-					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
-					   &mac_cfg1, 4))
-			return -EIO;
-		/* set gmii mode */
-		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
-					    (port << 3), 0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
-					    (port << 3), 1);
+		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+		NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
 	}
-	mii_cfg = 0;
-	netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
-				   &mii_cfg, 4))
-		return -EIO;
-	mac_cfg0 = 0;
-	netxen_gb_enable_tx(mac_cfg0);
-	netxen_gb_enable_rx(mac_cfg0);
-	netxen_gb_unset_rx_flowctl(mac_cfg0);
-	netxen_gb_unset_tx_flowctl(mac_cfg0);
 
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				   &mac_cfg0, 4))
-		return -EIO;
 	return 0;
 }
 
@@ -737,8 +415,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
 		return -EINVAL;
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
-				   &mac_cfg0, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0))
 		return -EIO;
 	return 0;
 }
@@ -756,8 +433,8 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
 		return -EINVAL;
 
 	mac_cfg = 0;
-	if (adapter->hw_write_wx(adapter,
-		NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
+	if (NXWR32(adapter,
+			NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg))
 		return -EIO;
 	return 0;
 }
@@ -773,9 +450,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
 		return -EINVAL;
 
 	/* save previous contents */
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
-				  &reg, 4))
-		return -EIO;
+	reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR);
 	if (mode == NETXEN_NIU_PROMISC_MODE) {
 		switch (port) {
 		case 0:
@@ -811,98 +486,11 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
 			return -EIO;
 		}
 	}
-	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
-				   &reg, 4))
+	if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg))
 		return -EIO;
 	return 0;
 }
 
-/*
- * Set the MAC address for an XG port
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t addr)
-{
-	int phy = adapter->physical_port;
-	u8 temp[4];
-	u32 val;
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		return 0;
-
-	if ((phy < 0) || (phy > NETXEN_NIU_MAX_XG_PORTS))
-		return -EIO;
-
-	temp[0] = temp[1] = 0;
-	switch (phy) {
-	case 0:
-	    memcpy(temp + 2, addr, 2);
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
-				&val, 4))
-		return -EIO;
-
-	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
-				&val, 4))
-		return -EIO;
-	    break;
-
-	case 1:
-	    memcpy(temp + 2, addr, 2);
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
-				&val, 4))
-		return -EIO;
-
-	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
-				&val, 4))
-		return -EIO;
-	    break;
-
-	default:
-	    printk(KERN_ERR "Unknown port %d\n", phy);
-	    break;
-	}
-
-	return 0;
-}
-
-/*
- * Return the current station MAC address.
- * Note that the passed-in value must already be in network byte order.
- */
-int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
-			      netxen_ethernet_macaddr_t * addr)
-{
-	int phy = adapter->physical_port;
-	u32 stationhigh;
-	u32 stationlow;
-	u8 val[8];
-
-	if (addr == NULL)
-		return -EINVAL;
-	if (phy != 0)
-		return -EINVAL;
-
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
-				  &stationhigh, 4))
-		return -EIO;
-	if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
-				  &stationlow, 4))
-		return -EIO;
-	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
-	((__le32 *)val)[0] = cpu_to_le32(stationlow);
-
-	memcpy(addr, val + 2, 6);
-
-	return 0;
-}
-
 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 		u32 mode)
 {
@@ -912,9 +500,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 	if (port > NETXEN_NIU_MAX_XG_PORTS)
 		return -EINVAL;
 
-	if (adapter->hw_read_wx(adapter,
-		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
-			return -EIO;
+	reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port));
 	if (mode == NETXEN_NIU_PROMISC_MODE)
 		reg = (reg | 0x2000UL);
 	else
@@ -925,8 +511,40 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
 	else
 		reg = (reg & ~0x1000UL);
 
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
+	NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
+
+	return 0;
+}
+
+int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr)
+{
+	u32 mac_hi, mac_lo;
+	u32 reg_hi, reg_lo;
+
+	u8 phy = adapter->physical_port;
+	u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ?
+		NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS;
+
+	if (phy >= phy_count)
+		return -EINVAL;
+
+	mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24);
+	mac_hi = addr[2] | ((u32)addr[3] << 8) |
+		((u32)addr[4] << 16) | ((u32)addr[5] << 24);
+
+	if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+		reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy);
+		reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy);
+	} else {
+		reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy);
+		reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy);
+	}
+
+	/* write twice to flush */
+	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+		return -EIO;
+	if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi))
+		return -EIO;
 
 	return 0;
 }
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index 26d95fb..b73a62c 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
+ * Copyright (C) 2003 - 2009 NetXen, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -22,9 +22,10 @@
  *
  * Contact Information:
  *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
+ * NetXen Inc,
+ * 18922 Forge Drive
+ * Cupertino, CA 95014-0701
+ *
  */
 
 #ifndef __NIC_PHAN_REG_H_
@@ -35,23 +36,25 @@
  */
 #define NIC_CRB_BASE               NETXEN_CAM_RAM(0x200)
 #define NETXEN_NIC_REG(X)             (NIC_CRB_BASE+(X))
+#define NIC_CRB_BASE_2             NETXEN_CAM_RAM(0x700)
+#define NETXEN_NIC_REG_2(X)         (NIC_CRB_BASE_2+(X))
 
 #define CRB_PHAN_CNTRL_LO_OFFSET    NETXEN_NIC_REG(0x00)
 #define CRB_PHAN_CNTRL_HI_OFFSET    NETXEN_NIC_REG(0x04)
 #define CRB_CMD_PRODUCER_OFFSET     NETXEN_NIC_REG(0x08)
 #define CRB_CMD_CONSUMER_OFFSET     NETXEN_NIC_REG(0x0c)
-#define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)	/* C0 EPG BUG  */
+#define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)
 #define CRB_PAUSE_ADDR_HI           NETXEN_NIC_REG(0x14)
 #define NX_CDRP_CRB_OFFSET          NETXEN_NIC_REG(0x18)
 #define NX_ARG1_CRB_OFFSET          NETXEN_NIC_REG(0x1c)
 #define NX_ARG2_CRB_OFFSET          NETXEN_NIC_REG(0x20)
 #define NX_ARG3_CRB_OFFSET          NETXEN_NIC_REG(0x24)
 #define NX_SIGN_CRB_OFFSET          NETXEN_NIC_REG(0x28)
-#define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)	/* 4 regs for perf */
+#define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)
 #define CRB_CMD_DMA_LOOP            NETXEN_NIC_REG(0x24)
 #define CRB_RCV_INTR_LOOP           NETXEN_NIC_REG(0x28)
 #define CRB_RCV_DMA_LOOP            NETXEN_NIC_REG(0x2c)
-#define CRB_ENABLE_TX_INTR          NETXEN_NIC_REG(0x30)	/* phantom init status */
+#define CRB_ENABLE_TX_INTR          NETXEN_NIC_REG(0x30)
 #define CRB_MMAP_ADDR_3             NETXEN_NIC_REG(0x34)
 #define CRB_CMDPEG_CMDRING          NETXEN_NIC_REG(0x38)
 #define CRB_HOST_DUMMY_BUF_ADDR_HI  NETXEN_NIC_REG(0x3c)
@@ -64,7 +67,7 @@
 #define CRB_MMAP_SIZE_1             NETXEN_NIC_REG(0x58)
 #define CRB_MMAP_SIZE_2             NETXEN_NIC_REG(0x5c)
 #define CRB_MMAP_SIZE_3             NETXEN_NIC_REG(0x60)
-#define CRB_GLOBAL_INT_COAL         NETXEN_NIC_REG(0x64)	/* interrupt coalescing */
+#define CRB_GLOBAL_INT_COAL         NETXEN_NIC_REG(0x64)
 #define CRB_INT_COAL_MODE           NETXEN_NIC_REG(0x68)
 #define CRB_MAX_RCV_BUFS            NETXEN_NIC_REG(0x6c)
 #define CRB_TX_INT_THRESHOLD        NETXEN_NIC_REG(0x70)
@@ -82,14 +85,15 @@
 #define CRB_AGENT_TX_TYPE           NETXEN_NIC_REG(0xa0)
 #define CRB_AGENT_TX_ADDR           NETXEN_NIC_REG(0xa4)
 #define CRB_AGENT_TX_MSS            NETXEN_NIC_REG(0xa8)
-#define CRB_TX_STATE                NETXEN_NIC_REG(0xac)	/* Debug -performance */
+#define CRB_TX_STATE                NETXEN_NIC_REG(0xac)
 #define CRB_TX_COUNT                NETXEN_NIC_REG(0xb0)
 #define CRB_RX_STATE                NETXEN_NIC_REG(0xb4)
 #define CRB_RX_PERF_DEBUG_1         NETXEN_NIC_REG(0xb8)
-#define CRB_RX_LRO_CONTROL          NETXEN_NIC_REG(0xbc)	/* LRO On/OFF */
+#define CRB_RX_LRO_CONTROL          NETXEN_NIC_REG(0xbc)
 #define CRB_RX_LRO_START_NUM        NETXEN_NIC_REG(0xc0)
-#define CRB_MPORT_MODE              NETXEN_NIC_REG(0xc4)	/* Multiport Mode */
+#define CRB_MPORT_MODE              NETXEN_NIC_REG(0xc4)
 #define CRB_CMD_RING_SIZE           NETXEN_NIC_REG(0xc8)
+#define CRB_DMA_SHIFT               NETXEN_NIC_REG(0xcc)
 #define CRB_INT_VECTOR              NETXEN_NIC_REG(0xd4)
 #define CRB_CTX_RESET               NETXEN_NIC_REG(0xd8)
 #define CRB_HOST_STS_PROD           NETXEN_NIC_REG(0xdc)
@@ -107,8 +111,6 @@
 #define CRB_CMD_CONSUMER_OFFSET_1   NETXEN_NIC_REG(0x1b0)
 #define CRB_CMD_PRODUCER_OFFSET_2   NETXEN_NIC_REG(0x1b8)
 #define CRB_CMD_CONSUMER_OFFSET_2   NETXEN_NIC_REG(0x1bc)
-
-// 1c0 to 1cc used for signature reg
 #define CRB_CMD_PRODUCER_OFFSET_3   NETXEN_NIC_REG(0x1d0)
 #define CRB_CMD_CONSUMER_OFFSET_3   NETXEN_NIC_REG(0x1d4)
 #define CRB_TEMP_STATE              NETXEN_NIC_REG(0x1b4)
@@ -118,13 +120,13 @@
 #define CRB_V2P_2		    NETXEN_NIC_REG(0x298)
 #define CRB_V2P_3		    NETXEN_NIC_REG(0x29c)
 #define CRB_V2P(port)		    (CRB_V2P_0+((port)*4))
-#define CRB_DRIVER_VERSION	    NETXEN_NIC_REG(0x2a0)
-/* sw int status/mask registers */
+#define CRB_DRIVER_VERSION	   NETXEN_NIC_REG(0x2a0)
 #define CRB_SW_INT_MASK_0	   NETXEN_NIC_REG(0x1d8)
 #define CRB_SW_INT_MASK_1	   NETXEN_NIC_REG(0x1e0)
 #define CRB_SW_INT_MASK_2	   NETXEN_NIC_REG(0x1e4)
 #define CRB_SW_INT_MASK_3	   NETXEN_NIC_REG(0x1e8)
 
+#define CRB_FW_CAPABILITIES_1      NETXEN_CAM_RAM(0x128)
 #define CRB_MAC_BLOCK_START        NETXEN_CAM_RAM(0x1c0)
 
 /*
@@ -134,7 +136,7 @@
 #define CRB_NIC_CAPABILITIES_HOST	NETXEN_NIC_REG(0x1a8)
 #define CRB_NIC_CAPABILITIES_FW	  	NETXEN_NIC_REG(0x1dc)
 #define CRB_NIC_MSI_MODE_HOST		NETXEN_NIC_REG(0x270)
-#define CRB_NIC_MSI_MODE_FW	  		NETXEN_NIC_REG(0x274)
+#define CRB_NIC_MSI_MODE_FW	  	NETXEN_NIC_REG(0x274)
 
 #define INTR_SCHEME_PERPORT	      	0x1
 #define MSI_MODE_MULTIFUNC	      	0x1
@@ -160,13 +162,10 @@
 
 struct netxen_recv_crb {
 	u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
-	u32 crb_sts_consumer;
+	u32 crb_sts_consumer[NUM_STS_DESC_RINGS];
+	u32 sw_int_mask[NUM_STS_DESC_RINGS];
 };
 
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][1])
-
 /*
  * Temperature control.
  */