📄 sis_main.c
字号:
/* Terrible hack, but the correct CRTC data for * these modes only produces a black screen... */ var->left_margin = (400 - 376); var->right_margin = (328 - 320); var->hsync_len = (376 - 328); } else { var->left_margin = D * 8; var->right_margin = F * 8; var->hsync_len = C * 8; } var->activate = FB_ACTIVATE_NOW; var->sync = 0; mr_data = inSISREG(SISMISCR); if (mr_data & 0x80) var->sync &= ~FB_SYNC_VERT_HIGH_ACT; else var->sync |= FB_SYNC_VERT_HIGH_ACT; if (mr_data & 0x40) var->sync &= ~FB_SYNC_HOR_HIGH_ACT; else var->sync |= FB_SYNC_HOR_HIGH_ACT; VT += 2; VT <<= 1; HT = (HT + 5) * 8; if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { VT <<= 1; } hrate = (double) ivideo.refresh_rate * (double) VT / 2; drate = hrate * HT; var->pixclock = (u32) (1E12 / drate); if(sisfb_ypan) { var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3)); if(var->yres_virtual <= var->yres) { var->yres_virtual = var->yres; } } else var->yres_virtual = var->yres;}static int sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *fb_info){ if (regno >= ivideo.video_cmap_len) return 1; *red = sis_palette[regno].red; *green = sis_palette[regno].green; *blue = sis_palette[regno].blue; *transp = 0; return 0;}static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info){ if (regno >= ivideo.video_cmap_len) return 1; sis_palette[regno].red = red; sis_palette[regno].green = green; sis_palette[regno].blue = blue; switch (ivideo.video_bpp) {#ifdef FBCON_HAS_CFB8 case 8: outSISREG(SISDACA, regno); outSISREG(SISDACD, (red >> 10)); outSISREG(SISDACD, (green >> 10)); outSISREG(SISDACD, (blue >> 10)); if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) { outSISREG(SISDAC2A, regno); outSISREG(SISDAC2D, (red >> 8)); outSISREG(SISDAC2D, (green >> 8)); outSISREG(SISDAC2D, (blue >> 8)); } break;#endif#ifdef FBCON_HAS_CFB16 case 16: sis_fbcon_cmap.cfb16[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break;#endif#ifdef FBCON_HAS_CFB32 case 32: red >>= 8; green >>= 8; blue >>= 8; sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); break;#endif } return 0;}static void sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info){ struct fb_fix_screeninfo fix; long flags; struct display *display; struct display_switch *sw; if(con >= 0) display = &fb_display[con]; else display = &sis_disp; sisfb_get_fix(&fix, con, 0); display->screen_base = ivideo.video_vbase; 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->next_line = fix.line_length; display->can_soft_blank = 0; display->inverse = sisfb_inverse; display->var = *var; save_flags(flags); switch (ivideo.video_bpp) {#ifdef FBCON_HAS_CFB8 case 8:#ifdef SISFBACCEL sw = ivideo.accel ? &fbcon_sis8 : &fbcon_cfb8;#else sw = &fbcon_cfb8;#endif break;#endif#ifdef FBCON_HAS_CFB16 case 16:#ifdef SISFBACCEL sw = ivideo.accel ? &fbcon_sis16 : &fbcon_cfb16;#else sw = &fbcon_cfb16;#endif display->dispsw_data = sis_fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB32 case 32:#ifdef SISFBACCEL sw = ivideo.accel ? &fbcon_sis32 : &fbcon_cfb32;#else sw = &fbcon_cfb32;#endif display->dispsw_data = sis_fbcon_cmap.cfb32; break;#endif default: sw = &fbcon_dummy; return; } memcpy(&sisfb_sw, sw, sizeof(*sw)); display->dispsw = &sisfb_sw; restore_flags(flags); if(sisfb_ypan) { /* display->scrollmode = 0; */ } else { display->scrollmode = SCROLL_YREDRAW; sisfb_sw.bmove = fbcon_redraw_bmove; }}static void sisfb_do_install_cmap(int con, struct fb_info *info){ if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info); else fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1, sisfb_setcolreg, info);}static int sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ if(con == -1) memcpy(var, &default_var, sizeof(struct fb_var_screeninfo)); else *var = fb_display[con].var; /* For FSTN, DSTN */ if (var->xres == 320 && var->yres == 480) var->yres = 240; return 0;}static int sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ int err; unsigned int cols, rows; fb_display[con].var.activate = FB_ACTIVATE_NOW; if(sisfb_do_set_var(var, con == currcon, info)) { sisfb_crtc_to_var(var); return -EINVAL; } sisfb_crtc_to_var(var); sisfb_set_disp(con, var, info); if(info->changevar) (*info->changevar) (con); if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) return err; sisfb_do_install_cmap(con, info); cols = sisbios_mode[sisfb_mode_idx].cols; rows = sisbios_mode[sisfb_mode_idx].rows;#if 0 /* Why was this called here? */ vc_resize_con(rows, cols, fb_display[con].conp->vc_num); #endif return 0;}static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (con == currcon) return fb_get_cmap(cmap, kspc, sis_getcolreg, info); else if (fb_display[con].cmap.len) fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2); return 0;}static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0); if (err) return err; } if (con == currcon) return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}static int sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info){ int err; 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; } if(con == currcon) { if((err = sisfb_pan_var(var)) < 0) return err; } 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;}static int sisfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma){ struct fb_var_screeninfo var; unsigned long start; unsigned long off; u32 len, mmio_off; if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL; off = vma->vm_pgoff << PAGE_SHIFT; start = (unsigned long) ivideo.video_base; len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);#if 0 if (off >= len) { off -= len;#endif /* By Jake Page: Treat mmap request with offset beyond heapstart * as request for mapping the mmio area */ mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart); if(off >= mmio_off) { off -= mmio_off; sisfb_get_var(&var, currcon, info); if(var.accel_flags) return -EINVAL; start = (unsigned long) ivideo.mmio_base; len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size); } start &= PAGE_MASK; if((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; off += start; vma->vm_pgoff = off >> PAGE_SHIFT; vma->vm_flags |= VM_IO; /* by Jake Page; is that really needed? */#if defined(__i386__) || defined(__x86_64__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;#endif if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0;}static void sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly){ struct display *p = &fb_display[currcon]; u16 c; u8 *cdat; int widthb; u8 *gbuf = gly->gmask; int size; gly->fontheight = fontheight(p); gly->fontwidth = fontwidth(p); widthb = (fontwidth(p) + 7) / 8; c = gly->ch & p->charmask; if (fontwidth(p) <= 8) cdat = p->fontdata + c * fontheight(p); else cdat = p->fontdata + (c * fontheight(p) << 1); size = fontheight(p) * widthb; memcpy(gbuf, cdat, size); gly->ngmask = size;}static int sisfb_update_var(int con, struct fb_info *info){ return(sisfb_pan_var(&fb_display[con].var));}static int sisfb_switch(int con, struct fb_info *info){ int cols, rows; if(fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info); fb_display[con].var.activate = FB_ACTIVATE_NOW; if(!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo))) { currcon = con; return 1; } currcon = con; sisfb_do_set_var(&fb_display[con].var, 1, info); sisfb_set_disp(con, &fb_display[con].var, info); sisfb_do_install_cmap(con, info); cols = sisbios_mode[sisfb_mode_idx].cols; rows = sisbios_mode[sisfb_mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); sisfb_update_var(con, info); return 1;}static void sisfb_blank(int blank, struct fb_info *info){ u8 reg; if(sisfb_bridgeisslave()) return; inSISIDXREG(SISCR, 0x17, reg); if(blank > 0) reg &= 0x7f; else reg |= 0x80; outSISIDXREG(SISCR, 0x17, reg); outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */}#endif/* ------------ FBDev related routines for 2.5 series ----------- */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static int sisfb_open(struct fb_info *info, int user){ return 0;}static int sisfb_release(struct fb_info *info, int user){ return 0;}static int sisfb_get_cmap_len(const struct fb_var_screeninfo *var){ int rc = 16; switch(var->bits_per_pixel) { case 8: rc = 256; break; case 16: rc = 16; break; case 32: rc = 16; break; } return rc;}static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ if (regno >= sisfb_get_cmap_len(&info->var)) return 1; switch (info->var.bits_per_pixel) { case 8: outSISREG(SISDACA, regno); outSISREG(SISDACD, (red >> 10)); outSISREG(SISDACD, (green >> 10)); outSISREG(SISDACD, (blue >> 10)); if (ivideo.currentvbflags & VB_DISPTYPE_DISP2) { outSISREG(SISDAC2A, regno); outSISREG(SISDAC2D, (red >> 8)); outSISREG(SISDAC2D, (green >> 8)); outSISREG(SISDAC2D, (blue >> 8)); } break; case 16: ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 32: red >>= 8; green >>= 8; blue >>= 8; ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green << 8) | (blue); break; } return 0;}static int sisfb_set_par(struct fb_info *info){ int err; if((err = sisfb_do_set_var(&info->var, 1, info))) return err; sisfb_get_fix(&info->fix, info->currcon, info); return 0;}static int sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -