OSDN Git Service

gas/opcodes: blackfin: move dsp mac func defines to common header
[pf3gnuchains/sourceware.git] / winsup / cygwin / fhandler_mem.cc
1 /* fhandler_mem.cc.  See fhandler.h for a description of the fhandler classes.
2
3    Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009,
4    2010 Red Hat, Inc.
5
6    This file is part of Cygwin.
7
8    This software is a copyrighted work licensed under the terms of the
9    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10    details. */
11
12 #include "winsup.h"
13 #include <unistd.h>
14
15 #include "cygerrno.h"
16 #include "path.h"
17 #include "fhandler.h"
18 #include "ntdll.h"
19
20 /**********************************************************************/
21 /* fhandler_dev_mem */
22
23 fhandler_dev_mem::fhandler_dev_mem ()
24   : fhandler_base ()
25 {
26 }
27
28 fhandler_dev_mem::~fhandler_dev_mem ()
29 {
30 }
31
32 int
33 fhandler_dev_mem::open (int flags, mode_t)
34 {
35   if (!wincap.has_physical_mem_access ())
36     {
37       set_errno (ENOENT);
38       debug_printf ("%s is accessible under NT4/W2K/XP only", dev ().name);
39       return 0;
40     }
41
42   if (dev () == FH_MEM) /* /dev/mem */
43     {
44       NTSTATUS ret;
45       SYSTEM_BASIC_INFORMATION sbi;
46       if ((ret = NtQuerySystemInformation (SystemBasicInformation, (PVOID) &sbi,
47                                            sizeof sbi, NULL)) != STATUS_SUCCESS)
48         {
49           __seterrno_from_nt_status (ret);
50           debug_printf("NtQuerySystemInformation: ret %d, Dos(ret) %E", ret);
51           mem_size = 0;
52         }
53       else
54         mem_size = sbi.PhysicalPageSize * sbi.NumberOfPhysicalPages;
55       debug_printf ("MemSize: %d MB", mem_size >> 20);
56     }
57   else if (dev () == FH_KMEM) /* /dev/kmem - Not yet supported */
58     {
59       mem_size = 0;
60       debug_printf ("KMemSize: %d MB", mem_size >> 20);
61     }
62   else if (dev () == FH_PORT) /* /dev/port == First 64K of /dev/mem */
63     {
64       mem_size = 65536;
65       debug_printf ("PortSize: 64 KB");
66     }
67   else
68     {
69       mem_size = 0;
70       debug_printf ("Illegal minor number!!!");
71     }
72
73   /* Check for illegal flags. */
74   if (flags & (O_APPEND | O_TRUNC | O_EXCL))
75     {
76       set_errno (EINVAL);
77       return 0;
78     }
79
80   OBJECT_ATTRIBUTES attr;
81   InitializeObjectAttributes (&attr, &ro_u_pmem,
82                               OBJ_CASE_INSENSITIVE
83                               | (flags & O_CLOEXEC ? 0 : OBJ_INHERIT),
84                               NULL, NULL);
85
86   ACCESS_MASK section_access;
87   if ((flags & O_ACCMODE) == O_RDONLY)
88     {
89       set_access (GENERIC_READ);
90       section_access = SECTION_MAP_READ;
91     }
92   else if ((flags & O_ACCMODE) == O_WRONLY)
93     {
94       set_access (GENERIC_WRITE);
95       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
96     }
97   else
98     {
99       set_access (GENERIC_READ | GENERIC_WRITE);
100       section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
101     }
102
103   HANDLE mem;
104   NTSTATUS ret = NtOpenSection (&mem, section_access, &attr);
105   if (!NT_SUCCESS (ret))
106     {
107       __seterrno_from_nt_status (ret);
108       set_io_handle (NULL);
109       return 0;
110     }
111
112   set_io_handle (mem);
113   set_open_status ();
114   return 1;
115 }
116
117 ssize_t __stdcall
118 fhandler_dev_mem::write (const void *ptr, size_t ulen)
119 {
120   if (!ulen || pos >= mem_size)
121     return 0;
122
123   if (!(get_access () & GENERIC_WRITE))
124     {
125       set_errno (EINVAL);
126       return -1;
127     }
128
129   if (pos + ulen > mem_size)
130     ulen = mem_size - pos;
131
132   PHYSICAL_ADDRESS phys;
133   NTSTATUS ret;
134   void *viewmem = NULL;
135   DWORD len = ulen + getsystempagesize () - 1;
136
137   phys.QuadPart = (ULONGLONG) pos;
138   if ((ret = NtMapViewOfSection (get_handle (),
139                                  INVALID_HANDLE_VALUE,
140                                  &viewmem,
141                                  0L,
142                                  len,
143                                  &phys,
144                                  &len,
145                                  ViewShare,
146                                  0,
147                                  PAGE_READONLY)) != STATUS_SUCCESS)
148     {
149       __seterrno_from_nt_status (ret);
150       return -1;
151     }
152
153   memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen);
154
155   if (!NT_SUCCESS (ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
156     {
157       __seterrno_from_nt_status (ret);
158       return -1;
159     }
160
161   pos += ulen;
162   return ulen;
163 }
164
165 void __stdcall
166 fhandler_dev_mem::read (void *ptr, size_t& ulen)
167 {
168   if (!ulen || pos >= mem_size)
169     {
170       ulen = 0;
171       return;
172     }
173
174   if (!(get_access () & GENERIC_READ))
175     {
176       set_errno (EINVAL);
177       ulen = (size_t) -1;
178       return;
179     }
180
181   if (pos + ulen > mem_size)
182     ulen = mem_size - pos;
183
184   PHYSICAL_ADDRESS phys;
185   NTSTATUS ret;
186   void *viewmem = NULL;
187   DWORD len = ulen + getsystempagesize () - 1;
188
189   phys.QuadPart = (ULONGLONG) pos;
190   if ((ret = NtMapViewOfSection (get_handle (),
191                                  INVALID_HANDLE_VALUE,
192                                  &viewmem,
193                                  0L,
194                                  len,
195                                  &phys,
196                                  &len,
197                                  ViewShare,
198                                  0,
199                                  PAGE_READONLY)) != STATUS_SUCCESS)
200     {
201       __seterrno_from_nt_status (ret);
202       ulen = (size_t) -1;
203       return;
204     }
205
206   memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen);
207
208   if (!NT_SUCCESS (ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
209     {
210       __seterrno_from_nt_status (ret);
211       ulen = (size_t) -1;
212       return;
213     }
214
215   pos += ulen;
216 }
217
218 _off64_t
219 fhandler_dev_mem::lseek (_off64_t offset, int whence)
220 {
221   switch (whence)
222     {
223     case SEEK_SET:
224       pos = offset;
225       break;
226
227     case SEEK_CUR:
228       pos += offset;
229       break;
230
231     case SEEK_END:
232       pos = mem_size;
233       pos += offset;
234       break;
235
236     default:
237       set_errno (EINVAL);
238       return ILLEGAL_SEEK;
239     }
240
241   if (pos > mem_size)
242     {
243       set_errno (EINVAL);
244       return ILLEGAL_SEEK;
245     }
246
247   return pos;
248 }
249
250 int
251 fhandler_dev_mem::fstat (struct __stat64 *buf)
252 {
253   fhandler_base::fstat (buf);
254   buf->st_blksize = getsystempagesize ();
255   if (is_auto_device ())
256     {
257       buf->st_mode = S_IFCHR;
258       if (wincap.has_physical_mem_access ())
259         buf->st_mode |= S_IRUSR | S_IWUSR |
260                         S_IRGRP | S_IWGRP |
261                         S_IROTH | S_IWOTH;
262     }
263
264   return 0;
265 }
266
267 int
268 fhandler_dev_mem::dup (fhandler_base *child)
269 {
270   int ret = fhandler_base::dup (child);
271
272   if (! ret)
273     {
274       fhandler_dev_mem *fhc = (fhandler_dev_mem *) child;
275
276       fhc->mem_size = mem_size;
277       fhc->pos = pos;
278     }
279   return ret;
280 }