[parisc-linux] more on pci mmio swapping
Randolph Chung
Randolph Chung <randolph@tausq.org>
Fri, 16 Nov 2001 23:48:59 -0800
The story so far...
1. pci is mostly little-endian
2. most of the other linux big-endian architectures define the 16-bit/32-bit
read/write operations to do cpu_to_le byte swapping
3. parisc (and s390) do not currently do this
I've looked at the part in the Dino ERS again that willy pointed out. As
far as I can tell it's not talking about byte swapping but more about
address invariance. In fact the ERS specifically says that if the host
is running in BE mode, the driver is responsible for byte swapping.
I've looked at a sample of pci drivers that we are using for parisc
right now. In the case of the sym53c8xx driver, there is hppa specific
code to do cpu_to_le translation before doing writes.
So, given these things, I'm inclined to say that our current
implementation is not correct. Grant concurs, though it'd be great to
have folks like Alan (Cox) confirm this :)
The attached patch is my proposed changes. I've tested it on a c3000
with tulip/sym53c8xx and it works. I've done some digging into other
common drivers to see if anything else will break. So far I haven't come
up with anything, but Grant thinks acenic may break....
with this patch, the usb controller on suckyio is being detected
correctly (at least more correctly than before), though it's still
not quite working yet.
comments on this are most welcome. I hope to check this in some time
next week.
randolph
--
@..@ http://www.TauSq.org/
(----)
( >__< )
^^ ~~ ^^
Index: arch/parisc/lib/io.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/lib/io.c,v
retrieving revision 1.6
diff -u -r1.6 io.c
--- arch/parisc/lib/io.c 2001/11/07 23:51:31 1.6
+++ arch/parisc/lib/io.c 2001/11/15 08:00:31
@@ -24,7 +24,7 @@
count--;
}
while (count > 3) {
- writel(*(u32 *)src, dest);
+ __raw_writel(*(u32 *)src, dest);
(unsigned long) src += 4;
dest += 4;
count -= 4;
@@ -68,14 +68,14 @@
}
if (src & 2) {
- *(u16 *)dest = readw(src);
+ *(u16 *)dest = __raw_readw(src);
((u16 *)src)++;
((u16 *)dest)++;
count-=2;
}
while (count > 3) {
- *(u32 *)dest = readl(src);
+ *(u32 *)dest = __raw_readl(src);
dest += 4;
src += 4;
count -= 4;
@@ -83,7 +83,7 @@
shortcopy:
while (count > 1) {
- *(u16 *)dest = readw(src);
+ *(u16 *)dest = __raw_readw(src);
((u16 *)src)++;
((u16 *)dest)++;
count-=2;
@@ -109,7 +109,7 @@
count--;
}
while (count > 3) {
- writel(fill32, dest);
+ __raw_writel(fill32, dest);
dest += 4;
count -= 4;
}
Index: drivers/scsi/sym53c8xx_defs.h
===================================================================
RCS file: /var/cvs/linux/drivers/scsi/sym53c8xx_defs.h,v
retrieving revision 1.11
diff -u -r1.11 sym53c8xx_defs.h
--- drivers/scsi/sym53c8xx_defs.h 2001/08/01 15:26:34 1.11
+++ drivers/scsi/sym53c8xx_defs.h 2001/11/15 08:00:35
@@ -406,11 +406,11 @@
#define readb_raw readb
#define writeb_raw writeb
-#if defined(__hppa__) && !defined(SCSI_NCR_BIG_ENDIAN)
-#define readw_l2b(a) le16_to_cpu(readw(a))
-#define readl_l2b(a) le32_to_cpu(readl(a))
-#define writew_b2l(v,a) writew(cpu_to_le16(v),a)
-#define writel_b2l(v,a) writel(cpu_to_le32(v),a)
+#if defined(SCSI_NCR_BIG_ENDIAN)
+#define readw_l2b __raw_readw
+#define readl_l2b __raw_readl
+#define writew_b2l __raw_writew
+#define writel_b2l __raw_writel
#else /* Other bid-endian */
#define readw_l2b readw
#define readl_l2b readl
Index: include/asm-parisc/io.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/io.h,v
retrieving revision 1.25
diff -u -r1.25 io.h
--- include/asm-parisc/io.h 2001/11/03 23:06:00 1.25
+++ include/asm-parisc/io.h 2001/11/15 08:00:36
@@ -147,11 +147,11 @@
#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
#else /* !USE_HPPA_IOREMAP */
#define readb(addr) __raw_readb((unsigned long)addr)
-#define readw(addr) __raw_readw((unsigned long)addr)
-#define readl(addr) __raw_readl((unsigned long)addr)
+#define readw(addr) le16_to_cpu(__raw_readw((unsigned long)addr))
+#define readl(addr) le32_to_cpu(__raw_readl((unsigned long)addr))
#define writeb(b,addr) __raw_writeb(b,(unsigned long)addr)
-#define writew(b,addr) __raw_writew(b,(unsigned long)addr)
-#define writel(b,addr) __raw_writel(b,(unsigned long)addr)
+#define writew(b,addr) __raw_writew(cpu_to_le16(b),(unsigned long)addr)
+#define writel(b,addr) __raw_writel(cpu_to_le32(b),(unsigned long)addr)
#endif /* !USE_HPPA_IOREMAP */
extern void memcpy_fromio(void *dest, unsigned long src, int count);