[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);