patch-2.1.48 linux/arch/ppc/kernel/port_io.c

Next file: linux/arch/ppc/kernel/ppc_asm.tmpl
Previous file: linux/arch/ppc/kernel/pmac_time.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.47/linux/arch/ppc/kernel/port_io.c linux/arch/ppc/kernel/port_io.c
@@ -1,149 +1,146 @@
 /*
  * I/O 'port' access routines
  */
+#include <asm/byteorder.h>
+#include <asm/io.h>
 
-/* This is really only correct for the MVME16xx (PreP)? */
+#define inb_asm(port) {( \
+  unsigned char ret; \
+  asm ( "lbz %0,0(%1)\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" : "=r" (ret) : "r" (port+_IO_BASE)); \
+  return ret; \
+})
 
-#define _IO_BASE ((unsigned long)0x80000000)
-
-unsigned char
+inline unsigned char
 inb(int port)
 {
-	return (*((unsigned  char *)(_IO_BASE+port)));
+  unsigned char ret;
+  asm("/*inb*/\n");
+  asm ( "lbz %0,0(%1)" : "=r" (ret) : "r" (port+_IO_BASE));
+  return ret;
 }
 
-unsigned short
+inline unsigned short
 inw(int port)
 {
-	return (_LE_to_BE_short(*((unsigned short *)(_IO_BASE+port))));
+  unsigned short ret;
+  asm("/*inw*/\n");
+  asm ( "lhbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0));
+  return ret;
 }
 
-unsigned long
+inline unsigned long
 inl(int port)
 {
-	return (_LE_to_BE_long(*((unsigned  long *)(_IO_BASE+port))));
+  unsigned long ret;
+  asm("/*inl*/\n");
+  asm ( "lwbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0));
+  return ret;
 }
 
-void insb(int port, char *ptr, int len)
+inline unsigned char
+outb(unsigned char val,int port)
 {
-	unsigned char *io_ptr = (unsigned char *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*ptr++ = *io_ptr;
-	}
+  asm("/*outb*/\n");
+  asm ( "stb %0,0(%1)" :: "r" (val), "r" (port+_IO_BASE));
+  return (val);
 }
 
-#if 0
-void insw(int port, short *ptr, int len)
-{
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*ptr++ = _LE_to_BE_short(*io_ptr);
-	}
-}
-#else
-void insw(int port, short *ptr, int len)
+inline unsigned short
+outw(unsigned short val,int port)
 {
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	_insw(io_ptr, ptr, len);
+  asm("/*outw*/\n");
+  asm ( "sthbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0));
+  return (val);
 }
-#endif
 
-void insw_unswapped(int port, short *ptr, int len)
+inline unsigned long
+outl(unsigned long val,int port)
 {
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*ptr++ = *io_ptr;
-	}
+  asm("/*outl*/\n");
+  asm ( "stwbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0));
+  return (val);
 }
 
-void insl(int port, long *ptr, int len)
+void insb(int port, char *ptr, int len)
 {
-	unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*ptr++ = _LE_to_BE_long(*io_ptr);
-	}
+  memcpy( (void *)ptr, (void *)(port+_IO_BASE), len);
 }
 
-unsigned char  inb_p(int port) {return (inb(port)); }
-unsigned short inw_p(int port) {return (inw(port)); }
-unsigned long  inl_p(int port) {return (inl(port)); }
-
-unsigned char
-outb(unsigned char val,int port)
+void insw(int port, short *ptr, int len)
 {
-	*((unsigned  char *)(_IO_BASE+port)) = (val);
-	return (val);
+  asm ("mtctr	%2 \n\t"
+       "subi	%1,%1,2 \n\t"
+       "00:\n\t"
+       "lhbrx	%2,0,%0 \n\t"
+       "sthu	%2,2(%1) \n\t"
+       "bdnz 00b \n\t"
+       :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
 }
 
-unsigned short
-outw(unsigned short val,int port)
+void insw_unswapped(int port, short *ptr, int len)
 {
-	*((unsigned  short *)(_IO_BASE+port)) = _LE_to_BE_short(val);
-	return (val);
+  memcpy( (void *)ptr, (void *)(port+_IO_BASE), (len*sizeof(short)) );
 }
 
-unsigned long
-outl(unsigned long val,int port)
+void insl(int port, long *ptr, int len)
 {
-	*((unsigned  long *)(_IO_BASE+port)) = _LE_to_BE_long(val);
-	return (val);
+  asm ("mtctr	%2 \n\t"
+       "subi	%1,%1,4 \n\t"
+       "00:\n\t"
+       "lhbrx	%2,0,%0 \n\t"
+       "sthu	%2,4(%1) \n\t"
+       "bdnz 00b \n\t"
+       :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
 }
 
 void outsb(int port, char *ptr, int len)
 {
-	unsigned char *io_ptr = (unsigned char *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*io_ptr = *ptr++;
-	}
+  memcpy( (void *)ptr, (void *)(port+_IO_BASE), len );
 }
 
-#if 0
 void outsw(int port, short *ptr, int len)
 {
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*io_ptr = _LE_to_BE_short(*ptr++);
-	}
+  asm ("mtctr	%2\n\t"
+       "subi	%1,%1,2\n\t"
+       "00:lhzu	%2,2(%1)\n\t"
+       "sthbrx	%2,0,%0\n\t"
+       "bdnz	00b\n\t"
+       :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
 }
-#else
-void outsw(int port, short *ptr, int len)
-{
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	_outsw(io_ptr, ptr, len);
-}
-#endif
 
 void outsw_unswapped(int port, short *ptr, int len)
 {
-	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*io_ptr = *ptr++;
-	}
+  memcpy( (void *)ptr, (void *)(port+_IO_BASE), len*sizeof(short) );  
 }
 
 void outsl(int port, long *ptr, int len)
 {
-	unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
-	while (len-- > 0)
-	{
-		*io_ptr = _LE_to_BE_long(*ptr++);
-	}
-}
-
-unsigned char  outb_p(unsigned char val,int port) { return (outb(val,port)); }
-unsigned short outw_p(unsigned short val,int port) { return (outw(val,port)); }
-unsigned long  outl_p(unsigned long val,int port) { return (outl(val,port)); }
-
-
-/* makes writing to the ibm acorn power management stuff easier -- Cort */
-/* args in forn of PA.B as in tech spec for ibm carolina */
-void ibm_write(unsigned char val,unsigned int port)
-{
+  asm ("mtctr	%2\n\t"
+       "subi	%1,%1,4\n\t"
+       "00:lwzu	%2,4(%1)\n\t"
+       "sthbrx	%2,0,%0\n\t"
+       "bdnz	00b\n\t"
+       :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
+}
+
+void insl_unswapped(int port, long *ptr, int len)
+{
+        unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
+        /* Ensure I/O operations complete */
+        __asm__ volatile("eieio");
+        while (len-- > 0)
+        {
+                *ptr++ = (*io_ptr);
+        }
+}
+
+void outsl_unswapped(int port, long *ptr, int len)
+{
+        unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
+        /* Ensure I/O operations complete */
+        __asm__ volatile("eieio");
+        while (len-- > 0)
+        {
+                *io_ptr = (*ptr++);
+        }
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov