儲存庫 vbox 的更動 67402
- 時間撮記:
- 2017-6-14 下午01:13:07 (7 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Additions/linux/drm/vbox_irq.c
r67175 r67402 41 41 static void vbox_clear_irq(void) 42 42 { 43 outl((uint32_t)~0, VGA_PORT_HGSMI_HOST);44 } 45 46 static u int32_tvbox_get_flags(struct vbox_private *vbox)43 outl((u32)~0, VGA_PORT_HGSMI_HOST); 44 } 45 46 static u32 vbox_get_flags(struct vbox_private *vbox) 47 47 { 48 48 return readl(vbox->guest_heap + HOST_FLAGS_OFFSET); … … 51 51 void vbox_report_hotplug(struct vbox_private *vbox) 52 52 { 53 53 schedule_work(&vbox->hotplug_work); 54 54 } 55 55 56 56 irqreturn_t vbox_irq_handler(int irq, void *arg) 57 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 58 struct drm_device *dev = (struct drm_device *)arg; 59 struct vbox_private *vbox = (struct vbox_private *)dev->dev_private; 60 u32 host_flags = vbox_get_flags(vbox); 61 62 if (!(host_flags & HGSMIHOSTFLAGS_IRQ)) 63 return IRQ_NONE; 64 65 /* 66 * Due to a bug in the initial host implementation of hot-plug irqs, 67 * the hot-plug and cursor capability flags were never cleared. 68 * Fortunately we can tell when they would have been set by checking 69 * that the VSYNC flag is not set. 70 */ 71 if (host_flags & 72 (HGSMIHOSTFLAGS_HOTPLUG | HGSMIHOSTFLAGS_CURSOR_CAPABILITIES) && 73 !(host_flags & HGSMIHOSTFLAGS_VSYNC)) 74 vbox_report_hotplug(vbox); 75 76 vbox_clear_irq(); 77 78 return IRQ_HANDLED; 79 } 80 81 /** 82 * Check that the position hints provided by the host are suitable for GNOME 77 83 * shell (i.e. all screens disjoint and hints for all enabled screens) and if 78 84 * not replace them with default ones. Providing valid hints improves the 79 * chances that we will get a known screen layout for pointer mapping. */ 85 * chances that we will get a known screen layout for pointer mapping. 86 */ 80 87 static void validate_or_set_position_hints(struct vbox_private *vbox) 81 88 { 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 } 89 int i, j; 90 u16 currentx = 0; 91 bool valid = true; 92 93 for (i = 0; i < vbox->num_crtcs; ++i) { 94 for (j = 0; j < i; ++j) { 95 struct VBVAMODEHINT *hintsi = &vbox->last_mode_hints[i]; 96 struct VBVAMODEHINT *hintsj = &vbox->last_mode_hints[j]; 97 98 if (hintsi->fEnabled && hintsj->fEnabled) { 99 if (hintsi->dx >= 0xffff || 100 hintsi->dy >= 0xffff || 101 hintsj->dx >= 0xffff || 102 hintsj->dy >= 0xffff || 103 (hintsi->dx < 104 hintsj->dx + (hintsj->cx & 0x8fff) && 105 hintsi->dx + (hintsi->cx & 0x8fff) > 106 hintsj->dx) || 107 (hintsi->dy < 108 hintsj->dy + (hintsj->cy & 0x8fff) && 109 hintsi->dy + (hintsi->cy & 0x8fff) > 110 hintsj->dy)) 111 valid = false; 112 } 113 } 114 } 115 if (!valid) 116 for (i = 0; i < vbox->num_crtcs; ++i) { 117 if (vbox->last_mode_hints[i].fEnabled) { 118 vbox->last_mode_hints[i].dx = currentx; 119 vbox->last_mode_hints[i].dy = 0; 120 currentx += 121 vbox->last_mode_hints[i].cx & 0x8fff; 122 } 123 } 110 124 } 111 125 … … 115 129 static void vbox_update_mode_hints(struct vbox_private *vbox) 116 130 { 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); 131 struct drm_device *dev = vbox->dev; 132 struct drm_connector *connector; 133 struct vbox_connector *vbox_connector; 134 struct VBVAMODEHINT *hints; 135 u16 flags; 136 bool disconnected; 137 unsigned int crtc_id; 138 int rc; 139 140 rc = VBoxHGSMIGetModeHints(vbox->guest_pool, vbox->num_crtcs, 141 vbox->last_mode_hints); 142 if (RT_FAILURE(rc)) { 143 DRM_ERROR("vboxvideo: VBoxHGSMIGetModeHints failed, rc=%i.\n", 144 rc); 145 return; 146 } 147 validate_or_set_position_hints(vbox); 133 148 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) 134 149 drm_modeset_lock_all(dev); 135 150 #else 136 151 mutex_lock(&dev->mode_config.mutex); 137 152 #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 } 153 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 154 vbox_connector = to_vbox_connector(connector); 155 hints = 156 &vbox->last_mode_hints[vbox_connector->vbox_crtc->crtc_id]; 157 if (hints->magic == VBVAMODEHINT_MAGIC) { 158 disconnected = !(hints->fEnabled); 159 crtc_id = vbox_connector->vbox_crtc->crtc_id; 160 flags = VBVA_SCREEN_F_ACTIVE 161 | (disconnected ? VBVA_SCREEN_F_DISABLED : 162 VBVA_SCREEN_F_BLANK); 163 vbox_connector->mode_hint.width = hints->cx & 0x8fff; 164 vbox_connector->mode_hint.height = hints->cy & 0x8fff; 165 vbox_connector->vbox_crtc->x_hint = hints->dx; 166 vbox_connector->vbox_crtc->y_hint = hints->dy; 167 vbox_connector->mode_hint.disconnected = disconnected; 168 if (vbox_connector->vbox_crtc->disconnected != 169 disconnected) { 170 VBoxHGSMIProcessDisplayInfo(vbox->guest_pool, 171 crtc_id, 0, 0, 0, 172 hints->cx * 4, 173 hints->cx, 174 hints->cy, 0, 175 flags); 176 vbox_connector->vbox_crtc->disconnected = 177 disconnected; 178 } 179 } 180 } 159 181 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) 160 182 drm_modeset_unlock_all(dev); 161 183 #else 162 184 mutex_unlock(&dev->mode_config.mutex); 163 185 #endif 164 186 } … … 166 188 static void vbox_hotplug_worker(struct work_struct *work) 167 189 { 168 169 170 171 172 190 struct vbox_private *vbox = container_of(work, struct vbox_private, 191 hotplug_work); 192 193 vbox_update_mode_hints(vbox); 194 drm_kms_helper_hotplug_event(vbox->dev); 173 195 } 174 196 175 197 int vbox_irq_init(struct vbox_private *vbox) 176 198 { 177 178 179 199 int ret; 200 201 vbox_update_mode_hints(vbox); 180 202 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) 181 203 ret = drm_irq_install(vbox->dev, vbox->dev->pdev->irq); 182 204 #else 183 205 ret = drm_irq_install(vbox->dev); 184 206 #endif 185 186 187 188 189 190 191 192 207 if (unlikely(ret != 0)) { 208 vbox_irq_fini(vbox); 209 DRM_ERROR("Failed installing irq: %d\n", ret); 210 return 1; 211 } 212 INIT_WORK(&vbox->hotplug_work, vbox_hotplug_worker); 213 vbox->isr_installed = true; 214 return 0; 193 215 } 194 216 195 217 void vbox_irq_fini(struct vbox_private *vbox) 196 218 { 197 198 199 200 201 202 } 219 if (vbox->isr_installed) { 220 drm_irq_uninstall(vbox->dev); 221 flush_work(&vbox->hotplug_work); 222 vbox->isr_installed = false; 223 } 224 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器