3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
19 * This is an implementation of memory regions that can be used to read/write
20 * channel memory (in main memory of the host system) from code running in
21 * a virtual partition.
24 #include "memregion.h"
26 #define MYDRVNAME "memregion"
36 static BOOL mapit(struct memregion *memregion);
37 static void unmapit(struct memregion *memregion);
40 visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes)
42 struct memregion *rc = NULL;
43 struct memregion *memregion;
45 memregion = kzalloc(sizeof(*memregion), GFP_KERNEL | __GFP_NORETRY);
46 if (memregion == NULL)
49 memregion->physaddr = physaddr;
50 memregion->nbytes = nbytes;
51 memregion->overlapped = FALSE;
52 if (!mapit(memregion)) {
59 visor_memregion_destroy(memregion);
64 EXPORT_SYMBOL_GPL(visor_memregion_create);
67 visor_memregion_create_overlapped(struct memregion *parent, ulong offset,
70 struct memregion *memregion = NULL;
75 if (parent->mapped == NULL)
78 if ((offset >= parent->nbytes) ||
79 ((offset + nbytes) >= parent->nbytes))
82 memregion = kzalloc(sizeof(*memregion), GFP_KERNEL|__GFP_NORETRY);
83 if (memregion == NULL)
86 memregion->physaddr = parent->physaddr + offset;
87 memregion->nbytes = nbytes;
88 memregion->mapped = ((u8 __iomem *)(parent->mapped)) + offset;
89 memregion->requested = FALSE;
90 memregion->overlapped = TRUE;
93 EXPORT_SYMBOL_GPL(visor_memregion_create_overlapped);
96 mapit(struct memregion *memregion)
98 ulong physaddr = (ulong)(memregion->physaddr);
99 ulong nbytes = memregion->nbytes;
101 memregion->requested = FALSE;
102 if (request_mem_region(physaddr, nbytes, MYDRVNAME))
103 memregion->requested = TRUE;
104 memregion->mapped = ioremap_cache(physaddr, nbytes);
105 if (!memregion->mapped)
111 unmapit(struct memregion *memregion)
113 if (memregion->mapped != NULL) {
114 iounmap(memregion->mapped);
115 memregion->mapped = NULL;
117 if (memregion->requested) {
118 release_mem_region((ulong)(memregion->physaddr),
120 memregion->requested = FALSE;
125 visor_memregion_get_physaddr(struct memregion *memregion)
127 return memregion->physaddr;
129 EXPORT_SYMBOL_GPL(visor_memregion_get_physaddr);
132 visor_memregion_get_nbytes(struct memregion *memregion)
134 return memregion->nbytes;
136 EXPORT_SYMBOL_GPL(visor_memregion_get_nbytes);
139 visor_memregion_get_pointer(struct memregion *memregion)
141 return memregion->mapped;
143 EXPORT_SYMBOL_GPL(visor_memregion_get_pointer);
146 visor_memregion_resize(struct memregion *memregion, ulong newsize)
148 if (newsize == memregion->nbytes)
150 if (memregion->overlapped)
151 /* no error check here - we no longer know the
154 memregion->nbytes = newsize;
157 memregion->nbytes = newsize;
158 if (!mapit(memregion))
163 EXPORT_SYMBOL_GPL(visor_memregion_resize);
166 memregion_readwrite(BOOL is_write,
167 struct memregion *memregion, ulong offset,
168 void *local, ulong nbytes)
170 if (offset + nbytes > memregion->nbytes)
174 memcpy_toio(memregion->mapped + offset, local, nbytes);
176 memcpy_fromio(local, memregion->mapped + offset, nbytes);
182 visor_memregion_read(struct memregion *memregion, ulong offset, void *dest,
185 return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
187 EXPORT_SYMBOL_GPL(visor_memregion_read);
190 visor_memregion_write(struct memregion *memregion, ulong offset, void *src,
193 return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
195 EXPORT_SYMBOL_GPL(visor_memregion_write);
198 visor_memregion_destroy(struct memregion *memregion)
200 if (memregion == NULL)
202 if (!memregion->overlapped)
206 EXPORT_SYMBOL_GPL(visor_memregion_destroy);