Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6.git] / Documentation / ia64 / aliasing-test.c
1 /*
2  * Exercise /dev/mem mmap cases that have been troublesome in the past
3  *
4  * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
5  *      Bjorn Helgaas <bjorn.helgaas@hp.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <dirent.h>
16 #include <fcntl.h>
17 #include <fnmatch.h>
18 #include <string.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <linux/pci.h>
23
24 int sum;
25
26 int map_mem(char *path, off_t offset, size_t length, int touch)
27 {
28         int fd, rc;
29         void *addr;
30         int *c;
31
32         fd = open(path, O_RDWR);
33         if (fd == -1) {
34                 perror(path);
35                 return -1;
36         }
37
38         if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
39                 rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
40                 if (rc == -1)
41                         perror("PCIIOC_MMAP_IS_MEM ioctl");
42         }
43
44         addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
45         if (addr == MAP_FAILED)
46                 return 1;
47
48         if (touch) {
49                 c = (int *) addr;
50                 while (c < (int *) (addr + length))
51                         sum += *c++;
52         }
53
54         rc = munmap(addr, length);
55         if (rc == -1) {
56                 perror("munmap");
57                 return -1;
58         }
59
60         close(fd);
61         return 0;
62 }
63
64 int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
65 {
66         struct dirent **namelist;
67         char *name, *path2;
68         int i, n, r, rc, result = 0;
69         struct stat buf;
70
71         n = scandir(path, &namelist, 0, alphasort);
72         if (n < 0) {
73                 perror("scandir");
74                 return -1;
75         }
76
77         for (i = 0; i < n; i++) {
78                 name = namelist[i]->d_name;
79
80                 if (fnmatch(".", name, 0) == 0)
81                         goto skip;
82                 if (fnmatch("..", name, 0) == 0)
83                         goto skip;
84
85                 path2 = malloc(strlen(path) + strlen(name) + 3);
86                 strcpy(path2, path);
87                 strcat(path2, "/");
88                 strcat(path2, name);
89
90                 if (fnmatch(file, name, 0) == 0) {
91                         rc = map_mem(path2, offset, length, touch);
92                         if (rc == 0)
93                                 fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
94                         else if (rc > 0)
95                                 fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
96                         else {
97                                 fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
98                                 return rc;
99                         }
100                 } else {
101                         r = lstat(path2, &buf);
102                         if (r == 0 && S_ISDIR(buf.st_mode)) {
103                                 rc = scan_tree(path2, file, offset, length, touch);
104                                 if (rc < 0)
105                                         return rc;
106                         }
107                 }
108
109                 result |= rc;
110                 free(path2);
111
112 skip:
113                 free(namelist[i]);
114         }
115         free(namelist);
116         return rc;
117 }
118
119 char buf[1024];
120
121 int read_rom(char *path)
122 {
123         int fd, rc;
124         size_t size = 0;
125
126         fd = open(path, O_RDWR);
127         if (fd == -1) {
128                 perror(path);
129                 return -1;
130         }
131
132         rc = write(fd, "1", 2);
133         if (rc <= 0) {
134                 perror("write");
135                 return -1;
136         }
137
138         do {
139                 rc = read(fd, buf, sizeof(buf));
140                 if (rc > 0)
141                         size += rc;
142         } while (rc > 0);
143
144         close(fd);
145         return size;
146 }
147
148 int scan_rom(char *path, char *file)
149 {
150         struct dirent **namelist;
151         char *name, *path2;
152         int i, n, r, rc, result = 0;
153         struct stat buf;
154
155         n = scandir(path, &namelist, 0, alphasort);
156         if (n < 0) {
157                 perror("scandir");
158                 return -1;
159         }
160
161         for (i = 0; i < n; i++) {
162                 name = namelist[i]->d_name;
163
164                 if (fnmatch(".", name, 0) == 0)
165                         goto skip;
166                 if (fnmatch("..", name, 0) == 0)
167                         goto skip;
168
169                 path2 = malloc(strlen(path) + strlen(name) + 3);
170                 strcpy(path2, path);
171                 strcat(path2, "/");
172                 strcat(path2, name);
173
174                 if (fnmatch(file, name, 0) == 0) {
175                         rc = read_rom(path2);
176
177                         /*
178                          * It's OK if the ROM is unreadable.  Maybe there
179                          * is no ROM, or some other error ocurred.  The
180                          * important thing is that no MCA happened.
181                          */
182                         if (rc > 0)
183                                 fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
184                         else {
185                                 fprintf(stderr, "PASS: %s not readable\n", path2);
186                                 return rc;
187                         }
188                 } else {
189                         r = lstat(path2, &buf);
190                         if (r == 0 && S_ISDIR(buf.st_mode)) {
191                                 rc = scan_rom(path2, file);
192                                 if (rc < 0)
193                                         return rc;
194                         }
195                 }
196
197                 result |= rc;
198                 free(path2);
199
200 skip:
201                 free(namelist[i]);
202         }
203         free(namelist);
204         return rc;
205 }
206
207 int main()
208 {
209         int rc;
210
211         if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
212                 fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
213         else
214                 fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
215
216         /*
217          * It's not safe to blindly read the VGA frame buffer.  If you know
218          * how to poke the card the right way, it should respond, but it's
219          * not safe in general.  Many machines, e.g., Intel chipsets, cover
220          * up a non-responding card by just returning -1, but others will
221          * report the failure as a machine check.
222          */
223         if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
224                 fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
225         else
226                 fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
227
228         if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
229                 fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
230         else
231                 fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
232
233         /*
234          * Often you can map all the individual pieces above (0-0xA0000,
235          * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
236          * thing at once.  This is because the individual pieces use different
237          * attributes, and there's no single attribute supported over the
238          * whole region.
239          */
240         rc = map_mem("/dev/mem", 0, 1024*1024, 0);
241         if (rc == 0)
242                 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
243         else if (rc > 0)
244                 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
245         else
246                 fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
247
248         scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
249         scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
250         scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
251         scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
252
253         scan_rom("/sys/devices", "rom");
254
255         scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
256         scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
257         scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
258         scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
259 }