linux/drivers/video/fbdev/hyperv_fb.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012, Microsoft Corporation.
 *
 * Author:
 *   Haiyang Zhang <[email protected]>
 */

/*
 * Hyper-V Synthetic Video Frame Buffer Driver
 *
 * This is the driver for the Hyper-V Synthetic Video, which supports
 * screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
 * Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
 * or earlier.
 *
 * It also solves the double mouse cursor issue of the emulated video mode.
 *
 * The default screen resolution is 1152x864, which may be changed by a
 * kernel parameter:
 *     video=hyperv_fb:<width>x<height>
 *     For example: video=hyperv_fb:1280x1024
 *
 * Portrait orientation is also supported:
 *     For example: video=hyperv_fb:864x1152
 *
 * When a Windows 10 RS5+ host is used, the virtual machine screen
 * resolution is obtained from the host. The "video=hyperv_fb" option is
 * not needed, but still can be used to overwrite what the host specifies.
 * The VM resolution on the host could be set by executing the powershell
 * "set-vmvideo" command. For example
 *     set-vmvideo -vmname name -horizontalresolution:1920 \
 * -verticalresolution:1200 -resolutiontype single
 *
 * Gen 1 VMs also support direct using VM's physical memory for framebuffer.
 * It could improve the efficiency and performance for framebuffer and VM.
 * This requires to allocate contiguous physical memory from Linux kernel's
 * CMA memory allocator. To enable this, supply a kernel parameter to give
 * enough memory space to CMA allocator for framebuffer. For example:
 *    cma=130m
 * This gives 130MB memory to CMA allocator that can be allocated to
 * framebuffer. For reference, 8K resolution (7680x4320) takes about
 * 127MB memory.
 */

#define pr_fmt(fmt)

#include <linux/aperture.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/panic_notifier.h>
#include <linux/efi.h>
#include <linux/console.h>

#include <linux/hyperv.h>

/* Hyper-V Synthetic Video Protocol definitions and structures */
#define MAX_VMBUS_PKT_SIZE

#define SYNTHVID_VERSION(major, minor)
/* Support for VERSION_WIN7 is removed. #define is retained for reference. */
#define SYNTHVID_VERSION_WIN7
#define SYNTHVID_VERSION_WIN8
#define SYNTHVID_VERSION_WIN10

#define SYNTHVID_VER_GET_MAJOR(ver)
#define SYNTHVID_VER_GET_MINOR(ver)

#define SYNTHVID_DEPTH_WIN8
#define SYNTHVID_FB_SIZE_WIN8

enum pipe_msg_type {};

struct pipe_msg_hdr {} __packed;


enum synthvid_msg_type {};

#define SYNTHVID_EDID_BLOCK_SIZE
#define SYNTHVID_MAX_RESOLUTION_COUNT

struct hvd_screen_info {} __packed;

struct synthvid_msg_hdr {} __packed;

struct synthvid_version_req {} __packed;

struct synthvid_version_resp {} __packed;

struct synthvid_supported_resolution_req {} __packed;

struct synthvid_supported_resolution_resp {} __packed;

struct synthvid_vram_location {} __packed;

struct synthvid_vram_location_ack {} __packed;

struct video_output_situation {} __packed;

struct synthvid_situation_update {} __packed;

struct synthvid_situation_update_ack {} __packed;

struct synthvid_pointer_position {} __packed;


#define CURSOR_MAX_X
#define CURSOR_MAX_Y
#define CURSOR_ARGB_PIXEL_SIZE
#define CURSOR_MAX_SIZE
#define CURSOR_COMPLETE

struct synthvid_pointer_shape {} __packed;

struct synthvid_feature_change {} __packed;

struct rect {} __packed;

struct synthvid_dirt {} __packed;

struct synthvid_msg {} __packed;


/* FB driver definitions and structures */
#define HVFB_WIDTH
#define HVFB_HEIGHT
#define HVFB_WIDTH_MIN
#define HVFB_HEIGHT_MIN

#define RING_BUFSIZE
#define VSP_TIMEOUT
#define HVFB_UPDATE_DELAY
#define HVFB_ONDEMAND_THROTTLE

struct hvfb_par {};

static uint screen_width =;
static uint screen_height =;
static uint screen_depth;
static uint screen_fb_size;
static uint dio_fb_size; /* FB size for deferred IO */

/* Send message to Hyper-V host */
static inline int synthvid_send(struct hv_device *hdev,
				struct synthvid_msg *msg)
{}


