VirtualBox

Ignore:
Timestamp:
Sep 24, 2007 3:47:01 AM (17 years ago)
Author:
vboxsync
Message:

did the freebsd device skeleton. the cloning doesn't seem quiet stable yet wrt unloading (may panic).

Location:
trunk/src/VBox/HostDrivers/Support/freebsd
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c

    r4800 r4988  
    4141#include <sys/errno.h>
    4242#include <sys/kernel.h>
     43#include <sys/fcntl.h>
    4344#include <sys/conf.h>
    4445#include <sys/uio.h>
     
    5253#include <iprt/assert.h>
    5354#include <iprt/log.h>
     55#include <iprt/alloc.h>
     56#include <iprt/err.h>
    5457
    5558
     
    6063static int VBoxDrvFreeBSDLoad(void);
    6164static int VBoxDrvFreeBSDUnload(void);
     65static void VBoxDrvFreeBSDClone(void *pvArg, struct ucred *pCred, char *pachName, int cchName, struct cdev **ppDev);
     66
    6267static d_fdopen_t   VBoxDrvFreeBSDOpen;
    6368static d_close_t    VBoxDrvFreeBSDClose;
    6469static d_ioctl_t    VBoxDrvFreeBSDIOCtl;
    65 static int VBoxDrvFreeBsdErr2Native(int rc);
     70static int          VBoxDrvFreeBSDIOCtlSlow(PSUPDRVSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd);
    6671
    6772
     
    7277 * Module info structure used by the kernel.
    7378 */
    74 static moduledata_t g_VBoxDrvFreeBSDModule =
     79static moduledata_t         g_VBoxDrvFreeBSDModule =
    7580{
    7681    "vboxdrv",
     
    8085
    8186/** Declare the module as a pseudo device. */
    82 DECLARE_MODULE(vboxdrv, g_VBoxDrvFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY);
     87DECLARE_MODULE(vboxdrv,     g_VBoxDrvFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY);
    8388
    8489/**
     
    8893{
    8994    .d_version =        D_VERSION,
    90     .d_flags =          D_TRACKCLOSE,
     95    .d_flags =          D_PSEUDO | D_TRACKCLOSE,
    9196    .d_fdopen =         VBoxDrvFreeBSDOpen,
    9297    .d_close =          VBoxDrvFreeBSDClose,
     
    95100};
    96101
    97 /** The make_dev result. */
    98 static struct cdev         *g_pVBoxDrvFreeBSDChrDev;
     102/** List of cloned device. Managed by the kernel. */
     103static struct clonedevs    *g_pVBoxDrvFreeBSDClones;
     104/** The dev_clone event handler tag. */
     105static eventhandler_tag     g_VBoxDrvFreeBSDEHTag;
    99106
    100107/** The device extention. */
    101 static SUPDRVDEVEXT         g_DevExt;
    102 
    103 /** Spinlock protecting g_apSessionHashTab. */
    104 static RTSPINLOCK           g_Spinlock = NIL_RTSPINLOCK;
    105 /** Hash table */
    106 static PSUPDRVSESSION       g_apSessionHashTab[19];
    107 /** Calculates the index into g_apSessionHashTab.*/
    108 #define SESSION_HASH(sfn)       ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
     108static SUPDRVDEVEXT         g_VBoxDrvFreeBSDDevExt;
    109109
    110110
     
    141141    if (RT_SUCCESS(rc))
    142142        return 0;
    143     return VBoxDrvFreeBsdErr2Native(rc);
     143    return RTErrConvertToErrno(rc);
    144144}
    145145
     
    158158         * Initialize the device extension.
    159159         */
    160         rc = supdrvInitDevExt(&g_DevExt);
     160        rc = supdrvInitDevExt(&g_VBoxDrvFreeBSDDevExt);
    161161        if (RT_SUCCESS(rc))
    162162        {
    163163            /*
    164              * Initialize the session hash table.
     164             * Configure device cloning.
    165165             */
    166             rc = RTSpinlockCreate(&g_Spinlock);
    167             if (RT_SUCCESS(rc))
     166            clone_setup(&g_pVBoxDrvFreeBSDClones);
     167            g_VBoxDrvFreeBSDEHTag = EVENTHANDLER_REGISTER(dev_clone, VBoxDrvFreeBSDClone, 0, 1000);
     168            if (g_VBoxDrvFreeBSDEHTag)
    168169            {
    169                 /*
    170                  * Create our device node.
    171                  */
    172                 /** @todo find a way to fix this 0666 permission issue. Perhaps by defining some vboxusers group with a fixed gid? */
    173                 g_pVBoxDrvFreeBSDChrDev = make_dev(&g_VBoxDrvFreeBSDChrDevSW,
    174                                                    0,
    175                                                    UID_ROOT,
    176                                                    GID_WHEEL,
    177                                                    0666,
    178                                                    "vboxdrv");
    179                 if (g_pVBoxDrvFreeBSDChrDev)
    180                 {
    181                     dprintf(("VBoxDrvFreeBSDLoad: returns successfully\n"));
    182                     return VINF_SUCCESS;
    183                 }
    184 
    185                 printf("vboxdrv: make_dev failed\n");
    186                 rc = SUPDRV_ERR_ALREADY_LOADED;
    187                 RTSpinlockDestroy(g_Spinlock);
    188                 g_Spinlock = NIL_RTSPINLOCK;
     170                dprintf(("VBoxDrvFreeBSDLoad: returns successfully\n"));
     171                return VINF_SUCCESS;
    189172            }
    190             else
    191                 printf("vboxdrv: RTSpinlockCreate failed, rc=%d\n", rc);
    192             supdrvDeleteDevExt(&g_DevExt);
     173
     174            printf("vboxdrv: EVENTHANDLER_REGISTER(dev_clone,,,) failed\n");
     175            clone_cleanup(&g_pVBoxDrvFreeBSDClones);
     176            rc = SUPDRV_ERR_ALREADY_LOADED;
     177            supdrvDeleteDevExt(&g_VBoxDrvFreeBSDDevExt);
    193178        }
    194179        else
     
    203188static int VBoxDrvFreeBSDUnload(void)
    204189{
    205     int rc;
    206190    dprintf(("VBoxDrvFreeBSDUnload:\n"));
    207191
     
    211195     * Reserve what we did in VBoxDrvFreeBSDInit.
    212196     */
    213     if (g_pVBoxDrvFreeBSDChrDev)
    214     {
    215         destroy_dev(g_pVBoxDrvFreeBSDChrDev);
    216         g_pVBoxDrvFreeBSDChrDev = NULL;
    217     }
    218 
    219     supdrvDeleteDevExt(&g_DevExt);
    220 
    221     rc = RTSpinlockDestroy(g_Spinlock);
    222     AssertRC(rc);
    223     g_Spinlock = NIL_RTSPINLOCK;
     197    clone_cleanup(&g_pVBoxDrvFreeBSDClones);
     198
     199    supdrvDeleteDevExt(&g_VBoxDrvFreeBSDDevExt);
    224200
    225201    RTR0Term();
    226202
    227     memset(&g_DevExt, 0, sizeof(g_DevExt));
     203    memset(&g_VBoxDrvFreeBSDDevExt, 0, sizeof(g_VBoxDrvFreeBSDDevExt));
    228204
    229205    dprintf(("VBoxDrvFreeBSDUnload: returns\n"));
     
    232208
    233209
    234 static int VBoxDrvFreeBSDOpen(struct cdev *dev, int oflags, struct thread *td, int fdidx)
    235 {
    236     dprintf(("VBoxDrvFreeBSDOpen:\n"));
    237     return EOPNOTSUPP;
    238 }
    239 
    240 
    241 static int VBoxDrvFreeBSDClose(struct cdev *dev, int fflag, int devtype, struct thread *td)
    242 {
    243     dprintf(("VBoxDrvFreeBSDClose:\n"));
    244     return EBADF;
    245 }
    246 
    247 
    248 static int VBoxDrvFreeBSDIOCtl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
    249 {
    250     dprintf(("VBoxDrvFreeBSDIOCtl:\n"));
    251     return EINVAL;
    252 }
    253 
    254 
    255 /**
    256  * Converts an supdrv error code to a FreeBSD error code.
    257  *
    258  * @returns corresponding FreeBSD error code.
    259  * @param   rc  supdrv error code (SUPDRV_ERR_* defines).
    260  */
    261 static int VBoxDrvFreeBsdErr2Native(int rc)
    262 {
    263     switch (rc)
    264     {
    265         case 0:                             return 0;
    266         case SUPDRV_ERR_GENERAL_FAILURE:    return EACCES;
    267         case SUPDRV_ERR_INVALID_PARAM:      return EINVAL;
    268         case SUPDRV_ERR_INVALID_MAGIC:      return EILSEQ;
    269         case SUPDRV_ERR_INVALID_HANDLE:     return ENXIO;
    270         case SUPDRV_ERR_INVALID_POINTER:    return EFAULT;
    271         case SUPDRV_ERR_LOCK_FAILED:        return ENOLCK;
    272         case SUPDRV_ERR_ALREADY_LOADED:     return EEXIST;
    273         case SUPDRV_ERR_PERMISSION_DENIED:  return EPERM;
    274         case SUPDRV_ERR_VERSION_MISMATCH:   return ENOSYS;
    275     }
    276 
    277     return EPERM;
    278 }
     210/**
     211 * DEVFS event handler.
     212 */
     213static void VBoxDrvFreeBSDClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev)
     214{
     215    int iUnit;
     216    int rc;
     217
     218    dprintf(("VBoxDrvFreeBSDClone: pszName=%s ppDev=%p\n", pszName, ppDev));
     219
     220    /*
     221     * One device node per user, si_drv1 points to the session.
     222     * /dev/vboxdrv<N> where N = {0...255}.
     223     */
     224    if (!ppDev)
     225        return;
     226    if (dev_stdclone(pszName, NULL, "vboxdrv", &iUnit) != 1)
     227        return;
     228    if (iUnit >= 256 || iUnit < 0)
     229    {
     230        dprintf(("VBoxDrvFreeBSDClone: iUnit=%d >= 256 - rejected\n", iUnit));
     231        return;
     232    }
     233
     234    dprintf(("VBoxDrvFreeBSDClone: pszName=%s iUnit=%d\n", pszName, iUnit));
     235
     236    rc = clone_create(&g_pVBoxDrvFreeBSDClones, &g_VBoxDrvFreeBSDChrDevSW, &iUnit, ppDev, 0);
     237    dprintf(("VBoxDrvFreeBSDClone: clone_create -> %d; iUnit=%d\n", rc, iUnit));
     238    if (rc)
     239    {
     240        *ppDev = make_dev(&g_VBoxDrvFreeBSDChrDevSW,
     241                          unit2minor(iUnit),
     242                          UID_ROOT,
     243                          GID_WHEEL,
     244                          0666,
     245                          "vboxdrv%d", iUnit);
     246        if (*ppDev)
     247        {
     248            dev_ref(*ppDev);
     249            (*ppDev)->si_flags |= SI_CHEAPCLONE;
     250            dprintf(("VBoxDrvFreeBSDClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
     251                     *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
     252            (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL;
     253        }
     254        else
     255            OSDBGPRINT(("VBoxDrvFreeBSDClone: make_dev iUnit=%d failed\n", iUnit));
     256    }
     257    else
     258        dprintf(("VBoxDrvFreeBSDClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n",
     259                 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2));
     260}
     261
     262
     263
     264/**
     265 *
     266 * @returns 0 on success, errno on failure.
     267 *          EBUSY if the device is used by someone else.
     268 * @param   pDev    The device node.
     269 * @param   fOpen   The open flags.
     270 * @param   pTd     The thread.
     271 * @param   pFd     The file descriptor. FreeBSD 7.0 and later.
     272 * @param   iFd     The file descriptor index(?). Pre FreeBSD 7.0.
     273 */
     274#if FreeBSD >= 700 /* figure when and how to check properly */
     275static int VBoxDrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd, struct file *pFd)
     276#else
     277static int VBoxDrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd, int iFd)
     278#endif
     279{
     280    PSUPDRVSESSION pSession;
     281    int rc;
     282
     283    dprintf(("VBoxDrvFreeBSDOpen: fOpen=%#x iUnit=%d\n", fOpen, minor2unit(minor(pDev))));
     284
     285    /*
     286     * Let's be a bit picky about the flags...
     287     */
     288    if (fOpen != (FREAD|FWRITE /*=O_RDWR*/))
     289    {
     290        dprintf(("VBoxDrvFreeBSDOpen: fOpen=%#x expected %#x\n", fOpen, O_RDWR));
     291        return EINVAL;
     292    }
     293
     294    /*
     295     * Try grab it (we don't grab the giant, remember).
     296     */
     297    if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL))
     298        return EBUSY;
     299
     300    /*
     301     * Create a new session.
     302     */
     303    rc = supdrvCreateSession(&g_VBoxDrvFreeBSDDevExt, &pSession);
     304    if (RT_SUCCESS(rc))
     305    {
     306        pSession->Uid = 0;
     307        pSession->Gid = 0;
     308        pSession->Process = RTProcSelf();
     309        pSession->R0Process = RTR0ProcHandleSelf();
     310        if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42))
     311            return 0;
     312
     313        OSDBGPRINT(("VBoxDrvFreeBSDOpen: si_drv1=%p, expected 0x42!\n", pDev->si_drv1));
     314        supdrvCloseSession(&g_VBoxDrvFreeBSDDevExt, pSession);
     315    }
     316
     317    return RTErrConvertToErrno(rc);
     318}
     319
     320
     321/**
     322 * Close a file device previously opened by VBoxDrvFreeBSDOpen
     323 *
     324 * @returns 0 on success.
     325 * @param   pDev        The device.
     326 * @param   fFile       The file descriptor flags.
     327 * @param   DevType     The device type (CHR.
     328 * @param   pTd         The calling thread.
     329 */
     330static int VBoxDrvFreeBSDClose(struct cdev *pDev, int fFile, int DevType, struct thread *pTd)
     331{
     332    PSUPDRVSESSION pSession = (PSUPDRVSESSION)pDev->si_drv1;
     333    dprintf(("VBoxDrvFreeBSDClose: fFile=%#x iUnit=%d pSession=%p\n", fFile, minor2unit(minor(pDev)), pSession));
     334
     335    /*
     336     * Close the session if it's still hanging on to the device...
     337     */
     338    if (VALID_PTR(pSession))
     339    {
     340        supdrvCloseSession(&g_VBoxDrvFreeBSDDevExt, pSession);
     341        if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, NULL, pSession))
     342            OSDBGPRINT(("VBoxDrvFreeBSDClose: si_drv1=%p expected %p!\n", pDev->si_drv1, pSession));
     343    }
     344    else
     345        OSDBGPRINT(("VBoxDrvFreeBSDClose: si_drv1=%p!\n", pSession));
     346    return 0;
     347}
     348
     349
     350/**
     351 * I/O control request.
     352 *
     353 * @returns depends...
     354 * @param   pDev        The device.
     355 * @param   ulCmd       The command.
     356 * @param   pvData      Pointer to the data.
     357 * @param   fFile       The file descriptor flags.
     358 * @param   pTd         The calling thread.
     359 */
     360static int VBoxDrvFreeBSDIOCtl(struct cdev *pDev, u_long ulCmd, caddr_t pvData, int fFile, struct thread *pTd)
     361{
     362    /*
     363     * Validate the input.
     364     */
     365    PSUPDRVSESSION pSession = (PSUPDRVSESSION)pDev->si_drv1;
     366    if (RT_UNLIKELY(!VALID_PTR(pSession)))
     367        return EINVAL;
     368
     369    /*
     370     * Deal with the fast ioctl path first.
     371     */
     372    if (    ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
     373        ||  ulCmd == SUP_IOCTL_FAST_DO_HWACC_RUN
     374        ||  ulCmd == SUP_IOCTL_FAST_DO_NOP)
     375        return supdrvIOCtlFast(ulCmd, &g_VBoxDrvFreeBSDDevExt, pSession);
     376
     377    return VBoxDrvFreeBSDIOCtlSlow(pSession, ulCmd, pvData, pTd);
     378}
     379
     380
     381/**
     382 * Deal with the 'slow' I/O control requests.
     383 *
     384 * @returns 0 on success, appropriate errno on failure.
     385 * @param   pSession    The session.
     386 * @param   ulCmd       The command.
     387 * @param   pvData      The request data.
     388 * @param   pTd         The calling thread.
     389 */
     390static int VBoxDrvFreeBSDIOCtlSlow(PSUPDRVSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd)
     391{
     392    PSUPREQHDR  pHdr;
     393    uint32_t    cbReq = IOCPARM_LEN(ulCmd);
     394    void       *pvUser = NULL;
     395
     396    /*
     397     * Buffered request?
     398     */
     399    if ((IOC_DIRMASK & ulCmd) == IOC_INOUT)
     400    {
     401        pHdr = (PSUPREQHDR)pvData;
     402        if (RT_UNLIKELY(cbReq < sizeof(*pHdr)))
     403        {
     404            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: cbReq=%#x < %#x; ulCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), ulCmd));
     405            return EINVAL;
     406        }
     407        if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
     408        {
     409            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", pHdr->fFlags, ulCmd));
     410            return EINVAL;
     411        }
     412        if (RT_UNLIKELY(    RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq
     413                        ||  pHdr->cbIn < sizeof(*pHdr)
     414                        ||  pHdr->cbOut < sizeof(*pHdr)))
     415        {
     416            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x) != %#x; ulCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, ulCmd));
     417            return EINVAL;
     418        }
     419    }
     420    /*
     421     * Big unbuffered request?
     422     */
     423    else if ((IOC_DIRMASK & ulCmd) == IOC_VOID && !cbReq)
     424    {
     425        /*
     426         * Read the header, validate it and figure out how much that needs to be buffered.
     427         */
     428        SUPREQHDR Hdr;
     429        pvUser = *(void **)pvData;
     430        int rc = copyin(pvUser, &Hdr, sizeof(Hdr));
     431        if (RT_UNLIKELY(rc))
     432        {
     433            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,Hdr,) -> %#x; ulCmd=%#lx\n", pvUser, rc, ulCmd));
     434            return rc;
     435        }
     436        if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
     437        {
     438            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", Hdr.fFlags, ulCmd));
     439            return EINVAL;
     440        }
     441        cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);
     442        if (RT_UNLIKELY(    Hdr.cbIn < sizeof(Hdr)
     443                        ||  Hdr.cbOut < sizeof(Hdr)
     444                        ||  cbReq > _1M*16))
     445        {
     446            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x); ulCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, ulCmd));
     447            return EINVAL;
     448        }
     449
     450        /*
     451         * Allocate buffer and copy in the data.
     452         */
     453        pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq);
     454        if (RT_UNLIKELY(!pHdr))
     455        {
     456            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: failed to allocate buffer of %d bytes; ulCmd=%#lx\n", cbReq, ulCmd));
     457            return ENOMEM;
     458        }
     459        rc = copyin(pvUser, pHdr, Hdr.cbIn);
     460        if (RT_UNLIKELY(rc))
     461        {
     462            OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,%p,%#x) -> %#x; ulCmd=%#lx\n",
     463                        pvUser, pHdr, Hdr.cbIn, rc, ulCmd));
     464            RTMemTmpFree(pHdr);
     465            return rc;
     466        }
     467    }
     468    else
     469    {
     470        dprintf(("VBoxDrvFreeBSDIOCtlSlow: huh? cbReq=%#x ulCmd=%#lx\n", cbReq, ulCmd));
     471        return EINVAL;
     472    }
     473
     474    /*
     475     * Process the IOCtl.
     476     */
     477    int rc = supdrvIOCtl(ulCmd, &g_VBoxDrvFreeBSDDevExt, pSession, pHdr);
     478    if (RT_LIKELY(!rc))
     479    {
     480        /*
     481         * If unbuffered, copy back the result before returning.
     482         */
     483        if (pvUser)
     484        {
     485            uint32_t cbOut = pHdr->cbOut;
     486            if (cbOut > cbReq)
     487            {
     488                OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, ulCmd));
     489                cbOut = cbReq;
     490            }
     491            rc = copyout(pHdr, pvUser, cbOut);
     492            if (RT_UNLIKELY(rc))
     493                OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyout(%p,%p,%#x) -> %d; uCmd=%#lx!\n", pHdr, pvUser, cbOut, rc, ulCmd));
     494
     495            /* cleanup */
     496            RTMemTmpFree(pHdr);
     497        }
     498        dprintf(("VBoxDrvFreeBSDIOCtlSlow: returns %d / %d ulCmd=%lx\n", 0, pHdr->rc, ulCmd));
     499    }
     500    else
     501    {
     502        /*
     503         * The request failed, just clean up.
     504         */
     505        if (pvUser)
     506            RTMemTmpFree(pHdr);
     507
     508        dprintf(("VBoxDrvFreeBSDIOCtlSlow: ulCmd=%lx pData=%p failed, rc=%d\n", ulCmd, pvData, rc));
     509        rc = EINVAL;
     510    }
     511
     512    return rc;
     513}
     514
    279515
    280516
  • trunk/src/VBox/HostDrivers/Support/freebsd/SUPLib-freebsd.cpp

    r4925 r4988  
    4343*   Defined Constants And Macros                                               *
    4444*******************************************************************************/
    45 /** BSD Device name. */
     45/** FreeBSD base device name. */
    4646#define DEVICE_NAME     "/dev/vboxdrv"
    4747
     
    6565     * Try open the BSD device.
    6666     */
    67     g_hDevice = open(DEVICE_NAME, O_RDWR, 0);
     67    char szDevice[sizeof(DEVICE_NAME) + 16];
     68    for (unsigned iUnit = 0; iUnit < 1024; iUnit++)
     69    {
     70        errno = 0;
     71        RTStrPrintf(szDevice, sizeof(szDevice), DEVICE_NAME "%d", iUnit);
     72        g_hDevice = open(szDevice, O_RDWR, 0);
     73        if (g_hDevice >= 0 || errno != EBUSY)
     74            break;
     75    }
    6876    if (g_hDevice < 0)
    6977    {
     
    7785            default:        rc = VERR_VM_DRIVER_OPEN_ERROR; break;
    7886        }
    79         LogRel(("Failed to open \"%s\", errno=%d, rc=%Vrc\n", DEVICE_NAME, errno, rc));
    80         return RTErrConvertFromErrno(rc);
     87        LogRel(("Failed to open \"%s\", errno=%d, rc=%Vrc\n", szDevice, errno, rc));
     88        return rc;
    8189    }
    8290
Note: See TracChangeset for help on using the changeset viewer.

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