source: mainline/uspace/rd/rd.c@ 84947a4

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

Improve the rd task (not tested):

  • allow more connections
  • support write operation
  • support concurrent requests
  • sanity checks
  • add comments

Please review.

  • Property mode set to 100644
File size: 5.5 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
59/**
60 * This futex protects the ramdisk's data.
61 * If we were to serve multiple requests (read + write or several writes)
62 * concurrently (i.e. from two or more threads), each read and write needs to be
63 * protected by this futex.
64 */
65atomic_t rd_futex = FUTEX_INITIALIZER;
66
67/** Handle one connection to ramdisk.
68 *
69 * @param iid Hash of the request that opened the connection.
70 * @param icall Call data of the request that opened the connection.
71 */
72static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
73{
74 ipc_callid_t callid;
75 ipc_call_t call;
76 int retval;
77 uintptr_t fs_va = NULL;
78 ipcarg_t offset;
79
80 /*
81 * We allocate VA for communication per connection.
82 * This allows us to potentionally have more clients and work
83 * concurrently.
84 */
85 fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE));
86 if (!fs_va) {
87 /*
88 * Hang up the phone if we cannot proceed any further.
89 * This is the answer to the call that opened the connection.
90 */
91 ipc_answer_fast(iid, EHANGUP, 0, 0);
92 return;
93 } else {
94 /*
95 * Answer the first IPC_M_CONNECT_ME_TO call.
96 * Return supported block size as ARG1.
97 */
98 ipc_answer_fast(iid, EOK, BLOCK_SIZE, 0);
99 }
100
101 /*
102 * Now we wait for the client to send us its communication as_area.
103 */
104 callid = async_get_call(&call);
105 if (IPC_GET_METHOD(call) == IPC_M_AS_AREA_SEND) {
106 if (IPC_GET_ARG1(call) >= (ipcarg_t) BLOCK_SIZE) {
107 /*
108 * The client sends an as_area that can absorb the whole
109 * block.
110 */
111 ipc_answer_fast(callid, EOK, (uintptr_t) fs_va, 0);
112 } else {
113 /*
114 * The client offered as_area too small.
115 * Close the connection.
116 */
117 ipc_answer_fast(callid, EHANGUP, 0, 0);
118 return;
119 }
120 } else {
121 /*
122 * The client doesn't speak the same protocol.
123 * At this point we can't handle protocol variations.
124 * Close the connection.
125 */
126 ipc_answer_fast(callid, EHANGUP, 0, 0);
127 return;
128 }
129
130 while (1) {
131 callid = async_get_call(&call);
132 switch (IPC_GET_METHOD(call)) {
133 case IPC_M_PHONE_HUNGUP:
134 /*
135 * The other side has hung up.
136 * Answer the message and exit the pseudo thread.
137 */
138 ipc_answer_fast(callid, EOK, 0, 0);
139 return;
140 case RD_READ_BLOCK:
141 offset = IPC_GET_ARG1(call);
142 futex_down(&rd_futex);
143 memcpy((void *) fs_va, rd_addr + offset, BLOCK_SIZE);
144 futex_up(&rd_futex);
145 retval = EOK;
146 break;
147 case RD_WRITE_BLOCK:
148 offset = IPC_GET_ARG1(call);
149 futex_up(&rd_futex);
150 memcpy(rd_addr + offset, (void *) fs_va, BLOCK_SIZE);
151 futex_down(&rd_futex);
152 retval = EOK;
153 break;
154 default:
155 /*
156 * The client doesn't speak the same protocol.
157 * Instead of closing the connection, we just ignore
158 * the call. This can be useful if the client uses a
159 * newer version of the protocol.
160 */
161 retval = EINVAL;
162 break;
163 }
164 ipc_answer_fast(callid, retval, 0, 0);
165 }
166}
167
168/** Prepare the ramdisk image for operation. */
169static bool rd_init(void)
170{
171 int retval, flags;
172
173 size_t rd_size = sysinfo_value("rd.size");
174 void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
175
176 if (rd_size == 0)
177 return false;
178
179 rd_addr = as_get_mappable_page(rd_size);
180
181 flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
182 retval = physmem_map(rd_ph_addr, rd_addr,
183 ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
184
185 if (retval < 0)
186 return false;
187 return true;
188}
189
190int main(int argc, char **argv)
191{
192 if (rd_init()) {
193 ipcarg_t phonead;
194
195 async_set_client_connection(rd_connection);
196
197 /* Register service at nameserver */
198 if (ipc_connect_to_me(PHONE_NS, SERVICE_RD, 0, &phonead) != 0)
199 return -1;
200
201 async_manager();
202
203 /* Never reached */
204 return 0;
205 }
206
207 return -1;
208}
209
210/**
211 * @}
212 */
Note: See TracBrowser for help on using the repository browser.