VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/module/vboxmod.c@ 2586

Last change on this file since 2586 was 2182, checked in by vboxsync, 18 years ago

consider asynchronous HGCM requests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/** @file
2 *
3 * vboxadd -- VirtualBox Guest Additions for Linux
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#include "the-linux-kernel.h"
23#include "version-generated.h"
24
25/* #define IRQ_DEBUG */
26
27#include "vboxmod.h"
28#include "waitcompat.h"
29#include <VBox/log.h>
30
31#define VERSION "0.5"
32
33MODULE_DESCRIPTION("VirtualBox Guest Additions for Linux Module");
34MODULE_AUTHOR("InnoTek Systemberatung GmbH");
35MODULE_LICENSE("GPL");
36#ifdef MODULE_VERSION
37MODULE_VERSION(VBOX_VERSION_STRING);
38#endif
39
40/* Runtime assert implementation for Linux ring 0 */
41RTDECL(void) AssertMsg1(const char *pszExpr, unsigned uLine,
42 const char *pszFile, const char *pszFunction)
43{
44 elog("!!Assertion Failed!!\n"
45 "Expression: %s\n"
46 "Location : %s(%d) %s\n",
47 pszExpr, pszFile, uLine, pszFunction);
48 Log(("!!Assertion Failed!!\n"
49 "Expression: %s\n"
50 "Location : %s(%d) %s\n",
51 pszExpr, pszFile, uLine, pszFunction));
52}
53
54/* Runtime assert implementation for Linux ring 0 */
55RTDECL(void) AssertMsg2(const char *pszFormat, ...)
56{
57 va_list ap;
58 char msg[256];
59
60 va_start(ap, pszFormat);
61 vsnprintf(msg, sizeof(msg) - 1, pszFormat, ap);
62 msg[sizeof(msg) - 1] = '\0';
63 elog("%s", msg);
64 Log(("%s", msg));
65 va_end(ap);
66}
67
68#if 0 /* We now have real backdoor logging */
69/* Backdoor logging function, needed by the runtime */
70RTDECL(size_t) RTLogBackdoorPrintf (const char *pszFormat, ...)
71{
72 va_list ap;
73 char msg[256];
74 size_t n;
75
76 va_start(ap, pszFormat);
77 n = vsnprintf(msg, sizeof(msg) - 1, pszFormat, ap);
78 msg[sizeof(msg) - 1] = '\0';
79 printk ("%s", msg);
80 va_end(ap);
81 return n;
82}
83#endif
84
85/** device extension structure (we only support one device instance) */
86static VBoxDevice *vboxDev = NULL;
87/** our file node major id (set dynamically) */
88#ifdef CONFIG_VBOXADD_MAJOR
89static unsigned int vbox_major = CONFIG_VBOXADD_MAJOR;
90#else
91static unsigned int vbox_major = 0;
92#endif
93
94DECLVBGL (void *) vboxadd_cmc_open (void)
95{
96 return vboxDev;
97}
98
99DECLVBGL (void) vboxadd_cmc_close (void *opaque)
100{
101 (void) opaque;
102}
103
104EXPORT_SYMBOL (vboxadd_cmc_open);
105EXPORT_SYMBOL (vboxadd_cmc_close);
106
107/**
108 * File open handler
109 *
110 */
111static int vboxadd_open(struct inode *inode, struct file *filp)
112{
113 /* no checks required */
114 return 0;
115}
116
117/**
118 * File close handler
119 *
120 */
121static int vboxadd_release(struct inode *inode, struct file * filp)
122{
123 /* no action required */
124 return 0;
125}
126
127/**
128 * Wait for event
129 *
130 */
131static void
132vboxadd_wait_for_event_helper (VBoxDevice *dev, long timeout,
133 uint32_t in_mask, uint32_t * out_mask)
134{
135 BUG ();
136}
137
138static void
139vboxadd_wait_for_event (VBoxGuestWaitEventInfo * info)
140{
141 long timeout;
142
143 timeout = msecs_to_jiffies (info->u32TimeoutIn);
144 vboxadd_wait_for_event_helper (vboxDev, timeout,
145 info->u32EventMaskIn,
146 &info->u32EventFlagsOut);
147}
148
149
150/**
151 * IOCTL handler
152 *
153 */
154static int vboxadd_ioctl(struct inode *inode, struct file *filp,
155 unsigned int cmd, unsigned long arg)
156{
157 switch (cmd)
158 {
159 case IOCTL_VBOXGUEST_WAITEVENT:
160 {
161 VBoxGuestWaitEventInfo info;
162 char *ptr = (void *) arg;
163
164 if (copy_from_user (&info, ptr, sizeof (info)))
165 {
166 printk (KERN_ERR "vboxadd_ioctl: can not get event info\n");
167 return -EFAULT;
168 }
169
170 vboxadd_wait_for_event (&info);
171
172 ptr += offsetof (VBoxGuestWaitEventInfo, u32EventFlagsOut);
173 if (put_user (info.u32EventFlagsOut, ptr))
174 {
175 printk (KERN_ERR "vboxadd_ioctl: can not put out_mask\n");
176 return -EFAULT;
177 }
178 return 0;
179 }
180
181 case IOCTL_VBOXGUEST_VMMREQUEST:
182 {
183 VMMDevRequestHeader reqHeader;
184 VMMDevRequestHeader *reqFull = NULL;
185 size_t cbRequestSize;
186 size_t cbVanillaRequestSize;
187 int rc;
188
189 if (_IOC_SIZE(cmd) != sizeof(VMMDevRequestHeader))
190 {
191 printk(KERN_ERR "vboxadd_ioctl: invalid VMM request structure size: %d\n",
192 _IOC_SIZE(cmd));
193 return -EINVAL;
194 }
195 if (copy_from_user(&reqHeader, (void*)arg, _IOC_SIZE(cmd)))
196 {
197 printk(KERN_ERR "vboxadd_ioctl: copy_from_user failed for vmm request!\n");
198 return -EFAULT;
199 }
200 /* get the request size */
201 cbVanillaRequestSize = vmmdevGetRequestSize(reqHeader.requestType);
202 if (!cbVanillaRequestSize)
203 {
204 printk(KERN_ERR "vboxadd_ioctl: invalid request type: %d\n",
205 reqHeader.requestType);
206 return -EINVAL;
207 }
208
209 cbRequestSize = reqHeader.size;
210 if (cbRequestSize < cbVanillaRequestSize)
211 {
212 printk(KERN_ERR
213 "vboxadd_ioctl: invalid request size: %d min: %d type: %d\n",
214 cbRequestSize,
215 cbVanillaRequestSize,
216 reqHeader.requestType);
217 return -EINVAL;
218 }
219 /* request storage for the full request */
220 rc = VbglGRAlloc(&reqFull, cbRequestSize, reqHeader.requestType);
221 if (VBOX_FAILURE(rc))
222 {
223 printk(KERN_ERR
224 "vboxadd_ioctl: could not allocate request structure! rc = %d\n", rc);
225 return -EFAULT;
226 }
227 /* now get the full request */
228 if (copy_from_user(reqFull, (void*)arg, cbRequestSize))
229 {
230 printk(KERN_ERR
231 "vboxadd_ioctl: failed to fetch full request from user space!\n");
232 VbglGRFree(reqFull);
233 return -EFAULT;
234 }
235
236 /* now issue the request */
237 rc = VbglGRPerform(reqFull);
238
239 /* asynchronous processing? */
240 if (rc == VINF_HGCM_ASYNC_EXECUTE)
241 {
242 VMMDevHGCMRequestHeader *reqHGCM = (VMMDevHGCMRequestHeader*)reqFull;
243 wait_event (vboxDev->eventq, reqHGCM->fu32Flags & VBOX_HGCM_REQ_DONE);
244 rc = reqFull->rc;
245 }
246
247 /* failed? */
248 if (VBOX_FAILURE(rc) || VBOX_FAILURE(reqFull->rc))
249 {
250 printk(KERN_ERR "vboxadd_ioctl: request execution failed!\n");
251 VbglGRFree(reqFull);
252 return -EFAULT;
253 }
254 else
255 {
256 /* success, copy the result data to user space */
257 if (copy_to_user((void*)arg, (void*)reqFull, cbRequestSize))
258 {
259 printk(KERN_ERR
260 "vboxadd_ioctl: error copying request result to user space!\n");
261 VbglGRFree(reqFull);
262 return -EFAULT;
263 }
264 }
265 VbglGRFree(reqFull);
266 break;
267 }
268
269 case IOCTL_VBOXGUEST_HGCM_CALL:
270 {
271 /* This IOCTL allows the guest to make an HGCM call from user space. The
272 OS-independant part of the Guest Additions already contain code for making an
273 HGCM call from the guest, but this code assumes that the call is made from the
274 kernel's address space. So before calling it, we have to copy all parameters
275 to the HGCM call from user space to kernel space and reconstruct the structures
276 passed to the call (which include pointers to other memory) inside the kernel's
277 address space. */
278 return vbox_ioctl_hgcm_call(arg, vboxDev);
279 }
280
281 default:
282 {
283 elog("vboxadd_ioctl: unknown command: %x, IOCTL_VBOXGUEST_HGCM_CALL is %x\n", cmd,
284 IOCTL_VBOXGUEST_HGCM_CALL);
285 Log(("vboxadd_ioctl: unknown command: %x, IOCTL_VBOXGUEST_HGCM_CALL is %x\n", cmd,
286 IOCTL_VBOXGUEST_HGCM_CALL));
287 return -EINVAL;
288 }
289 }
290 return 0;
291}
292
293#ifdef DEBUG
294static ssize_t
295vboxadd_read (struct file *file, char *buf, size_t count, loff_t *loff)
296{
297 if (count != 8 || *loff != 0)
298 {
299 return -EINVAL;
300 }
301 *(uint32_t *) buf = vboxDev->pVMMDevMemory->V.V1_04.fHaveEvents;
302 *(uint32_t *) (buf + 4) = vboxDev->u32Events;
303 *loff += 8;
304 return 8;
305}
306#endif
307
308/** strategy handlers (file operations) */
309static struct file_operations vbox_fops =
310{
311 .owner = THIS_MODULE,
312 .open = vboxadd_open,
313 .release = vboxadd_release,
314 .ioctl = vboxadd_ioctl,
315#ifdef DEBUG
316 .read = vboxadd_read,
317#endif
318 .llseek = no_llseek
319};
320
321#ifndef IRQ_RETVAL
322/* interrupt handlers in 2.4 kernels don't return anything */
323# define irqreturn_t void
324# define IRQ_RETVAL(n)
325#endif
326
327/**
328 * vboxadd_irq_handler
329 *
330 * Interrupt handler
331 *
332 * @returns scsi error code
333 * @param irq Irq number
334 * @param dev_id Irq handler parameter
335 * @param regs Regs
336 *
337 */
338#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
339static irqreturn_t vboxadd_irq_handler(int irq, void *dev_id)
340#else
341static irqreturn_t vboxadd_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
342#endif
343{
344 int fIRQTaken = 0;
345 int rcVBox;
346
347#ifdef IRQ_DEBUG
348 printk ("%s: vboxDev->pVMMDevMemory=%p vboxDev->pVMMDevMemory->fHaveEvents=%d\n",
349 __func__, vboxDev->pVMMDevMemory, vboxDev->pVMMDevMemory->fHaveEvents);
350#endif
351
352 /* check if IRQ was asserted by VBox */
353 if (vboxDev->pVMMDevMemory->V.V1_04.fHaveEvents != 0)
354 {
355#ifdef IRQ_DEBUG
356 printk(KERN_INFO "vboxadd: got IRQ with event mask 0x%x\n",
357 vboxDev->pVMMDevMemory->u32HostEvents);
358#endif
359
360 /* make a copy of the event mask */
361 rcVBox = VbglGRPerform (&vboxDev->irqAckRequest->header);
362 if (VBOX_SUCCESS(rcVBox) && VBOX_SUCCESS(vboxDev->irqAckRequest->header.rc))
363 {
364 if (likely (vboxDev->irqAckRequest->events))
365 {
366 vboxDev->u32Events |= vboxDev->irqAckRequest->events;
367 wake_up (&vboxDev->eventq);
368 }
369 }
370 else
371 {
372 /* impossible... */
373 printk(KERN_ERR
374 "vboxadd: failed acknowledging IRQ! rc = %x, header.rc = %d\n",
375 rcVBox, vboxDev->irqAckRequest->header.rc);
376 BUG ();
377 }
378
379 /* it was ours! */
380 fIRQTaken = 1;
381 }
382#ifdef IRQ_DEBUG
383 else
384 {
385 printk ("vboxadd: stale IRQ mem=%p events=%d devevents=%#x\n",
386 vboxDev->pVMMDevMemory,
387 vboxDev->pVMMDevMemory->fHaveEvents,
388 vboxDev->u32Events);
389 }
390#endif
391 /* it was ours */
392 return IRQ_RETVAL(fIRQTaken);
393}
394
395/**
396 * Helper function to reserve a fixed kernel address space window
397 * and tell the VMM that it can safely put its hypervisor there.
398 * This function might fail which is not a critical error.
399 */
400static int vboxadd_reserve_hypervisor(void)
401{
402 VMMDevReqHypervisorInfo *req = NULL;
403 int rcVBox;
404
405 /* allocate request structure */
406 rcVBox = VbglGRAlloc(
407 (VMMDevRequestHeader**)&req,
408 sizeof(VMMDevReqHypervisorInfo),
409 VMMDevReq_GetHypervisorInfo
410 );
411 if (VBOX_FAILURE(rcVBox))
412 {
413 printk(KERN_ERR "vboxadd: failed to allocate hypervisor info structure! rc = %d\n",
414 rcVBox);
415 goto bail_out;
416 }
417 /* query the hypervisor information */
418 rcVBox = VbglGRPerform(&req->header);
419 if (VBOX_SUCCESS(rcVBox) && VBOX_SUCCESS(req->header.rc))
420 {
421 /* are we supposed to make a reservation? */
422 if (req->hypervisorSize)
423 {
424 /** @todo repeat this several times until we get an address the host likes */
425
426 void *hypervisorArea;
427 /* reserve another 4MB because the start needs to be 4MB aligned */
428 uint32_t hypervisorSize = req->hypervisorSize + 0x400000;
429 /* perform a fictive IO space mapping */
430 hypervisorArea = ioremap(HYPERVISOR_PHYSICAL_START, hypervisorSize);
431 if (hypervisorArea)
432 {
433 /* communicate result to VMM, align at 4MB */
434 req->hypervisorStart = (vmmDevHypPtr)ALIGNP(hypervisorArea, 0x400000);
435 req->header.requestType = VMMDevReq_SetHypervisorInfo;
436 req->header.rc = VERR_GENERAL_FAILURE;
437 rcVBox = VbglGRPerform(&req->header);
438 if (VBOX_SUCCESS(rcVBox) && VBOX_SUCCESS(req->header.rc))
439 {
440 /* store mapping for future unmapping */
441 vboxDev->hypervisorStart = hypervisorArea;
442 vboxDev->hypervisorSize = hypervisorSize;
443 }
444 else
445 {
446 printk(KERN_ERR "vboxadd: failed to set hypervisor region! "
447 "rc = %d, header.rc = %d\n",
448 rcVBox, req->header.rc);
449 goto bail_out;
450 }
451 }
452 else
453 {
454 printk(KERN_ERR "vboxadd: failed to allocate 0x%x bytes of IO space\n",
455 hypervisorSize);
456 goto bail_out;
457 }
458 }
459 }
460 else
461 {
462 printk(KERN_ERR "vboxadd: failed to query hypervisor info! rc = %d, header.rc = %d\n",
463 rcVBox, req->header.rc);
464 goto bail_out;
465 }
466 /* successful return */
467 VbglGRFree(&req->header);
468 return 0;
469bail_out:
470 /* error return */
471 if (req)
472 VbglGRFree(&req->header);
473 return 1;
474}
475
476/**
477 * Helper function to free the hypervisor address window
478 *
479 */
480static int vboxadd_free_hypervisor(void)
481{
482 VMMDevReqHypervisorInfo *req = NULL;
483 int rcVBox;
484
485 /* allocate request structure */
486 rcVBox = VbglGRAlloc(
487 (VMMDevRequestHeader**)&req,
488 sizeof(VMMDevReqHypervisorInfo),
489 VMMDevReq_SetHypervisorInfo
490 );
491 if (VBOX_FAILURE(rcVBox))
492 {
493 printk(KERN_ERR
494 "vboxadd: failed to allocate hypervisor info structure! rc = %d\n", rcVBox);
495 goto bail_out;
496 }
497 /* reset the hypervisor information */
498 req->hypervisorStart = 0;
499 req->hypervisorSize = 0;
500 rcVBox = VbglGRPerform(&req->header);
501 if (VBOX_SUCCESS(rcVBox) && VBOX_SUCCESS(req->header.rc))
502 {
503 /* now we can free the associated IO space mapping */
504 iounmap(vboxDev->hypervisorStart);
505 vboxDev->hypervisorStart = 0;
506 }
507 else
508 {
509 printk(KERN_ERR "vboxadd: failed to reset hypervisor info! rc = %d, header.rc = %d\n",
510 rcVBox, req->header.rc);
511 goto bail_out;
512 }
513 return 0;
514
515 bail_out:
516 if (req)
517 VbglGRFree(&req->header);
518 return 1;
519}
520
521/**
522 * Helper to free resources
523 *
524 */
525static void free_resources(void)
526{
527 if (vboxDev)
528 {
529 if (vboxDev->hypervisorStart)
530 {
531 vboxadd_free_hypervisor();
532 }
533 if (vboxDev->irqAckRequest)
534 {
535 VbglGRFree(&vboxDev->irqAckRequest->header);
536 VbglTerminate();
537 }
538 if (vboxDev->pVMMDevMemory)
539 iounmap(vboxDev->pVMMDevMemory);
540 if (vboxDev->vmmdevmem)
541 release_mem_region(vboxDev->vmmdevmem, vboxDev->vmmdevmem_size);
542 if (vboxDev->irq)
543 free_irq(vboxDev->irq, vboxDev);
544 kfree(vboxDev);
545 vboxDev = NULL;
546 }
547}
548
549/**
550 * Module initialization
551 *
552 */
553static __init int init(void)
554{
555 int err;
556 int rcVBox;
557 struct pci_dev *pcidev = NULL;
558 VMMDevReportGuestInfo *infoReq = NULL;
559
560 printk(KERN_INFO "vboxadd: initializing. Version %s\n", VERSION);
561
562 if (vboxadd_cmc_init ())
563 {
564 printk (KERN_ERR "vboxadd: could not init cmc.\n");
565 return -ENODEV;
566 }
567
568 /*
569 * Detect PCI device
570 */
571 pcidev = pci_find_device(VMMDEV_VENDORID, VMMDEV_DEVICEID, pcidev);
572 if (!pcidev)
573 {
574 printk(KERN_ERR "vboxadd: VirtualBox PCI device not found.\n");
575 return -ENODEV;
576 }
577
578 err = pci_enable_device (pcidev);
579 if (err)
580 {
581 printk (KERN_ERR "vboxadd: could not enable device: %d\n", err);
582 return -ENODEV;
583 }
584
585 /* register a character device */
586 err = register_chrdev(vbox_major, "vboxadd", &vbox_fops);
587 if (err < 0 || ((vbox_major & err) || (!vbox_major && !err)))
588 {
589 printk(KERN_ERR "vboxadd: register_chrdev failed: vbox_major: %d, err = %d\n",
590 vbox_major, err);
591 return -ENODEV;
592 }
593 /* if no major code was set, take the return value */
594 if (!vbox_major)
595 vbox_major = err;
596
597 /* allocate and initialize device extension */
598 vboxDev = kmalloc(sizeof(*vboxDev), GFP_KERNEL);
599 if (!vboxDev)
600 {
601 printk(KERN_ERR "vboxadd: cannot allocate device!\n");
602 err = -ENOMEM;
603 goto fail;
604 }
605 memset(vboxDev, 0, sizeof(*vboxDev));
606 snprintf(vboxDev->name, sizeof(vboxDev->name), "vboxadd");
607
608 /* get the IO port region */
609 vboxDev->io_port = pci_resource_start(pcidev, 0);
610
611 /* get the memory region */
612 vboxDev->vmmdevmem = pci_resource_start(pcidev, 1);
613 /* and size */
614 vboxDev->vmmdevmem_size = pci_resource_len(pcidev, 1);
615
616 /* all resources found? */
617 if (!vboxDev->io_port || !vboxDev->vmmdevmem || !vboxDev->vmmdevmem_size)
618 {
619 printk(KERN_ERR "vboxadd: did not find expected hardware resources!\n");
620 goto fail;
621 }
622
623 /* request ownership of adapter memory */
624 if (request_mem_region(vboxDev->vmmdevmem, vboxDev->vmmdevmem_size, "vboxadd") == 0)
625 {
626 printk(KERN_ERR "vboxadd: failed to request adapter memory!\n");
627 goto fail;
628 }
629
630 /* map adapter memory into kernel address space and check version */
631 vboxDev->pVMMDevMemory = (VMMDevMemory *) ioremap(
632 vboxDev->vmmdevmem,
633 vboxDev->vmmdevmem_size
634 );
635 if (!vboxDev->pVMMDevMemory)
636 {
637 printk (KERN_ERR "vboxadd: ioremap failed\n");
638 goto fail;
639 }
640
641 if (vboxDev->pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION)
642 {
643 printk(KERN_ERR
644 "vboxadd: invalid VMM device memory version! (got 0x%x, expected 0x%x)\n",
645 vboxDev->pVMMDevMemory->u32Version, VMMDEV_MEMORY_VERSION);
646 goto fail;
647 }
648
649 /* initialize VBGL subsystem */
650 rcVBox = VbglInit(vboxDev->io_port, vboxDev->pVMMDevMemory);
651 if (VBOX_FAILURE(rcVBox))
652 {
653 printk(KERN_ERR "vboxadd: could not initialize VBGL subsystem! rc = %d\n", rcVBox);
654 goto fail;
655 }
656
657 /* report guest information to host, this must be done as the very first request */
658 rcVBox = VbglGRAlloc(
659 (VMMDevRequestHeader**)&infoReq,
660 sizeof(VMMDevReportGuestInfo),
661 VMMDevReq_ReportGuestInfo
662 );
663 if (VBOX_FAILURE(rcVBox))
664 {
665 printk(KERN_ERR "vboxadd: could not allocate request structure! rc = %d\n", rcVBox);
666 goto fail;
667 }
668
669 /* report guest version to host, the VMMDev requires that to be done first */
670 infoReq->guestInfo.additionsVersion = VMMDEV_VERSION;
671#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
672 infoReq->guestInfo.osType = OSTypeLinux26;
673#else
674 infoReq->guestInfo.osType = OSTypeLinux24;
675#endif
676 rcVBox = VbglGRPerform(&infoReq->header);
677 if (VBOX_FAILURE(rcVBox) || VBOX_FAILURE(infoReq->header.rc))
678 {
679 printk(KERN_ERR
680 "vboxadd: error reporting guest info to host! rc = %d, header.rc = %d\n",
681 rcVBox, infoReq->header.rc);
682 VbglGRFree(&infoReq->header);
683 goto fail;
684 }
685 VbglGRFree(&infoReq->header);
686
687 /* perform hypervisor address space reservation */
688 if (vboxadd_reserve_hypervisor())
689 {
690 /* we just ignore the error, no address window reservation, non fatal */
691 }
692
693 /* allocate a VMM request structure for use in the ISR */
694 rcVBox = VbglGRAlloc(
695 (VMMDevRequestHeader**)&vboxDev->irqAckRequest,
696 sizeof(VMMDevEvents),
697 VMMDevReq_AcknowledgeEvents
698 );
699 if (VBOX_FAILURE(rcVBox))
700 {
701 printk(KERN_ERR "vboxadd: could not allocate request structure! rc = %d\n", rcVBox);
702 goto fail;
703 }
704
705 /* get ISR */
706 err = request_irq(pcidev->irq, vboxadd_irq_handler, SA_SHIRQ, "vboxadd", vboxDev);
707 if (err)
708 {
709 printk(KERN_ERR "vboxadd: Could not request IRQ %d, err: %d\n", pcidev->irq, err);
710 goto fail;
711 }
712 vboxDev->irq = pcidev->irq;
713
714 init_waitqueue_head (&vboxDev->eventq);
715
716 /* some useful information for the user */
717 printk(KERN_INFO
718 "vboxadd: major code: %d, "
719 "using irq %d, "
720 "io port 0x%x, memory at 0x%x (size %d bytes), "
721 "hypervisor window at 0x%p (size 0x%x bytes)\n",
722 vbox_major, vboxDev->irq, vboxDev->io_port,
723 vboxDev->vmmdevmem, vboxDev->vmmdevmem_size,
724 vboxDev->hypervisorStart, vboxDev->hypervisorSize);
725
726 /* successful return */
727 return 0;
728fail:
729 free_resources();
730 unregister_chrdev(vbox_major, "vboxadd");
731 return err;
732}
733
734/**
735 * Module termination
736 *
737 */
738static __exit void fini(void)
739{
740 printk(KERN_DEBUG "vboxadd: unloading...\n");
741
742 unregister_chrdev(vbox_major, "vboxadd");
743 free_resources();
744 vboxadd_cmc_fini ();
745 printk(KERN_DEBUG "vboxadd: unloaded\n");
746}
747
748module_init(init);
749module_exit(fini);
750
751/* PCI hotplug structure */
752static const struct pci_device_id __devinitdata vmmdev_pci_id[] =
753{
754 {
755 .vendor = VMMDEV_VENDORID,
756 .device = VMMDEV_DEVICEID
757 },
758 {
759 /* empty entry */
760 }
761};
762MODULE_DEVICE_TABLE(pci, vmmdev_pci_id);
763
764int __gxx_personality_v0 = 0xdeadbeef;
765
766/*
767 * Local Variables:
768 * c-mode: bsd
769 * indent-tabs-mode: nil
770 * c-plusplus: evil
771 * End:
772 */
Note: See TracBrowser for help on using the repository browser.

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