FreeNOS
MemoryChannel.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <Assert.h>
19#include <Log.h>
20#include <MemoryBlock.h>
21#include "MemoryChannel.h"
22
23MemoryChannel::MemoryChannel(const Channel::Mode mode, const Size messageSize)
24 : Channel(mode, messageSize)
25 , m_maximumMessages((PAGESIZE / messageSize) - 1U)
26{
27 assert(messageSize >= sizeof(RingHead));
28 assert(messageSize < (PAGESIZE / 2));
29
30 reset(true);
31}
32
36
38{
39 if (hardReset)
40 {
41 MemoryBlock::set(&m_head, 0, sizeof(m_head));
42 }
43 else if (m_mode == Channel::Producer)
44 {
45 m_data.read(0, sizeof(m_head), &m_head);
46 }
47 else if (m_mode == Channel::Consumer)
48 {
49 m_feedback.read(0, sizeof(m_head), &m_head);
50 }
51 return Success;
52}
53
55 const Address feedback,
56 const bool hardReset)
57{
58 m_data.setBase(data);
59 m_feedback.setBase(feedback);
60
61 return reset(hardReset);
62}
63
65 const Address feedback,
66 const bool hardReset)
67{
70
71 switch (m_mode)
72 {
73 case Consumer:
74 feedAccess |= Memory::Writable;
75 break;
76
77 case Producer:
78 dataAccess |= Memory::Writable;
79 break;
80 }
81
82 IO::Result result = m_data.map(data, PAGESIZE, dataAccess);
83 if (result != IO::Success)
84 {
85 ERROR("failed to map data physical address " << (void*)data << ": " << (int)result);
86 return IOError;
87 }
88
89 result = m_feedback.map(feedback, PAGESIZE, feedAccess);
90 if (result != IO::Success)
91 {
92 ERROR("failed to map feedback physical address " << (void*)feedback << ": " << (int)result);
93 return IOError;
94 }
95
96 return reset(hardReset);
97}
98
100{
101 Result result = Success;
102
103 if (m_data.unmap() != IO::Success)
104 {
105 result = IOError;
106 }
107
109 {
110 result = IOError;
111 }
112
113 return result;
114}
115
117{
118 RingHead head;
119
120 // Read the current ring head
121 m_data.read(0, sizeof(head), &head);
122
123 // Check if a message is present
124 if (head.index == m_head.index)
125 return NotFound;
126
127 // Read one message
129
130 // Increment head index
132
133 // Update read index
134 m_feedback.write(0, sizeof(m_head), &m_head);
135 return Success;
136}
137
139{
140 RingHead reader;
141
142 // Read current ring head
143 m_feedback.read(0, sizeof(RingHead), &reader);
144
145 // Check if buffer space is available for the message
146 if (((m_head.index + 1) % m_maximumMessages) == reader.index)
147 return ChannelFull;
148
149 // write the message
151
152 // Increment write index
154 m_data.write(0, sizeof(m_head), &m_head);
155 return Success;
156}
157
159{
160#ifndef INTEL
161 if (m_mode == Producer)
163 else if (m_mode == Consumer)
165#endif /* INTEL */
166
167 return Success;
168}
169
171{
172 // Flush caches in usermode via the kernel.
173 if (!isKernel)
174 {
175#ifndef __HOST__
176 Memory::Range range;
177 range.virt = page;
178
179 const API::Result result = VMCtl(SELF, CacheClean, &range);
180 if (result != API::Success)
181 {
182 ERROR("failed to clean data cache at " << (void *) page <<
183 ": result = " << (int) result);
184 return IOError;
185 }
186#endif /* __HOST__ */
187 }
188 // Clean both pages from the cache directly
189 else
190 {
191 Arch::Cache cache;
192 cache.cleanData(page);
193 }
194
195 return Success;
196}
Result
Enumeration of generic kernel API result codes.
Definition API.h:69
@ Success
Definition API.h:70
ARMv6 cache management implementation.
Definition ARMCacheV6.h:43
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition ARMIO.h:46
u32 read(u32 reg) const
read from memory mapped I/O register
Definition ARMIO.h:62
virtual Result cleanData(Address addr)
Clean one data page.
Definition Cache.cpp:20
Unidirectional point-to-point messaging channel.
Definition Channel.h:35
Mode
Channel modes.
Definition Channel.h:57
@ Consumer
Definition Channel.h:59
@ Producer
Definition Channel.h:58
const Mode m_mode
Channel mode.
Definition Channel.h:114
const Size m_messageSize
Message size.
Definition Channel.h:117
Result
Result codes.
Definition Channel.h:42
@ Success
Definition Channel.h:43
@ ChannelFull
Definition Channel.h:48
@ IOError
Definition Channel.h:47
@ NotFound
Definition Channel.h:49
void setBase(const Address base)
Set memory I/O base offset.
Definition IO.cpp:33
Result map(Address phys, Size size=4096, Memory::Access access=Memory::Readable|Memory::Writable|Memory::User)
Map I/O address space.
Definition IO.cpp:38
Address getBase() const
Get memory I/O base offset.
Definition IO.cpp:28
Result
Result codes.
Definition IO.h:43
@ Success
Definition IO.h:44
Result unmap()
Unmap I/O address space.
Definition IO.cpp:70
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Result setPhysical(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by physical address.
virtual Result flush()
Flush message buffers.
Result unmap()
Unmap memory pages from virtual address space.
MemoryChannel(const Mode mode, const Size messageSize)
Constructor.
Result flushPage(const Address page) const
Flush memory page.
Arch::IO m_data
The data page.
const Size m_maximumMessages
Maximum number of messages that can be stored.
virtual Result read(void *buffer)
Read a message.
virtual ~MemoryChannel()
Destructor.
virtual Result write(const void *buffer)
Write a message.
RingHead m_head
Local RingHead.
Result reset(const bool hardReset)
Reset to initial state.
Arch::IO m_feedback
The feedback page.
Result setVirtual(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by virtual address.
#define SELF
Definition ProcessID.h:35
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition VMCtl.h:61
@ CacheClean
Definition VMCtl.h:46
#define PAGESIZE
ARM uses 4K pages.
Definition ARMConstant.h:97
C uint isKernel
Non-zero if this executable is linked as the kernel.
#define assert(exp)
Insert program diagnostics.
Definition assert.h:60
unsigned long Address
A memory address.
Definition Types.h:131
#define ERROR(msg)
Output an error message.
Definition Log.h:61
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
Access
Memory access flags.
Definition Memory.h:39
@ User
Definition Memory.h:44
@ Readable
Definition Memory.h:41
@ Writable
Definition Memory.h:42
Defines in-memory ring header.
Size index
Index where the ring buffer starts.
Memory range.
Definition Memory.h:56
Address virt
Virtual address.
Definition Memory.h:57