patch-2.4.21 linux-2.4.21/include/asm-ppc/io.h
Next file: linux-2.4.21/include/asm-ppc/ioctl.h
Previous file: linux-2.4.21/include/asm-ppc/immap_8260.h
Back to the patch index
Back to the overall index
- Lines: 143
- Date:
2003-06-13 07:51:38.000000000 -0700
- Orig file:
linux-2.4.20/include/asm-ppc/io.h
- Orig date:
2001-11-02 17:43:54.000000000 -0800
diff -urN linux-2.4.20/include/asm-ppc/io.h linux-2.4.21/include/asm-ppc/io.h
@@ -1,6 +1,3 @@
-/*
- * BK Id: SCCS/s.io.h 1.14 10/16/01 15:58:42 trini
- */
#ifdef __KERNEL__
#ifndef _PPC_IO_H
#define _PPC_IO_H
@@ -80,9 +77,22 @@
#ifdef CONFIG_ALL_PPC
/*
- * We have to handle possible machine checks here on powermacs
- * and potentially some CHRPs -- paulus.
+ * On powermacs, we will get a machine check exception if we
+ * try to read data from a non-existent I/O port. Because the
+ * machine check is an asynchronous exception, it isn't
+ * well-defined which instruction SRR0 will point to when the
+ * exception occurs.
+ * With the sequence below (twi; isync; nop), we have found that
+ * the machine check occurs on one of the three instructions on
+ * all PPC implementations tested so far. The twi and isync are
+ * needed on the 601 (in fact twi; sync works too), the isync and
+ * nop are needed on 604[e|r], and any of twi, sync or isync will
+ * work on 603[e], 750, 74x0.
+ * The twi creates an explicit data dependency on the returned
+ * value which seems to be needed to make the 601 wait for the
+ * load to finish.
*/
+
#define __do_in_asm(name, op) \
extern __inline__ unsigned int name(unsigned int port) \
{ \
@@ -181,7 +191,6 @@
#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
-#ifdef __KERNEL__
/*
* Map in an area of physical address space, for accessing
* I/O devices etc.
@@ -197,6 +206,15 @@
unsigned int size, int flags);
/*
+ * This makes sure that a value has been returned from a device
+ * before any subsequent loads or stores are performed.
+ */
+extern inline void io_flush(int value)
+{
+ __asm__ __volatile__("twi 0,%0,0; isync" : : "r" (value));
+}
+
+/*
* The PCI bus is inherently Little-Endian. The PowerPC is being
* run Big-Endian. Thus all values which cross the [PCI] barrier
* must be endian-adjusted. Also, the local DRAM has a different
@@ -250,11 +268,9 @@
/*
* Change "struct page" to physical address.
*/
-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + PPC_MEMSTART)
#define page_to_bus(page) (page_to_phys(page) + PCI_DRAM_OFFSET)
-#endif /* __KERNEL__ */
-
/*
* Enforce In-order Execution of I/O:
* Acts as a barrier to ensure all previous I/O accesses have
@@ -265,7 +281,7 @@
__asm__ __volatile__ ("eieio" : : : "memory");
}
-/* Enforce in-order execution of data I/O.
+/* Enforce in-order execution of data I/O.
* No distinction between read/write on PPC; use eieio for all three.
*/
#define iobarrier_rw() eieio()
@@ -274,12 +290,19 @@
/*
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ *
+ * Read operations have additional twi & isync to make sure the read
+ * is actually performed (i.e. the data has come back) before we start
+ * executing any following instructions.
*/
extern inline int in_8(volatile unsigned char *addr)
{
int ret;
- __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+ __asm__ __volatile__(
+ "lbz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
return ret;
}
@@ -292,7 +315,9 @@
{
int ret;
- __asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) :
+ __asm__ __volatile__("lhbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) :
"r" (addr), "m" (*addr));
return ret;
}
@@ -301,7 +326,9 @@
{
int ret;
- __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+ __asm__ __volatile__("lhz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
return ret;
}
@@ -320,7 +347,9 @@
{
unsigned ret;
- __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
+ __asm__ __volatile__("lwbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) :
"r" (addr), "m" (*addr));
return ret;
}
@@ -329,7 +358,9 @@
{
unsigned ret;
- __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+ __asm__ __volatile__("lwz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)