📄 amifb.c
字号:
while (1) { dst += dst_idx >> SHIFT_PER_LONG; dst_idx &= (BITS_PER_LONG-1); bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n); if (!--bpp) break; color >>= 1; dst_idx += next_plane*8; }}static inline void xor_one_line(int bpp, unsigned long next_plane, unsigned long *dst, int dst_idx, u32 n, u32 color){ while (color) { dst += dst_idx >> SHIFT_PER_LONG; dst_idx &= (BITS_PER_LONG-1); bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n); if (!--bpp) break; color >>= 1; dst_idx += next_plane*8; }}static void amifb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ struct amifb_par *par = (struct amifb_par *)info->par; int dst_idx, x2, y2; unsigned long *dst; u32 width, height; if (!rect->width || !rect->height) return; /* * We could use hardware clipping but on many cards you get around * hardware clipping by writing to framebuffer directly. * */ x2 = rect->dx + rect->width; y2 = rect->dy + rect->height; x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; width = x2 - rect->dx; height = y2 - rect->dy; dst = (unsigned long *) ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; dst_idx += rect->dy*par->next_line*8+rect->dx; while (height--) { switch (rect->rop) { case ROP_COPY: fill_one_line(info->var.bits_per_pixel, par->next_plane, dst, dst_idx, width, rect->color); break; case ROP_XOR: xor_one_line(info->var.bits_per_pixel, par->next_plane, dst, dst_idx, width, rect->color); break; } dst_idx += par->next_line*8; }}static inline void copy_one_line(int bpp, unsigned long next_plane, unsigned long *dst, int dst_idx, unsigned long *src, int src_idx, u32 n){ while (1) { dst += dst_idx >> SHIFT_PER_LONG; dst_idx &= (BITS_PER_LONG-1); src += src_idx >> SHIFT_PER_LONG; src_idx &= (BITS_PER_LONG-1); bitcpy(dst, dst_idx, src, src_idx, n); if (!--bpp) break; dst_idx += next_plane*8; src_idx += next_plane*8; }}static inline void copy_one_line_rev(int bpp, unsigned long next_plane, unsigned long *dst, int dst_idx, unsigned long *src, int src_idx, u32 n){ while (1) { dst += dst_idx >> SHIFT_PER_LONG; dst_idx &= (BITS_PER_LONG-1); src += src_idx >> SHIFT_PER_LONG; src_idx &= (BITS_PER_LONG-1); bitcpy_rev(dst, dst_idx, src, src_idx, n); if (!--bpp) break; dst_idx += next_plane*8; src_idx += next_plane*8; }}static void amifb_copyarea(struct fb_info *info, const struct fb_copyarea *area){ struct amifb_par *par = (struct amifb_par *)info->par; int x2, y2; u32 dx, dy, sx, sy, width, height; unsigned long *dst, *src; int dst_idx, src_idx; int rev_copy = 0; /* clip the destination */ x2 = area->dx + area->width; y2 = area->dy + area->height; dx = area->dx > 0 ? area->dx : 0; dy = area->dy > 0 ? area->dy : 0; x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; width = x2 - dx; height = y2 - dy; if (area->sx + dx < area->dx || area->sy + dy < area->dy) return; /* update sx,sy */ sx = area->sx + (dx - area->dx); sy = area->sy + (dy - area->dy); /* the source must be completely inside the virtual screen */ if (sx + width > info->var.xres_virtual || sy + height > info->var.yres_virtual) return; if (dy > sy || (dy == sy && dx > sx)) { dy += height; sy += height; rev_copy = 1; } dst = (unsigned long *) ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); src = dst; dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; src_idx = dst_idx; dst_idx += dy*par->next_line*8+dx; src_idx += sy*par->next_line*8+sx; if (rev_copy) { while (height--) { dst_idx -= par->next_line*8; src_idx -= par->next_line*8; copy_one_line_rev(info->var.bits_per_pixel, par->next_plane, dst, dst_idx, src, src_idx, width); } } else { while (height--) { copy_one_line(info->var.bits_per_pixel, par->next_plane, dst, dst_idx, src, src_idx, width); dst_idx += par->next_line*8; src_idx += par->next_line*8; } }}static inline void expand_one_line(int bpp, unsigned long next_plane, unsigned long *dst, int dst_idx, u32 n, const u8 *data, u32 bgcolor, u32 fgcolor){ const unsigned long *src; int src_idx; while (1) { dst += dst_idx >> SHIFT_PER_LONG; dst_idx &= (BITS_PER_LONG-1); if ((bgcolor ^ fgcolor) & 1) { src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1)); src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8; if (fgcolor & 1) bitcpy(dst, dst_idx, src, src_idx, n); else bitcpy_not(dst, dst_idx, src, src_idx, n); /* set or clear */ } else bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n); if (!--bpp) break; bgcolor >>= 1; fgcolor >>= 1; dst_idx += next_plane*8; }}static void amifb_imageblit(struct fb_info *info, const struct fb_image *image){ struct amifb_par *par = (struct amifb_par *)info->par; int x2, y2; unsigned long *dst; int dst_idx; const char *src; u32 dx, dy, width, height, pitch; /* * We could use hardware clipping but on many cards you get around * hardware clipping by writing to framebuffer directly like we are * doing here. */ x2 = image->dx + image->width; y2 = image->dy + image->height; dx = image->dx; dy = image->dy; x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; width = x2 - dx; height = y2 - dy; if (image->depth == 1) { dst = (unsigned long *) ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; dst_idx += dy*par->next_line*8+dx; src = image->data; pitch = (image->width+7)/8; while (height--) { expand_one_line(info->var.bits_per_pixel, par->next_plane, dst, dst_idx, width, src, image->bg_color, image->fg_color); dst_idx += par->next_line*8; src += pitch; } } else { c2p_planar(info->screen_base, image->data, dx, dy, width, height, par->next_line, par->next_plane, image->width, info->var.bits_per_pixel); }} /* * Amiga Frame Buffer Specific ioctls */static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){ union { struct fb_fix_cursorinfo fix; struct fb_var_cursorinfo var; struct fb_cursorstate state; } crsr; void __user *argp = (void __user *)arg; int i; switch (cmd) { case FBIOGET_FCURSORINFO: i = ami_get_fix_cursorinfo(&crsr.fix); if (i) return i; return copy_to_user(argp, &crsr.fix, sizeof(crsr.fix)) ? -EFAULT : 0; case FBIOGET_VCURSORINFO: i = ami_get_var_cursorinfo(&crsr.var, ((struct fb_var_cursorinfo __user *)arg)->data); if (i) return i; return copy_to_user(argp, &crsr.var, sizeof(crsr.var)) ? -EFAULT : 0; case FBIOPUT_VCURSORINFO: if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) return -EFAULT; return ami_set_var_cursorinfo(&crsr.var, ((struct fb_var_cursorinfo __user *)arg)->data); case FBIOGET_CURSORSTATE: i = ami_get_cursorstate(&crsr.state); if (i) return i; return copy_to_user(argp, &crsr.state, sizeof(crsr.state)) ? -EFAULT : 0; case FBIOPUT_CURSORSTATE: if (copy_from_user(&crsr.state, argp, sizeof(crsr.state))) return -EFAULT; return ami_set_cursorstate(&crsr.state); } return -EINVAL;} /* * Allocate, Clear and Align a Block of Chip Memory */static u_long unaligned_chipptr = 0;static inline u_long __init chipalloc(u_long size){ size += PAGE_SIZE-1; if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size, "amifb [RAM]"))) panic("No Chip RAM for frame buffer"); memset((void *)unaligned_chipptr, 0, size); return PAGE_ALIGN(unaligned_chipptr);}static inline void chipfree(void){ if (unaligned_chipptr) amiga_chip_free((void *)unaligned_chipptr);} /* * Initialisation */static int __init amifb_init(void){ int tag, i, err = 0; u_long chipptr; u_int defmode;#ifndef MODULE char *option = NULL; if (fb_get_options("amifb", &option)) { amifb_video_off(); return -ENODEV; } amifb_setup(option);#endif if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) return -ENODEV; /* * We request all registers starting from bplpt[0] */ if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, "amifb [Denise/Lisa]")) return -EBUSY; custom.dmacon = DMAF_ALL | DMAF_MASTER; switch (amiga_chipset) {#ifdef CONFIG_FB_AMIGA_OCS case CS_OCS: strcat(fb_info.fix.id, "OCS");default_chipset: chipset = TAG_OCS; maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ maxdepth[TAG_HIRES] = 4; maxdepth[TAG_LORES] = 6; maxfmode = TAG_FMODE_1; defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC; fb_info.fix.smem_len = VIDEOMEMSIZE_OCS; break;#endif /* CONFIG_FB_AMIGA_OCS */#ifdef CONFIG_FB_AMIGA_ECS case CS_ECS: strcat(fb_info.fix.id, "ECS"); chipset = TAG_ECS; maxdepth[TAG_SHRES] = 2; maxdepth[TAG_HIRES] = 4; maxdepth[TAG_LORES] = 6; maxfmode = TAG_FMODE_1; if (AMIGAHW_PRESENT(AMBER_FF)) defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC; else defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC; if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > VIDEOMEMSIZE_ECS_1M) fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; else fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; break;#endif /* CONFIG_FB_AMIGA_ECS */#ifdef CONFIG_FB_AMIGA_AGA case CS_AGA: strcat(fb_info.fix.id, "AGA"); chipset = TAG_AGA; maxdepth[TAG_SHRES] = 8; maxdepth[TAG_HIRES] = 8; maxdepth[TAG_LORES] = 8; maxfmode = TAG_FMODE_4; defmode = DEFMODE_AGA; if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > VIDEOMEMSIZE_AGA_1M) fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; else fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; break;#endif /* CONFIG_FB_AMIGA_AGA */ default:#ifdef CONFIG_FB_AMIGA_OCS printk("Unknown graphics chipset, defaulting to OCS\n"); strcat(fb_info.fix.id, "Unknown"); goto default_chipset;#else /* CONFIG_FB_AMIGA_OCS */ err = -ENODEV; goto amifb_error;#endif /* CONFIG_FB_AMIGA_OCS */ break; } /* * Calculate the Pixel Clock Values for this Machine */ { u_long tmp = DIVUL(200000000000ULL, amiga_eclock); pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */ pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */ pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */ } /* * Replace the Tag Values with the Real Pixel Clock Values */ for (i = 0; i < NUM_TOTAL_MODES; i++) { struct fb_videomode *mode = &ami_modedb[i]; tag = mode->pixclock; if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { mode->pixclock = pixclock[tag]; } } /* * These monitor specs are for a typical Amiga monitor (e.g. A1960) */ if (fb_info.monspecs.hfmin == 0) { fb_info.monspecs.hfmin = 15000; fb_info.monspecs.hfmax = 38000; fb_info.monspecs.vfmin = 49; fb_info.monspecs.vfmax = 90; } fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; fb_info.flags = FBINFO_DEFAULT; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { err = -EINVAL; goto amifb_error; } fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, &fb_info.modelist); round_down_bpp = 0; chipptr = chipalloc(fb_info.fix.smem_len+ SPRITEMEMSIZE+ DUMMYSPRITEMEMSIZE+ COPINITSIZE+ 4*COPLISTSIZE); assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); assignchunk(cop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -