[haiku-development] Proposed addition to freebsd_network and marvell_yukon driver

  • From: Tomas Wilhelmsson <tomas.wilhelmsson@xxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Wed, 3 Mar 2010 08:31:25 +0100

The yukon driver runs and identifies my card in my new laptop and adds a
device for it and assigns it an ip, but when i plugin the cable i get
"PANIC: should never be called" on __haiku_disable_interrupts and i dont
know how to fix that up, but hoping on you guys =)

Other proposed changes to freebsd_network is for the ssb driver needed for
BWM wifi driver (i think its a replacement for bwi driver)

Anyhow, if anyone can fix up the marvell_yukon driver so that i can use my
brand new laptop in haiku i would love you =)

Tried to clean up the patches but might have missed some basic coding
guidelines, first try at getting something done for haiku =)

Have a nice day!
Tomas Wilhelmsson
Index: dev/msk/if_msk.c
===================================================================
--- dev/msk/if_msk.c    (revision 35579)
+++ dev/msk/if_msk.c    (working copy)
@@ -99,7 +99,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: src/sys/dev/msk/if_msk.c,v 1.89 2010/03/02 01:45:02 
yongari Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -113,8 +113,10 @@
 #include <sys/sockio.h>
 #include <sys/queue.h>
 #include <sys/sysctl.h>
-#include <sys/taskqueue.h>
+#include <sys/mutex.h>
+#include <sys/callout.h>
 
+
 #include <net/bpf.h>
 #include <net/ethernet.h>
 #include <net/if.h>
@@ -137,7 +139,6 @@
 
 #include <dev/mii/mii.h>
 #include <dev/mii/miivar.h>
-#include <dev/mii/brgphyreg.h>
 
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
@@ -201,6 +202,8 @@
            "Marvell Yukon 88E8040 Fast Ethernet" },
        { VENDORID_MARVELL, DEVICEID_MRVL_8040T,
            "Marvell Yukon 88E8040T Fast Ethernet" },
+       { VENDORID_MARVELL, DEVICEID_MRVL_8042,
+           "Marvell Yukon 88E8042 Fast Ethernet" },
        { VENDORID_MARVELL, DEVICEID_MRVL_8048,
            "Marvell Yukon 88E8048 Fast Ethernet" },
        { VENDORID_MARVELL, DEVICEID_MRVL_4361,
@@ -221,6 +224,8 @@
            "Marvell Yukon 88E8071 Gigabit Ethernet" },
        { VENDORID_MARVELL, DEVICEID_MRVL_436C,
            "Marvell Yukon 88E8072 Gigabit Ethernet" },
+       { VENDORID_MARVELL, DEVICEID_MRVL_4380,
+           "Marvell Yukon 88E8057 Gigabit Ethernet" },
        { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX,
            "D-Link 550SX Gigabit Ethernet" },
        { VENDORID_DLINK, DEVICEID_DLINK_DGE560SX,
@@ -235,7 +240,9 @@
         "Yukon EX",
         "Yukon EC",
         "Yukon FE",
-        "Yukon FE+"
+        "Yukon FE+",
+        "Yukon Supreme",
+        "Yukon Ultra 2"
 };
 
 static int mskc_probe(device_t);
@@ -252,9 +259,7 @@
 static int msk_detach(device_t);
 
 static void msk_tick(void *);
-static void msk_legacy_intr(void *);
-static int msk_intr(void *);
-static void msk_int_task(void *, int);
+static void msk_intr(void *);
 static void msk_intr_phy(struct msk_if_softc *);
 static void msk_intr_gmac(struct msk_if_softc *);
 static __inline void msk_rxput(struct msk_if_softc *);
@@ -268,8 +273,8 @@
 static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, uint32_t, int);
 static void msk_txeof(struct msk_if_softc *, int);
 static int msk_encap(struct msk_if_softc *, struct mbuf **);
-static void msk_tx_task(void *, int);
 static void msk_start(struct ifnet *);
+static void msk_start_locked(struct ifnet *);
 static int msk_ioctl(struct ifnet *, u_long, caddr_t);
 static void msk_set_prefetch(struct msk_softc *, int, bus_addr_t, uint32_t);
 static void msk_set_rambuffer(struct msk_if_softc *);
@@ -388,12 +393,6 @@
        { -1,                   0,              0 }
 };
 
-static struct resource_spec msk_irq_spec_msi2[] = {
-       { SYS_RES_IRQ,          1,              RF_ACTIVE },
-       { SYS_RES_IRQ,          2,              RF_ACTIVE },
-       { -1,                   0,              0 }
-};
-
 static int
 msk_miibus_readreg(device_t dev, int phy, int reg)
 {
@@ -533,28 +532,25 @@
                        break;
                }
 
-               if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0)
-                       gmac |= GM_GPCR_DUP_FULL;
                /* Disable Rx flow control. */
-               if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) == 0)
+               if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FLAG0) == 0)
                        gmac |= GM_GPCR_FC_RX_DIS;
                /* Disable Tx flow control. */
-               if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) == 0)
+               if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FLAG1) == 0)
                        gmac |= GM_GPCR_FC_TX_DIS;
+               if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
+                       gmac |= GM_GPCR_DUP_FULL;
+               else
+                       gmac |= GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS;
                gmac |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
                GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
                /* Read again to ensure writing. */
                GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL);
-
-               gmac = GMC_PAUSE_ON;
-               if (((mii->mii_media_active & IFM_GMASK) &
-                   (IFM_FLAG0 | IFM_FLAG1)) == 0)
-                       gmac = GMC_PAUSE_OFF;
-               /* Diable pause for 10/100 Mbps in half-duplex mode. */
-               if ((((mii->mii_media_active & IFM_GMASK) & IFM_FDX) == 0) &&
-                   (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX ||
-                   IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T))
-                       gmac = GMC_PAUSE_OFF;
+               gmac = GMC_PAUSE_OFF;
+               if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+                       if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FLAG0) != 
0)
+                               gmac = GMC_PAUSE_ON;
+               }
                CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), gmac);
 
                /* Enable PHY interrupt for FIFO underrun/overflow. */
@@ -733,6 +729,7 @@
        int i;
 
        sc_if->msk_cdata.msk_tso_mtu = 0;
+       sc_if->msk_cdata.msk_last_csum = 0;
        sc_if->msk_cdata.msk_tx_prod = 0;
        sc_if->msk_cdata.msk_tx_cons = 0;
        sc_if->msk_cdata.msk_tx_cnt = 0;
@@ -1001,11 +998,6 @@
                if ((mask & IFCAP_RXCSUM) != 0 &&
                    (IFCAP_RXCSUM & ifp->if_capabilities) != 0)
                        ifp->if_capenable ^= IFCAP_RXCSUM;
-               if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
-                   (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
-                       ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
-                       msk_setvlan(sc_if, ifp);
-               }
                if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
                    (IFCAP_VLAN_HWCSUM & ifp->if_capabilities) != 0)
                        ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
@@ -1017,6 +1009,16 @@
                        else
                                ifp->if_hwassist &= ~CSUM_TSO;
                }
+               if ((mask & IFCAP_VLAN_HWTSO) != 0 &&
+                   (IFCAP_VLAN_HWTSO & ifp->if_capabilities) != 0)
+                       ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
+               if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+                   (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
+                       ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
+                       if ((IFCAP_VLAN_HWTAGGING & ifp->if_capenable) == 0)
+                               ifp->if_capenable &= ~IFCAP_VLAN_HWTSO;
+                       msk_setvlan(sc_if, ifp);
+               }
                if (ifp->if_mtu > ETHERMTU &&
                    (sc_if->msk_flags & MSK_FLAG_JUMBO_NOCSUM) != 0) {
                        ifp->if_hwassist &= ~(MSK_CSUM_FEATURES | CSUM_TSO);
@@ -1142,6 +1144,7 @@
                case CHIP_ID_YUKON_EC_U:
                case CHIP_ID_YUKON_EX:
                case CHIP_ID_YUKON_FE_P:
+               case CHIP_ID_YUKON_UL_2:
                        CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_OFF);
 
                        /* Enable all clocks. */
@@ -1344,35 +1347,22 @@
          * On dual port PCI-X card, there is an problem where status
          * can be received out of order due to split transactions.
          */
-       if (sc->msk_bustype == MSK_PCIX_BUS && sc->msk_num_port > 1) {
-               int pcix;
+       if (sc->msk_pcixcap != 0 && sc->msk_num_port > 1) {
                uint16_t pcix_cmd;
 
-               if (pci_find_extcap(sc->msk_dev, PCIY_PCIX, &pcix) == 0) {
-                       pcix_cmd = pci_read_config(sc->msk_dev, pcix + 2, 2);
-                       /* Clear Max Outstanding Split Transactions. */
-                       pcix_cmd &= ~0x70;
-                       CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-                       pci_write_config(sc->msk_dev, pcix + 2, pcix_cmd, 2);
-                       CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-               }
+               pcix_cmd = pci_read_config(sc->msk_dev,
+                   sc->msk_pcixcap + PCIXR_COMMAND, 2);
+               /* Clear Max Outstanding Split Transactions. */
+               pcix_cmd &= ~PCIXM_COMMAND_MAX_SPLITS;
+               CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+               pci_write_config(sc->msk_dev,
+                   sc->msk_pcixcap + PCIXR_COMMAND, pcix_cmd, 2);
+               CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
         }
-       if (sc->msk_bustype == MSK_PEX_BUS) {
-               uint16_t v, width;
-
-               v = pci_read_config(sc->msk_dev, PEX_DEV_CTRL, 2);
-               /* Change Max. Read Request Size to 4096 bytes. */
-               v &= ~PEX_DC_MAX_RRS_MSK;
-               v |= PEX_DC_MAX_RD_RQ_SIZE(5);
-               pci_write_config(sc->msk_dev, PEX_DEV_CTRL, v, 2);
-               width = pci_read_config(sc->msk_dev, PEX_LNK_STAT, 2);
-               width = (width & PEX_LS_LINK_WI_MSK) >> 4;
-               v = pci_read_config(sc->msk_dev, PEX_LNK_CAP, 2);
-               v = (v & PEX_LS_LINK_WI_MSK) >> 4;
-               if (v != width)
-                       device_printf(sc->msk_dev,
-                           "negotiated width of link(x%d) != "
-                           "max. width of link(x%d)\n", width, v); 
+       if (sc->msk_expcap != 0) {
+               /* Change Max. Read Request Size to 2048 bytes. */
+               if (pci_get_max_read_req(sc->msk_dev) == 512)
+                       pci_set_max_read_req(sc->msk_dev, 2048);
        }
 
        /* Clear status list. */
@@ -1510,22 +1500,17 @@
         * Enable Rx checksum offloading if controller support new
         * descriptor format.
         */
-       if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 && 
+       if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 &&
            (sc_if->msk_flags & MSK_FLAG_NORX_CSUM) == 0)
                ifp->if_capabilities |= IFCAP_RXCSUM;
        ifp->if_hwassist = MSK_CSUM_FEATURES | CSUM_TSO;
        ifp->if_capenable = ifp->if_capabilities;
        ifp->if_ioctl = msk_ioctl;
        ifp->if_start = msk_start;
-       ifp->if_timer = 0;
-       ifp->if_watchdog = NULL;
        ifp->if_init = msk_init;
        IFQ_SET_MAXLEN(&ifp->if_snd, MSK_TX_RING_CNT - 1);
        ifp->if_snd.ifq_drv_maxlen = MSK_TX_RING_CNT - 1;
        IFQ_SET_READY(&ifp->if_snd);
-
-       TASK_INIT(&sc_if->msk_tx_task, 1, msk_tx_task, ifp);
-
        /*
         * Get station address for this interface. Note that
         * dual port cards actually come with three station
@@ -1555,12 +1540,12 @@
                 * this workaround does not work so disable checksum offload
                 * for VLAN interface.
                 */
-               ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+               ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO;
                /*
                 * Enable Rx checksum offloading for VLAN taggedd frames
                 * if controller support new descriptor format.
                 */
-               if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 && 
+               if ((sc_if->msk_flags & MSK_FLAG_DESCV2) != 0 &&
                    (sc_if->msk_flags & MSK_FLAG_NORX_CSUM) == 0)
                        ifp->if_capabilities |= IFCAP_VLAN_HWCSUM;
        }
@@ -1645,7 +1630,8 @@
        sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f;
        /* Bail out if chip is not recognized. */
        if (sc->msk_hw_id < CHIP_ID_YUKON_XL ||
-           sc->msk_hw_id > CHIP_ID_YUKON_FE_P) {
+           sc->msk_hw_id > CHIP_ID_YUKON_UL_2 ||
+           sc->msk_hw_id == CHIP_ID_YUKON_SUPR) {
                device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n",
                    sc->msk_hw_id, sc->msk_hw_rev);
                mtx_destroy(&sc->msk_mtx);
@@ -1670,6 +1656,14 @@
                }
        }
 
+       sc->msk_int_holdoff = MSK_INT_HOLDOFF_DEFAULT;
+       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+           "int_holdoff", CTLFLAG_RW, &sc->msk_int_holdoff, 0,
+           "Maximum number of time to delay interrupts");
+       resource_int_value(device_get_name(dev), device_get_unit(dev),
+           "int_holdoff", &sc->msk_int_holdoff);
+
        /* Soft reset. */
        CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
        CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
@@ -1683,24 +1677,26 @@
        }
 
        /* Check bus type. */
-       if (pci_find_extcap(sc->msk_dev, PCIY_EXPRESS, &reg) == 0)
+       if (pci_find_extcap(sc->msk_dev, PCIY_EXPRESS, &reg) == 0) {
                sc->msk_bustype = MSK_PEX_BUS;
-       else if (pci_find_extcap(sc->msk_dev, PCIY_PCIX, &reg) == 0)
+               sc->msk_expcap = reg;
+       } else if (pci_find_extcap(sc->msk_dev, PCIY_PCIX, &reg) == 0) {
                sc->msk_bustype = MSK_PCIX_BUS;
-       else
+               sc->msk_pcixcap = reg;
+       } else
                sc->msk_bustype = MSK_PCI_BUS;
 
        switch (sc->msk_hw_id) {
        case CHIP_ID_YUKON_EC:
-               sc->msk_clock = 125;    /* 125 Mhz */
+               sc->msk_clock = 125;    /* 125 MHz */
                sc->msk_pflags |= MSK_FLAG_JUMBO;
                break;
        case CHIP_ID_YUKON_EC_U:
-               sc->msk_clock = 125;    /* 125 Mhz */
+               sc->msk_clock = 125;    /* 125 MHz */
                sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_JUMBO_NOCSUM;
                break;
        case CHIP_ID_YUKON_EX:
-               sc->msk_clock = 125;    /* 125 Mhz */
+               sc->msk_clock = 125;    /* 125 MHz */
                sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_DESCV2 |
                    MSK_FLAG_AUTOTX_CSUM;
                /*
@@ -1718,11 +1714,11 @@
                        sc->msk_pflags |= MSK_FLAG_JUMBO_NOCSUM;
                break;
        case CHIP_ID_YUKON_FE:
-               sc->msk_clock = 100;    /* 100 Mhz */
+               sc->msk_clock = 100;    /* 100 MHz */
                sc->msk_pflags |= MSK_FLAG_FASTETHER;
                break;
        case CHIP_ID_YUKON_FE_P:
-               sc->msk_clock = 50;     /* 50 Mhz */
+               sc->msk_clock = 50;     /* 50 MHz */
                sc->msk_pflags |= MSK_FLAG_FASTETHER | MSK_FLAG_DESCV2 |
                    MSK_FLAG_AUTOTX_CSUM;
                if (sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) {
@@ -1741,11 +1737,15 @@
                }
                break;
        case CHIP_ID_YUKON_XL:
-               sc->msk_clock = 156;    /* 156 Mhz */
+               sc->msk_clock = 156;    /* 156 MHz */
                sc->msk_pflags |= MSK_FLAG_JUMBO;
                break;
+       case CHIP_ID_YUKON_UL_2:
+               sc->msk_clock = 125;    /* 125 MHz */
+               sc->msk_pflags |= MSK_FLAG_JUMBO;
+               break;
        default:
-               sc->msk_clock = 156;    /* 156 Mhz */
+               sc->msk_clock = 156;    /* 156 MHz */
                break;
        }
 
@@ -1753,37 +1753,16 @@
        msic = pci_msi_count(dev);
        if (bootverbose)
                device_printf(dev, "MSI count : %d\n", msic);
-       /*
-        * The Yukon II reports it can handle two messages, one for each
-        * possible port.  We go ahead and allocate two messages and only
-        * setup a handler for both if we have a dual port card.
-        *
-        * XXX: I haven't untangled the interrupt handler to handle dual
-        * port cards with separate MSI messages, so for now I disable MSI
-        * on dual port cards.
-        */
        if (legacy_intr != 0)
                msi_disable = 1;
-       if (msi_disable == 0) {
-               switch (msic) {
-               case 2:
-               case 1: /* 88E8058 reports 1 MSI message */
-                       msir = msic;
-                       if (sc->msk_num_port == 1 &&
-                           pci_alloc_msi(dev, &msir) == 0) {
-                               if (msic == msir) {
-                                       sc->msk_pflags |= MSK_FLAG_MSI;
-                                       sc->msk_irq_spec = msic == 2 ?
-                                           msk_irq_spec_msi2 :
-                                           msk_irq_spec_msi;
-                               } else
-                                       pci_release_msi(dev);
-                       }
-                       break;
-               default:
-                       device_printf(dev,
-                           "Unexpected number of MSI messages : %d\n", msic);
-                       break;
+       if (msi_disable == 0 && msic > 0) {
+               msir = 1;
+               if (pci_alloc_msi(dev, &msir) == 0) {
+                       if (msir == 1) {
+                               sc->msk_pflags |= MSK_FLAG_MSI;
+                               sc->msk_irq_spec = msk_irq_spec_msi;
+                       } else
+                               pci_release_msi(dev);
                }
        }
 
@@ -1854,25 +1833,10 @@
        }
 
        /* Hook interrupt last to avoid having to lock softc. */
-       if (legacy_intr)
-               error = bus_setup_intr(dev, sc->msk_irq[0], INTR_TYPE_NET |
-                   INTR_MPSAFE, NULL, msk_legacy_intr, sc,
-                   &sc->msk_intrhand[0]);
-       else {
-               TASK_INIT(&sc->msk_int_task, 0, msk_int_task, sc);
-               sc->msk_tq = taskqueue_create_fast("msk_taskq", M_WAITOK,
-                   taskqueue_thread_enqueue, &sc->msk_tq);
-               taskqueue_start_threads(&sc->msk_tq, 1, PI_NET, "%s taskq",
-                   device_get_nameunit(sc->msk_dev));
-               error = bus_setup_intr(dev, sc->msk_irq[0], INTR_TYPE_NET |
-                   INTR_MPSAFE, msk_intr, NULL, sc, &sc->msk_intrhand[0]);
-       }
-
+       error = bus_setup_intr(dev, sc->msk_irq[0], INTR_TYPE_NET |
+           INTR_MPSAFE, NULL, msk_intr, sc, &sc->msk_intrhand);
        if (error != 0) {
                device_printf(dev, "couldn't set up interrupt handler\n");
-               if (legacy_intr == 0)
-                       taskqueue_free(sc->msk_tq);
-               sc->msk_tq = NULL;
                goto fail;
        }
 fail:
@@ -1909,7 +1873,6 @@
                /* Can't hold locks while calling detach. */
                MSK_IF_UNLOCK(sc_if);
                callout_drain(&sc_if->msk_tick_ch);
-               taskqueue_drain(taskqueue_fast, &sc_if->msk_tx_task);
                ether_ifdetach(ifp);
                MSK_IF_LOCK(sc_if);
        }
@@ -1974,19 +1937,10 @@
 
        msk_status_dma_free(sc);
 
-       if (legacy_intr == 0 && sc->msk_tq != NULL) {
-               taskqueue_drain(sc->msk_tq, &sc->msk_int_task);
-               taskqueue_free(sc->msk_tq);
-               sc->msk_tq = NULL;
+       if (sc->msk_intrhand) {
+               bus_teardown_intr(dev, sc->msk_irq[0], sc->msk_intrhand);
+               sc->msk_intrhand = NULL;
        }
-       if (sc->msk_intrhand[0]) {
-               bus_teardown_intr(dev, sc->msk_irq[0], sc->msk_intrhand[0]);
-               sc->msk_intrhand[0] = NULL;
-       }
-       if (sc->msk_intrhand[1]) {
-               bus_teardown_intr(dev, sc->msk_irq[0], sc->msk_intrhand[0]);
-               sc->msk_intrhand[1] = NULL;
-       }
        bus_release_resources(dev, sc->msk_irq_spec, sc->msk_irq);
        if ((sc->msk_pflags & MSK_FLAG_MSI) != 0)
                pci_release_msi(dev);
@@ -2516,7 +2470,7 @@
        struct mbuf *m;
        bus_dmamap_t map;
        bus_dma_segment_t txsegs[MSK_MAXTXSEGS];
-       uint32_t control, prod, si;
+       uint32_t control, csum, prod, si;
        uint16_t offset, tcp_offset, tso_mtu;
        int error, i, nseg, tso;
 
@@ -2677,7 +2631,7 @@
        }
        /* Check if we have a VLAN tag to insert. */
        if ((m->m_flags & M_VLANTAG) != 0) {
-               if (tso == 0) {
+               if (tx_le == NULL) {
                        tx_le = &sc_if->msk_rdata.msk_tx_ring[prod];
                        tx_le->msk_addr = htole32(0);
                        tx_le->msk_control = htole32(OP_VLAN | HW_OWNER |
@@ -2695,17 +2649,22 @@
                if ((sc_if->msk_flags & MSK_FLAG_AUTOTX_CSUM) != 0)
                        control |= CALSUM;
                else {
-                       tx_le = &sc_if->msk_rdata.msk_tx_ring[prod];
-                       tx_le->msk_addr = htole32(((tcp_offset +
-                           m->m_pkthdr.csum_data) & 0xffff) |
-                           ((uint32_t)tcp_offset << 16));
-                       tx_le->msk_control = htole32(1 << 16 |
-                           (OP_TCPLISW | HW_OWNER));
-                       control = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+                       control |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
                        if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
                                control |= UDPTCP;
-                       sc_if->msk_cdata.msk_tx_cnt++;
-                       MSK_INC(prod, MSK_TX_RING_CNT);
+                       /* Checksum write position. */
+                       csum = (tcp_offset + m->m_pkthdr.csum_data) & 0xffff;
+                       /* Checksum start position. */
+                       csum |= (uint32_t)tcp_offset << 16;
+                       if (csum != sc_if->msk_cdata.msk_last_csum) {
+                               tx_le = &sc_if->msk_rdata.msk_tx_ring[prod];
+                               tx_le->msk_addr = htole32(csum);
+                               tx_le->msk_control = htole32(1 << 16 |
+                                   (OP_TCPLISW | HW_OWNER));
+                               sc_if->msk_cdata.msk_tx_cnt++;
+                               MSK_INC(prod, MSK_TX_RING_CNT);
+                               sc_if->msk_cdata.msk_last_csum = csum;
+                       }
                }
        }
 
@@ -2757,30 +2716,29 @@
 }
 
 static void
-msk_tx_task(void *arg, int pending)
+msk_start(struct ifnet *ifp)
 {
-       struct ifnet *ifp;
+       struct msk_if_softc *sc_if;
 
-       ifp = arg;
-       msk_start(ifp);
+       sc_if = ifp->if_softc;
+       MSK_IF_LOCK(sc_if);
+       msk_start_locked(ifp);
+       MSK_IF_UNLOCK(sc_if);
 }
 
 static void
-msk_start(struct ifnet *ifp)
+msk_start_locked(struct ifnet *ifp)
 {
-        struct msk_if_softc *sc_if;
-        struct mbuf *m_head;
+       struct msk_if_softc *sc_if;
+       struct mbuf *m_head;
        int enq;
 
        sc_if = ifp->if_softc;
+       MSK_IF_LOCK_ASSERT(sc_if);
 
-       MSK_IF_LOCK(sc_if);
-
        if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
-           IFF_DRV_RUNNING || (sc_if->msk_flags & MSK_FLAG_LINK) == 0) {
-               MSK_IF_UNLOCK(sc_if);
+           IFF_DRV_RUNNING || (sc_if->msk_flags & MSK_FLAG_LINK) == 0)
                return;
-       }
 
        for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
            sc_if->msk_cdata.msk_tx_cnt <
@@ -2818,16 +2776,12 @@
                /* Set a timeout in case the chip goes out to lunch. */
                sc_if->msk_watchdog_timer = MSK_TX_TIMEOUT;
        }
-
-       MSK_IF_UNLOCK(sc_if);
 }
 
 static void
 msk_watchdog(struct msk_if_softc *sc_if)
 {
        struct ifnet *ifp;
-       uint32_t ridx;
-       int idx;
 
        MSK_IF_LOCK_ASSERT(sc_if);
 
@@ -2844,30 +2798,12 @@
                return;
        }
 
-       /*
-        * Reclaim first as there is a possibility of losing Tx completion
-        * interrupts.
-        */
-       ridx = sc_if->msk_port == MSK_PORT_A ? STAT_TXA1_RIDX : STAT_TXA2_RIDX;
-       idx = CSR_READ_2(sc_if->msk_softc, ridx);
-       if (sc_if->msk_cdata.msk_tx_cons != idx) {
-               msk_txeof(sc_if, idx);
-               if (sc_if->msk_cdata.msk_tx_cnt == 0) {
-                       if_printf(ifp, "watchdog timeout (missed Tx interrupts) 
"
-                           "-- recovering\n");
-                       if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-                               taskqueue_enqueue(taskqueue_fast,
-                                   &sc_if->msk_tx_task);
-                       return;
-               }
-       }
-
        if_printf(ifp, "watchdog timeout\n");
        ifp->if_oerrors++;
        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
        msk_init_locked(sc_if);
        if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-               taskqueue_enqueue(taskqueue_fast, &sc_if->msk_tx_task);
+               msk_start_locked(ifp);
 }
 
 static int
@@ -3189,6 +3125,9 @@
        mii = device_get_softc(sc_if->msk_miibus);
 
        mii_tick(mii);
+       if ((sc_if->msk_flags & MSK_FLAG_LINK) == 0)
+               msk_miibus_statchg(sc_if->msk_if_dev);
+       msk_handle_events(sc_if->msk_softc);
        msk_watchdog(sc_if);
        callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if);
 }
@@ -3216,11 +3155,9 @@
        status = CSR_READ_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_SRC));
 
        /* GMAC Rx FIFO overrun. */
-       if ((status & GM_IS_RX_FF_OR) != 0) {
+       if ((status & GM_IS_RX_FF_OR) != 0)
                CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T),
                    GMF_CLI_RX_FO);
-               device_printf(sc_if->msk_if_dev, "Rx FIFO overrun!\n");
-       }
        /* GMAC Tx FIFO underrun. */
        if ((status & GM_IS_TX_FF_UR) != 0) {
                CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T),
@@ -3389,32 +3326,20 @@
        int rxput[2];
        struct msk_stat_desc *sd;
        uint32_t control, status;
-       int cons, idx, len, port, rxprog;
+       int cons, len, port, rxprog;
 
-       idx = CSR_READ_2(sc, STAT_PUT_IDX);
-       if (idx == sc->msk_stat_cons)
-               return (0);
-
        /* Sync status LEs. */
        bus_dmamap_sync(sc->msk_stat_tag, sc->msk_stat_map,
            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-       /* XXX Sync Rx LEs here. */
 
        rxput[MSK_PORT_A] = rxput[MSK_PORT_B] = 0;
-
        rxprog = 0;
-       for (cons = sc->msk_stat_cons; cons != idx;) {
+       cons = sc->msk_stat_cons;
+       for (;;) {
                sd = &sc->msk_stat_ring[cons];
                control = le32toh(sd->msk_control);
                if ((control & HW_OWNER) == 0)
                        break;
-               /*
-                * Marvell's FreeBSD driver updates status LE after clearing
-                * HW_OWNER. However we don't have a way to sync single LE
-                * with bus_dma(9) API. bus_dma(9) provides a way to sync
-                * an entire DMA map. So don't sync LE until we have a better
-                * way to sync LEs.
-                */
                control &= ~HW_OWNER;
                sd->msk_control = htole32(control);
                status = le32toh(sd->msk_status);
@@ -3475,24 +3400,25 @@
        }
 
        sc->msk_stat_cons = cons;
-       /* XXX We should sync status LEs here. See above notes. */
+       bus_dmamap_sync(sc->msk_stat_tag, sc->msk_stat_map,
+           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        if (rxput[MSK_PORT_A] > 0)
                msk_rxput(sc->msk_if[MSK_PORT_A]);
        if (rxput[MSK_PORT_B] > 0)
                msk_rxput(sc->msk_if[MSK_PORT_B]);
 
-       return (sc->msk_stat_cons != CSR_READ_2(sc, STAT_PUT_IDX));
+       return (rxprog > sc->msk_process_limit ? EAGAIN : 0);
 }
 
-/* Legacy interrupt handler for shared interrupt. */
 static void
-msk_legacy_intr(void *xsc)
+msk_intr(void *xsc)
 {
        struct msk_softc *sc;
        struct msk_if_softc *sc_if0, *sc_if1;
        struct ifnet *ifp0, *ifp1;
        uint32_t status;
+       int domore;
 
        sc = xsc;
        MSK_LOCK(sc);
@@ -3537,9 +3463,8 @@
        if ((status & Y2_IS_HW_ERR) != 0)
                msk_intr_hwerr(sc);
 
-       while (msk_handle_events(sc) != 0)
-               ;
-       if ((status & Y2_IS_STAT_BMU) != 0)
+       domore = msk_handle_events(sc);
+       if ((status & Y2_IS_STAT_BMU) != 0 && domore == 0)
                CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ);
 
        /* Reenable interrupts. */
@@ -3547,106 +3472,15 @@
 
        if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
            !IFQ_DRV_IS_EMPTY(&ifp0->if_snd))
-               taskqueue_enqueue(taskqueue_fast, &sc_if0->msk_tx_task);
+               msk_start_locked(ifp0);
        if (ifp1 != NULL && (ifp1->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
            !IFQ_DRV_IS_EMPTY(&ifp1->if_snd))
-               taskqueue_enqueue(taskqueue_fast, &sc_if1->msk_tx_task);
+               msk_start_locked(ifp1);
 
        MSK_UNLOCK(sc);
 }
 
-static int
-msk_intr(void *xsc)
-{
-       struct msk_softc *sc;
-       uint32_t status;
-
-       sc = xsc;
-       status = CSR_READ_4(sc, B0_Y2_SP_ISRC2);
-       /* Reading B0_Y2_SP_ISRC2 masks further interrupts. */
-       if (status == 0 || status == 0xffffffff) {
-               CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
-               return (FILTER_STRAY);
-       }
-
-       taskqueue_enqueue(sc->msk_tq, &sc->msk_int_task);
-       return (FILTER_HANDLED);
-}
-
 static void
-msk_int_task(void *arg, int pending)
-{
-       struct msk_softc *sc;
-       struct msk_if_softc *sc_if0, *sc_if1;
-       struct ifnet *ifp0, *ifp1;
-       uint32_t status;
-       int domore;
-
-       sc = arg;
-       MSK_LOCK(sc);
-
-       /* Get interrupt source. */
-       status = CSR_READ_4(sc, B0_ISRC);
-       if (status == 0 || status == 0xffffffff ||
-           (sc->msk_pflags & MSK_FLAG_SUSPEND) != 0 ||
-           (status & sc->msk_intrmask) == 0)
-               goto done;
-
-       sc_if0 = sc->msk_if[MSK_PORT_A];
-       sc_if1 = sc->msk_if[MSK_PORT_B];
-       ifp0 = ifp1 = NULL;
-       if (sc_if0 != NULL)
-               ifp0 = sc_if0->msk_ifp;
-       if (sc_if1 != NULL)
-               ifp1 = sc_if1->msk_ifp;
-
-       if ((status & Y2_IS_IRQ_PHY1) != 0 && sc_if0 != NULL)
-               msk_intr_phy(sc_if0);
-       if ((status & Y2_IS_IRQ_PHY2) != 0 && sc_if1 != NULL)
-               msk_intr_phy(sc_if1);
-       if ((status & Y2_IS_IRQ_MAC1) != 0 && sc_if0 != NULL)
-               msk_intr_gmac(sc_if0);
-       if ((status & Y2_IS_IRQ_MAC2) != 0 && sc_if1 != NULL)
-               msk_intr_gmac(sc_if1);
-       if ((status & (Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2)) != 0) {
-               device_printf(sc->msk_dev, "Rx descriptor error\n");
-               sc->msk_intrmask &= ~(Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2);
-               CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask);
-               CSR_READ_4(sc, B0_IMSK);
-       }
-        if ((status & (Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2)) != 0) {
-               device_printf(sc->msk_dev, "Tx descriptor error\n");
-               sc->msk_intrmask &= ~(Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2);
-               CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask);
-               CSR_READ_4(sc, B0_IMSK);
-       }
-       if ((status & Y2_IS_HW_ERR) != 0)
-               msk_intr_hwerr(sc);
-
-       domore = msk_handle_events(sc);
-       if ((status & Y2_IS_STAT_BMU) != 0)
-               CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ);
-
-       if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
-           !IFQ_DRV_IS_EMPTY(&ifp0->if_snd))
-               taskqueue_enqueue(taskqueue_fast, &sc_if0->msk_tx_task);
-       if (ifp1 != NULL && (ifp1->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
-           !IFQ_DRV_IS_EMPTY(&ifp1->if_snd))
-               taskqueue_enqueue(taskqueue_fast, &sc_if1->msk_tx_task);
-
-       if (domore > 0) {
-               taskqueue_enqueue(sc->msk_tq, &sc->msk_int_task);
-               MSK_UNLOCK(sc);
-               return;
-       }
-done:
-       MSK_UNLOCK(sc);
-
-       /* Reenable interrupts. */
-       CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
-}
-
-static void
 msk_set_tx_stfwd(struct msk_if_softc *sc_if)
 {
        struct msk_softc *sc;
@@ -3704,10 +3538,10 @@
        struct msk_softc *sc;
        struct ifnet *ifp;
        struct mii_data  *mii;
-       uint16_t eaddr[ETHER_ADDR_LEN / 2];
+       uint8_t *eaddr;
        uint16_t gmac;
        uint32_t reg;
-       int error, i;
+       int error;
 
        MSK_IF_LOCK_ASSERT(sc_if);
 
@@ -3741,7 +3575,7 @@
                CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL),
                    GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON |
                    GMC_BYP_RETR_ON);
- 
+
        /*
         * Initialize GMAC first such that speed/duplex/flow-control
         * parameters are renegotiated when interface is brought up.
@@ -3776,13 +3610,19 @@
        GMAC_WRITE_2(sc, sc_if->msk_port, GM_SERIAL_MODE, gmac);
 
        /* Set station address. */
-        bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
-        for (i = 0; i < ETHER_ADDR_LEN /2; i++)
-               GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1L + i * 4,
-                   eaddr[i]);
-        for (i = 0; i < ETHER_ADDR_LEN /2; i++)
-               GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2L + i * 4,
-                   eaddr[i]);
+       eaddr = IF_LLADDR(ifp);
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1L,
+           eaddr[0] | (eaddr[1] << 8));
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1M,
+           eaddr[2] | (eaddr[3] << 8));
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1H,
+           eaddr[4] | (eaddr[5] << 8));
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2L,
+           eaddr[0] | (eaddr[1] << 8));
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2M,
+           eaddr[2] | (eaddr[3] << 8));
+       GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2H,
+           eaddr[4] | (eaddr[5] << 8));
 
        /* Disable interrupts for counter overflows. */
        GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_IRQ_MSK, 0);
@@ -3930,6 +3770,17 @@
                sc->msk_intrmask |= Y2_IS_PORT_B;
                sc->msk_intrhwemask |= Y2_HWE_L2_MASK;
        }
+       /* Configure IRQ moderation mask. */
+       CSR_WRITE_4(sc, B2_IRQM_MSK, sc->msk_intrmask);
+       if (sc->msk_int_holdoff > 0) {
+               /* Configure initial IRQ moderation timer value. */
+               CSR_WRITE_4(sc, B2_IRQM_INI,
+                   MSK_USECS(sc, sc->msk_int_holdoff));
+               CSR_WRITE_4(sc, B2_IRQM_VAL,
+                   MSK_USECS(sc, sc->msk_int_holdoff));
+               /* Start IRQ moderation. */
+               CSR_WRITE_1(sc, B2_IRQM_CTRL, TIM_START);
+       }
        CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask);
        CSR_READ_4(sc, B0_HWE_IMSK);
        CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask);
Index: dev/msk/if_mskreg.h
===================================================================
--- dev/msk/if_mskreg.h (revision 35579)
+++ dev/msk/if_mskreg.h (working copy)
@@ -93,7 +93,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/*$FreeBSD$*/
+/*$FreeBSD: src/sys/dev/msk/if_mskreg.h,v 1.36 2010/03/02 01:45:02 yongari Exp 
$*/
 
 /*
  * SysKonnect PCI vendor ID
@@ -133,6 +133,7 @@
 #define DEVICEID_MRVL_8039     0x4353
 #define DEVICEID_MRVL_8040     0x4354
 #define DEVICEID_MRVL_8040T    0x4355
+#define DEVICEID_MRVL_8042     0x4357
 #define DEVICEID_MRVL_8048     0x435A
 #define DEVICEID_MRVL_4360     0x4360
 #define DEVICEID_MRVL_4361     0x4361
@@ -143,6 +144,7 @@
 #define DEVICEID_MRVL_436A     0x436A
 #define DEVICEID_MRVL_436B     0x436B
 #define DEVICEID_MRVL_436C     0x436C
+#define DEVICEID_MRVL_4380     0x4380
 
 /*
  * D-Link gigabit ethernet device ID
@@ -890,6 +892,8 @@
 #define CHIP_ID_YUKON_EC       0xb6 /* Chip ID for YUKON-2 EC */
 #define CHIP_ID_YUKON_FE       0xb7 /* Chip ID for YUKON-2 FE */
 #define CHIP_ID_YUKON_FE_P     0xb8 /* Chip ID for YUKON-2 FE+ */
+#define CHIP_ID_YUKON_SUPR     0xb9 /* Chip ID for YUKON-2 Supreme */
+#define CHIP_ID_YUKON_UL_2     0xba /* Chip ID for YUKON-2 Ultra 2 */
 
 #define        CHIP_REV_YU_XL_A0       0 /* Chip Rev. for Yukon-2 A0 */
 #define        CHIP_REV_YU_XL_A1       1 /* Chip Rev. for Yukon-2 A1 */
@@ -2357,6 +2361,7 @@
        bus_dmamap_t            msk_jumbo_rx_ring_map;
        bus_dmamap_t            msk_jumbo_rx_sparemap;
        uint16_t                msk_tso_mtu;
+       uint32_t                msk_last_csum;
        int                     msk_tx_prod;
        int                     msk_tx_cons;
        int                     msk_tx_cnt;
@@ -2401,6 +2406,8 @@
 #define        MSK_PROC_MIN            30
 #define        MSK_PROC_MAX            (MSK_RX_RING_CNT - 1)
 
