Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Xen para-virtual frame buffer device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2005-2006 Anthony Liguori <aliguori@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  Based on linux/drivers/video/q40fb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *  This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *  License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * Switch to grant tables when they become capable of dealing with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * frame buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <asm/xen/hypervisor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <xen/xen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <xen/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <xen/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <xen/interface/io/fbif.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <xen/interface/io/protocols.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include <xen/xenbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include <xen/platform_pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) struct xenfb_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	unsigned char		*fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct fb_info		*fb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	int			x1, y1, x2, y2;	/* dirty rectangle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 						   protected by dirty_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	spinlock_t		dirty_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int			nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	int			irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	struct xenfb_page	*page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long 		*gfns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	int			update_wanted; /* XENFB_TYPE_UPDATE wanted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	int			feature_resize; /* XENFB_TYPE_RESIZE ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct xenfb_resize	resize;		/* protected by resize_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	int			resize_dpy;	/* ditto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	spinlock_t		resize_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct xenbus_device	*xbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) #define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) enum { KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int video[KPARAM_CNT] = { 2, XENFB_WIDTH, XENFB_HEIGHT };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) module_param_array(video, int, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) MODULE_PARM_DESC(video,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	"Video memory size in MB, width, height in pixels (default 2,800,600)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static void xenfb_make_preferred_console(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static int xenfb_remove(struct xenbus_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static void xenfb_disconnect_backend(struct xenfb_info *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static void xenfb_send_event(struct xenfb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			     union xenfb_out_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u32 prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	prod = info->page->out_prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	/* caller ensures !xenfb_queue_full() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	mb();			/* ensure ring space available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	XENFB_OUT_RING_REF(info->page, prod) = *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	wmb();			/* ensure ring contents visible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	info->page->out_prod = prod + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	notify_remote_via_irq(info->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static void xenfb_do_update(struct xenfb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			    int x, int y, int w, int h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	union xenfb_out_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	memset(&event, 0, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	event.type = XENFB_TYPE_UPDATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	event.update.x = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	event.update.y = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	event.update.width = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	event.update.height = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	/* caller ensures !xenfb_queue_full() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	xenfb_send_event(info, &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void xenfb_do_resize(struct xenfb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	union xenfb_out_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	memset(&event, 0, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	event.resize = info->resize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	/* caller ensures !xenfb_queue_full() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	xenfb_send_event(info, &event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int xenfb_queue_full(struct xenfb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	u32 cons, prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	prod = info->page->out_prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	cons = info->page->out_cons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	return prod - cons == XENFB_OUT_RING_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void xenfb_handle_resize_dpy(struct xenfb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	spin_lock_irqsave(&info->resize_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (info->resize_dpy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		if (!xenfb_queue_full(info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			info->resize_dpy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			xenfb_do_resize(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	spin_unlock_irqrestore(&info->resize_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static void xenfb_refresh(struct xenfb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			  int x1, int y1, int w, int h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	int x2 = x1 + w - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	int y2 = y1 + h - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	xenfb_handle_resize_dpy(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (!info->update_wanted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	spin_lock_irqsave(&info->dirty_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	/* Combine with dirty rectangle: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (info->y1 < y1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		y1 = info->y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (info->y2 > y2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		y2 = info->y2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (info->x1 < x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		x1 = info->x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (info->x2 > x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		x2 = info->x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (xenfb_queue_full(info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		/* Can't send right now, stash it in the dirty rectangle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		info->x1 = x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		info->x2 = x2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		info->y1 = y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		info->y2 = y2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		spin_unlock_irqrestore(&info->dirty_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	/* Clear dirty rectangle: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	info->x1 = info->y1 = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	info->x2 = info->y2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	spin_unlock_irqrestore(&info->dirty_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (x1 <= x2 && y1 <= y2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void xenfb_deferred_io(struct fb_info *fb_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			      struct list_head *pagelist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct xenfb_info *info = fb_info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	unsigned long beg, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	int y1, y2, miny, maxy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	miny = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	maxy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	list_for_each_entry(page, pagelist, lru) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		beg = page->index << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		end = beg + PAGE_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		y1 = beg / fb_info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		y2 = end / fb_info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		if (y2 >= fb_info->var.yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			y2 = fb_info->var.yres - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		if (miny > y1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			miny = y1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		if (maxy < y2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			maxy = y2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static struct fb_deferred_io xenfb_defio = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	.delay		= HZ / 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	.deferred_io	= xenfb_deferred_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			   unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			   struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	if (regno > info->cmap.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	red = CNVT_TOHW(red, info->var.red.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	green = CNVT_TOHW(green, info->var.green.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	blue = CNVT_TOHW(blue, info->var.blue.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	transp = CNVT_TOHW(transp, info->var.transp.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #undef CNVT_TOHW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	v = (red << info->var.red.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	    (green << info->var.green.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	    (blue << info->var.blue.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		((u32 *)info->pseudo_palette)[regno] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	struct xenfb_info *info = p->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	sys_fillrect(p, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	struct xenfb_info *info = p->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	sys_imageblit(p, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	struct xenfb_info *info = p->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	sys_copyarea(p, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	struct xenfb_info *info = p->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	ssize_t res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	res = fb_sys_write(p, buf, count, ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	struct xenfb_info *xenfb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	int required_mem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	xenfb_info = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if (!xenfb_info->feature_resize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		if (var->xres == video[KPARAM_WIDTH] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		    var->yres == video[KPARAM_HEIGHT] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		    var->bits_per_pixel == xenfb_info->page->depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	/* Can't resize past initial width and height */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (var->xres > video[KPARAM_WIDTH] || var->yres > video[KPARAM_HEIGHT])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	required_mem_len = var->xres * var->yres * xenfb_info->page->depth / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	if (var->bits_per_pixel == xenfb_info->page->depth &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	    var->xres <= info->fix.line_length / (XENFB_DEPTH / 8) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	    required_mem_len <= info->fix.smem_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		var->yres_virtual = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int xenfb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct xenfb_info *xenfb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	xenfb_info = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	spin_lock_irqsave(&xenfb_info->resize_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	xenfb_info->resize.type = XENFB_TYPE_RESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	xenfb_info->resize.width = info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	xenfb_info->resize.height = info->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	xenfb_info->resize.stride = info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	xenfb_info->resize.depth = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	xenfb_info->resize.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	xenfb_info->resize_dpy = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	spin_unlock_irqrestore(&xenfb_info->resize_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static const struct fb_ops xenfb_fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	.fb_read	= fb_sys_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	.fb_write	= xenfb_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	.fb_setcolreg	= xenfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	.fb_fillrect	= xenfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	.fb_copyarea	= xenfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	.fb_imageblit	= xenfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	.fb_check_var	= xenfb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	.fb_set_par     = xenfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	 * No in events recognized, simply ignore them all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	 * If you need to recognize some, see xen-kbdfront's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	 * input_handler() for how to do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	struct xenfb_info *info = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	struct xenfb_page *page = info->page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	if (page->in_cons != page->in_prod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		info->page->in_cons = info->page->in_prod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		notify_remote_via_irq(info->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	/* Flush dirty rectangle: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static int xenfb_probe(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		       const struct xenbus_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	struct xenfb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	struct fb_info *fb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	int fb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	info = kzalloc(sizeof(*info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	if (info == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	/* Limit kernel param videoram amount to what is in xenstore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		if (val < video[KPARAM_MEM])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			video[KPARAM_MEM] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	video[KPARAM_WIDTH] = xenbus_read_unsigned(dev->otherend, "width",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 						   video[KPARAM_WIDTH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	video[KPARAM_HEIGHT] = xenbus_read_unsigned(dev->otherend, "height",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 						    video[KPARAM_HEIGHT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	/* If requested res does not fit in available memory, use default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	fb_size = video[KPARAM_MEM] * 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	    > fb_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		pr_warn("display parameters %d,%d,%d invalid, use defaults\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			video[KPARAM_MEM], video[KPARAM_WIDTH],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 			video[KPARAM_HEIGHT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		video[KPARAM_WIDTH] = XENFB_WIDTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		video[KPARAM_HEIGHT] = XENFB_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		fb_size = XENFB_DEFAULT_FB_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	dev_set_drvdata(&dev->dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	info->xbdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	info->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	info->x1 = info->y1 = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	spin_lock_init(&info->dirty_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	spin_lock_init(&info->resize_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	info->fb = vzalloc(fb_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	if (info->fb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	info->gfns = vmalloc(array_size(sizeof(unsigned long), info->nr_pages));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	if (!info->gfns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	/* set up shared page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	if (!info->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	/* abusing framebuffer_alloc() to allocate pseudo_palette */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	if (fb_info == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		goto error_nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	/* complete the abuse: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	fb_info->pseudo_palette = fb_info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	fb_info->par = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	fb_info->screen_base = info->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	fb_info->fbops = &xenfb_fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	fb_info->var.bits_per_pixel = XENFB_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	fb_info->var.red = (struct fb_bitfield){16, 8, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	fb_info->var.green = (struct fb_bitfield){8, 8, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	fb_info->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	fb_info->var.height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	fb_info->var.width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	fb_info->var.vmode = FB_VMODE_NONINTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	fb_info->fix.smem_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	fb_info->fix.smem_len = fb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	strcpy(fb_info->fix.id, "xen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	fb_info->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		framebuffer_release(fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	fb_info->fbdefio = &xenfb_defio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	fb_deferred_io_init(fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	xenfb_init_shared_page(info, fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	ret = xenfb_connect_backend(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		goto error_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	ret = register_framebuffer(fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		xenbus_dev_fatal(dev, ret, "register_framebuffer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		goto error_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	info->fb_info = fb_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	xenfb_make_preferred_console();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) error_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	fb_deferred_io_cleanup(fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	fb_dealloc_cmap(&fb_info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	framebuffer_release(fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) error_nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		xenbus_dev_fatal(dev, ret, "allocating device memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	xenfb_remove(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static void xenfb_make_preferred_console(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	struct console *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	if (console_set_on_cmdline)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	for_each_console(c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		if (!strcmp(c->name, "tty") && c->index == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		unregister_console(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		c->flags |= CON_CONSDEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		register_console(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static int xenfb_resume(struct xenbus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	xenfb_disconnect_backend(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	xenfb_init_shared_page(info, info->fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	return xenfb_connect_backend(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int xenfb_remove(struct xenbus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	xenfb_disconnect_backend(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	if (info->fb_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		fb_deferred_io_cleanup(info->fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		unregister_framebuffer(info->fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		fb_dealloc_cmap(&info->fb_info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		framebuffer_release(info->fb_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	free_page((unsigned long)info->page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	vfree(info->gfns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	vfree(info->fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static unsigned long vmalloc_to_gfn(void *address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	return xen_page_to_gfn(vmalloc_to_page(address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static void xenfb_init_shared_page(struct xenfb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 				   struct fb_info *fb_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	int epd = PAGE_SIZE / sizeof(info->gfns[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	for (i = 0; i < info->nr_pages; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		info->gfns[i] = vmalloc_to_gfn(info->fb + i * PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	for (i = 0; i * epd < info->nr_pages; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		info->page->pd[i] = vmalloc_to_gfn(&info->gfns[i * epd]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	info->page->width = fb_info->var.xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	info->page->height = fb_info->var.yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	info->page->depth = fb_info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	info->page->line_length = fb_info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	info->page->mem_length = fb_info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	info->page->in_cons = info->page->in_prod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	info->page->out_cons = info->page->out_prod = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static int xenfb_connect_backend(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 				 struct xenfb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	int ret, evtchn, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	struct xenbus_transaction xbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	ret = xenbus_alloc_evtchn(dev, &evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	irq = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 					0, dev->devicetype, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		xenbus_free_evtchn(dev, evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		return irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)  again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	ret = xenbus_transaction_start(&xbt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		xenbus_dev_fatal(dev, ret, "starting transaction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		goto unbind_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 			    virt_to_gfn(info->page));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 			    evtchn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 		goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 			    XEN_IO_PROTO_ABI_NATIVE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		goto error_xenbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	ret = xenbus_transaction_end(xbt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		if (ret == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 			goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		xenbus_dev_fatal(dev, ret, "completing transaction");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		goto unbind_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	xenbus_switch_state(dev, XenbusStateInitialised);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	info->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)  error_xenbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	xenbus_transaction_end(xbt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	xenbus_dev_fatal(dev, ret, "writing xenstore");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)  unbind_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	unbind_from_irqhandler(irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static void xenfb_disconnect_backend(struct xenfb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	/* Prevent xenfb refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	info->update_wanted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	if (info->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 		unbind_from_irqhandler(info->irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	info->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static void xenfb_backend_changed(struct xenbus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 				  enum xenbus_state backend_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	struct xenfb_info *info = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	switch (backend_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	case XenbusStateInitialising:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	case XenbusStateInitialised:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	case XenbusStateReconfiguring:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	case XenbusStateReconfigured:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	case XenbusStateUnknown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	case XenbusStateInitWait:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 		xenbus_switch_state(dev, XenbusStateConnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	case XenbusStateConnected:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		 * Work around xenbus race condition: If backend goes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 		 * through InitWait to Connected fast enough, we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		 * get Connected twice here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		if (dev->state != XenbusStateConnected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 			/* no InitWait seen yet, fudge it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 			xenbus_switch_state(dev, XenbusStateConnected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		if (xenbus_read_unsigned(info->xbdev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 					 "request-update", 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			info->update_wanted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		info->feature_resize = xenbus_read_unsigned(dev->otherend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 							"feature-resize", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	case XenbusStateClosed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		if (dev->state == XenbusStateClosed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		fallthrough;	/* Missed the backend's CLOSING state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	case XenbusStateClosing:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		xenbus_frontend_closed(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static const struct xenbus_device_id xenfb_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	{ "vfb" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	{ "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static struct xenbus_driver xenfb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	.ids = xenfb_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	.probe = xenfb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	.remove = xenfb_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	.resume = xenfb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	.otherend_changed = xenfb_backend_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static int __init xenfb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	if (!xen_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	/* Nothing to do if running in dom0. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	if (xen_initial_domain())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	if (!xen_has_pv_devices())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	return xenbus_register_frontend(&xenfb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void __exit xenfb_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	xenbus_unregister_driver(&xenfb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) module_init(xenfb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) module_exit(xenfb_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) MODULE_ALIAS("xen:vfb");