📄 matroxfb_base.c
字号:
hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); hw->CRTCEXT[8] = pos >> 21; if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw); } if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt, hw); up_read(&ACCESS_FBINFO(altout.lock)); } ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display)); if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->program(MINFO, hw); } if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device), hw); up_read(&ACCESS_FBINFO(altout.lock)); } ACCESS_FBINFO(cursor.redraw) = 1; ACCESS_FBINFO(currenthw) = hw; ACCESS_FBINFO(newhw) = ohw; if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->start(MINFO); } if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } matrox_cfbX_init(PMINFO display); do_install_cmap(PMINFO display);#if defined(CONFIG_FB_COMPAT_XPMAC) if (console_fb_info == &ACCESS_FBINFO(fbcon)) { int vmode, cmode; display_info.width = var->xres; display_info.height = var->yres; display_info.depth = var->bits_per_pixel; display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8; if (mac_var_to_vmode(var, &vmode, &cmode)) display_info.mode = 0; else display_info.mode = vmode; strcpy(display_info.name, ACCESS_FBINFO(matrox_name)); display_info.fb_address = ACCESS_FBINFO(video.base); display_info.cmap_adr_address = 0; display_info.cmap_data_address = 0; display_info.disp_reg_address = ACCESS_FBINFO(mmio.base); }#endif /* CONFIG_FB_COMPAT_XPMAC */ } } return 0;#undef minfo}static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){ DBG("matrox_getcolreg")#define minfo ((struct matrox_fb_info*)info) /* * Read a single color register and split it into colors/transparent. * Return != 0 for invalid regno. */ if (regno >= ACCESS_FBINFO(curr.cmap_len)) return 1; *red = ACCESS_FBINFO(palette[regno].red); *green = ACCESS_FBINFO(palette[regno].green); *blue = ACCESS_FBINFO(palette[regno].blue); *transp = ACCESS_FBINFO(palette[regno].transp); return 0;#undef minfo}static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) struct display* dsp = (con < 0) ? ACCESS_FBINFO(fbcon.disp) : fb_display + con; DBG("matroxfb_get_cmap") if (ACCESS_FBINFO(dead)) { return -ENXIO; } if (con == ACCESS_FBINFO(currcon)) /* current console? */ return fb_get_cmap(cmap, kspc, matrox_getcolreg, info); else if (dsp->cmap.len) /* non default colormap? */ fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp->var)), cmap, kspc ? 0 : 2); return 0;#undef minfo}static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ unsigned int cmap_len; struct display* dsp = (con < 0) ? info->disp : (fb_display + con);#define minfo ((struct matrox_fb_info*)info) DBG("matroxfb_set_cmap") if (ACCESS_FBINFO(dead)) { return -ENXIO; } cmap_len = matroxfb_get_cmap_len(&dsp->var); if (dsp->cmap.len != cmap_len) { int err; err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0); if (err) return err; } if (con == ACCESS_FBINFO(currcon)) { /* current console? */ return fb_set_cmap(cmap, kspc, matrox_setcolreg, info); } else fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1); return 0;#undef minfo}static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank){ unsigned int sts1; memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC | FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK; sts1 = mga_inb(M_INSTS1); vblank->vcount = mga_inl(M_VCOUNT); /* BTW, on my PIII/450 with G400, reading M_INSTS1 byte makes this call about 12% slower (1.70 vs. 2.05 us per ioctl()) */ if (sts1 & 1) vblank->flags |= FB_VBLANK_HBLANKING; if (sts1 & 8) vblank->flags |= FB_VBLANK_VSYNCING; if (vblank->count >= ACCESS_FBINFO(currcon_display)->var.yres) vblank->flags |= FB_VBLANK_VBLANKING; vblank->hcount = 0; vblank->count = 0; return 0;}static int matroxfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) DBG("matroxfb_ioctl") if (ACCESS_FBINFO(dead)) { return -ENXIO; } switch (cmd) { case FBIOGET_VBLANK: { struct fb_vblank vblank; int err; err = matroxfb_get_vblank(PMINFO &vblank); if (err) return err; if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_MODE: { struct matroxioc_output_mode mom; int val; if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) return -EFAULT; if (mom.output >= sizeof(u_int32_t)) return -EINVAL; switch (mom.output) { case MATROXFB_OUTPUT_PRIMARY: if (mom.mode != MATROXFB_OUTPUT_MODE_MONITOR) return -EINVAL; /* mode did not change... */ return 0; case MATROXFB_OUTPUT_SECONDARY: val = -EINVAL; down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device)) val = ACCESS_FBINFO(altout.output)->setmode(ACCESS_FBINFO(altout.device), mom.mode); up_read(&ACCESS_FBINFO(altout.lock)); if (val != 1) return val; if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) matroxfb_switch(ACCESS_FBINFO(currcon), info); if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { struct matroxfb_dh_fb_info* crtc2; down_read(&ACCESS_FBINFO(crtc2.lock)); crtc2 = (struct matroxfb_dh_fb_info*)(ACCESS_FBINFO(crtc2.info)); if (crtc2) crtc2->fbcon.switch_con(crtc2->currcon, &crtc2->fbcon); up_read(&ACCESS_FBINFO(crtc2.lock)); } return 0; case MATROXFB_OUTPUT_DFP: if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP)) return -ENXIO; if (mom.mode!= MATROXFB_OUTPUT_MODE_MONITOR) return -EINVAL; /* mode did not change... */ return 0; default: return -EINVAL; } return 0; } case MATROXFB_GET_OUTPUT_MODE: { struct matroxioc_output_mode mom; int val; if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) return -EFAULT; if (mom.output >= sizeof(u_int32_t)) return -EINVAL; switch (mom.output) { case MATROXFB_OUTPUT_PRIMARY: mom.mode = MATROXFB_OUTPUT_MODE_MONITOR; break; case MATROXFB_OUTPUT_SECONDARY: val = -EINVAL; down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device)) val = ACCESS_FBINFO(altout.output)->getmode(ACCESS_FBINFO(altout.device), &mom.mode); up_read(&ACCESS_FBINFO(altout.lock)); if (val) return val; break; case MATROXFB_OUTPUT_DFP: if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP)) return -ENXIO; mom.mode = MATROXFB_OUTPUT_MODE_MONITOR; break; default: return -EINVAL; } if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom))) return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_CONNECTION: { u_int32_t tmp; if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp))) return -EFAULT; if (tmp & ~ACCESS_FBINFO(output.all)) return -EINVAL; if (tmp & ACCESS_FBINFO(output.sh)) return -EINVAL; if (tmp & MATROXFB_OUTPUT_CONN_DFP) { if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY) return -EINVAL; if (ACCESS_FBINFO(output.sh)) return -EINVAL; } if (tmp == ACCESS_FBINFO(output.ph)) return 0; ACCESS_FBINFO(output.ph) = tmp; matroxfb_switch(ACCESS_FBINFO(currcon), info); return 0; } case MATROXFB_GET_OUTPUT_CONNECTION: { if (put_user(ACCESS_FBINFO(output.ph), (u_int32_t*)arg)) return -EFAULT; return 0; } case MATROXFB_GET_AVAILABLE_OUTPUTS: { u_int32_t tmp; tmp = ACCESS_FBINFO(output.all) & ~ACCESS_FBINFO(output.sh); if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) tmp &= ~MATROXFB_OUTPUT_CONN_SECONDARY; if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) tmp &= ~MATROXFB_OUTPUT_CONN_DFP; if (put_user(tmp, (u_int32_t*)arg)) return -EFAULT; return 0; } case MATROXFB_GET_ALL_OUTPUTS: { if (put_user(ACCESS_FBINFO(output.all), (u_int32_t*)arg)) return -EFAULT; return 0; } } return -EINVAL;#undef minfo}static struct fb_ops matroxfb_ops = { owner: THIS_MODULE, fb_open: matroxfb_open, fb_release: matroxfb_release, fb_get_fix: matroxfb_get_fix, fb_get_var: matroxfb_get_var, fb_set_var: matroxfb_set_var, fb_get_cmap: matroxfb_get_cmap, fb_set_cmap: matroxfb_set_cmap, fb_pan_display: matroxfb_pan_display, fb_ioctl: matroxfb_ioctl,};int matroxfb_switch(int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) struct fb_cmap* cmap; struct display *p; DBG("matroxfb_switch"); if (ACCESS_FBINFO(currcon) >= 0) { /* Do we have to save the colormap? */ cmap = &(ACCESS_FBINFO(currcon_display)->cmap); dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO(currcon), cmap->len); if (cmap->len) { dprintk(KERN_DEBUG "switch1a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp); fb_get_cmap(cmap, 1, matrox_getcolreg, info);#ifdef DEBUG if (cmap->red) { dprintk(KERN_DEBUG "switch1r: %X\n", cmap->red[0]); }#endif } } ACCESS_FBINFO(currcon) = con; if (con < 0) p = ACCESS_FBINFO(fbcon.disp); else p = fb_display + con; ACCESS_FBINFO(currcon_display) = p; p->var.activate = FB_ACTIVATE_NOW;#ifdef DEBUG cmap = &p->cmap; dprintk(KERN_DEBUG "switch2: con = %d, cmap.len = %d\n", con, cmap->len); dprintk(KERN_DEBUG "switch2a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp); if (p->cmap.red) { dprintk(KERN_DEBUG "switch2r: %X\n", cmap->red[0]); }#endif matroxfb_set_var(&p->var, con, info);#ifdef DEBUG dprintk(KERN_DEBUG "switch3: con = %d, cmap.len = %d\n", con, cmap->len); dprintk(KERN_DEBUG "switch3a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp); if (p->cmap.red) { dprintk(KERN_DEBUG "switch3r: %X\n", cmap->red[0]); }#endif return 0;#undef minfo}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static void matroxfb_blank(int blank, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) int seq; int crtc; CRITFLAGS DBG("matroxfb_blank") if (ACCESS_FBINFO(dead)) return; switch (blank) { case 1: seq = 0x20; crtc = 0x00; break; /* works ??? */ case 2: seq = 0x20; crtc = 0x10; break; case 3: seq = 0x20; crtc = 0x20; break; case 4: seq = 0x20; crtc = 0x30; break; default: seq = 0x00; crtc = 0x00; break; } CRITBEGIN mga_outb(M_SEQ_INDEX, 1); mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq); mga_outb(M_EXTVGA_INDEX, 1); mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc); CRITEND#undef minfo}#define RSDepth(X) (((X) >> 8) & 0x0F)#define RS8bpp 0x1#define RS15bpp 0x2#define RS16bpp 0x3#define RS32bpp 0x4#define RS4bpp 0x5#define RS24bpp 0x6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -