brcm-2.6: remove old b44 support patches, integrate bcm47xx support into newest versi...
authorFelix Fietkau <nbd@openwrt.org>
Thu, 12 Jan 2006 02:16:42 +0000 (02:16 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Thu, 12 Jan 2006 02:16:42 +0000 (02:16 +0000)
SVN-Revision: 2929

openwrt/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch [new file with mode: 0644]
openwrt/target/linux/generic-2.6/patches/003-net-b44-1.patch [deleted file]
openwrt/target/linux/generic-2.6/patches/003-net-b44-2.patch [deleted file]

diff --git a/openwrt/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch b/openwrt/target/linux/brcm-2.6/patches/004-b44_bcm47xx_support.patch
new file mode 100644 (file)
index 0000000..e1856f9
--- /dev/null
@@ -0,0 +1,639 @@
+diff -urN linux.old/drivers/net/b44.c linux.dev/drivers/net/b44.c
+--- linux.old/drivers/net/b44.c        2006-01-12 01:44:42.548326000 +0100
++++ linux.dev/drivers/net/b44.c        2006-01-12 03:07:38.209775500 +0100
+@@ -1,7 +1,9 @@
+-/* b44.c: Broadcom 4400 device driver.
++/* b44.c: Broadcom 4400/47xx device driver.
+  *
+  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+- * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
++ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
++ * Copyright (C) 2006 Felix Fietkau (nbd@openwrt.org)
+  *
+  * Distribute under GPL.
+  */
+@@ -31,6 +33,28 @@
+ #define DRV_MODULE_VERSION    "0.97"
+ #define DRV_MODULE_RELDATE    "Nov 30, 2005"
++#ifdef CONFIG_BCM947XX
++extern char *nvram_get(char *name);
++static inline void e_aton(char *str, char *dest)
++{
++      int i = 0;
++
++      if (str == NULL) {
++              memset(dest, 0, 6);
++              return;
++      }
++      
++      for (;;) {
++              dest[i++] = (char) simple_strtoul(str, NULL, 16);
++              str += 2;
++              if (!*str++ || i == 6)
++                      break;
++      }
++}
++
++static int b44_4713_instance;
++#endif
++
+ #define B44_DEF_MSG_ENABLE      \
+       (NETIF_MSG_DRV          | \
+        NETIF_MSG_PROBE        | \
+@@ -77,8 +101,8 @@
+ static char version[] __devinitdata =
+       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+-MODULE_AUTHOR("Florian Schirmer, Pekka Pietikainen, David S. Miller");
+-MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
++MODULE_AUTHOR("Felix Fietkau, Florian Schirmer, Pekka Pietikainen, David S. Miller");
++MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_MODULE_VERSION);
+@@ -93,6 +117,10 @@
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++#ifdef CONFIG_BCM947XX
++      { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
++        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++#endif
+       { }     /* terminate list with empty entry */
+ };
+@@ -131,17 +159,6 @@
+                                     dma_desc_sync_size, dir);
+ }
+-static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
+-{
+-      return readl(bp->regs + reg);
+-}
+-
+-static inline void bw32(const struct b44 *bp, 
+-                      unsigned long reg, unsigned long val)
+-{
+-      writel(val, bp->regs + reg);
+-}
+-
+ static int b44_wait_bit(struct b44 *bp, unsigned long reg,
+                       u32 bit, unsigned long timeout, const int clear)
+ {
+@@ -268,6 +285,10 @@
+               break;
+       };
+ #endif
++#ifdef CONFIG_BCM947XX
++      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++              return b44_4713_instance++;
++#endif
+       return 0;
+ }
+@@ -313,14 +334,14 @@
+       bw32(bp, B44_IMASK, bp->imask);
+ }
+-static int b44_readphy(struct b44 *bp, int reg, u32 *val)
++static int __b44_readphy(struct b44 *bp, int phy_addr, int reg, u32 *val)
+ {
+       int err;
+       bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+       bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
+                            (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
+-                           (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++                           (phy_addr << MDIO_DATA_PMD_SHIFT) |
+                            (reg << MDIO_DATA_RA_SHIFT) |
+                            (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
+       err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+@@ -329,18 +350,34 @@
+       return err;
+ }
+-static int b44_writephy(struct b44 *bp, int reg, u32 val)
++static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
+ {
+       bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+       bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
+                            (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
+-                           (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
++                           (phy_addr << MDIO_DATA_PMD_SHIFT) |
+                            (reg << MDIO_DATA_RA_SHIFT) |
+                            (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
+                            (val & MDIO_DATA_DATA)));
+       return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
+ }
++static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
++{
++      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++              return 0;
++
++      return __b44_readphy(bp, bp->phy_addr, reg, val);
++}
++
++static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
++{
++      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++              return 0;
++              
++      return __b44_writephy(bp, bp->phy_addr, reg, val);
++}
++
+ /* miilib interface */
+ /* FIXME FIXME: phy_id is ignored, bp->phy_addr use is unconditional
+  * due to code existing before miilib use was added to this driver.
+@@ -369,6 +406,8 @@
+       u32 val;
+       int err;
++      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++              return 0;
+       err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
+       if (err)
+               return err;
+@@ -439,6 +478,8 @@
+       u32 val;
+       int err;
++      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
++              return 0;
+       if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
+               goto out;
+       if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
+@@ -534,6 +575,19 @@
+ {
+       u32 bmsr, aux;
++      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
++              bp->flags |= B44_FLAG_100_BASE_T;
++              bp->flags |= B44_FLAG_FULL_DUPLEX;
++              if (!netif_carrier_ok(bp->dev)) {
++                      u32 val = br32(bp, B44_TX_CTRL);
++                      val |= TX_CTRL_DUPLEX;
++                      bw32(bp, B44_TX_CTRL, val);
++                      netif_carrier_on(bp->dev);
++                      b44_link_report(bp);
++              }
++              return;
++      }
++
+       if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
+           !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
+           (bmsr != 0xffff)) {
+@@ -1281,9 +1335,10 @@
+               bw32(bp, B44_DMARX_CTRL, 0);
+               bp->rx_prod = bp->rx_cons = 0;
+       } else {
+-              ssb_pci_setup(bp, (bp->core_unit == 0 ?
+-                                 SBINTVEC_ENET0 :
+-                                 SBINTVEC_ENET1));
++              if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
++                      ssb_pci_setup(bp, (bp->core_unit == 0 ?
++                                         SBINTVEC_ENET0 :
++                                         SBINTVEC_ENET1));
+       }
+       ssb_core_reset(bp);
+@@ -1291,8 +1346,14 @@
+       b44_clear_stats(bp);
+       /* Make PHY accessible. */
+-      bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
++      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
++              bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
++                           (((100000000 + (B44_MDC_RATIO / 2)) / B44_MDC_RATIO)
++                           & MDIO_CTRL_MAXF_MASK)));
++      else
++              bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+                            (0x0d & MDIO_CTRL_MAXF_MASK)));
++
+       br32(bp, B44_MDIO_CTRL);
+       if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+@@ -1834,18 +1895,297 @@
+       .get_perm_addr          = ethtool_op_get_perm_addr,
+ };
++static int b44_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
++{
++      struct b44 *bp = dev->priv;
++      struct pci_dev *pci_dev = bp->pdev;
++      u32 ethcmd;
++
++      if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
++              return -EFAULT;
++
++      switch (ethcmd) {
++      case ETHTOOL_GDRVINFO: {
++              struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
++              strcpy (info.driver, DRV_MODULE_NAME);
++              strcpy (info.version, DRV_MODULE_VERSION);
++              memset(&info.fw_version, 0, sizeof(info.fw_version));
++              strcpy (info.bus_info, pci_name(pci_dev));
++              info.eedump_len = 0;
++              info.regdump_len = 0;
++              if (copy_to_user (useraddr, &info, sizeof (info)))
++                      return -EFAULT;
++              return 0;
++      }
++
++      case ETHTOOL_GSET: {
++              struct ethtool_cmd cmd = { ETHTOOL_GSET };
++
++              if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
++                      return -EAGAIN;
++              cmd.supported = (SUPPORTED_Autoneg);
++              cmd.supported |= (SUPPORTED_100baseT_Half |
++                                SUPPORTED_100baseT_Full |
++                                SUPPORTED_10baseT_Half |
++                                SUPPORTED_10baseT_Full |
++                                SUPPORTED_MII);
++
++              cmd.advertising = 0;
++              if (bp->flags & B44_FLAG_ADV_10HALF)
++                      cmd.advertising |= ADVERTISE_10HALF;
++              if (bp->flags & B44_FLAG_ADV_10FULL)
++                      cmd.advertising |= ADVERTISE_10FULL;
++              if (bp->flags & B44_FLAG_ADV_100HALF)
++                      cmd.advertising |= ADVERTISE_100HALF;
++              if (bp->flags & B44_FLAG_ADV_100FULL)
++                      cmd.advertising |= ADVERTISE_100FULL;
++              cmd.advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
++              cmd.speed = (bp->flags & B44_FLAG_100_BASE_T) ?
++                      SPEED_100 : SPEED_10;
++              cmd.duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
++                      DUPLEX_FULL : DUPLEX_HALF;
++              cmd.port = 0;
++              cmd.phy_address = bp->phy_addr;
++              cmd.transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
++                      XCVR_INTERNAL : XCVR_EXTERNAL;
++              cmd.autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
++                      AUTONEG_DISABLE : AUTONEG_ENABLE;
++              cmd.maxtxpkt = 0;
++              cmd.maxrxpkt = 0;
++              if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
++                      return -EFAULT;
++              return 0;
++      }
++      case ETHTOOL_SSET: {
++              struct ethtool_cmd cmd;
++
++              if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
++                      return -EAGAIN;
++
++              if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
++                      return -EFAULT;
++
++              /* We do not support gigabit. */
++              if (cmd.autoneg == AUTONEG_ENABLE) {
++                      if (cmd.advertising &
++                          (ADVERTISED_1000baseT_Half |
++                           ADVERTISED_1000baseT_Full))
++                              return -EINVAL;
++              } else if ((cmd.speed != SPEED_100 &&
++                          cmd.speed != SPEED_10) ||
++                         (cmd.duplex != DUPLEX_HALF &&
++                          cmd.duplex != DUPLEX_FULL)) {
++                              return -EINVAL;
++              }
++
++              spin_lock_irq(&bp->lock);
++
++              if (cmd.autoneg == AUTONEG_ENABLE) {
++                      bp->flags &= ~B44_FLAG_FORCE_LINK;
++                      bp->flags &= ~(B44_FLAG_ADV_10HALF |
++                                     B44_FLAG_ADV_10FULL |
++                                     B44_FLAG_ADV_100HALF |
++                                     B44_FLAG_ADV_100FULL);
++                      if (cmd.advertising & ADVERTISE_10HALF)
++                              bp->flags |= B44_FLAG_ADV_10HALF;
++                      if (cmd.advertising & ADVERTISE_10FULL)
++                              bp->flags |= B44_FLAG_ADV_10FULL;
++                      if (cmd.advertising & ADVERTISE_100HALF)
++                              bp->flags |= B44_FLAG_ADV_100HALF;
++                      if (cmd.advertising & ADVERTISE_100FULL)
++                              bp->flags |= B44_FLAG_ADV_100FULL;
++              } else {
++                      bp->flags |= B44_FLAG_FORCE_LINK;
++                      if (cmd.speed == SPEED_100)
++                              bp->flags |= B44_FLAG_100_BASE_T;
++                      if (cmd.duplex == DUPLEX_FULL)
++                              bp->flags |= B44_FLAG_FULL_DUPLEX;
++              }
++
++              b44_setup_phy(bp);
++
++              spin_unlock_irq(&bp->lock);
++
++              return 0;
++      }
++
++      case ETHTOOL_GMSGLVL: {
++              struct ethtool_value edata = { ETHTOOL_GMSGLVL };
++              edata.data = bp->msg_enable;
++              if (copy_to_user(useraddr, &edata, sizeof(edata)))
++                      return -EFAULT;
++              return 0;
++      }
++      case ETHTOOL_SMSGLVL: {
++              struct ethtool_value edata;
++              if (copy_from_user(&edata, useraddr, sizeof(edata)))
++                      return -EFAULT;
++              bp->msg_enable = edata.data;
++              return 0;
++      }
++      case ETHTOOL_NWAY_RST: {
++              u32 bmcr;
++              int r;
++
++              spin_lock_irq(&bp->lock);
++              b44_readphy(bp, MII_BMCR, &bmcr);
++              b44_readphy(bp, MII_BMCR, &bmcr);
++              r = -EINVAL;
++              if (bmcr & BMCR_ANENABLE) {
++                      b44_writephy(bp, MII_BMCR,
++                                   bmcr | BMCR_ANRESTART);
++                      r = 0;
++              }
++              spin_unlock_irq(&bp->lock);
++
++              return r;
++      }
++      case ETHTOOL_GLINK: {
++              struct ethtool_value edata = { ETHTOOL_GLINK };
++              edata.data = netif_carrier_ok(bp->dev) ? 1 : 0;
++              if (copy_to_user(useraddr, &edata, sizeof(edata)))
++                      return -EFAULT;
++              return 0;
++      }
++      case ETHTOOL_GRINGPARAM: {
++              struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
++
++              ering.rx_max_pending = B44_RX_RING_SIZE - 1;
++              ering.rx_pending = bp->rx_pending;
++
++              /* XXX ethtool lacks a tx_max_pending, oops... */
++
++              if (copy_to_user(useraddr, &ering, sizeof(ering)))
++                      return -EFAULT;
++              return 0;
++      }
++      case ETHTOOL_SRINGPARAM: {
++              struct ethtool_ringparam ering;
++
++              if (copy_from_user(&ering, useraddr, sizeof(ering)))
++                      return -EFAULT;
++
++              if ((ering.rx_pending > B44_RX_RING_SIZE - 1) ||
++                  (ering.rx_mini_pending != 0) ||
++                  (ering.rx_jumbo_pending != 0) ||
++                  (ering.tx_pending > B44_TX_RING_SIZE - 1))
++                      return -EINVAL;
++
++              spin_lock_irq(&bp->lock);
++
++              bp->rx_pending = ering.rx_pending;
++              bp->tx_pending = ering.tx_pending;
++
++              b44_halt(bp);
++              b44_init_rings(bp);
++              b44_init_hw(bp);
++              netif_wake_queue(bp->dev);
++              spin_unlock_irq(&bp->lock);
++
++              b44_enable_ints(bp);
++              
++              return 0;
++      }
++      case ETHTOOL_GPAUSEPARAM: {
++              struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
++
++              epause.autoneg =
++                      (bp->flags & B44_FLAG_PAUSE_AUTO) != 0;
++              epause.rx_pause =
++                      (bp->flags & B44_FLAG_RX_PAUSE) != 0;
++              epause.tx_pause =
++                      (bp->flags & B44_FLAG_TX_PAUSE) != 0;
++              if (copy_to_user(useraddr, &epause, sizeof(epause)))
++                      return -EFAULT;
++              return 0;
++      }
++      case ETHTOOL_SPAUSEPARAM: {
++              struct ethtool_pauseparam epause;
++
++              if (copy_from_user(&epause, useraddr, sizeof(epause)))
++                      return -EFAULT;
++
++              spin_lock_irq(&bp->lock);
++              if (epause.autoneg)
++                      bp->flags |= B44_FLAG_PAUSE_AUTO;
++              else
++                      bp->flags &= ~B44_FLAG_PAUSE_AUTO;
++              if (epause.rx_pause)
++                      bp->flags |= B44_FLAG_RX_PAUSE;
++              else
++                      bp->flags &= ~B44_FLAG_RX_PAUSE;
++              if (epause.tx_pause)
++                      bp->flags |= B44_FLAG_TX_PAUSE;
++              else
++                      bp->flags &= ~B44_FLAG_TX_PAUSE;
++              if (bp->flags & B44_FLAG_PAUSE_AUTO) {
++                      b44_halt(bp);
++                      b44_init_rings(bp);
++                      b44_init_hw(bp);
++              } else {
++                      __b44_set_flow_ctrl(bp, bp->flags);
++              }
++              spin_unlock_irq(&bp->lock);
++
++              b44_enable_ints(bp);
++              
++              return 0;
++      }
++      };
++
++      return -EOPNOTSUPP;
++}
++
+ static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ {
+       struct mii_ioctl_data *data = if_mii(ifr);
+       struct b44 *bp = netdev_priv(dev);
+       int err = -EINVAL;
+-      if (!netif_running(dev))
++      if (bp->pdev->device != PCI_DEVICE_ID_BCM4713) {
++              if (!netif_running(dev))
++                      goto out;
++
++              spin_lock_irq(&bp->lock);
++              err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
++              spin_unlock_irq(&bp->lock);
+               goto out;
++      }
+-      spin_lock_irq(&bp->lock);
+-      err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
+-      spin_unlock_irq(&bp->lock);
++      switch (cmd) {
++      case SIOCETHTOOL:
++              return b44_ethtool_ioctl(dev, (void __user*) ifr->ifr_data);
++
++      case SIOCGMIIPHY:
++              data->phy_id = bp->phy_addr;
++
++              /* fallthru */
++      case SIOCGMIIREG: {
++              u32 mii_regval;
++              spin_lock_irq(&bp->lock);
++              err = __b44_readphy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
++              spin_unlock_irq(&bp->lock);
++
++              data->val_out = mii_regval;
++
++              return err;
++      }
++
++      case SIOCSMIIREG:
++              if (!capable(CAP_NET_ADMIN))
++                      return -EPERM;
++
++              spin_lock_irq(&bp->lock);
++              err = __b44_writephy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
++              spin_unlock_irq(&bp->lock);
++
++              return err;
++
++      default:
++              break;
++      };
++      return -EOPNOTSUPP;
++              
+ out:
+       return err;
+ }
+@@ -1865,22 +2205,43 @@
+ static int __devinit b44_get_invariants(struct b44 *bp)
+ {
+       u8 eeprom[128];
+-      int err;
++      u8 buf[32];
++      int err = 0;
+-      err = b44_read_eeprom(bp, &eeprom[0]);
+-      if (err)
+-              goto out;
+-
+-      bp->dev->dev_addr[0] = eeprom[79];
+-      bp->dev->dev_addr[1] = eeprom[78];
+-      bp->dev->dev_addr[2] = eeprom[81];
+-      bp->dev->dev_addr[3] = eeprom[80];
+-      bp->dev->dev_addr[4] = eeprom[83];
+-      bp->dev->dev_addr[5] = eeprom[82];
+-      memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
+-
+-      bp->phy_addr = eeprom[90] & 0x1f;
++#ifdef CONFIG_BCM947XX
++      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
++              /* 
++               * BCM47xx boards don't have a EEPROM. The MAC is stored in
++               * a NVRAM area somewhere in the flash memory.
++               */
++              sprintf(buf, "et%dmacaddr", b44_4713_instance);
++              e_aton(nvram_get(buf), bp->dev->dev_addr);
++              /* 
++               * BCM47xx boards don't have a PHY. Usually there is a switch
++               * chip with multiple PHYs connected to the PHY port.
++               */
++              bp->phy_addr = B44_PHY_ADDR_NO_PHY;
++              bp->dma_offset = 0;
++      } else
++#endif
++      {
++              err = b44_read_eeprom(bp, &eeprom[0]);
++              if (err)
++                      goto out;
++      
++              bp->dev->dev_addr[0] = eeprom[79];
++              bp->dev->dev_addr[1] = eeprom[78];
++              bp->dev->dev_addr[2] = eeprom[81];
++              bp->dev->dev_addr[3] = eeprom[80];
++              bp->dev->dev_addr[4] = eeprom[83];
++              bp->dev->dev_addr[5] = eeprom[82];
++              memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
++      
++              bp->phy_addr = eeprom[90] & 0x1f;
++              bp->dma_offset = SB_PCI_DMA;
++      }
++      
+       /* With this, plus the rx_header prepended to the data by the
+        * hardware, we'll land the ethernet header on a 2-byte boundary.
+        */
+@@ -1889,11 +2250,7 @@
+       bp->imask = IMASK_DEF;
+       bp->core_unit = ssb_core_unit(bp);
+-      bp->dma_offset = SB_PCI_DMA;
+-      /* XXX - really required? 
+-         bp->flags |= B44_FLAG_BUGGY_TXPTR;
+-         */
+ out:
+       return err;
+ }
+@@ -2032,11 +2389,17 @@
+       pci_save_state(bp->pdev);
+-      printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
++      printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
++              (pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
+       for (i = 0; i < 6; i++)
+               printk("%2.2x%c", dev->dev_addr[i],
+                      i == 5 ? '\n' : ':');
++      /* Initialize phy */
++      spin_lock_irq(&bp->lock);
++      b44_chip_reset(bp);
++      spin_unlock_irq(&bp->lock);
++
+       return 0;
+ err_out_iounmap:
+diff -urN linux.old/drivers/net/b44.h linux.dev/drivers/net/b44.h
+--- linux.old/drivers/net/b44.h        2006-01-12 01:44:42.548326000 +0100
++++ linux.dev/drivers/net/b44.h        2006-01-12 02:55:06.290783500 +0100
+@@ -292,6 +292,10 @@
+ #define SSB_PCI_MASK1         0xfc000000
+ #define SSB_PCI_MASK2         0xc0000000
++#define br32(bp, REG) readl((void *)bp->regs + (REG))
++#define bw32(bp, REG,VAL)     writel((VAL), (void *)bp->regs + (REG))
++#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
++
+ /* 4400 PHY registers */
+ #define B44_MII_AUXCTRL               24      /* Auxiliary Control */
+ #define  MII_AUXCTRL_DUPLEX   0x0001  /* Full Duplex */
+@@ -345,6 +349,8 @@
+ };
+ #define B44_MCAST_TABLE_SIZE  32
++#define B44_PHY_ADDR_NO_PHY   30
++#define B44_MDC_RATIO         5000000
+ #define       B44_STAT_REG_DECLARE            \
+       _B44(tx_good_octets)            \
+@@ -420,6 +426,7 @@
+       u32                     dma_offset;
+       u32                     flags;
++#define B44_FLAG_INIT_COMPLETE        0x00000001
+ #define B44_FLAG_BUGGY_TXPTR  0x00000002
+ #define B44_FLAG_REORDER_BUG  0x00000004
+ #define B44_FLAG_PAUSE_AUTO   0x00008000
diff --git a/openwrt/target/linux/generic-2.6/patches/003-net-b44-1.patch b/openwrt/target/linux/generic-2.6/patches/003-net-b44-1.patch
deleted file mode 100644 (file)
index 726ea54..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-diff -ur linux-2.6.15-rc5/drivers/net/b44.c linux-2.6.15-rc5-openwrt/drivers/net/b44.c
---- linux-2.6.15-rc5/drivers/net/b44.c 2005-12-04 06:10:42.000000000 +0100
-+++ linux-2.6.15-rc5-openwrt/drivers/net/b44.c 2005-08-15 02:20:18.000000000 +0200
-@@ -18,7 +18,7 @@
- #include <linux/pci.h>
- #include <linux/delay.h>
- #include <linux/init.h>
--#include <linux/dma-mapping.h>
-+#include <linux/version.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
-@@ -28,8 +28,8 @@
- #define DRV_MODULE_NAME               "b44"
- #define PFX DRV_MODULE_NAME   ": "
--#define DRV_MODULE_VERSION    "0.97"
--#define DRV_MODULE_RELDATE    "Nov 30, 2005"
-+#define DRV_MODULE_VERSION    "0.95"
-+#define DRV_MODULE_RELDATE    "Aug 3, 2004"
- #define B44_DEF_MSG_ENABLE      \
-       (NETIF_MSG_DRV          | \
-@@ -101,35 +101,10 @@
- static void b44_halt(struct b44 *);
- static void b44_init_rings(struct b44 *);
- static void b44_init_hw(struct b44 *);
--
--static int dma_desc_align_mask;
--static int dma_desc_sync_size;
--
--static const char b44_gstrings[][ETH_GSTRING_LEN] = {
--#define _B44(x...)    # x,
--B44_STAT_REG_DECLARE
--#undef _B44
--};
--
--static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
--                                                dma_addr_t dma_base,
--                                                unsigned long offset,
--                                                enum dma_data_direction dir)
--{
--      dma_sync_single_range_for_device(&pdev->dev, dma_base,
--                                       offset & dma_desc_align_mask,
--                                       dma_desc_sync_size, dir);
--}
--
--static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
--                                             dma_addr_t dma_base,
--                                             unsigned long offset,
--                                             enum dma_data_direction dir)
--{
--      dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
--                                    offset & dma_desc_align_mask,
--                                    dma_desc_sync_size, dir);
--}
-+static int b44_poll(struct net_device *dev, int *budget);
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+static void b44_poll_controller(struct net_device *dev);
-+#endif
- static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
- {
-@@ -503,10 +478,7 @@
-       for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
-               *val++ += br32(bp, reg);
-       }
--
--      /* Pad */
--      reg += 8*4UL;
--
-+      val = &bp->hw_stats.rx_good_octets;
-       for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
-               *val++ += br32(bp, reg);
-       }
-@@ -657,7 +629,7 @@
-       /* Hardware bug work-around, the chip is unable to do PCI DMA
-          to/from anything above 1GB :-( */
--      if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
-+      if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
-               /* Sigh... */
-               pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
-               dev_kfree_skb_any(skb);
-@@ -667,7 +639,7 @@
-               mapping = pci_map_single(bp->pdev, skb->data,
-                                        RX_PKT_BUF_SZ,
-                                        PCI_DMA_FROMDEVICE);
--              if (mapping + RX_PKT_BUF_SZ > B44_DMA_MASK) {
-+              if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
-                       pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb_any(skb);
-                       return -ENOMEM;
-@@ -696,11 +668,6 @@
-       dp->ctrl = cpu_to_le32(ctrl);
-       dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
--      if (bp->flags & B44_FLAG_RX_RING_HACK)
--              b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
--                                           dest_idx * sizeof(dp),
--                                           DMA_BIDIRECTIONAL);
--
-       return RX_PKT_BUF_SZ;
- }
-@@ -725,11 +692,6 @@
-       pci_unmap_addr_set(dest_map, mapping,
-                          pci_unmap_addr(src_map, mapping));
--      if (bp->flags & B44_FLAG_RX_RING_HACK)
--              b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
--                                        src_idx * sizeof(src_desc),
--                                        DMA_BIDIRECTIONAL);
--
-       ctrl = src_desc->ctrl;
-       if (dest_idx == (B44_RX_RING_SIZE - 1))
-               ctrl |= cpu_to_le32(DESC_CTRL_EOT);
-@@ -738,14 +700,8 @@
-       dest_desc->ctrl = ctrl;
-       dest_desc->addr = src_desc->addr;
--
-       src_map->skb = NULL;
--      if (bp->flags & B44_FLAG_RX_RING_HACK)
--              b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
--                                           dest_idx * sizeof(dest_desc),
--                                           DMA_BIDIRECTIONAL);
--
-       pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
-                                      RX_PKT_BUF_SZ,
-                                      PCI_DMA_FROMDEVICE);
-@@ -894,10 +850,11 @@
- {
-       struct net_device *dev = dev_id;
-       struct b44 *bp = netdev_priv(dev);
-+      unsigned long flags;
-       u32 istat, imask;
-       int handled = 0;
--      spin_lock(&bp->lock);
-+      spin_lock_irqsave(&bp->lock, flags);
-       istat = br32(bp, B44_ISTAT);
-       imask = br32(bp, B44_IMASK);
-@@ -908,12 +865,6 @@
-       istat &= imask;
-       if (istat) {
-               handled = 1;
--
--              if (unlikely(!netif_running(dev))) {
--                      printk(KERN_INFO "%s: late interrupt.\n", dev->name);
--                      goto irq_ack;
--              }
--
-               if (netif_rx_schedule_prep(dev)) {
-                       /* NOTE: These writes are posted by the readback of
-                        *       the ISTAT register below.
-@@ -926,11 +877,10 @@
-                              dev->name);
-               }
--irq_ack:
-               bw32(bp, B44_ISTAT, istat);
-               br32(bp, B44_ISTAT);
-       }
--      spin_unlock(&bp->lock);
-+      spin_unlock_irqrestore(&bp->lock, flags);
-       return IRQ_RETVAL(handled);
- }
-@@ -958,7 +908,6 @@
- {
-       struct b44 *bp = netdev_priv(dev);
-       struct sk_buff *bounce_skb;
--      int rc = NETDEV_TX_OK;
-       dma_addr_t mapping;
-       u32 len, entry, ctrl;
-@@ -968,28 +917,29 @@
-       /* This is a hard error, log it. */
-       if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) {
-               netif_stop_queue(dev);
-+              spin_unlock_irq(&bp->lock);
-               printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-                      dev->name);
--              goto err_out;
-+              return 1;
-       }
-       mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
--      if (mapping + len > B44_DMA_MASK) {
-+      if(mapping+len > B44_DMA_MASK) {
-               /* Chip can't handle DMA to/from >1GB, use bounce buffer */
-               pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
-               bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
-                                            GFP_ATOMIC|GFP_DMA);
-               if (!bounce_skb)
--                      goto err_out;
-+                      return NETDEV_TX_BUSY;
-               mapping = pci_map_single(bp->pdev, bounce_skb->data,
-                                        len, PCI_DMA_TODEVICE);
--              if (mapping + len > B44_DMA_MASK) {
-+              if(mapping+len > B44_DMA_MASK) {
-                       pci_unmap_single(bp->pdev, mapping,
-                                        len, PCI_DMA_TODEVICE);
-                       dev_kfree_skb_any(bounce_skb);
--                      goto err_out;
-+                      return NETDEV_TX_BUSY;
-               }
-               memcpy(skb_put(bounce_skb, len), skb->data, skb->len);
-@@ -1009,11 +959,6 @@
-       bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
-       bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
--      if (bp->flags & B44_FLAG_TX_RING_HACK)
--              b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
--                                           entry * sizeof(bp->tx_ring[0]),
--                                           DMA_TO_DEVICE);
--
-       entry = NEXT_TX(entry);
-       bp->tx_prod = entry;
-@@ -1029,16 +974,11 @@
-       if (TX_BUFFS_AVAIL(bp) < 1)
-               netif_stop_queue(dev);
--      dev->trans_start = jiffies;
--
--out_unlock:
-       spin_unlock_irq(&bp->lock);
--      return rc;
-+      dev->trans_start = jiffies;
--err_out:
--      rc = NETDEV_TX_BUSY;
--      goto out_unlock;
-+      return 0;
- }
- static int b44_change_mtu(struct net_device *dev, int new_mtu)
-@@ -1112,7 +1052,8 @@
-  *
-  * The chip has been shut down and the driver detached from
-  * the networking, so no interrupts or new tx packets will
-- * end up in the driver.
-+ * end up in the driver.  bp->lock is not held and we are not
-+ * in an interrupt context and thus may sleep.
-  */
- static void b44_init_rings(struct b44 *bp)
- {
-@@ -1123,16 +1064,6 @@
-       memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
-       memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
--      if (bp->flags & B44_FLAG_RX_RING_HACK)
--              dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
--                                         DMA_TABLE_BYTES,
--                                         PCI_DMA_BIDIRECTIONAL);
--
--      if (bp->flags & B44_FLAG_TX_RING_HACK)
--              dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
--                                         DMA_TABLE_BYTES,
--                                         PCI_DMA_TODEVICE);
--
-       for (i = 0; i < bp->rx_pending; i++) {
-               if (b44_alloc_rx_skb(bp, -1, i) < 0)
-                       break;
-@@ -1145,33 +1076,23 @@
-  */
- static void b44_free_consistent(struct b44 *bp)
- {
--      kfree(bp->rx_buffers);
--      bp->rx_buffers = NULL;
--      kfree(bp->tx_buffers);
--      bp->tx_buffers = NULL;
-+      if (bp->rx_buffers) {
-+              kfree(bp->rx_buffers);
-+              bp->rx_buffers = NULL;
-+      }
-+      if (bp->tx_buffers) {
-+              kfree(bp->tx_buffers);
-+              bp->tx_buffers = NULL;
-+      }
-       if (bp->rx_ring) {
--              if (bp->flags & B44_FLAG_RX_RING_HACK) {
--                      dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
--                                       DMA_TABLE_BYTES,
--                                       DMA_BIDIRECTIONAL);
--                      kfree(bp->rx_ring);
--              } else
--                      pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
--                                          bp->rx_ring, bp->rx_ring_dma);
-+              pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-+                                  bp->rx_ring, bp->rx_ring_dma);
-               bp->rx_ring = NULL;
--              bp->flags &= ~B44_FLAG_RX_RING_HACK;
-       }
-       if (bp->tx_ring) {
--              if (bp->flags & B44_FLAG_TX_RING_HACK) {
--                      dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
--                                       DMA_TABLE_BYTES,
--                                       DMA_TO_DEVICE);
--                      kfree(bp->tx_ring);
--              } else
--                      pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
--                                          bp->tx_ring, bp->tx_ring_dma);
-+              pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
-+                                  bp->tx_ring, bp->tx_ring_dma);
-               bp->tx_ring = NULL;
--              bp->flags &= ~B44_FLAG_TX_RING_HACK;
-       }
- }
-@@ -1184,67 +1105,25 @@
-       int size;
-       size  = B44_RX_RING_SIZE * sizeof(struct ring_info);
--      bp->rx_buffers = kzalloc(size, GFP_KERNEL);
-+      bp->rx_buffers = kmalloc(size, GFP_KERNEL);
-       if (!bp->rx_buffers)
-               goto out_err;
-+      memset(bp->rx_buffers, 0, size);
-       size = B44_TX_RING_SIZE * sizeof(struct ring_info);
--      bp->tx_buffers = kzalloc(size, GFP_KERNEL);
-+      bp->tx_buffers = kmalloc(size, GFP_KERNEL);
-       if (!bp->tx_buffers)
-               goto out_err;
-+      memset(bp->tx_buffers, 0, size);
-       size = DMA_TABLE_BYTES;
-       bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
--      if (!bp->rx_ring) {
--              /* Allocation may have failed due to pci_alloc_consistent
--                 insisting on use of GFP_DMA, which is more restrictive
--                 than necessary...  */
--              struct dma_desc *rx_ring;
--              dma_addr_t rx_ring_dma;
--
--              rx_ring = kzalloc(size, GFP_KERNEL);
--              if (!rx_ring)
--                      goto out_err;
--
--              rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
--                                           DMA_TABLE_BYTES,
--                                           DMA_BIDIRECTIONAL);
--
--              if (rx_ring_dma + size > B44_DMA_MASK) {
--                      kfree(rx_ring);
--                      goto out_err;
--              }
--
--              bp->rx_ring = rx_ring;
--              bp->rx_ring_dma = rx_ring_dma;
--              bp->flags |= B44_FLAG_RX_RING_HACK;
--      }
-+      if (!bp->rx_ring)
-+              goto out_err;
-       bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
--      if (!bp->tx_ring) {
--              /* Allocation may have failed due to pci_alloc_consistent
--                 insisting on use of GFP_DMA, which is more restrictive
--                 than necessary...  */
--              struct dma_desc *tx_ring;
--              dma_addr_t tx_ring_dma;
--
--              tx_ring = kzalloc(size, GFP_KERNEL);
--              if (!tx_ring)
--                      goto out_err;
--
--              tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
--                                           DMA_TABLE_BYTES,
--                                           DMA_TO_DEVICE);
--
--              if (tx_ring_dma + size > B44_DMA_MASK) {
--                      kfree(tx_ring);
--                      goto out_err;
--              }
--
--              bp->tx_ring = tx_ring;
--              bp->tx_ring_dma = tx_ring_dma;
--              bp->flags |= B44_FLAG_TX_RING_HACK;
--      }
-+      if (!bp->tx_ring)
-+              goto out_err;
-       return 0;
-@@ -1394,21 +1273,19 @@
-       err = b44_alloc_consistent(bp);
-       if (err)
--              goto out;
-+              return err;
-+
-+      err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev);
-+      if (err)
-+              goto err_out_free;
-+
-+      spin_lock_irq(&bp->lock);
-       b44_init_rings(bp);
-       b44_init_hw(bp);
-+      bp->flags |= B44_FLAG_INIT_COMPLETE;
--      netif_carrier_off(dev);
--      b44_check_phy(bp);
--
--      err = request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev);
--      if (unlikely(err < 0)) {
--              b44_chip_reset(bp);
--              b44_free_rings(bp);
--              b44_free_consistent(bp);
--              goto out;
--      }
-+      spin_unlock_irq(&bp->lock);
-       init_timer(&bp->timer);
-       bp->timer.expires = jiffies + HZ;
-@@ -1417,8 +1294,11 @@
-       add_timer(&bp->timer);
-       b44_enable_ints(bp);
--      netif_start_queue(dev);
--out:
-+
-+      return 0;
-+
-+err_out_free:
-+      b44_free_consistent(bp);
-       return err;
- }
-@@ -1453,8 +1333,6 @@
-       netif_stop_queue(dev);
--      netif_poll_disable(dev);
--
-       del_timer_sync(&bp->timer);
-       spin_lock_irq(&bp->lock);
-@@ -1464,14 +1342,13 @@
- #endif
-       b44_halt(bp);
-       b44_free_rings(bp);
-+      bp->flags &= ~B44_FLAG_INIT_COMPLETE;
-       netif_carrier_off(bp->dev);
-       spin_unlock_irq(&bp->lock);
-       free_irq(dev->irq, dev);
--      netif_poll_enable(dev);
--
-       b44_free_consistent(bp);
-       return 0;
-@@ -1536,6 +1413,8 @@
- {
-       struct b44 *bp = netdev_priv(dev);
-       u32 val;
-+      int i=0;
-+      unsigned char zero[6] = {0,0,0,0,0,0};
-       val = br32(bp, B44_RXCONFIG);
-       val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
-@@ -1543,17 +1422,14 @@
-               val |= RXCONFIG_PROMISC;
-               bw32(bp, B44_RXCONFIG, val);
-       } else {
--              unsigned char zero[6] = {0, 0, 0, 0, 0, 0};
--              int i = 0;
--
-               __b44_set_mac_addr(bp);
-               if (dev->flags & IFF_ALLMULTI)
-                       val |= RXCONFIG_ALLMULTI;
-               else
--                      i = __b44_load_mcast(bp, dev);
-+                      i=__b44_load_mcast(bp, dev);
-               
--              for (; i < 64; i++) {
-+              for(;i<64;i++) {
-                       __b44_cam_write(bp, zero, i);                   
-               }
-               bw32(bp, B44_RXCONFIG, val);
-@@ -1617,7 +1493,7 @@
- {
-       struct b44 *bp = netdev_priv(dev);
--      if (!netif_running(dev))
-+      if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
-               return -EAGAIN;
-       cmd->supported = (SUPPORTED_Autoneg);
-       cmd->supported |= (SUPPORTED_100baseT_Half |
-@@ -1628,14 +1504,14 @@
-       cmd->advertising = 0;
-       if (bp->flags & B44_FLAG_ADV_10HALF)
--              cmd->advertising |= ADVERTISED_10baseT_Half;
-+              cmd->advertising |= ADVERTISE_10HALF;
-       if (bp->flags & B44_FLAG_ADV_10FULL)
--              cmd->advertising |= ADVERTISED_10baseT_Full;
-+              cmd->advertising |= ADVERTISE_10FULL;
-       if (bp->flags & B44_FLAG_ADV_100HALF)
--              cmd->advertising |= ADVERTISED_100baseT_Half;
-+              cmd->advertising |= ADVERTISE_100HALF;
-       if (bp->flags & B44_FLAG_ADV_100FULL)
--              cmd->advertising |= ADVERTISED_100baseT_Full;
--      cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
-+              cmd->advertising |= ADVERTISE_100FULL;
-+      cmd->advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-       cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ?
-               SPEED_100 : SPEED_10;
-       cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
-@@ -1655,7 +1531,7 @@
- {
-       struct b44 *bp = netdev_priv(dev);
--      if (!netif_running(dev))
-+      if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
-               return -EAGAIN;
-       /* We do not support gigabit. */
-@@ -1785,37 +1661,6 @@
-       return 0;
- }
--static void b44_get_strings(struct net_device *dev, u32 stringset, u8 *data)
--{
--      switch(stringset) {
--      case ETH_SS_STATS:
--              memcpy(data, *b44_gstrings, sizeof(b44_gstrings));
--              break;
--      }
--}
--
--static int b44_get_stats_count(struct net_device *dev)
--{
--      return ARRAY_SIZE(b44_gstrings);
--}
--
--static void b44_get_ethtool_stats(struct net_device *dev,
--                                struct ethtool_stats *stats, u64 *data)
--{
--      struct b44 *bp = netdev_priv(dev);
--      u32 *val = &bp->hw_stats.tx_good_octets;
--      u32 i;
--
--      spin_lock_irq(&bp->lock);
--
--      b44_stats_update(bp);
--
--      for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++)
--              *data++ = *val++;
--
--      spin_unlock_irq(&bp->lock);
--}
--
- static struct ethtool_ops b44_ethtool_ops = {
-       .get_drvinfo            = b44_get_drvinfo,
-       .get_settings           = b44_get_settings,
-@@ -1828,25 +1673,18 @@
-       .set_pauseparam         = b44_set_pauseparam,
-       .get_msglevel           = b44_get_msglevel,
-       .set_msglevel           = b44_set_msglevel,
--      .get_strings            = b44_get_strings,
--      .get_stats_count        = b44_get_stats_count,
--      .get_ethtool_stats      = b44_get_ethtool_stats,
--      .get_perm_addr          = ethtool_op_get_perm_addr,
- };
- static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
- {
-       struct mii_ioctl_data *data = if_mii(ifr);
-       struct b44 *bp = netdev_priv(dev);
--      int err = -EINVAL;
--
--      if (!netif_running(dev))
--              goto out;
-+      int err;
-       spin_lock_irq(&bp->lock);
-       err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
-       spin_unlock_irq(&bp->lock);
--out:
-+
-       return err;
- }
-@@ -1877,7 +1715,6 @@
-       bp->dev->dev_addr[3] = eeprom[80];
-       bp->dev->dev_addr[4] = eeprom[83];
-       bp->dev->dev_addr[5] = eeprom[82];
--      memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
-       bp->phy_addr = eeprom[90] & 0x1f;
-@@ -1942,9 +1779,9 @@
-       
-       err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
-       if (err) {
--              printk(KERN_ERR PFX "No usable DMA configuration, "
--                     "aborting.\n");
--              goto err_out_free_res;
-+        printk(KERN_ERR PFX "No usable DMA configuration, "
-+               "aborting.\n");
-+        goto err_out_free_res;
-       }
-       b44reg_base = pci_resource_start(pdev, 0);
-@@ -1966,8 +1803,10 @@
-       bp = netdev_priv(dev);
-       bp->pdev = pdev;
-       bp->dev = dev;
--
--      bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
-+      if (b44_debug >= 0)
-+              bp->msg_enable = (1 << b44_debug) - 1;
-+      else
-+              bp->msg_enable = B44_DEF_MSG_ENABLE;
-       spin_lock_init(&bp->lock);
-@@ -2057,14 +1896,17 @@
- static void __devexit b44_remove_one(struct pci_dev *pdev)
- {
-       struct net_device *dev = pci_get_drvdata(pdev);
--      struct b44 *bp = netdev_priv(dev);
--      unregister_netdev(dev);
--      iounmap(bp->regs);
--      free_netdev(dev);
--      pci_release_regions(pdev);
--      pci_disable_device(pdev);
--      pci_set_drvdata(pdev, NULL);
-+      if (dev) {
-+              struct b44 *bp = netdev_priv(dev);
-+
-+              unregister_netdev(dev);
-+              iounmap(bp->regs);
-+              free_netdev(dev);
-+              pci_release_regions(pdev);
-+              pci_disable_device(pdev);
-+              pci_set_drvdata(pdev, NULL);
-+      }
- }
- static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
-@@ -2085,9 +1927,6 @@
-       b44_free_rings(bp);
-       spin_unlock_irq(&bp->lock);
--
--      free_irq(dev->irq, dev);
--      pci_disable_device(pdev);
-       return 0;
- }
-@@ -2097,15 +1936,10 @@
-       struct b44 *bp = netdev_priv(dev);
-       pci_restore_state(pdev);
--      pci_enable_device(pdev);
--      pci_set_master(pdev);
-       if (!netif_running(dev))
-               return 0;
--      if (request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev))
--              printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
--
-       spin_lock_irq(&bp->lock);
-       b44_init_rings(bp);
-@@ -2117,7 +1951,6 @@
-       add_timer(&bp->timer);
-       b44_enable_ints(bp);
--      netif_wake_queue(dev);
-       return 0;
- }
-@@ -2132,12 +1965,6 @@
- static int __init b44_init(void)
- {
--      unsigned int dma_desc_align_size = dma_get_cache_alignment();
--
--      /* Setup paramaters for syncing RX/TX DMA descriptors */
--      dma_desc_align_mask = ~(dma_desc_align_size - 1);
--      dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
--
-       return pci_module_init(&b44_driver);
- }
-diff -ur linux-2.6.15-rc5/drivers/net/b44.h linux-2.6.15-rc5-openwrt/drivers/net/b44.h
---- linux-2.6.15-rc5/drivers/net/b44.h 2005-12-04 06:10:42.000000000 +0100
-+++ linux-2.6.15-rc5-openwrt/drivers/net/b44.h 2005-08-15 02:20:18.000000000 +0200
-@@ -346,63 +346,29 @@
- #define B44_MCAST_TABLE_SIZE  32
--#define       B44_STAT_REG_DECLARE            \
--      _B44(tx_good_octets)            \
--      _B44(tx_good_pkts)              \
--      _B44(tx_octets)                 \
--      _B44(tx_pkts)                   \
--      _B44(tx_broadcast_pkts)         \
--      _B44(tx_multicast_pkts)         \
--      _B44(tx_len_64)                 \
--      _B44(tx_len_65_to_127)          \
--      _B44(tx_len_128_to_255)         \
--      _B44(tx_len_256_to_511)         \
--      _B44(tx_len_512_to_1023)        \
--      _B44(tx_len_1024_to_max)        \
--      _B44(tx_jabber_pkts)            \
--      _B44(tx_oversize_pkts)          \
--      _B44(tx_fragment_pkts)          \
--      _B44(tx_underruns)              \
--      _B44(tx_total_cols)             \
--      _B44(tx_single_cols)            \
--      _B44(tx_multiple_cols)          \
--      _B44(tx_excessive_cols)         \
--      _B44(tx_late_cols)              \
--      _B44(tx_defered)                \
--      _B44(tx_carrier_lost)           \
--      _B44(tx_pause_pkts)             \
--      _B44(rx_good_octets)            \
--      _B44(rx_good_pkts)              \
--      _B44(rx_octets)                 \
--      _B44(rx_pkts)                   \
--      _B44(rx_broadcast_pkts)         \
--      _B44(rx_multicast_pkts)         \
--      _B44(rx_len_64)                 \
--      _B44(rx_len_65_to_127)          \
--      _B44(rx_len_128_to_255)         \
--      _B44(rx_len_256_to_511)         \
--      _B44(rx_len_512_to_1023)        \
--      _B44(rx_len_1024_to_max)        \
--      _B44(rx_jabber_pkts)            \
--      _B44(rx_oversize_pkts)          \
--      _B44(rx_fragment_pkts)          \
--      _B44(rx_missed_pkts)            \
--      _B44(rx_crc_align_errs)         \
--      _B44(rx_undersize)              \
--      _B44(rx_crc_errs)               \
--      _B44(rx_align_errs)             \
--      _B44(rx_symbol_errs)            \
--      _B44(rx_pause_pkts)             \
--      _B44(rx_nonpause_pkts)
--
- /* SW copy of device statistics, kept up to date by periodic timer
-- * which probes HW values. Check b44_stats_update if you mess with
-- * the layout
-+ * which probes HW values.  Must have same relative layout as HW
-+ * register above, because b44_stats_update depends upon this.
-  */
- struct b44_hw_stats {
--#define _B44(x)       u32 x;
--B44_STAT_REG_DECLARE
--#undef _B44
-+      u32 tx_good_octets, tx_good_pkts, tx_octets;
-+      u32 tx_pkts, tx_broadcast_pkts, tx_multicast_pkts;
-+      u32 tx_len_64, tx_len_65_to_127, tx_len_128_to_255;
-+      u32 tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max;
-+      u32 tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts;
-+      u32 tx_underruns, tx_total_cols, tx_single_cols;
-+      u32 tx_multiple_cols, tx_excessive_cols, tx_late_cols;
-+      u32 tx_defered, tx_carrier_lost, tx_pause_pkts;
-+      u32 __pad1[8];
-+
-+      u32 rx_good_octets, rx_good_pkts, rx_octets;
-+      u32 rx_pkts, rx_broadcast_pkts, rx_multicast_pkts;
-+      u32 rx_len_64, rx_len_65_to_127, rx_len_128_to_255;
-+      u32 rx_len_256_to_511, rx_len_512_to_1023, rx_len_1024_to_max;
-+      u32 rx_jabber_pkts, rx_oversize_pkts, rx_fragment_pkts;
-+      u32 rx_missed_pkts, rx_crc_align_errs, rx_undersize;
-+      u32 rx_crc_errs, rx_align_errs, rx_symbol_errs;
-+      u32 rx_pause_pkts, rx_nonpause_pkts;
- };
- struct b44 {
-@@ -420,6 +386,7 @@
-       u32                     dma_offset;
-       u32                     flags;
-+#define B44_FLAG_INIT_COMPLETE        0x00000001
- #define B44_FLAG_BUGGY_TXPTR  0x00000002
- #define B44_FLAG_REORDER_BUG  0x00000004
- #define B44_FLAG_PAUSE_AUTO   0x00008000
-@@ -433,8 +400,6 @@
- #define B44_FLAG_ADV_100HALF  0x04000000
- #define B44_FLAG_ADV_100FULL  0x08000000
- #define B44_FLAG_INTERNAL_PHY 0x10000000
--#define B44_FLAG_RX_RING_HACK 0x20000000
--#define B44_FLAG_TX_RING_HACK 0x40000000
-       u32                     rx_offset;
diff --git a/openwrt/target/linux/generic-2.6/patches/003-net-b44-2.patch b/openwrt/target/linux/generic-2.6/patches/003-net-b44-2.patch
deleted file mode 100644 (file)
index 8bfe429..0000000
+++ /dev/null
@@ -1,1089 +0,0 @@
-diff -ur linux-2.6.14.3/drivers/net/b44.c linux-2.6.14.3-openwrt/drivers/net/b44.c
---- linux-2.6.14.3/drivers/net/b44.c   2005-11-24 23:10:21.000000000 +0100
-+++ linux-2.6.14.3-openwrt/drivers/net/b44.c   2005-12-08 13:24:35.000000000 +0100
-@@ -1,7 +1,8 @@
--/* b44.c: Broadcom 4400 device driver.
-+/* b44.c: Broadcom 4400/47xx device driver.
-  *
-  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
-- * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
-+ * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
-+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
-  *
-  * Distribute under GPL.
-  */
-@@ -78,7 +79,7 @@
-       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
- MODULE_AUTHOR("Florian Schirmer, Pekka Pietikainen, David S. Miller");
--MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
-+MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
- MODULE_LICENSE("GPL");
- MODULE_VERSION(DRV_MODULE_VERSION);
-@@ -93,6 +94,8 @@
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-+      { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
-+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
-       { }     /* terminate list with empty entry */
- };
-@@ -106,24 +109,13 @@
- static void b44_poll_controller(struct net_device *dev);
- #endif
--static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
--{
--      return readl(bp->regs + reg);
--}
--
--static inline void bw32(const struct b44 *bp, 
--                      unsigned long reg, unsigned long val)
--{
--      writel(val, bp->regs + reg);
--}
--
- static int b44_wait_bit(struct b44 *bp, unsigned long reg,
-                       u32 bit, unsigned long timeout, const int clear)
- {
-       unsigned long i;
-       for (i = 0; i < timeout; i++) {
--              u32 val = br32(bp, reg);
-+              u32 val = br32(reg);
-               if (clear && !(val & bit))
-                       break;
-@@ -154,7 +146,7 @@
- static u32 ssb_get_core_rev(struct b44 *bp)
- {
--      return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
-+      return (br32(B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
- }
- static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
-@@ -165,13 +157,13 @@
-       pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, BCM4400_PCI_CORE_ADDR);
-       pci_rev = ssb_get_core_rev(bp);
--      val = br32(bp, B44_SBINTVEC);
-+      val = br32(B44_SBINTVEC);
-       val |= cores;
--      bw32(bp, B44_SBINTVEC, val);
-+      bw32(B44_SBINTVEC, val);
--      val = br32(bp, SSB_PCI_TRANS_2);
-+      val = br32(SSB_PCI_TRANS_2);
-       val |= SSB_PCI_PREF | SSB_PCI_BURST;
--      bw32(bp, SSB_PCI_TRANS_2, val);
-+      bw32(SSB_PCI_TRANS_2, val);
-       pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, bar_orig);
-@@ -180,18 +172,18 @@
- static void ssb_core_disable(struct b44 *bp)
- {
--      if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
-+      if (br32(B44_SBTMSLOW) & SBTMSLOW_RESET)
-               return;
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
-       b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
-       b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
-                           SBTMSLOW_REJECT | SBTMSLOW_RESET));
--      br32(bp, B44_SBTMSLOW);
-+      br32(B44_SBTMSLOW);
-       udelay(1);
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
--      br32(bp, B44_SBTMSLOW);
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
-+      br32(B44_SBTMSLOW);
-       udelay(1);
- }
-@@ -200,58 +192,65 @@
-       u32 val;
-       ssb_core_disable(bp);
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
--      br32(bp, B44_SBTMSLOW);
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-+      br32(B44_SBTMSLOW);
-       udelay(1);
-       /* Clear SERR if set, this is a hw bug workaround.  */
--      if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
--              bw32(bp, B44_SBTMSHIGH, 0);
-+      if (br32(B44_SBTMSHIGH) & SBTMSHIGH_SERR)
-+              bw32(B44_SBTMSHIGH, 0);
--      val = br32(bp, B44_SBIMSTATE);
-+      val = br32(B44_SBIMSTATE);
-       if (val & (SBIMSTATE_IBE | SBIMSTATE_TO))
--              bw32(bp, B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
-+              bw32(B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
--      br32(bp, B44_SBTMSLOW);
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-+      br32(B44_SBTMSLOW);
-       udelay(1);
--      bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
--      br32(bp, B44_SBTMSLOW);
-+      bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK));
-+      br32(B44_SBTMSLOW);
-       udelay(1);
- }
-+static int b44_4713_instance;
-+
- static int ssb_core_unit(struct b44 *bp)
- {
--#if 0
--      u32 val = br32(bp, B44_SBADMATCH0);
--      u32 base;
--
--      type = val & SBADMATCH0_TYPE_MASK;
--      switch (type) {
--      case 0:
--              base = val & SBADMATCH0_BS0_MASK;
--              break;
--
--      case 1:
--              base = val & SBADMATCH0_BS1_MASK;
--              break;
--
--      case 2:
--      default:
--              base = val & SBADMATCH0_BS2_MASK;
--              break;
--      };
--#endif
--      return 0;
-+      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
-+              return b44_4713_instance++;
-+      else
-+              return 0;
- }
- static int ssb_is_core_up(struct b44 *bp)
- {
--      return ((br32(bp, B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
-+      return ((br32(B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
-               == SBTMSLOW_CLOCK);
- }
-+static void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
-+{
-+      u32 val;
-+
-+      bw32(B44_CAM_CTRL, (CAM_CTRL_READ |
-+                          (index << CAM_CTRL_INDEX_SHIFT)));
-+
-+      b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);  
-+
-+      val = br32(B44_CAM_DATA_LO);
-+
-+      data[2] = (val >> 24) & 0xFF;
-+      data[3] = (val >> 16) & 0xFF;
-+      data[4] = (val >> 8) & 0xFF;
-+      data[5] = (val >> 0) & 0xFF;
-+
-+      val = br32(B44_CAM_DATA_HI);
-+      
-+      data[0] = (val >> 8) & 0xFF;
-+      data[1] = (val >> 0) & 0xFF;
-+}
-+
- static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
- {
-       u32 val;
-@@ -260,19 +259,19 @@
-       val |= ((u32) data[3]) << 16;
-       val |= ((u32) data[4]) <<  8;
-       val |= ((u32) data[5]) <<  0;
--      bw32(bp, B44_CAM_DATA_LO, val);
-+      bw32(B44_CAM_DATA_LO, val);
-       val = (CAM_DATA_HI_VALID | 
-              (((u32) data[0]) << 8) |
-              (((u32) data[1]) << 0));
--      bw32(bp, B44_CAM_DATA_HI, val);
--      bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
-+      bw32(B44_CAM_DATA_HI, val);
-+      bw32(B44_CAM_CTRL, (CAM_CTRL_WRITE |
-                           (index << CAM_CTRL_INDEX_SHIFT)));
-       b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);  
- }
- static inline void __b44_disable_ints(struct b44 *bp)
- {
--      bw32(bp, B44_IMASK, 0);
-+      bw32(B44_IMASK, 0);
- }
- static void b44_disable_ints(struct b44 *bp)
-@@ -280,42 +279,59 @@
-       __b44_disable_ints(bp);
-       /* Flush posted writes. */
--      br32(bp, B44_IMASK);
-+      br32(B44_IMASK);
- }
- static void b44_enable_ints(struct b44 *bp)
- {
--      bw32(bp, B44_IMASK, bp->imask);
-+      bw32(B44_IMASK, bp->imask);
- }
--static int b44_readphy(struct b44 *bp, int reg, u32 *val)
-+static int __b44_readphy(struct b44 *bp, int phy_addr, int reg, u32 *val)
- {
-       int err;
--      bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
--      bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
-+      bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-+      bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
-                            (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
--                           (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
-+                           (phy_addr << MDIO_DATA_PMD_SHIFT) |
-                            (reg << MDIO_DATA_RA_SHIFT) |
-                            (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
-       err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
--      *val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
-+      *val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA;
-       return err;
- }
--static int b44_writephy(struct b44 *bp, int reg, u32 val)
-+static int b44_readphy(struct b44 *bp, int reg, u32 *val)
-+{
-+      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-+              return 0;
-+
-+      return __b44_readphy(bp, bp->phy_addr, reg, val);
-+}
-+
-+static int __b44_writephy(struct b44 *bp, int phy_addr, int reg, u32 val)
- {
--      bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
--      bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
-+      bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-+      bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
-                            (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
--                           (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
-+                           (phy_addr << MDIO_DATA_PMD_SHIFT) |
-                            (reg << MDIO_DATA_RA_SHIFT) |
-                            (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
-                            (val & MDIO_DATA_DATA)));
-       return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
- }
-+static int b44_writephy(struct b44 *bp, int reg, u32 val)
-+{
-+      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-+              return 0;
-+              
-+      return __b44_writephy(bp, bp->phy_addr, reg, val);
-+}
-+
-+
- /* miilib interface */
- /* FIXME FIXME: phy_id is ignored, bp->phy_addr use is unconditional
-  * due to code existing before miilib use was added to this driver.
-@@ -344,6 +360,9 @@
-       u32 val;
-       int err;
-+      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-+              return 0;
-+
-       err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
-       if (err)
-               return err;
-@@ -367,20 +386,20 @@
-       bp->flags &= ~(B44_FLAG_TX_PAUSE | B44_FLAG_RX_PAUSE);
-       bp->flags |= pause_flags;
--      val = br32(bp, B44_RXCONFIG);
-+      val = br32(B44_RXCONFIG);
-       if (pause_flags & B44_FLAG_RX_PAUSE)
-               val |= RXCONFIG_FLOW;
-       else
-               val &= ~RXCONFIG_FLOW;
--      bw32(bp, B44_RXCONFIG, val);
-+      bw32(B44_RXCONFIG, val);
--      val = br32(bp, B44_MAC_FLOW);
-+      val = br32(B44_MAC_FLOW);
-       if (pause_flags & B44_FLAG_TX_PAUSE)
-               val |= (MAC_FLOW_PAUSE_ENAB |
-                       (0xc0 & MAC_FLOW_RX_HI_WATER));
-       else
-               val &= ~MAC_FLOW_PAUSE_ENAB;
--      bw32(bp, B44_MAC_FLOW, val);
-+      bw32(B44_MAC_FLOW, val);
- }
- static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
-@@ -414,6 +433,9 @@
-       u32 val;
-       int err;
-+      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
-+              return 0;
-+
-       if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
-               goto out;
-       if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
-@@ -476,11 +498,11 @@
-       val = &bp->hw_stats.tx_good_octets;
-       for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
--              *val++ += br32(bp, reg);
-+              *val++ += br32(reg);
-       }
-       val = &bp->hw_stats.rx_good_octets;
-       for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
--              *val++ += br32(bp, reg);
-+              *val++ += br32(reg);
-       }
- }
-@@ -506,6 +528,19 @@
- {
-       u32 bmsr, aux;
-+      if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
-+              bp->flags |= B44_FLAG_100_BASE_T;
-+              bp->flags |= B44_FLAG_FULL_DUPLEX;
-+              if (!netif_carrier_ok(bp->dev)) {
-+                      u32 val = br32(B44_TX_CTRL);
-+                      val |= TX_CTRL_DUPLEX;
-+                      bw32(B44_TX_CTRL, val);
-+                      netif_carrier_on(bp->dev);
-+                      b44_link_report(bp);
-+              }
-+              return;
-+      }
-+
-       if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
-           !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
-           (bmsr != 0xffff)) {
-@@ -520,14 +555,14 @@
-               if (!netif_carrier_ok(bp->dev) &&
-                   (bmsr & BMSR_LSTATUS)) {
--                      u32 val = br32(bp, B44_TX_CTRL);
-+                      u32 val = br32(B44_TX_CTRL);
-                       u32 local_adv, remote_adv;
-                       if (bp->flags & B44_FLAG_FULL_DUPLEX)
-                               val |= TX_CTRL_DUPLEX;
-                       else
-                               val &= ~TX_CTRL_DUPLEX;
--                      bw32(bp, B44_TX_CTRL, val);
-+                      bw32(B44_TX_CTRL, val);
-                       if (!(bp->flags & B44_FLAG_FORCE_LINK) &&
-                           !b44_readphy(bp, MII_ADVERTISE, &local_adv) &&
-@@ -572,7 +607,7 @@
- {
-       u32 cur, cons;
--      cur  = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK;
-+      cur  = br32(B44_DMATX_STAT) & DMATX_STAT_CDMASK;
-       cur /= sizeof(struct dma_desc);
-       /* XXX needs updating when NETIF_F_SG is supported */
-@@ -596,7 +631,7 @@
-           TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH)
-               netif_wake_queue(bp->dev);
--      bw32(bp, B44_GPTIMER, 0);
-+      bw32(B44_GPTIMER, 0);
- }
- /* Works like this.  This chip writes a 'struct rx_header" 30 bytes
-@@ -713,7 +748,7 @@
-       u32 cons, prod;
-       received = 0;
--      prod  = br32(bp, B44_DMARX_STAT) & DMARX_STAT_CDMASK;
-+      prod  = br32(B44_DMARX_STAT) & DMARX_STAT_CDMASK;
-       prod /= sizeof(struct dma_desc);
-       cons = bp->rx_cons;
-@@ -792,7 +827,7 @@
-       }
-       bp->rx_cons = cons;
--      bw32(bp, B44_DMARX_PTR, cons * sizeof(struct dma_desc));
-+      bw32(B44_DMARX_PTR, cons * sizeof(struct dma_desc));
-       return received;
- }
-@@ -856,8 +891,8 @@
-       spin_lock_irqsave(&bp->lock, flags);
--      istat = br32(bp, B44_ISTAT);
--      imask = br32(bp, B44_IMASK);
-+      istat = br32(B44_ISTAT);
-+      imask = br32(B44_IMASK);
-       /* ??? What the fuck is the purpose of the interrupt mask
-        * ??? register if we have to mask it out by hand anyways?
-@@ -877,8 +912,8 @@
-                              dev->name);
-               }
--              bw32(bp, B44_ISTAT, istat);
--              br32(bp, B44_ISTAT);
-+              bw32(B44_ISTAT, istat);
-+              br32(B44_ISTAT);
-       }
-       spin_unlock_irqrestore(&bp->lock, flags);
-       return IRQ_RETVAL(handled);
-@@ -965,11 +1000,11 @@
-       wmb();
--      bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-+      bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-       if (bp->flags & B44_FLAG_BUGGY_TXPTR)
--              bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-+              bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
-       if (bp->flags & B44_FLAG_REORDER_BUG)
--              br32(bp, B44_DMATX_PTR);
-+              br32(B44_DMATX_PTR);
-       if (TX_BUFFS_AVAIL(bp) < 1)
-               netif_stop_queue(dev);
-@@ -1137,32 +1172,35 @@
- {
-       unsigned long reg;
--      bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-+      bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-       for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL)
--              br32(bp, reg);
-+              br32(reg);
-       for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL)
--              br32(bp, reg);
-+              br32(reg);
- }
- /* bp->lock is held. */
- static void b44_chip_reset(struct b44 *bp)
- {
-+      unsigned int sb_clock;
-+
-       if (ssb_is_core_up(bp)) {
--              bw32(bp, B44_RCV_LAZY, 0);
--              bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
-+              bw32(B44_RCV_LAZY, 0);
-+              bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE);
-               b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
--              bw32(bp, B44_DMATX_CTRL, 0);
-+              bw32(B44_DMATX_CTRL, 0);
-               bp->tx_prod = bp->tx_cons = 0;
--              if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
-+              if (br32(B44_DMARX_STAT) & DMARX_STAT_EMASK) {
-                       b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
-                                    100, 0);
-               }
--              bw32(bp, B44_DMARX_CTRL, 0);
-+              bw32(B44_DMARX_CTRL, 0);
-               bp->rx_prod = bp->rx_cons = 0;
-       } else {
--              ssb_pci_setup(bp, (bp->core_unit == 0 ?
--                                 SBINTVEC_ENET0 :
--                                 SBINTVEC_ENET1));
-+              if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
-+                      ssb_pci_setup(bp, (bp->core_unit == 0 ?
-+                                         SBINTVEC_ENET0 :
-+                                         SBINTVEC_ENET1));
-       }
-       ssb_core_reset(bp);
-@@ -1170,20 +1208,26 @@
-       b44_clear_stats(bp);
-       /* Make PHY accessible. */
--      bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
--                           (0x0d & MDIO_CTRL_MAXF_MASK)));
--      br32(bp, B44_MDIO_CTRL);
--
--      if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
--              bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
--              br32(bp, B44_ENET_CTRL);
-+      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
-+              sb_clock = 100000000; /* 100 MHz */
-+      else
-+              sb_clock = 62500000; /* 62.5 MHz */
-+
-+      bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
-+                           (((sb_clock + (B44_MDC_RATIO / 2)) / B44_MDC_RATIO)
-+                           & MDIO_CTRL_MAXF_MASK)));
-+      br32(B44_MDIO_CTRL);
-+
-+      if (!(br32(B44_DEVCTRL) & DEVCTRL_IPP)) {
-+              bw32(B44_ENET_CTRL, ENET_CTRL_EPSEL);
-+              br32(B44_ENET_CTRL);
-               bp->flags &= ~B44_FLAG_INTERNAL_PHY;
-       } else {
--              u32 val = br32(bp, B44_DEVCTRL);
-+              u32 val = br32(B44_DEVCTRL);
-               if (val & DEVCTRL_EPR) {
--                      bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
--                      br32(bp, B44_DEVCTRL);
-+                      bw32(B44_DEVCTRL, (val & ~DEVCTRL_EPR));
-+                      br32(B44_DEVCTRL);
-                       udelay(100);
-               }
-               bp->flags |= B44_FLAG_INTERNAL_PHY;
-@@ -1200,13 +1244,13 @@
- /* bp->lock is held. */
- static void __b44_set_mac_addr(struct b44 *bp)
- {
--      bw32(bp, B44_CAM_CTRL, 0);
-+      bw32(B44_CAM_CTRL, 0);
-       if (!(bp->dev->flags & IFF_PROMISC)) {
-               u32 val;
-               __b44_cam_write(bp, bp->dev->dev_addr, 0);
--              val = br32(bp, B44_CAM_CTRL);
--              bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-+              val = br32(B44_CAM_CTRL);
-+              bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-       }
- }
-@@ -1240,30 +1284,30 @@
-       b44_setup_phy(bp);
-       /* Enable CRC32, set proper LED modes and power on PHY */
--      bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
--      bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
-+      bw32(B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
-+      bw32(B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
-       /* This sets the MAC address too.  */
-       __b44_set_rx_mode(bp->dev);
-       /* MTU + eth header + possible VLAN tag + struct rx_header */
--      bw32(bp, B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
--      bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-+      bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-+      bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
--      bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
--      bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
--      bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
--      bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-+      bw32(B44_TX_WMARK, 56); /* XXX magic */
-+      bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
-+      bw32(B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
-+      bw32(B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-                             (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
--      bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
-+      bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
--      bw32(bp, B44_DMARX_PTR, bp->rx_pending);
-+      bw32(B44_DMARX_PTR, bp->rx_pending);
-       bp->rx_prod = bp->rx_pending;   
--      bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
-+      bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
--      val = br32(bp, B44_ENET_CTRL);
--      bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
-+      val = br32(B44_ENET_CTRL);
-+      bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
- }
- static int b44_open(struct net_device *dev)
-@@ -1419,11 +1463,11 @@
-       int i=0;
-       unsigned char zero[6] = {0,0,0,0,0,0};
--      val = br32(bp, B44_RXCONFIG);
-+      val = br32(B44_RXCONFIG);
-       val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
-       if (dev->flags & IFF_PROMISC) {
-               val |= RXCONFIG_PROMISC;
--              bw32(bp, B44_RXCONFIG, val);
-+              bw32(B44_RXCONFIG, val);
-       } else {
-               __b44_set_mac_addr(bp);
-@@ -1435,9 +1479,9 @@
-               for(;i<64;i++) {
-                       __b44_cam_write(bp, zero, i);                   
-               }
--              bw32(bp, B44_RXCONFIG, val);
--              val = br32(bp, B44_CAM_CTRL);
--              bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-+              bw32(B44_RXCONFIG, val);
-+              val = br32(B44_CAM_CTRL);
-+              bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
-       }
- }
-@@ -1678,17 +1722,288 @@
-       .set_msglevel           = b44_set_msglevel,
- };
-+static int b44_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
-+{
-+      struct b44 *bp = dev->priv;
-+      struct pci_dev *pci_dev = bp->pdev;
-+      u32 ethcmd;
-+
-+      if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
-+              return -EFAULT;
-+
-+      switch (ethcmd) {
-+      case ETHTOOL_GDRVINFO: {
-+              struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-+              strcpy (info.driver, DRV_MODULE_NAME);
-+              strcpy (info.version, DRV_MODULE_VERSION);
-+              memset(&info.fw_version, 0, sizeof(info.fw_version));
-+              strcpy (info.bus_info, pci_name(pci_dev));
-+              info.eedump_len = 0;
-+              info.regdump_len = 0;
-+              if (copy_to_user (useraddr, &info, sizeof (info)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+
-+      case ETHTOOL_GSET: {
-+              struct ethtool_cmd cmd = { ETHTOOL_GSET };
-+
-+              if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
-+                      return -EAGAIN;
-+              cmd.supported = (SUPPORTED_Autoneg);
-+              cmd.supported |= (SUPPORTED_100baseT_Half |
-+                                SUPPORTED_100baseT_Full |
-+                                SUPPORTED_10baseT_Half |
-+                                SUPPORTED_10baseT_Full |
-+                                SUPPORTED_MII);
-+
-+              cmd.advertising = 0;
-+              if (bp->flags & B44_FLAG_ADV_10HALF)
-+                      cmd.advertising |= ADVERTISE_10HALF;
-+              if (bp->flags & B44_FLAG_ADV_10FULL)
-+                      cmd.advertising |= ADVERTISE_10FULL;
-+              if (bp->flags & B44_FLAG_ADV_100HALF)
-+                      cmd.advertising |= ADVERTISE_100HALF;
-+              if (bp->flags & B44_FLAG_ADV_100FULL)
-+                      cmd.advertising |= ADVERTISE_100FULL;
-+              cmd.advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
-+              cmd.speed = (bp->flags & B44_FLAG_100_BASE_T) ?
-+                      SPEED_100 : SPEED_10;
-+              cmd.duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
-+                      DUPLEX_FULL : DUPLEX_HALF;
-+              cmd.port = 0;
-+              cmd.phy_address = bp->phy_addr;
-+              cmd.transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
-+                      XCVR_INTERNAL : XCVR_EXTERNAL;
-+              cmd.autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
-+                      AUTONEG_DISABLE : AUTONEG_ENABLE;
-+              cmd.maxtxpkt = 0;
-+              cmd.maxrxpkt = 0;
-+              if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+      case ETHTOOL_SSET: {
-+              struct ethtool_cmd cmd;
-+
-+              if (!(bp->flags & B44_FLAG_INIT_COMPLETE))
-+                      return -EAGAIN;
-+
-+              if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
-+                      return -EFAULT;
-+
-+              /* We do not support gigabit. */
-+              if (cmd.autoneg == AUTONEG_ENABLE) {
-+                      if (cmd.advertising &
-+                          (ADVERTISED_1000baseT_Half |
-+                           ADVERTISED_1000baseT_Full))
-+                              return -EINVAL;
-+              } else if ((cmd.speed != SPEED_100 &&
-+                          cmd.speed != SPEED_10) ||
-+                         (cmd.duplex != DUPLEX_HALF &&
-+                          cmd.duplex != DUPLEX_FULL)) {
-+                              return -EINVAL;
-+              }
-+
-+              spin_lock_irq(&bp->lock);
-+
-+              if (cmd.autoneg == AUTONEG_ENABLE) {
-+                      bp->flags &= ~B44_FLAG_FORCE_LINK;
-+                      bp->flags &= ~(B44_FLAG_ADV_10HALF |
-+                                     B44_FLAG_ADV_10FULL |
-+                                     B44_FLAG_ADV_100HALF |
-+                                     B44_FLAG_ADV_100FULL);
-+                      if (cmd.advertising & ADVERTISE_10HALF)
-+                              bp->flags |= B44_FLAG_ADV_10HALF;
-+                      if (cmd.advertising & ADVERTISE_10FULL)
-+                              bp->flags |= B44_FLAG_ADV_10FULL;
-+                      if (cmd.advertising & ADVERTISE_100HALF)
-+                              bp->flags |= B44_FLAG_ADV_100HALF;
-+                      if (cmd.advertising & ADVERTISE_100FULL)
-+                              bp->flags |= B44_FLAG_ADV_100FULL;
-+              } else {
-+                      bp->flags |= B44_FLAG_FORCE_LINK;
-+                      if (cmd.speed == SPEED_100)
-+                              bp->flags |= B44_FLAG_100_BASE_T;
-+                      if (cmd.duplex == DUPLEX_FULL)
-+                              bp->flags |= B44_FLAG_FULL_DUPLEX;
-+              }
-+
-+              b44_setup_phy(bp);
-+
-+              spin_unlock_irq(&bp->lock);
-+
-+              return 0;
-+      }
-+
-+      case ETHTOOL_GMSGLVL: {
-+              struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-+              edata.data = bp->msg_enable;
-+              if (copy_to_user(useraddr, &edata, sizeof(edata)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+      case ETHTOOL_SMSGLVL: {
-+              struct ethtool_value edata;
-+              if (copy_from_user(&edata, useraddr, sizeof(edata)))
-+                      return -EFAULT;
-+              bp->msg_enable = edata.data;
-+              return 0;
-+      }
-+      case ETHTOOL_NWAY_RST: {
-+              u32 bmcr;
-+              int r;
-+
-+              spin_lock_irq(&bp->lock);
-+              b44_readphy(bp, MII_BMCR, &bmcr);
-+              b44_readphy(bp, MII_BMCR, &bmcr);
-+              r = -EINVAL;
-+              if (bmcr & BMCR_ANENABLE) {
-+                      b44_writephy(bp, MII_BMCR,
-+                                   bmcr | BMCR_ANRESTART);
-+                      r = 0;
-+              }
-+              spin_unlock_irq(&bp->lock);
-+
-+              return r;
-+      }
-+      case ETHTOOL_GLINK: {
-+              struct ethtool_value edata = { ETHTOOL_GLINK };
-+              edata.data = netif_carrier_ok(bp->dev) ? 1 : 0;
-+              if (copy_to_user(useraddr, &edata, sizeof(edata)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+      case ETHTOOL_GRINGPARAM: {
-+              struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
-+
-+              ering.rx_max_pending = B44_RX_RING_SIZE - 1;
-+              ering.rx_pending = bp->rx_pending;
-+
-+              /* XXX ethtool lacks a tx_max_pending, oops... */
-+
-+              if (copy_to_user(useraddr, &ering, sizeof(ering)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+      case ETHTOOL_SRINGPARAM: {
-+              struct ethtool_ringparam ering;
-+
-+              if (copy_from_user(&ering, useraddr, sizeof(ering)))
-+                      return -EFAULT;
-+
-+              if ((ering.rx_pending > B44_RX_RING_SIZE - 1) ||
-+                  (ering.rx_mini_pending != 0) ||
-+                  (ering.rx_jumbo_pending != 0) ||
-+                  (ering.tx_pending > B44_TX_RING_SIZE - 1))
-+                      return -EINVAL;
-+
-+              spin_lock_irq(&bp->lock);
-+
-+              bp->rx_pending = ering.rx_pending;
-+              bp->tx_pending = ering.tx_pending;
-+
-+              b44_halt(bp);
-+              b44_init_rings(bp);
-+              b44_init_hw(bp);
-+              netif_wake_queue(bp->dev);
-+              spin_unlock_irq(&bp->lock);
-+
-+              b44_enable_ints(bp);
-+              
-+              return 0;
-+      }
-+      case ETHTOOL_GPAUSEPARAM: {
-+              struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
-+
-+              epause.autoneg =
-+                      (bp->flags & B44_FLAG_PAUSE_AUTO) != 0;
-+              epause.rx_pause =
-+                      (bp->flags & B44_FLAG_RX_PAUSE) != 0;
-+              epause.tx_pause =
-+                      (bp->flags & B44_FLAG_TX_PAUSE) != 0;
-+              if (copy_to_user(useraddr, &epause, sizeof(epause)))
-+                      return -EFAULT;
-+              return 0;
-+      }
-+      case ETHTOOL_SPAUSEPARAM: {
-+              struct ethtool_pauseparam epause;
-+
-+              if (copy_from_user(&epause, useraddr, sizeof(epause)))
-+                      return -EFAULT;
-+
-+              spin_lock_irq(&bp->lock);
-+              if (epause.autoneg)
-+                      bp->flags |= B44_FLAG_PAUSE_AUTO;
-+              else
-+                      bp->flags &= ~B44_FLAG_PAUSE_AUTO;
-+              if (epause.rx_pause)
-+                      bp->flags |= B44_FLAG_RX_PAUSE;
-+              else
-+                      bp->flags &= ~B44_FLAG_RX_PAUSE;
-+              if (epause.tx_pause)
-+                      bp->flags |= B44_FLAG_TX_PAUSE;
-+              else
-+                      bp->flags &= ~B44_FLAG_TX_PAUSE;
-+              if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-+                      b44_halt(bp);
-+                      b44_init_rings(bp);
-+                      b44_init_hw(bp);
-+              } else {
-+                      __b44_set_flow_ctrl(bp, bp->flags);
-+              }
-+              spin_unlock_irq(&bp->lock);
-+
-+              b44_enable_ints(bp);
-+              
-+              return 0;
-+      }
-+      };
-+
-+      return -EOPNOTSUPP;
-+}
-+
- static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
- {
-       struct mii_ioctl_data *data = if_mii(ifr);
-       struct b44 *bp = netdev_priv(dev);
-       int err;
--      spin_lock_irq(&bp->lock);
--      err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
--      spin_unlock_irq(&bp->lock);
-+      switch (cmd) {
-+      case SIOCETHTOOL:
-+              return b44_ethtool_ioctl(dev, (void __user*) ifr->ifr_data);
-+
-+      case SIOCGMIIPHY:
-+              data->phy_id = bp->phy_addr;
-+
-+              /* fallthru */
-+      case SIOCGMIIREG: {
-+              u32 mii_regval;
--      return err;
-+              spin_lock_irq(&bp->lock);
-+              err = __b44_readphy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
-+              spin_unlock_irq(&bp->lock);
-+
-+              data->val_out = mii_regval;
-+
-+              return err;
-+      }
-+
-+      case SIOCSMIIREG:
-+              if (!capable(CAP_NET_ADMIN))
-+                      return -EPERM;
-+
-+              spin_lock_irq(&bp->lock);
-+              err = __b44_writephy(bp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
-+              spin_unlock_irq(&bp->lock);
-+
-+              return err;
-+
-+      default:
-+              /* do nothing */
-+              break;
-+      };
-+      return -EOPNOTSUPP;
- }
- /* Read 128-bytes of EEPROM. */
-@@ -1698,7 +2013,7 @@
-       u16 *ptr = (u16 *) data;
-       for (i = 0; i < 128; i += 2)
--              ptr[i / 2] = readw(bp->regs + 4096 + i);
-+              ptr[i / 2] = readw((void *)bp->regs + 4096 + i);
-       return 0;
- }
-@@ -1707,19 +2022,41 @@
- {
-       u8 eeprom[128];
-       int err;
-+      unsigned long flags;
--      err = b44_read_eeprom(bp, &eeprom[0]);
--      if (err)
--              goto out;
--
--      bp->dev->dev_addr[0] = eeprom[79];
--      bp->dev->dev_addr[1] = eeprom[78];
--      bp->dev->dev_addr[2] = eeprom[81];
--      bp->dev->dev_addr[3] = eeprom[80];
--      bp->dev->dev_addr[4] = eeprom[83];
--      bp->dev->dev_addr[5] = eeprom[82];
--
--      bp->phy_addr = eeprom[90] & 0x1f;
-+      if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
-+              /* 
-+               * BCM47xx boards don't have a EEPROM. The MAC is stored in
-+               * a NVRAM area somewhere in the flash memory. As we don't
-+               * know the location and/or the format of the NVRAM area
-+               * here, we simply rely on the bootloader to write the
-+               * MAC into the CAM.
-+               */
-+              spin_lock_irqsave(&bp->lock, flags);
-+              __b44_cam_read(bp, bp->dev->dev_addr, 0);
-+              spin_unlock_irqrestore(&bp->lock, flags);
-+
-+              /* 
-+               * BCM47xx boards don't have a PHY. Usually there is a switch
-+               * chip with multiple PHYs connected to the PHY port.
-+               */
-+              bp->phy_addr = B44_PHY_ADDR_NO_PHY;
-+              bp->dma_offset = 0;
-+      } else {
-+              err = b44_read_eeprom(bp, &eeprom[0]);
-+              if (err)
-+                      return err;
-+
-+              bp->dev->dev_addr[0] = eeprom[79];
-+              bp->dev->dev_addr[1] = eeprom[78];
-+              bp->dev->dev_addr[2] = eeprom[81];
-+              bp->dev->dev_addr[3] = eeprom[80];
-+              bp->dev->dev_addr[4] = eeprom[83];
-+              bp->dev->dev_addr[5] = eeprom[82];
-+
-+              bp->phy_addr = eeprom[90] & 0x1f;
-+              bp->dma_offset = SB_PCI_DMA;
-+      } 
-       /* With this, plus the rx_header prepended to the data by the
-        * hardware, we'll land the ethernet header on a 2-byte boundary.
-@@ -1729,13 +2066,12 @@
-       bp->imask = IMASK_DEF;
-       bp->core_unit = ssb_core_unit(bp);
--      bp->dma_offset = SB_PCI_DMA;
-       /* XXX - really required? 
-          bp->flags |= B44_FLAG_BUGGY_TXPTR;
-          */
--out:
--      return err;
-+
-+      return 0;
- }
- static int __devinit b44_init_one(struct pci_dev *pdev,
-@@ -1813,7 +2149,7 @@
-       spin_lock_init(&bp->lock);
--      bp->regs = ioremap(b44reg_base, b44reg_len);
-+      bp->regs = (unsigned long) ioremap(b44reg_base, b44reg_len);
-       if (bp->regs == 0UL) {
-               printk(KERN_ERR PFX "Cannot map device registers, "
-                      "aborting.\n");
-@@ -1874,15 +2210,21 @@
-       pci_save_state(bp->pdev);
--      printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
-+      printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
-+              (pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
-       for (i = 0; i < 6; i++)
-               printk("%2.2x%c", dev->dev_addr[i],
-                      i == 5 ? '\n' : ':');
-+      /* Initialize phy */
-+      spin_lock_irq(&bp->lock);
-+      b44_chip_reset(bp);
-+      spin_unlock_irq(&bp->lock);
-+      
-       return 0;
- err_out_iounmap:
--      iounmap(bp->regs);
-+      iounmap((void *) bp->regs);
- err_out_free_dev:
-       free_netdev(dev);
-@@ -1904,7 +2246,7 @@
-               struct b44 *bp = netdev_priv(dev);
-               unregister_netdev(dev);
--              iounmap(bp->regs);
-+              iounmap((void *) bp->regs);
-               free_netdev(dev);
-               pci_release_regions(pdev);
-               pci_disable_device(pdev);
-diff -ur linux-2.6.14.3/drivers/net/b44.h linux-2.6.14.3-openwrt/drivers/net/b44.h
---- linux-2.6.14.3/drivers/net/b44.h   2005-11-24 23:10:21.000000000 +0100
-+++ linux-2.6.14.3-openwrt/drivers/net/b44.h   2005-12-08 13:24:35.000000000 +0100
-@@ -292,6 +292,9 @@
- #define SSB_PCI_MASK1         0xfc000000
- #define SSB_PCI_MASK2         0xc0000000
-+#define br32(REG)     readl((void *)bp->regs + (REG))
-+#define bw32(REG,VAL) writel((VAL), (void *)bp->regs + (REG))
-+
- /* 4400 PHY registers */
- #define B44_MII_AUXCTRL               24      /* Auxiliary Control */
- #define  MII_AUXCTRL_DUPLEX   0x0001  /* Full Duplex */
-@@ -345,6 +348,8 @@
- };
- #define B44_MCAST_TABLE_SIZE  32
-+#define B44_PHY_ADDR_NO_PHY   30
-+#define B44_MDC_RATIO         5000000
- /* SW copy of device statistics, kept up to date by periodic timer
-  * which probes HW values.  Must have same relative layout as HW
-@@ -410,7 +415,7 @@
-       struct net_device_stats stats;
-       struct b44_hw_stats     hw_stats;
--      void __iomem            *regs;
-+      unsigned long           regs;
-       struct pci_dev          *pdev;
-       struct net_device       *dev;