VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/drm/vbox_irq.c@ 66891

Last change on this file since 66891 was 66544, checked in by vboxsync, 8 years ago

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
Change header of files which are expected to end up in the Linux kernel to the MIT licence to simplify life for people wanting to port vboxvideo to other kernels and to simplify synchronising changes back to VirtualBox. Update author information in files which have it, but do not add it to files which do not.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: vbox_irq.c 66544 2017-04-12 17:02:30Z vboxsync $ */
2/** @file
3 * VirtualBox Additions Linux kernel video driver
4 */
5
6/*
7 * Copyright (C) 2016-2017 Oracle Corporation
8 * This file is based on qxl_irq.c
9 * Copyright 2013 Red Hat Inc.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * Authors: Dave Airlie
30 * Alon Levy
31 * Michael Thayer <[email protected],
32 * Hans de Goede <[email protected]>
33 */
34
35#include "vbox_drv.h"
36
37#include <VBoxVideo.h>
38
39#include <drm/drm_crtc_helper.h>
40
41static void vbox_clear_irq(void)
42{
43 outl((uint32_t)~0, VGA_PORT_HGSMI_HOST);
44}
45
46static uint32_t vbox_get_flags(struct vbox_private *vbox)
47{
48 return readl(vbox->guest_heap + HOST_FLAGS_OFFSET);
49}
50
51void vbox_report_hotplug(struct vbox_private *vbox)
52{
53 schedule_work(&vbox->hotplug_work);
54}
55
56irqreturn_t vbox_irq_handler(int irq, void *arg)
57{
58 struct drm_device *dev = (struct drm_device *) arg;
59 struct vbox_private *vbox = (struct vbox_private *)dev->dev_private;
60 uint32_t host_flags = vbox_get_flags(vbox);
61
62 if (!(host_flags & HGSMIHOSTFLAGS_IRQ))
63 return IRQ_NONE;
64
65 /* Due to a bug in the initial host implementation of hot-plug interrupts,
66 * the hot-plug and cursor capability flags were never cleared. Fortunately
67 * we can tell when they would have been set by checking that the VSYNC flag
68 * is not set. */
69 if ( host_flags & (HGSMIHOSTFLAGS_HOTPLUG | HGSMIHOSTFLAGS_CURSOR_CAPABILITIES)
70 && !(host_flags & HGSMIHOSTFLAGS_VSYNC))
71 vbox_report_hotplug(vbox);
72 vbox_clear_irq();
73 return IRQ_HANDLED;
74}
75
76/** Check that the position hints provided by the host are suitable for GNOME
77 * shell (i.e. all screens disjoint and hints for all enabled screens) and if
78 * not replace them with default ones. Providing valid hints improves the
79 * chances that we will get a known screen layout for pointer mapping. */
80static void validate_or_set_position_hints(struct vbox_private *vbox)
81{
82 int i, j;
83 uint16_t currentx = 0;
84 bool valid = true;
85
86 for (i = 0; i < vbox->num_crtcs; ++i) {
87 for (j = 0; j < i; ++j) {
88 struct VBVAMODEHINT *hintsi = &vbox->last_mode_hints[i];
89 struct VBVAMODEHINT *hintsj = &vbox->last_mode_hints[j];
90
91 if (hintsi->fEnabled && hintsj->fEnabled) {
92 if ((hintsi->dx >= 0xffff || hintsi->dy >= 0xffff ||
93 hintsj->dx >= 0xffff || hintsj->dy >= 0xffff) ||
94 (hintsi->dx < hintsj->dx + (hintsj->cx & 0x8fff) &&
95 hintsi->dx + (hintsi->cx & 0x8fff) > hintsj->dx) ||
96 (hintsi->dy < hintsj->dy + (hintsj->cy & 0x8fff) &&
97 hintsi->dy + (hintsi->cy & 0x8fff) > hintsj->dy))
98 valid = false;
99 }
100 }
101 }
102 if (!valid)
103 for (i = 0; i < vbox->num_crtcs; ++i) {
104 if (vbox->last_mode_hints[i].fEnabled) {
105 vbox->last_mode_hints[i].dx = currentx;
106 vbox->last_mode_hints[i].dy = 0;
107 currentx += vbox->last_mode_hints[i].cx & 0x8fff;
108 }
109 }
110}
111
112/**
113 * Query the host for the most recent video mode hints.
114 */
115static void vbox_update_mode_hints(struct vbox_private *vbox)
116{
117 struct drm_device *dev = vbox->dev;
118 struct drm_connector *connector;
119 struct vbox_connector *vbox_connector;
120 struct VBVAMODEHINT *hints;
121 uint16_t flags;
122 bool disconnected;
123 unsigned crtc_id;
124 int rc;
125
126 rc = VBoxHGSMIGetModeHints(&vbox->submit_info, vbox->num_crtcs,
127 vbox->last_mode_hints);
128 if (RT_FAILURE(rc)) {
129 printk("vboxvideo: VBoxHGSMIGetModeHints failed, rc=%i.\n", rc);
130 return;
131 }
132 validate_or_set_position_hints(vbox);
133#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
134 drm_modeset_lock_all(dev);
135#else
136 mutex_lock(&dev->mode_config.mutex);
137#endif
138 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
139 vbox_connector = to_vbox_connector(connector);
140 hints = &vbox->last_mode_hints[vbox_connector->vbox_crtc->crtc_id];
141 if (hints->magic == VBVAMODEHINT_MAGIC) {
142 disconnected = !(hints->fEnabled);
143 crtc_id = vbox_connector->vbox_crtc->crtc_id;
144 flags = VBVA_SCREEN_F_ACTIVE
145 | (disconnected ? VBVA_SCREEN_F_DISABLED : VBVA_SCREEN_F_BLANK);
146 vbox_connector->mode_hint.width = hints->cx & 0x8fff;
147 vbox_connector->mode_hint.height = hints->cy & 0x8fff;
148 vbox_connector->vbox_crtc->x_hint = hints->dx;
149 vbox_connector->vbox_crtc->y_hint = hints->dy;
150 vbox_connector->mode_hint.disconnected = disconnected;
151 if (vbox_connector->vbox_crtc->disconnected != disconnected) {
152 VBoxHGSMIProcessDisplayInfo(&vbox->submit_info, crtc_id,
153 0, 0, 0, hints->cx * 4, hints->cx,
154 hints->cy, 0, flags);
155 vbox_connector->vbox_crtc->disconnected = disconnected;
156 }
157 }
158 }
159#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
160 drm_modeset_unlock_all(dev);
161#else
162 mutex_unlock(&dev->mode_config.mutex);
163#endif
164}
165
166static void vbox_hotplug_worker(struct work_struct *work)
167{
168 struct vbox_private *vbox = container_of(work, struct vbox_private,
169 hotplug_work);
170
171 vbox_update_mode_hints(vbox);
172 drm_kms_helper_hotplug_event(vbox->dev);
173}
174
175int vbox_irq_init(struct vbox_private *vbox)
176{
177 int ret;
178
179 vbox_update_mode_hints(vbox);
180#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
181 ret = drm_irq_install(vbox->dev, vbox->dev->pdev->irq);
182#else
183 ret = drm_irq_install(vbox->dev);
184#endif
185 if (unlikely(ret != 0)) {
186 vbox_irq_fini(vbox);
187 DRM_ERROR("Failed installing irq: %d\n", ret);
188 return 1;
189 }
190 INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker);
191 vbox->isr_installed = true;
192 return 0;
193}
194
195void vbox_irq_fini(struct vbox_private *vbox)
196{
197 if (vbox->isr_installed) {
198 drm_irq_uninstall(vbox->dev);
199 flush_work(&vbox->hotplug_work);
200 vbox->isr_installed = false;
201 }
202}
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