original comment: +Wilson03172004,marked due to this pci host does not support MWI
[linux-2.4.git] / arch / mips / sni / io.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Low level I/O functions for SNI.
7  */
8 #include <linux/string.h>
9 #include <linux/spinlock.h>
10 #include <asm/addrspace.h>
11 #include <asm/system.h>
12 #include <asm/sni.h>
13
14 /*
15  * Urgs...  We only can see a 16mb window of the 4gb EISA address space
16  * at PCIMT_EISA_BASE.  Maladia segmentitis ...
17  *
18  * To avoid locking and all the related headacke we implement this such
19  * that accessing the bus address space nests, so we're treating this
20  * correctly even for interrupts.  This is going to suck seriously for
21  * the SMP members of the RM family.
22  *
23  * Making things worse the PCIMT_CSMAPISA register resides on the X bus with
24  * it's unbeatable 1.4 mb/s transfer rate.
25  */
26
27 static inline void eisa_map(unsigned long address)
28 {
29         unsigned char upper;
30
31         upper = address >> 24;
32         *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
33 }
34
35 #define save_eisa_map()                                                 \
36         (*(volatile unsigned char *)PCIMT_CSMAPISA)
37 #define restore_eisa_map(val)                                           \
38         do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0)
39
40 static unsigned char sni_readb(unsigned long addr)
41 {
42         unsigned char res;
43         unsigned int save_map;
44
45         save_map = save_eisa_map();
46         eisa_map(addr);
47         addr &= 0xffffff;
48         res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
49         restore_eisa_map(save_map);
50
51         return res;
52 }
53
54 static unsigned short sni_readw(unsigned long addr)
55 {
56         unsigned short res;
57         unsigned int save_map;
58
59         save_map = save_eisa_map();
60         eisa_map(addr);
61         addr &= 0xffffff;
62         res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
63         restore_eisa_map(save_map);
64
65         return res;
66 }
67
68 static unsigned int sni_readl(unsigned long addr)
69 {
70         unsigned int res;
71         unsigned int save_map;
72
73         save_map = save_eisa_map();
74         eisa_map(addr);
75         addr &= 0xffffff;
76         res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
77         restore_eisa_map(save_map);
78
79         return res;
80 }
81
82 static void sni_writeb(unsigned char val, unsigned long addr)
83 {
84         unsigned int save_map;
85
86         save_map = save_eisa_map();
87         eisa_map(addr);
88         addr &= 0xffffff;
89         *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
90         restore_eisa_map(save_map);
91 }
92
93 static void sni_writew(unsigned short val, unsigned long addr)
94 {
95         unsigned int save_map;
96
97         save_map = save_eisa_map();
98         eisa_map(addr);
99         addr &= 0xffffff;
100         *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
101         restore_eisa_map(save_map);
102 }
103
104 static void sni_writel(unsigned int val, unsigned long addr)
105 {
106         unsigned int save_map;
107
108         save_map = save_eisa_map();
109         eisa_map(addr);
110         addr &= 0xffffff;
111         *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
112         restore_eisa_map(save_map);
113 }
114
115 static void sni_memset_io(unsigned long addr, int val, unsigned long len)
116 {
117         unsigned long waddr;
118         unsigned int save_map;
119
120         save_map = save_eisa_map();
121         waddr = PCIMT_EISA_BASE | (addr & 0xffffff);
122         while(len) {
123                 unsigned long fraglen;
124
125                 fraglen = (~addr + 1) & 0xffffff;
126                 fraglen = (fraglen < len) ? fraglen : len;
127                 eisa_map(addr);
128                 memset((char *)waddr, val, fraglen);
129                 addr += fraglen;
130                 waddr = waddr + fraglen - 0x1000000;
131                 len -= fraglen;
132         }
133         restore_eisa_map(save_map);
134 }
135
136 static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
137 {
138         unsigned long waddr;
139         unsigned int save_map;
140
141         save_map = save_eisa_map();
142         waddr = PCIMT_EISA_BASE | (from & 0xffffff);
143         while(len) {
144                 unsigned long fraglen;
145
146                 fraglen = (~from + 1) & 0xffffff;
147                 fraglen = (fraglen < len) ? fraglen : len;
148                 eisa_map(from);
149                 memcpy((void *)to, (void *)waddr, fraglen);
150                 to += fraglen;
151                 from += fraglen;
152                 waddr = waddr + fraglen - 0x1000000;
153                 len -= fraglen;
154         }
155         restore_eisa_map(save_map);
156 }
157
158 static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
159 {
160         unsigned long waddr;
161         unsigned int save_map;
162
163         save_map = save_eisa_map();
164         waddr = PCIMT_EISA_BASE | (to & 0xffffff);
165         while(len) {
166                 unsigned long fraglen;
167
168                 fraglen = (~to + 1) & 0xffffff;
169                 fraglen = (fraglen < len) ? fraglen : len;
170                 eisa_map(to);
171                 memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen);
172                 to += fraglen;
173                 from += fraglen;
174                 waddr = waddr + fraglen - 0x1000000;
175                 len -= fraglen;
176         }
177         restore_eisa_map(save_map);
178 }