📄 neofb.c
字号:
vmode: FB_VMODE_NONINTERLACED};#endifstatic struct fb_var_screeninfo *neofb_var = NULL;static int __devinit neo_map_mmio (struct neofb_info *info){ DBG("neo_map_mmio"); info->mmio.pbase = pci_resource_start (info->pcidev, 1); info->mmio.len = MMIO_SIZE; if (!request_mem_region (info->mmio.pbase, MMIO_SIZE, "memory mapped I/O")) { printk ("neofb: memory mapped IO in use\n"); return -EBUSY; } info->mmio.vbase = ioremap (info->mmio.pbase, MMIO_SIZE); if (!info->mmio.vbase) { printk ("neofb: unable to map memory mapped IO\n"); release_mem_region (info->mmio.pbase, info->mmio.len); return -ENOMEM; } else printk (KERN_INFO "neofb: mapped io at %p\n", info->mmio.vbase); info->fb.fix.mmio_start = info->mmio.pbase; info->fb.fix.mmio_len = info->mmio.len; return 0;}static void __devinit neo_unmap_mmio (struct neofb_info *info){ DBG("neo_unmap_mmio"); if (info->mmio.vbase) { iounmap (info->mmio.vbase); info->mmio.vbase = NULL; release_mem_region (info->mmio.pbase, info->mmio.len); }}static int __devinit neo_map_video (struct neofb_info *info, int video_len){ DBG("neo_map_video"); info->video.pbase = pci_resource_start (info->pcidev, 0); info->video.len = video_len; if (!request_mem_region (info->video.pbase, info->video.len, "frame buffer")) { printk ("neofb: frame buffer in use\n"); return -EBUSY; } info->video.vbase = ioremap (info->video.pbase, info->video.len); if (!info->video.vbase) { printk ("neofb: unable to map screen memory\n"); release_mem_region (info->video.pbase, info->video.len); return -ENOMEM; } else printk (KERN_INFO "neofb: mapped framebuffer at %p\n", info->video.vbase); info->fb.fix.smem_start = info->video.pbase; info->fb.fix.smem_len = info->video.len; info->fb.screen_base = info->video.vbase;#ifdef CONFIG_MTRR info->video.mtrr = mtrr_add (info->video.pbase, pci_resource_len (info->pcidev, 0), MTRR_TYPE_WRCOMB, 1);#endif /* Clear framebuffer, it's all white in memory after boot */ memset (info->video.vbase, 0, info->video.len); return 0;}static void __devinit neo_unmap_video (struct neofb_info *info){ DBG("neo_unmap_video"); if (info->video.vbase) {#ifdef CONFIG_MTRR mtrr_del (info->video.mtrr, info->video.pbase, info->video.len);#endif iounmap (info->video.vbase); info->video.vbase = NULL; info->fb.screen_base = NULL; release_mem_region (info->video.pbase, info->video.len); }}static int __devinit neo_init_hw (struct neofb_info *info){ int videoRam = 896; int maxClock = 65000; int CursorMem = 1024; int CursorOff = 0x100; int linearSize = 1024; int maxWidth = 1024; int maxHeight = 1024; unsigned char type, display; int w; DBG("neo_init_hw"); neoUnlock();#if 0 printk (KERN_DEBUG "--- Neo extended register dump ---\n"); for (w=0; w<0x85; w++) printk (KERN_DEBUG "CR %p: %p\n", (void*)w, (void*)VGArCR (w)); for (w=0; w<0xC7; w++) printk (KERN_DEBUG "GR %p: %p\n", (void*)w, (void*)VGArGR (w));#endif /* Determine the panel type */ VGAwGR(0x09,0x26); type = VGArGR(0x21); display = VGArGR(0x20); /* Determine panel width -- used in NeoValidMode. */ w = VGArGR(0x20); VGAwGR(0x09,0x00); switch ((w & 0x18) >> 3) { case 0x00: info->NeoPanelWidth = 640; info->NeoPanelHeight = 480; neofb_var = &neofb_var640x480x8; break; case 0x01: info->NeoPanelWidth = 800; info->NeoPanelHeight = 600; neofb_var = &neofb_var800x600x8; break; case 0x02: info->NeoPanelWidth = 1024; info->NeoPanelHeight = 768; neofb_var = &neofb_var1024x768x8; break; case 0x03: /* 1280x1024 panel support needs to be added */#ifdef NOT_DONE info->NeoPanelWidth = 1280; info->NeoPanelHeight = 1024; neofb_var = &neofb_var1280x1024x8; break;#else printk (KERN_ERR "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported\n"); return -1;#endif default: info->NeoPanelWidth = 640; info->NeoPanelHeight = 480; neofb_var = &neofb_var640x480x8; break; } printk (KERN_INFO "Panel is a %dx%d %s %s display\n", info->NeoPanelWidth, info->NeoPanelHeight, (type & 0x02) ? "color" : "monochrome", (type & 0x10) ? "TFT" : "dual scan"); switch (info->accel) { case FB_ACCEL_NEOMAGIC_NM2070: videoRam = 896; maxClock = 65000; CursorMem = 2048; CursorOff = 0x100; linearSize = 1024; maxWidth = 1024; maxHeight = 1024; break; case FB_ACCEL_NEOMAGIC_NM2090: case FB_ACCEL_NEOMAGIC_NM2093: videoRam = 1152; maxClock = 80000; CursorMem = 2048; CursorOff = 0x100; linearSize = 2048; maxWidth = 1024; maxHeight = 1024; break; case FB_ACCEL_NEOMAGIC_NM2097: videoRam = 1152; maxClock = 80000; CursorMem = 1024; CursorOff = 0x100; linearSize = 2048; maxWidth = 1024; maxHeight = 1024; break; case FB_ACCEL_NEOMAGIC_NM2160: videoRam = 2048; maxClock = 90000; CursorMem = 1024; CursorOff = 0x100; linearSize = 2048; maxWidth = 1024; maxHeight = 1024; break; case FB_ACCEL_NEOMAGIC_NM2200: videoRam = 2560; maxClock = 110000; CursorMem = 1024; CursorOff = 0x1000; linearSize = 4096; maxWidth = 1280; maxHeight = 1024; /* ???? */ info->neo2200 = (Neo2200*) info->mmio.vbase; break; case FB_ACCEL_NEOMAGIC_NM2230: videoRam = 3008; maxClock = 110000; CursorMem = 1024; CursorOff = 0x1000; linearSize = 4096; maxWidth = 1280; maxHeight = 1024; /* ???? */ info->neo2200 = (Neo2200*) info->mmio.vbase; break; case FB_ACCEL_NEOMAGIC_NM2360: videoRam = 4096; maxClock = 110000; CursorMem = 1024; CursorOff = 0x1000; linearSize = 4096; maxWidth = 1280; maxHeight = 1024; /* ???? */ info->neo2200 = (Neo2200*) info->mmio.vbase; break; case FB_ACCEL_NEOMAGIC_NM2380: videoRam = 6144; maxClock = 110000; CursorMem = 1024; CursorOff = 0x1000; linearSize = 8192; maxWidth = 1280; maxHeight = 1024; /* ???? */ info->neo2200 = (Neo2200*) info->mmio.vbase; break; } info->maxClock = maxClock; return videoRam * 1024;}static struct neofb_info * __devinit neo_alloc_fb_info (struct pci_dev *dev, const struct pci_device_id *id){ struct neofb_info *info; info = kmalloc (sizeof(struct neofb_info) + sizeof(struct display) + sizeof(u32) * 16, GFP_KERNEL); if (!info) return NULL; memset (info, 0, sizeof(struct neofb_info) + sizeof(struct display)); info->currcon = -1; info->pcidev = dev; info->accel = id->driver_data; info->pci_burst = !nopciburst; info->lcd_stretch = !nostretch; if (!internal && !external) { info->internal_display = 1; info->external_display = 0; } else { info->internal_display = internal; info->external_display = external; } switch (info->accel) { case FB_ACCEL_NEOMAGIC_NM2070: sprintf (info->fb.fix.id, "MagicGraph 128"); break; case FB_ACCEL_NEOMAGIC_NM2090: sprintf (info->fb.fix.id, "MagicGraph 128V"); break; case FB_ACCEL_NEOMAGIC_NM2093: sprintf (info->fb.fix.id, "MagicGraph 128ZV"); break; case FB_ACCEL_NEOMAGIC_NM2097: sprintf (info->fb.fix.id, "MagicGraph 128ZV+"); break; case FB_ACCEL_NEOMAGIC_NM2160: sprintf (info->fb.fix.id, "MagicGraph 128XD"); break; case FB_ACCEL_NEOMAGIC_NM2200: sprintf (info->fb.fix.id, "MagicGraph 256AV"); break; case FB_ACCEL_NEOMAGIC_NM2230: sprintf (info->fb.fix.id, "MagicGraph 256AV+"); break; case FB_ACCEL_NEOMAGIC_NM2360: sprintf (info->fb.fix.id, "MagicGraph 256ZX"); break; case FB_ACCEL_NEOMAGIC_NM2380: sprintf (info->fb.fix.id, "MagicGraph 256XL+"); break; } info->fb.fix.type = FB_TYPE_PACKED_PIXELS; info->fb.fix.type_aux = 0; info->fb.fix.xpanstep = 0; info->fb.fix.ypanstep = 4; info->fb.fix.ywrapstep = 0; info->fb.fix.accel = id->driver_data; info->fb.var.nonstd = 0; info->fb.var.activate = FB_ACTIVATE_NOW; info->fb.var.height = -1; info->fb.var.width = -1; info->fb.var.accel_flags = 0; strcpy (info->fb.modename, info->fb.fix.id); info->fb.fbops = &neofb_ops; info->fb.changevar = NULL; info->fb.switch_con = neofb_switch; info->fb.updatevar = neofb_updatevar; info->fb.blank = neofb_blank; info->fb.flags = FBINFO_FLAG_DEFAULT; info->fb.disp = (struct display *)(info + 1); info->fb.pseudo_palette = (void *)(info->fb.disp + 1); fb_alloc_cmap (&info->fb.cmap, NR_PALETTE, 0); return info;}static void __devinit neo_free_fb_info (struct neofb_info *info){ if (info) { /* * Free the colourmap */ fb_alloc_cmap (&info->fb.cmap, 0, 0); kfree (info); }}/* --------------------------------------------------------------------- */static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_id* id){ struct neofb_info *info; u_int h_sync, v_sync; int err; int video_len; DBG("neofb_probe"); err = pci_enable_device (dev); if (err) return err; err = -ENOMEM; info = neo_alloc_fb_info (dev, id); if (!info) goto failed; err = neo_map_mmio (info); if (err) goto failed; video_len = neo_init_hw (info); if (video_len < 0) { err = video_len; goto failed; } err = neo_map_video (info, video_len); if (err) goto failed; neofb_set_var (neofb_var, -1, &info->fb); /* * Calculate the hsync and vsync frequencies. Note that * we split the 1e12 constant up so that we can preserve * the precision and fit the results into 32-bit registers. * (1953125000 * 512 = 1e12) */ h_sync = 1953125000 / info->fb.var.pixclock; h_sync = h_sync * 512 / (info->fb.var.xres + info->fb.var.left_margin + info->fb.var.right_margin + info->fb.var.hsync_len); v_sync = h_sync / (info->fb.var.yres + info->fb.var.upper_margin + info->fb.var.lower_margin + info->fb.var.vsync_len); printk(KERN_INFO "neofb v" NEOFB_VERSION ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n", info->fb.fix.smem_len >> 10, info->fb.var.xres, info->fb.var.yres, h_sync / 1000, h_sync % 1000, v_sync); err = register_framebuffer (&info->fb); if (err < 0) goto failed; printk (KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(info->fb.node), info->fb.modename); /* * Our driver data */ pci_set_drvdata(dev, info); return 0;failed: neo_unmap_video (info); neo_unmap_mmio (info); neo_free_fb_info (info); return err;}static void __devexit neofb_remove (struct pci_dev *dev){ struct neofb_info *info = pci_get_drvdata(dev); DBG("neofb_remove"); if (info) { /* * If unregister_framebuffer fails, then * we will be leaving hooks that could cause * oopsen laying around. */ if (unregister_framebuffer (&info->fb)) printk (KERN_WARNING "neofb: danger danger! Oopsen imminent!\n"); neo_unmap_video (info); neo_unmap_mmio (info); neo_free_fb_info (info); /* * Ensure that the driver data is no longer * valid. */ pci_set_drvdata(dev, NULL); }}static struct pci_device_id neofb_devices[] __devinitdata = { {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360}, {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380}, {0, 0, 0, 0, 0, 0, 0}};MODULE_DEVICE_TABLE(pci, neofb_devices);static struct pci_driver neofb_driver = { name: "neofb", id_table: neofb_devices, probe: neofb_probe, remove: __devexit_p(neofb_remove)};/* **************************** init-time only **************************** */static void __init neo_init (void){ DBG("neo_init"); pci_register_driver (&neofb_driver);}/* **************************** exit-time only **************************** */static void __exit neo_done (void){ DBG("neo_done"); pci_unregister_driver (&neofb_driver);}#ifndef MODULE/* ************************* init in-kernel code ************************** */int __init neofb_setup (char *options){ char *this_opt; DBG("neofb_setup"); if (!options || !*options) return 0; for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; if (!strncmp(this_opt, "disabled", 8)) disabled = 1; if (!strncmp(this_opt, "internal", 8)) internal = 1; if (!strncmp(this_opt, "external", 8)) external = 1; if (!strncmp(this_opt, "nostretch", 9)) nostretch = 1; if (!strncmp(this_opt, "nopciburst", 10)) nopciburst = 1; } return 0;}static int __initdata initialized = 0;int __init neofb_init(void){ DBG("neofb_init"); if (disabled) return -ENXIO; if (!initialized) { initialized = 1; neo_init(); } /* never return failure, user can hotplug card later... */ return 0;}#else/* *************************** init module code **************************** */int __init init_module(void){ DBG("init_module"); if (disabled) return -ENXIO; neo_init(); /* never return failure; user can hotplug card later... */ return 0;}#endif /* MODULE */module_exit(neo_done);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -