source: mainline/uspace/srv/bd/rd/rd.c@ 4c5deac

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4c5deac was b688fd8, checked in by Martin Decky <martin@…>, 10 years ago

gradually introduce async ports, initial phase

The initial phase is to reimplement the traditional async client connections as an untyped fallback port. This creates the possibility to introduce ports typed by interface type gradually in later changesets.

  • Property mode set to 100644
File size: 5.8 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/services.h>
42#include <ipc/ns.h>
43#include <sysinfo.h>
44#include <as.h>
45#include <bd_srv.h>
46#include <ddi.h>
47#include <align.h>
48#include <stdbool.h>
49#include <errno.h>
50#include <async.h>
51#include <align.h>
52#include <async.h>
53#include <fibril_synch.h>
54#include <stdio.h>
55#include <loc.h>
56#include <macros.h>
57#include <inttypes.h>
58
59#define NAME "rd"
60
61/** Pointer to the ramdisk's image */
62static void *rd_addr = AS_AREA_ANY;
63
64/** Size of the ramdisk */
65static size_t rd_size;
66
67/** Block size */
68static const size_t block_size = 512;
69
70static int rd_open(bd_srvs_t *, bd_srv_t *);
71static int rd_close(bd_srv_t *);
72static int rd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
73static int rd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
74static int rd_get_block_size(bd_srv_t *, size_t *);
75static int rd_get_num_blocks(bd_srv_t *, aoff64_t *);
76
77/** This rwlock protects the ramdisk's data.
78 *
79 * If we were to serve multiple requests (read + write or several writes)
80 * concurrently (i.e. from two or more threads), each read and write needs to
81 * be protected by this rwlock.
82 *
83 */
84static fibril_rwlock_t rd_lock;
85
86static bd_ops_t rd_bd_ops = {
87 .open = rd_open,
88 .close = rd_close,
89 .read_blocks = rd_read_blocks,
90 .write_blocks = rd_write_blocks,
91 .get_block_size = rd_get_block_size,
92 .get_num_blocks = rd_get_num_blocks
93};
94
95static bd_srvs_t bd_srvs;
96
97static void rd_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
98{
99 bd_conn(iid, icall, &bd_srvs);
100}
101
102/** Open device. */
103static int rd_open(bd_srvs_t *bds, bd_srv_t *bd)
104{
105 return EOK;
106}
107
108/** Close device. */
109static int rd_close(bd_srv_t *bd)
110{
111 return EOK;
112}
113
114/** Read blocks from the device. */
115static int rd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
116 size_t size)
117{
118 if ((ba + cnt) * block_size > rd_size) {
119 /* Reading past the end of the device. */
120 return ELIMIT;
121 }
122
123 fibril_rwlock_read_lock(&rd_lock);
124 memcpy(buf, rd_addr + ba * block_size, min(block_size * cnt, size));
125 fibril_rwlock_read_unlock(&rd_lock);
126
127 return EOK;
128}
129
130/** Write blocks to the device. */
131static int rd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
132 const void *buf, size_t size)
133{
134 if ((ba + cnt) * block_size > rd_size) {
135 /* Writing past the end of the device. */
136 return ELIMIT;
137 }
138
139 fibril_rwlock_write_lock(&rd_lock);
140 memcpy(rd_addr + ba * block_size, buf, min(block_size * cnt, size));
141 fibril_rwlock_write_unlock(&rd_lock);
142
143 return EOK;
144}
145
146/** Prepare the ramdisk image for operation. */
147static bool rd_init(void)
148{
149 sysarg_t size;
150 int ret = sysinfo_get_value("rd.size", &size);
151 if ((ret != EOK) || (size == 0)) {
152 printf("%s: No RAM disk found\n", NAME);
153 return false;
154 }
155
156 sysarg_t addr_phys;
157 ret = sysinfo_get_value("rd.address.physical", &addr_phys);
158 if ((ret != EOK) || (addr_phys == 0)) {
159 printf("%s: Invalid RAM disk physical address\n", NAME);
160 return false;
161 }
162
163 rd_size = ALIGN_UP(size, block_size);
164 unsigned int flags =
165 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
166
167 ret = physmem_map(addr_phys,
168 ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags, &rd_addr);
169 if (ret != EOK) {
170 printf("%s: Error mapping RAM disk\n", NAME);
171 return false;
172 }
173
174 printf("%s: Found RAM disk at %p, %" PRIun " bytes\n", NAME,
175 (void *) addr_phys, size);
176
177 bd_srvs_init(&bd_srvs);
178 bd_srvs.ops = &rd_bd_ops;
179
180 async_set_fallback_port_handler(rd_client_conn, NULL);
181 ret = loc_server_register(NAME);
182 if (ret != EOK) {
183 printf("%s: Unable to register driver (%d)\n", NAME, ret);
184 return false;
185 }
186
187 service_id_t service_id;
188 ret = loc_service_register("bd/initrd", &service_id);
189 if (ret != EOK) {
190 printf("%s: Unable to register device service\n", NAME);
191 return false;
192 }
193
194 fibril_rwlock_initialize(&rd_lock);
195
196 return true;
197}
198
199/** Get device block size. */
200static int rd_get_block_size(bd_srv_t *bd, size_t *rsize)
201{
202 *rsize = block_size;
203 return EOK;
204}
205
206/** Get number of blocks on device. */
207static int rd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
208{
209 *rnb = rd_size / block_size;
210 return EOK;
211}
212
213int main(int argc, char **argv)
214{
215 printf("%s: HelenOS RAM disk server\n", NAME);
216
217 if (!rd_init())
218 return -1;
219
220 printf("%s: Accepting connections\n", NAME);
221 async_manager();
222
223 /* Never reached */
224 return 0;
225}
226
227/**
228 * @}
229 */
Note: See TracBrowser for help on using the repository browser.