This source file includes following definitions.
- ifmedia_init
- ifmedia_add
- ifmedia_list_add
- ifmedia_set
- ifmedia_ioctl
- ifmedia_match
- ifmedia_delete_instance
- ifmedia_baudrate
- ifmedia_printword
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/errno.h>
89 #include <sys/ioctl.h>
90 #include <sys/socket.h>
91 #include <sys/malloc.h>
92
93 #include <net/if.h>
94 #include <net/if_media.h>
95 #include <net/netisr.h>
96
97
98
99
100
101
102
103
104 #ifdef IFMEDIA_DEBUG
105 int ifmedia_debug = 0;
106 static void ifmedia_printword(int);
107 #endif
108
109
110
111
112 void
113 ifmedia_init(struct ifmedia *ifm, int dontcare_mask,
114 ifm_change_cb_t change_callback, ifm_stat_cb_t status_callback)
115 {
116 TAILQ_INIT(&ifm->ifm_list);
117 ifm->ifm_cur = NULL;
118 ifm->ifm_media = 0;
119 ifm->ifm_mask = dontcare_mask;
120 ifm->ifm_change = change_callback;
121 ifm->ifm_status = status_callback;
122 }
123
124
125
126
127
128 void
129 ifmedia_add(struct ifmedia *ifm, int mword, int data, void *aux)
130 {
131 struct ifmedia_entry *entry;
132
133 #ifdef IFMEDIA_DEBUG
134 if (ifmedia_debug) {
135 if (ifm == NULL) {
136 printf("ifmedia_add: null ifm\n");
137 return;
138 }
139 printf("Adding entry for ");
140 ifmedia_printword(mword);
141 }
142 #endif
143
144 entry = malloc(sizeof(*entry), M_IFADDR, M_NOWAIT);
145 if (entry == NULL)
146 panic("ifmedia_add: can't malloc entry");
147
148 entry->ifm_media = mword;
149 entry->ifm_data = data;
150 entry->ifm_aux = aux;
151
152 TAILQ_INSERT_TAIL(&ifm->ifm_list, entry, ifm_list);
153 }
154
155
156
157
158
159 void
160 ifmedia_list_add(struct ifmedia *ifm, struct ifmedia_entry *lp, int count)
161 {
162 int i;
163
164 for (i = 0; i < count; i++)
165 ifmedia_add(ifm, lp[i].ifm_media, lp[i].ifm_data,
166 lp[i].ifm_aux);
167 }
168
169
170
171
172
173
174
175
176 void
177 ifmedia_set(struct ifmedia *ifm, int target)
178 {
179 struct ifmedia_entry *match;
180
181 match = ifmedia_match(ifm, target, ifm->ifm_mask);
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 if (match == NULL) {
198 printf("ifmedia_set: no match for 0x%x/0x%x\n",
199 target, ~ifm->ifm_mask);
200 target = (target & IFM_NMASK) | IFM_NONE;
201 match = ifmedia_match(ifm, target, ifm->ifm_mask);
202 if (match == NULL) {
203 ifmedia_add(ifm, target, 0, NULL);
204 match = ifmedia_match(ifm, target, ifm->ifm_mask);
205 if (match == NULL) {
206 panic("ifmedia_set failed");
207 }
208 }
209 }
210 ifm->ifm_cur = match;
211
212 #ifdef IFMEDIA_DEBUG
213 if (ifmedia_debug) {
214 printf("ifmedia_set: target ");
215 ifmedia_printword(target);
216 printf("ifmedia_set: setting to ");
217 ifmedia_printword(ifm->ifm_cur->ifm_media);
218 }
219 #endif
220 }
221
222
223
224
225 int
226 ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, struct ifmedia *ifm,
227 u_long cmd)
228 {
229 struct ifmedia_entry *match;
230 struct ifmediareq *ifmr = (struct ifmediareq *) ifr;
231 int error = 0;
232
233 if (ifp == NULL || ifr == NULL || ifm == NULL)
234 return (EINVAL);
235
236 switch (cmd) {
237
238
239
240
241 case SIOCSIFMEDIA:
242 {
243 struct ifmedia_entry *oldentry;
244 u_int oldmedia;
245 u_int newmedia = ifr->ifr_media;
246
247 match = ifmedia_match(ifm, newmedia, ifm->ifm_mask);
248 if (match == NULL) {
249 #ifdef IFMEDIA_DEBUG
250 if (ifmedia_debug) {
251 printf(
252 "ifmedia_ioctl: no media found for 0x%x\n",
253 newmedia);
254 }
255 #endif
256 return (EINVAL);
257 }
258
259
260
261
262
263
264
265 if ((IFM_SUBTYPE(newmedia) != IFM_AUTO) &&
266 (newmedia == ifm->ifm_media) &&
267 (match == ifm->ifm_cur))
268 return 0;
269
270
271
272
273
274
275 #ifdef IFMEDIA_DEBUG
276 if (ifmedia_debug) {
277 printf("ifmedia_ioctl: switching %s to ",
278 ifp->if_xname);
279 ifmedia_printword(match->ifm_media);
280 }
281 #endif
282 oldentry = ifm->ifm_cur;
283 oldmedia = ifm->ifm_media;
284 ifm->ifm_cur = match;
285 ifm->ifm_media = newmedia;
286 error = (*ifm->ifm_change)(ifp);
287 if (error) {
288 ifm->ifm_cur = oldentry;
289 ifm->ifm_media = oldmedia;
290 }
291 break;
292 }
293
294
295
296
297 case SIOCGIFMEDIA:
298 {
299 struct ifmedia_entry *ep;
300 size_t nwords;
301
302 if(ifmr->ifm_count < 0)
303 return (EINVAL);
304
305 ifmr->ifm_active = ifmr->ifm_current = ifm->ifm_cur ?
306 ifm->ifm_cur->ifm_media : IFM_NONE;
307 ifmr->ifm_mask = ifm->ifm_mask;
308 ifmr->ifm_status = 0;
309 (*ifm->ifm_status)(ifp, ifmr);
310
311
312
313
314
315 ep = TAILQ_FIRST(&ifm->ifm_list);
316 for (nwords = 0; ep != NULL; ep = TAILQ_NEXT(ep, ifm_list))
317 nwords++;
318
319 if (ifmr->ifm_count != 0) {
320 size_t count;
321 size_t minwords = nwords > (size_t)ifmr->ifm_count
322 ? (size_t)ifmr->ifm_count
323 : nwords;
324 int *kptr = (int *)malloc(minwords * sizeof(int),
325 M_TEMP, M_WAITOK);
326
327
328
329 ep = TAILQ_FIRST(&ifm->ifm_list);
330 for (count = 0; ep != NULL && count < minwords;
331 ep = TAILQ_NEXT(ep, ifm_list), count++)
332 kptr[count] = ep->ifm_media;
333
334 error = copyout(kptr, ifmr->ifm_ulist,
335 minwords * sizeof(int));
336 if (error == 0 && ep != NULL)
337 error = E2BIG;
338 free(kptr, M_TEMP);
339 }
340 ifmr->ifm_count = nwords;
341 break;
342 }
343
344 default:
345 return (EINVAL);
346 }
347
348 return (error);
349 }
350
351
352
353
354 struct ifmedia_entry *
355 ifmedia_match(struct ifmedia *ifm, u_int target, u_int mask)
356 {
357 struct ifmedia_entry *match, *next;
358
359 match = NULL;
360 mask = ~mask;
361
362 for (next = TAILQ_FIRST(&ifm->ifm_list); next != NULL;
363 next = TAILQ_NEXT(next, ifm_list)) {
364 if ((next->ifm_media & mask) == (target & mask)) {
365 if (match) {
366 #if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
367 printf("ifmedia_match: multiple match for "
368 "0x%x/0x%x, selected instance %d\n",
369 target, mask, IFM_INST(match->ifm_media));
370 #endif
371 break;
372 }
373 match = next;
374 }
375 }
376
377 return match;
378 }
379
380
381
382
383 void
384 ifmedia_delete_instance(struct ifmedia *ifm, u_int inst)
385 {
386 struct ifmedia_entry *ife, *nife;
387
388 for (ife = TAILQ_FIRST(&ifm->ifm_list); ife != NULL;
389 ife = nife) {
390 nife = TAILQ_NEXT(ife, ifm_list);
391 if (inst == IFM_INST_ANY ||
392 inst == IFM_INST(ife->ifm_media)) {
393 TAILQ_REMOVE(&ifm->ifm_list, ife, ifm_list);
394 free(ife, M_IFADDR);
395 }
396 }
397 }
398
399
400
401
402
403 struct ifmedia_baudrate ifmedia_baudrate_descriptions[] =
404 IFM_BAUDRATE_DESCRIPTIONS;
405
406 int
407 ifmedia_baudrate(int mword)
408 {
409 int i;
410
411 for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) {
412 if ((mword & (IFM_NMASK|IFM_TMASK)) ==
413 ifmedia_baudrate_descriptions[i].ifmb_word)
414 return (ifmedia_baudrate_descriptions[i].ifmb_baudrate);
415 }
416
417
418 return (0);
419 }
420
421 #ifdef IFMEDIA_DEBUG
422
423 struct ifmedia_description ifm_type_descriptions[] =
424 IFM_TYPE_DESCRIPTIONS;
425
426 struct ifmedia_description ifm_subtype_descriptions[] =
427 IFM_SUBTYPE_DESCRIPTIONS;
428
429 struct ifmedia_description ifm_option_descriptions[] =
430 IFM_OPTION_DESCRIPTIONS;
431
432
433
434
435 static void
436 ifmedia_printword(int ifmw)
437 {
438 struct ifmedia_description *desc;
439 int seen_option = 0;
440
441
442 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL;
443 desc++) {
444 if (IFM_TYPE(ifmw) == desc->ifmt_word)
445 break;
446 }
447 if (desc->ifmt_string == NULL)
448 printf("<unknown type> ");
449 else
450 printf("%s ", desc->ifmt_string);
451
452
453 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL;
454 desc++) {
455 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) &&
456 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(ifmw))
457 break;
458 }
459 if (desc->ifmt_string == NULL)
460 printf("<unknown subtype>");
461 else
462 printf("%s", desc->ifmt_string);
463
464
465 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL;
466 desc++) {
467 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) &&
468 (ifmw & desc->ifmt_word) != 0 &&
469 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) {
470 if (seen_option == 0)
471 printf(" <");
472 printf("%s%s", seen_option ? "," : "",
473 desc->ifmt_string);
474 seen_option |= IFM_OPTIONS(desc->ifmt_word);
475 }
476 }
477 printf("%s\n", seen_option ? ">" : "");
478 }
479
480 #endif