Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
David S. Miller | 1774 | 95.94% | 4 | 15.38% |
Linus Torvalds (pre-git) | 43 | 2.33% | 16 | 61.54% |
David Alan Gilbert | 23 | 1.24% | 1 | 3.85% |
Rusty Russell | 4 | 0.22% | 1 | 3.85% |
Andres Salomon | 2 | 0.11% | 1 | 3.85% |
Joe Perches | 1 | 0.05% | 1 | 3.85% |
Greg Kroah-Hartman | 1 | 0.05% | 1 | 3.85% |
Sam Ravnborg | 1 | 0.05% | 1 | 3.85% |
Total | 1849 | 26 |
// SPDX-License-Identifier: GPL-2.0 /* * Procedures for drawing on the screen early on in the boot process. * * Benjamin Herrenschmidt <benh@kernel.crashing.org> */ #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> #include <linux/console.h> #include <linux/font.h> #include <asm/btext.h> #include <asm/oplib.h> #include <asm/io.h> #define NO_SCROLL #ifndef NO_SCROLL static void scrollscreen(void); #endif static void draw_byte(unsigned char c, long locX, long locY); static void draw_byte_32(const unsigned char *bits, unsigned int *base, int rb); static void draw_byte_16(const unsigned char *bits, unsigned int *base, int rb); static void draw_byte_8(const unsigned char *bits, unsigned int *base, int rb); #define __force_data __section(".data") static int g_loc_X __force_data; static int g_loc_Y __force_data; static int g_max_loc_X __force_data; static int g_max_loc_Y __force_data; static int dispDeviceRowBytes __force_data; static int dispDeviceDepth __force_data; static int dispDeviceRect[4] __force_data; static unsigned char *dispDeviceBase __force_data; static int __init btext_initialize(phandle node) { unsigned int width, height, depth, pitch; unsigned long address = 0; u32 prop; if (prom_getproperty(node, "width", (char *)&width, 4) < 0) return -EINVAL; if (prom_getproperty(node, "height", (char *)&height, 4) < 0) return -EINVAL; if (prom_getproperty(node, "depth", (char *)&depth, 4) < 0) return -EINVAL; pitch = width * ((depth + 7) / 8); if (prom_getproperty(node, "linebytes", (char *)&prop, 4) >= 0 && prop != 0xffffffffu) pitch = prop; if (pitch == 1) pitch = 0x1000; if (prom_getproperty(node, "address", (char *)&prop, 4) >= 0) address = prop; /* FIXME: Add support for PCI reg properties. Right now, only * reliable on macs */ if (address == 0) return -EINVAL; g_loc_X = 0; g_loc_Y = 0; g_max_loc_X = width / 8; g_max_loc_Y = height / 16; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; dispDeviceDepth = depth == 15 ? 16 : depth; dispDeviceRect[0] = dispDeviceRect[1] = 0; dispDeviceRect[2] = width; dispDeviceRect[3] = height; return 0; } /* Calc the base address of a given point (x,y) */ static unsigned char * calc_base(int x, int y) { unsigned char *base = dispDeviceBase; base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; return base; } static void btext_clearscreen(void) { unsigned int *base = (unsigned int *)calc_base(0, 0); unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * (dispDeviceDepth >> 3)) >> 2; int i,j; for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) { unsigned int *ptr = base; for(j=width; j; --j) *(ptr++) = 0; base += (dispDeviceRowBytes >> 2); } } #ifndef NO_SCROLL static void scrollscreen(void) { unsigned int *src = (unsigned int *)calc_base(0,16); unsigned int *dst = (unsigned int *)calc_base(0,0); unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * (dispDeviceDepth >> 3)) >> 2; int i,j; for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) { unsigned int *src_ptr = src; unsigned int *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = *(src_ptr++); src += (dispDeviceRowBytes >> 2); dst += (dispDeviceRowBytes >> 2); } for (i=0; i<16; i++) { unsigned int *dst_ptr = dst; for(j=width; j; --j) *(dst_ptr++) = 0; dst += (dispDeviceRowBytes >> 2); } } #endif /* ndef NO_SCROLL */ static void btext_drawchar(char c) { int cline = 0; #ifdef NO_SCROLL int x; #endif switch (c) { case '\b': if (g_loc_X > 0) --g_loc_X; break; case '\t': g_loc_X = (g_loc_X & -8) + 8; break; case '\r': g_loc_X = 0; break; case '\n': g_loc_X = 0; g_loc_Y++; cline = 1; break; default: draw_byte(c, g_loc_X++, g_loc_Y); } if (g_loc_X >= g_max_loc_X) { g_loc_X = 0; g_loc_Y++; cline = 1; } #ifndef NO_SCROLL while (g_loc_Y >= g_max_loc_Y) { scrollscreen(); g_loc_Y--; } #else /* wrap around from bottom to top of screen so we don't waste time scrolling each line. -- paulus. */ if (g_loc_Y >= g_max_loc_Y) g_loc_Y = 0; if (cline) { for (x = 0; x < g_max_loc_X; ++x) draw_byte(' ', x, g_loc_Y); } #endif } static void btext_drawtext(const char *c, unsigned int len) { while (len--) btext_drawchar(*c++); } static void draw_byte(unsigned char c, long locX, long locY) { unsigned char *base = calc_base(locX << 3, locY << 4); unsigned int font_index = c * 16; const unsigned char *font = font_sun_8x16.data + font_index; int rb = dispDeviceRowBytes; switch(dispDeviceDepth) { case 24: case 32: draw_byte_32(font, (unsigned int *)base, rb); break; case 15: case 16: draw_byte_16(font, (unsigned int *)base, rb); break; case 8: draw_byte_8(font, (unsigned int *)base, rb); break; } } static unsigned int expand_bits_8[16] = { 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff }; static unsigned int expand_bits_16[4] = { 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff }; static void draw_byte_32(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0xFFFFFFFFUL; int bg = 0x00000000UL; for (l = 0; l < 16; ++l) { bits = *font++; base[0] = (-(bits >> 7) & fg) ^ bg; base[1] = (-((bits >> 6) & 1) & fg) ^ bg; base[2] = (-((bits >> 5) & 1) & fg) ^ bg; base[3] = (-((bits >> 4) & 1) & fg) ^ bg; base[4] = (-((bits >> 3) & 1) & fg) ^ bg; base[5] = (-((bits >> 2) & 1) & fg) ^ bg; base[6] = (-((bits >> 1) & 1) & fg) ^ bg; base[7] = (-(bits & 1) & fg) ^ bg; base = (unsigned int *) ((char *)base + rb); } } static void draw_byte_16(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0xFFFFFFFFUL; int bg = 0x00000000UL; unsigned int *eb = (int *)expand_bits_16; for (l = 0; l < 16; ++l) { bits = *font++; base[0] = (eb[bits >> 6] & fg) ^ bg; base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; base[3] = (eb[bits & 3] & fg) ^ bg; base = (unsigned int *) ((char *)base + rb); } } static void draw_byte_8(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0x0F0F0F0FUL; int bg = 0x00000000UL; unsigned int *eb = (int *)expand_bits_8; for (l = 0; l < 16; ++l) { bits = *font++; base[0] = (eb[bits >> 4] & fg) ^ bg; base[1] = (eb[bits & 0xf] & fg) ^ bg; base = (unsigned int *) ((char *)base + rb); } } static void btext_console_write(struct console *con, const char *s, unsigned int n) { btext_drawtext(s, n); } static struct console btext_console = { .name = "btext", .write = btext_console_write, .flags = CON_PRINTBUFFER | CON_ENABLED | CON_BOOT | CON_ANYTIME, .index = 0, }; int __init btext_find_display(void) { phandle node; char type[32]; int ret; node = prom_inst2pkg(prom_stdout); if (prom_getproperty(node, "device_type", type, 32) < 0) return -ENODEV; if (strcmp(type, "display")) return -ENODEV; ret = btext_initialize(node); if (!ret) { btext_clearscreen(); register_console(&btext_console); } return ret; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1