VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/solaris/VBoxNetAdp-solaris.c@ 55747

Last change on this file since 55747 was 50664, checked in by vboxsync, 11 years ago

Support,VBoxNet[Flt|Adp]/solaris: Fix S10 regression with trunk, ddi_quiesce_not_needed missing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.9 KB
Line 
1/* $Id: VBoxNetAdp-solaris.c 50664 2014-03-03 10:54:25Z vboxsync $ */
2/** @file
3 * VBoxNetAdapter - Network Adapter Driver (Host), Solaris Specific Code.
4 */
5
6/*
7 * Copyright (C) 2009-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
31#ifdef DEBUG_ramshankar
32# define LOG_ENABLED
33# define LOG_INSTANCE RTLogRelDefaultInstance()
34#endif
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <VBox/version.h>
38#include <iprt/assert.h>
39#include <iprt/semaphore.h>
40#include <iprt/initterm.h>
41#include <iprt/assert.h>
42#include <iprt/mem.h>
43#include <iprt/rand.h>
44
45#include <sys/types.h>
46#include <sys/dlpi.h>
47#include <sys/types.h>
48#include <sys/param.h>
49#include <sys/stat.h>
50#include <sys/stream.h>
51#include <sys/stropts.h>
52#include <sys/strsun.h>
53#include <sys/modctl.h>
54#include <sys/ddi.h>
55#include <sys/sunddi.h>
56#include <sys/sunldi.h>
57#include <sys/gld.h>
58
59#include "../VBoxNetAdpInternal.h"
60
61/*******************************************************************************
62* Defined Constants And Macros *
63*******************************************************************************/
64#define DEVICE_NAME "vboxnet"
65/** The module descriptions as seen in 'modinfo'. */
66#define DEVICE_DESC_DRV "VirtualBox NetAdp"
67
68
69/*******************************************************************************
70* Internal Functions *
71*******************************************************************************/
72static int VBoxNetAdpSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
73static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
74static int VBoxNetAdpSolarisQuiesceNotNeeded(dev_info_t *pDip);
75
76/**
77 * Streams: module info.
78 */
79static struct module_info g_VBoxNetAdpSolarisModInfo =
80{
81 0x0dd, /* module id */
82 DEVICE_NAME,
83 0, /* min. packet size */
84 INFPSZ, /* max. packet size */
85 0, /* hi-water mark */
86 0 /* lo-water mark */
87};
88
89/**
90 * Streams: read queue hooks.
91 */
92static struct qinit g_VBoxNetAdpSolarisReadQ =
93{
94 NULL, /* read */
95 gld_rsrv,
96 gld_open,
97 gld_close,
98 NULL, /* admin (reserved) */
99 &g_VBoxNetAdpSolarisModInfo,
100 NULL /* module stats */
101};
102
103/**
104 * Streams: write queue hooks.
105 */
106static struct qinit g_VBoxNetAdpSolarisWriteQ =
107{
108 gld_wput,
109 gld_wsrv,
110 NULL, /* open */
111 NULL, /* close */
112 NULL, /* admin (reserved) */
113 &g_VBoxNetAdpSolarisModInfo,
114 NULL /* module stats */
115};
116
117/**
118 * Streams: IO stream tab.
119 */
120static struct streamtab g_VBoxNetAdpSolarisStreamTab =
121{
122 &g_VBoxNetAdpSolarisReadQ,
123 &g_VBoxNetAdpSolarisWriteQ,
124 NULL, /* muxread init */
125 NULL /* muxwrite init */
126};
127
128/**
129 * cb_ops: driver char/block entry points
130 */
131static struct cb_ops g_VBoxNetAdpSolarisCbOps =
132{
133 nulldev, /* cb open */
134 nulldev, /* cb close */
135 nodev, /* b strategy */
136 nodev, /* b dump */
137 nodev, /* b print */
138 nodev, /* cb read */
139 nodev, /* cb write */
140 nodev, /* cb ioctl */
141 nodev, /* c devmap */
142 nodev, /* c mmap */
143 nodev, /* c segmap */
144 nochpoll, /* c poll */
145 ddi_prop_op, /* property ops */
146 &g_VBoxNetAdpSolarisStreamTab,
147 D_MP, /* compat. flag */
148 CB_REV /* revision */
149};
150
151/**
152 * dev_ops: driver entry/exit and other ops.
153 */
154static struct dev_ops g_VBoxNetAdpSolarisDevOps =
155{
156 DEVO_REV, /* driver build revision */
157 0, /* ref count */
158 gld_getinfo,
159 nulldev, /* identify */
160 nulldev, /* probe */
161 VBoxNetAdpSolarisAttach,
162 VBoxNetAdpSolarisDetach,
163 nodev, /* reset */
164 &g_VBoxNetAdpSolarisCbOps,
165 (struct bus_ops *)0,
166 nodev, /* power */
167 VBoxNetAdpSolarisQuiesceNotNeeded
168};
169
170/**
171 * modldrv: export driver specifics to kernel
172 */
173static struct modldrv g_VBoxNetAdpSolarisDriver =
174{
175 &mod_driverops, /* extern from kernel */
176 DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
177 &g_VBoxNetAdpSolarisDevOps
178};
179
180/**
181 * modlinkage: export install/remove/info to the kernel
182 */
183static struct modlinkage g_VBoxNetAdpSolarisModLinkage =
184{
185 MODREV_1, /* loadable module system revision */
186 {
187 &g_VBoxNetAdpSolarisDriver, /* adapter streams driver framework */
188 NULL /* terminate array of linkage structures */
189 }
190};
191
192
193/*******************************************************************************
194* Global Variables *
195*******************************************************************************/
196/** The default ethernet broadcast address */
197static uchar_t achBroadcastAddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
198
199/**
200 * vboxnetadp_state_t: per-instance data
201 */
202typedef struct vboxnetadp_state_t
203{
204 dev_info_t *pDip; /* device info. */
205 RTMAC FactoryMac; /* default 'factory' MAC address */
206 RTMAC CurrentMac; /* current MAC address */
207} vboxnetadp_state_t;
208
209
210/*******************************************************************************
211* Internal Functions *
212*******************************************************************************/
213static int vboxNetAdpSolarisGenerateMac(PRTMAC pMac);
214static int vboxNetAdpSolarisSetMacAddress(gld_mac_info_t *pMacInfo, unsigned char *pszMacAddr);
215static int vboxNetAdpSolarisSend(gld_mac_info_t *pMacInfo, mblk_t *pMsg);
216static int vboxNetAdpSolarisStub(gld_mac_info_t *pMacInfo);
217static int vboxNetAdpSolarisSetPromisc(gld_mac_info_t *pMacInfo, int fPromisc);
218static int vboxNetAdpSolarisSetMulticast(gld_mac_info_t *pMacInfo, unsigned char *pMulticastAddr, int fMulticast);
219static int vboxNetAdpSolarisGetStats(gld_mac_info_t *pMacInfo, struct gld_stats *pStats);
220
221
222/**
223 * Kernel entry points
224 */
225int _init(void)
226{
227 LogFunc((DEVICE_NAME ":_init\n"));
228
229 /*
230 * Prevent module autounloading.
231 */
232 modctl_t *pModCtl = mod_getctl(&g_VBoxNetAdpSolarisModLinkage);
233 if (pModCtl)
234 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
235 else
236 LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
237
238 /*
239 * Initialize IPRT.
240 */
241 int rc = RTR0Init(0);
242 if (RT_SUCCESS(rc))
243 {
244 rc = mod_install(&g_VBoxNetAdpSolarisModLinkage);
245 if (!rc)
246 return rc;
247
248 LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc));
249 RTR0Term();
250 }
251 else
252 LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc));
253
254 return RTErrConvertToErrno(rc);
255}
256
257
258int _fini(void)
259{
260 LogFunc((DEVICE_NAME ":_fini\n"));
261
262 /*
263 * Undo the work done during start (in reverse order).
264 */
265 RTR0Term();
266
267 return mod_remove(&g_VBoxNetAdpSolarisModLinkage);
268}
269
270
271int _info(struct modinfo *pModInfo)
272{
273 LogFunc((DEVICE_NAME ":_info\n"));
274
275 int rc = mod_info(&g_VBoxNetAdpSolarisModLinkage, pModInfo);
276
277 Log((DEVICE_NAME ":_info returns %d\n", rc));
278 return rc;
279}
280
281
282/**
283 * Attach entry point, to attach a device to the system or resume it.
284 *
285 * @param pDip The module structure instance.
286 * @param enmCmd Operation type (attach/resume).
287 *
288 * @returns corresponding solaris error code.
289 */
290static int VBoxNetAdpSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
291{
292 LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
293
294 int rc = -1;
295 switch (enmCmd)
296 {
297 case DDI_ATTACH:
298 {
299 gld_mac_info_t *pMacInfo = gld_mac_alloc(pDip);
300 if (pMacInfo)
301 {
302 vboxnetadp_state_t *pState = RTMemAllocZ(sizeof(vboxnetadp_state_t));
303 if (pState)
304 {
305 pState->pDip = pDip;
306
307 /*
308 * Setup GLD MAC layer registration info.
309 */
310 pMacInfo->gldm_reset = vboxNetAdpSolarisStub;
311 pMacInfo->gldm_start = vboxNetAdpSolarisStub;
312 pMacInfo->gldm_stop = vboxNetAdpSolarisStub;
313 pMacInfo->gldm_set_mac_addr = vboxNetAdpSolarisSetMacAddress;
314 pMacInfo->gldm_set_multicast = vboxNetAdpSolarisSetMulticast;
315 pMacInfo->gldm_set_promiscuous = vboxNetAdpSolarisSetPromisc;
316 pMacInfo->gldm_send = vboxNetAdpSolarisSend;
317 pMacInfo->gldm_intr = NULL;
318 pMacInfo->gldm_get_stats = vboxNetAdpSolarisGetStats;
319 pMacInfo->gldm_ioctl = NULL;
320 pMacInfo->gldm_ident = DEVICE_NAME;
321 pMacInfo->gldm_type = DL_ETHER;
322 pMacInfo->gldm_minpkt = 0;
323 pMacInfo->gldm_maxpkt = VBOXNETADP_MTU;
324 pMacInfo->gldm_capabilities = GLD_CAP_LINKSTATE;
325 AssertCompile(sizeof(RTMAC) == ETHERADDRL);
326
327 pMacInfo->gldm_addrlen = ETHERADDRL;
328 pMacInfo->gldm_saplen = -2;
329 pMacInfo->gldm_broadcast_addr = achBroadcastAddr;
330 pMacInfo->gldm_ppa = ddi_get_instance(pState->pDip);
331 pMacInfo->gldm_devinfo = pState->pDip;
332 pMacInfo->gldm_private = (caddr_t)pState;
333
334 /*
335 * We use a semi-random MAC addresses similar to a guest NIC's MAC address
336 * as the default factory address of the interface.
337 */
338 rc = vboxNetAdpSolarisGenerateMac(&pState->FactoryMac);
339 if (RT_SUCCESS(rc))
340 {
341 bcopy(&pState->FactoryMac, &pState->CurrentMac, sizeof(RTMAC));
342 pMacInfo->gldm_vendor_addr = (unsigned char *)&pState->FactoryMac;
343
344 /*
345 * Now try registering our GLD with the MAC layer.
346 * Registration can fail on some S10 versions when the MTU size is more than 1500.
347 * When we implement jumbo frames we should probably retry with MTU 1500 for S10.
348 */
349 rc = gld_register(pDip, (char *)ddi_driver_name(pDip), pMacInfo);
350 if (rc == DDI_SUCCESS)
351 {
352 ddi_report_dev(pDip);
353 gld_linkstate(pMacInfo, GLD_LINKSTATE_UP);
354 return DDI_SUCCESS;
355 }
356 else
357 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to register GLD. rc=%d\n", rc));
358 }
359 else
360 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to generate mac address.rc=%d\n"));
361
362 RTMemFree(pState);
363 }
364 else
365 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to alloc state.\n"));
366
367 gld_mac_free(pMacInfo);
368 }
369 else
370 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisAttach failed to alloc mac structure.\n"));
371 return DDI_FAILURE;
372 }
373
374 case DDI_RESUME:
375 {
376 /* Nothing to do here... */
377 return DDI_SUCCESS;
378 }
379
380 /* case DDI_PM_RESUME: */
381 default:
382 return DDI_FAILURE;
383 }
384}
385
386
387/**
388 * Detach entry point, to detach a device to the system or suspend it.
389 *
390 * @param pDip The module structure instance.
391 * @param enmCmd Operation type (detach/suspend).
392 *
393 * @returns corresponding solaris error code.
394 */
395static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
396{
397 LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));
398
399 switch (enmCmd)
400 {
401 case DDI_DETACH:
402 {
403 /*
404 * Unregister and clean up.
405 */
406 gld_mac_info_t *pMacInfo = ddi_get_driver_private(pDip);
407 if (pMacInfo)
408 {
409 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
410 if (pState)
411 {
412 gld_linkstate(pMacInfo, GLD_LINKSTATE_DOWN);
413 int rc = gld_unregister(pMacInfo);
414 if (rc == DDI_SUCCESS)
415 {
416 gld_mac_free(pMacInfo);
417 RTMemFree(pState);
418 return DDI_SUCCESS;
419 }
420 else
421 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to unregister GLD from MAC layer.rc=%d\n", rc));
422 }
423 else
424 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get internal state.\n"));
425 }
426 else
427 LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get driver private GLD data.\n"));
428
429 return DDI_FAILURE;
430 }
431
432 case DDI_RESUME:
433 {
434 /* Nothing to do here... */
435 return DDI_SUCCESS;
436 }
437
438 /* case DDI_SUSPEND: */
439 /* case DDI_HOTPLUG_DETACH: */
440 default:
441 return DDI_FAILURE;
442 }
443}
444
445
446/**
447 * Quiesce not-needed entry point, as Solaris 10 doesn't have any
448 * ddi_quiesce_not_needed() function.
449 *
450 * @param pDip The module structure instance.
451 *
452 * @return corresponding solaris error code.
453 */
454static int VBoxNetAdpSolarisQuiesceNotNeeded(dev_info_t *pDip)
455{
456 return DDI_SUCCESS;
457}
458
459
460static int vboxNetAdpSolarisGenerateMac(PRTMAC pMac)
461{
462 pMac->au8[0] = 0x08;
463 pMac->au8[1] = 0x00;
464 pMac->au8[2] = 0x27;
465 RTRandBytes(&pMac->au8[3], 3);
466 Log((DEVICE_NAME ":VBoxNetAdpSolarisGenerateMac Generated %.*Rhxs\n", sizeof(RTMAC), &pMac));
467 return VINF_SUCCESS;
468}
469
470
471static int vboxNetAdpSolarisSetMacAddress(gld_mac_info_t *pMacInfo, unsigned char *pszMacAddr)
472{
473 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
474 if (pState)
475 {
476 bcopy(pszMacAddr, &pState->CurrentMac, sizeof(RTMAC));
477 Log((DEVICE_NAME ":vboxNetAdpSolarisSetMacAddress updated MAC %.*Rhxs\n", sizeof(RTMAC), &pState->CurrentMac));
478 return GLD_SUCCESS;
479 }
480 else
481 LogRel((DEVICE_NAME ":vboxNetAdpSolarisSetMacAddress failed to get internal state.\n"));
482 return GLD_FAILURE;
483}
484
485
486static int vboxNetAdpSolarisSend(gld_mac_info_t *pMacInfo, mblk_t *pMsg)
487{
488 while (pMsg)
489 {
490 mblk_t *pMsgNext = pMsg->b_cont;
491 pMsg->b_cont = NULL;
492 freemsg(pMsg);
493 pMsg = pMsgNext;
494 }
495 return GLD_SUCCESS;
496}
497
498
499static int vboxNetAdpSolarisStub(gld_mac_info_t *pMacInfo)
500{
501 return GLD_SUCCESS;
502}
503
504
505static int vboxNetAdpSolarisSetMulticast(gld_mac_info_t *pMacInfo, unsigned char *pMulticastAddr, int fMulticast)
506{
507 return GLD_SUCCESS;
508}
509
510
511static int vboxNetAdpSolarisSetPromisc(gld_mac_info_t *pMacInfo, int fPromisc)
512{
513 /* Host requesting promiscuous intnet connection... */
514 return GLD_SUCCESS;
515}
516
517
518static int vboxNetAdpSolarisGetStats(gld_mac_info_t *pMacInfo, struct gld_stats *pStats)
519{
520 /*
521 * For now fake up stats. Stats like duplex and speed are better set as they
522 * are used in utilities like dladm. Link state capabilities are critical
523 * as they are used by ipadm while trying to restore persistent interface configs.
524 */
525 vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
526 if (pState)
527 {
528 pStats->glds_speed = 1000000000ULL; /* Bits/sec. */
529 pStats->glds_media = GLDM_UNKNOWN; /* Media/Connector Type */
530 pStats->glds_intr = 0; /* Interrupt count */
531 pStats->glds_norcvbuf = 0; /* Recv. discards */
532 pStats->glds_errxmt = 0; /* Xmit errors */
533 pStats->glds_errrcv = 0; /* Recv. errors */
534 pStats->glds_missed = 0; /* Pkt Drops on Recv. */
535 pStats->glds_underflow = 0; /* Buffer underflows */
536 pStats->glds_overflow = 0; /* Buffer overflows */
537
538 /* Ether */
539 pStats->glds_frame = 0; /* Align errors */
540 pStats->glds_crc = 0; /* CRC errors */
541 pStats->glds_duplex = GLD_DUPLEX_FULL; /* Link duplex state */
542 pStats->glds_nocarrier = 0; /* Carrier sense errors */
543 pStats->glds_collisions = 0; /* Xmit Collisions */
544 pStats->glds_excoll = 0; /* Frame discard due to excess collisions */
545 pStats->glds_xmtlatecoll = 0; /* Late collisions */
546 pStats->glds_defer = 0; /* Deferred Xmits */
547 pStats->glds_dot3_first_coll = 0; /* Single collision frames */
548 pStats->glds_dot3_multi_coll = 0; /* Multiple collision frames */
549 pStats->glds_dot3_sqe_error = 0; /* SQE errors */
550 pStats->glds_dot3_mac_xmt_error = 0; /* MAC Xmit errors */
551 pStats->glds_dot3_mac_rcv_error = 0; /* Mac Recv. errors */
552 pStats->glds_dot3_frame_too_long = 0; /* Frame too long errors */
553 pStats->glds_short = 0; /* Runt frames */
554
555 pStats->glds_noxmtbuf = 0; /* Xmit Buf errors */
556 pStats->glds_xmtretry = 0; /* Xmit retries */
557 pStats->glds_multixmt = 0; /* Multicast Xmits */
558 pStats->glds_multircv = 0; /* Multicast Recvs. */
559 pStats->glds_brdcstxmt = 0; /* Broadcast Xmits*/
560 pStats->glds_brdcstrcv = 0; /* Broadcast Recvs. */
561
562 return GLD_SUCCESS;
563 }
564 else
565 LogRel((DEVICE_NAME ":vboxNetAdpSolarisGetStats failed to get internal state.\n"));
566 return GLD_FAILURE;
567}
568
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette