The following reply was made to PR kern/118975; it has been noted by GNATS.

From: =?ISO-8859-1?Q?Thomas_Nystr=F6m?= <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED], [EMAIL PROTECTED]
Cc:  
Subject: Re: kern/118975: [bge] [patch] Broadcom 5906 not handled by FreeBSD
Date: Sat, 01 Mar 2008 20:35:04 +0100

 This is a multi-part message in MIME format.
 --------------000103070907090204020108
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Updated patch for 7.0-RELEASE (and probably -CURRENT).
 
 /thn
 
 
 --------------000103070907090204020108
 Content-Type: text/plain;
  name="broadcom5906-70.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="broadcom5906-70.diff"
 
 --- ./sys/dev/bge/if_bge.c.70  2008-03-01 15:03:15.000000000 +0100
 +++ ./sys/dev/bge/if_bge.c     2008-03-01 15:00:22.000000000 +0100
 @@ -195,6 +195,8 @@
        { BCOM_VENDORID,        BCOM_DEVICEID_BCM5901 },
        { BCOM_VENDORID,        BCOM_DEVICEID_BCM5901A2 },
        { BCOM_VENDORID,        BCOM_DEVICEID_BCM5903M },
 +      { BCOM_VENDORID,        BCOM_DEVICEID_BCM5906 },
 +      { BCOM_VENDORID,        BCOM_DEVICEID_BCM5906M },
  
        { SK_VENDORID,          SK_DEVICEID_ALTIMA },
  
 @@ -271,6 +273,8 @@
        { BGE_CHIPID_BCM5787_A0,        "BCM5754/5787 A0" }, 
        { BGE_CHIPID_BCM5787_A1,        "BCM5754/5787 A1" },
        { BGE_CHIPID_BCM5787_A2,        "BCM5754/5787 A2" },
 +      { BGE_CHIPID_BCM5906_A1,        "BCM5906 A1" },
 +      { BGE_CHIPID_BCM5906_A2,        "BCM5906 A2" },
  
        { 0, NULL }
  };
 @@ -293,6 +297,7 @@
        { BGE_ASICREV_BCM5755,          "unknown BCM5755" },
        /* 5754 and 5787 share the same ASIC ID */
        { BGE_ASICREV_BCM5787,          "unknown BCM5754/5787" },
 +      { BGE_ASICREV_BCM5906,          "unknown BCM5906" },
  
        { 0, NULL }
  };
 @@ -305,6 +310,9 @@
  
  const struct bge_revision * bge_lookup_rev(uint32_t);
  const struct bge_vendor * bge_lookup_vendor(uint16_t);
 +
 +typedef int   (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]);
 +
  static int bge_probe(device_t);
  static int bge_attach(device_t);
  static int bge_detach(device_t);
 @@ -315,6 +323,11 @@
  static int bge_dma_alloc(device_t);
  static void bge_dma_free(struct bge_softc *);
  
 +static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]);
 +static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]);
 +static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]);
 +static int bge_get_eaddr(struct bge_softc *, uint8_t[]);
 +
  static void bge_txeof(struct bge_softc *);
  static void bge_rxeof(struct bge_softc *);
  
 @@ -337,6 +350,9 @@
  static int bge_ifmedia_upd(struct ifnet *);
  static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
  
 +static uint8_t bge_nvram_getbyte(struct bge_softc *, int, uint8_t *);
 +static int bge_read_nvram(struct bge_softc *, caddr_t, int, int);
 +
  static uint8_t bge_eeprom_getbyte(struct bge_softc *, int, uint8_t *);
  static int bge_read_eeprom(struct bge_softc *, caddr_t, int, int);
  
 @@ -359,6 +375,7 @@
  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);
 +static void bge_writembx(struct bge_softc *, int, int);
  #ifdef notdef
  static uint32_t bge_readreg_ind(struct bge_softc *, int);
  #endif
 @@ -474,6 +491,10 @@
                        return (0);
        }
  #endif
 +
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
 +              return (0);
 +
        return (1);
  }
  
 @@ -533,6 +554,15 @@
        CSR_WRITE_4(sc, off, val);
  }
  
 +static void
 +bge_writembx(struct bge_softc *sc, int off, int val)
 +{
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
 +              off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI;
 +
 +      CSR_WRITE_4(sc, off, val);
 +}
 +
  /*
   * Map a single buffer address.
   */
 @@ -555,6 +585,78 @@
        ctx->bge_busaddr = segs->ds_addr;
  }
  
 +static uint8_t
 +bge_nvram_getbyte(struct bge_softc *sc, int addr, uint8_t *dest)
 +{
 +      uint32_t access, byte = 0;
 +      int i;
 +
 +      /* Lock. */
 +      CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1);
 +      for (i = 0; i < 8000; i++) {
 +              if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1)
 +                      break;
 +              DELAY(20);
 +      }
 +      if (i == 8000)
 +              return (1);
 +
 +      /* Enable access. */
 +      access = CSR_READ_4(sc, BGE_NVRAM_ACCESS);
 +      CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE);
 +
 +      CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc);
 +      CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD);
 +      for (i = 0; i < BGE_TIMEOUT * 10; i++) {
 +              DELAY(10);
 +              if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) {
 +                      DELAY(10);
 +                      break;
 +              }
 +      }
 +
 +      if (i == BGE_TIMEOUT * 10) {
 +              if_printf(sc->bge_ifp, "nvram read timed out\n");
 +              return (1);
 +      }
 +
 +      /* Get result. */
 +      byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA);
 +
 +      *dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF;
 +
 +      /* Disable access. */
 +      CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access);
 +
 +      /* Unlock. */
 +      CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1);
 +      CSR_READ_4(sc, BGE_NVRAM_SWARB);
 +
 +      return (0);
 +}
 +
 +/*
 + * Read a sequence of bytes from NVRAM.
 + */
 +static int
 +bge_read_nvram(struct bge_softc *sc, caddr_t dest, int off, int cnt)
 +{
 +      int err = 0, i;
 +      uint8_t byte = 0;
 +
 +      if (sc->bge_asicrev != BGE_ASICREV_BCM5906)
 +              return (1);
 +
 +      for (i = 0; i < cnt; i++) {
 +              err = bge_nvram_getbyte(sc, off + i, &byte);
 +              if (err)
 +                      break;
 +              *(dest + i) = byte;
 +      }
 +
 +      return (err ? 1 : 0);
 +}
 +
  /*
   * Read a byte of data stored in the EEPROM at address 'addr.' The
   * BCM570x supports both the traditional bitbang interface and an
 @@ -659,11 +761,13 @@
        }
  
        if (i == BGE_TIMEOUT) {
 -              device_printf(sc->bge_dev, "PHY read timed out\n");
 +              device_printf(sc->bge_dev, "PHY read timed out "
 +                        "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val);
                val = 0;
                goto done;
        }
  
 +      DELAY(5);
        val = CSR_READ_4(sc, BGE_MI_COMM);
  
  done:
 @@ -687,6 +791,10 @@
  
        sc = device_get_softc(dev);
  
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906 &&
 +          (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL))
 +              return(0);
 +
        /* Reading with autopolling on may trigger PCI errors */
        autopoll = CSR_READ_4(sc, BGE_MI_MODE);
        if (autopoll & BGE_MIMODE_AUTOPOLL) {
 @@ -699,12 +807,17 @@
  
        for (i = 0; i < BGE_TIMEOUT; i++) {
                DELAY(10);
 -              if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY))
 +              if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
 +                      DELAY(5);
 +                      CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */
                        break;
 +              }
        }
  
        if (i == BGE_TIMEOUT) {
 -              device_printf(sc->bge_dev, "PHY write timed out\n");
 +              device_printf(sc->bge_dev,
 +                        "PHY write timed out (phy %d, reg %d, val %d)\n",
 +                        phy, reg, val);
                return (0);
        }
  
 @@ -887,7 +1000,7 @@
            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  
        sc->bge_std = i - 1;
 -      CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
 +      bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
  
        return (0);
  }
 @@ -934,7 +1047,7 @@
                                    BGE_RCB_FLAG_USE_EXT_RX_BD);
        CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags);
  
 -      CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
 +      bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
  
        return (0);
  }
 @@ -990,17 +1103,17 @@
  
        /* Initialize transmit producer index for host-memory send ring. */
        sc->bge_tx_prodidx = 0;
 -      CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
 +      bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
  
        /* 5700 b2 errata */
        if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
 -              CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
 +              bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx);
  
        /* NIC-memory send ring not used; initialize to zero. */
 -      CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
 +      bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
        /* 5700 b2 errata */
        if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
 -              CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
 +              bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0);
  
        return (0);
  }
 @@ -1271,6 +1384,15 @@
        /* Set the timer prescaler (always 66Mhz) */
        CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
  
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
 +              DELAY(40);      /* XXX */
 +
 +              /* Put PHY into ready state */
 +              BGE_CLRBIT(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ);
 +              CSR_READ_4(sc, BGE_MISC_CFG); /* Flush */
 +              DELAY(40);
 +      }
 +
        return (0);
  }
  
 @@ -1307,15 +1429,21 @@
                CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LEN, 0x2000);
        }
  
 +
        /* Configure mbuf pool watermarks */
 -      if (BGE_IS_5705_PLUS(sc)) {
 -              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
 -              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10);
 -      } else {
 +      if (!BGE_IS_5705_PLUS(sc)) {
                CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50);
                CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20);
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
 +      } else if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04);
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10);
 +      } else {
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0);
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10);
 +              CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
        }
 -      CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60);
  
        /* Configure DMA resource watermarks */
        CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5);
 @@ -1462,15 +1590,15 @@
                    BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt,
                    BGE_RCB_FLAG_RING_DISABLED));
                RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0);
 -              CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO +
 +              bge_writembx(sc, BGE_MBX_RX_CONS0_LO +
                    (i * (sizeof(uint64_t))), 0);
                vrcb += sizeof(struct bge_rcb);
        }
  
        /* Initialize RX ring indexes */
 -      CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, 0);
 -      CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
 -      CSR_WRITE_4(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
 +      bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0);
 +      bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0);
 +      bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0);
  
        /*
         * Set up RX return ring 0
 @@ -2230,7 +2358,6 @@
        struct ifnet *ifp;
        struct bge_softc *sc;
        uint32_t hwcfg = 0;
 -      uint32_t mac_tmp = 0;
        u_char eaddr[ETHER_ADDR_LEN];
        int error, reg, rid, trys;
  
 @@ -2283,6 +2410,7 @@
        case BGE_ASICREV_BCM5752:
        case BGE_ASICREV_BCM5755:
        case BGE_ASICREV_BCM5787:
 +      case BGE_ASICREV_BCM5906:
                sc->bge_flags |= BGE_FLAG_575X_PLUS;
                /* FALLTHRU */
        case BGE_ASICREV_BCM5705:
 @@ -2304,7 +2432,7 @@
                if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
                    sc->bge_asicrev == BGE_ASICREV_BCM5787)
                        sc->bge_flags |= BGE_FLAG_JITTER_BUG;
 -              else
 +              else if (sc->bge_asicrev != BGE_ASICREV_BCM5906)
                        sc->bge_flags |= BGE_FLAG_BER_BUG;
        }
  
 @@ -2415,22 +2543,14 @@
        }
  
  #ifdef __sparc64__
 -      if ((sc->bge_flags & BGE_FLAG_EEPROM) == 0)
 +      if (((sc->bge_flags & BGE_FLAG_EEPROM) == 0) &&
 +          (sc->bge_asicrev != BGE_ASICREV_BCM5906))
                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)) {
 +              error = bge_get_eaddr(sc, eaddr);
 +              if (error) {
                        device_printf(sc->bge_dev,
                            "failed to read station address\n");
                        error = ENXIO;
 @@ -2688,7 +2808,8 @@
  
        dev = sc->bge_dev;
  
 -      if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc)) {
 +      if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc) &&
 +          (sc->bge_asicrev != BGE_ASICREV_BCM5906)) {
                if (sc->bge_flags & BGE_FLAG_PCIE)
                        write_op = bge_writemem_direct;
                else
 @@ -2744,6 +2865,17 @@
        /* Issue global reset */
        write_op(sc, BGE_MISC_CFG, reset);
  
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
 +              uint32_t status, ctrl;
 +
 +              status = CSR_READ_4(sc, BGE_VCPU_STATUS);
 +              CSR_WRITE_4(sc, BGE_VCPU_STATUS,
 +                  status | BGE_VCPU_STATUS_DRV_RESET);
 +              ctrl = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL);
 +              CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL,
 +                  ctrl & ~BGE_VCPU_EXT_CTRL_HALT_CPU);
 +      }
 +
        DELAY(1000);
  
        /* XXX: Broadcom Linux driver. */
 @@ -2788,21 +2920,34 @@
        } else
                CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
  
 -      /*
 -       * Poll until we see the 1's complement of the magic number.
 -       * 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;
 -      }
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906) {
 +              for (i = 0; i < BGE_TIMEOUT; i++) {
 +                      val = CSR_READ_4(sc, BGE_VCPU_STATUS);
 +                      if (val & BGE_VCPU_STATUS_INIT_DONE)
 +                              break;
 +                      DELAY(100);
 +              }
 +              if (i == BGE_TIMEOUT) {
 +                      device_printf(sc->bge_dev, "reset timed out\n");
 +                      return (1);
 +              }
 +      } else {
 +              /*
 +               * Poll until we see the 1's complement of the magic number.
 +               * 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;
 +              }
  
 -      if ((sc->bge_flags & BGE_FLAG_EEPROM) && i == BGE_TIMEOUT)
 -              device_printf(sc->bge_dev, "firmware handshake timed out, "
 -                  "found 0x%08x\n", val);
 +              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
 @@ -3022,11 +3167,11 @@
                bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag,
                    sc->bge_cdata.bge_rx_jumbo_ring_map, BUS_DMASYNC_PREWRITE);
  
 -      CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
 +      bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx);
        if (stdcnt)
 -              CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
 +              bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std);
        if (jumbocnt)
 -              CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
 +              bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo);
  #ifdef notyet
        /*
         * This register wraps very quickly under heavy packet drops.
 @@ -3168,7 +3313,7 @@
         * the status check).  So toggling would probably be a pessimization
         * even with MSI.  It would only be needed for using a task queue.
         */
 -      CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
 +      bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
  
        /*
         * Do the mandatory PCI flush as well as get the link status.
 @@ -3545,10 +3690,10 @@
                return;
  
        /* Transmit. */
 -      CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
 +      bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
        /* 5700 b2 errata */
        if (sc->bge_chiprev == BGE_CHIPREV_5700_BX)
 -              CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
 +              bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx);
  
        sc->bge_tx_prodidx = prodidx;
  
 @@ -3675,7 +3820,7 @@
        if (ifp->if_capenable & IFCAP_POLLING) {
                BGE_SETBIT(sc, BGE_PCI_MISC_CTL,
                    BGE_PCIMISCCTL_MASK_PCI_INTR);
 -              CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
 +              bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
        } else
  #endif
  
 @@ -3683,7 +3828,7 @@
        {
        BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
        BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
 -      CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
 +      bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
        }
        
        bge_ifmedia_upd_locked(ifp);
 @@ -3906,7 +4051,7 @@
                                BGE_LOCK(sc);
                                BGE_SETBIT(sc, BGE_PCI_MISC_CTL,
                                    BGE_PCIMISCCTL_MASK_PCI_INTR);
 -                              CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
 +                              bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
                                ifp->if_capenable |= IFCAP_POLLING;
                                BGE_UNLOCK(sc);
                        } else {
 @@ -3915,7 +4060,7 @@
                                BGE_LOCK(sc);
                                BGE_CLRBIT(sc, BGE_PCI_MISC_CTL,
                                    BGE_PCIMISCCTL_MASK_PCI_INTR);
 -                              CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
 +                              bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
                                ifp->if_capenable &= ~IFCAP_POLLING;
                                BGE_UNLOCK(sc);
                        }
 @@ -4040,7 +4185,7 @@
  
        /* Disable host interrupts. */
        BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
 -      CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
 +      bge_writembx(sc, BGE_MBX_IRQ0_LO, 1);
  
        /*
         * Tell firmware we're shutting down.
 @@ -4536,3 +4681,64 @@
        return (error);
  }
  #endif
 +
 +static int
 +bge_get_eaddr_mem(struct bge_softc *sc, uint8_t ether_addr[])
 +{
 +      uint32_t mac_addr;
 +      int ret = 1;
 +
 +      mac_addr = bge_readmem_ind(sc, 0x0c14);
 +      if ((mac_addr >> 16) == 0x484b) {
 +              ether_addr[0] = (uint8_t)(mac_addr >> 8);
 +              ether_addr[1] = (uint8_t)mac_addr;
 +              mac_addr = bge_readmem_ind(sc, 0x0c18);
 +              ether_addr[2] = (uint8_t)(mac_addr >> 24);
 +              ether_addr[3] = (uint8_t)(mac_addr >> 16);
 +              ether_addr[4] = (uint8_t)(mac_addr >> 8);
 +              ether_addr[5] = (uint8_t)mac_addr;
 +              ret = 0;
 +      }
 +      return ret;
 +}
 +
 +static int
 +bge_get_eaddr_nvram(struct bge_softc *sc, uint8_t ether_addr[])
 +{
 +      int mac_offset = BGE_EE_MAC_OFFSET;
 +
 +      if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
 +              mac_offset = BGE_EE_MAC_OFFSET_5906;
 +
 +      return bge_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN);
 +}
 +
 +static int
 +bge_get_eaddr_eeprom(struct bge_softc *sc, uint8_t ether_addr[])
 +{
 +      if (!(sc->bge_flags & BGE_FLAG_EEPROM))
 +              return 1;
 +
 +      return bge_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2,
 +                             ETHER_ADDR_LEN);
 +}
 +
 +static int
 +bge_get_eaddr(struct bge_softc *sc, uint8_t eaddr[])
 +{
 +      static const bge_eaddr_fcn_t bge_eaddr_funcs[] = {
 +              /* NOTE: Order is critical */
 +              bge_get_eaddr_mem,
 +              bge_get_eaddr_nvram,
 +              bge_get_eaddr_eeprom,
 +              NULL
 +      };
 +      const bge_eaddr_fcn_t *func;
 +
 +      for (func = bge_eaddr_funcs; *func != NULL; ++func) {
 +              if ((*func)(sc, eaddr) == 0)
 +                      break;
 +      }
 +      return (*func == NULL ? ENXIO : 0);
 +}
 +
 --- ./sys/dev/bge/if_bgereg.h.orig     2007-05-22 21:22:58.000000000 +0200
 +++ ./sys/dev/bge/if_bgereg.h  2008-03-01 14:55:49.000000000 +0100
 @@ -283,6 +283,8 @@
  #define       BGE_CHIPID_BCM5787_A0           0xb0000000
  #define       BGE_CHIPID_BCM5787_A1           0xb0010000
  #define       BGE_CHIPID_BCM5787_A2           0xb0020000
 +#define       BGE_CHIPID_BCM5906_A1           0xc0010000
 +#define       BGE_CHIPID_BCM5906_A2           0xc0020000
  
  /* shorthand one */
  #define       BGE_ASICREV(x)                  ((x) >> 28)
 @@ -299,6 +301,7 @@
  #define       BGE_ASICREV_BCM5755             0x0a
  #define       BGE_ASICREV_BCM5754             0x0b
  #define       BGE_ASICREV_BCM5787             0x0b
 +#define       BGE_ASICREV_BCM5906             0x0c
  
  /* chip revisions */
  #define       BGE_CHIPREV(x)                  ((x) >> 24)
 @@ -1438,6 +1441,17 @@
  #define       BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW  0x40000000
  #define       BGE_RXCPUSTAT_BLOCKING_READ     0x80000000
  
 +/*
 + * V? CPU registers
 + */
 +#define       BGE_VCPU_STATUS                 0x5100
 +#define       BGE_VCPU_EXT_CTRL               0x6890
 +
 +#define       BGE_VCPU_STATUS_INIT_DONE       0x04000000
 +#define       BGE_VCPU_STATUS_DRV_RESET       0x08000000
 +
 +#define       BGE_VCPU_EXT_CTRL_HALT_CPU      0x00400000
 +#define       BGE_VCPU_EXT_CTRL_DISABLE_WOL   0x20000000
  
  /*
   * TX CPU registers
 @@ -1683,6 +1697,55 @@
  #define       BGE_MDI_CTL                     0x6844
  #define       BGE_EE_DELAY                    0x6848
  #define       BGE_FASTBOOT_PC                 0x6894
 +/*
 + * NVRAM Control registers
 + */
 +#define       BGE_NVRAM_CMD                   0x7000
 +#define       BGE_NVRAM_STAT                  0x7004
 +#define       BGE_NVRAM_WRDATA                0x7008
 +#define       BGE_NVRAM_ADDR                  0x700c
 +#define       BGE_NVRAM_RDDATA                0x7010
 +#define       BGE_NVRAM_CFG1                  0x7014
 +#define       BGE_NVRAM_CFG2                  0x7018
 +#define       BGE_NVRAM_CFG3                  0x701c
 +#define       BGE_NVRAM_SWARB                 0x7020
 +#define       BGE_NVRAM_ACCESS                0x7024
 +#define       BGE_NVRAM_WRITE1                0x7028
 +
 +#define       BGE_NVRAMCMD_RESET              0x00000001
 +#define       BGE_NVRAMCMD_DONE               0x00000008
 +#define       BGE_NVRAMCMD_START              0x00000010
 +#define       BGE_NVRAMCMD_WR                 0x00000020 /* 1 = wr, 0 = rd */
 +#define       BGE_NVRAMCMD_ERASE              0x00000040
 +#define       BGE_NVRAMCMD_FIRST              0x00000080
 +#define       BGE_NVRAMCMD_LAST               0x00000100
 +
 +#define       BGE_NVRAM_READCMD \
 +      (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
 +      BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE)
 +#define       BGE_NVRAM_WRITECMD \
 +      (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \
 +      BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR)
 +
 +#define       BGE_NVRAMSWARB_SET0             0x00000001
 +#define       BGE_NVRAMSWARB_SET1             0x00000002
 +#define       BGE_NVRAMSWARB_SET2             0x00000003
 +#define       BGE_NVRAMSWARB_SET3             0x00000004
 +#define       BGE_NVRAMSWARB_CLR0             0x00000010
 +#define       BGE_NVRAMSWARB_CLR1             0x00000020
 +#define       BGE_NVRAMSWARB_CLR2             0x00000040
 +#define       BGE_NVRAMSWARB_CLR3             0x00000080
 +#define       BGE_NVRAMSWARB_GNT0             0x00000100
 +#define       BGE_NVRAMSWARB_GNT1             0x00000200
 +#define       BGE_NVRAMSWARB_GNT2             0x00000400
 +#define       BGE_NVRAMSWARB_GNT3             0x00000800
 +#define       BGE_NVRAMSWARB_REQ0             0x00001000
 +#define       BGE_NVRAMSWARB_REQ1             0x00002000
 +#define       BGE_NVRAMSWARB_REQ2             0x00004000
 +#define       BGE_NVRAMSWARB_REQ3             0x00008000
 +
 +#define       BGE_NVRAMACC_ENABLE             0x00000001
 +#define       BGE_NVRAMACC_WRENABLE           0x00000002
  
  /* Mode control register */
  #define       BGE_MODECTL_INT_SNDCOAL_ONLY    0x00000001
 @@ -1711,6 +1774,7 @@
  /* Misc. config register */
  #define       BGE_MISCCFG_RESET_CORE_CLOCKS   0x00000001
  #define       BGE_MISCCFG_TIMER_PRESCALER     0x000000FE
 +#define       BGE_MISCCFG_EPHY_IDDQ           0x00200000
  
  #define       BGE_32BITTIME_66MHZ             (0x41 << 1)
  
 @@ -2037,6 +2101,8 @@
  #define       BCOM_DEVICEID_BCM5901           0x170D
  #define       BCOM_DEVICEID_BCM5901A2         0x170E
  #define       BCOM_DEVICEID_BCM5903M          0x16FF
 +#define       BCOM_DEVICEID_BCM5906           0x1712
 +#define       BCOM_DEVICEID_BCM5906M          0x1713
  
  /*
   * Alteon AceNIC PCI vendor/device ID.
 @@ -2090,6 +2156,7 @@
   * Offset of MAC address inside EEPROM.
   */
  #define       BGE_EE_MAC_OFFSET               0x7C
 +#define       BGE_EE_MAC_OFFSET_5906          0x10
  #define       BGE_EE_HWCFG_OFFSET             0xC8
  
  #define       BGE_HWCFG_VOLTAGE               0x00000003
 @@ -2474,6 +2541,7 @@
  #define       BGE_FLAG_BER_BUG        0x02000000
  #define       BGE_FLAG_ADJUST_TRIM    0x04000000
  #define       BGE_FLAG_CRC_BUG        0x08000000
 +#define       BGE_FLAG_NO_EEPROM      0x10000000
        uint32_t                bge_chipid;
        uint8_t                 bge_asicrev;
        uint8_t                 bge_chiprev;
 --- ./sys/dev/mii/brgphy.c.70  2008-03-01 14:54:58.000000000 +0100
 +++ ./sys/dev/mii/brgphy.c     2008-03-01 14:55:49.000000000 +0100
 @@ -131,6 +131,7 @@
        MII_PHY_DESC(xxBROADCOM_ALT1, BCM5755),
        MII_PHY_DESC(xxBROADCOM_ALT1, BCM5787),
        MII_PHY_DESC(xxBROADCOM_ALT1, BCM5708S),
 +      MII_PHY_DESC(BROADCOM2, BCM5906),
        MII_PHY_END
  };
  
 @@ -186,6 +187,7 @@
        /* Handle any special cases based on the PHY ID */
        switch (bsc->mii_oui) {
        case MII_OUI_BROADCOM: 
 +      case MII_OUI_BROADCOM2: 
                break;
        case MII_OUI_xxBROADCOM:
                switch (bsc->mii_model) {
 @@ -226,12 +228,14 @@
                bce_sc = ifp->if_softc;
        }
  
 -      /* Todo: Need to add additional controllers such as 5906 & 5787F */
 +      /* Todo: Need to add additional controllers such as 5787F */
        /* The 590x chips are 10/100 only. */
        if (bge_sc &&
            pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID &&
            (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 ||
 -          pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2)) {
 +           pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2 ||
 +           pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906 ||
 +           pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906M)) {
                fast_ether = 1;
                sc->mii_anegticks = MII_ANEGTICKS;
        }
 @@ -930,6 +934,11 @@
                            PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) &
                            ~BRGPHY_PHY_EXTCTL_3_LED);
                }
 +
 +              /* Adjust output voltage (From Linux driver) */
 +              if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906)
 +                      PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
 +
        /* Handle any bce (NetXtreme II) workarounds. */
        } else if (bce_sc) {
  
 --- ./sys/dev/mii/brgphyreg.h.70       2008-03-01 14:55:05.000000000 +0100
 +++ ./sys/dev/mii/brgphyreg.h  2008-03-01 14:55:49.000000000 +0100
 @@ -161,6 +161,7 @@
  #define       BRGPHY_MII_DSP_RW_PORT  0x15    /* DSP coefficient r/w port */
  
  #define       BRGPHY_MII_DSP_ADDR_REG 0x17    /* DSP coefficient addr 
register */
 +#define BRGPHY_MII_EPHY_PTEST 0x17    /* 5906 PHY register */
  
  #define       BRGPHY_DSP_TAP_NUMBER_MASK              0x00
  #define       BRGPHY_DSP_AGC_A                        0x00
 --- ./sys/dev/mii/miidevs.orig 2007-11-05 02:42:02.000000000 +0100
 +++ ./sys/dev/mii/miidevs      2008-03-01 14:55:49.000000000 +0100
 @@ -52,6 +52,7 @@
  oui ALTIMA                    0x0010a9        Altima Communications
  oui AMD                               0x00001a        Advanced Micro Devices
  oui BROADCOM                  0x001018        Broadcom Corporation
 +oui BROADCOM2                 0x000af7        Broadcom Corporation
  oui CICADA                    0x0003F1        Cicada Semiconductor
  oui DAVICOM                   0x00606e        Davicom Semiconductor
  oui ICPLUS                    0x0090c3        IC Plus Corp.
 @@ -135,6 +136,7 @@
  model xxBROADCOM_ALT1 BCM5755 0x000c BCM5755 10/100/1000baseTX PHY
  model xxBROADCOM_ALT1 BCM5787 0x000e BCM5787 10/100/1000baseTX PHY
  model xxBROADCOM_ALT1 BCM5708S        0x0015 BCM5708S 1000/2500BaseSX PHY
 +model BROADCOM2 BCM5906               0x0004 BCM5906 10/100baseTX PHY
  
  /* Cicada Semiconductor PHYs (now owned by Vitesse?) */
  model CICADA CS8201           0x0001 Cicada CS8201 10/100/1000TX PHY
 
 --------------000103070907090204020108--
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to