+#define        MSK_INT_HOLDOFF_DEFAULT 100
+
 #define        MSK_TX_TIMEOUT          5
 #define        MSK_PUT_WM      10
 
@@ -2463,14 +2470,16 @@
 struct msk_softc {
        struct resource         *msk_res[1];    /* I/O resource */
        struct resource_spec    *msk_res_spec;
-       struct resource         *msk_irq[2];    /* IRQ resources */
+       struct resource         *msk_irq[1];    /* IRQ resources */
        struct resource_spec    *msk_irq_spec;
-       void                    *msk_intrhand[2]; /* irq handler handle */
+       void                    *msk_intrhand; /* irq handler handle */
        device_t                msk_dev;
        uint8_t                 msk_hw_id;
        uint8_t                 msk_hw_rev;
        uint8_t                 msk_bustype;
        uint8_t                 msk_num_port;
+       int                     msk_expcap;
+       int                     msk_pcixcap;
        int                     msk_ramsize;    /* amount of SRAM on NIC */
        uint32_t                msk_pmd;        /* physical media type */
        uint32_t                msk_intrmask;
@@ -2489,10 +2498,9 @@
        bus_dmamap_t            msk_stat_map;
        struct msk_stat_desc    *msk_stat_ring;
        bus_addr_t              msk_stat_ring_paddr;
+       int                     msk_int_holdoff;
        int                     msk_process_limit;
        int                     msk_stat_cons;
-       struct taskqueue        *msk_tq;
-       struct task             msk_int_task;
        struct mtx              msk_mtx;
 };
 
@@ -2537,7 +2545,6 @@
        struct msk_ring_data    msk_rdata;
        struct msk_softc        *msk_softc;     /* parent controller */
        struct msk_hw_stats     msk_stats;
-       struct task             msk_tx_task;
        int                     msk_if_flags;
        uint16_t                msk_vtag;       /* VLAN tag id. */
 };
Index: dev/msk/glue.c
===================================================================
--- dev/msk/glue.c      (revision 35579)
+++ dev/msk/glue.c      (working copy)
@@ -7,7 +7,6 @@
 
 #include <sys/bus.h>
 
-
 HAIKU_FBSD_DRIVER_GLUE(marvell_yukon, mskc, pci)
 
 extern driver_t *DRIVER_MODULE_NAME(e1000phy, miibus);
Index: compat/machine/bus.h
===================================================================
--- compat/machine/bus.h        (revision 35579)
+++ compat/machine/bus.h        (working copy)
@@ -144,7 +144,10 @@
 void bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t handle,
        bus_size_t offset, uint32_t value);
 
+void bus_space_read_multi_8(bus_space_tag_t space, bus_space_handle_t handle,
+       bus_size_t offset, uint64_t *datap, bus_size_t count);
 
+
 static inline void
 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
        bus_size_t offset, u_int32_t *addr, size_t count)
@@ -220,6 +223,108 @@
 }
 
 
+static inline void
+bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+       bus_size_t offset, const u_int16_t *addr, size_t count)
+{
+       if (tag == I386_BUS_SPACE_IO)
+               outsw(bsh + offset, addr, count);
+       else
+       {
+               __asm __volatile("\n\
+               cld\n\
+               1:      lodsw\n\
+               movw %%ax,(%2)\n\
+               loop 1b":
+               "=S" (addr), "=c" (count):
+               "r" (bsh + offset), "" (addr), "1" (count) :
+               "%eax", "memory", "cc");
+       }
+
+}
+
+
+static inline void
+bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+       bus_size_t offset, const u_int32_t *addr, size_t count)
+{
+       if (tag == I386_BUS_SPACE_IO)
+               outsw(bsh + offset, addr, count);
+       else
+       {
+               __asm __volatile("\n\
+               cld\n\
+               1:      lodsl\n\
+               movw %%eax,(%2)\n\
+               loop 1b":
+               "=S" (addr), "=c" (count):
+               "r" (bsh + offset), "" (addr), "1" (count) :
+               "%eax", "memory", "cc");
+       }
+}
+
+
+static inline
+void bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
+       bus_size_t offset, u_int8_t *addr, bus_size_t count)
+{
+       if (tag == I386_BUS_SPACE_IO)
+               insb(bsh + offset, addr, count);
+       else
+       {
+               __asm __volatile("\n\
+               cld\n\
+               1:      movb (%2),%%al\n\
+               stosb\n\
+               loop 1b":
+               "=D" (addr), "=c" (count):
+               "r" (bsh + offset), "" (addr), "1" (count) :
+               "%eax", "memory");
+       }
+
+}
+
+
+static inline
+void bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
+       bus_size_t offset, u_int16_t *addr, bus_size_t count)
+{
+       if (tag == I386_BUS_SPACE_IO)
+               insw(bsh + offset, addr, count);
+       else
+       {
+               __asm __volatile("\n\
+               cld\n\
+               1:      movw (%2),%%ax\n\
+               stosw\n\
+               loop 1b":
+               "=D" (addr), "=c" (count):
+               "r" (bsh + offset), "" (addr), "1" (count) :
+               "%eax", "memory");
+       }
+}
+
+
+static inline
+void bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
+       bus_size_t offset, u_int32_t *addr, bus_size_t count)
+{
+       if (tag == I386_BUS_SPACE_IO)
+               insl(bsh + offset, addr, count);
+       else
+       {
+               __asm __volatile("\n\
+               cld\n\
+               1:      movl (%2),%%eax\n\
+               stosl\n\
+               loop 1b":
+               "=D" (addr), "=c" (count):
+               "r" (bsh + offset), "" (addr), "1" (count) :
+               "%eax", "memory");
+       }
+}
+
+
 #include <machine/bus_dma.h>
 
 
Index: compat/machine/cpufunc.h
===================================================================
--- compat/machine/cpufunc.h    (revision 35579)
+++ compat/machine/cpufunc.h    (working copy)
@@ -40,4 +40,50 @@
                         : "d" (port));
 }
 
+
+static __inline void
+outsw(u_int port, const void *addr, size_t cnt)
+{
+       __asm __volatile("cld; rep; outsw"
+                        : "+S" (addr), "+c" (cnt)
+                        : "d" (port));
+}
+
+
+static __inline void
+outsl(u_int port, const void *addr, size_t cnt)
+{
+       __asm __volatile("cld; rep; outsl"
+                        : "+S" (addr), "+c" (cnt)
+                        : "d" (port));
+}
+
+
+static __inline void
+insb(u_int port, void *addr, size_t cnt)
+{
+       __asm __volatile("cld; rep; insb"
+                        : "+D" (addr), "+c" (cnt)
+                        : "d" (port));
+}
+
+
+static __inline void
+insw(u_int port, void *addr, size_t cnt)
+{
+       __asm __volatile("cld; rep; insw"
+                        : "+D" (addr), "+c" (cnt)
+                        : "d" (port));
+}
+
+
+static __inline void
+insl(u_int port, void *addr, size_t cnt)
+{
+       __asm __volatile("cld; rep; insl"
+                        : "+D" (addr), "+c" (cnt)
+                        : "d" (port));
+}
+
+
 #endif /* _FBSD_COMPAT_MACHINE_CPUFUNC_H_ */
Index: compat/net/if.h
===================================================================
--- compat/net/if.h     (revision 35579)
+++ compat/net/if.h     (working copy)
@@ -27,6 +27,7 @@
 #define IFCAP_NETCONS          0x0004  /* can be a network console */
 #define        IFCAP_VLAN_MTU          0x0008  /* VLAN-compatible MTU */
 #define        IFCAP_VLAN_HWTAGGING    0x0010  /* hardware VLAN tag support */
+#define IFCAP_VLAN_HWTSO       0
 #define        IFCAP_JUMBO_MTU         0x0020  /* 9000 byte MTU supported */
 #define        IFCAP_POLLING           0x0040  /* driver supports polling */
 #define        IFCAP_VLAN_HWCSUM       0x0080
Index: compat/dev/pci/pcivar.h
===================================================================
--- compat/dev/pci/pcivar.h     (revision 35579)
+++ compat/dev/pci/pcivar.h     (working copy)
@@ -21,6 +21,7 @@
 
 
 int pci_enable_busmaster(device_t dev);
+int pci_disable_busmaster(device_t dev);
 int pci_enable_io(device_t dev, int reg);
 
 uint32_t pci_get_devid(device_t dev);
@@ -54,6 +55,9 @@
 int pci_get_powerstate(device_t dev);
 int pci_set_powerstate(device_t dev, int newPowerState);
 
+int pci_get_max_read_req(device_t dev);
+int pci_set_max_read_req(device_t dev, int size);
+
 static inline int
 pci_get_vpd_ident(device_t dev, const char **identptr)
 {
Index: compat/sys/bus.h
===================================================================
--- compat/sys/bus.h    (revision 35579)
+++ compat/sys/bus.h    (working copy)
@@ -99,10 +99,12 @@
 int device_get_unit(device_t dev);
 void *device_get_softc(device_t dev);
 int device_printf(device_t dev, const char *, ...) __printflike(2, 3);
+int device_probe_and_attach(device_t dev);
 void device_set_desc(device_t dev, const char *desc);
 void device_set_desc_copy(device_t dev, const char *desc);
 const char *device_get_desc(device_t dev);
 device_t device_get_parent(device_t dev);
+int device_get_children(device_t dev, device_t **listp, int *countp);
 u_int32_t device_get_flags(device_t dev);
 
 void device_set_ivars(device_t dev, void *);
Index: compat/sys/libkern.h
===================================================================
--- compat/sys/libkern.h        (revision 35579)
+++ compat/sys/libkern.h        (working copy)
@@ -18,4 +18,6 @@
 
 extern int abs(int a);
 
+int fls(int);
+
 #endif /* _FBSD_COMPAT_SYS_LIBKERN_H_ */
Index: compat.c
===================================================================
--- compat.c    (revision 35579)
+++ compat.c    (working copy)
@@ -143,6 +143,13 @@
 }
 
 
+int
+device_probe_and_attach(device_t dev)
+{
+       #warning "not impl"
+}
+
+
 void
 device_set_desc(device_t dev, const char *desc)
 {
@@ -172,6 +179,38 @@
 }
 
 
+int
+device_get_children(device_t dev, device_t **listp, int *countp)
+{
+/*
+       int count;
+       device_t child;
+       device_t *list;
+
+       count = 0;
+       TAILQ_FOREACH(child, &dev->children, link) {
+               count++;
+       }
+
+       list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO);
+       if (!list)
+               return (ENOMEM);
+
+       count = 0;
+       TAILQ_FOREACH(child, &dev->children, link) {
+               list[count] = child;
+               count++;
+       }
+
+       *devlistp = list;
+       *devcountp = count;
+
+       return (0);
+*/
+       #warning "not impl"
+}
+
+
 void
 device_set_ivars(device_t dev, void *ivars)
 {
Index: libkern.c
===================================================================
--- libkern.c   (revision 35579)
+++ libkern.c   (working copy)
@@ -12,3 +12,14 @@
 {
        return random();
 }
+
+int fls(int mask)
+{
+       int bit;
+
+       if (mask == 0)
+               return (0);
+       for (bit = 1; mask != 1; bit++)
+               mask = (unsigned int)mask >> 1;
+       return (bit);
+}
Index: bus.c
===================================================================
--- bus.c       (revision 35579)
+++ bus.c       (working copy)
@@ -581,6 +581,14 @@
 }
 
 
+static void
+pci_clear_command_bit(device_t dev, uint16_t bit)
+{
+       uint16_t command = pci_read_config(dev, PCI_command, 2);
+       pci_write_config(dev, PCI_command, command & ~bit, 2);
+}
+
+
 int
 pci_enable_busmaster(device_t dev)
 {
@@ -590,6 +598,14 @@
 
 
 int
+pci_disable_busmaster(device_t dev)
+{
+       pci_clear_command_bit(dev, PCI_command_master);
+       return 0;
+}
+
+
+int
 pci_enable_io(device_t dev, int space)
 {
        /* adapted from FreeBSD's pci_enable_io_method */
@@ -785,3 +801,38 @@
 
        return EOK;
 }
+
+
+int pci_get_max_read_req(device_t dev)
+{
+       int cap;
+       uint16_t val;
+
+       if (pci_find_extcap(dev, PCIY_EXPRESS, &cap) != 0)
+               return (0);
+       val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
+       val &= PCIM_EXP_CTL_MAX_READ_REQUEST;
+       val >>= 12;
+       return (1 << (val + 7));
+}
+
+
+int pci_set_max_read_req(device_t dev, int size)
+{
+       int cap;
+       uint16_t val;
+
+       if (pci_find_extcap(dev, PCIY_EXPRESS, &cap) != 0)
+               return (0);
+       if (size < 128)
+               size = 128;
+       if (size > 4096)
+               size = 4096;
+       size = (1 << (fls(size) - 1));
+       val = pci_read_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, 2);
+       val &= ~PCIM_EXP_CTL_MAX_READ_REQUEST;
+       val |= (fls(size) - 8) << 12;
+       pci_write_config(dev, cap + PCIR_EXPRESS_DEVICE_CTL, val, 2);
+       return (size);
+}
+

Other related posts: