Index: if_bge.c =================================================================== RCS file: /home/ncvs/src/sys/dev/bge/if_bge.c,v retrieving revision 1.91.2.23 diff -p -u -u -r1.91.2.23 if_bge.c --- if_bge.c 8 May 2007 16:18:21 -0000 1.91.2.23 +++ if_bge.c 3 Dec 2007 08:55:17 -0000 @@ -106,6 +106,13 @@ __FBSDID("$FreeBSD: src/sys/dev/bge/if_b #include "miidevs.h" #include +#ifdef __sparc64__ +#include +#include +#include +#include +#endif + #include #include @@ -335,6 +342,7 @@ static int bge_read_eeprom(struct bge_so static void bge_setpromisc(struct bge_softc *); static void bge_setmulti(struct bge_softc *); +static void bge_setvlan(struct bge_softc *); static int bge_newbuf_std(struct bge_softc *, int, struct mbuf *); static int bge_newbuf_jumbo(struct bge_softc *, int, struct mbuf *); @@ -348,6 +356,7 @@ static int bge_init_tx_ring(struct bge_s static int bge_chipinit(struct bge_softc *); static int bge_blockinit(struct bge_softc *); +static int bge_has_eeprom(struct bge_softc *); static uint32_t bge_readmem_ind(struct bge_softc *, int); static void bge_writemem_ind(struct bge_softc *, int, int); #ifdef notdef @@ -382,6 +391,7 @@ static int bge_sysctl_reg_read(SYSCTL_HA static int bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS); #endif static void bge_add_sysctls(struct bge_softc *); +static int bge_sysctl_stats(SYSCTL_HANDLER_ARGS); static device_method_t bge_methods[] = { /* Device interface */ @@ -415,18 +425,58 @@ static devclass_t bge_devclass; DRIVER_MODULE(bge, pci, bge_driver, bge_devclass, 0, 0); DRIVER_MODULE(miibus, bge, miibus_driver, miibus_devclass, 0, 0); -static int bge_fake_autoneg = 0; static int bge_allow_asf = 0; -TUNABLE_INT("hw.bge.fake_autoneg", &bge_fake_autoneg); TUNABLE_INT("hw.bge.allow_asf", &bge_allow_asf); SYSCTL_NODE(_hw, OID_AUTO, bge, CTLFLAG_RD, 0, "BGE driver parameters"); -SYSCTL_INT(_hw_bge, OID_AUTO, fake_autoneg, CTLFLAG_RD, &bge_fake_autoneg, 0, - "Enable fake autonegotiation for certain blade systems"); SYSCTL_INT(_hw_bge, OID_AUTO, allow_asf, CTLFLAG_RD, &bge_allow_asf, 0, "Allow ASF mode if available"); +#define SPARC64_BLADE_1500_MODEL "SUNW,Sun-Blade-1500" +#define SPARC64_BLADE_1500_PATH_BGE "/pci@1f,700000/network@2" +#define SPARC64_BLADE_2500_MODEL "SUNW,Sun-Blade-2500" +#define SPARC64_BLADE_2500_PATH_BGE "/pci@1c,600000/network@3" +#define SPARC64_OFW_SUBVENDOR "subsystem-vendor-id" + +static int +bge_has_eeprom(struct bge_softc *sc) +{ +#ifdef __sparc64__ + char buf[sizeof(SPARC64_BLADE_1500_PATH_BGE)]; + device_t dev; + uint32_t subvendor; + + dev = sc->bge_dev; + + /* + * The on-board BGEs found in sun4u machines aren't fitted with + * an EEPROM which means that we have to obtain the MAC address + * via OFW and that some tests will always fail. We distinguish + * such BGEs by the subvendor ID, which also has to be obtained + * from OFW instead of the PCI configuration space as the latter + * indicates Broadcom as the subvendor of the netboot interface. + * For early Blade 1500 and 2500 we even have to check the OFW + * device path as the subvendor ID always defaults to Broadcom + * there. + */ + if (OF_getprop(ofw_bus_get_node(dev), SPARC64_OFW_SUBVENDOR, + &subvendor, sizeof(subvendor)) == sizeof(subvendor) && + subvendor == SUN_VENDORID) + return (0); + memset(buf, 0, sizeof(buf)); + if (OF_package_to_path(ofw_bus_get_node(dev), buf, sizeof(buf)) > 0) { + if (strcmp(sparc64_model, SPARC64_BLADE_1500_MODEL) == 0 && + strcmp(buf, SPARC64_BLADE_1500_PATH_BGE) == 0) + return (0); + if (strcmp(sparc64_model, SPARC64_BLADE_2500_MODEL) == 0 && + strcmp(buf, SPARC64_BLADE_2500_PATH_BGE) == 0) + return (0); + } +#endif + return (1); +} + static uint32_t bge_readmem_ind(struct bge_softc *sc, int off) { @@ -538,7 +588,7 @@ bge_eeprom_getbyte(struct bge_softc *sc, break; } - if (i == BGE_TIMEOUT) { + if (i == BGE_TIMEOUT * 10) { device_printf(sc->bge_dev, "EEPROM read timed out\n"); return (1); } @@ -602,6 +652,7 @@ bge_miibus_readreg(device_t dev, int phy BGE_MIPHY(phy) | BGE_MIREG(reg)); for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); val = CSR_READ_4(sc, BGE_MI_COMM); if (!(val & BGE_MICOMM_BUSY)) break; @@ -647,20 +698,21 @@ bge_miibus_writereg(device_t dev, int ph BGE_MIPHY(phy) | BGE_MIREG(reg) | val); for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) break; } + if (i == BGE_TIMEOUT) { + device_printf(sc->bge_dev, "PHY write timed out\n"); + return (0); + } + if (autopoll & BGE_MIMODE_AUTOPOLL) { BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); DELAY(40); } - if (i == BGE_TIMEOUT) { - device_printf(sc->bge_dev, "PHY read timed out\n"); - return (0); - } - return (0); } @@ -1007,6 +1059,22 @@ bge_setmulti(struct bge_softc *sc) } static void +bge_setvlan(struct bge_softc *sc) +{ + struct ifnet *ifp; + + BGE_LOCK_ASSERT(sc); + + ifp = sc->bge_ifp; + + /* Enable or disable VLAN tag stripping as needed. */ + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) + BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_KEEP_VLAN_DIAG); + else + BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_KEEP_VLAN_DIAG); +} + +static void bge_sig_pre_reset(sc, type) struct bge_softc *sc; int type; @@ -1099,9 +1167,12 @@ bge_chipinit(struct bge_softc *sc) /* * Check the 'ROM failed' bit on the RX CPU to see if - * self-tests passed. + * self-tests passed. Skip this check when there's no + * EEPROM fitted, since in that case it will always + * fail. */ - if (CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) { + if ((sc->bge_flags & BGE_FLAG_EEPROM) && + CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) { device_printf(sc->bge_dev, "RX CPU self-diagnostics failed!\n"); return (ENODEV); } @@ -1121,60 +1192,60 @@ bge_chipinit(struct bge_softc *sc) i < BGE_STATUS_BLOCK_END + 1; i += sizeof(uint32_t)) BGE_MEMWIN_WRITE(sc, i, 0); - /* Set up the PCI DMA control register. */ + /* + * Set up the PCI DMA control register. + */ + dma_rw_ctl = BGE_PCIDMARWCTL_RD_CMD_SHIFT(6) | + BGE_PCIDMARWCTL_WR_CMD_SHIFT(7); if (sc->bge_flags & BGE_FLAG_PCIE) { - /* PCI Express bus */ - dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | - BGE_PCIDMARWCTL_RD_WAT_SHIFT(0xF) | - BGE_PCIDMARWCTL_WR_WAT_SHIFT(0x2); + /* Read watermark not used, 128 bytes for write. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_WR_WAT_SHIFT(3); } else if (sc->bge_flags & BGE_FLAG_PCIX) { - /* PCI-X bus */ if (BGE_IS_5714_FAMILY(sc)) { - dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD; - dma_rw_ctl &= ~BGE_PCIDMARWCTL_ONEDMA_ATONCE; /* XXX */ - /* XXX magic values, Broadcom-supplied Linux driver */ - dma_rw_ctl |= (1 << 20) | (1 << 18); - if (sc->bge_asicrev == BGE_ASICREV_BCM5780) - dma_rw_ctl |= BGE_PCIDMARWCTL_ONEDMA_ATONCE; - else - dma_rw_ctl |= 1 << 15; - - } else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) - /* - * The 5704 uses a different encoding of read/write - * watermarks. - */ - dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | - BGE_PCIDMARWCTL_RD_WAT_SHIFT(0x7) | - BGE_PCIDMARWCTL_WR_WAT_SHIFT(0x3); - else - dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | - BGE_PCIDMARWCTL_RD_WAT_SHIFT(0x3) | - BGE_PCIDMARWCTL_WR_WAT_SHIFT(0x3) | + /* 256 bytes for read and write. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(2) | + BGE_PCIDMARWCTL_WR_WAT_SHIFT(2); + dma_rw_ctl |= (sc->bge_asicrev == BGE_ASICREV_BCM5780) ? + BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL : + BGE_PCIDMARWCTL_ONEDMA_ATONCE_LOCAL; + } else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) { + /* 1536 bytes for read, 384 bytes for write. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(7) | + BGE_PCIDMARWCTL_WR_WAT_SHIFT(3); + } else { + /* 384 bytes for read and write. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(3) | + BGE_PCIDMARWCTL_WR_WAT_SHIFT(3) | 0x0F; - - /* - * 5703 and 5704 need ONEDMA_AT_ONCE as a workaround - * for hardware bugs. - */ + } if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704) { uint32_t tmp; + /* Set ONE_DMA_AT_ONCE for hardware workaround. */ tmp = CSR_READ_4(sc, BGE_PCI_CLKCTL) & 0x1F; - if (tmp == 0x6 || tmp == 0x7) - dma_rw_ctl |= BGE_PCIDMARWCTL_ONEDMA_ATONCE; - } - } else - /* Conventional PCI bus */ - dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | - BGE_PCIDMARWCTL_RD_WAT_SHIFT(0x7) | - BGE_PCIDMARWCTL_WR_WAT_SHIFT(0x7) | - 0x0F; + if (tmp == 6 || tmp == 7) + dma_rw_ctl |= + BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL; + /* Set PCI-X DMA write workaround. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_ASRT_ALL_BE; + } + } else { + /* Conventional PCI bus: 256 bytes for read and write. */ + dma_rw_ctl |= BGE_PCIDMARWCTL_RD_WAT_SHIFT(7) | + BGE_PCIDMARWCTL_WR_WAT_SHIFT(7); + + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) + dma_rw_ctl |= 0x0F; + } + if (sc->bge_asicrev == BGE_ASICREV_BCM5700 || + sc->bge_asicrev == BGE_ASICREV_BCM5701) + dma_rw_ctl |= BGE_PCIDMARWCTL_USE_MRM | + BGE_PCIDMARWCTL_ASRT_ALL_BE; if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || - sc->bge_asicrev == BGE_ASICREV_BCM5704 || - sc->bge_asicrev == BGE_ASICREV_BCM5705) + sc->bge_asicrev == BGE_ASICREV_BCM5704) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); @@ -1268,9 +1339,9 @@ bge_blockinit(struct bge_softc *sc) /* Poll for buffer manager start indication */ for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) break; - DELAY(10); } if (i == BGE_TIMEOUT) { @@ -1286,9 +1357,9 @@ bge_blockinit(struct bge_softc *sc) /* Wait until queue initialization is complete */ for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); if (CSR_READ_4(sc, BGE_FTQ_RESET) == 0) break; - DELAY(10); } if (i == BGE_TIMEOUT) { @@ -1457,9 +1528,9 @@ bge_blockinit(struct bge_softc *sc) /* Poll to make sure it's shut down. */ for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); if (!(CSR_READ_4(sc, BGE_HCC_MODE) & BGE_HCCMODE_ENABLE)) break; - DELAY(10); } if (i == BGE_TIMEOUT) { @@ -2121,7 +2192,7 @@ static int bge_has_multiple_ports(struct bge_softc *sc) { device_t dev = sc->bge_dev; - u_int b, s, f, fscan; + u_int b, f, fscan, s; b = pci_get_bus(dev); s = pci_get_slot(dev); @@ -2170,8 +2241,8 @@ bge_attach(device_t dev) struct bge_softc *sc; uint32_t hwcfg = 0; uint32_t mac_tmp = 0; - u_char eaddr[6]; - int error = 0, rid, trys, reg; + u_char eaddr[ETHER_ADDR_LEN]; + int error, reg, rid, trys; sc = device_get_softc(dev); sc->bge_dev = dev; @@ -2202,6 +2273,9 @@ bge_attach(device_t dev) sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); + if (bge_has_eeprom(sc)) + sc->bge_flags |= BGE_FLAG_EEPROM; + /* Save chipset family. */ switch (sc->bge_asicrev) { case BGE_ASICREV_BCM5700: @@ -2315,7 +2389,6 @@ bge_attach(device_t dev) /* Try to reset the chip. */ if (bge_reset(sc)) { device_printf(sc->bge_dev, "chip reset failed\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2338,7 +2411,6 @@ bge_attach(device_t dev) bge_sig_pre_reset(sc, BGE_RESET_STOP); if (bge_reset(sc)) { device_printf(sc->bge_dev, "chip reset failed\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2348,29 +2420,32 @@ bge_attach(device_t dev) if (bge_chipinit(sc)) { device_printf(sc->bge_dev, "chip initialization failed\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } - /* - * Get station address from the EEPROM. - */ - mac_tmp = bge_readmem_ind(sc, 0x0C14); - if ((mac_tmp >> 16) == 0x484B) { - eaddr[0] = (u_char)(mac_tmp >> 8); - eaddr[1] = (u_char)mac_tmp; - mac_tmp = bge_readmem_ind(sc, 0x0C18); - eaddr[2] = (u_char)(mac_tmp >> 24); - eaddr[3] = (u_char)(mac_tmp >> 16); - eaddr[4] = (u_char)(mac_tmp >> 8); - eaddr[5] = (u_char)mac_tmp; - } else if (bge_read_eeprom(sc, eaddr, - BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) { - device_printf(sc->bge_dev, "failed to read station address\n"); - bge_release_resources(sc); - error = ENXIO; - goto fail; +#ifdef __sparc64__ + if ((sc->bge_flags & BGE_FLAG_EEPROM) == 0) + OF_getetheraddr(dev, eaddr); + else +#endif + { + mac_tmp = bge_readmem_ind(sc, 0x0C14); + if ((mac_tmp >> 16) == 0x484B) { + eaddr[0] = (u_char)(mac_tmp >> 8); + eaddr[1] = (u_char)mac_tmp; + mac_tmp = bge_readmem_ind(sc, 0x0C18); + eaddr[2] = (u_char)(mac_tmp >> 24); + eaddr[3] = (u_char)(mac_tmp >> 16); + eaddr[4] = (u_char)(mac_tmp >> 8); + eaddr[5] = (u_char)mac_tmp; + } else if (bge_read_eeprom(sc, eaddr, + BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) { + device_printf(sc->bge_dev, + "failed to read station address\n"); + error = ENXIO; + goto fail; + } } /* 5705 limits RX return ring to 512 entries. */ @@ -2382,7 +2457,6 @@ bge_attach(device_t dev) if (bge_dma_alloc(dev)) { device_printf(sc->bge_dev, "failed to allocate DMA resources\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2398,7 +2472,6 @@ bge_attach(device_t dev) ifp = sc->bge_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(sc->bge_dev, "failed to if_alloc()\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2444,11 +2517,10 @@ bge_attach(device_t dev) */ if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER) hwcfg = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG); - else { + else if (sc->bge_flags & BGE_FLAG_EEPROM) { if (bge_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET, sizeof(hwcfg))) { device_printf(sc->bge_dev, "failed to read EEPROM\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2494,7 +2566,6 @@ again: } device_printf(sc->bge_dev, "MII without any PHY!\n"); - bge_release_resources(sc); error = ENXIO; goto fail; } @@ -2542,7 +2613,11 @@ again: bge_add_sysctls(sc); + return (0); + fail: + bge_release_resources(sc); + return (error); } @@ -2725,20 +2800,19 @@ bge_reset(struct bge_softc *sc) /* * Poll until we see the 1's complement of the magic number. - * This indicates that the firmware initialization - * is complete. + * This indicates that the firmware initialization is complete. + * We expect this to fail if no EEPROM is fitted though. */ for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); if (val == ~BGE_MAGIC_NUMBER) break; - DELAY(10); } - if (i == BGE_TIMEOUT) { + if ((sc->bge_flags & BGE_FLAG_EEPROM) && i == BGE_TIMEOUT) device_printf(sc->bge_dev, "firmware handshake timed out, " "found 0x%08x\n", val); - } /* * XXX Wait for the value of the PCISTATE register to @@ -2850,7 +2924,8 @@ bge_rxeof(struct bge_softc *sc) rxidx = cur_rx->bge_idx; BGE_INC(sc->bge_rx_saved_considx, sc->bge_return_ring_cnt); - if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING && + cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { have_tag = 1; vlan_tag = cur_rx->bge_vlan_tag; } @@ -3545,7 +3620,8 @@ bge_init_locked(struct bge_softc *sc) /* Specify MTU. */ CSR_WRITE_4(sc, BGE_RX_MTU, ifp->if_mtu + - ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN); + ETHER_HDR_LEN + ETHER_CRC_LEN + + (ifp->if_capenable & IFCAP_VLAN_MTU ? ETHER_VLAN_ENCAP_LEN : 0)); /* Load our MAC address. */ m = (uint16_t *)IF_LLADDR(sc->bge_ifp); @@ -3558,6 +3634,9 @@ bge_init_locked(struct bge_softc *sc) /* Program multicast filter. */ bge_setmulti(sc); + /* Program VLAN tag stripping. */ + bge_setvlan(sc); + /* Init RX ring. */ bge_init_rx_ring_std(sc); @@ -3673,18 +3752,20 @@ bge_ifmedia_upd_locked(struct ifnet *ifp * mechanism for programming the autoneg * advertisement registers in TBI mode. */ - if (bge_fake_autoneg == 0 && - sc->bge_asicrev == BGE_ASICREV_BCM5704) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5704) { uint32_t sgdig; - CSR_WRITE_4(sc, BGE_TX_TBI_AUTONEG, 0); - sgdig = CSR_READ_4(sc, BGE_SGDIG_CFG); - sgdig |= BGE_SGDIGCFG_AUTO | - BGE_SGDIGCFG_PAUSE_CAP | - BGE_SGDIGCFG_ASYM_PAUSE; - CSR_WRITE_4(sc, BGE_SGDIG_CFG, - sgdig | BGE_SGDIGCFG_SEND); - DELAY(5); - CSR_WRITE_4(sc, BGE_SGDIG_CFG, sgdig); + sgdig = CSR_READ_4(sc, BGE_SGDIG_STS); + if (sgdig & BGE_SGDIGSTS_DONE) { + CSR_WRITE_4(sc, BGE_TX_TBI_AUTONEG, 0); + sgdig = CSR_READ_4(sc, BGE_SGDIG_CFG); + sgdig |= BGE_SGDIGCFG_AUTO | + BGE_SGDIGCFG_PAUSE_CAP | + BGE_SGDIGCFG_ASYM_PAUSE; + CSR_WRITE_4(sc, BGE_SGDIG_CFG, + sgdig | BGE_SGDIGCFG_SEND); + DELAY(5); + CSR_WRITE_4(sc, BGE_SGDIG_CFG, sgdig); + } } break; case IFM_1000_SX: @@ -3861,6 +3942,23 @@ bge_ioctl(struct ifnet *ifp, u_long comm VLAN_CAPABILITIES(ifp); #endif } + + if (mask & IFCAP_VLAN_MTU) { + ifp->if_capenable ^= IFCAP_VLAN_MTU; + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + bge_init(sc); + } + + if (mask & IFCAP_VLAN_HWTAGGING) { + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + BGE_LOCK(sc); + bge_setvlan(sc); + BGE_UNLOCK(sc); +#ifdef VLAN_CAPABILITIES + VLAN_CAPABILITIES(ifp); +#endif + } + break; default: error = ether_ioctl(ifp, command, data); @@ -4177,11 +4275,17 @@ bge_link_upd(struct bge_softc *sc) BGE_MACSTAT_LINK_CHANGED); } +#define BGE_SYSCTL_STAT(sc, ctx, desc, parent, node, oid) \ + SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, oid, CTLTYPE_UINT|CTLFLAG_RD, \ + sc, offsetof(struct bge_stats, node), bge_sysctl_stats, "IU", \ + desc) + static void bge_add_sysctls(struct bge_softc *sc) { struct sysctl_ctx_list *ctx; - struct sysctl_oid_list *children; + struct sysctl_oid_list *children, *schildren; + struct sysctl_oid *tree; ctx = device_get_sysctl_ctx(sc->bge_dev); children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->bge_dev)); @@ -4199,16 +4303,140 @@ bge_add_sysctls(struct bge_softc *sc) CTLTYPE_INT | CTLFLAG_RW, sc, 0, bge_sysctl_mem_read, "I", "Memory Read"); - SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, "stat_IfHcInOctets", - CTLFLAG_RD, - &sc->bge_ldata.bge_stats->rxstats.ifHCInOctets.bge_addr_lo, - "Bytes received"); - - SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, "stat_IfHcOutOctets", - CTLFLAG_RD, - &sc->bge_ldata.bge_stats->txstats.ifHCOutOctets.bge_addr_lo, - "Bytes received"); #endif + + if (BGE_IS_5705_PLUS(sc)) + return; + + tree = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", CTLFLAG_RD, + NULL, "BGE Statistics"); + schildren = children = SYSCTL_CHILDREN(tree); + BGE_SYSCTL_STAT(sc, ctx, "Frames Dropped Due To Filters", + children, COSFramesDroppedDueToFilters, + "FramesDroppedDueToFilters"); + BGE_SYSCTL_STAT(sc, ctx, "NIC DMA Write Queue Full", + children, nicDmaWriteQueueFull, "DmaWriteQueueFull"); + BGE_SYSCTL_STAT(sc, ctx, "NIC DMA Write High Priority Queue Full", + children, nicDmaWriteHighPriQueueFull, "DmaWriteHighPriQueueFull"); + BGE_SYSCTL_STAT(sc, ctx, "NIC No More RX Buffer Descriptors", + children, nicNoMoreRxBDs, "NoMoreRxBDs"); + BGE_SYSCTL_STAT(sc, ctx, "Discarded Input Frames", + children, ifInDiscards, "InputDiscards"); + BGE_SYSCTL_STAT(sc, ctx, "Input Errors", + children, ifInErrors, "InputErrors"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Recv Threshold Hit", + children, nicRecvThresholdHit, "RecvThresholdHit"); + BGE_SYSCTL_STAT(sc, ctx, "NIC DMA Read Queue Full", + children, nicDmaReadQueueFull, "DmaReadQueueFull"); + BGE_SYSCTL_STAT(sc, ctx, "NIC DMA Read High Priority Queue Full", + children, nicDmaReadHighPriQueueFull, "DmaReadHighPriQueueFull"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Send Data Complete Queue Full", + children, nicSendDataCompQueueFull, "SendDataCompQueueFull"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Ring Set Send Producer Index", + children, nicRingSetSendProdIndex, "RingSetSendProdIndex"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Ring Status Update", + children, nicRingStatusUpdate, "RingStatusUpdate"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Interrupts", + children, nicInterrupts, "Interrupts"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Avoided Interrupts", + children, nicAvoidedInterrupts, "AvoidedInterrupts"); + BGE_SYSCTL_STAT(sc, ctx, "NIC Send Threshold Hit", + children, nicSendThresholdHit, "SendThresholdHit"); + + tree = SYSCTL_ADD_NODE(ctx, schildren, OID_AUTO, "rx", CTLFLAG_RD, + NULL, "BGE RX Statistics"); + children = SYSCTL_CHILDREN(tree); + BGE_SYSCTL_STAT(sc, ctx, "Inbound Octets", + children, rxstats.ifHCInOctets, "Octets"); + BGE_SYSCTL_STAT(sc, ctx, "Fragments", + children, rxstats.etherStatsFragments, "Fragments"); + BGE_SYSCTL_STAT(sc, ctx, "Inbound Unicast Packets", + children, rxstats.ifHCInUcastPkts, "UcastPkts"); + BGE_SYSCTL_STAT(sc, ctx, "Inbound Multicast Packets", + children, rxstats.ifHCInMulticastPkts, "MulticastPkts"); + BGE_SYSCTL_STAT(sc, ctx, "FCS Errors", + children, rxstats.dot3StatsFCSErrors, "FCSErrors"); + BGE_SYSCTL_STAT(sc, ctx, "Alignment Errors", + children, rxstats.dot3StatsAlignmentErrors, "AlignmentErrors"); + BGE_SYSCTL_STAT(sc, ctx, "XON Pause Frames Received", + children, rxstats.xonPauseFramesReceived, "xonPauseFramesReceived"); + BGE_SYSCTL_STAT(sc, ctx, "XOFF Pause Frames Received", + children, rxstats.xoffPauseFramesReceived, + "xoffPauseFramesReceived"); + BGE_SYSCTL_STAT(sc, ctx, "MAC Control Frames Received", + children, rxstats.macControlFramesReceived, + "ControlFramesReceived"); + BGE_SYSCTL_STAT(sc, ctx, "XOFF State Entered", + children, rxstats.xoffStateEntered, "xoffStateEntered"); + BGE_SYSCTL_STAT(sc, ctx, "Frames Too Long", + children, rxstats.dot3StatsFramesTooLong, "FramesTooLong"); + BGE_SYSCTL_STAT(sc, ctx, "Jabbers", + children, rxstats.etherStatsJabbers, "Jabbers"); + BGE_SYSCTL_STAT(sc, ctx, "Undersized Packets", + children, rxstats.etherStatsUndersizePkts, "UndersizePkts"); + BGE_SYSCTL_STAT(sc, ctx, "Inbound Range Length Errors", + children, rxstats.inRangeLengthError, "inRangeLengthError"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Range Length Errors", + children, rxstats.outRangeLengthError, "outRangeLengthError"); + + tree = SYSCTL_ADD_NODE(ctx, schildren, OID_AUTO, "tx", CTLFLAG_RD, + NULL, "BGE TX Statistics"); + children = SYSCTL_CHILDREN(tree); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Octets", + children, txstats.ifHCOutOctets, "Octets"); + BGE_SYSCTL_STAT(sc, ctx, "TX Collisions", + children, txstats.etherStatsCollisions, "Collisions"); + BGE_SYSCTL_STAT(sc, ctx, "XON Sent", + children, txstats.outXonSent, "XonSent"); + BGE_SYSCTL_STAT(sc, ctx, "XOFF Sent", + children, txstats.outXoffSent, "XoffSent"); + BGE_SYSCTL_STAT(sc, ctx, "Flow Control Done", + children, txstats.flowControlDone, "flowControlDone"); + BGE_SYSCTL_STAT(sc, ctx, "Internal MAC TX errors", + children, txstats.dot3StatsInternalMacTransmitErrors, + "InternalMacTransmitErrors"); + BGE_SYSCTL_STAT(sc, ctx, "Single Collision Frames", + children, txstats.dot3StatsSingleCollisionFrames, + "SingleCollisionFrames"); + BGE_SYSCTL_STAT(sc, ctx, "Multiple Collision Frames", + children, txstats.dot3StatsMultipleCollisionFrames, + "MultipleCollisionFrames"); + BGE_SYSCTL_STAT(sc, ctx, "Deferred Transmissions", + children, txstats.dot3StatsDeferredTransmissions, + "DeferredTransmissions"); + BGE_SYSCTL_STAT(sc, ctx, "Excessive Collisions", + children, txstats.dot3StatsExcessiveCollisions, + "ExcessiveCollisions"); + BGE_SYSCTL_STAT(sc, ctx, "Late Collisions", + children, txstats.dot3StatsLateCollisions, + "LateCollisions"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Unicast Packets", + children, txstats.ifHCOutUcastPkts, "UcastPkts"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Multicast Packets", + children, txstats.ifHCOutMulticastPkts, "MulticastPkts"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Broadcast Packets", + children, txstats.ifHCOutBroadcastPkts, "BroadcastPkts"); + BGE_SYSCTL_STAT(sc, ctx, "Carrier Sense Errors", + children, txstats.dot3StatsCarrierSenseErrors, + "CarrierSenseErrors"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Discards", + children, txstats.ifOutDiscards, "Discards"); + BGE_SYSCTL_STAT(sc, ctx, "Outbound Errors", + children, txstats.ifOutErrors, "Errors"); +} + +static int +bge_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + struct bge_softc *sc; + uint32_t result; + int offset; + + sc = (struct bge_softc *)arg1; + offset = arg2; + result = CSR_READ_4(sc, BGE_MEMWIN_START + BGE_STATS_BLOCK + offset + + offsetof(bge_hostaddr, bge_addr_lo)); + return (sysctl_handle_int(oidp, &result, 0, req)); } #ifdef BGE_REGISTER_DEBUG Index: if_bgereg.h =================================================================== RCS file: /home/ncvs/src/sys/dev/bge/if_bgereg.h,v retrieving revision 1.36.2.10 diff -p -u -u -r1.36.2.10 if_bgereg.h --- if_bgereg.h 21 Mar 2007 22:53:22 -0000 1.36.2.10 +++ if_bgereg.h 3 Dec 2007 08:49:49 -0000 @@ -316,7 +316,9 @@ #define BGE_PCIDMARWCTL_MINDMA 0x000000FF #define BGE_PCIDMARWCTL_RDADRR_BNDRY 0x00000700 #define BGE_PCIDMARWCTL_WRADDR_BNDRY 0x00003800 -#define BGE_PCIDMARWCTL_ONEDMA_ATONCE 0x00004000 +#define BGE_PCIDMARWCTL_ONEDMA_ATONCE 0x0000C000 +#define BGE_PCIDMARWCTL_ONEDMA_ATONCE_GLOBAL 0x00004000 +#define BGE_PCIDMARWCTL_ONEDMA_ATONCE_LOCAL 0x00008000 #define BGE_PCIDMARWCTL_RD_WAT 0x00070000 #define BGE_PCIDMARWCTL_WR_WAT 0x00380000 #define BGE_PCIDMARWCTL_USE_MRM 0x00400000 @@ -2080,6 +2082,11 @@ struct bge_status_block { #define APPLE_DEVICE_BCM5701 0x1645 /* + * Sun PCI vendor ID + */ +#define SUN_VENDORID 0x108e + +/* * Offset of MAC address inside EEPROM. */ #define BGE_EE_MAC_OFFSET 0x7C @@ -2101,9 +2108,6 @@ struct bge_status_block { #define BGE_MEDIA_COPPER 0x00000010 #define BGE_MEDIA_FIBER 0x00000020 -#define BGE_PCI_READ_CMD 0x06000000 -#define BGE_PCI_WRITE_CMD 0x70000000 - #define BGE_TICKS_PER_SEC 1000000 /* @@ -2454,6 +2458,7 @@ struct bge_softc { uint32_t bge_flags; #define BGE_FLAG_TBI 0x00000001 #define BGE_FLAG_JUMBO 0x00000002 +#define BGE_FLAG_EEPROM 0x00000004 #define BGE_FLAG_MSI 0x00000100 #define BGE_FLAG_PCIX 0x00000200 #define BGE_FLAG_PCIE 0x00000400