/* Send screen resolution info to host */
static int synthvid_send_situ(struct hv_device *hdev)
{}

/* Send mouse pointer info to host */
static int synthvid_send_ptr(struct hv_device *hdev)
{}

/* Send updated screen area (dirty rectangle) location to host */
static int
synthvid_update(struct fb_info *info, int x1, int y1, int x2, int y2)
{}

static void hvfb_docopy(struct hvfb_par *par,
			unsigned long offset,
			unsigned long size)
{}

/* Deferred IO callback */
static void synthvid_deferred_io(struct fb_info *p, struct list_head *pagereflist)
{}

static struct fb_deferred_io synthvid_defio =;

/*
 * Actions on received messages from host:
 * Complete the wait event.
 * Or, reply with screen and cursor info.
 */
static void synthvid_recv_sub(struct hv_device *hdev)
{}

/* Receive callback for messages from the host */
static void synthvid_receive(void *ctx)
{}

/* Check if the ver1 version is equal or greater than ver2 */
static inline bool synthvid_ver_ge(u32 ver1, u32 ver2)
{}

/* Check synthetic video protocol version with the host */
static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
{}

/* Get current resolution from the host */
static int synthvid_get_supported_resolution(struct hv_device *hdev)
{}

/* Connect to VSP (Virtual Service Provider) on host */
static int synthvid_connect_vsp(struct hv_device *hdev)
{}

/* Send VRAM and Situation messages to the host */
static int synthvid_send_config(struct hv_device *hdev)
{}


/*
 * Delayed work callback:
 * It is scheduled to call whenever update request is received and it has
 * not been called in last HVFB_ONDEMAND_THROTTLE time interval.
 */
static void hvfb_update_work(struct work_struct *w)
{}

/*
 * Control the on-demand refresh frequency. It schedules a delayed
 * screen update if it has not yet.
 */
static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par,
					   int x1, int y1, int w, int h)
{}

static int hvfb_on_panic(struct notifier_block *nb,
			 unsigned long e, void *p)
{}

/* Framebuffer operation handlers */

static int hvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{}

static int hvfb_set_par(struct fb_info *info)
{}


static inline u32 chan_to_field(u32 chan, struct fb_bitfield *bf)
{}

static int hvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
			  unsigned blue, unsigned transp, struct fb_info *info)
{}

static int hvfb_blank(int blank, struct fb_info *info)
{}

static void hvfb_ops_damage_range(struct fb_info *info, off_t off, size_t len)
{}

static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)
{}

/*
 * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the
 *       driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases.
 */
FB_GEN_DEFAULT_DEFERRED_IOMEM_OPS(hvfb_ops,
				  hvfb_ops_damage_range,
				  hvfb_ops_damage_area)

static const struct fb_ops hvfb_ops =;

/* Get options from kernel paramenter "video=" */
static void hvfb_get_option(struct fb_info *info)
{}

/*
 * Allocate enough contiguous physical memory.
 * Return physical address if succeeded or -1 if failed.
 */
static phys_addr_t hvfb_get_phymem(struct hv_device *hdev,
				   unsigned int request_size)
{}

/* Release contiguous physical memory */
static void hvfb_release_phymem(struct hv_device *hdev,
				phys_addr_t paddr, unsigned int size)
{}


/* Get framebuffer memory from Hyper-V video pci space */
static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
{}

/* Release the framebuffer */
static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info)
{}


static int hvfb_probe(struct hv_device *hdev,
		      const struct hv_vmbus_device_id *dev_id)
{}

static void hvfb_remove(struct hv_device *hdev)
{}

static int hvfb_suspend(struct hv_device *hdev)
{}

static int hvfb_resume(struct hv_device *hdev)
{}


static const struct pci_device_id pci_stub_id_table[] =;

static const struct hv_vmbus_device_id id_table[] =;

MODULE_DEVICE_TABLE(pci, pci_stub_id_table);
MODULE_DEVICE_TABLE(vmbus, id_table);

static struct hv_driver hvfb_drv =;

static int hvfb_pci_stub_probe(struct pci_dev *pdev,
			       const struct pci_device_id *ent)
{}

static void hvfb_pci_stub_remove(struct pci_dev *pdev)
{}

static struct pci_driver hvfb_pci_stub_driver =;

static int __init hvfb_drv_init(void)
{}

static void __exit hvfb_drv_exit(void)
{}

module_init();
module_exit(hvfb_drv_exit);

MODULE_LICENSE();
MODULE_DESCRIPTION();