VirtualBox

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

Last change on this file since 67269 was 67175, checked in by vboxsync, 8 years ago

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
[PATCH 2/3] additions/linux/drm: Remove unnecessary wrapping of guest_pool in a struct
Signed-off-by: Hans de Goede <hdegoede@…>

  • 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 67175 2017-05-31 14:38:02Z 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->guest_pool, 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->guest_pool, 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