Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 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 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 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 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 ocurred.  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 }
263 
  This page was automatically generated by the LXR engine.