📄 leofb.c
字号:
/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $ * leofb.c: Leo (ZX) 24/8bit frame buffer driver * * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) */#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/selection.h>#include <video/sbusfb.h>#include <asm/io.h>#define LEO_OFF_LC_SS0_KRN 0x00200000UL#define LEO_OFF_LC_SS0_USR 0x00201000UL#define LEO_OFF_LC_SS1_KRN 0x01200000UL#define LEO_OFF_LC_SS1_USR 0x01201000UL#define LEO_OFF_LD_SS0 0x00400000UL#define LEO_OFF_LD_SS1 0x01400000UL#define LEO_OFF_LD_GBL 0x00401000UL#define LEO_OFF_LX_KRN 0x00600000UL#define LEO_OFF_LX_CURSOR 0x00601000UL#define LEO_OFF_SS0 0x00800000UL#define LEO_OFF_SS1 0x01800000UL#define LEO_OFF_UNK 0x00602000UL#define LEO_OFF_UNK2 0x00000000UL#define LEO_CUR_ENABLE 0x00000080#define LEO_CUR_UPDATE 0x00000030#define LEO_CUR_PROGRESS 0x00000006#define LEO_CUR_UPDATECMAP 0x00000003#define LEO_CUR_TYPE_MASK 0x00000000#define LEO_CUR_TYPE_IMAGE 0x00000020#define LEO_CUR_TYPE_CMAP 0x00000050struct leo_cursor { u8 xxx0[16]; volatile u32 cur_type; volatile u32 cur_misc; volatile u32 cur_cursxy; volatile u32 cur_data;};#define LEO_KRN_TYPE_CLUT0 0x00001000#define LEO_KRN_TYPE_CLUT1 0x00001001#define LEO_KRN_TYPE_CLUT2 0x00001002#define LEO_KRN_TYPE_WID 0x00001003#define LEO_KRN_TYPE_UNK 0x00001006#define LEO_KRN_TYPE_VIDEO 0x00002003#define LEO_KRN_TYPE_CLUTDATA 0x00004000#define LEO_KRN_CSR_ENABLE 0x00000008#define LEO_KRN_CSR_PROGRESS 0x00000004#define LEO_KRN_CSR_UNK 0x00000002#define LEO_KRN_CSR_UNK2 0x00000001struct leo_lx_krn { volatile u32 krn_type; volatile u32 krn_csr; volatile u32 krn_value;};struct leo_lc_ss0_krn { volatile u32 misc; u8 xxx0[0x800-4]; volatile u32 rev;};struct leo_lc_ss0_usr { volatile u32 csr; volatile u32 addrspace; volatile u32 fontmsk; volatile u32 fontt; volatile u32 extent; volatile u32 src; u32 dst; volatile u32 copy; volatile u32 fill;};struct leo_lc_ss1_krn { u8 unknown;};struct leo_lc_ss1_usr { u8 unknown;};struct leo_ld { u8 xxx0[0xe00]; volatile u32 csr; volatile u32 wid; volatile u32 wmask; volatile u32 widclip; volatile u32 vclipmin; volatile u32 vclipmax; volatile u32 pickmin; /* SS1 only */ volatile u32 pickmax; /* SS1 only */ volatile u32 fg; volatile u32 bg; volatile u32 src; /* Copy/Scroll (SS0 only) */ volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ u32 xxx1[3]; volatile u32 setsem; /* SS1 only */ volatile u32 clrsem; /* SS1 only */ volatile u32 clrpick; /* SS1 only */ volatile u32 clrdat; /* SS1 only */ volatile u32 alpha; /* SS1 only */ u8 xxx2[0x2c]; volatile u32 winbg; volatile u32 planemask; volatile u32 rop; volatile u32 z; volatile u32 dczf; /* SS1 only */ volatile u32 dczb; /* SS1 only */ volatile u32 dcs; /* SS1 only */ volatile u32 dczs; /* SS1 only */ volatile u32 pickfb; /* SS1 only */ volatile u32 pickbb; /* SS1 only */ volatile u32 dcfc; /* SS1 only */ volatile u32 forcecol; /* SS1 only */ volatile u32 door[8]; /* SS1 only */ volatile u32 pick[5]; /* SS1 only */};#define LEO_SS1_MISC_ENABLE 0x00000001#define LEO_SS1_MISC_STEREO 0x00000002struct leo_ld_ss1 { u8 xxx0[0xef4]; volatile u32 ss1_misc;};struct leo_ld_gbl { u8 unknown;};static struct sbus_mmap_map leo_mmap_map[] = { { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 }, { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 }, { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 }, { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 }, { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 }, { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 }, { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 }, { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 }, { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 }, { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 }, { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 }, { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 }, { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 }, { 0, 0, 0 }};static void leo_setup(struct display *p){ p->next_line = 8192; p->next_plane = 0;}static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; int x, y, w, h; int i; spin_lock_irqsave(&fb->lock, flags); do { i = sbus_readl(&us->csr); } while (i & 0x20000000); sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); } else { y = sy * fontheight(p); h = height * fontheight(p); } if (fontwidthlog(p)) { x = sx << fontwidthlog(p); w = width << fontwidthlog(p); } else { x = sx * fontwidth(p); w = width * fontwidth(p); } sbus_writel((w - 1) | ((h - 1) << 11), &us->extent); sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000, &us->fill); spin_unlock_irqrestore(&fb->lock, flags);}static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes){ int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); sbus_writel((attr_bgcol(p,s)<<24), &ss->fg); while (count-- > 0) { do { i = sbus_readl(&us->csr); } while (i & 0x20000000); sbus_writel((boxes[2] - boxes[0] - 1) | ((boxes[3] - boxes[1] - 1) << 11), &us->extent); sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000, &us->fill); boxes += 4; } spin_unlock_irqrestore(&fb->lock, flags);}static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; int i, x, y; u8 *fd; u32 *u; spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = yy << (fontheightlog(p) + 11); i = (c & p->charmask) << fontheightlog(p); } else { y = (yy * fontheight(p)) << 11; i = (c & p->charmask) * fontheight(p); } if (fontwidth(p) <= 8) fd = p->fontdata + i; else fd = p->fontdata + (i << 1); if (fontwidthlog(p)) x = xx << fontwidthlog(p); else x = xx * fontwidth(p); do { i = sbus_readl(&us->csr); } while (i & 0x20000000); sbus_writel(attr_fgcol(p,c) << 24, &ss->fg); sbus_writel(attr_bgcol(p,c) << 24, &ss->bg); sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk); u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val = *fd++ << 24; sbus_writel(val, u); } } else { for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val = *(u16 *)fd << 16; sbus_writel(val, u); fd += 2; } } spin_unlock_irqrestore(&fb->lock, flags);}static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0; unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u16 c; u32 *u; spin_lock_irqsave(&fb->lock, flags); do { i = sbus_readl(&us->csr); } while (i & 0x20000000); c = scr_readw(s); sbus_writel(attr_fgcol(p, c) << 24, &ss->fg); sbus_writel(attr_bgcol(p, c) << 24, &ss->bg); sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk); if (fontwidthlog(p)) x = (xx << fontwidthlog(p)); else x = xx * fontwidth(p); if (fontheightlog(p)) y = yy << (fontheightlog(p) + 11); else y = (yy * fontheight(p)) << 11; u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk); x = 4*fontwidth(p) - fontheight(p)*2048; while (count >= 4) { count -= 4; if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val; val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); sbus_writel(val, u); } u += x; } else { for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val; val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); sbus_writel(val, u); } u += x; } } } else { sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk); x = 2*fontwidth(p) - fontheight(p)*2048; while (count >= 2) { count -= 2; if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val; val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); sbus_writel(val, u); fd1 += 2; fd2 += 2; } u += x; } } sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk); x = fontwidth(p) - fontheight(p)*2048; while (count) { count--; if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++, u += 2048) { u32 val = *fd1++ << 24; sbus_writel(val, u); } } else { fd1 = p->fontdata + (i << 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -