VirtualBox

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

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

bugref:8834: Makeself installers/Linux: indicate problems better in the exit codes
[PATCH] additions/linux/drm: Cleanup vram mapping and offset
calculating code

Trying to put everything in one pci_iomap_range mapped area leads to
hard to read code and has no advantages. It actually causes us to map
more memory then we need, resulting in part of the memory being intended
for generic use also being mapped.

This commit splits the mapping up in to 2 pci_iomap_range calls, one
for the guest_heap + host-flags and another one for the vbva buffers
which is not done until we actually know how much buffers we need.

Signed-off-by: Hans de Goede <hdegoede@…>
Minor adjustment: GUEST_HEAP_OFFSET -> GUEST_HEAP_OFFSET(vbox)

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