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
RevLine 
[228b135]1/*
[ff3a34b]2 * Copyright (c) 2007 Michal Konopa
3 * Copyright (c) 2007 Martin Jelen
4 * Copyright (c) 2007 Peter Majer
[84947a4]5 * Copyright (c) 2007 Jakub Jermar
[228b135]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>
[7c34822e]44#include <sysinfo.h>
45#include <as.h>
46#include <ddi.h>
47#include <align.h>
48#include <bool.h>
[228b135]49#include <errno.h>
50#include <async.h>
[ff3a34b]51#include <align.h>
52#include <async.h>
[84947a4]53#include <futex.h>
[ff3a34b]54#include "rd.h"
[228b135]55
[84947a4]56/** Pointer to the ramdisk's image. */
[ff3a34b]57static void *rd_addr;
[3ae470a]58/** Size of the ramdisk. */
59static size_t rd_size;
[228b135]60
[84947a4]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 */
[228b135]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;
[3ae470a]79 void *fs_va = NULL;
[ff3a34b]80 ipcarg_t offset;
[228b135]81
[84947a4]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 */
[b74959bd]93 ipc_answer_0(iid, EHANGUP);
[84947a4]94 return;
95 } else {
96 /*
97 * Answer the first IPC_M_CONNECT_ME_TO call.
98 * Return supported block size as ARG1.
99 */
[b74959bd]100 ipc_answer_1(iid, EOK, BLOCK_SIZE);
[84947a4]101 }
102
103 /*
104 * Now we wait for the client to send us its communication as_area.
105 */
[27d293a]106 size_t size;
107 if (ipc_share_out_receive(&callid, &size, NULL)) {
108 if (size >= BLOCK_SIZE) {
[84947a4]109 /*
110 * The client sends an as_area that can absorb the whole
111 * block.
112 */
[215e375]113 (void) ipc_share_out_finalize(callid, fs_va);
[84947a4]114 } else {
115 /*
116 * The client offered as_area too small.
117 * Close the connection.
118 */
[b74959bd]119 ipc_answer_0(callid, EHANGUP);
[84947a4]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 */
[b74959bd]128 ipc_answer_0(callid, EHANGUP);
[84947a4]129 return;
130 }
131
[228b135]132 while (1) {
133 callid = async_get_call(&call);
134 switch (IPC_GET_METHOD(call)) {
[8b243f2]135 case IPC_M_PHONE_HUNGUP:
[84947a4]136 /*
137 * The other side has hung up.
[0f78e74]138 * Answer the message and exit the fibril.
[84947a4]139 */
[b74959bd]140 ipc_answer_0(callid, EOK);
[8b243f2]141 return;
[84947a4]142 case RD_READ_BLOCK:
143 offset = IPC_GET_ARG1(call);
[3ae470a]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 }
[84947a4]151 futex_down(&rd_futex);
[3ae470a]152 memcpy(fs_va, rd_addr + offset, BLOCK_SIZE);
[84947a4]153 futex_up(&rd_futex);
154 retval = EOK;
155 break;
156 case RD_WRITE_BLOCK:
[8b243f2]157 offset = IPC_GET_ARG1(call);
[3ae470a]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 }
[84947a4]165 futex_up(&rd_futex);
[3ae470a]166 memcpy(rd_addr + offset, fs_va, BLOCK_SIZE);
[84947a4]167 futex_down(&rd_futex);
[8b243f2]168 retval = EOK;
169 break;
170 default:
[84947a4]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 */
[8b243f2]177 retval = EINVAL;
[84947a4]178 break;
[228b135]179 }
[b74959bd]180 ipc_answer_0(callid, retval);
[8b243f2]181 }
[228b135]182}
183
[84947a4]184/** Prepare the ramdisk image for operation. */
[7c34822e]185static bool rd_init(void)
[228b135]186{
[ff3a34b]187 int retval, flags;
188
[3ae470a]189 rd_size = sysinfo_value("rd.size");
[8b243f2]190 void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
[7c34822e]191
192 if (rd_size == 0)
193 return false;
[228b135]194
[ff3a34b]195 rd_addr = as_get_mappable_page(rd_size);
[228b135]196
[ff3a34b]197 flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
[8b243f2]198 retval = physmem_map(rd_ph_addr, rd_addr,
199 ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
[ff3a34b]200
201 if (retval < 0)
202 return false;
[7c34822e]203 return true;
204}
[228b135]205
[7c34822e]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 */
[38c706cc]214 if (ipc_connect_to_me(PHONE_NS, SERVICE_RD, 0, 0, &phonead) != 0)
[7c34822e]215 return -1;
216
217 async_manager();
218
219 /* Never reached */
220 return 0;
221 }
222
223 return -1;
[228b135]224}
225
226/**
227 * @}
228 */
Note: See TracBrowser for help on using the repository browser.