📄 fbdev.c
字号:
dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= dsp->var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual || var->yoffset + dsp->var.yres > dsp->var.yres_virtual) return -EINVAL; } base = var->yoffset * dsp->line_length + var->xoffset; if (con == rivainfo->currcon) { rivainfo->riva.SetStartAddress(&rivainfo->riva, base); } dsp->var.xoffset = var->xoffset; dsp->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) dsp->var.vmode |= FB_VMODE_YWRAP; else dsp->var.vmode &= ~FB_VMODE_YWRAP; DPRINTK("EXIT, returning 0\n"); return 0;}static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){ struct rivafb_info *rivainfo = (struct rivafb_info *)info; DPRINTK("ENTER\n"); assert(rivainfo != NULL); /* no rivafb-specific ioctls */ DPRINTK("EXIT, returning -EINVAL\n"); return -EINVAL;}static int rivafb_rasterimg(struct fb_info *info, int start){ struct rivafb_info *rinfo = (struct rivafb_info *)info; wait_for_idle(rinfo); return 0;}static int rivafb_switch(int con, struct fb_info *info){ struct rivafb_info *rivainfo = (struct rivafb_info *)info; struct fb_cmap *cmap; struct display *dsp; DPRINTK("ENTER\n"); assert(rivainfo != NULL); dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con]; if (rivainfo->currcon >= 0) { /* Do we have to save the colormap? */ cmap = &(rivainfo->currcon_display->cmap); DPRINTK("switch1: con = %d, cmap.len = %d\n", rivainfo->currcon, cmap->len); if (cmap->len) { DPRINTK("switch1a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp); fb_get_cmap(cmap, 1, riva_getcolreg, info); } } rivainfo->currcon = con; rivainfo->currcon_display = dsp; rivafb_set_var(&dsp->var, con, info); riva_set_dispsw(rivainfo, dsp); DPRINTK("EXIT, returning 0\n"); return 0;}static int rivafb_updatevar(int con, struct fb_info *info){ int rc; DPRINTK("ENTER\n"); rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var, con, info); DPRINTK("EXIT, returning %d\n", rc); return rc;}static void rivafb_blank(int blank, struct fb_info *info){ unsigned char tmp, vesa; struct rivafb_info *rinfo = (struct rivafb_info *)info; DPRINTK("ENTER\n"); assert(rinfo != NULL); tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */ vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */ if (blank) { tmp |= 0x20; switch (blank - 1) { case VESA_NO_BLANKING: break; case VESA_VSYNC_SUSPEND: vesa |= 0x80; break; case VESA_HSYNC_SUSPEND: vesa |= 0x40; break; case VESA_POWERDOWN: vesa |= 0xc0; break; } } SEQout(rinfo, 0x01, tmp); CRTCout(rinfo, 0x1a, vesa); DPRINTK("EXIT\n");}/* ------------------------------------------------------------------------- * * * initialization helper functions * * ------------------------------------------------------------------------- *//* kernel interface */static struct fb_ops riva_fb_ops = { owner: THIS_MODULE, fb_get_fix: rivafb_get_fix, fb_get_var: rivafb_get_var, fb_set_var: rivafb_set_var, fb_get_cmap: rivafb_get_cmap, fb_set_cmap: rivafb_set_cmap, fb_pan_display: rivafb_pan_display, fb_ioctl: rivafb_ioctl, fb_rasterimg: rivafb_rasterimg,};static int __devinit riva_init_disp_var(struct rivafb_info *rinfo){#ifndef MODULE if (mode_option) fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option, NULL, 0, NULL, 8);#endif return 0;}static int __devinit riva_init_disp(struct rivafb_info *rinfo){ struct fb_info *info; struct display *disp; DPRINTK("ENTER\n"); assert(rinfo != NULL); info = &rinfo->info; disp = &rinfo->disp; disp->var = rivafb_default_var; if (noaccel) disp->var.accel_flags &= ~FB_ACCELF_TEXT; else disp->var.accel_flags |= FB_ACCELF_TEXT; info->disp = disp; /* FIXME: assure that disp->cmap is completely filled out */ rinfo->currcon_display = disp; if ((riva_init_disp_var(rinfo)) < 0) { DPRINTK("EXIT, returning -1\n"); return -1; } riva_set_dispsw(rinfo, disp); DPRINTK("EXIT, returning 0\n"); return 0;}static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo){ struct fb_info *info; assert(rinfo != NULL); info = &rinfo->info; strcpy(info->modename, rinfo->drvr_name); info->node = -1; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &riva_fb_ops; /* FIXME: set monspecs to what??? */ info->display_fg = NULL; strncpy(info->fontname, fontname, sizeof(info->fontname)); info->fontname[sizeof(info->fontname) - 1] = 0; info->changevar = NULL; info->switch_con = rivafb_switch; info->updatevar = rivafb_updatevar; info->blank = rivafb_blank; if (riva_init_disp(rinfo) < 0) /* must be done last */ return -1; return 0;}/* ------------------------------------------------------------------------- * * * PCI bus * * ------------------------------------------------------------------------- */static int __devinit rivafb_init_one(struct pci_dev *pd, const struct pci_device_id *ent){ struct rivafb_info *rinfo; struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; assert(pd != NULL); assert(rci != NULL); rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL); if (!rinfo) goto err_out; memset(rinfo, 0, sizeof(struct rivafb_info)); rinfo->drvr_name = rci->name; rinfo->riva.Architecture = rci->arch_rev; rinfo->pd = pd; rinfo->base0_region_size = pci_resource_len(pd, 0); rinfo->base1_region_size = pci_resource_len(pd, 1); assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */ assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */ rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0); rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1); if (!request_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size, "rivafb")) { printk(KERN_ERR PFX "cannot reserve MMIO region\n"); goto err_out_kfree; } if (!request_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size, "rivafb")) { printk(KERN_ERR PFX "cannot reserve FB region\n"); goto err_out_free_base0; } rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys, rinfo->base0_region_size); if (!rinfo->ctrl_base) { printk(KERN_ERR PFX "cannot ioremap MMIO base\n"); goto err_out_free_base1; } rinfo->fb_base = ioremap(rinfo->fb_base_phys, rinfo->base1_region_size); if (!rinfo->fb_base) { printk(KERN_ERR PFX "cannot ioremap FB base\n"); goto err_out_iounmap_ctrl; } #ifdef CONFIG_MTRR if (!nomtrr) { rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys, rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1); if (rinfo->mtrr.vram < 0) { printk(KERN_ERR PFX "unable to setup MTRR\n"); } else { rinfo->mtrr.vram_valid = 1; /* let there be speed */ printk(KERN_INFO PFX "RIVA MTRR set to ON\n"); } }#endif /* CONFIG_MTRR */ rinfo->riva.EnableIRQ = 0; rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000); rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000); rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000); rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000); rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000); rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000); rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000); rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000); rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000); rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000); rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000); rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0; switch (rinfo->riva.Architecture) { case NV_ARCH_03: rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000); break; case NV_ARCH_04: case NV_ARCH_10: case NV_ARCH_20: rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000); rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000); break; } RivaGetConfig(&rinfo->riva); /* back to normal */ assert(rinfo->pd != NULL); /* unlock io */ CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ rinfo->riva.LockUnlock(&rinfo->riva, 0); riva_save_state(rinfo, &rinfo->initial_state); rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024; rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000; if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo); if (riva_set_fbinfo(rinfo) < 0) { printk(KERN_ERR PFX "error setting initial video mode\n"); goto err_out_cursor; } if (register_framebuffer((struct fb_info *)rinfo) < 0) { printk(KERN_ERR PFX "error registering riva framebuffer\n"); goto err_out_load_state; } riva_boards = riva_board_list_add(riva_boards, rinfo); pci_set_drvdata(pd, rinfo); printk(KERN_INFO PFX "PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n", rinfo->riva.Architecture, RIVAFB_VERSION, rinfo->drvr_name, rinfo->ram_amount / (1024 * 1024), rinfo->fb_base_phys); return 0;err_out_load_state: riva_load_state(rinfo, &rinfo->initial_state);err_out_cursor: rivafb_exit_cursor(rinfo);/* err_out_iounmap_fb: */ iounmap(rinfo->fb_base);err_out_iounmap_ctrl: iounmap(rinfo->ctrl_base);err_out_free_base1: release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);err_out_free_base0: release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);err_out_kfree: kfree(rinfo);err_out: return -ENODEV;}static void __devexit rivafb_remove_one(struct pci_dev *pd){ struct rivafb_info *board = pci_get_drvdata(pd); if (!board) return; riva_boards = riva_board_list_del(riva_boards, board); riva_load_state(board, &board->initial_state); unregister_framebuffer((struct fb_info *)board); rivafb_exit_cursor(board);#ifdef CONFIG_MTRR if (board->mtrr.vram_valid) mtrr_del(board->mtrr.vram, board->fb_base_phys, board->base1_region_size);#endif /* CONFIG_MTRR */ iounmap(board->ctrl_base); iounmap(board->fb_base); release_mem_region(board->ctrl_base_phys, board->base0_region_size); release_mem_region(board->fb_base_phys, board->base1_region_size); kfree(board); pci_set_drvdata(pd, NULL);}/* ------------------------------------------------------------------------- * * * initialization * * ------------------------------------------------------------------------- */#ifndef MODULEint __init rivafb_setup(char *options){ char *this_opt; if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; if (!strncmp(this_opt, "font:", 5)) { char *p; int i; p = this_opt + 5; for (i = 0; i < sizeof(fontname) - 1; i++) if (!*p || *p == ' ' || *p == ',') break; memcpy(fontname, this_opt + 5, i); fontname[i] = 0; } else if (!strncmp(this_opt, "noblink", 7)) { noblink = 1; } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; } else if (!strncmp(this_opt, "nomove", 6)) { nomove = 1;#ifdef CONFIG_MTRR } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1;#endif } else if (!strncmp(this_opt, "nohwcursor", 10)) { nohwcursor = 1; } else mode_option = this_opt; } return 0;}#endif /* !MODULE */static struct pci_driver rivafb_driver = { name: "rivafb", id_table: rivafb_pci_tbl, probe: rivafb_init_one, remove: __devexit_p(rivafb_remove_one),};/* ------------------------------------------------------------------------- * * * modularization * * ------------------------------------------------------------------------- */int __init rivafb_init(void){ int err;#ifdef MODULE if (font) strncpy(fontname, font, sizeof(fontname)-1);#endif err = pci_module_init(&rivafb_driver); if (err) return err; return 0;}#ifdef MODULEstatic void __exit rivafb_exit(void){ pci_unregister_driver(&rivafb_driver);}module_init(rivafb_init);module_exit(rivafb_exit);MODULE_PARM(font, "s");MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");MODULE_PARM(noaccel, "i");MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");MODULE_PARM(nomove, "i");MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");MODULE_PARM(nohwcursor, "i");MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");MODULE_PARM(noblink, "i");MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");#ifdef CONFIG_MTRRMODULE_PARM(nomtrr, "i");MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");#endif#endif /* MODULE */MODULE_AUTHOR("Ani Joshi, maintainer");MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -