source: mainline/uspace/srv/ethip/ethip_nic.c@ 06295a9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 06295a9 was 06295a9, checked in by Jiri Svoboda <jiri@…>, 14 years ago

NIC discovery in ethip. Create one IP link for each NIC.

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 2012 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/** @addtogroup inet
30 * @{
31 */
32/**
33 * @file
34 * @brief
35 */
36
37#include <async.h>
38#include <bool.h>
39#include <errno.h>
40#include <fibril_synch.h>
41#include <inet/iplink_srv.h>
42#include <io/log.h>
43#include <loc.h>
44#include <device/nic.h>
45#include <stdlib.h>
46
47#include "ethip.h"
48#include "ethip_nic.h"
49
50static int ethip_nic_open(service_id_t sid);
51static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
52
53static LIST_INITIALIZE(ethip_nic_list);
54static FIBRIL_MUTEX_INITIALIZE(ethip_discovery_lock);
55
56static int ethip_nic_check_new(void)
57{
58 bool already_known;
59 category_id_t iplink_cat;
60 service_id_t *svcs;
61 size_t count, i;
62 int rc;
63
64 fibril_mutex_lock(&ethip_discovery_lock);
65
66 rc = loc_category_get_id("nic", &iplink_cat, IPC_FLAG_BLOCKING);
67 if (rc != EOK) {
68 log_msg(LVL_ERROR, "Failed resolving category 'nic'.");
69 fibril_mutex_unlock(&ethip_discovery_lock);
70 return ENOENT;
71 }
72
73 rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
74 if (rc != EOK) {
75 log_msg(LVL_ERROR, "Failed getting list of IP links.");
76 fibril_mutex_unlock(&ethip_discovery_lock);
77 return EIO;
78 }
79
80 for (i = 0; i < count; i++) {
81 already_known = false;
82
83 list_foreach(ethip_nic_list, nic_link) {
84 ethip_nic_t *nic = list_get_instance(nic_link,
85 ethip_nic_t, nic_list);
86 if (nic->svc_id == svcs[i]) {
87 already_known = true;
88 break;
89 }
90 }
91
92 if (!already_known) {
93 log_msg(LVL_DEBUG, "Found NIC '%lu'",
94 (unsigned long) svcs[i]);
95 rc = ethip_nic_open(svcs[i]);
96 if (rc != EOK)
97 log_msg(LVL_ERROR, "Could not open NIC.");
98 }
99 }
100
101 fibril_mutex_unlock(&ethip_discovery_lock);
102 return EOK;
103}
104
105static ethip_nic_t *ethip_nic_new(void)
106{
107 ethip_nic_t *nic = calloc(1, sizeof(ethip_nic_t));
108
109 if (nic == NULL) {
110 log_msg(LVL_ERROR, "Failed allocating NIC structure. "
111 "Out of memory.");
112 return NULL;
113 }
114
115 link_initialize(&nic->nic_list);
116
117 return nic;
118}
119
120static void ethip_nic_delete(ethip_nic_t *nic)
121{
122 if (nic->svc_name != NULL)
123 free(nic->svc_name);
124 free(nic);
125}
126
127static int ethip_nic_open(service_id_t sid)
128{
129 ethip_nic_t *nic;
130 int rc;
131 bool in_list = false;
132
133 log_msg(LVL_DEBUG, "ethip_nic_open()");
134 nic = ethip_nic_new();
135 if (nic == NULL)
136 return ENOMEM;
137
138 rc = loc_service_get_name(sid, &nic->svc_name);
139 if (rc != EOK) {
140 log_msg(LVL_ERROR, "Failed getting service name.");
141 goto error;
142 }
143
144 nic->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
145 if (nic->sess == NULL) {
146 log_msg(LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
147 goto error;
148 }
149
150 nic->svc_id = sid;
151
152 rc = nic_callback_create(nic->sess, ethip_nic_cb_conn, nic);
153 if (rc != EOK) {
154 log_msg(LVL_ERROR, "Failed creating callback connection "
155 "from '%s'", nic->svc_name);
156 goto error;
157 }
158
159 rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
160 if (rc != EOK) {
161 log_msg(LVL_ERROR, "Failed activating NIC '%s'.",
162 nic->svc_name);
163 goto error;
164 }
165
166 log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
167 list_append(&nic->nic_list, &ethip_nic_list);
168 in_list = true;
169
170 rc = ethip_iplink_init(nic);
171 if (rc != EOK)
172 goto error;
173
174 log_msg(LVL_DEBUG, "Initialized IP link service.");
175
176 return EOK;
177
178error:
179 if (in_list)
180 list_remove(&nic->nic_list);
181 if (nic->sess != NULL)
182 async_hangup(nic->sess);
183 ethip_nic_delete(nic);
184 return rc;
185}
186
187static void ethip_nic_cat_change_cb(void)
188{
189 (void) ethip_nic_check_new();
190}
191
192static void ethip_nic_addr_changed(ethip_nic_t *nic, ipc_callid_t callid,
193 ipc_call_t *call)
194{
195 log_msg(LVL_DEBUG, "ethip_nic_addr_changed()");
196 async_answer_0(callid, ENOTSUP);
197}
198
199static void ethip_nic_received(ethip_nic_t *nic, ipc_callid_t callid,
200 ipc_call_t *call)
201{
202 log_msg(LVL_DEBUG, "ethip_nic_received()");
203 async_answer_0(callid, ENOTSUP);
204}
205
206static void ethip_nic_device_state(ethip_nic_t *nic, ipc_callid_t callid,
207 ipc_call_t *call)
208{
209 log_msg(LVL_DEBUG, "ethip_nic_device_state()");
210 async_answer_0(callid, ENOTSUP);
211}
212
213static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
214{
215 ethip_nic_t *nic;
216
217 log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
218
219 while (true) {
220 ipc_call_t call;
221 ipc_callid_t callid = async_get_call(&call);
222
223 if (!IPC_GET_IMETHOD(call)) {
224 /* TODO: Handle hangup */
225 return;
226 }
227
228 switch (IPC_GET_IMETHOD(call)) {
229 case NIC_EV_ADDR_CHANGED:
230 ethip_nic_addr_changed(nic, callid, &call);
231 break;
232 case NIC_EV_RECEIVED:
233 ethip_nic_received(nic, callid, &call);
234 break;
235 case NIC_EV_DEVICE_STATE:
236 ethip_nic_device_state(nic, callid, &call);
237 break;
238 default:
239 async_answer_0(callid, ENOTSUP);
240 }
241 }
242}
243
244int ethip_nic_discovery_start(void)
245{
246 int rc;
247
248 rc = loc_register_cat_change_cb(ethip_nic_cat_change_cb);
249 if (rc != EOK) {
250 log_msg(LVL_ERROR, "Failed registering callback for NIC "
251 "discovery (%d).", rc);
252 return rc;
253 }
254
255 return ethip_nic_check_new();
256}
257
258/** @}
259 */
Note: See TracBrowser for help on using the repository browser.