📄 sis_main.c
字号:
} /*karl:endif (reg != 0xB1)*/ }}static void sisfb_crtc_to_var(struct fb_var_screeninfo *var){ u16 VRE, VBE, VRS, VBS, VDE, VT; u16 HRE, HBE, HRS, HBS, HDE, HT; u8 sr_data, cr_data, cr_data2, cr_data3, mr_data; int A, B, C, D, E, F, temp; double hrate, drate; vgawb(SEQ_ADR, IND_SIS_COLOR_MODE); sr_data = vgarb(SEQ_DATA); if (sr_data & SIS_INTERLACED_MODE) var->vmode = FB_VMODE_INTERLACED; else var->vmode = FB_VMODE_NONINTERLACED; switch ((sr_data & 0x1C) >> 2) { case SIS_8BPP_COLOR_MODE: var->bits_per_pixel = 8; break; case SIS_16BPP_COLOR_MODE: var->bits_per_pixel = 16; break; case SIS_32BPP_COLOR_MODE: var->bits_per_pixel = 32; break; } switch (var->bits_per_pixel) { case 8: var->red.length = 6; var->green.length = 6; var->blue.length = 6; video_cmap_len = 256; break; case 16: var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; video_cmap_len = 16; break; case 24: var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; video_cmap_len = 16; break; case 32: var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; video_cmap_len = 16; break; } vgawb(SEQ_ADR, 0xA); sr_data = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x6); cr_data = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x7); cr_data2 = vgarb(CRTC_DATA); VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) | ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10); A = VT + 2; vgawb(CRTC_ADR, 0x12); cr_data = vgarb(CRTC_DATA); VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) | ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9); E = VDE + 1; vgawb(CRTC_ADR, 0x10); cr_data = vgarb(CRTC_DATA); VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) | ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7); F = VRS + 1 - E; vgawb(CRTC_ADR, 0x15); cr_data = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x9); cr_data3 = vgarb(CRTC_DATA); VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) | ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8); vgawb(CRTC_ADR, 0x16); cr_data = vgarb(CRTC_DATA); VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4); temp = VBE - ((E - 1) & 511); B = (temp > 0) ? temp : (temp + 512); vgawb(CRTC_ADR, 0x11); cr_data = vgarb(CRTC_DATA); VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); temp = VRE - ((E + F - 1) & 31); C = (temp > 0) ? temp : (temp + 32); D = B - F - C; var->yres = var->yres_virtual = E; /* TW: We have to report the physical dimension to the console! */ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { var->yres <<= 1; var->yres_virtual <<=1; } /* TW end */ var->upper_margin = D; var->lower_margin = F; var->vsync_len = C; vgawb(SEQ_ADR, 0xb); sr_data = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x0); cr_data = vgarb(CRTC_DATA); HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8); A = HT + 5; vgawb(CRTC_ADR, 0x1); cr_data = vgarb(CRTC_DATA); HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6); E = HDE + 1; vgawb(CRTC_ADR, 0x4); cr_data = vgarb(CRTC_DATA); HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2); F = HRS - E - 3; vgawb(CRTC_ADR, 0x2); cr_data = vgarb(CRTC_DATA); HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4); vgawb(SEQ_ADR, 0xc); sr_data = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x3); cr_data = vgarb(CRTC_DATA); vgawb(CRTC_ADR, 0x5); cr_data2 = vgarb(CRTC_DATA); HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) | ((u16) (sr_data & 0x03) << 6); HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); temp = HBE - ((E - 1) & 255); B = (temp > 0) ? temp : (temp + 256); temp = HRE - ((E + F + 3) & 63); C = (temp > 0) ? temp : (temp + 64); D = B - F - C; var->xres = var->xres_virtual = E * 8; 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 = vgarb(0x1C); 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; hrate = (double) ivideo.refresh_rate * (double) VT / 2; drate = hrate * HT; var->pixclock = (u32) (1E12 / drate);}/* ------------------ Public Routines -------------------------------- */static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, fb_info.modename); fix->smem_start = ivideo.video_base; /*karl:10/01/2001*/ /* TW */ if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) { if (ivideo.video_size > 0x800000) fix->smem_len = 0x800000; else fix->smem_len = 0x400000; } else fix->smem_len = sisfb_mem * 1024; fix->type = video_type; fix->type_aux = 0; if (ivideo.video_bpp == 8) fix->visual = FB_VISUAL_PSEUDOCOLOR; else fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = video_linelength; fix->mmio_start = ivideo.mmio_base; fix->mmio_len = sisfb_mmio_size; fix->accel = FB_ACCEL_SIS_GLAMOUR; fix->reserved[0] = ivideo.video_size & 0xFFFF; fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF; fix->reserved[2] = sisfb_caps; return 0;}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; /* JennyLee 2001126: for FSTN */ if (var->xres == 320 && var->yres == 480) var->yres = 240; /* ~JennyLee */ 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); 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; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); 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(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, video_cmap_len, 0); if (err) return err; } if (con == currcon) return fb_set_cmap(cmap, kspc, sis_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}static int sisfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){ switch (cmd) { case FBIO_ALLOC: if (!capable(CAP_SYS_RAWIO)) return -EPERM; sis_malloc((struct sis_memreq *) arg); break; case FBIO_FREE: if (!capable(CAP_SYS_RAWIO)) return -EPERM; sis_free(*(unsigned long *) arg); break; case FBIOGET_GLYPH: sis_get_glyph((SIS_GLYINFO *) arg); break; case FBIOGET_HWCINFO: { unsigned long *hwc_offset = (unsigned long *) arg; if (sisfb_caps & HW_CURSOR_CAP) *hwc_offset = sisfb_hwcursor_vbase - (unsigned long) ivideo.video_vbase; else *hwc_offset = 0; break; } case FBIOPUT_MODEINFO: { struct mode_info *x = (struct mode_info *)arg; ivideo.video_bpp = x->bpp; ivideo.video_width = x->xres; ivideo.video_height = x->yres; ivideo.video_vwidth = x->v_xres; ivideo.video_vheight = x->v_yres; ivideo.org_x = x->org_x; ivideo.org_y = x->org_y; ivideo.refresh_rate = x->vrate; break; } case FBIOGET_DISPINFO: sis_dispinfo((struct ap_data *)arg); break; default: return -EINVAL; } 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; 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 (off >= len) { off -= len; 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;#if defined(__i386__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot))#else /* TW: 2.5 API */ if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot))#endif return -EAGAIN; return 0;}static struct fb_ops sisfb_ops = { owner: THIS_MODULE, fb_get_fix: sisfb_get_fix, fb_get_var: sisfb_get_var, fb_set_var: sisfb_set_var, fb_get_cmap: sisfb_get_cmap, fb_set_cmap: sisfb_set_cmap, fb_ioctl: sisfb_ioctl, fb_mmap: sisfb_mmap,};/* ------------ Interface to the low level console driver -------------*/static int sisfb_update_var(int con, struct fb_info *info){ return 0;}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); 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; vgawb(CRTC_ADR, 0x17); reg = vgarb(CRTC_DATA); if (blank > 0) reg &= 0x7f; else reg |= 0x80; vgawb(CRTC_ADR, 0x17); vgawb(CRTC_DATA, reg);}int sisfb_setup(char *options){ char *this_opt; fb_info.fontname[0] = '\0'; ivideo.refresh_rate = 0; if (!options || !*options) return 0;#if 0 /* TW (Alex Tribble): Change for 2.5 series */ for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) {#endif while((this_opt = strsep(&options, ","))) { if (!*this_opt) continue; if (!strcmp(this_opt, "inverse")) { sisfb_inverse = 1; fb_invert_cmaps(); } else if (!strncmp(this_opt, "font:", 5)) { strcpy(fb_info.fontname, this_opt + 5); } else if (!strncmp(this_opt, "mode:", 5)) { sisfb_search_mode(this_opt + 5); } else if (!strncmp(this_opt, "vrate:", 6)) { ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0); } else if (!strncmp(this_opt, "rate:", 5)) { ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0); } else if (!strncmp(this_opt, "off", 3)) { sisfb_off = 1; } else if (!strncmp(this_opt, "crt1off", 7)) { sisfb_crt1off = 1; } else if (!strncmp(this_opt, "filter:", 7)) { filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -