📄 pm2fb.c
字号:
if (p->video & PM2F_DATA_64_ENABLE) { v.xres=v.xres<<1; v.right_margin=v.right_margin<<1; v.hsync_len=v.hsync_len<<1; v.left_margin=v.left_margin<<1; } switch (p->depth) { case 8: v.red.length=v.green.length=v.blue.length=8; v.xres=v.xres<<2; v.right_margin=v.right_margin<<2; v.hsync_len=v.hsync_len<<2; v.left_margin=v.left_margin<<2; break; case 16: v.red.offset=11; v.red.length=5; v.green.offset=5; v.green.length=6; v.blue.length=5; v.xres=v.xres<<1; v.right_margin=v.right_margin<<1; v.hsync_len=v.hsync_len<<1; v.left_margin=v.left_margin<<1; break; case 32: v.transp.offset=24; v.red.offset=16; v.green.offset=8; v.red.length=v.green.length=v.blue.length= v.transp.length=8; break; case 24: v.blue.offset=16; v.green.offset=8; v.red.length=v.green.length=v.blue.length=8; v.xres=(v.xres<<2)/3; v.right_margin=(v.right_margin<<2)/3; v.hsync_len=(v.hsync_len<<2)/3; v.left_margin=(v.left_margin<<2)/3; break; } base=from3264(p->base, p->depth, 1); v.xoffset=base%v.xres; v.yoffset=base/v.xres; v.height=v.width=-1; v.pixclock=KHZ2PICOS(p->pixclock); if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH) v.sync|=FB_SYNC_HOR_HIGH_ACT; if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH) v.sync|=FB_SYNC_VERT_HIGH_ACT; if (p->video & PM2F_LINE_DOUBLE) v.vmode=FB_VMODE_DOUBLE; *var=v; return 0;}static void set_user_mode(struct pm2fb_info* i) { if (pm2fb_options.flags & OPTF_YPAN) { int h = i->current_par.height; i->current_par.height=i->regions.fb_size/ (i->current_par.width*i->current_par.depth/8); i->current_par.height=MIN(i->current_par.height,2047); i->current_par.height=MAX(i->current_par.height,h); }}static void pm2fb_get_par(void* par, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; if (!i->current_par_valid) { set_user_mode(i); pm2fb_reset(i); set_screen(i, &i->current_par); i->current_par_valid=1; } *((struct pm2fb_par* )par)=i->current_par;}static void pm2fb_set_par(const void* par, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_par* p; p=(struct pm2fb_par* )par; if (i->current_par_valid) { i->current_par.base=p->base; if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) { WAIT_FIFO(i, 1); pm2_WR(i, PM2R_SCREEN_BASE, p->base); return; } } set_screen(i, p); i->current_par=*p; i->current_par_valid=1;#ifdef PM2FB_HW_CURSOR if (i->cursor) { pm2v_set_cursor_color(i, cursor_color_map, cursor_color_map, cursor_color_map); pm2v_set_cursor_shape(i); }#endif}static int pm2fb_getcolreg(unsigned regno, unsigned* red, unsigned* green, unsigned* blue, unsigned* transp, struct fb_info* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; if (regno<256) { *red=i->palette[regno].red<<8|i->palette[regno].red; *green=i->palette[regno].green<<8|i->palette[regno].green; *blue=i->palette[regno].blue<<8|i->palette[regno].blue; *transp=i->palette[regno].transp<<8|i->palette[regno].transp; } return regno>255;}static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; if (regno<16) { switch (i->current_par.depth) {#ifdef FBCON_HAS_CFB8 case 8: break;#endif#ifdef FBCON_HAS_CFB16 case 16: i->cmap.cmap16[regno]= ((u32 )red & 0xf800) | (((u32 )green & 0xfc00)>>5) | (((u32 )blue & 0xf800)>>11); break;#endif#ifdef FBCON_HAS_CFB24 case 24: i->cmap.cmap24[regno]= (((u32 )blue & 0xff00) << 8) | ((u32 )green & 0xff00) | (((u32 )red & 0xff00) >> 8); break;#endif#ifdef FBCON_HAS_CFB32 case 32: i->cmap.cmap32[regno]= (((u32 )transp & 0xff00) << 16) | (((u32 )red & 0xff00) << 8) | (((u32 )green & 0xff00)) | (((u32 )blue & 0xff00) >> 8); break;#endif default: DPRINTK("bad depth %u\n", i->current_par.depth); break; } } if (regno<256) { i->palette[regno].red=red >> 8; i->palette[regno].green=green >> 8; i->palette[regno].blue=blue >> 8; i->palette[regno].transp=transp >> 8; if (i->current_par.depth==8) set_color(i, regno, red>>8, green>>8, blue>>8); } return regno>255;}static void pm2fb_set_disp(const void* par, struct display* disp, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; unsigned long flags; unsigned long depth; save_flags(flags); cli(); disp->screen_base = i->regions.v_fb; switch (depth=((struct pm2fb_par* )par)->depth) {#ifdef FBCON_HAS_CFB8 case 8: disp->dispsw=&pm2_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 16: disp->dispsw=&pm2_cfb16; disp->dispsw_data=i->cmap.cmap16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: disp->dispsw=&pm2_cfb24; disp->dispsw_data=i->cmap.cmap24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: disp->dispsw=&pm2_cfb32; disp->dispsw_data=i->cmap.cmap32; break;#endif default: disp->dispsw=&fbcon_dummy; break; } restore_flags(flags);}#ifdef PM2FB_HW_CURSOR/*************************************************************************** * Hardware cursor support ***************************************************************************/ static u8 cursor_bits_lookup[16] = { 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55};static u8 cursor_mask_lookup[16] = { 0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8, 0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa};static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue){ struct pm2_cursor *c = fb->cursor; int i; for (i = 0; i < 2; i++) { c->color[3*i] = red[i]; c->color[3*i+1] = green[i]; c->color[3*i+2] = blue[i]; } WAIT_FIFO(fb, 14); pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8); for (i = 0; i < 6; i++) pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PALETTE+i, c->color[i]); pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);}static void pm2v_set_cursor_shape(struct pm2fb_info *fb){ struct pm2_cursor *c = fb->cursor; u8 m, b; int i, x, y; WAIT_FIFO(fb, 1); pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PATTERN >> 8); for (y = 0, i = 0; y < c->size.y; y++) { WAIT_FIFO(fb, 32); for (x = 0; x < c->size.x >> 3; x++) { m = c->mask[x][y]; b = c->bits[x][y]; pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, cursor_mask_lookup[m >> 4] | cursor_bits_lookup[(b & m) >> 4]); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, cursor_mask_lookup[m & 0x0f] | cursor_bits_lookup[(b & m) & 0x0f]); i+=2; } for ( ; x < 8; x++) { pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0); i+=2; } } for (; y < 64; y++) { WAIT_FIFO(fb, 32); for (x = 0; x < 8; x++) { pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0); i+=2; } } WAIT_FIFO(fb, 1); pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);}static void pm2v_set_cursor(struct pm2fb_info *fb, int on){ struct pm2_cursor *c = fb->cursor; int x = c->pos.x; if (!on) x = 4000; WAIT_FIFO(fb, 14); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_LOW, x & 0xff); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0x0f); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_LOW, c->pos.y & 0xff); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HIGH, (c->pos.y >> 8) & 0x0f); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HOT, c->hot.x & 0x3f); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HOT, c->hot.y & 0x3f); pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_MODE, 0x11);}static void pm2_cursor_timer_handler(unsigned long dev_addr){ struct pm2fb_info *fb = (struct pm2fb_info *)dev_addr; if (!fb->cursor->enable) goto out; if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) { fb->cursor->on ^= 1; pm2v_set_cursor(fb, fb->cursor->on); fb->cursor->vbl_cnt = fb->cursor->blink_rate; }out: fb->cursor->timer->expires = jiffies + (HZ / 50); add_timer(fb->cursor->timer);}static void pm2fb_cursor(struct display *p, int mode, int x, int y){ struct pm2fb_info *fb = (struct pm2fb_info *)p->fb_info; struct pm2_cursor *c = fb->cursor; if (!c) return; x *= fontwidth(p); y *= fontheight(p); if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) return; c->enable = 0; if (c->on) pm2v_set_cursor(fb, 0); c->pos.x = x; c->pos.y = y; switch (mode) { case CM_ERASE: c->on = 0; break; case CM_DRAW: case CM_MOVE: if (c->on) pm2v_set_cursor(fb, 1); else c->vbl_cnt = CURSOR_DRAW_DELAY; c->enable = 1; break; }}static struct pm2_cursor * __init pm2_init_cursor(struct pm2fb_info *fb){ struct pm2_cursor *cursor; if (fb->type != PM2_TYPE_PERMEDIA2V) return 0; /* FIXME: Support hw cursor everywhere */ cursor = kmalloc(sizeof(struct pm2_cursor), GFP_ATOMIC); if (!cursor) return 0; memset(cursor, 0, sizeof(*cursor)); cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL); if (!cursor->timer) { kfree(cursor); return 0; } memset(cursor->timer, 0, sizeof(*cursor->timer)); cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; if (curblink) { init_timer(cursor->timer); cursor->timer->expires = jiffies + (HZ / 50); cursor->timer->data = (unsigned long)fb; cursor->timer->function = pm2_cursor_timer_handler; add_timer(cursor->timer); } return cursor;}static int pm2fb_set_font(struct display *d, int width, int height){ struct pm2fb_info *fb = (struct pm2fb_info *)d->fb_info; struct pm2_cursor *c = fb->cursor; int i, j; if (c) { if (!width || !height) { width = 8; height = 16; } c->hot.x = 0; c->hot.y = 0; c->size.x = width; c->size.y = height; memset(c->bits, 0xff, sizeof(c->bits)); memset(c->mask, 0, sizeof(c->mask)); for (i = 0, j = width; j >= 0; j -= 8, i++) { c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j)); c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); } pm2v_set_cursor_color(fb, cursor_color_map, cursor_color_map, cursor_color_map); pm2v_set_cursor_shape(fb); } return 1;}#endif /* PM2FB_HW_CURSOR *//*************************************************************************** * Begin of public functions ***************************************************************************/#ifdef MODULEstatic void pm2fb_cleanup(void) { struct pm2fb_info* i = &fb_info; unregister_framebuffer((struct fb_info *)i); pm2fb_reset(i); UNMAP(i->regions.v_fb, i->regions.fb_size); release_mem_region(i->regions.p_fb, i->regions.fb_size); UNMAP(i->regions.v_regs, PM2_REGS_SIZE); release_mem_region(i->regions.p_regs, PM2_REGS_SIZE); if (board_table[i->board].cleanup) board_table[i->board].cleanup(i);}#endif /* MODULE */int __init pm2fb_init(void){ MOD_INC_USE_COUNT; memset(&fb_info, 0, sizeof(fb_info)); memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par)); if (!pm2fb_conf(&fb_info)) { MOD_DEC_USE_COUNT; return -ENXIO; } pm2fb_reset(&fb_info); fb_info.disp.scrollmode=SCROLL_YNOMOVE; fb_info.gen.parsize=sizeof(struct pm2fb_par); fb_info.gen.fbhw=&pm2fb_hwswitch; strcpy(fb_info.gen.info.modename, permedia2_name); fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT; fb_info.gen.info.fbops=&pm2fb_ops; fb_info.gen.info.disp=&fb_info.disp; strcpy(fb_info.gen.info.fontname, pm2fb_options.font); fb_info.gen.info.switch_con=&fbgen_switch; fb_info.gen.info.updatevar=&fbgen_update_var; fb_info.gen.info.blank=&fbgen_blank; fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info); fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen); fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info)<0) { printk(KERN_ERR "pm2fb: unable to register.\n"); MOD_DEC_USE_COUNT; return -EINVAL; } printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n", GET_FB_IDX(fb_info.gen.info.node), board_table[fb_info.board].name, permedia2_name, (u32 )(fb_info.regions.fb_size>>10)); return 0;}static void __init pm2fb_mode_setup(char* options){ int i; for (i=0; user_mode[i].name[0] && strcmp(options, user_mode[i].name); i++); if (user_mode[i].name[0]) { memcpy(&pm2fb_options.user_mode, &user_mode[i].par, sizeof(pm2fb_options.user_mode)); pm2fb_options.flags |= OPTF_USER; }}static void __init pm2fb_font_setup(char* options){ strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font)); pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';}int __init pm2fb_setup(char* options){ char* next; while (options) { if ((next=strchr(options, ','))) *(next++)='\0'; if (!strncmp(options, "font:", 5)) pm2fb_font_setup(options+5); else if (!strncmp(options, "mode:", 5)) pm2fb_mode_setup(options+5); else if (!strcmp(options, "ypan")) pm2fb_options.flags |= OPTF_YPAN; else if (!strcmp(options, "oldmem")) pm2fb_options.flags |= OPTF_OLD_MEM; else if (!strcmp(options, "virtual")) pm2fb_options.flags |= OPTF_VIRTUAL; else if (!strcmp(options, "noblink")) curblink = 0; options=next; } return 0;}/*************************************************************************** * Begin of module functions ***************************************************************************/#ifdef MODULEMODULE_LICENSE("GPL");static char *mode = NULL;MODULE_PARM(mode, "s");int __init init_module(void) { if (mode) pm2fb_mode_setup(mode); return pm2fb_init();}void cleanup_module(void) { pm2fb_cleanup();}#endif /* MODULE *//*************************************************************************** * That's all folks! ***************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -