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

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

cstyle improvements
replace traditional K&R-style function declarations and definitions

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