108e89f1eSPekka Enberg #include "kvm/framebuffer.h" 2*49a8afd1SSasha Levin #include "kvm/kvm.h" 308e89f1eSPekka Enberg 408e89f1eSPekka Enberg #include <linux/kernel.h> 508e89f1eSPekka Enberg #include <linux/list.h> 608e89f1eSPekka Enberg #include <stdlib.h> 77fca1897SSasha Levin #include <sys/mman.h> 848d9e01aSSasha Levin #include <errno.h> 908e89f1eSPekka Enberg 1008e89f1eSPekka Enberg static LIST_HEAD(framebuffers); 1108e89f1eSPekka Enberg fb__register(struct framebuffer * fb)1208e89f1eSPekka Enbergstruct framebuffer *fb__register(struct framebuffer *fb) 1308e89f1eSPekka Enberg { 1408e89f1eSPekka Enberg INIT_LIST_HEAD(&fb->node); 1508e89f1eSPekka Enberg list_add(&fb->node, &framebuffers); 1608e89f1eSPekka Enberg 1708e89f1eSPekka Enberg return fb; 1808e89f1eSPekka Enberg } 1908e89f1eSPekka Enberg fb__attach(struct framebuffer * fb,struct fb_target_operations * ops)2008e89f1eSPekka Enbergint fb__attach(struct framebuffer *fb, struct fb_target_operations *ops) 2108e89f1eSPekka Enberg { 2208e89f1eSPekka Enberg if (fb->nr_targets >= FB_MAX_TARGETS) 2348d9e01aSSasha Levin return -ENOSPC; 2408e89f1eSPekka Enberg 2508e89f1eSPekka Enberg fb->targets[fb->nr_targets++] = ops; 2608e89f1eSPekka Enberg 2708e89f1eSPekka Enberg return 0; 2808e89f1eSPekka Enberg } 2908e89f1eSPekka Enberg start_targets(struct framebuffer * fb)3008e89f1eSPekka Enbergstatic int start_targets(struct framebuffer *fb) 3108e89f1eSPekka Enberg { 3208e89f1eSPekka Enberg unsigned long i; 3308e89f1eSPekka Enberg 3408e89f1eSPekka Enberg for (i = 0; i < fb->nr_targets; i++) { 3508e89f1eSPekka Enberg struct fb_target_operations *ops = fb->targets[i]; 3608e89f1eSPekka Enberg int err = 0; 3708e89f1eSPekka Enberg 3808e89f1eSPekka Enberg if (ops->start) 3908e89f1eSPekka Enberg err = ops->start(fb); 4008e89f1eSPekka Enberg 4108e89f1eSPekka Enberg if (err) 4208e89f1eSPekka Enberg return err; 4308e89f1eSPekka Enberg } 4408e89f1eSPekka Enberg 4508e89f1eSPekka Enberg return 0; 4608e89f1eSPekka Enberg } 4708e89f1eSPekka Enberg fb__init(struct kvm * kvm)48ba46fe53SSasha Levinint fb__init(struct kvm *kvm) 4908e89f1eSPekka Enberg { 5008e89f1eSPekka Enberg struct framebuffer *fb; 5108e89f1eSPekka Enberg 5208e89f1eSPekka Enberg list_for_each_entry(fb, &framebuffers, node) { 5308e89f1eSPekka Enberg int err; 5408e89f1eSPekka Enberg 5508e89f1eSPekka Enberg err = start_targets(fb); 5608e89f1eSPekka Enberg if (err) 5708e89f1eSPekka Enberg return err; 5808e89f1eSPekka Enberg } 5908e89f1eSPekka Enberg 6008e89f1eSPekka Enberg return 0; 6108e89f1eSPekka Enberg } 62*49a8afd1SSasha Levin firmware_init(fb__init); 6308e89f1eSPekka Enberg fb__exit(struct kvm * kvm)64ba46fe53SSasha Levinint fb__exit(struct kvm *kvm) 6508e89f1eSPekka Enberg { 6608e89f1eSPekka Enberg struct framebuffer *fb; 6708e89f1eSPekka Enberg 6808e89f1eSPekka Enberg list_for_each_entry(fb, &framebuffers, node) { 6948d9e01aSSasha Levin u32 i; 7048d9e01aSSasha Levin 7148d9e01aSSasha Levin for (i = 0; i < fb->nr_targets; i++) 7248d9e01aSSasha Levin if (fb->targets[i]->stop) 7348d9e01aSSasha Levin fb->targets[i]->stop(fb); 7448d9e01aSSasha Levin 757fca1897SSasha Levin munmap(fb->mem, fb->mem_size); 7608e89f1eSPekka Enberg } 77ba46fe53SSasha Levin 78ba46fe53SSasha Levin return 0; 7908e89f1eSPekka Enberg } 80*49a8afd1SSasha Levin firmware_exit(fb__exit); 81