VirtualBox

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

Last change on this file since 549 was 1, checked in by vboxsync, 55 years ago

import

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

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