SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

Diff markup

Differences between /drivers/mem.c (Article 7.5) and /drivers/mem.c (Article 9)


001 /* Copyright (C) 2005 David Decotigny             001 /* Copyright (C) 2005 David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <sos/assert.h>                           019 #include <sos/assert.h>
020 #include <sos/kmalloc.h>                          020 #include <sos/kmalloc.h>
021 #include <sos/physmem.h>                          021 #include <sos/physmem.h>
022 #include <hwcore/paging.h>                        022 #include <hwcore/paging.h>
023 #include <sos/kmem_slab.h>                        023 #include <sos/kmem_slab.h>
024 #include <sos/list.h>                             024 #include <sos/list.h>
025 #include <hwcore/paging.h>                        025 #include <hwcore/paging.h>
                                                   >> 026 #include <drivers/devices.h>
                                                   >> 027 #include <sos/kmem_vmm.h>
                                                   >> 028 #include <sos/uaccess.h>
                                                   >> 029 #include <sos/chardev.h>
026                                                   030 
027 #include "mem.h"                                  031 #include "mem.h"
028                                                   032 
029                                                   033 
030 /**                                               034 /**
031  * A mapped mem/kmem resource                     035  * A mapped mem/kmem resource
032  */                                               036  */
033 struct kernel_remapped_resource                   037 struct kernel_remapped_resource
034 {                                                 038 {
035   int ref_cnt;                                    039   int ref_cnt;
036   struct sos_umem_vmm_mapped_resource mr;         040   struct sos_umem_vmm_mapped_resource mr;
037 };                                                041 };
038                                                   042 
039                                                   043 
040 /** Called after the virtual region has been i    044 /** Called after the virtual region has been inserted inside its
041     address space */                              045     address space */
042 static void resource_ref(struct sos_umem_vmm_v    046 static void resource_ref(struct sos_umem_vmm_vr * vr)
043 {                                                 047 {
044   /* Retrieve the mem/kmem structure associate    048   /* Retrieve the mem/kmem structure associated with the mapped resource */
045   struct kernel_remapped_resource * resource;     049   struct kernel_remapped_resource * resource;
046   resource                                        050   resource
047     = (struct kernel_remapped_resource*)          051     = (struct kernel_remapped_resource*)
048     sos_umem_vmm_get_mapped_resource_of_vr(vr)    052     sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
049                                                   053 
050   /* Increment ref counter */                     054   /* Increment ref counter */
051   resource->ref_cnt ++;                           055   resource->ref_cnt ++;
052 }                                                 056 }
053                                                   057 
054                                                   058 
055 /** Called when the virtual region is removed     059 /** Called when the virtual region is removed from its address
056     space */                                      060     space */
057 static void resource_unref(struct sos_umem_vmm    061 static void resource_unref(struct sos_umem_vmm_vr * vr)
058 {                                                 062 {
059   /* Retrieve the mem/kmem structure associate    063   /* Retrieve the mem/kmem structure associated with the mapped resource */
060   struct kernel_remapped_resource * resource;     064   struct kernel_remapped_resource * resource;
061   resource                                        065   resource
062     = (struct kernel_remapped_resource*)          066     = (struct kernel_remapped_resource*)
063     sos_umem_vmm_get_mapped_resource_of_vr(vr)    067     sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
064                                                   068   
065   /* Decrement ref coutner */                     069   /* Decrement ref coutner */
066   SOS_ASSERT_FATAL(resource->ref_cnt > 0);        070   SOS_ASSERT_FATAL(resource->ref_cnt > 0);
067   resource->ref_cnt --;                           071   resource->ref_cnt --;
068                                                   072 
069   /* Free the resource if it becomes unused */    073   /* Free the resource if it becomes unused */
070   if (resource->ref_cnt == 0)                     074   if (resource->ref_cnt == 0)
071     sos_kfree((sos_vaddr_t)resource);             075     sos_kfree((sos_vaddr_t)resource);
072 }                                                 076 }
073                                                   077 
074                                                   078 
075 /** MOST IMPORTANT callback ! Called when a th    079 /** MOST IMPORTANT callback ! Called when a thread page faults on the
076     resource's mapping */                         080     resource's mapping */
077 static sos_ret_t kmem_page_in(struct sos_umem_    081 static sos_ret_t kmem_page_in(struct sos_umem_vmm_vr * vr,
078                               sos_uaddr_t uadd    082                               sos_uaddr_t uaddr,
079                               sos_bool_t write    083                               sos_bool_t write_access)
080 {                                                 084 {
081   sos_vaddr_t vaddr;                              085   sos_vaddr_t vaddr;
082   sos_ret_t retval = SOS_OK;                      086   sos_ret_t retval = SOS_OK;
083   sos_paddr_t ppage_paddr;                        087   sos_paddr_t ppage_paddr;
084                                                   088 
085   /* Compute address of kernel page */            089   /* Compute address of kernel page */
086   vaddr = uaddr - sos_umem_vmm_get_start_of_vr    090   vaddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
087     + sos_umem_vmm_get_offset_in_resource(vr);    091     + sos_umem_vmm_get_offset_in_resource(vr);
088                                                   092 
089   /* Don't allow demand paging of non kernel p    093   /* Don't allow demand paging of non kernel pages */
090   if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)      094   if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)
091     return -SOS_EFAULT;                           095     return -SOS_EFAULT;
092                                                   096 
093   /* Lookup physical kernel page */               097   /* Lookup physical kernel page */
094   ppage_paddr = sos_paging_get_paddr(SOS_PAGE_    098   ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(vaddr));
095                                                   099 
096   /* Cannot access unmapped kernel pages */       100   /* Cannot access unmapped kernel pages */
097   if (! ppage_paddr)                              101   if (! ppage_paddr)
098     return -SOS_EFAULT;                           102     return -SOS_EFAULT;
099                                                   103   
100   /* Remap it in user space */                    104   /* Remap it in user space */
101   retval = sos_paging_map(ppage_paddr,            105   retval = sos_paging_map(ppage_paddr,
102                           SOS_PAGE_ALIGN_INF(u    106                           SOS_PAGE_ALIGN_INF(uaddr),
103                           TRUE,                   107                           TRUE,
104                           sos_umem_vmm_get_pro    108                           sos_umem_vmm_get_prot_of_vr(vr));
105                                                   109 
106   return retval;                                  110   return retval;
107 }                                                 111 }
108                                                   112 
109                                                   113 
110 /** The callbacks for a mapped kmem resource *    114 /** The callbacks for a mapped kmem resource */
111 static struct sos_umem_vmm_vr_ops kmem_ops = (    115 static struct sos_umem_vmm_vr_ops kmem_ops = (struct sos_umem_vmm_vr_ops)
112 {                                                 116 {
113   .ref     = resource_ref,                        117   .ref     = resource_ref,
114   .unref   = resource_unref,                      118   .unref   = resource_unref,
115   .page_in = kmem_page_in,                        119   .page_in = kmem_page_in,
116 };                                                120 };
117                                                   121 
118                                                   122 
119 /** The callback that gets called when the res    123 /** The callback that gets called when the resource gets mapped */
120 static sos_ret_t kmem_mmap(struct sos_umem_vmm    124 static sos_ret_t kmem_mmap(struct sos_umem_vmm_vr *vr)
121 {                                                 125 {
122   return sos_umem_vmm_set_ops_of_vr(vr, &kmem_    126   return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ops);
123 }                                                 127 }
124                                                   128 
125                                                   129 
126 /** The function responsible for mapping the /    130 /** The function responsible for mapping the /dev/kmem resource in
127     user space */                                 131     user space */
                                                   >> 132 static
128 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm    133 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm_as * dest_as,
129                            sos_uaddr_t *uaddr,    134                            sos_uaddr_t *uaddr,
130                            sos_size_t size,       135                            sos_size_t size,
131                            sos_vaddr_t offset,    136                            sos_vaddr_t offset,
132                            sos_ui32_t access_r    137                            sos_ui32_t access_rights,
133                            sos_ui32_t flags)      138                            sos_ui32_t flags)
134 {                                                 139 {
135   sos_ret_t retval;                               140   sos_ret_t retval;
136   struct kernel_remapped_resource * kmem_resou    141   struct kernel_remapped_resource * kmem_resource;
137                                                   142 
138   /* Allocate a new "descriptor" for the resou    143   /* Allocate a new "descriptor" for the resource */
139   kmem_resource                                   144   kmem_resource
140     = (struct kernel_remapped_resource*) sos_k    145     = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*kmem_resource),
141                                                   146                                                      0);
142   if (! kmem_resource)                            147   if (! kmem_resource)
143     return -SOS_ENOMEM;                           148     return -SOS_ENOMEM;
144                                                   149 
145   memset(kmem_resource, 0x0, sizeof(*kmem_reso    150   memset(kmem_resource, 0x0, sizeof(*kmem_resource));
146   kmem_resource->mr.allowed_access_rights         151   kmem_resource->mr.allowed_access_rights 
147     = SOS_VM_MAP_PROT_READ                        152     = SOS_VM_MAP_PROT_READ
148     | SOS_VM_MAP_PROT_WRITE                       153     | SOS_VM_MAP_PROT_WRITE
149     | SOS_VM_MAP_PROT_EXEC;                       154     | SOS_VM_MAP_PROT_EXEC;
150   kmem_resource->mr.custom_data    = kmem_reso    155   kmem_resource->mr.custom_data    = kmem_resource;
151   kmem_resource->mr.mmap           = kmem_mmap    156   kmem_resource->mr.mmap           = kmem_mmap;
152                                                   157 
153   /* Map it in user space */                      158   /* Map it in user space */
154   retval = sos_umem_vmm_map(dest_as, uaddr, si    159   retval = sos_umem_vmm_map(dest_as, uaddr, size,
155                             access_rights, fla    160                             access_rights, flags,
156                             & kmem_resource->m    161                             & kmem_resource->mr, offset);
157   if (SOS_OK != retval)                           162   if (SOS_OK != retval)
158     {                                             163     {
159       sos_kfree((sos_vaddr_t)kmem_resource);      164       sos_kfree((sos_vaddr_t)kmem_resource);
160       return retval;                              165       return retval;
161     }                                             166     }
162                                                   167 
163   return SOS_OK;                                  168   return SOS_OK;
164 }                                                 169 }
165                                                   170 
166                                                   171 
167 /** MOST IMPORTANT callback ! Called when a th    172 /** MOST IMPORTANT callback ! Called when a thread page faults on the
168     resource's mapping */                         173     resource's mapping */
169 static sos_ret_t physmem_page_in(struct sos_um    174 static sos_ret_t physmem_page_in(struct sos_umem_vmm_vr * vr,
170                                  sos_uaddr_t u    175                                  sos_uaddr_t uaddr,
171                                  sos_bool_t wr    176                                  sos_bool_t write_access)
172 {                                                 177 {
173   sos_ret_t retval = SOS_OK;                      178   sos_ret_t retval = SOS_OK;
174   sos_paddr_t ppage_paddr;                        179   sos_paddr_t ppage_paddr;
175                                                   180 
176   /* Compute address of kernel page */            181   /* Compute address of kernel page */
177   ppage_paddr = uaddr - sos_umem_vmm_get_start    182   ppage_paddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
178     + sos_umem_vmm_get_offset_in_resource(vr);    183     + sos_umem_vmm_get_offset_in_resource(vr);
179                                                   184 
180   /* Remap page in user space */                  185   /* Remap page in user space */
181   retval = sos_paging_map(SOS_PAGE_ALIGN_INF(p    186   retval = sos_paging_map(SOS_PAGE_ALIGN_INF(ppage_paddr),
182                           SOS_PAGE_ALIGN_INF(u    187                           SOS_PAGE_ALIGN_INF(uaddr),
183                           TRUE,                   188                           TRUE,
184                           sos_umem_vmm_get_pro    189                           sos_umem_vmm_get_prot_of_vr(vr));
185   return retval;                                  190   return retval;
186 }                                                 191 }
187                                                   192 
188                                                   193 
189 /** The callbacks for a mapped physmem resourc    194 /** The callbacks for a mapped physmem resource */
190 static struct sos_umem_vmm_vr_ops physmem_ops     195 static struct sos_umem_vmm_vr_ops physmem_ops = (struct sos_umem_vmm_vr_ops)
191 {                                                 196 {
192   .ref     = resource_ref,                        197   .ref     = resource_ref,
193   .unref   = resource_unref,                      198   .unref   = resource_unref,
194   .page_in = physmem_page_in,                     199   .page_in = physmem_page_in,
195 };                                                200 };
196                                                   201 
197                                                   202 
198 /** The callback that gets called when the res    203 /** The callback that gets called when the resource gets mapped */
199 static sos_ret_t physmem_mmap(struct sos_umem_    204 static sos_ret_t physmem_mmap(struct sos_umem_vmm_vr *vr)
200 {                                                 205 {
201   return sos_umem_vmm_set_ops_of_vr(vr, &physm    206   return sos_umem_vmm_set_ops_of_vr(vr, &physmem_ops);
202 }                                                 207 }
203                                                   208 
204                                                   209 
205 /** The function responsible for mapping the /    210 /** The function responsible for mapping the /dev/mem resource in
206     user space */                                 211     user space */
                                                   >> 212 static
207 sos_ret_t sos_dev_physmem_map(struct sos_umem_    213 sos_ret_t sos_dev_physmem_map(struct sos_umem_vmm_as * dest_as,
208                               sos_uaddr_t *uad    214                               sos_uaddr_t *uaddr,
209                               sos_size_t size,    215                               sos_size_t size,
210                               sos_paddr_t offs    216                               sos_paddr_t offset,
211                               sos_ui32_t acces    217                               sos_ui32_t access_rights,
212                               sos_ui32_t flags    218                               sos_ui32_t flags)
213 {                                                 219 {
214   sos_ret_t retval;                               220   sos_ret_t retval;
215   struct kernel_remapped_resource * physmem_re    221   struct kernel_remapped_resource * physmem_resource;
216                                                   222 
217   physmem_resource                                223   physmem_resource
218     = (struct kernel_remapped_resource*) sos_k    224     = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*physmem_resource),
219                                                   225                                                      0);
220   if (! physmem_resource)                         226   if (! physmem_resource)
221     return -SOS_ENOMEM;                           227     return -SOS_ENOMEM;
222                                                   228 
223   memset(physmem_resource, 0x0, sizeof(*physme    229   memset(physmem_resource, 0x0, sizeof(*physmem_resource));
224   physmem_resource->mr.allowed_access_rights      230   physmem_resource->mr.allowed_access_rights 
225     = SOS_VM_MAP_PROT_READ                        231     = SOS_VM_MAP_PROT_READ
226     | SOS_VM_MAP_PROT_WRITE                       232     | SOS_VM_MAP_PROT_WRITE
227     | SOS_VM_MAP_PROT_EXEC;                       233     | SOS_VM_MAP_PROT_EXEC;
228   physmem_resource->mr.custom_data    = physme    234   physmem_resource->mr.custom_data    = physmem_resource;
229   physmem_resource->mr.mmap           = physme    235   physmem_resource->mr.mmap           = physmem_mmap;
230                                                   236 
231   retval = sos_umem_vmm_map(dest_as, uaddr, si    237   retval = sos_umem_vmm_map(dest_as, uaddr, size,
232                             access_rights, fla    238                             access_rights, flags,
233                             & physmem_resource    239                             & physmem_resource->mr, offset);
234   if (SOS_OK != retval)                           240   if (SOS_OK != retval)
235     {                                             241     {
236       sos_kfree((sos_vaddr_t)physmem_resource)    242       sos_kfree((sos_vaddr_t)physmem_resource);
237       return retval;                              243       return retval;
238     }                                             244     }
239                                                   245 
240   return SOS_OK;                                  246   return SOS_OK;
                                                   >> 247 }
                                                   >> 248 
                                                   >> 249 
                                                   >> 250 /*
                                                   >> 251  * /dev/mem and /dev/kmem character device operations
                                                   >> 252  *
                                                   >> 253  * the "custom_data" field of the FS node is used to store the total
                                                   >> 254  * number of pages available
                                                   >> 255  */
                                                   >> 256 #define GET_DEV_SIZE(fsnode) \
                                                   >> 257   ((sos_size_t)(fsnode)->custom_data)
                                                   >> 258 
                                                   >> 259 static sos_ret_t dev_mem_fs_open(struct sos_fs_node        * fsnode,
                                                   >> 260                                  struct sos_fs_opened_file * of,
                                                   >> 261                                  void * chardev_class_custom_data)
                                                   >> 262 {
                                                   >> 263   /* Make sure the device is supported by this driver and compute its
                                                   >> 264      "size" (use the custom_data field to store it) */
                                                   >> 265   switch (fsnode->dev_id.device_instance)
                                                   >> 266     {
                                                   >> 267       /* For /dev/kmem, go to the end of the kernel mapping */
                                                   >> 268     case SOS_CHARDEV_KMEM_MINOR:
                                                   >> 269       fsnode->custom_data = (void*)SOS_PAGING_BASE_USER_ADDRESS;
                                                   >> 270       return SOS_OK;
                                                   >> 271       break;
                                                   >> 272 
                                                   >> 273       /* For /dev/mem, go to the end of physical memory */
                                                   >> 274     case SOS_CHARDEV_PHYSMEM_MINOR:
                                                   >> 275       {
                                                   >> 276         sos_size_t ram_pages = 0;
                                                   >> 277         sos_physmem_get_state(& ram_pages, NULL);
                                                   >> 278         fsnode->custom_data = (void*)(ram_pages << SOS_PAGE_SHIFT);
                                                   >> 279       }
                                                   >> 280       return SOS_OK;
                                                   >> 281       break;
                                                   >> 282 
                                                   >> 283     default:
                                                   >> 284       break;
                                                   >> 285     }
                                                   >> 286 
                                                   >> 287   return -SOS_ENODEV;
                                                   >> 288 }
                                                   >> 289 
                                                   >> 290 
                                                   >> 291 static sos_ret_t dev_mem_fs_seek(struct sos_fs_opened_file *this,
                                                   >> 292                                  sos_lsoffset_t offset,
                                                   >> 293                                  sos_seek_whence_t whence,
                                                   >> 294                                  /* out */ sos_lsoffset_t * result_position)
                                                   >> 295 {
                                                   >> 296   /* Make sure the device is supported by this driver */
                                                   >> 297   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(this->direntry);
                                                   >> 298 
                                                   >> 299   /* Artificiallly update the position in the "file" */
                                                   >> 300   sos_lsoffset_t ref_offs;
                                                   >> 301   sos_lsoffset_t dev_size = GET_DEV_SIZE(fsnode);
                                                   >> 302 
                                                   >> 303   *result_position = this->position;
                                                   >> 304   switch (whence)
                                                   >> 305     {
                                                   >> 306     case SOS_SEEK_SET:
                                                   >> 307       ref_offs = 0;
                                                   >> 308       break;
                                                   >> 309 
                                                   >> 310     case SOS_SEEK_CUR:
                                                   >> 311       ref_offs = this->position;
                                                   >> 312       break;
                                                   >> 313 
                                                   >> 314     case SOS_SEEK_END:
                                                   >> 315       ref_offs = dev_size;
                                                   >> 316       break;
                                                   >> 317 
                                                   >> 318     default:
                                                   >> 319       return -SOS_EINVAL;
                                                   >> 320     }
                                                   >> 321 
                                                   >> 322   /* Forbid accesses "before" the start of the device */
                                                   >> 323   if (offset < -ref_offs)
                                                   >> 324     return -SOS_EINVAL;
                                                   >> 325 
                                                   >> 326   /* Forbid accesses "after" the end of the device */
                                                   >> 327   else if (ref_offs + offset > dev_size)
                                                   >> 328     return -SOS_EINVAL;
                                                   >> 329   
                                                   >> 330   this->position = ref_offs + offset;
                                                   >> 331   *result_position = this->position;
                                                   >> 332   return SOS_OK;
                                                   >> 333 }
                                                   >> 334 
                                                   >> 335 
                                                   >> 336 typedef enum { DO_READ, DO_WRITE } dev_mem_access_type_t;
                                                   >> 337 static sos_ret_t dev_mem_fs_access(struct sos_fs_opened_file *this,
                                                   >> 338                                    sos_uaddr_t user_buf,
                                                   >> 339                                    sos_size_t * /* in/out */len,
                                                   >> 340                                    dev_mem_access_type_t access_type)
                                                   >> 341 {
                                                   >> 342   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(this->direntry);
                                                   >> 343   sos_vaddr_t   physmem_transfer_kernel_page = 0; /* Used for /dev/mem only */
                                                   >> 344   sos_uoffset_t offs;
                                                   >> 345   sos_size_t    accesslen = 0;
                                                   >> 346 
                                                   >> 347   /* Readjust copy length to match the size of the device */
                                                   >> 348   if (this->position + *len >= GET_DEV_SIZE(fsnode))
                                                   >> 349     *len = GET_DEV_SIZE(fsnode) - this->position;
                                                   >> 350 
                                                   >> 351   /* Ignore zero-size requests */
                                                   >> 352   if (*len <= 0)
                                                   >> 353     return SOS_OK;
                                                   >> 354 
                                                   >> 355   /* For /dev/mem device, prepare a kernel page to copy the physical
                                                   >> 356      pages before transferring to user space */
                                                   >> 357   if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev_id.device_instance)
                                                   >> 358     {
                                                   >> 359       physmem_transfer_kernel_page = sos_kmem_vmm_alloc(1, 0);
                                                   >> 360       if (! physmem_transfer_kernel_page)
                                                   >> 361         return -SOS_ENOMEM;
                                                   >> 362     }
                                                   >> 363 
                                                   >> 364   /* Try to copy the data in page-size chunks */
                                                   >> 365   offs = this->position;
                                                   >> 366   while (offs < this->position + *len)
                                                   >> 367     {
                                                   >> 368       /* Retrieve page address of data in kernel memory */
                                                   >> 369       sos_uoffset_t page_boundary = SOS_PAGE_ALIGN_INF(offs);
                                                   >> 370       sos_vaddr_t   page_vaddr;
                                                   >> 371       sos_uoffset_t offset_in_page;
                                                   >> 372       sos_uoffset_t accesslen_in_page;
                                                   >> 373       sos_ret_t retval;
                                                   >> 374 
                                                   >> 375       /* For /dev/mem device, we need to map the page in kernel memory
                                                   >> 376          before */
                                                   >> 377       if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev_id.device_instance)
                                                   >> 378         {
                                                   >> 379           retval = sos_paging_map(page_boundary,
                                                   >> 380                                   physmem_transfer_kernel_page,
                                                   >> 381                                   FALSE,
                                                   >> 382                                   (access_type==DO_WRITE)?
                                                   >> 383                                     SOS_VM_MAP_PROT_WRITE
                                                   >> 384                                     :SOS_VM_MAP_PROT_READ);
                                                   >> 385           if (SOS_OK != retval)
                                                   >> 386             break;
                                                   >> 387 
                                                   >> 388           page_vaddr = physmem_transfer_kernel_page;
                                                   >> 389         }
                                                   >> 390       /* For /dev/kmem device, the page should already be in kernel space */
                                                   >> 391       else if (! sos_kmem_vmm_is_valid_vaddr(page_boundary))
                                                   >> 392         break; /* No: page is not mapped in kernel space ! */
                                                   >> 393       else
                                                   >> 394         page_vaddr = page_boundary; /* Yes, page is mapped */
                                                   >> 395 
                                                   >> 396       /* Now copy the data from kernel to user space */
                                                   >> 397       offset_in_page = offs - page_boundary;
                                                   >> 398       accesslen_in_page  = SOS_PAGE_SIZE - offset_in_page;
                                                   >> 399       if (accesslen + accesslen_in_page > *len)
                                                   >> 400         accesslen_in_page = *len - accesslen;
                                                   >> 401 
                                                   >> 402       if (access_type==DO_WRITE)
                                                   >> 403         retval = sos_memcpy_from_user(page_vaddr + offset_in_page,
                                                   >> 404                                       user_buf + accesslen,
                                                   >> 405                                       accesslen_in_page);
                                                   >> 406       else
                                                   >> 407         retval = sos_memcpy_to_user(user_buf + accesslen,
                                                   >> 408                                     page_vaddr + offset_in_page,
                                                   >> 409                                     accesslen_in_page);
                                                   >> 410       
                                                   >> 411       /* Now, for /dev/mem, unmap the page from kernel */
                                                   >> 412       if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev_id.device_instance)
                                                   >> 413         sos_paging_unmap(physmem_transfer_kernel_page);
                                                   >> 414       
                                                   >> 415       /* Go to next page if possible */
                                                   >> 416       if (retval < 0)
                                                   >> 417         break;
                                                   >> 418 
                                                   >> 419       accesslen += retval;
                                                   >> 420       /* If transfer was interrupted, stop here */
                                                   >> 421       if (retval < accesslen_in_page)
                                                   >> 422         break;
                                                   >> 423 
                                                   >> 424       /* Go on to next page */
                                                   >> 425       offs = page_boundary + SOS_PAGE_SIZE;
                                                   >> 426     }
                                                   >> 427 
                                                   >> 428   /* Release the temporary page for physical mem transfers */
                                                   >> 429   if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev_id.device_instance)
                                                   >> 430     sos_kmem_vmm_free(physmem_transfer_kernel_page);
                                                   >> 431 
                                                   >> 432   /* Update the position in the "file" */
                                                   >> 433   *len = accesslen;
                                                   >> 434   this->position += accesslen;
                                                   >> 435   return SOS_OK;
                                                   >> 436 }
                                                   >> 437 
                                                   >> 438 
                                                   >> 439 static sos_ret_t dev_mem_fs_read(struct sos_fs_opened_file *this,
                                                   >> 440                                    sos_uaddr_t dest_buf,
                                                   >> 441                                    sos_size_t * /* in/out */len)
                                                   >> 442 {
                                                   >> 443   return dev_mem_fs_access(this, dest_buf, len, DO_READ);
                                                   >> 444 }
                                                   >> 445 
                                                   >> 446 
                                                   >> 447 static sos_ret_t dev_mem_fs_write(struct sos_fs_opened_file *this,
                                                   >> 448                                   sos_uaddr_t src_buf,
                                                   >> 449                                   sos_size_t * /* in/out */len)
                                                   >> 450 {
                                                   >> 451   return dev_mem_fs_access(this, src_buf, len, DO_WRITE);
                                                   >> 452 }
                                                   >> 453 
                                                   >> 454 
                                                   >> 455 static sos_ret_t dev_mem_fs_mmap(struct sos_fs_opened_file *this,
                                                   >> 456                                  sos_uaddr_t *uaddr, sos_size_t size,
                                                   >> 457                                  sos_ui32_t access_rights,
                                                   >> 458                                  sos_ui32_t flags,
                                                   >> 459                                  sos_luoffset_t offset)
                                                   >> 460 {
                                                   >> 461   struct sos_fs_node * fsnode = sos_fs_nscache_get_fs_node(this->direntry);
                                                   >> 462   if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev_id.device_instance)
                                                   >> 463     return sos_dev_physmem_map(sos_process_get_address_space(this->owner),
                                                   >> 464                                uaddr, size, offset, access_rights, flags);
                                                   >> 465 
                                                   >> 466   return sos_dev_kmem_map(sos_process_get_address_space(this->owner),
                                                   >> 467                           uaddr, size, offset, access_rights, flags);
                                                   >> 468 }
                                                   >> 469 
                                                   >> 470 
                                                   >> 471 static struct sos_chardev_ops dev_mem_fs_ops
                                                   >> 472   = (struct sos_chardev_ops) {
                                                   >> 473     .open  = dev_mem_fs_open,
                                                   >> 474     .close = NULL,
                                                   >> 475     .seek  = dev_mem_fs_seek,
                                                   >> 476     .read  = dev_mem_fs_read,
                                                   >> 477     .write = dev_mem_fs_write,
                                                   >> 478     .mmap  = dev_mem_fs_mmap,
                                                   >> 479     .fcntl = NULL,
                                                   >> 480     .ioctl = NULL
                                                   >> 481   };
                                                   >> 482 
                                                   >> 483 
                                                   >> 484 sos_ret_t sos_dev_mem_chardev_setup()
                                                   >> 485 {
                                                   >> 486   return sos_chardev_register_class(SOS_CHARDEV_MEM_MAJOR,
                                                   >> 487                                     & dev_mem_fs_ops,
                                                   >> 488                                     NULL);
241 }                                                 489 }
                                                      

source navigation ] diff markup ] identifier search ] general search ]