Patch by Yuli Barcohen, 20 May 2004:
Add support for Interphase iSPAN boards.
diff --git a/drivers/smc91111.c b/drivers/smc91111.c
index 8b1103b..2a4f005 100644
--- a/drivers/smc91111.c
+++ b/drivers/smc91111.c
@@ -220,6 +220,77 @@
  ------------------------------------------------------------
 */
 
+#ifdef CONFIG_SMC_USE_IOFUNCS
+/*
+ * input and output functions
+ *
+ * Implemented due to inx,outx macros accessing the device improperly
+ * and putting the device into an unkown state.
+ *
+ * For instance, on Sharp LPD7A400 SDK, affects were chip memory
+ * could not be free'd (hence the alloc failures), duplicate packets,
+ * packets being corrupt (shifted) on the wire, etc.  Switching to the
+ * inx,outx functions fixed this problem.
+ */
+static inline word SMC_inw(dword offset);
+static inline void SMC_outw(word value, dword offset);
+static inline byte SMC_inb(dword offset);
+static inline void SMC_outb(byte value, dword offset);
+static inline void SMC_insw(dword offset, volatile uchar* buf, dword len);
+static inline void SMC_outsw(dword offset, uchar* buf, dword len);
+
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+static inline word SMC_inw(dword offset)
+{
+	word v;
+	v = *((volatile word*)(SMC_BASE_ADDRESS+offset));
+	barrier(); *(volatile u32*)(0xc0000000);
+	return v;
+}
+
+static inline void SMC_outw(word value, dword offset)
+{
+	*((volatile word*)(SMC_BASE_ADDRESS+offset)) = value;
+	barrier(); *(volatile u32*)(0xc0000000);
+}
+
+static inline byte SMC_inb(dword offset)
+{
+	word  _w;
+
+	_w = SMC_inw(offset & ~((dword)1));
+	return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w);
+}
+
+static inline void SMC_outb(byte value, dword offset)
+{
+	word  _w;
+
+	_w = SMC_inw(offset & ~((dword)1));
+	if (offset & 1)
+			*((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff);
+	else
+			*((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00);
+}
+
+static inline void SMC_insw(dword offset, volatile uchar* buf, dword len)
+{
+	while (len-- > 0) {
+		*((word*)buf)++ = SMC_inw(offset);
+		barrier(); *((volatile u32*)(0xc0000000));
+	}
+}
+
+static inline void SMC_outsw(dword offset, uchar* buf, dword len)
+{
+	while (len-- > 0) {
+		SMC_outw(*((word*)buf)++, offset);
+		barrier(); *(volatile u32*)(0xc0000000);
+	}
+}
+#endif  /* CONFIG_SMC_USE_IOFUNCS */
+
 static char unsigned smc_mac_addr[6] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8};
 
 /*
diff --git a/drivers/smc91111.h b/drivers/smc91111.h
index a228036..b373452 100644
--- a/drivers/smc91111.h
+++ b/drivers/smc91111.h
@@ -139,6 +139,7 @@
 
 #else /* if not CONFIG_PXA250 */
 
+#ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */
 /*
  * We have only 16 Bit PCMCIA access on Socket 0
  */
@@ -186,6 +187,8 @@
 				})
 #endif
 
+#endif  /* CONFIG_SMC_USE_IOFUNCS */
+
 #if defined(CONFIG_SMC_USE_32_BIT)
 
 #define	SMC_inl(r) 	(*((volatile dword *)(SMC_BASE_ADDRESS+(r))))