📄 cirrusfb.c
字号:
DPRINTK("EXIT\n"); return mem;}static void get_pci_addrs(const struct pci_dev *pdev, unsigned long *display, unsigned long *registers){ assert(pdev != NULL); assert(display != NULL); assert(registers != NULL); DPRINTK("ENTER\n"); *display = 0; *registers = 0; /* This is a best-guess for now */ if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { *display = pci_resource_start(pdev, 1); *registers = pci_resource_start(pdev, 0); } else { *display = pci_resource_start(pdev, 0); *registers = pci_resource_start(pdev, 1); } assert(*display != 0); DPRINTK("EXIT\n");}static void cirrusfb_pci_unmap(struct fb_info *info){ struct pci_dev *pdev = to_pci_dev(info->device); iounmap(info->screen_base);#if 0 /* if system didn't claim this region, we would... */ release_mem_region(0xA0000, 65535);#endif if (release_io_ports) release_region(0x3C0, 32); pci_release_regions(pdev);}#endif /* CONFIG_PCI */#ifdef CONFIG_ZORROstatic void cirrusfb_zorro_unmap(struct fb_info *info){ struct cirrusfb_info *cinfo = info->par; struct zorro_dev *zdev = to_zorro_dev(info->device); zorro_release_device(zdev); if (cinfo->btype == BT_PICASSO4) { cinfo->regbase -= 0x600000; iounmap((void *)cinfo->regbase); iounmap(info->screen_base); } else { if (zorro_resource_start(zdev) > 0x01000000) iounmap(info->screen_base); }}#endif /* CONFIG_ZORRO */static int __devinit cirrusfb_set_fbinfo(struct fb_info *info){ struct cirrusfb_info *cinfo = info->par; struct fb_var_screeninfo *var = &info->var; info->pseudo_palette = cinfo->pseudo_palette; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA; if (noaccel) info->flags |= FBINFO_HWACCEL_DISABLED; info->fbops = &cirrusfb_ops; if (cinfo->btype == BT_GD5480) { if (var->bits_per_pixel == 16) info->screen_base += 1 * MB_; if (var->bits_per_pixel == 32) info->screen_base += 2 * MB_; } /* Fill fix common fields */ strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name, sizeof(info->fix.id)); /* monochrome: only 1 memory plane */ /* 8 bit and above: Use whole memory area */ info->fix.smem_len = info->screen_size; if (var->bits_per_pixel == 1) info->fix.smem_len /= 4; info->fix.type_aux = 0; info->fix.xpanstep = 1; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; /* FIXME: map region at 0xB8000 if available, fill in here */ info->fix.mmio_len = 0; info->fix.accel = FB_ACCEL_NONE; fb_alloc_cmap(&info->cmap, 256, 0); return 0;}static int __devinit cirrusfb_register(struct fb_info *info){ struct cirrusfb_info *cinfo = info->par; int err; enum cirrus_board btype; DPRINTK("ENTER\n"); printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based " "graphic boards, v" CIRRUSFB_VERSION "\n"); btype = cinfo->btype; /* sanity checks */ assert(btype != BT_NONE); /* set all the vital stuff */ cirrusfb_set_fbinfo(info); DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); if (!err) { DPRINTK("wrong initial video mode\n"); err = -EINVAL; goto err_dealloc_cmap; } info->var.activate = FB_ACTIVATE_NOW; err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); if (err < 0) { /* should never happen */ DPRINTK("choking on default var... umm, no good.\n"); goto err_dealloc_cmap; } err = register_framebuffer(info); if (err < 0) { printk(KERN_ERR "cirrusfb: could not register " "fb device; err = %d!\n", err); goto err_dealloc_cmap; } DPRINTK("EXIT, returning 0\n"); return 0;err_dealloc_cmap: fb_dealloc_cmap(&info->cmap); cinfo->unmap(info); framebuffer_release(info); return err;}static void __devexit cirrusfb_cleanup(struct fb_info *info){ struct cirrusfb_info *cinfo = info->par; DPRINTK("ENTER\n"); switch_monitor(cinfo, 0); unregister_framebuffer(info); fb_dealloc_cmap(&info->cmap); printk("Framebuffer unregistered\n"); cinfo->unmap(info); framebuffer_release(info); DPRINTK("EXIT\n");}#ifdef CONFIG_PCIstatic int __devinit cirrusfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent){ struct cirrusfb_info *cinfo; struct fb_info *info; enum cirrus_board btype; unsigned long board_addr, board_size; int ret; ret = pci_enable_device(pdev); if (ret < 0) { printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n"); goto err_out; } info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); if (!info) { printk(KERN_ERR "cirrusfb: could not allocate memory\n"); ret = -ENOMEM; goto err_disable; } cinfo = info->par; cinfo->btype = btype = (enum cirrus_board) ent->driver_data; DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", pdev->resource[0].start, btype); DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start); if (isPReP) { pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000);#ifdef CONFIG_PPC_PREP get_prep_addrs(&board_addr, &info->fix.mmio_start);#endif /* PReP dies if we ioremap the IO registers, but it works w/out... */ cinfo->regbase = (char __iomem *) info->fix.mmio_start; } else { DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n"); get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); /* FIXME: this forces VGA. alternatives? */ cinfo->regbase = NULL; } DPRINTK("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fix.mmio_start); board_size = (btype == BT_GD5480) ? 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase); ret = pci_request_regions(pdev, "cirrusfb"); if (ret < 0) { printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " "abort\n", board_addr); goto err_release_fb; }#if 0 /* if the system didn't claim this region, we would... */ if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n", 0xA0000L); ret = -EBUSY; goto err_release_regions; }#endif if (request_region(0x3C0, 32, "cirrusfb")) release_io_ports = 1; info->screen_base = ioremap(board_addr, board_size); if (!info->screen_base) { ret = -EIO; goto err_release_legacy; } info->fix.smem_start = board_addr; info->screen_size = board_size; cinfo->unmap = cirrusfb_pci_unmap; printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus " "Logic chipset on PCI bus\n", info->screen_size >> 10, board_addr); pci_set_drvdata(pdev, info); ret = cirrusfb_register(info); if (ret) iounmap(info->screen_base); return ret;err_release_legacy: if (release_io_ports) release_region(0x3C0, 32);#if 0 release_mem_region(0xA0000, 65535);err_release_regions:#endif pci_release_regions(pdev);err_release_fb: framebuffer_release(info);err_disable:err_out: return ret;}static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev){ struct fb_info *info = pci_get_drvdata(pdev); DPRINTK("ENTER\n"); cirrusfb_cleanup(info); DPRINTK("EXIT\n");}static struct pci_driver cirrusfb_pci_driver = { .name = "cirrusfb", .id_table = cirrusfb_pci_table, .probe = cirrusfb_pci_register, .remove = __devexit_p(cirrusfb_pci_unregister),#ifdef CONFIG_PM#if 0 .suspend = cirrusfb_pci_suspend, .resume = cirrusfb_pci_resume,#endif#endif};#endif /* CONFIG_PCI */#ifdef CONFIG_ZORROstatic int __devinit cirrusfb_zorro_register(struct zorro_dev *z, const struct zorro_device_id *ent){ struct cirrusfb_info *cinfo; struct fb_info *info; enum cirrus_board btype; struct zorro_dev *z2 = NULL; unsigned long board_addr, board_size, size; int ret; btype = ent->driver_data; if (cirrusfb_zorro_table2[btype].id2) z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); size = cirrusfb_zorro_table2[btype].size; printk(KERN_INFO "cirrusfb: %s board detected; ", cirrusfb_board_info[btype].name); info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); if (!info) { printk(KERN_ERR "cirrusfb: could not allocate memory\n"); ret = -ENOMEM; goto err_out; } cinfo = info->par; cinfo->btype = btype; assert(z); assert(btype != BT_NONE); board_addr = zorro_resource_start(z); board_size = zorro_resource_len(z); info->screen_size = size; if (!zorro_request_device(z, "cirrusfb")) { printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " "abort\n", board_addr); ret = -EBUSY; goto err_release_fb; } printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); ret = -EIO; if (btype == BT_PICASSO4) { printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000); /* To be precise, for the P4 this is not the */ /* begin of the board, but the begin of RAM. */ /* for P4, map in its address space in 2 chunks (### TEST! ) */ /* (note the ugly hardcoded 16M number) */ cinfo->regbase = ioremap(board_addr, 16777216); if (!cinfo->regbase) goto err_release_region; DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase); cinfo->regbase += 0x600000; info->fix.mmio_start = board_addr + 0x600000; info->fix.smem_start = board_addr + 16777216; info->screen_base = ioremap(info->fix.smem_start, 16777216); if (!info->screen_base) goto err_unmap_regbase; } else { printk(KERN_INFO " REG at $%lx\n", (unsigned long) z2->resource.start); info->fix.smem_start = board_addr; if (board_addr > 0x01000000) info->screen_base = ioremap(board_addr, board_size); else info->screen_base = (caddr_t) ZTWO_VADDR(board_addr); if (!info->screen_base) goto err_release_region; /* set address for REG area of board */ cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); info->fix.mmio_start = z2->resource.start; DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", cinfo->regbase); } cinfo->unmap = cirrusfb_zorro_unmap; printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); zorro_set_drvdata(z, info); ret = cirrusfb_register(info); if (ret) { if (btype == BT_PICASSO4) { iounmap(info->screen_base); iounmap(cinfo->regbase - 0x600000); } else if (board_addr > 0x01000000) iounmap(info->screen_base); } return ret;err_unmap_regbase: /* Parental advisory: explicit hack */ iounmap(cinfo->regbase - 0x600000);err_release_region: release_region(board_addr, board_size);err_release_fb: framebuffer_release(info);err_out: return ret;}void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z){ struct fb_info *info = zorro_get_drvdata(z); DPRINTK("ENTER\n"); cirrusfb_cleanup(info); DPRINTK("EXIT\n");}static struct zorro_driver cirrusfb_zorro_driver = { .name = "cirrusfb", .id_table = cirrusfb_zorro_table, .probe = cirrusfb_zorro_register, .remove = __devexit_p(cirrusfb_zorro_unregister),};#endif /* CONFIG_ZORRO */static int __init cirrusfb_init(void){ int error = 0;#ifndef MODULE char *option = NULL; if (fb_get_options("cirrusfb", &option)) return -ENODEV; cirrusfb_setup(option);#endif#ifdef CONFIG_ZORRO error |= zorro_register_driver(&cirrusfb_zorro_driver);#endif#ifdef CONFIG_PCI error |= pci_register_driver(&cirrusfb_pci_driver);#endif return error;}#ifndef MODULEstatic int __init cirrusfb_setup(char *options) { char *this_opt; DPRINTK("ENTER\n"); if (!options || !*options) return 0; while ((this_opt = strsep(&options, ",")) != NULL) { if (!*this_opt) continue; DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); if (!strcmp(this_opt, "noaccel")) noaccel = 1; else if (!strncmp(this_opt, "mode:", 5)) mode_option = this_opt + 5; else mode_option = this_opt; } return 0;}#endif /* * Modularization */MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");MODULE_LICENSE("GPL");static void __exit cirrusfb_exit(void){#ifdef CONFIG_PCI pci_unregister_driver(&cirrusfb_pci_driver);#endif#ifdef CONFIG_ZORRO zorro_unregister_driver(&cirrusfb_zorro_driver);#end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -