fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / smc91x.h
index e0efd19..d2767e6 100644 (file)
 #define SMC_insb(a, r, p, l)   readsb((a) + (r), p, (l))
 #define SMC_outsb(a, r, p, l)  writesb((a) + (r), p, (l))
 
+#elif  defined(CONFIG_MACH_LOGICPD_PXA270)
+
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      0
+#define SMC_IO_SHIFT           0
+#define SMC_NOWAIT             1
+
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
+
 #elif  defined(CONFIG_ARCH_INNOKOM) || \
        defined(CONFIG_MACH_MAINSTONE) || \
        defined(CONFIG_ARCH_PXA_IDP) || \
@@ -171,16 +184,10 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_IO_SHIFT           0
 #define SMC_NOWAIT             1
 
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
 #define SMC_inw(a, r)          readw((a) + (r))
 #define SMC_outw(v, a, r)      writew(v, (a) + (r))
 #define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
 
 #include <asm/mach-types.h>
 #include <asm/arch/cpu.h>
@@ -188,8 +195,9 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define        SMC_IRQ_FLAGS (( \
                   machine_is_omap_h2() \
                || machine_is_omap_h3() \
+               || machine_is_omap_h4() \
                || (machine_is_omap_innovator() && !cpu_is_omap1510()) \
-       ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING)
+       ) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING)
 
 
 #elif  defined(CONFIG_SH_SH4202_MICRODEV)
@@ -230,7 +238,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_CAN_USE_16BIT      1
 #define SMC_CAN_USE_32BIT      0
 
-#define SMC_inb(a, r)          inb((u32)a) + (r))
+#define SMC_inb(a, r)          inb(((u32)a) + (r))
 #define SMC_inw(a, r)          inw(((u32)a) + (r))
 #define SMC_outb(v, a, r)      outb(v, ((u32)a) + (r))
 #define SMC_outw(v, a, r)      outw(v, ((u32)a) + (r))
@@ -242,15 +250,17 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
 
-#elif  defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404)
+#elif   defined(CONFIG_MACH_LPD79520) \
+     || defined(CONFIG_MACH_LPD7A400) \
+     || defined(CONFIG_MACH_LPD7A404)
 
-/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between
- * the way that the CPU handles chip selects and the way that the SMC
- * chip expects the chip select to operate.  Refer to
+/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
+ * way that the CPU handles chip selects and the way that the SMC chip
+ * expects the chip select to operate.  Refer to
  * Documentation/arm/Sharp-LH/IOBarrier for details.  The read from
- * IOBARRIER is a byte as a least-common denominator of possible
- * regions to use as the barrier.  It would be wasteful to read 32
- * bits from a byte oriented region.
+ * IOBARRIER is a byte, in order that we read the least-common
+ * denominator.  It would be wasteful to read 32 bits from an 8-bit
+ * accessible region.
  *
  * There is no explicit protection against interrupts intervening
  * between the writew and the IOBARRIER.  In SMC ISR there is a
@@ -269,22 +279,35 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_CAN_USE_16BIT      1
 #define SMC_CAN_USE_32BIT      0
 #define SMC_NOWAIT             0
-#define LPD7A40X_IOBARRIER     readb (IOBARRIER_VIRT)
+#define LPD7X_IOBARRIER                readb (IOBARRIER_VIRT)
 
-#define SMC_inw(a,r)           readw ((void*) ((a) + (r)))
-#define SMC_insw(a,r,p,l)      readsw ((void*) ((a) + (r)), p, l)
-#define SMC_outw(v,a,r)             ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; })
+#define SMC_inw(a,r)\
+   ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
+#define SMC_outw(v,a,r)          ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
+
+#define SMC_insw               LPD7_SMC_insw
+static inline void LPD7_SMC_insw (unsigned char* a, int r,
+                                 unsigned char* p, int l)
+{
+       unsigned short* ps = (unsigned short*) p;
+       while (l-- > 0) {
+               *ps++ = readw (a + r);
+               LPD7X_IOBARRIER;
+       }
+}
 
-static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
+#define SMC_outsw              LPD7_SMC_outsw
+static inline void LPD7_SMC_outsw (unsigned char* a, int r,
+                                  unsigned char* p, int l)
 {
        unsigned short* ps = (unsigned short*) p;
        while (l-- > 0) {
                writew (*ps++, a + r);
-               LPD7A40X_IOBARRIER;
+               LPD7X_IOBARRIER;
        }
 }
 
-#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER
+#define SMC_INTERRUPT_PREAMBLE LPD7X_IOBARRIER
 
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
@@ -321,6 +344,24 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
 
 #define SMC_IRQ_FLAGS          (0)
 
+#elif  defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          readb((a) + (r))
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS          (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
@@ -342,10 +383,6 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
 
 #endif
 
-#ifndef        SMC_IRQ_FLAGS
-#define        SMC_IRQ_FLAGS           SA_TRIGGER_RISING
-#endif
-
 #ifdef SMC_USE_PXA_DMA
 /*
  * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
@@ -434,17 +471,92 @@ smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 #endif
 
 static void
-smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
+smc_pxa_dma_irq(int dma, void *dummy)
 {
        DCSR(dma) = 0;
 }
 #endif  /* SMC_USE_PXA_DMA */
 
 
-/* Because of bank switching, the LAN91x uses only 16 I/O ports */
+/*
+ * Everything a particular hardware setup needs should have been defined
+ * at this point.  Add stubs for the undefined cases, mainly to avoid
+ * compilation warnings since they'll be optimized away, or to prevent buggy
+ * use of them.
+ */
+
+#if ! SMC_CAN_USE_32BIT
+#define SMC_inl(ioaddr, reg)           ({ BUG(); 0; })
+#define SMC_outl(x, ioaddr, reg)       BUG()
+#define SMC_insl(a, r, p, l)           BUG()
+#define SMC_outsl(a, r, p, l)          BUG()
+#endif
+
+#if !defined(SMC_insl) || !defined(SMC_outsl)
+#define SMC_insl(a, r, p, l)           BUG()
+#define SMC_outsl(a, r, p, l)          BUG()
+#endif
+
+#if ! SMC_CAN_USE_16BIT
+
+/*
+ * Any 16-bit access is performed with two 8-bit accesses if the hardware
+ * can't do it directly. Most registers are 16-bit so those are mandatory.
+ */
+#define SMC_outw(x, ioaddr, reg)                                       \
+       do {                                                            \
+               unsigned int __val16 = (x);                             \
+               SMC_outb( __val16, ioaddr, reg );                       \
+               SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\
+       } while (0)
+#define SMC_inw(ioaddr, reg)                                           \
+       ({                                                              \
+               unsigned int __val16;                                   \
+               __val16 =  SMC_inb( ioaddr, reg );                      \
+               __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \
+               __val16;                                                \
+       })
+
+#define SMC_insw(a, r, p, l)           BUG()
+#define SMC_outsw(a, r, p, l)          BUG()
+
+#endif
+
+#if !defined(SMC_insw) || !defined(SMC_outsw)
+#define SMC_insw(a, r, p, l)           BUG()
+#define SMC_outsw(a, r, p, l)          BUG()
+#endif
+
+#if ! SMC_CAN_USE_8BIT
+#define SMC_inb(ioaddr, reg)           ({ BUG(); 0; })
+#define SMC_outb(x, ioaddr, reg)       BUG()
+#define SMC_insb(a, r, p, l)           BUG()
+#define SMC_outsb(a, r, p, l)          BUG()
+#endif
+
+#if !defined(SMC_insb) || !defined(SMC_outsb)
+#define SMC_insb(a, r, p, l)           BUG()
+#define SMC_outsb(a, r, p, l)          BUG()
+#endif
+
+#ifndef SMC_CAN_USE_DATACS
+#define SMC_CAN_USE_DATACS     0
+#endif
+
 #ifndef SMC_IO_SHIFT
 #define SMC_IO_SHIFT   0
 #endif
+
+#ifndef        SMC_IRQ_FLAGS
+#define        SMC_IRQ_FLAGS           IRQF_TRIGGER_RISING
+#endif
+
+#ifndef SMC_INTERRUPT_PREAMBLE
+#define SMC_INTERRUPT_PREAMBLE
+#endif
+
+
+/* Because of bank switching, the LAN91x uses only 16 I/O ports */
 #define SMC_IO_EXTENT  (16 << SMC_IO_SHIFT)
 #define SMC_DATA_EXTENT (4)
 
@@ -817,6 +929,11 @@ static const char * chip_ids[ 16 ] =  {
  * Note: the following macros do *not* select the bank -- this must
  * be done separately as needed in the main code.  The SMC_REG() macro
  * only uses the bank argument for debugging purposes (when enabled).
+ *
+ * Note: despite inline functions being safer, everything leading to this
+ * should preferably be macros to let BUG() display the line number in
+ * the core source code since we're interested in the top call site
+ * not in any inline function location.
  */
 
 #if SMC_DEBUG > 0
@@ -834,62 +951,142 @@ static const char * chip_ids[ 16 ] =  {
 #define SMC_REG(reg, bank)     (reg<<SMC_IO_SHIFT)
 #endif
 
-#if SMC_CAN_USE_8BIT
-#define SMC_GET_PN()           SMC_inb( ioaddr, PN_REG )
-#define SMC_SET_PN(x)          SMC_outb( x, ioaddr, PN_REG )
-#define SMC_GET_AR()           SMC_inb( ioaddr, AR_REG )
-#define SMC_GET_TXFIFO()       SMC_inb( ioaddr, TXFIFO_REG )
-#define SMC_GET_RXFIFO()       SMC_inb( ioaddr, RXFIFO_REG )
-#define SMC_GET_INT()          SMC_inb( ioaddr, INT_REG )
-#define SMC_ACK_INT(x)         SMC_outb( x, ioaddr, INT_REG )
-#define SMC_GET_INT_MASK()     SMC_inb( ioaddr, IM_REG )
-#define SMC_SET_INT_MASK(x)    SMC_outb( x, ioaddr, IM_REG )
-#else
-#define SMC_GET_PN()           (SMC_inw( ioaddr, PN_REG ) & 0xFF)
-#define SMC_SET_PN(x)          SMC_outw( x, ioaddr, PN_REG )
-#define SMC_GET_AR()           (SMC_inw( ioaddr, PN_REG ) >> 8)
-#define SMC_GET_TXFIFO()       (SMC_inw( ioaddr, TXFIFO_REG ) & 0xFF)
-#define SMC_GET_RXFIFO()       (SMC_inw( ioaddr, TXFIFO_REG ) >> 8)
-#define SMC_GET_INT()          (SMC_inw( ioaddr, INT_REG ) & 0xFF)
+/*
+ * Hack Alert: Some setups just can't write 8 or 16 bits reliably when not
+ * aligned to a 32 bit boundary.  I tell you that does exist!
+ * Fortunately the affected register accesses can be easily worked around
+ * since we can write zeroes to the preceeding 16 bits without adverse
+ * effects and use a 32-bit access.
+ *
+ * Enforce it on any 32-bit capable setup for now.
+ */
+#define SMC_MUST_ALIGN_WRITE   SMC_CAN_USE_32BIT
+
+#define SMC_GET_PN()                                                   \
+       ( SMC_CAN_USE_8BIT      ? (SMC_inb(ioaddr, PN_REG))             \
+                               : (SMC_inw(ioaddr, PN_REG) & 0xFF) )
+
+#define SMC_SET_PN(x)                                                  \
+       do {                                                            \
+               if (SMC_MUST_ALIGN_WRITE)                               \
+                       SMC_outl((x)<<16, ioaddr, SMC_REG(0, 2));       \
+               else if (SMC_CAN_USE_8BIT)                              \
+                       SMC_outb(x, ioaddr, PN_REG);                    \
+               else                                                    \
+                       SMC_outw(x, ioaddr, PN_REG);                    \
+       } while (0)
+
+#define SMC_GET_AR()                                                   \
+       ( SMC_CAN_USE_8BIT      ? (SMC_inb(ioaddr, AR_REG))             \
+                               : (SMC_inw(ioaddr, PN_REG) >> 8) )
+
+#define SMC_GET_TXFIFO()                                               \
+       ( SMC_CAN_USE_8BIT      ? (SMC_inb(ioaddr, TXFIFO_REG))         \
+                               : (SMC_inw(ioaddr, TXFIFO_REG) & 0xFF) )
+
+#define SMC_GET_RXFIFO()                                               \
+         ( SMC_CAN_USE_8BIT    ? (SMC_inb(ioaddr, RXFIFO_REG))         \
+                               : (SMC_inw(ioaddr, TXFIFO_REG) >> 8) )
+
+#define SMC_GET_INT()                                                  \
+       ( SMC_CAN_USE_8BIT      ? (SMC_inb(ioaddr, INT_REG))            \
+                               : (SMC_inw(ioaddr, INT_REG) & 0xFF) )
+
 #define SMC_ACK_INT(x)                                                 \
        do {                                                            \
-               unsigned long __flags;                                  \
-               int __mask;                                             \
-               local_irq_save(__flags);                                \
-               __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;            \
-               SMC_outw( __mask | (x), ioaddr, INT_REG );              \
-               local_irq_restore(__flags);                             \
+               if (SMC_CAN_USE_8BIT)                                   \
+                       SMC_outb(x, ioaddr, INT_REG);                   \
+               else {                                                  \
+                       unsigned long __flags;                          \
+                       int __mask;                                     \
+                       local_irq_save(__flags);                        \
+                       __mask = SMC_inw( ioaddr, INT_REG ) & ~0xff;    \
+                       SMC_outw( __mask | (x), ioaddr, INT_REG );      \
+                       local_irq_restore(__flags);                     \
+               }                                                       \
        } while (0)
-#define SMC_GET_INT_MASK()     (SMC_inw( ioaddr, INT_REG ) >> 8)
-#define SMC_SET_INT_MASK(x)    SMC_outw( (x) << 8, ioaddr, INT_REG )
-#endif
 
-#define SMC_CURRENT_BANK()     SMC_inw( ioaddr, BANK_SELECT )
-#define SMC_SELECT_BANK(x)     SMC_outw( x, ioaddr, BANK_SELECT )
-#define SMC_GET_BASE()         SMC_inw( ioaddr, BASE_REG )
-#define SMC_SET_BASE(x)                SMC_outw( x, ioaddr, BASE_REG )
-#define SMC_GET_CONFIG()       SMC_inw( ioaddr, CONFIG_REG )
-#define SMC_SET_CONFIG(x)      SMC_outw( x, ioaddr, CONFIG_REG )
-#define SMC_GET_COUNTER()      SMC_inw( ioaddr, COUNTER_REG )
-#define SMC_GET_CTL()          SMC_inw( ioaddr, CTL_REG )
-#define SMC_SET_CTL(x)         SMC_outw( x, ioaddr, CTL_REG )
-#define SMC_GET_MII()          SMC_inw( ioaddr, MII_REG )
-#define SMC_SET_MII(x)         SMC_outw( x, ioaddr, MII_REG )
-#define SMC_GET_MIR()          SMC_inw( ioaddr, MIR_REG )
-#define SMC_SET_MIR(x)         SMC_outw( x, ioaddr, MIR_REG )
-#define SMC_GET_MMU_CMD()      SMC_inw( ioaddr, MMU_CMD_REG )
-#define SMC_SET_MMU_CMD(x)     SMC_outw( x, ioaddr, MMU_CMD_REG )
-#define SMC_GET_FIFO()         SMC_inw( ioaddr, FIFO_REG )
-#define SMC_GET_PTR()          SMC_inw( ioaddr, PTR_REG )
-#define SMC_SET_PTR(x)         SMC_outw( x, ioaddr, PTR_REG )
-#define SMC_GET_EPH_STATUS()   SMC_inw( ioaddr, EPH_STATUS_REG )
-#define SMC_GET_RCR()          SMC_inw( ioaddr, RCR_REG )
-#define SMC_SET_RCR(x)         SMC_outw( x, ioaddr, RCR_REG )
-#define SMC_GET_REV()          SMC_inw( ioaddr, REV_REG )
-#define SMC_GET_RPC()          SMC_inw( ioaddr, RPC_REG )
-#define SMC_SET_RPC(x)         SMC_outw( x, ioaddr, RPC_REG )
-#define SMC_GET_TCR()          SMC_inw( ioaddr, TCR_REG )
-#define SMC_SET_TCR(x)         SMC_outw( x, ioaddr, TCR_REG )
+#define SMC_GET_INT_MASK()                                             \
+       ( SMC_CAN_USE_8BIT      ? (SMC_inb(ioaddr, IM_REG))             \
+                               : (SMC_inw( ioaddr, INT_REG ) >> 8) )
+
+#define SMC_SET_INT_MASK(x)                                            \
+       do {                                                            \
+               if (SMC_CAN_USE_8BIT)                                   \
+                       SMC_outb(x, ioaddr, IM_REG);                    \
+               else                                                    \
+                       SMC_outw((x) << 8, ioaddr, INT_REG);            \
+       } while (0)
+
+#define SMC_CURRENT_BANK()     SMC_inw(ioaddr, BANK_SELECT)
+
+#define SMC_SELECT_BANK(x)                                             \
+       do {                                                            \
+               if (SMC_MUST_ALIGN_WRITE)                               \
+                       SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT);    \
+               else                                                    \
+                       SMC_outw(x, ioaddr, BANK_SELECT);               \
+       } while (0)
+
+#define SMC_GET_BASE()         SMC_inw(ioaddr, BASE_REG)
+
+#define SMC_SET_BASE(x)                SMC_outw(x, ioaddr, BASE_REG)
+
+#define SMC_GET_CONFIG()       SMC_inw(ioaddr, CONFIG_REG)
+
+#define SMC_SET_CONFIG(x)      SMC_outw(x, ioaddr, CONFIG_REG)
+
+#define SMC_GET_COUNTER()      SMC_inw(ioaddr, COUNTER_REG)
+
+#define SMC_GET_CTL()          SMC_inw(ioaddr, CTL_REG)
+
+#define SMC_SET_CTL(x)         SMC_outw(x, ioaddr, CTL_REG)
+
+#define SMC_GET_MII()          SMC_inw(ioaddr, MII_REG)
+
+#define SMC_SET_MII(x)         SMC_outw(x, ioaddr, MII_REG)
+
+#define SMC_GET_MIR()          SMC_inw(ioaddr, MIR_REG)
+
+#define SMC_SET_MIR(x)         SMC_outw(x, ioaddr, MIR_REG)
+
+#define SMC_GET_MMU_CMD()      SMC_inw(ioaddr, MMU_CMD_REG)
+
+#define SMC_SET_MMU_CMD(x)     SMC_outw(x, ioaddr, MMU_CMD_REG)
+
+#define SMC_GET_FIFO()         SMC_inw(ioaddr, FIFO_REG)
+
+#define SMC_GET_PTR()          SMC_inw(ioaddr, PTR_REG)
+
+#define SMC_SET_PTR(x)                                                 \
+       do {                                                            \
+               if (SMC_MUST_ALIGN_WRITE)                               \
+                       SMC_outl((x)<<16, ioaddr, SMC_REG(4, 2));       \
+               else                                                    \
+                       SMC_outw(x, ioaddr, PTR_REG);                   \
+       } while (0)
+
+#define SMC_GET_EPH_STATUS()   SMC_inw(ioaddr, EPH_STATUS_REG)
+
+#define SMC_GET_RCR()          SMC_inw(ioaddr, RCR_REG)
+
+#define SMC_SET_RCR(x)         SMC_outw(x, ioaddr, RCR_REG)
+
+#define SMC_GET_REV()          SMC_inw(ioaddr, REV_REG)
+
+#define SMC_GET_RPC()          SMC_inw(ioaddr, RPC_REG)
+
+#define SMC_SET_RPC(x)                                                 \
+       do {                                                            \
+               if (SMC_MUST_ALIGN_WRITE)                               \
+                       SMC_outl((x)<<16, ioaddr, SMC_REG(8, 0));       \
+               else                                                    \
+                       SMC_outw(x, ioaddr, RPC_REG);                   \
+       } while (0)
+
+#define SMC_GET_TCR()          SMC_inw(ioaddr, TCR_REG)
+
+#define SMC_SET_TCR(x)         SMC_outw(x, ioaddr, TCR_REG)
 
 #ifndef SMC_GET_MAC_ADDR
 #define SMC_GET_MAC_ADDR(addr)                                         \
@@ -920,151 +1117,84 @@ static const char * chip_ids[ 16 ] =  {
                SMC_outw( mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4 );   \
        } while (0)
 
-#if SMC_CAN_USE_32BIT
-/*
- * Some setups just can't write 8 or 16 bits reliably when not aligned
- * to a 32 bit boundary.  I tell you that exists!
- * We re-do the ones here that can be easily worked around if they can have
- * their low parts written to 0 without adverse effects.
- */
-#undef SMC_SELECT_BANK
-#define SMC_SELECT_BANK(x)     SMC_outl( (x)<<16, ioaddr, 12<<SMC_IO_SHIFT )
-#undef SMC_SET_RPC
-#define SMC_SET_RPC(x)         SMC_outl( (x)<<16, ioaddr, SMC_REG(8, 0) )
-#undef SMC_SET_PN
-#define SMC_SET_PN(x)          SMC_outl( (x)<<16, ioaddr, SMC_REG(0, 2) )
-#undef SMC_SET_PTR
-#define SMC_SET_PTR(x)         SMC_outl( (x)<<16, ioaddr, SMC_REG(4, 2) )
-#endif
-
-#if SMC_CAN_USE_32BIT
-#define SMC_PUT_PKT_HDR(status, length)                                        \
-       SMC_outl( (status) | (length) << 16, ioaddr, DATA_REG )
-#define SMC_GET_PKT_HDR(status, length)                                        \
-       do {                                                            \
-               unsigned int __val = SMC_inl( ioaddr, DATA_REG );       \
-               (status) = __val & 0xffff;                              \
-               (length) = __val >> 16;                                 \
-       } while (0)
-#else
 #define SMC_PUT_PKT_HDR(status, length)                                        \
        do {                                                            \
-               SMC_outw( status, ioaddr, DATA_REG );                   \
-               SMC_outw( length, ioaddr, DATA_REG );                   \
-       } while (0)
-#define SMC_GET_PKT_HDR(status, length)                                        \
-       do {                                                            \
-               (status) = SMC_inw( ioaddr, DATA_REG );                 \
-               (length) = SMC_inw( ioaddr, DATA_REG );                 \
-       } while (0)
-#endif
-
-#if SMC_CAN_USE_32BIT
-#define _SMC_PUSH_DATA(p, l)                                           \
-       do {                                                            \
-               char *__ptr = (p);                                      \
-               int __len = (l);                                        \
-               if (__len >= 2 && (unsigned long)__ptr & 2) {           \
-                       __len -= 2;                                     \
-                       SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG );    \
-                       __ptr += 2;                                     \
-               }                                                       \
-               SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);        \
-               if (__len & 2) {                                        \
-                       __ptr += (__len & ~3);                          \
-                       SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );  \
+               if (SMC_CAN_USE_32BIT)                                  \
+                       SMC_outl((status) | (length)<<16, ioaddr, DATA_REG); \
+               else {                                                  \
+                       SMC_outw(status, ioaddr, DATA_REG);             \
+                       SMC_outw(length, ioaddr, DATA_REG);             \
                }                                                       \
        } while (0)
-#define _SMC_PULL_DATA(p, l)                                           \
+
+#define SMC_GET_PKT_HDR(status, length)                                        \
        do {                                                            \
-               char *__ptr = (p);                                      \
-               int __len = (l);                                        \
-               if ((unsigned long)__ptr & 2) {                         \
-                       /*                                              \
-                        * We want 32bit alignment here.                \
-                        * Since some buses perform a full 32bit        \
-                        * fetch even for 16bit data we can't use       \
-                        * SMC_inw() here.  Back both source (on chip   \
-                        * and destination) pointers of 2 bytes.        \
-                        */                                             \
-                       __ptr -= 2;                                     \
-                       __len += 2;                                     \
-                       SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );  \
+               if (SMC_CAN_USE_32BIT) {                                \
+                       unsigned int __val = SMC_inl(ioaddr, DATA_REG); \
+                       (status) = __val & 0xffff;                      \
+                       (length) = __val >> 16;                         \
+               } else {                                                \
+                       (status) = SMC_inw(ioaddr, DATA_REG);           \
+                       (length) = SMC_inw(ioaddr, DATA_REG);           \
                }                                                       \
-               __len += 2;                                             \
-               SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2);         \
        } while (0)
-#elif SMC_CAN_USE_16BIT
-#define _SMC_PUSH_DATA(p, l)   SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define _SMC_PULL_DATA(p, l)   SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
-#elif SMC_CAN_USE_8BIT
-#define _SMC_PUSH_DATA(p, l)   SMC_outsb( ioaddr, DATA_REG, p, l )
-#define _SMC_PULL_DATA(p, l)   SMC_insb ( ioaddr, DATA_REG, p, l )
-#endif
 
-#if ! SMC_CAN_USE_16BIT
-#define SMC_outw(x, ioaddr, reg)                                       \
+#define SMC_PUSH_DATA(p, l)                                            \
        do {                                                            \
-               unsigned int __val16 = (x);                             \
-               SMC_outb( __val16, ioaddr, reg );                       \
-               SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\
+               if (SMC_CAN_USE_32BIT) {                                \
+                       void *__ptr = (p);                              \
+                       int __len = (l);                                \
+                       void __iomem *__ioaddr = ioaddr;                \
+                       if (__len >= 2 && (unsigned long)__ptr & 2) {   \
+                               __len -= 2;                             \
+                               SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \
+                               __ptr += 2;                             \
+                       }                                               \
+                       if (SMC_CAN_USE_DATACS && lp->datacs)           \
+                               __ioaddr = lp->datacs;                  \
+                       SMC_outsl(__ioaddr, DATA_REG, __ptr, __len>>2); \
+                       if (__len & 2) {                                \
+                               __ptr += (__len & ~3);                  \
+                               SMC_outw(*((u16 *)__ptr), ioaddr, DATA_REG); \
+                       }                                               \
+               } else if (SMC_CAN_USE_16BIT)                           \
+                       SMC_outsw(ioaddr, DATA_REG, p, (l) >> 1);       \
+               else if (SMC_CAN_USE_8BIT)                              \
+                       SMC_outsb(ioaddr, DATA_REG, p, l);              \
        } while (0)
-#define SMC_inw(ioaddr, reg)                                           \
-       ({                                                              \
-               unsigned int __val16;                                   \
-               __val16 =  SMC_inb( ioaddr, reg );                      \
-               __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \
-               __val16;                                                \
-       })
-#endif
-
-#ifdef SMC_CAN_USE_DATACS
-#define SMC_PUSH_DATA(p, l)                                            \
-       if ( lp->datacs ) {                                             \
-               unsigned char *__ptr = (p);                             \
-               int __len = (l);                                        \
-               if (__len >= 2 && (unsigned long)__ptr & 2) {           \
-                       __len -= 2;                                     \
-                       SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );  \
-                       __ptr += 2;                                     \
-               }                                                       \
-               outsl(lp->datacs, __ptr, __len >> 2);                   \
-               if (__len & 2) {                                        \
-                       __ptr += (__len & ~3);                          \
-                       SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );  \
-               }                                                       \
-       } else {                                                        \
-               _SMC_PUSH_DATA(p, l);                                   \
-       }
 
 #define SMC_PULL_DATA(p, l)                                            \
-       if ( lp->datacs ) {                                             \
-               unsigned char *__ptr = (p);                             \
-               int __len = (l);                                        \
-               if ((unsigned long)__ptr & 2) {                         \
-                       /*                                              \
-                        * We want 32bit alignment here.                \
-                        * Since some buses perform a full 32bit        \
-                        * fetch even for 16bit data we can't use       \
-                        * SMC_inw() here.  Back both source (on chip   \
-                        * and destination) pointers of 2 bytes.        \
-                        */                                             \
-                       __ptr -= 2;                                     \
+       do {                                                            \
+               if (SMC_CAN_USE_32BIT) {                                \
+                       void *__ptr = (p);                              \
+                       int __len = (l);                                \
+                       void __iomem *__ioaddr = ioaddr;                \
+                       if ((unsigned long)__ptr & 2) {                 \
+                               /*                                      \
+                                * We want 32bit alignment here.        \
+                                * Since some buses perform a full      \
+                                * 32bit fetch even for 16bit data      \
+                                * we can't use SMC_inw() here.         \
+                                * Back both source (on-chip) and       \
+                                * destination pointers of 2 bytes.     \
+                                * This is possible since the call to   \
+                                * SMC_GET_PKT_HDR() already advanced   \
+                                * the source pointer of 4 bytes, and   \
+                                * the skb_reserve(skb, 2) advanced     \
+                                * the destination pointer of 2 bytes.  \
+                                */                                     \
+                               __ptr -= 2;                             \
+                               __len += 2;                             \
+                               SMC_SET_PTR(2|PTR_READ|PTR_RCV|PTR_AUTOINC); \
+                       }                                               \
+                       if (SMC_CAN_USE_DATACS && lp->datacs)           \
+                               __ioaddr = lp->datacs;                  \
                        __len += 2;                                     \
-                       SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );  \
-               }                                                       \
-               __len += 2;                                             \
-               insl( lp->datacs, __ptr, __len >> 2);                   \
-       } else {                                                        \
-               _SMC_PULL_DATA(p, l);                                   \
-       }
-#else
-#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
-#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
-#endif
-
-#if !defined (SMC_INTERRUPT_PREAMBLE)
-# define SMC_INTERRUPT_PREAMBLE
-#endif
+                       SMC_insl(__ioaddr, DATA_REG, __ptr, __len>>2);  \
+               } else if (SMC_CAN_USE_16BIT)                           \
+                       SMC_insw(ioaddr, DATA_REG, p, (l) >> 1);        \
+               else if (SMC_CAN_USE_8BIT)                              \
+                       SMC_insb(ioaddr, DATA_REG, p, l);               \
+       } while (0)
 
 #endif  /* _SMC91X_H_ */