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