source: mainline/uspace/srv/bd/sata_bd/sata_bd.c@ dec4150

Last change on this file since dec4150 was 4c6fd56, checked in by Jiri Svoboda <jiri@…>, 2 years ago

loc_server_register() should be callable more than once (API only)

Now loc_server_register() returns a pointer to a loc_srv_t object,
that is then passed to loc_service_register() and
loc_service_add_to_cat().

Added loc_server_unregister() that unregisters the server
and frees the loc_srv_t object.

Updated all callers. The implementation, however, is a stub.
It is not actually possible to call loc_server_register() more
than once, yet.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2023 Jiri Svoboda
3 * Copyright (c) 2012 Petr Jerman
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup sata_bd
31 * @{
32 */
33
34/**
35 * @file
36 * @brief SATA disk driver
37 *
38 */
39
40#include <stddef.h>
41#include <bd_srv.h>
42#include <devman.h>
43#include <errno.h>
44#include <str_error.h>
45#include <stdio.h>
46#include <str.h>
47#include <loc.h>
48#include <macros.h>
49#include <task.h>
50
51#include <ahci_iface.h>
52#include "sata_bd.h"
53
54#define NAME "sata_bd"
55#define NAMESPACE "bd"
56
57/** Maximum number of disks handled */
58#define MAXDISKS 256
59
60static loc_srv_t *srv;
61static sata_bd_dev_t disk[MAXDISKS];
62static int disk_count;
63
64static errno_t sata_bd_open(bd_srvs_t *, bd_srv_t *);
65static errno_t sata_bd_close(bd_srv_t *);
66static errno_t sata_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
67static errno_t sata_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
68static errno_t sata_bd_get_block_size(bd_srv_t *, size_t *);
69static errno_t sata_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
70
71static bd_ops_t sata_bd_ops = {
72 .open = sata_bd_open,
73 .close = sata_bd_close,
74 .read_blocks = sata_bd_read_blocks,
75 .write_blocks = sata_bd_write_blocks,
76 .get_block_size = sata_bd_get_block_size,
77 .get_num_blocks = sata_bd_get_num_blocks
78};
79
80static sata_bd_dev_t *bd_srv_sata(bd_srv_t *bd)
81{
82 return (sata_bd_dev_t *) bd->srvs->sarg;
83}
84
85/** Find SATA devices in device tree.
86 *
87 * @param Device manager handle describing container for searching.
88 *
89 * @return EOK if succeed, error code otherwise.
90 *
91 */
92static errno_t scan_device_tree(devman_handle_t funh)
93{
94 devman_handle_t devh;
95 devman_handle_t *cfuns;
96 size_t count, i;
97 errno_t rc;
98
99 /* If device is SATA, add device to the disk array. */
100 disk[disk_count].sess = ahci_get_sess(funh, &disk[disk_count].dev_name);
101 if (disk[disk_count].sess != NULL) {
102
103 ahci_get_sata_device_name(disk[disk_count].sess,
104 SATA_DEV_NAME_LENGTH, disk[disk_count].sata_dev_name);
105
106 ahci_get_block_size(disk[disk_count].sess,
107 &disk[disk_count].block_size);
108
109 ahci_get_num_blocks(disk[disk_count].sess, &disk[disk_count].blocks);
110
111 bd_srvs_init(&disk[disk_count].bds);
112 disk[disk_count].bds.ops = &sata_bd_ops;
113 disk[disk_count].bds.sarg = &disk[disk_count];
114
115 printf("Device %s - %s , blocks: %lu, block_size: %lu\n",
116 disk[disk_count].dev_name, disk[disk_count].sata_dev_name,
117 (long unsigned int) disk[disk_count].blocks,
118 (long unsigned int) disk[disk_count].block_size);
119
120 ++disk_count;
121 }
122
123 /* search children */
124 rc = devman_fun_get_child(funh, &devh);
125 if (rc == ENOENT)
126 return EOK;
127
128 if (rc != EOK) {
129 printf(NAME ": Failed getting child device for function %s.\n", "xxx");
130 return rc;
131 }
132
133 rc = devman_dev_get_functions(devh, &cfuns, &count);
134 if (rc != EOK) {
135 printf(NAME ": Failed getting list of functions for device %s.\n",
136 "xxx");
137 return rc;
138 }
139
140 for (i = 0; i < count; i++)
141 scan_device_tree(cfuns[i]);
142
143 free(cfuns);
144 return EOK;
145}
146
147/** Find sata devices in device tree from root.
148 *
149 * @return EOK if succeed, error code otherwise.
150 *
151 */
152static errno_t get_sata_disks(void)
153{
154 devman_handle_t root_fun;
155 errno_t rc;
156
157 disk_count = 0;
158
159 rc = devman_fun_get_handle("/", &root_fun, 0);
160 if (rc != EOK) {
161 printf(NAME ": Error resolving root function.\n");
162 return EIO;
163 }
164
165 scan_device_tree(root_fun);
166
167 return EOK;
168}
169
170/** Block device connection handler. */
171static void sata_bd_connection(ipc_call_t *icall, void *arg)
172{
173 service_id_t dsid;
174 int disk_id, i;
175
176 /* Get the device service ID. */
177 dsid = ipc_get_arg2(icall);
178
179 /* Determine which disk device is the client connecting to. */
180 disk_id = -1;
181 for (i = 0; i < MAXDISKS; i++)
182 if (disk[i].service_id == dsid)
183 disk_id = i;
184
185 if (disk_id < 0) {
186 async_answer_0(icall, EINVAL);
187 return;
188 }
189
190 bd_conn(icall, &disk[disk_id].bds);
191}
192
193/** Open device. */
194static errno_t sata_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
195{
196 return EOK;
197}
198
199/** Close device. */
200static errno_t sata_bd_close(bd_srv_t *bd)
201{
202 return EOK;
203}
204
205/** Read blocks from partition. */
206static errno_t sata_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt, void *buf,
207 size_t size)
208{
209 sata_bd_dev_t *sbd = bd_srv_sata(bd);
210
211 if (size < cnt * sbd->block_size)
212 return EINVAL;
213
214 return ahci_read_blocks(sbd->sess, ba, cnt, buf);
215}
216
217/** Write blocks to partition. */
218static errno_t sata_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
219 const void *buf, size_t size)
220{
221 sata_bd_dev_t *sbd = bd_srv_sata(bd);
222
223 if (size < cnt * sbd->block_size)
224 return EINVAL;
225
226 return ahci_write_blocks(sbd->sess, ba, cnt, (void *)buf);
227}
228
229/** Get device block size. */
230static errno_t sata_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
231{
232 sata_bd_dev_t *sbd = bd_srv_sata(bd);
233
234 *rsize = sbd->block_size;
235 return EOK;
236}
237
238/** Get number of blocks on device. */
239static errno_t sata_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
240{
241 sata_bd_dev_t *sbd = bd_srv_sata(bd);
242
243 *rnb = sbd->blocks;
244 return EOK;
245}
246
247int main(int argc, char **argv)
248{
249 errno_t rc;
250 category_id_t disk_cat;
251
252 async_set_fallback_port_handler(sata_bd_connection, NULL);
253 rc = loc_server_register(NAME, &srv);
254 if (rc != EOK) {
255 printf(NAME ": Unable to register driver: %s.\n", str_error(rc));
256 return rc;
257 }
258
259 rc = get_sata_disks();
260 if (rc != EOK) {
261 // TODO: log the error
262 return rc;
263 }
264
265 rc = loc_category_get_id("disk", &disk_cat, IPC_FLAG_BLOCKING);
266 if (rc != EOK) {
267 printf("%s: Failed resolving category 'disk': %s.\n", NAME, str_error(rc));
268 return rc;
269 }
270
271 for (int i = 0; i < disk_count; i++) {
272 char name[1024];
273 snprintf(name, 1024, "%s/%s", NAMESPACE, disk[i].dev_name);
274 rc = loc_service_register(srv, name, &disk[i].service_id);
275 if (rc != EOK) {
276 printf(NAME ": Unable to register device %s: %s\n", name, str_error(rc));
277 return rc;
278 }
279
280 rc = loc_service_add_to_cat(srv, disk[i].service_id, disk_cat);
281 if (rc != EOK) {
282 printf("%s: Failed adding %s to category: %s.",
283 NAME, disk[i].dev_name, str_error(rc));
284 return rc;
285 }
286 }
287
288 printf(NAME ": Accepting connections\n");
289 task_retval(0);
290 async_manager();
291
292 /* Not reached */
293 return 0;
294}
295
296/**
297 * @}
298 */
Note: See TracBrowser for help on using the repository browser.