lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 05 Jan 2011 17:48:36 +0100
From:	Angelo Dureghello <angelo70@...il.com>
To:	linux-kernel@...r.kernel.org, netdev@...r.kernel.org
Subject: [RFC PATCH] m68knommu: added dm9000 support

This patch allows to use the dm9000 network chip with a m68knommu 
big-endian cpu. From the HW point of view, the cpu data bus connected to 
the dm9000 chip should be hardware-byte-swapped, crossing the bytes 
wires (D0:7 to D24:31, etc.). In anyway, has been also added an option 
to swap the bytes in the driver, if some cpu has been wired straight 
D0:D31 to dm9000.

Signed-off-by: Angelo Dureghello <angelo70@...il.com>
---

--- drivers/net/Kconfig.orig  2011-01-05 17:11:37.992376124 +0100
+++ drivers/net/Kconfig 2011-01-04 22:33:14.132301872 +0100
@@ -960,7 +960,7 @@ config TI_DAVINCI_EMAC

  config DM9000
    tristate "DM9000 support"
-  depends on ARM || BLACKFIN || MIPS
+  depends on COLDFIRE || ARM || BLACKFIN || MIPS
    select CRC32
    select MII
    ---help---
@@ -986,6 +986,14 @@ config DM9000_FORCE_SIMPLE_PHY_POLL
      costly MII PHY reads. Note, this will not work if the chip is
      operating with an external PHY.

+config DM9000_32BIT_SW_SWAP
+  bool "Software byte swap for 32 bit data bus"
+  depends on DM9000 && COLDFIRE
+  ---help---
+    This configuration allows to swap data bytes from the dm9000
+    driver itself, when the big endian cpu is wired straight to
+    the dm9000 32 bit data bus.
+
  config ENC28J60
    tristate "ENC28J60 support"
    depends on EXPERIMENTAL && SPI && NET_ETHERNET
@@ -3347,4 +3355,3 @@ config VMXNET3
           module will be called vmxnet3.

  endif # NETDEVICES
-


--- drivers/net/dm9000.c.orig    2010-12-30 23:19:39.747836070 +0100
+++ drivers/net/dm9000.c    2011-01-05 16:30:48.636116500 +0100
@@ -158,9 +158,17 @@ dm9000_reset(board_info_t * db)
      dev_dbg(db->dev, "resetting device\n");

      /* RESET device */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(DM9000_NCR, db->io_addr);
+#else
      writeb(DM9000_NCR, db->io_addr);
+#endif
      udelay(200);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(NCR_RST, db->io_data);
+#else
      writeb(NCR_RST, db->io_data);
+#endif
      udelay(200);
  }

@@ -170,8 +178,13 @@ dm9000_reset(board_info_t * db)
  static u8
  ior(board_info_t * db, int reg)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg, db->io_addr);
+    return (u8)readl(db->io_data);
+#else
      writeb(reg, db->io_addr);
      return readb(db->io_data);
+#endif
  }

  /*
@@ -181,43 +194,72 @@ ior(board_info_t * db, int reg)
  static void
  iow(board_info_t * db, int reg, int value)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg, db->io_addr);
+    writel(value, db->io_data);
+#else
      writeb(reg, db->io_addr);
      writeb(value, db->io_data);
+#endif
  }

  /* routines for sending block to chip */

  static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writesbsw(reg, data, count);
+#else
      writesb(reg, data, count);
+#endif
  }

  static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writeswsw(reg, data, (count+1) >> 1);
+#else
      writesw(reg, data, (count+1) >> 1);
+#endif
  }

  static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writeslsw(reg, data, (count+3) >> 2);
+#else
      writesl(reg, data, (count+3) >> 2);
+#endif
  }

  /* input block from chip to memory */

  static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readsbsw(reg, data, count);
+#else
      readsb(reg, data, count);
+#endif
  }


  static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readswsw(reg, data, (count+1) >> 1);
+#else
      readsw(reg, data, (count+1) >> 1);
+#endif
  }

  static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
  {
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    readslsw(reg, data, (count+3) >> 2);
+#else
      readsl(reg, data, (count+3) >> 2);
+#endif
  }

  /* dump block from chip to null */
@@ -863,8 +905,13 @@ static void dm9000_timeout(struct net_de
      netif_wake_queue(dev);

      /* Restore previous register address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-    spin_unlock_irqrestore(&db->lock, flags);
+#endif
+
+    spin_unlock_irqrestore(&db->lock,flags);
  }

  static void dm9000_send_packet(struct net_device *dev,
@@ -908,7 +955,11 @@ dm9000_start_xmit(struct sk_buff *skb, s
      spin_lock_irqsave(&db->lock, flags);

      /* Move data to DM9000 TX RAM */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   writel(DM9000_MWCMD, db->io_addr);
+#else
      writeb(DM9000_MWCMD, db->io_addr);
+#endif

      (db->outblk)(db->io_data, skb->data, skb->len);
      dev->stats.tx_bytes += skb->len;
@@ -981,7 +1032,11 @@ dm9000_rx(struct net_device *dev)
          ior(db, DM9000_MRCMDX);    /* Dummy read */

          /* Get most updated data */
-        rxbyte = readb(db->io_data);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+      rxbyte = (u8)readl(db->io_data);
+#else
+      rxbyte = readb(db->io_data);
+#endif

          /* Status check: this byte must be 0 or 1 */
          if (rxbyte & DM9000_PKT_ERR) {
@@ -996,8 +1051,13 @@ dm9000_rx(struct net_device *dev)

          /* A packet ready now & Get status/length */
          GoodPacket = true;
-        writeb(DM9000_MRCMD, db->io_addr);

+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+        writel(DM9000_MRCMD, db->io_addr);
+#else
+      writeb(DM9000_MRCMD, db->io_addr);
+#endif
+
          (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

          RxLen = le16_to_cpu(rxhdr.RxLen);
@@ -1077,7 +1137,7 @@ static irqreturn_t dm9000_interrupt(int
      unsigned long flags;
      u8 reg_save;

-    dm9000_dbg(db, 3, "entering %s\n", __func__);
+    //dm9000_dbg(db, 3, "entering %s\n", __func__);

      /* A real interrupt coming */

@@ -1085,7 +1145,11 @@ static irqreturn_t dm9000_interrupt(int
      spin_lock_irqsave(&db->lock, flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Disable all interrupts */
      iow(db, DM9000_IMR, IMR_PAR);
@@ -1100,7 +1164,7 @@ static irqreturn_t dm9000_interrupt(int
      /* Received the coming packet */
      if (int_status & ISR_PRS)
          dm9000_rx(dev);
-
+
      /* Trnasmit Interrupt check */
      if (int_status & ISR_PTS)
          dm9000_tx_done(dev, db);
@@ -1116,8 +1180,12 @@ static irqreturn_t dm9000_interrupt(int
      iow(db, DM9000_IMR, db->imr_all);

      /* Restore previous register address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-
+#endif
+
      spin_unlock_irqrestore(&db->lock, flags);

      return IRQ_HANDLED;
@@ -1233,11 +1301,15 @@ dm9000_phy_read(struct net_device *dev,
      int ret;

      mutex_lock(&db->addr_lock);
-
+
      spin_lock_irqsave(&db->lock,flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Fill the phyxcer register into REG_0C */
      iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1250,7 +1322,11 @@ dm9000_phy_read(struct net_device *dev,
      dm9000_msleep(db, 1);        /* Wait read complete */

      spin_lock_irqsave(&db->lock,flags);
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      iow(db, DM9000_EPCR, 0x0);    /* Clear phyxcer read command */

@@ -1258,9 +1334,14 @@ dm9000_phy_read(struct net_device *dev,
      ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);

      /* restore the previous address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
-    spin_unlock_irqrestore(&db->lock,flags);
+#endif

+    spin_unlock_irqrestore(&db->lock,flags);
+
      mutex_unlock(&db->addr_lock);

      dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
@@ -1284,7 +1365,11 @@ dm9000_phy_write(struct net_device *dev,
      spin_lock_irqsave(&db->lock,flags);

      /* Save previous register address */
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      /* Fill the phyxcer register into REG_0C */
      iow(db, DM9000_EPAR, DM9000_PHY | reg);
@@ -1295,18 +1380,31 @@ dm9000_phy_write(struct net_device *dev,

      iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);    /* Issue phyxcer 
write command */

+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
+#endif
+
      spin_unlock_irqrestore(&db->lock, flags);

      dm9000_msleep(db, 1);        /* Wait write complete */

      spin_lock_irqsave(&db->lock,flags);
-    reg_save = readb(db->io_addr);
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+   reg_save = (u8)readl(db->io_addr);
+#else
+   reg_save = readb(db->io_addr);
+#endif

      iow(db, DM9000_EPCR, 0x0);    /* Clear phyxcer write command */

      /* restore the previous address */
+#ifdef CONFIG_DM9000_32BIT_SW_SWAP
+    writel(reg_save, db->io_addr);
+#else
      writeb(reg_save, db->io_addr);
+#endif

      spin_unlock_irqrestore(&db->lock, flags);
      mutex_unlock(&db->addr_lock);
@@ -1713,4 +1811,3 @@ MODULE_AUTHOR("Sascha Hauer, Ben Dooks")
  MODULE_DESCRIPTION("Davicom DM9000 network driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:dm9000");
-

--- arch/m68k/include/asm/io_no.h.orig    2011-01-05 16:53:55.904905038 
+0100
+++ arch/m68k/include/asm/io_no.h    2011-01-04 23:45:08.893049554 +0100
@@ -47,6 +47,91 @@ static inline unsigned int _swapl(volati
  #define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
  #define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))

+static inline void writesb (void __iomem *reg, void *data, int count)
+{
+    unsigned char *p = (unsigned char*) data;
+
+    while (count--) writeb(*p++, reg);
+}
+
+static inline void writesbsw (void __iomem *reg, void *data, int count)
+{
+    unsigned char *p = (unsigned char *) data;
+
+    while (count--) writel((int)(*p++), reg);
+}
+
+static inline void writesw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short*) data;
+
+   while (count--) writew(*p++, reg);
+}
+
+static inline void writeswsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) writel((int)(_swapw(*p++)), reg);
+}
+
+static inline void writesl (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long*) data;
+
+   while (count--) writel(*p++, reg);
+}
+
+static inline void writeslsw (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) writel((int)(_swapl(*p++)), reg);
+}
+
+static inline void readsb (void __iomem *reg, void *data, int count)
+{
+   unsigned char *p = (unsigned char *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readsbsw (void __iomem *reg, void *data, int count)
+{
+   unsigned char *p = (unsigned char *) data;
+
+   while (count--) *p++ = (unsigned char)readl(reg);
+}
+
+static inline void readsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readswsw (void __iomem *reg, void *data, int count)
+{
+   unsigned short *p = (unsigned short *) data;
+
+   while (count--) *p++ = _swapw((unsigned short)readw(reg));
+}
+
+static inline void readsl (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) *p++ = readb(reg);
+}
+
+static inline void readslsw (void __iomem *reg, void *data, int count)
+{
+   unsigned long *p = (unsigned long *) data;
+
+   while (count--) *p++ = _swapl(readl(reg));
+}
+
+
  #define __raw_readb readb
  #define __raw_readw readw
  #define __raw_readl readl
@@ -180,4 +265,3 @@ extern void iounmap(void *addr);
  #endif /* __KERNEL__ */

  #endif /* _M68KNOMMU_IO_H */
-

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