1131abc56SHans de Goede /* SPDX-License-Identifier: MIT */ 2131abc56SHans de Goede /* 3131abc56SHans de Goede * Copyright (C) 2013-2017 Oracle Corporation 4131abc56SHans de Goede * This file is based on ast_drv.h 5131abc56SHans de Goede * Copyright 2012 Red Hat Inc. 6131abc56SHans de Goede * Authors: Dave Airlie <airlied@redhat.com> 7131abc56SHans de Goede * Michael Thayer <michael.thayer@oracle.com, 8131abc56SHans de Goede * Hans de Goede <hdegoede@redhat.com> 9131abc56SHans de Goede */ 10131abc56SHans de Goede #ifndef __VBOX_DRV_H__ 11131abc56SHans de Goede #define __VBOX_DRV_H__ 12131abc56SHans de Goede 13131abc56SHans de Goede #include <linux/genalloc.h> 14131abc56SHans de Goede #include <linux/io.h> 15131abc56SHans de Goede #include <linux/irqreturn.h> 16131abc56SHans de Goede #include <linux/string.h> 17131abc56SHans de Goede #include <linux/version.h> 18131abc56SHans de Goede 19131abc56SHans de Goede #include <drm/drm_encoder.h> 20131abc56SHans de Goede #include <drm/drm_fb_helper.h> 21131abc56SHans de Goede #include <drm/drm_gem.h> 22131abc56SHans de Goede 23131abc56SHans de Goede #include <drm/ttm/ttm_bo_api.h> 24131abc56SHans de Goede #include <drm/ttm/ttm_bo_driver.h> 25131abc56SHans de Goede #include <drm/ttm/ttm_placement.h> 26131abc56SHans de Goede #include <drm/ttm/ttm_memory.h> 27131abc56SHans de Goede #include <drm/ttm/ttm_module.h> 28131abc56SHans de Goede 29131abc56SHans de Goede #include "vboxvideo_guest.h" 30131abc56SHans de Goede #include "vboxvideo_vbe.h" 31131abc56SHans de Goede #include "hgsmi_ch_setup.h" 32131abc56SHans de Goede 33131abc56SHans de Goede #define DRIVER_NAME "vboxvideo" 34131abc56SHans de Goede #define DRIVER_DESC "Oracle VM VirtualBox Graphics Card" 35131abc56SHans de Goede #define DRIVER_DATE "20130823" 36131abc56SHans de Goede 37131abc56SHans de Goede #define DRIVER_MAJOR 1 38131abc56SHans de Goede #define DRIVER_MINOR 0 39131abc56SHans de Goede #define DRIVER_PATCHLEVEL 0 40131abc56SHans de Goede 41131abc56SHans de Goede #define VBOX_MAX_CURSOR_WIDTH 64 42131abc56SHans de Goede #define VBOX_MAX_CURSOR_HEIGHT 64 43131abc56SHans de Goede #define CURSOR_PIXEL_COUNT (VBOX_MAX_CURSOR_WIDTH * VBOX_MAX_CURSOR_HEIGHT) 44131abc56SHans de Goede #define CURSOR_DATA_SIZE (CURSOR_PIXEL_COUNT * 4 + CURSOR_PIXEL_COUNT / 8) 45131abc56SHans de Goede 46131abc56SHans de Goede #define VBOX_MAX_SCREENS 32 47131abc56SHans de Goede 48131abc56SHans de Goede #define GUEST_HEAP_OFFSET(vbox) ((vbox)->full_vram_size - \ 49131abc56SHans de Goede VBVA_ADAPTER_INFORMATION_SIZE) 50131abc56SHans de Goede #define GUEST_HEAP_SIZE VBVA_ADAPTER_INFORMATION_SIZE 51131abc56SHans de Goede #define GUEST_HEAP_USABLE_SIZE (VBVA_ADAPTER_INFORMATION_SIZE - \ 52131abc56SHans de Goede sizeof(struct hgsmi_host_flags)) 53131abc56SHans de Goede #define HOST_FLAGS_OFFSET GUEST_HEAP_USABLE_SIZE 54131abc56SHans de Goede 55131abc56SHans de Goede struct vbox_framebuffer { 56131abc56SHans de Goede struct drm_framebuffer base; 57131abc56SHans de Goede struct drm_gem_object *obj; 58131abc56SHans de Goede }; 59131abc56SHans de Goede 60131abc56SHans de Goede struct vbox_private { 61131abc56SHans de Goede /* Must be first; or we must define our own release callback */ 62131abc56SHans de Goede struct drm_device ddev; 63131abc56SHans de Goede struct drm_fb_helper fb_helper; 64131abc56SHans de Goede struct vbox_framebuffer afb; 65131abc56SHans de Goede 66131abc56SHans de Goede u8 __iomem *guest_heap; 67131abc56SHans de Goede u8 __iomem *vbva_buffers; 68131abc56SHans de Goede struct gen_pool *guest_pool; 69131abc56SHans de Goede struct vbva_buf_ctx *vbva_info; 70131abc56SHans de Goede bool any_pitch; 71131abc56SHans de Goede u32 num_crtcs; 72131abc56SHans de Goede /* Amount of available VRAM, including space used for buffers. */ 73131abc56SHans de Goede u32 full_vram_size; 74131abc56SHans de Goede /* Amount of available VRAM, not including space used for buffers. */ 75131abc56SHans de Goede u32 available_vram_size; 76131abc56SHans de Goede /* Array of structures for receiving mode hints. */ 77131abc56SHans de Goede struct vbva_modehint *last_mode_hints; 78131abc56SHans de Goede 79131abc56SHans de Goede int fb_mtrr; 80131abc56SHans de Goede 81131abc56SHans de Goede struct { 82131abc56SHans de Goede struct ttm_bo_device bdev; 83131abc56SHans de Goede } ttm; 84131abc56SHans de Goede 85131abc56SHans de Goede struct mutex hw_mutex; /* protects modeset and accel/vbva accesses */ 86131abc56SHans de Goede struct work_struct hotplug_work; 87131abc56SHans de Goede u32 input_mapping_width; 88131abc56SHans de Goede u32 input_mapping_height; 89131abc56SHans de Goede /* 90131abc56SHans de Goede * Is user-space using an X.Org-style layout of one large frame-buffer 91131abc56SHans de Goede * encompassing all screen ones or is the fbdev console active? 92131abc56SHans de Goede */ 93131abc56SHans de Goede bool single_framebuffer; 94131abc56SHans de Goede u8 cursor_data[CURSOR_DATA_SIZE]; 95131abc56SHans de Goede }; 96131abc56SHans de Goede 97131abc56SHans de Goede #undef CURSOR_PIXEL_COUNT 98131abc56SHans de Goede #undef CURSOR_DATA_SIZE 99131abc56SHans de Goede 100131abc56SHans de Goede struct vbox_gem_object; 101131abc56SHans de Goede 102131abc56SHans de Goede struct vbox_connector { 103131abc56SHans de Goede struct drm_connector base; 104131abc56SHans de Goede char name[32]; 105131abc56SHans de Goede struct vbox_crtc *vbox_crtc; 106131abc56SHans de Goede struct { 107131abc56SHans de Goede u32 width; 108131abc56SHans de Goede u32 height; 109131abc56SHans de Goede bool disconnected; 110131abc56SHans de Goede } mode_hint; 111131abc56SHans de Goede }; 112131abc56SHans de Goede 113131abc56SHans de Goede struct vbox_crtc { 114131abc56SHans de Goede struct drm_crtc base; 115131abc56SHans de Goede bool disconnected; 116131abc56SHans de Goede unsigned int crtc_id; 117131abc56SHans de Goede u32 fb_offset; 118131abc56SHans de Goede bool cursor_enabled; 119131abc56SHans de Goede u32 x_hint; 120131abc56SHans de Goede u32 y_hint; 121131abc56SHans de Goede /* 122131abc56SHans de Goede * When setting a mode we not only pass the mode to the hypervisor, 123131abc56SHans de Goede * but also information on how to map / translate input coordinates 124131abc56SHans de Goede * for the emulated USB tablet. This input-mapping may change when 125131abc56SHans de Goede * the mode on *another* crtc changes. 126131abc56SHans de Goede * 127131abc56SHans de Goede * This means that sometimes we must do a modeset on other crtc-s then 128131abc56SHans de Goede * the one being changed to update the input-mapping. Including crtc-s 129131abc56SHans de Goede * which may be disabled inside the guest (shown as a black window 130131abc56SHans de Goede * on the host unless closed by the user). 131131abc56SHans de Goede * 132131abc56SHans de Goede * With atomic modesetting the mode-info of disabled crtcs gets zeroed 133131abc56SHans de Goede * yet we need it when updating the input-map to avoid resizing the 134131abc56SHans de Goede * window as a side effect of a mode_set on another crtc. Therefor we 135131abc56SHans de Goede * cache the info of the last mode below. 136131abc56SHans de Goede */ 137131abc56SHans de Goede u32 width; 138131abc56SHans de Goede u32 height; 139131abc56SHans de Goede u32 x; 140131abc56SHans de Goede u32 y; 141131abc56SHans de Goede }; 142131abc56SHans de Goede 143131abc56SHans de Goede struct vbox_encoder { 144131abc56SHans de Goede struct drm_encoder base; 145131abc56SHans de Goede }; 146131abc56SHans de Goede 147131abc56SHans de Goede #define to_vbox_crtc(x) container_of(x, struct vbox_crtc, base) 148131abc56SHans de Goede #define to_vbox_connector(x) container_of(x, struct vbox_connector, base) 149131abc56SHans de Goede #define to_vbox_encoder(x) container_of(x, struct vbox_encoder, base) 150131abc56SHans de Goede #define to_vbox_framebuffer(x) container_of(x, struct vbox_framebuffer, base) 151131abc56SHans de Goede 152131abc56SHans de Goede bool vbox_check_supported(u16 id); 153131abc56SHans de Goede int vbox_hw_init(struct vbox_private *vbox); 154131abc56SHans de Goede void vbox_hw_fini(struct vbox_private *vbox); 155131abc56SHans de Goede 156131abc56SHans de Goede int vbox_mode_init(struct vbox_private *vbox); 157131abc56SHans de Goede void vbox_mode_fini(struct vbox_private *vbox); 158131abc56SHans de Goede 159131abc56SHans de Goede void vbox_report_caps(struct vbox_private *vbox); 160131abc56SHans de Goede 161131abc56SHans de Goede void vbox_framebuffer_dirty_rectangles(struct drm_framebuffer *fb, 162131abc56SHans de Goede struct drm_clip_rect *rects, 163131abc56SHans de Goede unsigned int num_rects); 164131abc56SHans de Goede 165131abc56SHans de Goede int vbox_framebuffer_init(struct vbox_private *vbox, 166131abc56SHans de Goede struct vbox_framebuffer *vbox_fb, 167131abc56SHans de Goede const struct drm_mode_fb_cmd2 *mode_cmd, 168131abc56SHans de Goede struct drm_gem_object *obj); 169131abc56SHans de Goede 170131abc56SHans de Goede int vboxfb_create(struct drm_fb_helper *helper, 171131abc56SHans de Goede struct drm_fb_helper_surface_size *sizes); 172131abc56SHans de Goede void vbox_fbdev_fini(struct vbox_private *vbox); 173131abc56SHans de Goede 174131abc56SHans de Goede struct vbox_bo { 175131abc56SHans de Goede struct ttm_buffer_object bo; 176131abc56SHans de Goede struct ttm_placement placement; 177131abc56SHans de Goede struct ttm_bo_kmap_obj kmap; 178131abc56SHans de Goede struct drm_gem_object gem; 179131abc56SHans de Goede struct ttm_place placements[3]; 180131abc56SHans de Goede int pin_count; 181131abc56SHans de Goede }; 182131abc56SHans de Goede 183131abc56SHans de Goede #define gem_to_vbox_bo(gobj) container_of((gobj), struct vbox_bo, gem) 184131abc56SHans de Goede 185131abc56SHans de Goede static inline struct vbox_bo *vbox_bo(struct ttm_buffer_object *bo) 186131abc56SHans de Goede { 187131abc56SHans de Goede return container_of(bo, struct vbox_bo, bo); 188131abc56SHans de Goede } 189131abc56SHans de Goede 190131abc56SHans de Goede #define to_vbox_obj(x) container_of(x, struct vbox_gem_object, base) 191131abc56SHans de Goede 192131abc56SHans de Goede static inline u64 vbox_bo_gpu_offset(struct vbox_bo *bo) 193131abc56SHans de Goede { 194131abc56SHans de Goede return bo->bo.offset; 195131abc56SHans de Goede } 196131abc56SHans de Goede 197131abc56SHans de Goede int vbox_dumb_create(struct drm_file *file, 198131abc56SHans de Goede struct drm_device *dev, 199131abc56SHans de Goede struct drm_mode_create_dumb *args); 200131abc56SHans de Goede 201131abc56SHans de Goede void vbox_gem_free_object(struct drm_gem_object *obj); 202131abc56SHans de Goede int vbox_dumb_mmap_offset(struct drm_file *file, 203131abc56SHans de Goede struct drm_device *dev, 204131abc56SHans de Goede u32 handle, u64 *offset); 205131abc56SHans de Goede 206131abc56SHans de Goede #define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT) 207131abc56SHans de Goede 208131abc56SHans de Goede int vbox_mm_init(struct vbox_private *vbox); 209131abc56SHans de Goede void vbox_mm_fini(struct vbox_private *vbox); 210131abc56SHans de Goede 211131abc56SHans de Goede int vbox_bo_create(struct vbox_private *vbox, int size, int align, 212131abc56SHans de Goede u32 flags, struct vbox_bo **pvboxbo); 213131abc56SHans de Goede 214131abc56SHans de Goede int vbox_gem_create(struct vbox_private *vbox, 215131abc56SHans de Goede u32 size, bool iskernel, struct drm_gem_object **obj); 216131abc56SHans de Goede 217131abc56SHans de Goede int vbox_bo_pin(struct vbox_bo *bo, u32 pl_flag); 218131abc56SHans de Goede int vbox_bo_unpin(struct vbox_bo *bo); 219131abc56SHans de Goede 220131abc56SHans de Goede static inline int vbox_bo_reserve(struct vbox_bo *bo, bool no_wait) 221131abc56SHans de Goede { 222131abc56SHans de Goede int ret; 223131abc56SHans de Goede 224131abc56SHans de Goede ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL); 225131abc56SHans de Goede if (ret) { 226131abc56SHans de Goede if (ret != -ERESTARTSYS && ret != -EBUSY) 227131abc56SHans de Goede DRM_ERROR("reserve failed %p\n", bo); 228131abc56SHans de Goede return ret; 229131abc56SHans de Goede } 230131abc56SHans de Goede return 0; 231131abc56SHans de Goede } 232131abc56SHans de Goede 233131abc56SHans de Goede static inline void vbox_bo_unreserve(struct vbox_bo *bo) 234131abc56SHans de Goede { 235131abc56SHans de Goede ttm_bo_unreserve(&bo->bo); 236131abc56SHans de Goede } 237131abc56SHans de Goede 238131abc56SHans de Goede void vbox_ttm_placement(struct vbox_bo *bo, int domain); 239131abc56SHans de Goede int vbox_bo_push_sysram(struct vbox_bo *bo); 240131abc56SHans de Goede int vbox_mmap(struct file *filp, struct vm_area_struct *vma); 241131abc56SHans de Goede void *vbox_bo_kmap(struct vbox_bo *bo); 242131abc56SHans de Goede void vbox_bo_kunmap(struct vbox_bo *bo); 243131abc56SHans de Goede 244131abc56SHans de Goede /* vbox_prime.c */ 245131abc56SHans de Goede int vbox_gem_prime_pin(struct drm_gem_object *obj); 246131abc56SHans de Goede void vbox_gem_prime_unpin(struct drm_gem_object *obj); 247131abc56SHans de Goede struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj); 248131abc56SHans de Goede struct drm_gem_object *vbox_gem_prime_import_sg_table( 249131abc56SHans de Goede struct drm_device *dev, struct dma_buf_attachment *attach, 250131abc56SHans de Goede struct sg_table *table); 251131abc56SHans de Goede void *vbox_gem_prime_vmap(struct drm_gem_object *obj); 252131abc56SHans de Goede void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); 253131abc56SHans de Goede int vbox_gem_prime_mmap(struct drm_gem_object *obj, 254131abc56SHans de Goede struct vm_area_struct *area); 255131abc56SHans de Goede 256131abc56SHans de Goede /* vbox_irq.c */ 257131abc56SHans de Goede int vbox_irq_init(struct vbox_private *vbox); 258131abc56SHans de Goede void vbox_irq_fini(struct vbox_private *vbox); 259131abc56SHans de Goede void vbox_report_hotplug(struct vbox_private *vbox); 260131abc56SHans de Goede irqreturn_t vbox_irq_handler(int irq, void *arg); 261131abc56SHans de Goede 262131abc56SHans de Goede /* vbox_hgsmi.c */ 263131abc56SHans de Goede void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size, 264131abc56SHans de Goede u8 channel, u16 channel_info); 265131abc56SHans de Goede void hgsmi_buffer_free(struct gen_pool *guest_pool, void *buf); 266131abc56SHans de Goede int hgsmi_buffer_submit(struct gen_pool *guest_pool, void *buf); 267131abc56SHans de Goede 268131abc56SHans de Goede static inline void vbox_write_ioport(u16 index, u16 data) 269131abc56SHans de Goede { 270131abc56SHans de Goede outw(index, VBE_DISPI_IOPORT_INDEX); 271131abc56SHans de Goede outw(data, VBE_DISPI_IOPORT_DATA); 272131abc56SHans de Goede } 273131abc56SHans de Goede 274131abc56SHans de Goede #endif 275