VirtualBox

Changeset 69979 in vbox


Ignore:
Timestamp:
Dec 7, 2017 1:34:16 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119485
Message:

VBoxGuest-netbsd.c: shuffle the code around to make the narration
organized more like that of a typical NetBSD driver. Mostly moves
autoconf machinery to the beginning. While here fix a couple of
indentation botches. No functional changes intended.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-netbsd.c

    r69936 r69979  
    2424 * terms and conditions of either the GPL or the CDDL or both.
    2525 */
    26 
    27 /** @todo r=bird: This must merge with SUPDrv-netbsd.c before long. The two
    28  * source files should only differ on prefixes and the extra bits wrt to the
    29  * pci device. I.e. it should be diffable so that fixes to one can easily be
    30  * applied to the other. */
    3126
    3227
     
    121116*********************************************************************************************************************************/
    122117/*
     118 * Driver(9) autoconf machinery.
     119 */
     120static int VBoxGuestNetBSDMatch(device_t parent, cfdata_t match, void *aux);
     121static void VBoxGuestNetBSDAttach(device_t parent, device_t self, void *aux);
     122static int VBoxGuestNetBSDDetach(device_t self, int flags);
     123
     124/*
     125 * IRQ related functions.
     126 */
     127static int  VBoxGuestNetBSDAddIRQ(vboxguest_softc *sc, struct pci_attach_args *pa);
     128static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *sc);
     129static int  VBoxGuestNetBSDISR(void *pvState);
     130
     131/*
    123132 * Character device file handlers.
    124133 */
     
    128137static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data);
    129138static int VBoxGuestNetBSDPoll(struct file *fp, int events);
    130 static void VBoxGuestNetBSDAttach(device_t, device_t, void*);
    131 static int VBoxGuestNetBSDDetach(device_t pDevice, int flags);
    132 
    133 /*
    134  * IRQ related functions.
    135  */
    136 static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *sc);
    137 static int  VBoxGuestNetBSDAddIRQ(vboxguest_softc *pvState, struct pci_attach_args *pa);
    138 static int  VBoxGuestNetBSDISR(void *pvState);
    139139
    140140
     
    181181extern struct cfdriver vboxguest_cd;
    182182
    183 /**
    184  * File open handler
    185  *
    186  */
    187 static int VBoxGuestNetBSDOpen(dev_t device, int flags, int fmt, struct lwp *process)
    188 {
    189     int rc;
    190     vboxguest_softc *vboxguest;
    191     struct vboxguest_session *session;
    192     file_t *fp;
    193     int fd, error;
    194 
    195     LogFlow((DEVICE_NAME ": %s\n", __func__));
    196 
    197     if ((vboxguest = device_lookup_private(&vboxguest_cd, minor(device))) == NULL)
    198     {
    199         printf("device_lookup_private failed\n");
    200         return (ENXIO);
    201     }
    202 
    203     if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0)
    204     {
    205         aprint_error_dev(vboxguest->sc_dev, "device not configured\n");
    206         return (ENXIO);
    207     }
    208 
    209     session = kmem_alloc(sizeof(*session), KM_SLEEP);
    210     if (session == NULL)
    211     {
    212         return (ENOMEM);
    213     }
    214 
    215     session->sc = vboxguest;
    216 
    217     if ((error = fd_allocfile(&fp, &fd)) != 0)
    218     {
    219         kmem_free(session, sizeof(*session));
    220         return error;
    221     }
    222 
    223     /*
    224      * Create a new session.
    225      */
    226     rc = VGDrvCommonCreateUserSession(&g_DevExt, &session->session);
    227     if (! RT_SUCCESS(rc))
    228     {
    229         aprint_error_dev(vboxguest->sc_dev, "VBox session creation failed\n");
    230         closef(fp); /* ??? */
    231         kmem_free(session, sizeof(*session));
    232         return RTErrConvertToErrno(rc);
    233     }
    234     ASMAtomicIncU32(&cUsers);
    235     return fd_clone(fp, fd, flags, &vboxguest_fileops, session);
    236 
    237 }
    238 
    239 /**
    240  * File close handler
    241  *
    242  */
    243 static int VBoxGuestNetBSDClose(struct file *fp)
    244 {
    245     struct vboxguest_session *session = fp->f_data;
    246     vboxguest_softc *vboxguest = session->sc;
    247 
    248     LogFlow((DEVICE_NAME ": %s\n", __func__));
    249 
    250     VGDrvCommonCloseSession(&g_DevExt, session->session);
    251     ASMAtomicDecU32(&cUsers);
    252 
    253     kmem_free(session, sizeof(*session));
     183
     184CFATTACH_DECL_NEW(vboxguest, sizeof(vboxguest_softc),
     185    VBoxGuestNetBSDMatch, VBoxGuestNetBSDAttach, VBoxGuestNetBSDDetach, NULL);
     186
     187
     188static int VBoxGuestNetBSDMatch(device_t parent, cfdata_t match, void *aux)
     189{
     190    const struct pci_attach_args *pa = aux;
     191
     192    if (   PCI_VENDOR(pa->pa_id) == VMMDEV_VENDORID
     193        && PCI_PRODUCT(pa->pa_id) == VMMDEV_DEVICEID)
     194    {
     195        return 1;
     196    }
    254197
    255198    return 0;
    256199}
    257200
    258 /**
    259  * IOCTL handler
    260  *
    261  */
    262 static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long command, void *data)
    263 {
    264     struct vboxguest_session *session = fp->f_data;
    265 
    266     if (VBGL_IOCTL_IS_FAST(command))
    267         return VGDrvCommonIoCtlFast(command, &g_DevExt, session->session);
    268 
    269     return VBoxGuestNetBSDIOCtlSlow(session, command, data);
    270 }
    271 
    272 static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data)
    273 {
    274     vboxguest_softc *vboxguest = session->sc;
    275     size_t cbReq = IOCPARM_LEN(command);
    276     PVBGLREQHDR pHdr = NULL;
    277     void *pvUser = NULL;
    278     int err, rc;
    279 
    280     LogFlow(("%s: command=%#lx data=%p\n", __func__, command, data));
    281 
    282     /*
    283      * Buffered request?
    284      */
    285     if ((command & IOC_DIRMASK) == IOC_INOUT)
    286     {
    287         /* will be validated by VGDrvCommonIoCtl() */
    288         pHdr = (PVBGLREQHDR)data;
    289     }
    290 
    291     /*
    292      * Big unbuffered request?  "data" is the userland pointer.
    293      */
    294     else if ((command & IOC_DIRMASK) == IOC_VOID && cbReq != 0)
    295     {
    296         /*
    297          * Read the header, validate it and figure out how much that
    298          * needs to be buffered.
    299          */
    300         VBGLREQHDR Hdr;
    301 
    302         if (RT_UNLIKELY(cbReq < sizeof(Hdr)))
    303             return ENOTTY;
    304 
    305         pvUser = data;
    306         err = copyin(pvUser, &Hdr, sizeof(Hdr));
    307         if (RT_UNLIKELY(err != 0))
    308             return err;
    309 
    310         if (RT_UNLIKELY(Hdr.uVersion != VBGLREQHDR_VERSION))
    311             return ENOTTY;
    312 
    313         if (cbReq > 16 * _1M)
    314             return EINVAL;
    315 
    316         if (Hdr.cbOut == 0)
    317             Hdr.cbOut = Hdr.cbIn;
    318 
    319         if (RT_UNLIKELY(   Hdr.cbIn  < sizeof(Hdr) || Hdr.cbIn  > cbReq
    320                         || Hdr.cbOut < sizeof(Hdr) || Hdr.cbOut > cbReq))
    321             return EINVAL;
    322 
    323         /*
    324          * Allocate buffer and copy in the data.
    325          */
    326         cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);
    327 
    328         pHdr = (PVBGLREQHDR)RTMemTmpAlloc(cbReq);
    329         if (RT_UNLIKELY(pHdr == NULL))
    330         {
    331             LogRel(("%s: command=%#lx data=%p: unable to allocate %zu bytes\n",
    332                     __func__, command, data, cbReq));
    333             return ENOMEM;
    334         }
    335 
    336         err = copyin(pvUser, pHdr, Hdr.cbIn);
    337         if (err != 0)
    338         {
    339             RTMemTmpFree(pHdr);
    340             return err;
    341         }
    342 
    343         if (Hdr.cbIn < cbReq)
    344             memset((uint8_t *)pHdr + Hdr.cbIn, '\0', cbReq - Hdr.cbIn);
    345     }
    346 
    347     /*
    348      * Process the IOCtl.
    349      */
    350     rc = VGDrvCommonIoCtl(command, &g_DevExt, session->session, pHdr, cbReq);
    351     if (RT_SUCCESS(rc))
    352     {
    353         err = 0;
    354 
    355         /*
    356          * If unbuffered, copy back the result before returning.
    357          */
    358         if (pvUser != NULL)
    359         {
    360             size_t cbOut = pHdr->cbOut;
    361             if (cbOut > cbReq)
    362             {
    363                 LogRel(("%s: command=%#lx data=%p: too much output: %zu > %zu\n",
    364                         __func__, command, data, cbOut, cbReq));
    365                 cbOut = cbReq;
    366             }
    367 
    368             err = copyout(pHdr, pvUser, cbOut);
    369             RTMemTmpFree(pHdr);
    370         }
    371     }
    372     else
    373     {
    374         LogRel(("%s: command=%#lx data=%p: error %Rrc\n",
    375                 __func__, command, data, rc));
    376 
    377         if (pvUser != NULL)
    378             RTMemTmpFree(pHdr);
    379 
    380         err = RTErrConvertToErrno(rc);
    381     }
    382 
    383     return err;
    384 }
    385 
    386 static int VBoxGuestNetBSDPoll(struct file *fp, int events)
    387 {
    388     struct vboxguest_session *session = fp->f_data;
    389     vboxguest_softc *vboxguest = session->sc;
    390 
    391     int rc = 0;
    392     int events_processed;
    393 
    394     uint32_t u32CurSeq;
    395 
    396     LogFlow((DEVICE_NAME ": %s\n", __func__));
    397 
    398     u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
    399     if (session->session->u32MousePosChangedSeq != u32CurSeq)
    400     {
    401         events_processed = events & (POLLIN | POLLRDNORM);
    402         session->session->u32MousePosChangedSeq = u32CurSeq;
    403     }
    404     else
    405     {
    406         events_processed = 0;
    407 
    408         selrecord(curlwp, &g_SelInfo);
    409     }
    410 
    411     return events_processed;
    412 }
    413 
    414 static int VBoxGuestNetBSDDetach(device_t self, int flags)
    415 {
    416     vboxguest_softc *vboxguest;
    417     vboxguest = device_private(self);
    418 
    419     LogFlow((DEVICE_NAME ": %s\n", __func__));
    420 
    421     if (cUsers > 0)
    422         return EBUSY;
    423 
    424     if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0)
    425         return 0;
    426 
    427     /*
    428      * Reverse what we did in VBoxGuestNetBSDAttach.
    429      */
    430 
    431     VBoxGuestNetBSDRemoveIRQ(vboxguest);
    432 
    433     VGDrvCommonDeleteDevExt(&g_DevExt);
    434 
    435     bus_space_unmap(vboxguest->iVMMDevMemResId, vboxguest->VMMDevMemHandle, vboxguest->VMMDevMemSize);
    436     bus_space_unmap(vboxguest->io_tag, vboxguest->io_handle, vboxguest->io_regsize);
    437 
    438     RTR0Term();
    439 
    440     return 0;
    441 }
    442 
    443 /**
    444  * Interrupt service routine.
    445  *
    446  * @returns Whether the interrupt was from VMMDev.
    447  * @param   pvState Opaque pointer to the device state.
    448  */
    449 static int VBoxGuestNetBSDISR(void *pvState)
    450 {
    451     LogFlow((DEVICE_NAME ": %s: pvState=%p\n", __func__, pvState));
    452 
    453     bool fOurIRQ = VGDrvCommonISR(&g_DevExt);
    454 
    455     return fOurIRQ ? 0 : 1;
    456 }
    457 
    458 void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
    459 {
    460     LogFlow((DEVICE_NAME ": %s\n", __func__));
    461 
    462     /*
    463      * Wake up poll waiters.
    464      */
    465     selnotify(&g_SelInfo, 0, 0);
    466 }
    467 
    468 /**
    469  * Sets IRQ for VMMDev.
    470  *
    471  * @returns NetBSD error code.
    472  * @param   vboxguest  Pointer to the state info structure.
    473  * @param   pa  Pointer to the PCI attach arguments.
    474  */
    475 static int VBoxGuestNetBSDAddIRQ(vboxguest_softc *vboxguest, struct pci_attach_args *pa)
    476 {
    477     int iResId = 0;
    478     int rc = 0;
    479     const char *intrstr;
    480 #if __NetBSD_Prereq__(6, 99, 39)
    481     char intstrbuf[100];
    482 #endif
    483 
    484     LogFlow((DEVICE_NAME ": %s\n", __func__));
    485 
    486     if (pci_intr_map(pa, &vboxguest->ih))
    487     {
    488         aprint_error_dev(vboxguest->sc_dev, "couldn't map interrupt.\n");
    489         return VERR_DEV_IO_ERROR;
    490     }
    491 
    492     intrstr = pci_intr_string(vboxguest->pc, vboxguest->ih
    493 #if __NetBSD_Prereq__(6, 99, 39)
    494                               , intstrbuf, sizeof(intstrbuf)
    495 #endif
    496                               );
    497     aprint_normal_dev(vboxguest->sc_dev, "interrupting at %s\n", intrstr);
    498 
    499     vboxguest->pfnIrqHandler = pci_intr_establish(vboxguest->pc, vboxguest->ih, IPL_BIO, VBoxGuestNetBSDISR, vboxguest);
    500     if (vboxguest->pfnIrqHandler == NULL)
    501     {
    502         aprint_error_dev(vboxguest->sc_dev, "couldn't establish interrupt\n");
    503         return VERR_DEV_IO_ERROR;
    504     }
    505 
    506     return VINF_SUCCESS;
    507 }
    508 
    509 /**
    510  * Removes IRQ for VMMDev.
    511  *
    512  * @param   vboxguest  Opaque pointer to the state info structure.
    513  */
    514 static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *vboxguest)
    515 {
    516     LogFlow((DEVICE_NAME ": %s\n", __func__));
    517 
    518     if (vboxguest->pfnIrqHandler)
    519     {
    520         pci_intr_disestablish(vboxguest->pc, vboxguest->pfnIrqHandler);
    521     }
    522 }
    523201
    524202static void VBoxGuestNetBSDAttach(device_t parent, device_t self, void *aux)
     
    556234     * Allocate I/O port resource.
    557235     */
    558     ioh_valid = (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0, &vboxguest->io_tag, &vboxguest->io_handle, &vboxguest->uIOPortBase, &vboxguest->io_regsize) == 0);
     236    ioh_valid = (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_IO, 0,
     237                                &vboxguest->io_tag, &vboxguest->io_handle,
     238                                &vboxguest->uIOPortBase, &vboxguest->io_regsize) == 0);
    559239
    560240    if (ioh_valid)
     
    564244         * Map the MMIO region.
    565245         */
    566         memh_valid = (pci_mapreg_map(pa, PCI_MAPREG_START+4, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR, &vboxguest->iVMMDevMemResId, &vboxguest->VMMDevMemHandle, &vboxguest->pMMIOBase, &vboxguest->VMMDevMemSize) == 0);
     246        memh_valid = (pci_mapreg_map(pa, PCI_MAPREG_START+4, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR,
     247                                     &vboxguest->iVMMDevMemResId, &vboxguest->VMMDevMemHandle,
     248                                     &vboxguest->pMMIOBase, &vboxguest->VMMDevMemSize) == 0);
    567249        if (memh_valid)
    568250        {
     
    571253             */
    572254            rc = VGDrvCommonInitDevExt(&g_DevExt, vboxguest->uIOPortBase,
    573                     bus_space_vaddr(vboxguest->iVMMDevMemResId,
    574                             vboxguest->VMMDevMemHandle),
     255                                       bus_space_vaddr(vboxguest->iVMMDevMemResId,
     256                                                       vboxguest->VMMDevMemHandle),
    575257                                       vboxguest->VMMDevMemSize,
    576258#if ARCH_BITS == 64
     
    614296}
    615297
    616 static int
    617 VBoxGuestNetBSDMatch(device_t parent, cfdata_t match, void *aux)
    618 {
    619     const struct pci_attach_args *pa = aux;
    620 
    621     if (   PCI_VENDOR(pa->pa_id) == VMMDEV_VENDORID
    622         && PCI_PRODUCT(pa->pa_id) == VMMDEV_DEVICEID)
    623     {
    624         return 1;
    625     }
     298
     299/**
     300 * Sets IRQ for VMMDev.
     301 *
     302 * @returns NetBSD error code.
     303 * @param   vboxguest  Pointer to the state info structure.
     304 * @param   pa  Pointer to the PCI attach arguments.
     305 */
     306static int VBoxGuestNetBSDAddIRQ(vboxguest_softc *vboxguest, struct pci_attach_args *pa)
     307{
     308    int iResId = 0;
     309    int rc = 0;
     310    const char *intrstr;
     311#if __NetBSD_Prereq__(6, 99, 39)
     312    char intstrbuf[100];
     313#endif
     314
     315    LogFlow((DEVICE_NAME ": %s\n", __func__));
     316
     317    if (pci_intr_map(pa, &vboxguest->ih))
     318    {
     319        aprint_error_dev(vboxguest->sc_dev, "couldn't map interrupt.\n");
     320        return VERR_DEV_IO_ERROR;
     321    }
     322
     323    intrstr = pci_intr_string(vboxguest->pc, vboxguest->ih
     324#if __NetBSD_Prereq__(6, 99, 39)
     325                              , intstrbuf, sizeof(intstrbuf)
     326#endif
     327                              );
     328    aprint_normal_dev(vboxguest->sc_dev, "interrupting at %s\n", intrstr);
     329
     330    vboxguest->pfnIrqHandler = pci_intr_establish(vboxguest->pc, vboxguest->ih, IPL_BIO, VBoxGuestNetBSDISR, vboxguest);
     331    if (vboxguest->pfnIrqHandler == NULL)
     332    {
     333        aprint_error_dev(vboxguest->sc_dev, "couldn't establish interrupt\n");
     334        return VERR_DEV_IO_ERROR;
     335    }
     336
     337    return VINF_SUCCESS;
     338}
     339
     340
     341static int VBoxGuestNetBSDDetach(device_t self, int flags)
     342{
     343    vboxguest_softc *vboxguest;
     344    vboxguest = device_private(self);
     345
     346    LogFlow((DEVICE_NAME ": %s\n", __func__));
     347
     348    if (cUsers > 0)
     349        return EBUSY;
     350
     351    if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0)
     352        return 0;
     353
     354    /*
     355     * Reverse what we did in VBoxGuestNetBSDAttach.
     356     */
     357
     358    VBoxGuestNetBSDRemoveIRQ(vboxguest);
     359
     360    VGDrvCommonDeleteDevExt(&g_DevExt);
     361
     362    bus_space_unmap(vboxguest->iVMMDevMemResId, vboxguest->VMMDevMemHandle, vboxguest->VMMDevMemSize);
     363    bus_space_unmap(vboxguest->io_tag, vboxguest->io_handle, vboxguest->io_regsize);
     364
     365    RTR0Term();
    626366
    627367    return 0;
    628368}
     369
     370
     371/**
     372 * Removes IRQ for VMMDev.
     373 *
     374 * @param   vboxguest  Opaque pointer to the state info structure.
     375 */
     376static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *vboxguest)
     377{
     378    LogFlow((DEVICE_NAME ": %s\n", __func__));
     379
     380    if (vboxguest->pfnIrqHandler)
     381    {
     382        pci_intr_disestablish(vboxguest->pc, vboxguest->pfnIrqHandler);
     383    }
     384}
     385
     386
     387/**
     388 * Interrupt service routine.
     389 *
     390 * @returns Whether the interrupt was from VMMDev.
     391 * @param   pvState Opaque pointer to the device state.
     392 */
     393static int VBoxGuestNetBSDISR(void *pvState)
     394{
     395    LogFlow((DEVICE_NAME ": %s: pvState=%p\n", __func__, pvState));
     396
     397    bool fOurIRQ = VGDrvCommonISR(&g_DevExt);
     398
     399    return fOurIRQ ? 0 : 1;
     400}
     401
     402
     403/*
     404 * Called by VGDrvCommonISR() if mouse position changed
     405 */
     406void VGDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
     407{
     408    LogFlow((DEVICE_NAME ": %s\n", __func__));
     409
     410    /*
     411     * Wake up poll waiters.
     412     */
     413    selnotify(&g_SelInfo, 0, 0);
     414}
     415
     416
     417/**
     418 * File open handler
     419 *
     420 */
     421static int VBoxGuestNetBSDOpen(dev_t device, int flags, int fmt, struct lwp *process)
     422{
     423    int rc;
     424    vboxguest_softc *vboxguest;
     425    struct vboxguest_session *session;
     426    file_t *fp;
     427    int fd, error;
     428
     429    LogFlow((DEVICE_NAME ": %s\n", __func__));
     430
     431    if ((vboxguest = device_lookup_private(&vboxguest_cd, minor(device))) == NULL)
     432    {
     433        printf("device_lookup_private failed\n");
     434        return (ENXIO);
     435    }
     436
     437    if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0)
     438    {
     439        aprint_error_dev(vboxguest->sc_dev, "device not configured\n");
     440        return (ENXIO);
     441    }
     442
     443    session = kmem_alloc(sizeof(*session), KM_SLEEP);
     444    if (session == NULL)
     445    {
     446        return (ENOMEM);
     447    }
     448
     449    session->sc = vboxguest;
     450
     451    if ((error = fd_allocfile(&fp, &fd)) != 0)
     452    {
     453        kmem_free(session, sizeof(*session));
     454        return error;
     455    }
     456
     457    /*
     458     * Create a new session.
     459     */
     460    rc = VGDrvCommonCreateUserSession(&g_DevExt, &session->session);
     461    if (! RT_SUCCESS(rc))
     462    {
     463        aprint_error_dev(vboxguest->sc_dev, "VBox session creation failed\n");
     464        closef(fp); /* ??? */
     465        kmem_free(session, sizeof(*session));
     466        return RTErrConvertToErrno(rc);
     467    }
     468    ASMAtomicIncU32(&cUsers);
     469    return fd_clone(fp, fd, flags, &vboxguest_fileops, session);
     470
     471}
     472
     473/**
     474 * File close handler
     475 *
     476 */
     477static int VBoxGuestNetBSDClose(struct file *fp)
     478{
     479    struct vboxguest_session *session = fp->f_data;
     480    vboxguest_softc *vboxguest = session->sc;
     481
     482    LogFlow((DEVICE_NAME ": %s\n", __func__));
     483
     484    VGDrvCommonCloseSession(&g_DevExt, session->session);
     485    ASMAtomicDecU32(&cUsers);
     486
     487    kmem_free(session, sizeof(*session));
     488
     489    return 0;
     490}
     491
     492/**
     493 * IOCTL handler
     494 *
     495 */
     496static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long command, void *data)
     497{
     498    struct vboxguest_session *session = fp->f_data;
     499
     500    if (VBGL_IOCTL_IS_FAST(command))
     501        return VGDrvCommonIoCtlFast(command, &g_DevExt, session->session);
     502
     503    return VBoxGuestNetBSDIOCtlSlow(session, command, data);
     504}
     505
     506static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data)
     507{
     508    vboxguest_softc *vboxguest = session->sc;
     509    size_t cbReq = IOCPARM_LEN(command);
     510    PVBGLREQHDR pHdr = NULL;
     511    void *pvUser = NULL;
     512    int err, rc;
     513
     514    LogFlow(("%s: command=%#lx data=%p\n", __func__, command, data));
     515
     516    /*
     517     * Buffered request?
     518     */
     519    if ((command & IOC_DIRMASK) == IOC_INOUT)
     520    {
     521        /* will be validated by VGDrvCommonIoCtl() */
     522        pHdr = (PVBGLREQHDR)data;
     523    }
     524
     525    /*
     526     * Big unbuffered request?  "data" is the userland pointer.
     527     */
     528    else if ((command & IOC_DIRMASK) == IOC_VOID && cbReq != 0)
     529    {
     530        /*
     531         * Read the header, validate it and figure out how much that
     532         * needs to be buffered.
     533         */
     534        VBGLREQHDR Hdr;
     535
     536        if (RT_UNLIKELY(cbReq < sizeof(Hdr)))
     537            return ENOTTY;
     538
     539        pvUser = data;
     540        err = copyin(pvUser, &Hdr, sizeof(Hdr));
     541        if (RT_UNLIKELY(err != 0))
     542            return err;
     543
     544        if (RT_UNLIKELY(Hdr.uVersion != VBGLREQHDR_VERSION))
     545            return ENOTTY;
     546
     547        if (cbReq > 16 * _1M)
     548            return EINVAL;
     549
     550        if (Hdr.cbOut == 0)
     551            Hdr.cbOut = Hdr.cbIn;
     552
     553        if (RT_UNLIKELY(   Hdr.cbIn  < sizeof(Hdr) || Hdr.cbIn  > cbReq
     554                        || Hdr.cbOut < sizeof(Hdr) || Hdr.cbOut > cbReq))
     555            return EINVAL;
     556
     557        /*
     558         * Allocate buffer and copy in the data.
     559         */
     560        cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);
     561
     562        pHdr = (PVBGLREQHDR)RTMemTmpAlloc(cbReq);
     563        if (RT_UNLIKELY(pHdr == NULL))
     564        {
     565            LogRel(("%s: command=%#lx data=%p: unable to allocate %zu bytes\n",
     566                    __func__, command, data, cbReq));
     567            return ENOMEM;
     568        }
     569
     570        err = copyin(pvUser, pHdr, Hdr.cbIn);
     571        if (err != 0)
     572        {
     573            RTMemTmpFree(pHdr);
     574            return err;
     575        }
     576
     577        if (Hdr.cbIn < cbReq)
     578            memset((uint8_t *)pHdr + Hdr.cbIn, '\0', cbReq - Hdr.cbIn);
     579    }
     580
     581    /*
     582     * Process the IOCtl.
     583     */
     584    rc = VGDrvCommonIoCtl(command, &g_DevExt, session->session, pHdr, cbReq);
     585    if (RT_SUCCESS(rc))
     586    {
     587        err = 0;
     588
     589        /*
     590         * If unbuffered, copy back the result before returning.
     591         */
     592        if (pvUser != NULL)
     593        {
     594            size_t cbOut = pHdr->cbOut;
     595            if (cbOut > cbReq)
     596            {
     597                LogRel(("%s: command=%#lx data=%p: too much output: %zu > %zu\n",
     598                        __func__, command, data, cbOut, cbReq));
     599                cbOut = cbReq;
     600            }
     601
     602            err = copyout(pHdr, pvUser, cbOut);
     603            RTMemTmpFree(pHdr);
     604        }
     605    }
     606    else
     607    {
     608        LogRel(("%s: command=%#lx data=%p: error %Rrc\n",
     609                __func__, command, data, rc));
     610
     611        if (pvUser != NULL)
     612            RTMemTmpFree(pHdr);
     613
     614        err = RTErrConvertToErrno(rc);
     615    }
     616
     617    return err;
     618}
     619
     620static int VBoxGuestNetBSDPoll(struct file *fp, int events)
     621{
     622    struct vboxguest_session *session = fp->f_data;
     623    vboxguest_softc *vboxguest = session->sc;
     624
     625    int rc = 0;
     626    int events_processed;
     627
     628    uint32_t u32CurSeq;
     629
     630    LogFlow((DEVICE_NAME ": %s\n", __func__));
     631
     632    u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
     633    if (session->session->u32MousePosChangedSeq != u32CurSeq)
     634    {
     635        events_processed = events & (POLLIN | POLLRDNORM);
     636        session->session->u32MousePosChangedSeq = u32CurSeq;
     637    }
     638    else
     639    {
     640        events_processed = 0;
     641
     642        selrecord(curlwp, &g_SelInfo);
     643    }
     644
     645    return events_processed;
     646}
     647
    629648
    630649/**
     
    671690}
    672691
    673 CFATTACH_DECL_NEW(vboxguest, sizeof(vboxguest_softc),
    674     VBoxGuestNetBSDMatch, VBoxGuestNetBSDAttach, VBoxGuestNetBSDDetach, NULL);
    675692
    676693MODULE(MODULE_CLASS_DRIVER, vboxguest, "pci");
Note: See TracChangeset for help on using the changeset viewer.

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