📄 uvesafb.c
字号:
static void __devinit uvesafb_init_mtrr(struct fb_info *info){#ifdef CONFIG_MTRR if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) { int temp_size = info->fix.smem_len; unsigned int type = 0; switch (mtrr) { case 1: type = MTRR_TYPE_UNCACHABLE; break; case 2: type = MTRR_TYPE_WRBACK; break; case 3: type = MTRR_TYPE_WRCOMB; break; case 4: type = MTRR_TYPE_WRTHROUGH; break; default: type = 0; break; } if (type) { int rc; /* Find the largest power-of-two */ while (temp_size & (temp_size - 1)) temp_size &= (temp_size - 1); /* Try and find a power of two to add */ do { rc = mtrr_add(info->fix.smem_start, temp_size, type, 1); temp_size >>= 1; } while (temp_size >= PAGE_SIZE && rc == -EINVAL); } }#endif /* CONFIG_MTRR */}static ssize_t uvesafb_show_vbe_ver(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);}static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);static ssize_t uvesafb_show_vbe_modes(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; int ret = 0, i; for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) { ret += snprintf(buf + ret, PAGE_SIZE - ret, "%dx%d-%d, 0x%.4x\n", par->vbe_modes[i].x_res, par->vbe_modes[i].y_res, par->vbe_modes[i].depth, par->vbe_modes[i].mode_id); } return ret;}static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);static ssize_t uvesafb_show_vendor(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; if (par->vbe_ib.oem_vendor_name_ptr) return snprintf(buf, PAGE_SIZE, "%s\n", (char *) (&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr); else return 0;}static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);static ssize_t uvesafb_show_product_name(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; if (par->vbe_ib.oem_product_name_ptr) return snprintf(buf, PAGE_SIZE, "%s\n", (char *) (&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr); else return 0;}static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);static ssize_t uvesafb_show_product_rev(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; if (par->vbe_ib.oem_product_rev_ptr) return snprintf(buf, PAGE_SIZE, "%s\n", (char *) (&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr); else return 0;}static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);static ssize_t uvesafb_show_oem_string(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; if (par->vbe_ib.oem_string_ptr) return snprintf(buf, PAGE_SIZE, "%s\n", (char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr); else return 0;}static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);static ssize_t uvesafb_show_nocrtc(struct device *dev, struct device_attribute *attr, char *buf){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);}static ssize_t uvesafb_store_nocrtc(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct fb_info *info = platform_get_drvdata(to_platform_device(dev)); struct uvesafb_par *par = info->par; if (count > 0) { if (buf[0] == '0') par->nocrtc = 0; else par->nocrtc = 1; } return count;}static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc, uvesafb_store_nocrtc);static struct attribute *uvesafb_dev_attrs[] = { &dev_attr_vbe_version.attr, &dev_attr_vbe_modes.attr, &dev_attr_oem_vendor.attr, &dev_attr_oem_product_name.attr, &dev_attr_oem_product_rev.attr, &dev_attr_oem_string.attr, &dev_attr_nocrtc.attr, NULL,};static struct attribute_group uvesafb_dev_attgrp = { .name = NULL, .attrs = uvesafb_dev_attrs,};static int __devinit uvesafb_probe(struct platform_device *dev){ struct fb_info *info; struct vbe_mode_ib *mode = NULL; struct uvesafb_par *par; int err = 0, i; info = framebuffer_alloc(sizeof(*par) + sizeof(u32) * 256, &dev->dev); if (!info) return -ENOMEM; par = info->par; err = uvesafb_vbe_init(info); if (err) { printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err); goto out; } info->fbops = &uvesafb_ops; i = uvesafb_vbe_init_mode(info); if (i < 0) { err = -EINVAL; goto out; } else { mode = &par->vbe_modes[i]; } if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { err = -ENXIO; goto out; } uvesafb_init_info(info, mode); if (!request_mem_region(info->fix.smem_start, info->fix.smem_len, "uvesafb")) { printk(KERN_ERR "uvesafb: cannot reserve video memory at " "0x%lx\n", info->fix.smem_start); err = -EIO; goto out_mode; } info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { printk(KERN_ERR "uvesafb: abort, cannot ioremap 0x%x bytes of video " "memory at 0x%lx\n", info->fix.smem_len, info->fix.smem_start); err = -EIO; goto out_mem; } if (!request_region(0x3c0, 32, "uvesafb")) { printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n"); err = -EIO; goto out_unmap; } uvesafb_init_mtrr(info); platform_set_drvdata(dev, info); if (register_framebuffer(info) < 0) { printk(KERN_ERR "uvesafb: failed to register framebuffer device\n"); err = -EINVAL; goto out_reg; } printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, " "using %dk, total %dk\n", info->fix.smem_start, info->screen_base, info->fix.smem_len/1024, par->vbe_ib.total_memory * 64); printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp); if (err != 0) printk(KERN_WARNING "fb%d: failed to register attributes\n", info->node); return 0;out_reg: release_region(0x3c0, 32);out_unmap: iounmap(info->screen_base);out_mem: release_mem_region(info->fix.smem_start, info->fix.smem_len);out_mode: if (!list_empty(&info->modelist)) fb_destroy_modelist(&info->modelist); fb_destroy_modedb(info->monspecs.modedb); fb_dealloc_cmap(&info->cmap);out: if (par->vbe_modes) kfree(par->vbe_modes); framebuffer_release(info); return err;}static int uvesafb_remove(struct platform_device *dev){ struct fb_info *info = platform_get_drvdata(dev); if (info) { struct uvesafb_par *par = info->par; sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp); unregister_framebuffer(info); release_region(0x3c0, 32); iounmap(info->screen_base); release_mem_region(info->fix.smem_start, info->fix.smem_len); fb_destroy_modedb(info->monspecs.modedb); fb_dealloc_cmap(&info->cmap); if (par) { if (par->vbe_modes) kfree(par->vbe_modes); if (par->vbe_state_orig) kfree(par->vbe_state_orig); if (par->vbe_state_saved) kfree(par->vbe_state_saved); } framebuffer_release(info); } return 0;}static struct platform_driver uvesafb_driver = { .probe = uvesafb_probe, .remove = uvesafb_remove, .driver = { .name = "uvesafb", },};static struct platform_device *uvesafb_device;#ifndef MODULEstatic int __devinit uvesafb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; if (!strcmp(this_opt, "redraw")) ypan = 0; else if (!strcmp(this_opt, "ypan")) ypan = 1; else if (!strcmp(this_opt, "ywrap")) ypan = 2; else if (!strcmp(this_opt, "vgapal")) pmi_setpal = 0; else if (!strcmp(this_opt, "pmipal")) pmi_setpal = 1; else if (!strncmp(this_opt, "mtrr:", 5)) mtrr = simple_strtoul(this_opt+5, NULL, 0); else if (!strcmp(this_opt, "nomtrr")) mtrr = 0; else if (!strcmp(this_opt, "nocrtc")) nocrtc = 1; else if (!strcmp(this_opt, "noedid")) noedid = 1; else if (!strcmp(this_opt, "noblank")) blank = 0; else if (!strncmp(this_opt, "vtotal:", 7)) vram_total = simple_strtoul(this_opt + 7, NULL, 0); else if (!strncmp(this_opt, "vremap:", 7)) vram_remap = simple_strtoul(this_opt + 7, NULL, 0); else if (!strncmp(this_opt, "maxhf:", 6)) maxhf = simple_strtoul(this_opt + 6, NULL, 0); else if (!strncmp(this_opt, "maxvf:", 6)) maxvf = simple_strtoul(this_opt + 6, NULL, 0); else if (!strncmp(this_opt, "maxclk:", 7)) maxclk = simple_strtoul(this_opt + 7, NULL, 0); else if (!strncmp(this_opt, "vbemode:", 8)) vbemode = simple_strtoul(this_opt + 8, NULL, 0); else if (this_opt[0] >= '0' && this_opt[0] <= '9') { mode_option = this_opt; } else { printk(KERN_WARNING "uvesafb: unrecognized option %s\n", this_opt); } } return 0;}#endif /* !MODULE */static ssize_t show_v86d(struct device_driver *dev, char *buf){ return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);}static ssize_t store_v86d(struct device_driver *dev, const char *buf, size_t count){ strncpy(v86d_path, buf, PATH_MAX); return count;}static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);static int __devinit uvesafb_init(void){ int err;#ifndef MODULE char *option = NULL; if (fb_get_options("uvesafb", &option)) return -ENODEV; uvesafb_setup(option);#endif err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback); if (err) return err; err = platform_driver_register(&uvesafb_driver); if (!err) { uvesafb_device = platform_device_alloc("uvesafb", 0); if (uvesafb_device) err = platform_device_add(uvesafb_device); else err = -ENOMEM; if (err) { platform_device_put(uvesafb_device); platform_driver_unregister(&uvesafb_driver); cn_del_callback(&uvesafb_cn_id); return err; } err = driver_create_file(&uvesafb_driver.driver, &driver_attr_v86d); if (err) { printk(KERN_WARNING "uvesafb: failed to register " "attributes\n"); err = 0; } } return err;}module_init(uvesafb_init);static void __devexit uvesafb_exit(void){ struct uvesafb_ktask *task; if (v86d_started) { task = uvesafb_prep(); if (task) { task->t.flags = TF_EXIT; uvesafb_exec(task); uvesafb_free(task); } } cn_del_callback(&uvesafb_cn_id); driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d); platform_device_unregister(uvesafb_device); platform_driver_unregister(&uvesafb_driver);}module_exit(uvesafb_exit);static int param_get_scroll(char *buffer, struct kernel_param *kp){ return 0;}static int param_set_scroll(const char *val, struct kernel_param *kp){ ypan = 0; if (!strcmp(val, "redraw")) ypan = 0; else if (!strcmp(val, "ypan")) ypan = 1; else if (!strcmp(val, "ywrap")) ypan = 2; return 0;}#define param_check_scroll(name, p) __param_check(name, p, void)module_param_named(scroll, ypan, scroll, 0);MODULE_PARM_DESC(scroll, "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'");module_param_named(vgapal, pmi_setpal, invbool, 0);MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");module_param_named(pmipal, pmi_setpal, bool, 0);MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");module_param(mtrr, uint, 0);MODULE_PARM_DESC(mtrr, "Memory Type Range Registers setting. Use 0 to disable.");module_param(blank, bool, 0);MODULE_PARM_DESC(blank, "Enable hardware blanking");module_param(nocrtc, bool, 0);MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");module_param(noedid, bool, 0);MODULE_PARM_DESC(noedid, "Ignore EDID-provided monitor limits when setting modes");module_param(vram_remap, uint, 0);MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");module_param(vram_total, uint, 0);MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");module_param(maxclk, ushort, 0);MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");module_param(maxhf, ushort, 0);MODULE_PARM_DESC(maxhf, "Maximum horizontal frequency [kHz], overrides EDID data");module_param(maxvf, ushort, 0);MODULE_PARM_DESC(maxvf, "Maximum vertical frequency [Hz], overrides EDID data");module_param(mode_option, charp, 0);MODULE_PARM_DESC(mode_option, "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");module_param(vbemode, ushort, 0);MODULE_PARM_DESC(vbemode, "VBE mode number to set, overrides the 'mode' option");module_param_string(v86d, v86d_path, PATH_MAX, 0660);MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");MODULE_LICENSE("GPL");MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -