source: mainline/uspace/drv/block/ata_bd/main.c@ e502572b

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

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file
30 */
31
32#include <assert.h>
33#include <stdio.h>
34#include <errno.h>
35#include <str_error.h>
36#include <ddf/driver.h>
37#include <ddf/log.h>
38#include <device/hw_res_parsed.h>
39
40#include "ata_bd.h"
41#include "main.h"
42
43static errno_t ata_dev_add(ddf_dev_t *dev);
44static errno_t ata_dev_remove(ddf_dev_t *dev);
45static errno_t ata_dev_gone(ddf_dev_t *dev);
46static errno_t ata_fun_online(ddf_fun_t *fun);
47static errno_t ata_fun_offline(ddf_fun_t *fun);
48
49static void ata_bd_connection(ipc_call_t *, void *);
50
51static driver_ops_t driver_ops = {
52 .dev_add = &ata_dev_add,
53 .dev_remove = &ata_dev_remove,
54 .dev_gone = &ata_dev_gone,
55 .fun_online = &ata_fun_online,
56 .fun_offline = &ata_fun_offline
57};
58
59static driver_t ata_driver = {
60 .name = NAME,
61 .driver_ops = &driver_ops
62};
63
64static errno_t ata_get_res(ddf_dev_t *dev, ata_base_t *ata_res)
65{
66 async_sess_t *parent_sess;
67 hw_res_list_parsed_t hw_res;
68 errno_t rc;
69
70 parent_sess = ddf_dev_parent_sess_get(dev);
71 if (parent_sess == NULL)
72 return ENOMEM;
73
74 hw_res_list_parsed_init(&hw_res);
75 rc = hw_res_get_list_parsed(parent_sess, &hw_res, 0);
76 if (rc != EOK)
77 return rc;
78
79 if (hw_res.io_ranges.count != 2) {
80 rc = EINVAL;
81 goto error;
82 }
83
84 addr_range_t *cmd_rng = &hw_res.io_ranges.ranges[0];
85 addr_range_t *ctl_rng = &hw_res.io_ranges.ranges[1];
86 ata_res->cmd = RNGABS(*cmd_rng);
87 ata_res->ctl = RNGABS(*ctl_rng);
88
89 if (RNGSZ(*ctl_rng) < sizeof(ata_ctl_t)) {
90 rc = EINVAL;
91 goto error;
92 }
93
94 if (RNGSZ(*cmd_rng) < sizeof(ata_cmd_t)) {
95 rc = EINVAL;
96 goto error;
97 }
98
99 return EOK;
100error:
101 hw_res_list_parsed_clean(&hw_res);
102 return rc;
103}
104
105/** Add new device
106 *
107 * @param dev New device
108 * @return EOK on success or an error code.
109 */
110static errno_t ata_dev_add(ddf_dev_t *dev)
111{
112 ata_ctrl_t *ctrl;
113 ata_base_t res;
114 errno_t rc;
115
116 rc = ata_get_res(dev, &res);
117 if (rc != EOK) {
118 ddf_msg(LVL_ERROR, "Invalid HW resource configuration.");
119 return EINVAL;
120 }
121
122 ctrl = ddf_dev_data_alloc(dev, sizeof(ata_ctrl_t));
123 if (ctrl == NULL) {
124 ddf_msg(LVL_ERROR, "Failed allocating soft state.");
125 rc = ENOMEM;
126 goto error;
127 }
128
129 ctrl->dev = dev;
130
131 rc = ata_ctrl_init(ctrl, &res);
132 if (rc != EOK) {
133 ddf_msg(LVL_ERROR, "Failed initializing ATA controller.");
134 rc = EIO;
135 goto error;
136 }
137
138 return EOK;
139error:
140 return rc;
141}
142
143static char *ata_fun_name(disk_t *disk)
144{
145 char *fun_name;
146
147 if (asprintf(&fun_name, "d%u", disk->disk_id) < 0)
148 return NULL;
149
150 return fun_name;
151}
152
153errno_t ata_fun_create(disk_t *disk)
154{
155 ata_ctrl_t *ctrl = disk->ctrl;
156 errno_t rc;
157 char *fun_name = NULL;
158 ddf_fun_t *fun = NULL;
159 ata_fun_t *afun = NULL;
160
161 fun_name = ata_fun_name(disk);
162 if (fun_name == NULL) {
163 ddf_msg(LVL_ERROR, "Out of memory.");
164 rc = ENOMEM;
165 goto error;
166 }
167
168 fun = ddf_fun_create(ctrl->dev, fun_exposed, fun_name);
169 if (fun == NULL) {
170 ddf_msg(LVL_ERROR, "Failed creating DDF function.");
171 rc = ENOMEM;
172 goto error;
173 }
174
175 /* Allocate soft state */
176 afun = ddf_fun_data_alloc(fun, sizeof(ata_fun_t));
177 if (afun == NULL) {
178 ddf_msg(LVL_ERROR, "Failed allocating softstate.");
179 rc = ENOMEM;
180 goto error;
181 }
182
183 afun->fun = fun;
184 afun->disk = disk;
185
186 bd_srvs_init(&afun->bds);
187 afun->bds.ops = &ata_bd_ops;
188 afun->bds.sarg = disk;
189
190 /* Set up a connection handler. */
191 ddf_fun_set_conn_handler(fun, ata_bd_connection);
192
193 rc = ddf_fun_bind(fun);
194 if (rc != EOK) {
195 ddf_msg(LVL_ERROR, "Failed binding DDF function %s: %s",
196 fun_name, str_error(rc));
197 goto error;
198 }
199
200 ddf_fun_add_to_category(fun, "disk");
201
202 free(fun_name);
203 disk->afun = afun;
204 return EOK;
205error:
206 if (fun != NULL)
207 ddf_fun_destroy(fun);
208 if (fun_name != NULL)
209 free(fun_name);
210
211 return rc;
212}
213
214errno_t ata_fun_remove(disk_t *disk)
215{
216 errno_t rc;
217 char *fun_name;
218
219 if (disk->afun == NULL)
220 return EOK;
221
222 fun_name = ata_fun_name(disk);
223 if (fun_name == NULL) {
224 ddf_msg(LVL_ERROR, "Out of memory.");
225 rc = ENOMEM;
226 goto error;
227 }
228
229 ddf_msg(LVL_DEBUG, "ata_fun_remove(%p, '%s')", disk, fun_name);
230 rc = ddf_fun_offline(disk->afun->fun);
231 if (rc != EOK) {
232 ddf_msg(LVL_ERROR, "Error offlining function '%s'.", fun_name);
233 goto error;
234 }
235
236 rc = ddf_fun_unbind(disk->afun->fun);
237 if (rc != EOK) {
238 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", fun_name);
239 goto error;
240 }
241
242 ddf_fun_destroy(disk->afun->fun);
243 disk->afun = NULL;
244 free(fun_name);
245 return EOK;
246error:
247 if (fun_name != NULL)
248 free(fun_name);
249 return rc;
250}
251
252errno_t ata_fun_unbind(disk_t *disk)
253{
254 errno_t rc;
255 char *fun_name;
256
257 if (disk->afun == NULL)
258 return EOK;
259
260 fun_name = ata_fun_name(disk);
261 if (fun_name == NULL) {
262 ddf_msg(LVL_ERROR, "Out of memory.");
263 rc = ENOMEM;
264 goto error;
265 }
266
267 ddf_msg(LVL_DEBUG, "ata_fun_unbind(%p, '%s')", disk, fun_name);
268 rc = ddf_fun_unbind(disk->afun->fun);
269 if (rc != EOK) {
270 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", fun_name);
271 goto error;
272 }
273
274 ddf_fun_destroy(disk->afun->fun);
275 disk->afun = NULL;
276 free(fun_name);
277 return EOK;
278error:
279 if (fun_name != NULL)
280 free(fun_name);
281 return rc;
282}
283
284static errno_t ata_dev_remove(ddf_dev_t *dev)
285{
286 ata_ctrl_t *ctrl = (ata_ctrl_t *)ddf_dev_data_get(dev);
287
288 ddf_msg(LVL_DEBUG, "ata_dev_remove(%p)", dev);
289
290 return ata_ctrl_remove(ctrl);
291}
292
293static errno_t ata_dev_gone(ddf_dev_t *dev)
294{
295 ata_ctrl_t *ctrl = (ata_ctrl_t *)ddf_dev_data_get(dev);
296
297 ddf_msg(LVL_DEBUG, "ata_dev_gone(%p)", dev);
298
299 return ata_ctrl_gone(ctrl);
300}
301
302static errno_t ata_fun_online(ddf_fun_t *fun)
303{
304 ddf_msg(LVL_DEBUG, "ata_fun_online()");
305 return ddf_fun_online(fun);
306}
307
308static errno_t ata_fun_offline(ddf_fun_t *fun)
309{
310 ddf_msg(LVL_DEBUG, "ata_fun_offline()");
311 return ddf_fun_offline(fun);
312}
313
314/** Block device connection handler */
315static void ata_bd_connection(ipc_call_t *icall, void *arg)
316{
317 ata_fun_t *afun;
318
319 afun = (ata_fun_t *) ddf_fun_data_get((ddf_fun_t *)arg);
320 bd_conn(icall, &afun->bds);
321}
322
323int main(int argc, char *argv[])
324{
325 printf(NAME ": HelenOS ATA(PI) device driver\n");
326 ddf_log_init(NAME);
327 return ddf_driver_main(&ata_driver);
328}
329
Note: See TracBrowser for help on using the repository browser.