source: mainline/uspace/app/nic/nic.c@ 6c1c1f7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6c1c1f7 was f2f4c00, checked in by Jakub Jermar <jakub@…>, 11 years ago

Merge the rtl8169 driver and improvements to the nic utility from
lp:~nufcia/helenos/rtl8169.

  • Revert the disabling of the ISA devices using IRQ 5.
  • Two minor build fixes for 64-bit platforms.
  • Property mode set to 100644
File size: 9.2 KB
Line 
1/*
2 * Copyright (c) 2014 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 nic
30 * @{
31 */
32/** @file NIC configuration utility.
33 *
34 */
35
36#include <errno.h>
37#include <loc.h>
38#include <nic_iface.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str_error.h>
42#include <sys/types.h>
43
44#define NAME "nic"
45
46typedef struct {
47 nic_device_info_t device_info;
48 nic_address_t address;
49 nic_cable_state_t link_state;
50 nic_channel_mode_t duplex;
51 int speed;
52} nic_info_t;
53
54static void print_syntax(void)
55{
56 printf("syntax:\n");
57 printf("\t" NAME " [<index> <cmd> [<args...>]]\n");
58 printf("\t<index> is NIC index number reported by the tool\n");
59 printf("\t<cmd> is:\n");
60 printf("\taddr <mac_address> - set MAC address\n");
61 printf("\tspeed <10|100|1000> - set NIC speed\n");
62 printf("\tduplex <half|full|simplex> - set duplex mode\n");
63 printf("\tauto - enable autonegotiation\n");
64}
65
66static async_sess_t *get_nic_by_index(size_t i)
67{
68 int rc;
69 size_t count;
70 char *svc_name;
71 category_id_t nic_cat;
72 service_id_t *nics = NULL;
73 async_sess_t *sess;
74
75 rc = loc_category_get_id("nic", &nic_cat, 0);
76 if (rc != EOK) {
77 printf("Error resolving category 'nic'.\n");
78 goto error;
79 }
80
81 rc = loc_category_get_svcs(nic_cat, &nics, &count);
82 if (rc != EOK) {
83 printf("Error getting list of NICs.\n");
84 goto error;
85 }
86
87 rc = loc_service_get_name(nics[i], &svc_name);
88 if (rc != EOK) {
89 printf("Error getting service name.\n");
90 goto error;
91 }
92
93 printf("Using device: %s\n", svc_name);
94
95 sess = loc_service_connect(EXCHANGE_SERIALIZE, nics[i], 0);
96 if (sess == NULL) {
97 printf("Error connecting to service.\n");
98 goto error;
99 }
100
101 return sess;
102error:
103 return NULL;
104}
105
106static int nic_get_info(service_id_t svc_id, char *svc_name,
107 nic_info_t *info)
108{
109 async_sess_t *sess;
110 nic_role_t role;
111 int rc;
112
113 sess = loc_service_connect(EXCHANGE_SERIALIZE, svc_id, 0);
114 if (sess == NULL) {
115 printf("Error connecting to service.\n");
116 goto error;
117 }
118
119 rc = nic_get_address(sess, &info->address);
120 if (rc != EOK) {
121 printf("Error getting NIC address.\n");
122 rc = EIO;
123 goto error;
124 }
125
126 rc = nic_get_device_info(sess, &info->device_info);
127 if (rc != EOK) {
128 printf("Error getting NIC device info.\n");
129 rc = EIO;
130 goto error;
131 }
132
133 rc = nic_get_cable_state(sess, &info->link_state);
134 if (rc != EOK) {
135 printf("Error getting link state.\n");
136 rc = EIO;
137 goto error;
138 }
139
140 rc = nic_get_operation_mode(sess, &info->speed, &info->duplex, &role);
141 if (rc != EOK) {
142 printf("Error getting NIC speed and duplex mode.\n");
143 rc = EIO;
144 goto error;
145 }
146
147
148 return EOK;
149error:
150 return rc;
151}
152
153static const char *nic_link_state_str(nic_cable_state_t link_state)
154{
155 switch (link_state) {
156 case NIC_CS_UNKNOWN: return "unknown";
157 case NIC_CS_PLUGGED: return "up";
158 case NIC_CS_UNPLUGGED: return "down";
159 default: assert(false); return NULL;
160 }
161}
162
163static const char *nic_duplex_mode_str(nic_channel_mode_t mode)
164{
165 switch (mode) {
166 case NIC_CM_FULL_DUPLEX: return "full-duplex";
167 case NIC_CM_HALF_DUPLEX: return "half-duplex";
168 case NIC_CM_SIMPLEX: return "simplex";
169 default: assert(false); return NULL;
170 }
171}
172
173static char *nic_addr_format(nic_address_t *a)
174{
175 int rc;
176 char *s;
177
178 rc = asprintf(&s, "%02x:%02x:%02x:%02x:%02x:%02x",
179 a->address[0], a->address[1], a->address[2],
180 a->address[3], a->address[4], a->address[5]);
181 if (rc < 0)
182 return NULL;
183
184 return s;
185}
186
187static int nic_list(void)
188{
189 category_id_t nic_cat;
190 service_id_t *nics = NULL;
191 nic_info_t nic_info;
192 size_t count, i;
193 char *svc_name;
194 char *addr_str;
195 int rc;
196
197 rc = loc_category_get_id("nic", &nic_cat, 0);
198 if (rc != EOK) {
199 printf("Error resolving category 'nic'.\n");
200 goto error;
201 }
202
203 rc = loc_category_get_svcs(nic_cat, &nics, &count);
204 if (rc != EOK) {
205 printf("Error getting list of NICs.\n");
206 goto error;
207 }
208
209 printf("[Index]: [Service Name]\n");
210 for (i = 0; i < count; i++) {
211 rc = loc_service_get_name(nics[i], &svc_name);
212 if (rc != EOK) {
213 printf("Error getting service name.\n");
214 goto error;
215 }
216
217 rc = nic_get_info(nics[i], svc_name, &nic_info);
218 if (rc != EOK)
219 goto error;
220
221 addr_str = nic_addr_format(&nic_info.address);
222 if (addr_str == NULL) {
223 printf("Out of memory.\n");
224 rc = ENOMEM;
225 goto error;
226 }
227
228 printf("%zu: %s\n", i, svc_name);
229 printf("\tMAC address: %s\n", addr_str);
230 printf("\tVendor name: %s\n",
231 nic_info.device_info.vendor_name);
232 printf("\tModel name: %s\n",
233 nic_info.device_info.model_name);
234 printf("\tLink state: %s\n",
235 nic_link_state_str(nic_info.link_state));
236
237 if (nic_info.link_state == NIC_CS_PLUGGED) {
238 printf("\tSpeed: %dMbps %s\n", nic_info.speed,
239 nic_duplex_mode_str(nic_info.duplex));
240 }
241
242 free(svc_name);
243 free(addr_str);
244 }
245
246 return EOK;
247error:
248 free(nics);
249 return rc;
250}
251
252static int nic_set_speed(int i, char *str)
253{
254 async_sess_t *sess;
255 uint32_t speed;
256 int oldspeed;
257 nic_channel_mode_t oldduplex;
258 nic_role_t oldrole;
259 int rc;
260
261 rc = str_uint32_t(str, NULL, 10, false, &speed);
262 if (rc != EOK) {
263 printf("Speed must be a numeric value.\n");
264 return rc;
265 }
266
267 if (speed != 10 && speed != 100 && speed != 1000) {
268 printf("Speed must be one of: 10, 100, 1000.\n");
269 return EINVAL;
270 }
271
272 sess = get_nic_by_index(i);
273 if (sess == NULL) {
274 printf("Specified NIC doesn't exist or cannot connect to it.\n");
275 return EINVAL;
276 }
277
278 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
279 if (rc != EOK) {
280 printf("Error getting NIC speed and duplex mode.\n");
281 return EIO;
282 }
283
284 return nic_set_operation_mode(sess, speed, oldduplex, oldrole);
285}
286
287static int nic_set_duplex(int i, char *str)
288{
289 async_sess_t *sess;
290 int oldspeed;
291 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
292 nic_channel_mode_t oldduplex;
293 nic_role_t oldrole;
294 int rc;
295
296 if (!str_cmp(str, "half"))
297 duplex = NIC_CM_HALF_DUPLEX;
298
299 if (!str_cmp(str, "full"))
300 duplex = NIC_CM_FULL_DUPLEX;
301
302 if (!str_cmp(str, "simplex"))
303 duplex = NIC_CM_SIMPLEX;
304
305 if (duplex == NIC_CM_UNKNOWN) {
306 printf("Invalid duplex specification.\n");
307 return EINVAL;
308 }
309
310 sess = get_nic_by_index(i);
311 if (sess == NULL) {
312 printf("Specified NIC doesn't exist or cannot connect to it.\n");
313 return EINVAL;
314 }
315
316 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
317 if (rc != EOK) {
318 printf("Error getting NIC speed and duplex mode.\n");
319 return EIO;
320 }
321
322 return nic_set_operation_mode(sess, oldspeed, duplex, oldrole);
323}
324
325static int nic_set_autoneg(int i)
326{
327 async_sess_t *sess;
328 int rc;
329
330 sess = get_nic_by_index(i);
331 if (sess == NULL) {
332 printf("Specified NIC doesn't exist or cannot connect to it.\n");
333 return EINVAL;
334 }
335
336 rc = nic_autoneg_restart(sess);
337 if (rc != EOK) {
338 printf("Error restarting NIC autonegotiation.\n");
339 return EIO;
340 }
341
342 return EOK;
343}
344
345static int nic_set_addr(int i, char *str)
346{
347 async_sess_t *sess;
348 nic_address_t addr;
349 int rc, idx;
350
351 sess = get_nic_by_index(i);
352 if (sess == NULL) {
353 printf("Specified NIC doesn't exist or cannot connect to it.\n");
354 return EINVAL;
355 }
356
357 if (str_size(str) != 17) {
358 printf("Invalid MAC address specified");
359 return EINVAL;
360 }
361
362 for (idx = 0; idx < 6; idx++) {
363 rc = str_uint8_t(&str[idx * 3], NULL, 16, false, &addr.address[idx]);
364 if (rc != EOK) {
365 printf("Invalid MAC address specified");
366 return EINVAL;
367 }
368 }
369
370 return nic_set_address(sess, &addr);
371}
372
373int main(int argc, char *argv[])
374{
375 int rc;
376 uint32_t index;
377
378 if (argc == 1) {
379 rc = nic_list();
380 if (rc != EOK)
381 return 1;
382 } else if (argc >= 3) {
383 rc = str_uint32_t(argv[1], NULL, 10, false, &index);
384 if (rc != EOK) {
385 printf(NAME ": Invalid argument.\n");
386 print_syntax();
387 return 1;
388 }
389
390 if (!str_cmp(argv[2], "addr"))
391 return nic_set_addr(index, argv[3]);
392
393 if (!str_cmp(argv[2], "speed"))
394 return nic_set_speed(index, argv[3]);
395
396 if (!str_cmp(argv[2], "duplex"))
397 return nic_set_duplex(index, argv[3]);
398
399 if (!str_cmp(argv[2], "auto"))
400 return nic_set_autoneg(index);
401
402 } else {
403 printf(NAME ": Invalid argument.\n");
404 print_syntax();
405 return 1;
406 }
407
408 return 0;
409}
410
411/** @}
412 */
Note: See TracBrowser for help on using the repository browser.