📄 fbcon.c
字号:
} if (p == (u16 *)softback_end) p = (u16 *)softback_buf; if (p == (u16 *)softback_in) p = (u16 *)conp->vc_origin; }}static int fbcon_scrolldelta(struct vc_data *conp, int lines){ int unit, offset, limit, scrollback_old; struct display *p; unit = fg_console; p = &fb_display[unit]; if (softback_top) { if (conp->vc_num != unit) return 0; if (vt_cons[unit]->vc_mode != KD_TEXT || !lines) return 0; if (logo_shown >= 0) { struct vc_data *conp2 = vc_cons[logo_shown].d; if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) conp2->vc_top = 0; if (logo_shown == unit) { unsigned long p, q; int i; p = softback_in; q = conp->vc_origin + logo_lines * conp->vc_size_row; for (i = 0; i < logo_lines; i++) { if (p == softback_top) break; if (p == softback_buf) p = softback_end; p -= conp->vc_size_row; q -= conp->vc_size_row; scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row); } softback_in = p; update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols); } logo_shown = -1; } fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); fbcon_redraw_softback(conp, p, lines); fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK); return 0; } if (!scrollback_phys_max) return -ENOSYS; scrollback_old = scrollback_current; scrollback_current -= lines; if (scrollback_current < 0) scrollback_current = 0; else if (scrollback_current > scrollback_max) scrollback_current = scrollback_max; if (scrollback_current == scrollback_old) return 0; if (!p->can_soft_blank && (console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines)) return 0; fbcon_cursor(conp, CM_ERASE); offset = p->yscroll-scrollback_current; limit = p->vrows; switch (p->scrollmode && __SCROLL_YMASK) { case __SCROLL_YWRAP: p->var.vmode |= FB_VMODE_YWRAP; break; case __SCROLL_YPAN: limit -= conp->vc_rows; p->var.vmode &= ~FB_VMODE_YWRAP; break; } if (offset < 0) offset += limit; else if (offset >= limit) offset -= limit; p->var.xoffset = 0; p->var.yoffset = offset*fontheight(p); p->fb_info->updatevar(unit, p->fb_info); if (!scrollback_current) fbcon_cursor(conp, CM_DRAW); return 0;}static int fbcon_set_origin(struct vc_data *conp){ if (softback_lines && !console_blanked) fbcon_scrolldelta(conp, softback_lines); return 0;}static inline unsigned safe_shift(unsigned d,int n){ return n<0 ? d>>-n : d<<n;}__initfunc(static int fbcon_show_logo( void )){ struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */ int depth = p->var.bits_per_pixel; int line = p->next_line; unsigned char *fb = p->screen_base; unsigned char *logo; unsigned char *dst, *src; int i, j, n, x1, y1, x; int logo_depth, done = 0; /*hacked by zerow_jp*/ int logo_w,logo_h,logo_line; /* Return if the frame buffer is not mapped */ if (!fb) return 0; /*hacked by zerow_jp*/ logo_w = LOGO_W; logo_h = LOGO_H; logo_line = LOGO_LINE; /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for * DIRECTCOLOR */ if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) || p->visual == FB_VISUAL_DIRECTCOLOR) { int is_truecolor = (p->visual == FB_VISUAL_DIRECTCOLOR); int use_256 = (!is_truecolor && depth >= 8) || (is_truecolor && depth >= 24); int first_col = use_256 ? 32 : depth > 4 ? 16 : 0; int num_cols = use_256 ? LINUX_LOGO_COLORS : 16; unsigned char *red, *green, *blue; if (use_256) { red = linux_logo_red; green = linux_logo_green; blue = linux_logo_blue; } else { red = linux_logo16_red; green = linux_logo16_green; blue = linux_logo16_blue; } for( i = 0; i < num_cols; i += n ) { n = num_cols - i; if (n > 16) /* palette_cmap provides space for only 16 colors at once */ n = 16; palette_cmap.start = first_col + i; palette_cmap.len = n; for( j = 0; j < n; ++j ) { palette_cmap.red[j] = (red[i+j] << 8) | red[i+j]; palette_cmap.green[j] = (green[i+j] << 8) | green[i+j]; palette_cmap.blue[j] = (blue[i+j] << 8) | blue[i+j]; } p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, p->fb_info); } } if (depth >= 8) { logo = linux_logo; logo_depth = 8; /*hacked by zerow_jp*/#ifdef CONFIG_MY_LOGO logo_w = MY_LOGO_W; logo_h = MY_LOGO_H; logo_line = MY_LOGO_LINE;#endif } else if (depth >= 4) { logo = linux_logo16; logo_depth = 4; } else { logo = linux_logo_bw; logo_depth = 1; } if (p->fb_info->fbops->fb_rasterimg) p->fb_info->fbops->fb_rasterimg(p->fb_info, 1);#ifdef CONFIG_MINI_LOGO if (depth >= 8){ /* paint mini_logo on linux_logo.*/ for (i = 0; i < smp_num_cpus + 1 ; i++){ unsigned char pix; x = MINI_LOGO_X + i * MINI_LOGO_ADD; if( x < 0 || x + MINI_LOGO_W > MY_LOGO_W) break ; dst = &linux_logo[MINI_LOGO_Y * logo_w + x]; for(y1 = 0; y1 < MINI_LOGO_H; y1 ++) for(x1 = 0; x1 < MINI_LOGO_W; x1 ++){ pix = mini_logo[y1 * MINI_LOGO_W + x1]; if(mini_logo[0] != pix) dst[y1 * logo_w + x1] = pix; } } }#endif for (x = 0; x < smp_num_cpus * (logo_w + 8) && x < p->var.xres - (logo_w + 8); x += (logo_w + 8)) { #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) if (p->visual == FB_VISUAL_DIRECTCOLOR) { unsigned int val; /* max. depth 32! */ int bdepth; int redshift, greenshift, blueshift; /* Bug: Doesn't obey msb_right ... (who needs that?) */ redshift = p->var.red.offset; greenshift = p->var.green.offset; blueshift = p->var.blue.offset; if (depth >= 24 && (depth % 8) == 0) { /* have at least 8 bits per color */ src = logo; bdepth = depth/8; for( y1 = 0; y1 < logo_h; y1++ ) { dst = fb + y1*line + x*bdepth; for( x1 = 0; x1 < logo_w; x1++, src++ ) { val = (*src << redshift) | (*src << greenshift) | (*src << blueshift); if (bdepth == 4 && !((long)dst & 3)) { /* Some cards require 32bit access */ *(u32 *)dst = val; dst += 4; } else {#ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i )#else for( i = bdepth-1; i >= 0; --i )#endif *dst++ = val >> (i*8); } } } } else if (depth >= 15 && depth <= 23) { /* have 5..7 bits per color, using 16 color image */ unsigned int pix; src = linux_logo16; bdepth = (depth+7)/8; /*hacked by zerow_jp*/ logo_w = LOGO_W; logo_h = LOGO_H; logo_line = LOGO_LINE; for( y1 = 0; y1 < logo_h; y1++ ) { dst = fb + y1*line + x*bdepth; for( x1 = 0; x1 < logo_w/2; x1++, src++ ) { pix = (*src >> 4) | 0x10; /* upper nibble */ val = (pix << redshift) | (pix << greenshift) | (pix << blueshift);#ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i )#else for( i = bdepth-1; i >= 0; --i )#endif *dst++ = val >> (i*8); pix = (*src & 0x0f) | 0x10; /* lower nibble */ val = (pix << redshift) | (pix << greenshift) | (pix << blueshift);#ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i )#else for( i = bdepth-1; i >= 0; --i )#endif *dst++ = val >> (i*8); } } } done = 1; }#endif#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) if ((depth % 8 == 0) && (p->visual == FB_VISUAL_TRUECOLOR)) { /* Modes without color mapping, needs special data transformation... */ unsigned int val; /* max. depth 32! */ int bdepth = depth/8; unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; unsigned char redmask, greenmask, bluemask; int redshift, greenshift, blueshift; /* Bug: Doesn't obey msb_right ... (who needs that?) */ redmask = mask[p->var.red.length < 8 ? p->var.red.length : 8]; greenmask = mask[p->var.green.length < 8 ? p->var.green.length : 8]; bluemask = mask[p->var.blue.length < 8 ? p->var.blue.length : 8]; redshift = p->var.red.offset - (8-p->var.red.length); greenshift = p->var.green.offset - (8-p->var.green.length); blueshift = p->var.blue.offset - (8-p->var.blue.length); src = logo; for( y1 = 0; y1 < logo_h; y1++ ) { dst = fb + y1*line + x*bdepth; for( x1 = 0; x1 < logo_w; x1++, src++ ) { val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) | safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) | safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift); if (bdepth == 4 && !((long)dst & 3)) { /* Some cards require 32bit access */ *(u32 *)dst = val; dst += 4; } else {#ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i )#else for( i = bdepth-1; i >= 0; --i )#endif *dst++ = val >> (i*8); } } } done = 1; }#endif#if defined(CONFIG_FBCON_CFB4) if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) { src = logo; for( y1 = 0; y1 < logo_h; y1++) { dst = fb + y1*line + x/2; for( x1 = 0; x1 < logo_w/2; x1++) { u8 q = *src++; q = (q << 4) | (q >> 4); *dst++ = q; } } done = 1; }#endif#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS) if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { /* depth 8 or more, packed, with color registers */ src = logo; for( y1 = 0; y1 < logo_h; y1++ ) { dst = fb + y1*line + x; for( x1 = 0; x1 < logo_w; x1++ ) *dst++ = *src++; } done = 1; }#endif#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \ defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ defined(CONFIG_FBCON_IPLAN2P8) if (depth >= 2 && (p->type == FB_TYPE_PLANES || p->type == FB_TYPE_INTERLEAVED_PLANES)) { /* planes (normal or interleaved), with color registers */ int bit; unsigned char val, mask; int plane = p->next_plane;#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ defined(CONFIG_FBCON_IPLAN2P8) int line_length = p->line_length; /* for support of Atari interleaved planes */#define MAP_X(x) (line_length ? (x) : ((x) & ~1)*depth + ((x) & 1))#else#define MAP_X(x) (x)#endif /* extract a bit from the source image */#define BIT(p,pix,bit) (p[pix*logo_depth/8] & \ (1 << ((8-((pix*logo_depth)&7)-logo_depth) + bit))) src = logo; for( y1 = 0; y1 < logo_h; y1++ ) { for( x1 = 0; x1 < logo_line; x1++, src += logo_depth ) { dst = fb + y1*line + MAP_X(x/8+x1); for( bit = 0; bit < logo_depth; bit++ ) { val = 0; for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) { if (BIT( src, i, bit )) val |= mask; } *dst = val; dst += plane; } } } /* fill remaining planes * special case for logo_depth == 4: we used color registers 16..31, * so fill plane 4 with 1 bits instead of 0 */ if (depth > logo_depth) { for( y1 = 0; y1 < logo_h; y1++ ) { for( x1 = 0; x1 < logo_line; x1++ ) { dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane; for( i = logo_depth; i < depth; i++, dst += plane ) *dst = (i == logo_depth && logo_depth == 4) ? 0xff : 0x00; } } } done = 1; break; }#endif#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_AFB) || \ defined(CONFIG_FBCON_ILBM) if (depth == 1 && (p->type == FB_TYPE_PACKED_PIXELS || p->type == FB_TYPE_PLANES || p->type == FB_TYPE_INTERLEAVED_PLANES)) { /* monochrome */ unsigned char inverse = p->inverse || p->visual == FB_VISUAL_MONO01 ? 0x00 : 0xff; /* can't use simply memcpy because need to apply inverse */ for( y1 = 0; y1 < logo_h; y1++ ) { src = logo + y1*logo_line; dst = fb + y1*line + x/8; for( x1 = 0; x1 < logo_line; ++x1 ) *dst++ = *src++ ^ inverse; } done = 1; }#endif#if defined(CONFIG_FBCON_VGA_PLANES) if (depth == 4 && p->type == FB_TYPE_VGA_PLANES) { outb_p(1,0x3ce); outb_p(0xf,0x3cf); outb_p(3,0x3ce); outb_p(0,0x3cf); outb_p(5,0x3ce); outb_p(0,0x3cf); src = logo; for (y1 = 0; y1 < logo_h; y1++) { for (x1 = 0; x1 < logo_w / 2; x1++) { dst = fb + y1*line + x1/4 + x/8; outb_p(0,0x3ce); outb_p(*src >> 4,0x3cf); outb_p(8,0x3ce); outb_p(1 << (7 - x1 % 4 * 2),0x3cf); *(volatile char *) dst |= 1; outb_p(0,0x3ce); outb_p(*src & 0xf,0x3cf); outb_p(8,0x3ce); outb_p(1 << (7 - (1 + x1 % 4 * 2)),0x3cf); *(volatile char *) dst |= 1; src++; } } done = 1; }#endif } if (p->fb_info->fbops->fb_rasterimg) p->fb_info->fbops->fb_rasterimg(p->fb_info, 0); /* Modes not yet supported: packed pixels with depth != 8 (does such a * thing exist in reality?) */ return done ? (logo_h + fontheight(p) - 1) / fontheight(p) : 0 ;}/* * The console `switch' structure for the frame buffer based consol
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -