summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2008-02-28 02:02:44 +0000
committerBrad Smith <brad@cvs.openbsd.org>2008-02-28 02:02:44 +0000
commit65697912e0a48794330cbf34f0de470f66cad844 (patch)
treebdc4f5643b6ed782fb8fd813f2741a1e0a75ce7a /sys
parent622058ef3bc1957eb500d3b3c391d88387ac36bf (diff)
Add initial bits for fiber support with the BCM5706/BCM5708 chipsets.
Tested with copper adapters by brad@, johan@ and Jung <moorang at gmail dot com> ok dlg@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_bnx.c134
-rw-r--r--sys/dev/pci/if_bnxreg.h4
2 files changed, 72 insertions, 66 deletions
diff --git a/sys/dev/pci/if_bnx.c b/sys/dev/pci/if_bnx.c
index 691690a6317..cc81227856f 100644
--- a/sys/dev/pci/if_bnx.c
+++ b/sys/dev/pci/if_bnx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bnx.c,v 1.57 2008/02/22 22:25:27 kettenis Exp $ */
+/* $OpenBSD: if_bnx.c,v 1.58 2008/02/28 02:02:43 brad Exp $ */
/*-
* Copyright (c) 2006 Broadcom Corporation
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $"
/*
* The following controllers are supported by this driver:
* BCM5706C A2, A3
- * BCM5708C B1
+ * BCM5708C B1, B2
*
* The following controllers are not supported by this driver:
* BCM5706C A0, A1
@@ -658,11 +658,6 @@ bnx_attach(struct device *parent, struct device *self, void *aux)
/* Save ASIC revsion info. */
sc->bnx_chipid = REG_RD(sc, BNX_MISC_ID);
- if (BNX_CHIP_BOND_ID(sc) & BNX_CHIP_BOND_ID_SERDES_BIT) {
- printf(": SerDes controllers are not supported!\n");
- goto bnx_attach_fail;
- }
-
/*
* Find the base address for shared memory access.
* Newer versions of bootcode use a signature and offset
@@ -749,7 +744,7 @@ bnx_attachhook(void *xsc)
struct pci_attach_args *pa = &sc->bnx_pa;
struct ifnet *ifp;
u_int32_t val;
- int error;
+ int error, mii_flags = 0;
if ((error = bnx_read_firmware(sc)) != 0) {
printf("%s: error %d, could not read firmware\n",
@@ -814,17 +809,17 @@ bnx_attachhook(void *xsc)
sc->bnx_stats_ticks = 1000000 & 0xffff00;
/*
- * The copper based NetXtreme II controllers
- * use an integrated PHY at address 1 while
- * the SerDes controllers use a PHY at
- * address 2.
+ * The SerDes based NetXtreme II controllers
+ * that support 2.5Gb operation (currently
+ * 5708S) use a PHY at address 2, otherwise
+ * the PHY is present at address 1.
*/
sc->bnx_phy_addr = 1;
if (BNX_CHIP_BOND_ID(sc) & BNX_CHIP_BOND_ID_SERDES_BIT) {
sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG;
sc->bnx_flags |= BNX_NO_WOL_FLAG;
- if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5708) {
+ if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) {
sc->bnx_phy_addr = 2;
val = REG_RD_IND(sc, sc->bnx_shmem_base +
BNX_SHARED_HW_CFG_CONFIG);
@@ -833,11 +828,6 @@ bnx_attachhook(void *xsc)
}
}
- if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) {
- printf(": SerDes is not supported by this driver!\n");
- goto bnx_attach_fail;
- }
-
/* Allocate DMA memory resources. */
sc->bnx_dmatag = pa->pa_dmat;
if (bnx_dma_alloc(sc)) {
@@ -853,10 +843,6 @@ bnx_attachhook(void *xsc)
ifp->if_ioctl = bnx_ioctl;
ifp->if_start = bnx_start;
ifp->if_watchdog = bnx_watchdog;
- if (sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG)
- ifp->if_baudrate = IF_Mbps(2500);
- else
- ifp->if_baudrate = IF_Gbps(1);
IFQ_SET_MAXLEN(&ifp->if_snd, USABLE_TX_BD - 1);
IFQ_SET_READY(&ifp->if_snd);
bcopy(sc->eaddr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
@@ -885,8 +871,10 @@ bnx_attachhook(void *xsc)
/* Look for our PHY. */
ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd,
bnx_ifmedia_sts);
+ if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG)
+ mii_flags |= MIIF_HAVEFIBER;
mii_attach(&sc->bnx_dev, &sc->bnx_mii, 0xffffffff,
- MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ MII_PHY_ANY, MII_OFFSET_ANY, mii_flags);
if (LIST_FIRST(&sc->bnx_mii.mii_phys) == NULL) {
printf("%s: no PHY found!\n", sc->bnx_dev.dv_xname);
@@ -949,12 +937,8 @@ bnx_detach(void *xsc)
ether_ifdetach(ifp);
/* If we have a child device on the MII bus remove it too. */
- if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) {
- ifmedia_removeall(&sc->bnx_ifmedia);
- } else {
- bus_generic_detach(dev);
- device_delete_child(dev, sc->bnx_mii);
- }
+ bus_generic_detach(dev);
+ device_delete_child(dev, sc->bnx_mii);
/* Release all remaining resources. */
bnx_release_resources(sc);
@@ -1214,28 +1198,52 @@ bnx_miibus_statchg(struct device *dev)
{
struct bnx_softc *sc = (struct bnx_softc *)dev;
struct mii_data *mii = &sc->bnx_mii;
+ int val;
- BNX_CLRBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT);
+ val = REG_RD(sc, BNX_EMAC_MODE);
+ val &= ~(BNX_EMAC_MODE_PORT | BNX_EMAC_MODE_HALF_DUPLEX |
+ BNX_EMAC_MODE_MAC_LOOP | BNX_EMAC_MODE_FORCE_LINK |
+ BNX_EMAC_MODE_25G);
- /* Set MII or GMII inerface based on the speed negotiated by the PHY. */
- if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
- DBPRINT(sc, BNX_INFO, "Setting GMII interface.\n");
- BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT_GMII);
- } else {
- DBPRINT(sc, BNX_INFO, "Setting MII interface.\n");
- BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT_MII);
+ /* Set MII or GMII interface based on the speed
+ * negotiated by the PHY.
+ */
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) {
+ DBPRINT(sc, BNX_INFO, "Enabling 10Mb interface.\n");
+ val |= BNX_EMAC_MODE_PORT_MII_10;
+ break;
+ }
+ /* FALLTHROUGH */
+ case IFM_100_TX:
+ DBPRINT(sc, BNX_INFO, "Enabling MII interface.\n");
+ val |= BNX_EMAC_MODE_PORT_MII;
+ break;
+ case IFM_2500_SX:
+ DBPRINT(sc, BNX_INFO, "Enabling 2.5G MAC mode.\n");
+ val |= BNX_EMAC_MODE_25G;
+ /* FALLTHROUGH */
+ case IFM_1000_T:
+ case IFM_1000_SX:
+ DBPRINT(sc, BNX_INFO, "Enablinb GMII interface.\n");
+ val |= BNX_EMAC_MODE_PORT_GMII;
+ break;
+ default:
+ val |= BNX_EMAC_MODE_PORT_GMII;
+ break;
}
/* Set half or full duplex based on the duplicity
* negotiated by the PHY.
*/
- if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
- DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n");
- BNX_CLRBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_HALF_DUPLEX);
- } else {
+ if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) {
DBPRINT(sc, BNX_INFO, "Setting Half-Duplex interface.\n");
- BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_HALF_DUPLEX);
- }
+ val |= BNX_EMAC_MODE_HALF_DUPLEX;
+ } else
+ DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n");
+
+ REG_WR(sc, BNX_EMAC_MODE, val);
}
/****************************************************************************/
@@ -2895,12 +2903,12 @@ void
bnx_stop(struct bnx_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mii_data *mii = NULL;
+ struct ifmedia_entry *ifm;
+ struct mii_data *mii;
+ int mtmp, itmp;
DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
- mii = &sc->bnx_mii;
-
timeout_del(&sc->bnx_timeout);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
@@ -2921,6 +2929,21 @@ bnx_stop(struct bnx_softc *sc)
/* Free TX buffers. */
bnx_free_tx_chain(sc);
+ /*
+ * Isolate/power down the PHY, but leave the media selection
+ * unchanged so that things will be put back to normal when
+ * we bring the interface back up.
+ */
+ mii = &sc->bnx_mii;
+ itmp = ifp->if_flags;
+ ifp->if_flags |= IFF_UP;
+ ifm = mii->mii_media.ifm_cur;
+ mtmp = ifm->ifm_media;
+ ifm->ifm_media = IFM_ETHER|IFM_NONE;
+ mii_mediachg(mii);
+ ifm->ifm_media = mtmp;
+ ifp->if_flags = itmp;
+
ifp->if_timer = 0;
sc->bnx_link = 0;
@@ -3615,13 +3638,9 @@ bnx_ifmedia_upd(struct ifnet *ifp)
{
struct bnx_softc *sc;
struct mii_data *mii;
- struct ifmedia *ifm;
int rc = 0;
sc = ifp->if_softc;
- ifm = &sc->bnx_ifmedia;
-
- /* DRC - ToDo: Add SerDes support. */
mii = &sc->bnx_mii;
sc->bnx_link = 0;
@@ -3654,8 +3673,6 @@ bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
mii = &sc->bnx_mii;
- /* DRC - ToDo: Add SerDes support. */
-
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
@@ -4517,7 +4534,7 @@ bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct bnx_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct ifaddr *ifa = (struct ifaddr *)data;
- struct mii_data *mii;
+ struct mii_data *mii = &sc->bnx_mii;
int s, error = 0;
s = splnet();
@@ -4580,14 +4597,7 @@ bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
DBPRINT(sc, BNX_VERBOSE, "bnx_phy_flags = 0x%08X\n",
sc->bnx_phy_flags);
- if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG)
- error = ifmedia_ioctl(ifp, ifr,
- &sc->bnx_ifmedia, command);
- else {
- mii = &sc->bnx_mii;
- error = ifmedia_ioctl(ifp, ifr,
- &mii->mii_media, command);
- }
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
default:
@@ -5062,8 +5072,6 @@ bnx_tick(void *xsc)
if (sc->bnx_link)
goto bnx_tick_exit;
- /* DRC - ToDo: Add SerDes support and check SerDes link here. */
-
mii = &sc->bnx_mii;
mii_tick(mii);
diff --git a/sys/dev/pci/if_bnxreg.h b/sys/dev/pci/if_bnxreg.h
index 7f94db70a86..99e6aff7fc8 100644
--- a/sys/dev/pci/if_bnxreg.h
+++ b/sys/dev/pci/if_bnxreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bnxreg.h,v 1.22 2008/02/22 22:25:27 kettenis Exp $ */
+/* $OpenBSD: if_bnxreg.h,v 1.23 2008/02/28 02:02:43 brad Exp $ */
/*-
* Copyright (c) 2006 Broadcom Corporation
@@ -4594,8 +4594,6 @@ struct bnx_softc
struct pci_attach_args bnx_pa;
pci_intr_handle_t bnx_ih;
- struct ifmedia bnx_ifmedia; /* TBI media info */
-
bus_space_tag_t bnx_btag; /* Device bus tag */
bus_space_handle_t bnx_bhandle; /* Device bus handle */
bus_size_t bnx_size;