Changeset 63339 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Aug 11, 2016 1:02:31 PM (8 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxGuest
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk
r63108 r63339 20 20 21 21 22 if1of ($(KBUILD_TARGET), darwin freebsd haiku $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linux,) os2 solaris win)22 if1of ($(KBUILD_TARGET), darwin freebsd haiku $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linux,) netbsd os2 solaris win) 23 23 # 24 24 # VBoxGuest - The Guest Additions Driver. … … 29 29 VBoxGuest_NAME.haiku = vboxguest 30 30 VBoxGuest_NAME.linux = vboxguest 31 VBoxGuest_NAME.netbsd = vboxguest 31 32 VBoxGuest_NAME.solaris = vboxguest 32 33 VBoxGuest_INST.darwin = $(INST_ADDITIONS)VBoxGuest.kext/Contents/MacOS/ … … 55 56 VBoxGuest_DEPS.haiku += $(VBOX_SVN_REV_HEADER) 56 57 VBoxGuest_DEPS.freebsd += $(VBOX_SVN_REV_HEADER) 58 VBoxGuest_DEPS.netbsd += $(VBOX_SVN_REV_HEADER) 57 59 VBoxGuest_DEPS.darwin += $(VBOX_SVN_REV_HEADER) 58 60 VBoxGuest_DEFS = VBGL_VBOXGUEST VBOX_WITH_HGCM 59 61 VBoxGuest_INCS = . 60 62 VBoxGuest_INCS.freebsd = $(VBoxGuest_0_OUTDIR) $(PATH_STAGE)/gen-sys-hdrs 63 VBoxGuest_INCS.netbsd = $(VBoxGuest_0_OUTDIR) 61 64 VBoxGuest_INCS.linux = ../../../Runtime/r0drv/linux 62 65 ifeq ($(KBUILD_HOST),solaris) … … 81 84 endif 82 85 endif # win 83 ifn1of ($(KBUILD_TARGET), linux freebsd solaris haiku)86 ifn1of ($(KBUILD_TARGET), linux freebsd netbsd solaris haiku) 84 87 VBoxGuest_SOURCES = VBoxGuest-$(KBUILD_TARGET).cpp 85 88 else -
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-netbsd.c
r63291 r63339 1 1 /* $Id$ */ 2 2 /** @file 3 * VirtualBox Guest Additions Driver for FreeBSD.3 * VirtualBox Guest Additions Driver for NetBSD. 4 4 */ 5 5 … … 16 16 */ 17 17 18 /** @todo r=bird: This must merge with SUPDrv- freebsd.c before long. The two18 /** @todo r=bird: This must merge with SUPDrv-netbsd.c before long. The two 19 19 * source files should only differ on prefixes and the extra bits wrt to the 20 20 * pci device. I.e. it should be diffable so that fixes to one can easily be … … 26 26 *********************************************************************************************************************************/ 27 27 #include <sys/param.h> 28 #undef PVM 29 #include <sys/types.h> 28 #include <sys/systm.h> 29 #include <sys/select.h> 30 #include <sys/conf.h> 31 #include <sys/kernel.h> 32 #include <sys/kmem.h> 30 33 #include <sys/module.h> 31 #include <sys/systm.h> 32 #include <sys/errno.h> 33 #include <sys/kernel.h> 34 #include <sys/fcntl.h> 35 #include <sys/conf.h> 36 #include <sys/uio.h> 34 #include <sys/device.h> 37 35 #include <sys/bus.h> 38 36 #include <sys/poll.h> 37 #include <sys/proc.h> 38 #include <sys/stat.h> 39 39 #include <sys/selinfo.h> 40 40 #include <sys/queue.h> 41 41 #include <sys/lock.h> 42 #include <sys/lockmgr.h> 42 #include <sys/types.h> 43 #include <sys/conf.h> 43 44 #include <sys/malloc.h> 45 #include <sys/uio.h> 44 46 #include <sys/file.h> 45 #include <sys/rman.h> 46 #include <machine/bus.h> 47 #include <machine/resource.h> 47 #include <sys/filedesc.h> 48 #include <sys/vfs_syscalls.h> 48 49 #include <dev/pci/pcivar.h> 49 50 #include <dev/pci/pcireg.h> 50 51 #include <dev/pci/pcidevs.h> 52 53 #ifdef PVM 54 # undef PVM 55 #endif 51 56 #include "VBoxGuestInternal.h" 52 #include <VBox/version.h>53 57 #include <VBox/log.h> 54 58 #include <iprt/assert.h> … … 69 73 * Structures and Typedefs * 70 74 *********************************************************************************************************************************/ 71 struct VBoxGuestDeviceState 72 { 73 /** Resource ID of the I/O port */ 74 int iIOPortResId; 75 /** Pointer to the I/O port resource. */ 76 struct resource *pIOPortRes; 77 /** Start address of the IO Port. */ 78 uint16_t uIOPortBase; 79 /** Resource ID of the MMIO area */ 80 int iVMMDevMemResId; 81 /** Pointer to the MMIO resource. */ 82 struct resource *pVMMDevMemRes; 83 /** Handle of the MMIO resource. */ 75 typedef struct VBoxGuestDeviceState 76 { 77 device_t sc_dev; 78 struct pci_attach_args *pa; 79 bus_space_tag_t io_tag; 80 bus_space_handle_t io_handle; 81 bus_addr_t uIOPortBase; 82 bus_size_t io_regsize; 83 bus_space_tag_t iVMMDevMemResId; 84 84 bus_space_handle_t VMMDevMemHandle; 85 85 86 /** Size of the memory area. */ 86 87 bus_size_t VMMDevMemSize; 87 88 /** Mapping of the register space */ 88 void *pMMIOBase; 89 /** IRQ number */ 90 int iIrqResId; 89 bus_addr_t pMMIOBase; 90 91 91 /** IRQ resource handle. */ 92 struct resource *pIrqRes;92 pci_intr_handle_t ih; 93 93 /** Pointer to the IRQ handler. */ 94 94 void *pfnIrqHandler; 95 /** VMMDev version */ 96 uint32_t u32Version; 95 96 /** Controller features, limits and status. */ 97 u_int vboxguest_state; 98 } vboxguest_softc; 99 100 101 struct vboxguest_session 102 { 103 vboxguest_softc *sc; 104 PVBOXGUESTSESSION session; 97 105 }; 98 106 107 #define VBOXGUEST_STATE_INITOK 1 << 0 99 108 100 109 /********************************************************************************************************************************* … … 104 113 * Character device file handlers. 105 114 */ 106 static d_fdopen_t vgdrvFreeBSDOpen;107 static d_close_t vgdrvFreeBSDClose;108 static d_ioctl_t vgdrvFreeBSDIOCtl;109 static d_write_t vgdrvFreeBSDWrite;110 static d_read_t vgdrvFreeBSDRead;111 static d_poll_t vgdrvFreeBSDPoll;115 static int VBoxGuestNetBSDOpen(dev_t device, int flags, int fmt, struct lwp *process); 116 static int VBoxGuestNetBSDClose(struct file *fp); 117 static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long cmd, void *addr); 118 static int VBoxGuestNetBSDPoll(struct file *fp, int events); 119 static void VBoxGuestNetBSDAttach(device_t, device_t, void*); 120 static int VBoxGuestNetBSDDetach(device_t pDevice, int flags); 112 121 113 122 /* 114 123 * IRQ related functions. 115 124 */ 116 static void vgdrvFreeBSDRemoveIRQ(device_t pDevice, void *pvState);117 static int vgdrvFreeBSDAddIRQ(device_t pDevice, void*pvState);118 static int vgdrvFreeBSDISR(void *pvState);125 static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *sc); 126 static int VBoxGuestNetBSDAddIRQ(vboxguest_softc *pvState); 127 static int VBoxGuestNetBSDISR(void *pvState); 119 128 120 129 … … 122 131 * Global Variables * 123 132 *********************************************************************************************************************************/ 124 static MALLOC_DEFINE(M_VBOXGUEST, "vboxguest", "VirtualBox Guest Device Driver");125 126 #ifndef D_NEEDMINOR127 # define D_NEEDMINOR 0128 #endif129 130 133 /* 131 134 * The /dev/vboxguest character device entry points. 132 135 */ 133 static struct cdevsw g_vgdrvFreeBSDChrDevSW = 134 { 135 .d_version = D_VERSION, 136 .d_flags = D_TRACKCLOSE | D_NEEDMINOR, 137 .d_fdopen = vgdrvFreeBSDOpen, 138 .d_close = vgdrvFreeBSDClose, 139 .d_ioctl = vgdrvFreeBSDIOCtl, 140 .d_read = vgdrvFreeBSDRead, 141 .d_write = vgdrvFreeBSDWrite, 142 .d_poll = vgdrvFreeBSDPoll, 143 .d_name = "vboxguest" 136 static struct cdevsw g_VBoxGuestNetBSDChrDevSW = 137 { 138 VBoxGuestNetBSDOpen, 139 noclose, 140 noread, 141 nowrite, 142 noioctl, 143 nostop, 144 notty, 145 nopoll, 146 nommap, 147 nokqfilter, 148 }; 149 150 static const struct fileops vboxguest_fileops = { 151 .fo_read = fbadop_read, 152 .fo_write = fbadop_write, 153 .fo_ioctl = VBoxGuestNetBSDIOCtl, 154 .fo_fcntl = fnullop_fcntl, 155 .fo_poll = VBoxGuestNetBSDPoll, 156 .fo_stat = fbadop_stat, 157 .fo_close = VBoxGuestNetBSDClose, 158 .fo_kqfilter = fnullop_kqfilter, 159 .fo_restart = fnullop_restart 144 160 }; 145 161 146 162 /** Device extention & session data association structure. */ 147 163 static VBOXGUESTDEVEXT g_DevExt; 148 149 /** List of cloned device. Managed by the kernel. */150 static struct clonedevs *g_pvgdrvFreeBSDClones;151 /** The dev_clone event handler tag. */152 static eventhandler_tag g_vgdrvFreeBSDEHTag;153 164 /** Reference counter */ 154 165 static volatile uint32_t cUsers; … … 156 167 static struct selinfo g_SelInfo; 157 168 158 /** 159 * DEVFS event handler. 160 */ 161 static void vgdrvFreeBSDClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev) 162 { 163 int iUnit; 164 int rc; 165 166 Log(("vgdrvFreeBSDClone: pszName=%s ppDev=%p\n", pszName, ppDev)); 167 168 /* 169 * One device node per user, si_drv1 points to the session. 170 * /dev/vboxguest<N> where N = {0...255}. 171 */ 172 if (!ppDev) 173 return; 174 if (strcmp(pszName, "vboxguest") == 0) 175 iUnit = -1; 176 else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1) 177 return; 178 if (iUnit >= 256) 179 { 180 Log(("vgdrvFreeBSDClone: iUnit=%d >= 256 - rejected\n", iUnit)); 181 return; 182 } 183 184 Log(("vgdrvFreeBSDClone: pszName=%s iUnit=%d\n", pszName, iUnit)); 185 186 rc = clone_create(&g_pvgdrvFreeBSDClones, &g_vgdrvFreeBSDChrDevSW, &iUnit, ppDev, 0); 187 Log(("vgdrvFreeBSDClone: clone_create -> %d; iUnit=%d\n", rc, iUnit)); 188 if (rc) 189 { 190 *ppDev = make_dev(&g_vgdrvFreeBSDChrDevSW, 191 iUnit, 192 UID_ROOT, 193 GID_WHEEL, 194 0664, 195 "vboxguest%d", iUnit); 196 if (*ppDev) 197 { 198 dev_ref(*ppDev); 199 (*ppDev)->si_flags |= SI_CHEAPCLONE; 200 Log(("vgdrvFreeBSDClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", 201 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); 202 (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL; 203 } 204 else 205 Log(("vgdrvFreeBSDClone: make_dev iUnit=%d failed\n", iUnit)); 206 } 207 else 208 Log(("vgdrvFreeBSDClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", 209 *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); 210 } 169 CFDRIVER_DECL(vboxguest, DV_DULL, NULL); 170 extern struct cfdriver vboxguest_cd; 211 171 212 172 /** … … 214 174 * 215 175 */ 216 #if __FreeBSD_version >= 700000 217 static int vgdrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd, struct file *pFd) 218 #else 219 static int vgdrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd) 220 #endif 221 { 222 int rc; 223 PVBOXGUESTSESSION pSession; 224 225 LogFlow(("vgdrvFreeBSDOpen:\n")); 226 227 /* 228 * Try grab it (we don't grab the giant, remember). 229 */ 230 if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL)) 231 return EBUSY; 176 static int VBoxGuestNetBSDOpen(dev_t device, int flags, int fmt, struct lwp *process) 177 { 178 int rc; 179 vboxguest_softc *vboxguest; 180 struct vboxguest_session *session; 181 file_t *fp; 182 int fd, error; 183 184 LogFlow((DEVICE_NAME ":VBoxGuestNetBSDOpen\n")); 185 186 if ((vboxguest = device_lookup_private(&vboxguest_cd, minor(device))) == NULL) { 187 printf("device_lookup_private failed\n"); 188 return (ENXIO); 189 } 190 if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0) { 191 aprint_error_dev(vboxguest->sc_dev, "device not configured\n"); 192 return (ENXIO); 193 } 194 195 session = kmem_alloc(sizeof(*session), KM_SLEEP); 196 if (session == NULL) { 197 return (ENOMEM); 198 } 199 200 session->sc = vboxguest; 201 202 if ((error = fd_allocfile(&fp, &fd)) != 0) { 203 kmem_free(session, sizeof(*session)); 204 return error; 205 } 232 206 233 207 /* 234 208 * Create a new session. 235 209 */ 236 rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession); 237 if (RT_SUCCESS(rc)) 238 { 239 if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42)) 240 { 241 Log(("vgdrvFreeBSDOpen: success - g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf())); 242 ASMAtomicIncU32(&cUsers); 243 return 0; 244 } 245 246 VGDrvCommonCloseSession(&g_DevExt, pSession); 247 } 248 249 LogRel(("vgdrvFreeBSDOpen: failed. rc=%d\n", rc)); 250 return RTErrConvertToErrno(rc); 210 rc = VGDrvCommonCreateUserSession(&g_DevExt, &session->session); 211 if (! RT_SUCCESS(rc)) 212 { 213 aprint_error_dev(vboxguest->sc_dev, "VBox session creation failed\n"); 214 closef(fp); /* ??? */ 215 kmem_free(session, sizeof(*session)); 216 return RTErrConvertToErrno(rc); 217 } 218 ASMAtomicIncU32(&cUsers); 219 return fd_clone(fp, fd, flags, &vboxguest_fileops, session); 220 251 221 } 252 222 … … 255 225 * 256 226 */ 257 static int vgdrvFreeBSDClose(struct cdev *pDev, int fFile, int DevType, struct thread *pTd) 258 { 259 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1; 260 Log(("vgdrvFreeBSDClose: fFile=%#x pSession=%p\n", fFile, pSession)); 261 262 /* 263 * Close the session if it's still hanging on to the device... 264 */ 265 if (VALID_PTR(pSession)) 266 { 267 VGDrvCommonCloseSession(&g_DevExt, pSession); 268 if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, NULL, pSession)) 269 Log(("vgdrvFreeBSDClose: si_drv1=%p expected %p!\n", pDev->si_drv1, pSession)); 270 ASMAtomicDecU32(&cUsers); 271 /* Don't use destroy_dev here because it may sleep resulting in a hanging user process. */ 272 destroy_dev_sched(pDev); 273 } 274 else 275 Log(("vgdrvFreeBSDClose: si_drv1=%p!\n", pSession)); 227 static int VBoxGuestNetBSDClose(struct file *fp) 228 { 229 struct vboxguest_session *session = fp->f_data; 230 vboxguest_softc *vboxguest = session->sc; 231 232 VGDrvCommonCloseSession(&g_DevExt, session->session); 233 ASMAtomicDecU32(&cUsers); 234 235 kmem_free(session, sizeof(*session)); 236 276 237 return 0; 277 238 } … … 281 242 * 282 243 */ 283 static int vgdrvFreeBSDIOCtl(struct cdev *pDev, u_long ulCmd, caddr_t pvData, int fFile, struct thread *pTd) 284 { 285 LogFlow(("vgdrvFreeBSDIOCtl\n")); 244 static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long command, void *data) 245 { 246 struct vboxguest_session *session = fp->f_data; 247 vboxguest_softc *vboxguest = session->sc; 286 248 287 249 int rc = 0; 288 250 289 251 /* 290 * Validate the input.291 */292 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1;293 if (RT_UNLIKELY(!VALID_PTR(pSession)))294 return EINVAL;295 296 /*297 252 * Validate the request wrapper. 298 253 */ 299 if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ)) 300 { 301 Log(("vgdrvFreeBSDIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), sizeof(VBGLBIGREQ))); 254 if (IOCPARM_LEN(command) != sizeof(VBGLBIGREQ)) { 255 Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad request %lu size=%lu expected=%d\n", command, IOCPARM_LEN(command), sizeof(VBGLBIGREQ))); 302 256 return ENOTTY; 303 257 } 304 258 305 PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ) pvData;259 PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ)data; 306 260 if (ReqWrap->u32Magic != VBGLBIGREQ_MAGIC) 307 261 { 308 Log(( "vgdrvFreeBSDIOCtl: bad magic %#x; pArg=%p Cmd=%lu.\n", ReqWrap->u32Magic, pvData, ulCmd));262 Log((DEVICE_NAME ": VBoxGuestNetBSDIOCtl: bad magic %#x; pArg=%p Cmd=%lu.\n", ReqWrap->u32Magic, data, command)); 309 263 return EINVAL; 310 264 } … … 312 266 || ReqWrap->cbData > _1M*16)) 313 267 { 314 printf( "vgdrvFreeBSDIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", ReqWrap->cbData, pvData, ulCmd);268 printf(DEVICE_NAME ": VBoxGuestNetBSDIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", ReqWrap->cbData, data, command); 315 269 return EINVAL; 316 270 } … … 322 276 if (RT_UNLIKELY(!pvBuf)) 323 277 { 324 Log(( "vgdrvFreeBSDIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap->cbData));278 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap->cbData)); 325 279 return ENOMEM; 326 280 } … … 330 284 { 331 285 RTMemTmpFree(pvBuf); 332 Log(("vgdrvFreeBSDIOCtl: copyin failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc)); 286 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: copyin failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, command, rc)); 287 aprint_error_dev(vboxguest->sc_dev, "copyin failed\n"); 333 288 return EFAULT; 334 289 } … … 337 292 { 338 293 RTMemTmpFree(pvBuf); 339 Log(( "vgdrvFreeBSDIOCtl: pvBuf invalid pointer %p\n", pvBuf));294 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: pvBuf invalid pointer %p\n", pvBuf)); 340 295 return EINVAL; 341 296 } 342 Log(("vgdrvFreeBSDIOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf()));343 297 344 298 /* … … 346 300 */ 347 301 size_t cbDataReturned; 348 rc = VGDrvCommonIoCtl(ulCmd, &g_DevExt, pSession, pvBuf, ReqWrap->cbData, &cbDataReturned); 349 if (RT_SUCCESS(rc)) 350 { 302 rc = VGDrvCommonIoCtl(command, &g_DevExt, session->session, pvBuf, ReqWrap->cbData, &cbDataReturned); 303 if (RT_SUCCESS(rc)) { 351 304 rc = 0; 352 305 if (RT_UNLIKELY(cbDataReturned > ReqWrap->cbData)) 353 306 { 354 Log(( "vgdrvFreeBSDIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap->cbData));307 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap->cbData)); 355 308 cbDataReturned = ReqWrap->cbData; 356 309 } … … 360 313 if (RT_UNLIKELY(rc)) 361 314 { 362 Log(("vgdrvFreeBSDIOCtl: copyout failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc)); 363 rc = EFAULT; 315 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: copyout failed; pvBuf=%p pArg=%p. rc=%d\n", pvBuf, data, rc)); 364 316 } 365 317 } 366 } 367 else 368 { 369 Log(("vgdrvFreeBSDIOCtl: VGDrvCommonIoCtl failed. rc=%d\n", rc)); 370 rc = EFAULT; 318 } else { 319 Log((DEVICE_NAME ":VBoxGuestNetBSDIOCtl: VGDrvCommonIoCtl failed. rc=%d\n", rc)); 320 rc = -rc; 371 321 } 372 322 RTMemTmpFree(pvBuf); … … 374 324 } 375 325 376 static int vgdrvFreeBSDPoll(struct cdev *pDev, int fEvents, struct thread *td) 377 { 378 int fEventsProcessed; 379 380 LogFlow(("vgdrvFreeBSDPoll: fEvents=%d\n", fEvents)); 381 382 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1; 383 if (RT_UNLIKELY(!VALID_PTR(pSession))) { 384 Log(("vgdrvFreeBSDPoll: no state data for %s\n", devtoname(pDev))); 385 return (fEvents & (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM)); 386 } 326 static int VBoxGuestNetBSDPoll(struct file *fp, int events) 327 { 328 struct vboxguest_session *session = fp->f_data; 329 vboxguest_softc *vboxguest = session->sc; 330 331 int rc = 0; 332 int events_processed; 387 333 388 334 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq); 389 if (pSession->u32MousePosChangedSeq != u32CurSeq) 390 { 391 fEventsProcessed = fEvents & (POLLIN | POLLRDNORM); 392 pSession->u32MousePosChangedSeq = u32CurSeq; 393 } 394 else 395 { 396 fEventsProcessed = 0; 397 398 selrecord(td, &g_SelInfo); 399 } 400 401 return fEventsProcessed; 402 } 403 404 static int vgdrvFreeBSDWrite(struct cdev *pDev, struct uio *pUio, int fIo) 405 { 406 return 0; 407 } 408 409 static int vgdrvFreeBSDRead(struct cdev *pDev, struct uio *pUio, int fIo) 410 { 411 return 0; 412 } 413 414 static int vgdrvFreeBSDDetach(device_t pDevice) 415 { 416 struct VBoxGuestDeviceState *pState = device_get_softc(pDevice); 335 if (session->session->u32MousePosChangedSeq != u32CurSeq) { 336 events_processed = events & (POLLIN | POLLRDNORM); 337 session->session->u32MousePosChangedSeq = u32CurSeq; 338 } else { 339 events_processed = 0; 340 341 selrecord(curlwp, &g_SelInfo); 342 } 343 344 return events_processed; 345 } 346 347 static int VBoxGuestNetBSDDetach(device_t self, int flags) 348 { 349 vboxguest_softc *vboxguest; 350 vboxguest = device_private(self); 417 351 418 352 if (cUsers > 0) 419 353 return EBUSY; 420 354 421 /* 422 * Reverse what we did in vgdrvFreeBSDAttach. 423 */ 424 if (g_vgdrvFreeBSDEHTag != NULL) 425 EVENTHANDLER_DEREGISTER(dev_clone, g_vgdrvFreeBSDEHTag); 426 427 clone_cleanup(&g_pvgdrvFreeBSDClones); 428 429 vgdrvFreeBSDRemoveIRQ(pDevice, pState); 430 431 if (pState->pVMMDevMemRes) 432 bus_release_resource(pDevice, SYS_RES_MEMORY, pState->iVMMDevMemResId, pState->pVMMDevMemRes); 433 if (pState->pIOPortRes) 434 bus_release_resource(pDevice, SYS_RES_IOPORT, pState->iIOPortResId, pState->pIOPortRes); 355 if ((vboxguest->vboxguest_state & VBOXGUEST_STATE_INITOK) == 0) { 356 return 0; 357 } 358 359 /* 360 * Reverse what we did in VBoxGuestNetBSDAttach. 361 */ 362 363 VBoxGuestNetBSDRemoveIRQ(vboxguest); 435 364 436 365 VGDrvCommonDeleteDevExt(&g_DevExt); … … 447 376 * @param pvState Opaque pointer to the device state. 448 377 */ 449 static int vgdrvFreeBSDISR(void *pvState)450 { 451 LogFlow(( "vgdrvFreeBSDISR:pvState=%p\n", pvState));378 static int VBoxGuestNetBSDISR(void *pvState) 379 { 380 LogFlow((DEVICE_NAME ":VBoxGuestNetBSDISR pvState=%p\n", pvState)); 452 381 453 382 bool fOurIRQ = VGDrvCommonISR(&g_DevExt); … … 456 385 } 457 386 458 void V GDrvNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)459 { 460 LogFlow(( "VGDrvNativeISRMousePollEvent:\n"));387 void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) 388 { 389 LogFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n")); 461 390 462 391 /* 463 392 * Wake up poll waiters. 464 393 */ 465 sel wakeup(&g_SelInfo);394 selnotify(&g_SelInfo, 0, 0); 466 395 } 467 396 … … 469 398 * Sets IRQ for VMMDev. 470 399 * 471 * @returns FreeBSD error code.400 * @returns NetBSD error code. 472 401 * @param pDevice Pointer to the device info structure. 473 402 * @param pvState Pointer to the state info structure. 474 403 */ 475 static int vgdrvFreeBSDAddIRQ(device_t pDevice, void *pvState)404 static int VBoxGuestNetBSDAddIRQ(vboxguest_softc *vboxguest) 476 405 { 477 406 int iResId = 0; 478 407 int rc = 0; 479 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState; 480 481 pState->pIrqRes = bus_alloc_resource_any(pDevice, SYS_RES_IRQ, &iResId, RF_SHAREABLE | RF_ACTIVE); 482 483 #if __FreeBSD_version >= 700000 484 rc = bus_setup_intr(pDevice, pState->pIrqRes, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)vgdrvFreeBSDISR, pState, 485 &pState->pfnIrqHandler); 486 #else 487 rc = bus_setup_intr(pDevice, pState->pIrqRes, INTR_TYPE_BIO, (driver_intr_t *)vgdrvFreeBSDISR, pState, &pState->pfnIrqHandler); 488 #endif 489 490 if (rc) 491 { 492 pState->pfnIrqHandler = NULL; 408 struct pci_attach_args *pa = vboxguest->pa; 409 const char *intrstr; 410 char intstrbuf[100]; 411 412 if (pci_intr_map(pa, &vboxguest->ih)) { 413 aprint_error_dev(vboxguest->sc_dev, "couldn't map interrupt.\n"); 493 414 return VERR_DEV_IO_ERROR; 494 415 } 495 496 pState->iIrqResId = iResId; 416 intrstr = pci_intr_string(vboxguest->pa->pa_pc, vboxguest->ih, 417 intstrbuf, sizeof(intstrbuf)); 418 aprint_normal_dev(vboxguest->sc_dev, "interrupting at %s\n", intrstr); 419 vboxguest->pfnIrqHandler = pci_intr_establish(vboxguest->pa->pa_pc, vboxguest->ih, IPL_BIO, VBoxGuestNetBSDISR, vboxguest); 420 if (vboxguest->pfnIrqHandler == NULL) { 421 aprint_error_dev(vboxguest->sc_dev, "couldn't establish interrupt\n"); 422 return VERR_DEV_IO_ERROR; 423 } 497 424 498 425 return VINF_SUCCESS; … … 505 432 * @param pvState Opaque pointer to the state info structure. 506 433 */ 507 static void vgdrvFreeBSDRemoveIRQ(device_t pDevice, void *pvState) 508 { 509 struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState; 510 511 if (pState->pIrqRes) 512 { 513 bus_teardown_intr(pDevice, pState->pIrqRes, pState->pfnIrqHandler); 514 bus_release_resource(pDevice, SYS_RES_IRQ, 0, pState->pIrqRes); 515 } 516 } 517 518 static int vgdrvFreeBSDAttach(device_t pDevice) 519 { 520 int rc; 521 int iResId; 522 struct VBoxGuestDeviceState *pState; 434 static void VBoxGuestNetBSDRemoveIRQ(vboxguest_softc *vboxguest) 435 { 436 if (vboxguest->pfnIrqHandler) 437 { 438 pci_intr_disestablish(vboxguest->pa->pa_pc, vboxguest->pfnIrqHandler); 439 } 440 } 441 442 static void VBoxGuestNetBSDAttach(device_t parent, device_t self, void *aux) 443 { 444 int rc = VINF_SUCCESS; 445 int iResId = 0; 446 vboxguest_softc *vboxguest; 447 struct pci_attach_args *pa = aux; 448 bus_space_tag_t iot, memt; 449 bus_space_handle_t ioh, memh; 450 bus_dma_segment_t seg; 451 int ioh_valid, memh_valid; 523 452 524 453 cUsers = 0; 454 455 aprint_normal(": VirtualBox Guest\n"); 456 457 vboxguest = device_private(self); 458 vboxguest->sc_dev = self; 525 459 526 460 /* … … 531 465 { 532 466 LogFunc(("RTR0Init failed.\n")); 533 return ENXIO; 534 } 535 536 pState = device_get_softc(pDevice); 467 aprint_error_dev(vboxguest->sc_dev, "RTR0Init failed\n"); 468 return ; 469 } 470 471 vboxguest->pa = pa; 537 472 538 473 /* 539 474 * Allocate I/O port resource. 540 475 */ 541 iResId = PCIR_BAR(0); 542 pState->pIOPortRes = bus_alloc_resource_any(pDevice, SYS_RES_IOPORT, &iResId, RF_ACTIVE); 543 pState->uIOPortBase = rman_get_start(pState->pIOPortRes); 544 pState->iIOPortResId = iResId; 545 if (pState->uIOPortBase) 546 { 476 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); 477 478 if (ioh_valid) 479 { 480 547 481 /* 548 482 * Map the MMIO region. 549 483 */ 550 iResId = PCIR_BAR(1); 551 pState->pVMMDevMemRes = bus_alloc_resource_any(pDevice, SYS_RES_MEMORY, &iResId, RF_ACTIVE); 552 pState->VMMDevMemHandle = rman_get_bushandle(pState->pVMMDevMemRes); 553 pState->VMMDevMemSize = rman_get_size(pState->pVMMDevMemRes); 554 555 pState->pMMIOBase = rman_get_virtual(pState->pVMMDevMemRes); 556 pState->iVMMDevMemResId = iResId; 557 if (pState->pMMIOBase) 484 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); 485 if (memh_valid) 558 486 { 559 487 /* 560 488 * Call the common device extension initializer. 561 489 */ 562 rc = VGDrvCommonInitDevExt(&g_DevExt, pState->uIOPortBase, 563 pState->pMMIOBase, pState->VMMDevMemSize, 490 rc = VGDrvCommonInitDevExt(&g_DevExt, vboxguest->uIOPortBase, 491 bus_space_vaddr(vboxguest->iVMMDevMemResId, 492 vboxguest->VMMDevMemHandle), 493 vboxguest->VMMDevMemSize, 564 494 #if ARCH_BITS == 64 565 VBOXOSTYPE_ FreeBSD_x64,495 VBOXOSTYPE_NetBSD_x64, 566 496 #else 567 VBOXOSTYPE_ FreeBSD,497 VBOXOSTYPE_NetBSD, 568 498 #endif 569 499 VMMDEV_EVENT_MOUSE_POSITION_CHANGED); … … 573 503 * Add IRQ of VMMDev. 574 504 */ 575 rc = vgdrvFreeBSDAddIRQ(pDevice, pState);505 rc = VBoxGuestNetBSDAddIRQ(vboxguest); 576 506 if (RT_SUCCESS(rc)) 577 507 { 578 /* 579 * Configure device cloning. 580 */ 581 clone_setup(&g_pvgdrvFreeBSDClones); 582 g_vgdrvFreeBSDEHTag = EVENTHANDLER_REGISTER(dev_clone, vgdrvFreeBSDClone, 0, 1000); 583 if (g_vgdrvFreeBSDEHTag) 584 { 585 printf(DEVICE_NAME ": loaded successfully\n"); 586 return 0; 587 } 588 589 printf(DEVICE_NAME ": EVENTHANDLER_REGISTER(dev_clone,,,) failed\n"); 590 clone_cleanup(&g_pvgdrvFreeBSDClones); 591 vgdrvFreeBSDRemoveIRQ(pDevice, pState); 508 vboxguest->vboxguest_state |= VBOXGUEST_STATE_INITOK; 509 return ; 592 510 } 593 else594 printf((DEVICE_NAME ": VGDrvCommonInitDevExt failed.\n"));595 511 VGDrvCommonDeleteDevExt(&g_DevExt); 512 } else { 513 aprint_error_dev(vboxguest->sc_dev, "init failed\n"); 596 514 } 597 else598 printf((DEVICE_NAME ": vgdrvFreeBSDAddIRQ failed.\n"));515 } else { 516 aprint_error_dev(vboxguest->sc_dev, "MMIO mapping failed\n"); 599 517 } 600 else 601 printf((DEVICE_NAME ": MMIO region setup failed.\n")); 602 } 603 else 604 printf((DEVICE_NAME ": IOport setup failed.\n")); 518 } else { 519 aprint_error_dev(vboxguest->sc_dev, "IO mapping failed\n"); 520 } 605 521 606 522 RTR0Term(); 607 return ENXIO; 608 } 609 610 static int vgdrvFreeBSDProbe(device_t pDevice) 611 { 612 if ((pci_get_vendor(pDevice) == VMMDEV_VENDORID) && (pci_get_device(pDevice) == VMMDEV_DEVICEID)) 613 return 0; 614 615 return ENXIO; 616 } 617 618 static device_method_t vgdrvFreeBSDMethods[] = 619 { 620 /* Device interface. */ 621 DEVMETHOD(device_probe, vgdrvFreeBSDProbe), 622 DEVMETHOD(device_attach, vgdrvFreeBSDAttach), 623 DEVMETHOD(device_detach, vgdrvFreeBSDDetach), 624 {0,0} 625 }; 626 627 static driver_t vgdrvFreeBSDDriver = 628 { 629 DEVICE_NAME, 630 vgdrvFreeBSDMethods, 631 sizeof(struct VBoxGuestDeviceState), 632 }; 633 634 static devclass_t vgdrvFreeBSDClass; 635 636 DRIVER_MODULE(vboxguest, pci, vgdrvFreeBSDDriver, vgdrvFreeBSDClass, 0, 0); 637 MODULE_VERSION(vboxguest, 1); 523 return ; 524 } 525 526 static int 527 VBoxGuestNetBSDMatch(device_t parent, cfdata_t match, void *aux) 528 { 529 const struct pci_attach_args *pa = aux; 530 if ((PCI_VENDOR(pa->pa_id) == VMMDEV_VENDORID) 531 && (PCI_PRODUCT(pa->pa_id) == VMMDEV_DEVICEID)) { 532 return 1; 533 } else { 534 return 2; 535 } 536 } 638 537 639 538 /* Common code that depend on g_DevExt. */ 640 539 #include "VBoxGuestIDC-unix.c.h" 641 540 541 CFATTACH_DECL_NEW(vboxguest, sizeof(vboxguest_softc), 542 VBoxGuestNetBSDMatch, VBoxGuestNetBSDAttach, VBoxGuestNetBSDDetach, NULL); 543 544 MODULE(MODULE_CLASS_DRIVER, vboxguest, "pci"); 545 546 static int loc[2] = {-1, -1}; 547 548 static const struct cfparent pspec = { 549 "pci", "pci", DVUNIT_ANY 550 }; 551 552 static struct cfdata vboxguest_cfdata[] = { 553 { 554 .cf_name = "vboxguest", 555 .cf_atname = "vboxguest", 556 .cf_unit = 0, /* Only unit 0 is ever used */ 557 .cf_fstate = FSTATE_STAR, 558 .cf_loc = loc, 559 .cf_flags = 0, 560 .cf_pspec = &pspec, 561 }, 562 { NULL, NULL, 0, 0, NULL, 0, NULL } 563 }; 564 565 static int 566 vboxguest_modcmd(modcmd_t cmd, void *opaque) 567 { 568 devmajor_t bmajor, cmajor; 569 int error; 570 register_t retval; 571 572 bmajor = cmajor = NODEVMAJOR; 573 switch (cmd) { 574 case MODULE_CMD_INIT: 575 error = config_cfdriver_attach(&vboxguest_cd); 576 if (error) { 577 printf("config_cfdriver_attach failed: %d", error); 578 break; 579 } 580 error = config_cfattach_attach(vboxguest_cd.cd_name, &vboxguest_ca); 581 if (error) { 582 config_cfdriver_detach(&vboxguest_cd); 583 printf("%s: unable to register cfattach\n", vboxguest_cd.cd_name); 584 break; 585 } 586 587 error = config_cfdata_attach(vboxguest_cfdata, 1); 588 if (error) { 589 printf("%s: unable to attach cfdata\n", vboxguest_cd.cd_name); 590 config_cfattach_detach(vboxguest_cd.cd_name, &vboxguest_ca); 591 config_cfdriver_detach(&vboxguest_cd); 592 break; 593 } 594 595 error = devsw_attach("vboxguest", NULL, &bmajor, &g_VBoxGuestNetBSDChrDevSW, &cmajor); 596 597 if (error == EEXIST) 598 error = 0; /* maybe built-in ... improve eventually */ 599 if (error) 600 break; 601 602 error = do_sys_mknod(curlwp, "/dev/vboxguest", 0666|S_IFCHR, makedev(cmajor, 0), &retval, UIO_SYSSPACE); 603 if (error == EEXIST) 604 error = 0; 605 break; 606 case MODULE_CMD_FINI: 607 error = config_cfdata_detach(vboxguest_cfdata); 608 if (error) 609 break; 610 error = config_cfattach_detach(vboxguest_cd.cd_name, &vboxguest_ca); 611 if (error) 612 break; 613 config_cfdriver_detach(&vboxguest_cd); 614 error = devsw_detach(NULL, &g_VBoxGuestNetBSDChrDevSW); 615 break; 616 default: 617 return ENOTTY; 618 } 619 return error; 620 }
Note:
See TracChangeset
for help on using the changeset viewer.