Changeset 69979 in vbox
- Timestamp:
- Dec 7, 2017 1:34:16 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119485
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-netbsd.c
r69936 r69979 24 24 * terms and conditions of either the GPL or the CDDL or both. 25 25 */ 26 27 /** @todo r=bird: This must merge with SUPDrv-netbsd.c before long. The two28 * source files should only differ on prefixes and the extra bits wrt to the29 * pci device. I.e. it should be diffable so that fixes to one can easily be30 * applied to the other. */31 26 32 27 … … 121 116 *********************************************************************************************************************************/ 122 117 /* 118 * Driver(9) autoconf machinery. 119 */ 120 static int VBoxGuestNetBSDMatch(device_t parent, cfdata_t match, void *aux); 121 static void VBoxGuestNetBSDAttach(device_t parent, device_t self, void *aux); 122 static int VBoxGuestNetBSDDetach(device_t self, int flags); 123 124 /* 125 * IRQ related functions. 126 */ 127 static int VBoxGuestNetBSDAddIRQ(vboxguest_softc *sc, struct pci_attach_args *pa); 128 static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *sc); 129 static int VBoxGuestNetBSDISR(void *pvState); 130 131 /* 123 132 * Character device file handlers. 124 133 */ … … 128 137 static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data); 129 138 static 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);139 139 140 140 … … 181 181 extern struct cfdriver vboxguest_cd; 182 182 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 184 CFATTACH_DECL_NEW(vboxguest, sizeof(vboxguest_softc), 185 VBoxGuestNetBSDMatch, VBoxGuestNetBSDAttach, VBoxGuestNetBSDDetach, NULL); 186 187 188 static 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 } 254 197 255 198 return 0; 256 199 } 257 200 258 /**259 * IOCTL handler260 *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 that298 * 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 > cbReq320 || 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 else373 {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 else405 {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 #endif483 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->ih493 #if __NetBSD_Prereq__(6, 99, 39)494 , intstrbuf, sizeof(intstrbuf)495 #endif496 );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 }523 201 524 202 static void VBoxGuestNetBSDAttach(device_t parent, device_t self, void *aux) … … 556 234 * Allocate I/O port resource. 557 235 */ 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); 559 239 560 240 if (ioh_valid) … … 564 244 * Map the MMIO region. 565 245 */ 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); 567 249 if (memh_valid) 568 250 { … … 571 253 */ 572 254 rc = VGDrvCommonInitDevExt(&g_DevExt, vboxguest->uIOPortBase, 573 bus_space_vaddr(vboxguest->iVMMDevMemResId,574 vboxguest->VMMDevMemHandle),255 bus_space_vaddr(vboxguest->iVMMDevMemResId, 256 vboxguest->VMMDevMemHandle), 575 257 vboxguest->VMMDevMemSize, 576 258 #if ARCH_BITS == 64 … … 614 296 } 615 297 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 */ 306 static 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 341 static 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(); 626 366 627 367 return 0; 628 368 } 369 370 371 /** 372 * Removes IRQ for VMMDev. 373 * 374 * @param vboxguest Opaque pointer to the state info structure. 375 */ 376 static 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 */ 393 static 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 */ 406 void 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 */ 421 static 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 */ 477 static 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 */ 496 static 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 506 static 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 620 static 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 629 648 630 649 /** … … 671 690 } 672 691 673 CFATTACH_DECL_NEW(vboxguest, sizeof(vboxguest_softc),674 VBoxGuestNetBSDMatch, VBoxGuestNetBSDAttach, VBoxGuestNetBSDDetach, NULL);675 692 676 693 MODULE(MODULE_CLASS_DRIVER, vboxguest, "pci");
Note:
See TracChangeset
for help on using the changeset viewer.