source: mainline/uspace/srv/rd/rd.c@ 215e375

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 215e375 was 215e375, checked in by Jakub Jermar <jakub@…>, 18 years ago

The IPC_M_SHARE_* and IPC_M_DATA_* calls pass through 3 stages. Rename the send,
receive and deliver wrappers to names ending with 'start', 'receive' and
'finalize', respectively. This should make it clearer for dummies.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2007 Michal Konopa
3 * Copyright (c) 2007 Martin Jelen
4 * Copyright (c) 2007 Peter Majer
5 * Copyright (c) 2007 Jakub Jermar
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * - The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/** @addtogroup rd
33 * @{
34 */
35
36/**
37 * @file rd.c
38 * @brief Initial RAM disk for HelenOS.
39 */
40
41#include <ipc/ipc.h>
42#include <ipc/services.h>
43#include <ipc/ns.h>
44#include <sysinfo.h>
45#include <as.h>
46#include <ddi.h>
47#include <align.h>
48#include <bool.h>
49#include <errno.h>
50#include <async.h>
51#include <align.h>
52#include <async.h>
53#include <futex.h>
54#include "rd.h"
55
56/** Pointer to the ramdisk's image. */
57static void *rd_addr;
58/** Size of the ramdisk. */
59static size_t rd_size;
60
61/**
62 * This futex protects the ramdisk's data.
63 * If we were to serve multiple requests (read + write or several writes)
64 * concurrently (i.e. from two or more threads), each read and write needs to be
65 * protected by this futex.
66 */
67atomic_t rd_futex = FUTEX_INITIALIZER;
68
69/** Handle one connection to ramdisk.
70 *
71 * @param iid Hash of the request that opened the connection.
72 * @param icall Call data of the request that opened the connection.
73 */
74static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
75{
76 ipc_callid_t callid;
77 ipc_call_t call;
78 int retval;
79 void *fs_va = NULL;
80 ipcarg_t offset;
81
82 /*
83 * We allocate VA for communication per connection.
84 * This allows us to potentionally have more clients and work
85 * concurrently.
86 */
87 fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE));
88 if (!fs_va) {
89 /*
90 * Hang up the phone if we cannot proceed any further.
91 * This is the answer to the call that opened the connection.
92 */
93 ipc_answer_0(iid, EHANGUP);
94 return;
95 } else {
96 /*
97 * Answer the first IPC_M_CONNECT_ME_TO call.
98 * Return supported block size as ARG1.
99 */
100 ipc_answer_1(iid, EOK, BLOCK_SIZE);
101 }
102
103 /*
104 * Now we wait for the client to send us its communication as_area.
105 */
106 size_t size;
107 if (ipc_share_out_receive(&callid, &size, NULL)) {
108 if (size >= BLOCK_SIZE) {
109 /*
110 * The client sends an as_area that can absorb the whole
111 * block.
112 */
113 (void) ipc_share_out_finalize(callid, fs_va);
114 } else {
115 /*
116 * The client offered as_area too small.
117 * Close the connection.
118 */
119 ipc_answer_0(callid, EHANGUP);
120 return;
121 }
122 } else {
123 /*
124 * The client doesn't speak the same protocol.
125 * At this point we can't handle protocol variations.
126 * Close the connection.
127 */
128 ipc_answer_0(callid, EHANGUP);
129 return;
130 }
131
132 while (1) {
133 callid = async_get_call(&call);
134 switch (IPC_GET_METHOD(call)) {
135 case IPC_M_PHONE_HUNGUP:
136 /*
137 * The other side has hung up.
138 * Answer the message and exit the fibril.
139 */
140 ipc_answer_0(callid, EOK);
141 return;
142 case RD_READ_BLOCK:
143 offset = IPC_GET_ARG1(call);
144 if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
145 /*
146 * Reading past the end of the device.
147 */
148 retval = ELIMIT;
149 break;
150 }
151 futex_down(&rd_futex);
152 memcpy(fs_va, rd_addr + offset, BLOCK_SIZE);
153 futex_up(&rd_futex);
154 retval = EOK;
155 break;
156 case RD_WRITE_BLOCK:
157 offset = IPC_GET_ARG1(call);
158 if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
159 /*
160 * Writing past the end of the device.
161 */
162 retval = ELIMIT;
163 break;
164 }
165 futex_up(&rd_futex);
166 memcpy(rd_addr + offset, fs_va, BLOCK_SIZE);
167 futex_down(&rd_futex);
168 retval = EOK;
169 break;
170 default:
171 /*
172 * The client doesn't speak the same protocol.
173 * Instead of closing the connection, we just ignore
174 * the call. This can be useful if the client uses a
175 * newer version of the protocol.
176 */
177 retval = EINVAL;
178 break;
179 }
180 ipc_answer_0(callid, retval);
181 }
182}
183
184/** Prepare the ramdisk image for operation. */
185static bool rd_init(void)
186{
187 int retval, flags;
188
189 rd_size = sysinfo_value("rd.size");
190 void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
191
192 if (rd_size == 0)
193 return false;
194
195 rd_addr = as_get_mappable_page(rd_size);
196
197 flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
198 retval = physmem_map(rd_ph_addr, rd_addr,
199 ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
200
201 if (retval < 0)
202 return false;
203 return true;
204}
205
206int main(int argc, char **argv)
207{
208 if (rd_init()) {
209 ipcarg_t phonead;
210
211 async_set_client_connection(rd_connection);
212
213 /* Register service at nameserver */
214 if (ipc_connect_to_me(PHONE_NS, SERVICE_RD, 0, 0, &phonead) != 0)
215 return -1;
216
217 async_manager();
218
219 /* Never reached */
220 return 0;
221 }
222
223 return -1;
224}
225
226/**
227 * @}
228 */
Note: See TracBrowser for help on using the repository browser.