📄 vfb.c
字号:
oldxres = display->var.xres; oldyres = display->var.yres; oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; display->var = *var; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel) { struct fb_fix_screeninfo fix; mambolfb_encode_fix(&fix, var); display->screen_base = (char *)videomemory; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->can_soft_blank = 0; display->inverse = 0; display->scrollmode = SCROLL_YREDRAW; // bovine: imagine what it does on RAM switch (var->bits_per_pixel) {#ifdef FBCON_HAS_MFB case 1: display->dispsw = &fbcon_mfb; break;#endif#ifdef FBCON_HAS_CFB2 case 2: display->dispsw = &fbcon_cfb2; break;#endif#ifdef FBCON_HAS_CFB4 case 4: display->dispsw = &fbcon_cfb4; break;#endif#ifdef FBCON_HAS_CFB8 case 8: display->dispsw = &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; display->dispsw_data = fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: display->dispsw = &fbcon_cfb24; display->dispsw_data = fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: display->dispsw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break;#endif default: display->dispsw = &fbcon_dummy; break; } if (fb_info.changevar) (*fb_info.changevar)(con); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; do_install_cmap(con, info); } } return 0;}/* * Pan or Wrap the Display (same on 84XX and mambolfb) * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int mambolfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info){ CHECK_BOUND(); if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual || var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual) return -EINVAL; } fb_display[con].var.xoffset = var->xoffset; fb_display[con].var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) fb_display[con].var.vmode |= FB_VMODE_YWRAP; else fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; return 0;}/* * Get the Colormap */static int mambolfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ CHECK_BOUND(); if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, mambolfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0;}/* * Set the Colormap */static int mambolfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; CHECK_BOUND(); if (!fb_display[con].cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0))) return err; } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, kspc, mambolfb_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}/* almost same on 84XX */static int mambolfbcon_switch(int con, struct fb_info *info){ /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, mambolfb_getcolreg, info); currcon = con; /* Install new colormap */ do_install_cmap(con, info); return 0;}/* * Update the `var' structure (called by fbcon.c) */static int mambolfbcon_updatevar(int con, struct fb_info *info){ /* Nothing */ return 0;}/* * Blank the display. */static void mambolfbcon_blank(int blank, struct fb_info *info){ /* Nothing */}/** * Unlock PCI regions locked to map the frame buffer, if any * @return < 0 on error */static int unlock_current_mambolfb(void){ int status = 0,i; if (bound){ for (i=0;i<osd.region_count; i++){ if (RMFAILED(gbus_unlock_region(p_gbus, osd.region_index+i))) status = -EINVAL; } } return status;}/** * Lock and map a memory space as the new frame buffer * @return < 0 on error */static int lock_map_mambolfb(void){ int status; memset((void *)&osd,0,sizeof(struct osd_descriptor)); /* Lock the regions we need */ status = gbus_lock_area(p_gbus, &osd.region_index, videomemory, videomemorysize, &osd.region_count, &osd.offset); if (RMFAILED(status)){ printk("Error locking PCI chunks\n"); return -EINVAL; } DEB(printk("locked %ld regions, starting from region %ld at offset 0x%08lx\n", osd.region_count, osd.region_index, osd.offset)); /* Update video address to the mapped OSD buffer */ videomemory = (u_long) gbus_map_region(p_gbus, osd.region_index, osd.region_count); if (videomemory == (u_long) NULL){ printk("Error mapping OSD buffer in kernel space\n"); status = gbus_unlock_region(p_gbus, osd.region_index); if (RMFAILED(status)) printk("Error unlocking regions\n"); return -EINVAL; } videomemory += osd.offset; DEB(printk("OSD videomemory=0x%lx (%ld bytes)\n",videomemory,videomemorysize)); return 0;} /** * Handle specific IOCTL * @param inode - inode of the underlying device * @param file - file of the underlying device * @param cmd - command * @param arg - pointer to the argument * @param con - tty or visible console attached to this fb * @param info - the frame buffer descriptor * @return < 0 on error * */static int mambolfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){ struct mambolfb_config_s config; switch(cmd){ case MAMBOLFBIO_SETBUFFER: if (copy_from_user(&config, (void *)arg, sizeof(config))) return -EFAULT; /* Cleanup the previous buffer if any */ if (unlock_current_mambolfb() < 0) /* Go on if it fails */ printk(KERN_INFO "Error unlocking Mambo/Tango frame buffer.\n"); /* Setup the frame buffer with the new config */ mambolfb_default.xres = config.xres; mambolfb_default.yres = config.yres; mambolfb_default.xres_virtual = config.xres; mambolfb_default.yres_virtual = config.yres; mambolfb_default.bits_per_pixel = config.bits_per_pixel; mambolfb_default.activate = FB_ACTIVATE_NOW; videomemory = config.videomemory; videomemorysize = config.videomemorysize; palette = config.palette; if (mambolfb_default.xres == 0 || mambolfb_default.yres == 0 || mambolfb_default.bits_per_pixel == 0 || videomemory == 0 || videomemorysize == 0 || palette == 0){ bound = 0; printk(KERN_INFO "Mambo/Tango frame buffer unbound.\n"); return 0; } bound = 1; if (lock_map_mambolfb() < 0){ printk(KERN_INFO "Error locking new Mambo/Tango frame buffer.\n"); return -EFAULT; } if (mambolfb_set_var(&mambolfb_default, -1, &fb_info) < 0){ printk(KERN_INFO "Error setting new var.\n"); return -EFAULT; } printk(KERN_INFO "fb%d: Mambo/Tango frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), videomemorysize>>10); return 0; case MAMBOLFBIO_GETBUFFER: /* TODO implement this one too */ return -ENOSYS; default: printk(KERN_INFO "%s : unkown command 0x%x\n", __func__, cmd); return -EFAULT; } return -EINVAL;}static struct fb_ops mambolfb_ops = { owner: THIS_MODULE, fb_get_fix: mambolfb_get_fix, fb_get_var: mambolfb_get_var, fb_set_var: mambolfb_set_var, fb_get_cmap: mambolfb_get_cmap, fb_set_cmap: mambolfb_set_cmap, fb_pan_display: mambolfb_pan_display, fb_mmap: mambolfb_mmap, fb_ioctl: mambolfb_ioctl};/* * Initialisation */static int __init mambolfb_init(void){ memset((void *)&fb_info,0,sizeof(struct fb_info)); memset((void *)&disp,0,sizeof(struct display)); strcpy(fb_info.modename, mambolfb_name); fb_info.changevar = NULL; fb_info.node = -1; fb_info.fbops = &mambolfb_ops; fb_info.disp = &disp; fb_info.switch_con = &mambolfbcon_switch; fb_info.updatevar = &mambolfbcon_updatevar; fb_info.blank = &mambolfbcon_blank; fb_info.flags = FBINFO_FLAG_DEFAULT; strcpy(fb_info.fontname,"Acorn8x8"); if (bound && mambolfb_set_var(&mambolfb_default, -1, &fb_info)) return -EINVAL; DEB(printk("registering fb\n")); if (register_framebuffer(&fb_info) < 0) { return -EINVAL; } if (bound) printk(KERN_INFO "fb%d: Mambo/Tango frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), videomemorysize>>10); else printk(KERN_INFO "fb%d: Mambo/Tango frame buffer device, not bound to any physical buffer yet\n", GET_FB_IDX(fb_info.node)); return 0;}static int __init parse(char *video_mode){ char *token; token = strsep(&video_mode, ":"); if (!token || !video_mode) return 0; mambolfb_default.xres = simple_strtoul(token,&token,0); mambolfb_default.xres_virtual = mambolfb_default.xres; token = strsep(&video_mode, ":"); if (!token || !video_mode) return 0; mambolfb_default.yres = simple_strtoul(token,&token,0); mambolfb_default.yres_virtual = mambolfb_default.yres; mambolfb_default.bits_per_pixel = simple_strtoul(video_mode,&video_mode,0); return 1;}static int __init init_mambolfb(void){ if (videomemory && videomemorysize && palette) /* We have a physical buffer */ bound=1; else /* No buffer given yet */ bound=0; if (mode){ DEB(printk("mode = %s\n",mode)); if (parse(mode) == 0){ return -EINVAL; } DEB(printk("mode = %ldx%ld %ld bpp\n", mambolfb_default.xres, mambolfb_default.yres, mambolfb_default.bits_per_pixel)); } /* TODO add chip number as a parameter */ p_llad = llad_open("0"); if (p_llad == NULL){ printk("Error, cannot open llad 0\n"); return -EINVAL; } p_gbus = gbus_open(p_llad); if (p_gbus == NULL){ llad_close(p_llad); printk("Error, cannot open gbus 0\n"); return -EINVAL; } if (bound && (lock_map_mambolfb() < 0)) return -EINVAL; return mambolfb_init();}static void __exit cleanup_mambolfb(void){ unregister_framebuffer(&fb_info); if (unlock_current_mambolfb() < 0) /* Go on if it fails */ printk(KERN_INFO "Error unlocking Mambo/Tango frame buffer.\n"); gbus_close(p_gbus); llad_close(p_llad);}module_init(init_mambolfb);module_exit(cleanup_mambolfb);/* vim:set shiftwidth=8 tabstop=8 noexpandtab: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -