⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xen-fbfront.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return IRQ_HANDLED;}static int __devinit xenfb_probe(struct xenbus_device *dev,				 const struct xenbus_device_id *id){	struct xenfb_info *info;	struct fb_info *fb_info;	int fb_size;	int val;	int ret;	info = kzalloc(sizeof(*info), GFP_KERNEL);	if (info == NULL) {		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");		return -ENOMEM;	}	/* Limit kernel param videoram amount to what is in xenstore */	if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {		if (val < video[KPARAM_MEM])			video[KPARAM_MEM] = val;	}	/* If requested res does not fit in available memory, use default */	fb_size = video[KPARAM_MEM] * 1024 * 1024;	if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8	    > fb_size) {		video[KPARAM_WIDTH] = XENFB_WIDTH;		video[KPARAM_HEIGHT] = XENFB_HEIGHT;		fb_size = XENFB_DEFAULT_FB_LEN;	}	dev->dev.driver_data = info;	info->xbdev = dev;	info->irq = -1;	info->x1 = info->y1 = INT_MAX;	spin_lock_init(&info->dirty_lock);	spin_lock_init(&info->resize_lock);	info->fb = vmalloc(fb_size);	if (info->fb == NULL)		goto error_nomem;	memset(info->fb, 0, fb_size);	info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;	info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);	if (!info->mfns)		goto error_nomem;	/* set up shared page */	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);	if (!info->page)		goto error_nomem;	/* abusing framebuffer_alloc() to allocate pseudo_palette */	fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);	if (fb_info == NULL)		goto error_nomem;	/* complete the abuse: */	fb_info->pseudo_palette = fb_info->par;	fb_info->par = info;	fb_info->screen_base = info->fb;	fb_info->fbops = &xenfb_fb_ops;	fb_info->var.xres_virtual = fb_info->var.xres = video[KPARAM_WIDTH];	fb_info->var.yres_virtual = fb_info->var.yres = video[KPARAM_HEIGHT];	fb_info->var.bits_per_pixel = XENFB_DEPTH;	fb_info->var.red = (struct fb_bitfield){16, 8, 0};	fb_info->var.green = (struct fb_bitfield){8, 8, 0};	fb_info->var.blue = (struct fb_bitfield){0, 8, 0};	fb_info->var.activate = FB_ACTIVATE_NOW;	fb_info->var.height = -1;	fb_info->var.width = -1;	fb_info->var.vmode = FB_VMODE_NONINTERLACED;	fb_info->fix.visual = FB_VISUAL_TRUECOLOR;	fb_info->fix.line_length = fb_info->var.xres * XENFB_DEPTH / 8;	fb_info->fix.smem_start = 0;	fb_info->fix.smem_len = fb_size;	strcpy(fb_info->fix.id, "xen");	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;	fb_info->fix.accel = FB_ACCEL_NONE;	fb_info->flags = FBINFO_FLAG_DEFAULT;	ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);	if (ret < 0) {		framebuffer_release(fb_info);		xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");		goto error;	}	fb_info->fbdefio = &xenfb_defio;	fb_deferred_io_init(fb_info);	xenfb_init_shared_page(info, fb_info);	ret = register_framebuffer(fb_info);	if (ret) {		fb_deferred_io_cleanup(fb_info);		fb_dealloc_cmap(&fb_info->cmap);		framebuffer_release(fb_info);		xenbus_dev_fatal(dev, ret, "register_framebuffer");		goto error;	}	info->fb_info = fb_info;	ret = xenfb_connect_backend(dev, info);	if (ret < 0)		goto error;	xenfb_make_preferred_console();	return 0; error_nomem:	ret = -ENOMEM;	xenbus_dev_fatal(dev, ret, "allocating device memory"); error:	xenfb_remove(dev);	return ret;}static __devinit voidxenfb_make_preferred_console(void){	struct console *c;	if (console_set_on_cmdline)		return;	acquire_console_sem();	for (c = console_drivers; c; c = c->next) {		if (!strcmp(c->name, "tty") && c->index == 0)			break;	}	release_console_sem();	if (c) {		unregister_console(c);		c->flags |= CON_CONSDEV;		c->flags &= ~CON_PRINTBUFFER; /* don't print again */		register_console(c);	}}static int xenfb_resume(struct xenbus_device *dev){	struct xenfb_info *info = dev->dev.driver_data;	xenfb_disconnect_backend(info);	xenfb_init_shared_page(info, info->fb_info);	return xenfb_connect_backend(dev, info);}static int xenfb_remove(struct xenbus_device *dev){	struct xenfb_info *info = dev->dev.driver_data;	xenfb_disconnect_backend(info);	if (info->fb_info) {		fb_deferred_io_cleanup(info->fb_info);		unregister_framebuffer(info->fb_info);		fb_dealloc_cmap(&info->fb_info->cmap);		framebuffer_release(info->fb_info);	}	free_page((unsigned long)info->page);	vfree(info->mfns);	vfree(info->fb);	kfree(info);	return 0;}static unsigned long vmalloc_to_mfn(void *address){	return pfn_to_mfn(vmalloc_to_pfn(address));}static void xenfb_init_shared_page(struct xenfb_info *info,				   struct fb_info *fb_info){	int i;	int epd = PAGE_SIZE / sizeof(info->mfns[0]);	for (i = 0; i < info->nr_pages; i++)		info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);	for (i = 0; i * epd < info->nr_pages; i++)		info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]);	info->page->width = fb_info->var.xres;	info->page->height = fb_info->var.yres;	info->page->depth = fb_info->var.bits_per_pixel;	info->page->line_length = fb_info->fix.line_length;	info->page->mem_length = fb_info->fix.smem_len;	info->page->in_cons = info->page->in_prod = 0;	info->page->out_cons = info->page->out_prod = 0;}static int xenfb_connect_backend(struct xenbus_device *dev,				 struct xenfb_info *info){	int ret, evtchn;	struct xenbus_transaction xbt;	ret = xenbus_alloc_evtchn(dev, &evtchn);	if (ret)		return ret;	ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,					0, dev->devicetype, info);	if (ret < 0) {		xenbus_free_evtchn(dev, evtchn);		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");		return ret;	}	info->irq = ret; again:	ret = xenbus_transaction_start(&xbt);	if (ret) {		xenbus_dev_fatal(dev, ret, "starting transaction");		return ret;	}	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",			    virt_to_mfn(info->page));	if (ret)		goto error_xenbus;	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",			    evtchn);	if (ret)		goto error_xenbus;	ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",			    XEN_IO_PROTO_ABI_NATIVE);	if (ret)		goto error_xenbus;	ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");	if (ret)		goto error_xenbus;	ret = xenbus_transaction_end(xbt, 0);	if (ret) {		if (ret == -EAGAIN)			goto again;		xenbus_dev_fatal(dev, ret, "completing transaction");		return ret;	}	xenbus_switch_state(dev, XenbusStateInitialised);	return 0; error_xenbus:	xenbus_transaction_end(xbt, 1);	xenbus_dev_fatal(dev, ret, "writing xenstore");	return ret;}static void xenfb_disconnect_backend(struct xenfb_info *info){	if (info->irq >= 0)		unbind_from_irqhandler(info->irq, info);	info->irq = -1;}static void xenfb_backend_changed(struct xenbus_device *dev,				  enum xenbus_state backend_state){	struct xenfb_info *info = dev->dev.driver_data;	int val;	switch (backend_state) {	case XenbusStateInitialising:	case XenbusStateInitialised:	case XenbusStateUnknown:	case XenbusStateClosed:		break;	case XenbusStateInitWait:InitWait:		xenbus_switch_state(dev, XenbusStateConnected);		break;	case XenbusStateConnected:		/*		 * Work around xenbus race condition: If backend goes		 * through InitWait to Connected fast enough, we can		 * get Connected twice here.		 */		if (dev->state != XenbusStateConnected)			goto InitWait; /* no InitWait seen yet, fudge it */		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,				 "request-update", "%d", &val) < 0)			val = 0;		if (val)			info->update_wanted = 1;		if (xenbus_scanf(XBT_NIL, dev->otherend,				 "feature-resize", "%d", &val) < 0)			val = 0;		info->feature_resize = val;		break;	case XenbusStateClosing:		xenbus_frontend_closed(dev);		break;	}}static struct xenbus_device_id xenfb_ids[] = {	{ "vfb" },	{ "" }};static struct xenbus_driver xenfb_driver = {	.name = "vfb",	.owner = THIS_MODULE,	.ids = xenfb_ids,	.probe = xenfb_probe,	.remove = xenfb_remove,	.resume = xenfb_resume,	.otherend_changed = xenfb_backend_changed,};static int __init xenfb_init(void){	if (!xen_domain())		return -ENODEV;	/* Nothing to do if running in dom0. */	if (xen_initial_domain())		return -ENODEV;	return xenbus_register_frontend(&xenfb_driver);}static void __exit xenfb_cleanup(void){	xenbus_unregister_driver(&xenfb_driver);}module_init(xenfb_init);module_exit(xenfb_cleanup);MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");MODULE_LICENSE("GPL");MODULE_ALIAS("xen:vfb");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -