source: mainline/uspace/srv/bd/sata_bd/sata_bd.c@ 498ced1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 498ced1 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.3 KB
Line 
1/*
2 * Copyright (c) 2012 Petr Jerman
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/** @addtogroup bd
30 * @{
31 */
32
33/**
34 * @file
35 * @brief SATA disk driver
36 *
37 */
38
39#include <stddef.h>
40#include <bd_srv.h>
41#include <devman.h>
42#include <errno.h>
43#include <str_error.h>
44#include <stdio.h>
45#include <str.h>
46#include <loc.h>
47#include <macros.h>
48#include <task.h>
49
50#include <ahci_iface.h>
51#include "sata_bd.h"
52
53#define NAME "sata_bd"
54#define NAMESPACE "bd"
55
56/** Maximum number of disks handled */
57#define MAXDISKS 256
58
59static sata_bd_dev_t disk[MAXDISKS];
60static int disk_count;
61
62static errno_t sata_bd_open(bd_srvs_t *, bd_srv_t *);
63static errno_t sata_bd_close(bd_srv_t *);
64static errno_t sata_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
65static errno_t sata_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
66static errno_t sata_bd_get_block_size(bd_srv_t *, size_t *);
67static errno_t sata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
68
69static bd_ops_t sata_bd_ops = {
70 .open = sata_bd_open,
71 .close = sata_bd_close,
72 .read_blocks = sata_bd_read_blocks,
73 .write_blocks = sata_bd_write_blocks,
74 .get_block_size = sata_bd_get_block_size,
75 .get_num_blocks = sata_bd_get_num_blocks
76};
77
78static sata_bd_dev_t *bd_srv_sata(bd_srv_t *bd)
79{
80 return (sata_bd_dev_t *) bd->srvs->sarg;
81}
82
83/** Find SATA devices in device tree.
84 *
85 * @param Device manager handle describing container for searching.
86 *
87 * @return EOK if succeed, error code otherwise.
88 *
89 */
90static errno_t scan_device_tree(devman_handle_t funh)
91{
92 devman_handle_t devh;
93 devman_handle_t *cfuns;
94 size_t count, i;
95 errno_t rc;
96
97 /* If device is SATA, add device to the disk array. */
98 disk[disk_count].sess = ahci_get_sess(funh, &disk[disk_count].dev_name);
99 if (disk[disk_count].sess != NULL) {
100
101 ahci_get_sata_device_name(disk[disk_count].sess,
102 SATA_DEV_NAME_LENGTH, disk[disk_count].sata_dev_name);
103
104 ahci_get_block_size(disk[disk_count].sess,
105 &disk[disk_count].block_size);
106
107 ahci_get_num_blocks(disk[disk_count].sess, &disk[disk_count].blocks);
108
109 bd_srvs_init(&disk[disk_count].bds);
110 disk[disk_count].bds.ops = &sata_bd_ops;
111 disk[disk_count].bds.sarg = &disk[disk_count];
112
113 printf("Device %s - %s , blocks: %lu, block_size: %lu\n",
114 disk[disk_count].dev_name, disk[disk_count].sata_dev_name,
115 (long unsigned int) disk[disk_count].blocks,
116 (long unsigned int) disk[disk_count].block_size);
117
118 ++disk_count;
119 }
120
121 /* search children */
122 rc = devman_fun_get_child(funh, &devh);
123 if (rc == ENOENT)
124 return EOK;
125
126 if (rc != EOK) {
127 printf(NAME ": Failed getting child device for function %s.\n", "xxx");
128 return rc;
129 }
130
131 rc = devman_dev_get_functions(devh, &cfuns, &count);
132 if (rc != EOK) {
133 printf(NAME ": Failed getting list of functions for device %s.\n",
134 "xxx");
135 return rc;
136 }
137
138 for (i = 0; i < count; i++)
139 scan_device_tree(cfuns[i]);
140
141 free(cfuns);
142 return EOK;
143}
144
145/** Find sata devices in device tree from root.
146 *
147 * @return EOK if succeed, error code otherwise.
148 *
149 */
150static errno_t get_sata_disks(void)
151{
152 devman_handle_t root_fun;
153 errno_t rc;
154
155 disk_count = 0;
156
157 rc = devman_fun_get_handle("/", &root_fun, 0);
158 if (rc != EOK) {
159 printf(NAME ": Error resolving root function.\n");
160 return EIO;
161 }
162
163 scan_device_tree(root_fun);
164
165 return EOK;
166}
167
168/** Block device connection handler. */
169static void sata_bd_connection(ipc_call_t *icall, void *arg)
170{
171 service_id_t dsid;
172 int disk_id, i;
173
174 /* Get the device service ID. */
175 dsid = IPC_GET_ARG2(*icall);
176
177 /* Determine which disk device is the client connecting to. */
178 disk_id = -1;
179 for (i = 0; i < MAXDISKS; i++)
180 if (disk[i].service_id == dsid)
181 disk_id = i;
182
183 if (disk_id < 0) {
184 async_answer_0(icall, EINVAL);
185 return;
186 }
187
188 bd_conn(icall, &disk[disk_id].bds);
189}
190
191/** Open device. */
192static errno_t sata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
193{
194 return EOK;
195}
196
197/** Close device. */
198static errno_t sata_bd_close(bd_srv_t *bd)
199{
200 return EOK;
201}
202
203/** Read blocks from partition. */
204static errno_t sata_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
205 size_t size)
206{
207 sata_bd_dev_t *sbd = bd_srv_sata(bd);
208
209 if (size < cnt * sbd->block_size)
210 return EINVAL;
211
212 return ahci_read_blocks(sbd->sess, ba, cnt, buf);
213}
214
215/** Write blocks to partition. */
216static errno_t sata_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
217 const void *buf, size_t size)
218{
219 sata_bd_dev_t *sbd = bd_srv_sata(bd);
220
221 if (size < cnt * sbd->block_size)
222 return EINVAL;
223
224 return ahci_write_blocks(sbd->sess, ba, cnt, (void *)buf);
225}
226
227/** Get device block size. */
228static errno_t sata_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
229{
230 sata_bd_dev_t *sbd = bd_srv_sata(bd);
231
232 *rsize = sbd->block_size;
233 return EOK;
234}
235
236/** Get number of blocks on device. */
237static errno_t sata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
238{
239 sata_bd_dev_t *sbd = bd_srv_sata(bd);
240
241 *rnb = sbd->blocks;
242 return EOK;
243}
244
245
246int main(int argc, char **argv)
247{
248 errno_t rc;
249 category_id_t disk_cat;
250
251 async_set_fallback_port_handler(sata_bd_connection, NULL);
252 rc = loc_server_register(NAME);
253 if (rc != EOK) {
254 printf(NAME ": Unable to register driver: %s.\n", str_error(rc));
255 return rc;
256 }
257
258 rc = get_sata_disks();
259 if (rc != EOK) {
260 // TODO: log the error
261 return rc;
262 }
263
264 rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
265 if (rc != EOK) {
266 printf("%s: Failed resolving category 'disk': %s.\n", NAME, str_error(rc));
267 return rc;
268 }
269
270 for (int i = 0; i < disk_count; i++) {
271 char name[1024];
272 snprintf(name, 1024, "%s/%s", NAMESPACE, disk[i].dev_name);
273 rc = loc_service_register(name, &disk[i].service_id);
274 if (rc != EOK) {
275 printf(NAME ": Unable to register device %s: %s\n", name, str_error(rc));
276 return rc;
277 }
278
279 rc = loc_service_add_to_cat(disk[i].service_id, disk_cat);
280 if (rc != EOK) {
281 printf("%s: Failed adding %s to category: %s.",
282 NAME, disk[i].dev_name, str_error(rc));
283 return rc;
284 }
285 }
286
287 printf(NAME ": Accepting connections\n");
288 task_retval(0);
289 async_manager();
290
291 /* Not reached */
292 return 0;
293}
294
295/**
296 * @}
297 */
Note: See TracBrowser for help on using the repository browser.