patch-2.3.9 linux/arch/mips/sni/io.c
Next file: linux/arch/mips/sni/pci.c
Previous file: linux/arch/mips/sni/int-handler.S
Back to the patch index
Back to the overall index
- Lines: 230
- Date:
Fri Jun 25 17:40:13 1999
- Orig file:
v2.3.8/linux/arch/mips/sni/io.c
- Orig date:
Tue Oct 20 13:52:55 1998
diff -u --recursive --new-file v2.3.8/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c
@@ -1,11 +1,10 @@
-/*
+/* $Id: io.c,v 1.3 1999/01/04 16:03:58 ralf Exp $
+ *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Low level I/O functions for SNI.
- *
- * $Id: io.c,v 1.2 1998/03/27 08:53:50 ralf Exp $
*/
#include <linux/string.h>
#include <asm/mipsconfig.h>
@@ -14,46 +13,42 @@
#include <asm/spinlock.h>
#include <asm/sni.h>
-unsigned char sni_map_isa_cache;
-
-#define unused __attribute__((unused))
-
-/*
- * The PCIMT_CSMAPISA is shared by all processors; we need locking.
- *
- * XXX It's legal to use all the I/O memory access functions in interrupt
- * code, so we need to use the _irq locking stuff which may result in
- * significant IRQ latencies.
- */
-static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED;
-
/*
* Urgs... We only can see a 16mb window of the 4gb EISA address space
* at PCIMT_EISA_BASE. Maladia segmentitis ...
*
- * XXX Check out if accessing PCIMT_CSMAPISA really is slow.
- * For now assume so.
+ * To avoid locking and all the related headacke we implement this such
+ * that accessing the bus address space nests, so we're treating this
+ * correctly even for interrupts. This is going to suck seriously for
+ * the SMP members of the RM family.
+ *
+ * Making things worse the PCIMT_CSMAPISA register resides on the X bus with
+ * it's unbeatable 1.4 mb/s transfer rate.
*/
-static inline void update_isa_cache(unsigned long address)
+
+static inline void eisa_map(unsigned long address)
{
unsigned char upper;
upper = address >> 24;
- if (sni_map_isa_cache != upper) {
- sni_map_isa_cache = upper;
- *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
- }
+ *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
}
+#define save_eisa_map() \
+ (*(volatile unsigned char *)PCIMT_CSMAPISA)
+#define restore_eisa_map(val) \
+ do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0)
+
static unsigned char sni_readb(unsigned long addr)
{
unsigned char res;
+ unsigned int save_map;
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
return res;
}
@@ -61,12 +56,13 @@
static unsigned short sni_readw(unsigned long addr)
{
unsigned short res;
+ unsigned int save_map;
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
return res;
}
@@ -74,101 +70,111 @@
static unsigned int sni_readl(unsigned long addr)
{
unsigned int res;
+ unsigned int save_map;
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
return res;
}
static void sni_writeb(unsigned char val, unsigned long addr)
{
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ unsigned int save_map;
+
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
static void sni_writew(unsigned short val, unsigned long addr)
{
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ unsigned int save_map;
+
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
static void sni_writel(unsigned int val, unsigned long addr)
{
- spin_lock_irq(&csmapisa_lock);
- update_isa_cache(addr);
+ unsigned int save_map;
+
+ save_map = save_eisa_map();
+ eisa_map(addr);
addr &= 0xffffff;
*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
static void sni_memset_io(unsigned long addr, int val, unsigned long len)
{
unsigned long waddr;
+ unsigned int save_map;
+ save_map = save_eisa_map();
waddr = PCIMT_EISA_BASE | (addr & 0xffffff);
- spin_lock_irq(&csmapisa_lock);
while(len) {
unsigned long fraglen;
fraglen = (~addr + 1) & 0xffffff;
fraglen = (fraglen < len) ? fraglen : len;
- update_isa_cache(addr);
+ eisa_map(addr);
memset((char *)waddr, val, fraglen);
addr += fraglen;
waddr = waddr + fraglen - 0x1000000;
len -= fraglen;
}
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
{
unsigned long waddr;
+ unsigned int save_map;
+ save_map = save_eisa_map();
waddr = PCIMT_EISA_BASE | (from & 0xffffff);
- spin_lock_irq(&csmapisa_lock);
while(len) {
unsigned long fraglen;
fraglen = (~from + 1) & 0xffffff;
fraglen = (fraglen < len) ? fraglen : len;
- update_isa_cache(from);
+ eisa_map(from);
memcpy((void *)to, (void *)waddr, fraglen);
to += fraglen;
from += fraglen;
waddr = waddr + fraglen - 0x1000000;
len -= fraglen;
}
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
{
unsigned long waddr;
+ unsigned int save_map;
+ save_map = save_eisa_map();
waddr = PCIMT_EISA_BASE | (to & 0xffffff);
- spin_lock_irq(&csmapisa_lock);
while(len) {
unsigned long fraglen;
fraglen = (~to + 1) & 0xffffff;
fraglen = (fraglen < len) ? fraglen : len;
- update_isa_cache(to);
+ eisa_map(to);
memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen);
to += fraglen;
from += fraglen;
waddr = waddr + fraglen - 0x1000000;
len -= fraglen;
}
- spin_unlock_irq(&csmapisa_lock);
+ restore_eisa_map(save_map);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)