diff --git a/ChangeLog b/ChangeLog index af9e3ee47..8c59fb243 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-06-26 Vladimir Serbinenko + + Init video early on yeeloong to avoid being rebooted by watchdog. + + * grub-core/Makefile.am (gensm712): New target. + (sm712_start.S): Likewise. + (boot/mips/loongson/fwstart.S): Depend on sm712_start.S + * grub-core/boot/mips/loongson/fwstart.S [!FULOONG2F]: Init SM712. + * grub-core/video/sm712.c [GENINIT]: Generate compact init procedure + description. + * include/grub/vga.h: Move registry definitions to... + * include/grub/vgaregs.h: ... here. + 2012-06-26 Vladimir Serbinenko * grub-core/boot/decompressor/minilib.c (grub_memcmp): Fix the compare diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 3410c2adf..7dc25197c 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -40,6 +40,15 @@ trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac $(builddir)/gentrigtables > $@ CLEANFILES += trigtables.c +gensm712: video/sm712.c + $(BUILD_CC) -DGENINIT -o $@ -I$(top_builddir) -I$(top_builddir)/include -I$(top_srcdir)/include $(CPPFLAGS) $< +CLEANFILES += gensm712 + +# trigtables.c +sm712_start.S: gensm712 video/sm712.c $(top_srcdir)/configure.ac + $(builddir)/gensm712 > $@ +CLEANFILES += sm712_start.S + # XXX Use Automake's LEX & YACC support grub_script.tab.h: script/parser.y $(YACC) -d -p grub_script_yy -b grub_script $< @@ -55,6 +64,7 @@ rs_decoder.S: $(srcdir)/lib/reed_solomon.c $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding kern/i386/pc/startup.S: $(builddir)/rs_decoder.S +boot/mips/loongson/fwstart.S: $(builddir)/sm712_start.S CLEANFILES += grub_script.yy.c grub_script.yy.h diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index 345000bd9..ec57be6a1 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -26,6 +26,12 @@ #include #include +#ifndef FULOONG2F +#include +#define GRUB_SM712_REG_BASE 0x700000 +#define GRUB_SM712_PCIID 0x0712126f +#endif + #ifdef FULOONG2F #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 @@ -748,3 +754,140 @@ continue: #endif cached_continue: +#ifndef FULOONG2F + /* We have to init video early enough or watchdog will reboot us. */ + + /* Setup PCI controller. */ + + lui $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) + lui $t1, %hi(0x8000000c) + addiu $t1, $t1, %lo(0x8000000c) + + sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0) + li $t1, 0xffffffff + sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0) + + li $t0, GRUB_MACHINE_PCI_CONTROLLER_HEADER + li $t1, (GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER \ + | GRUB_PCI_COMMAND_MEM_ENABLED) + sh $t0, GRUB_PCI_REG_COMMAND ($t1) + li $t1, ((1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) \ + | GRUB_PCI_STATUS_FAST_B2B_CAPABLE \ + | GRUB_PCI_STATUS_66MHZ_CAPABLE \ + | GRUB_PCI_STATUS_CAPABILITIES) + sh $t0, GRUB_PCI_REG_STATUS ($t1) + li $t0, 0xff + sw $t0, GRUB_PCI_REG_CACHELINE ($t1) + lui $t1, %hi(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ + | GRUB_PCI_ADDR_MEM_PREFETCH) + addiu $t1, $t1, %lo(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ + | GRUB_PCI_ADDR_MEM_PREFETCH) + sw $t0, GRUB_PCI_REG_ADDRESS_REG0 ($t1) + sw $zero, GRUB_PCI_REG_ADDRESS_REG1 ($t1) + + /* Find video. */ + /* $t4 chooses device in priority encoding. */ + /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. + This way we don't need to sacrifice a register for it. */ +retry_sm712: + /* We have only one bus (0). Function is 0. */ + lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) + lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) + lui $t3, %hi(GRUB_SM712_PCIID) + addiu $t3, $t3, %lo(GRUB_SM712_PCIID) + ori $t4, $zero, 1 +1: + andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) + /* In case of failure try again. SM712 may be slow to come up. */ + beql $t4, $zero, retry_sm712 + nop + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) + lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) + bnel $t2, $t3, 1b + sll $t4, $t4, 1 + + /* FIXME: choose address dynamically if needed. */ +#define SM712_MAP 0x04000000 + + lui $t2, %hi(SM712_MAP) + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) + sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_ADDRESS_REG0) ($t1) + + /* Set latency. */ + li $t2, 0x8 + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) + sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_CACHELINE) ($t1) + + /* Enable address spaces. */ + li $t2, 0x7 + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) + sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_COMMAND) ($t1) + + lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX) + li $t2, 0x18 + sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3) + + lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA) + li $t2, 0x11 + sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3) + + li $t2, ((((SM712_MAP & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK) \ + >> GRUB_MACHINE_PCI_WIN_SHIFT) \ + & GRUB_MACHINE_PCI_WIN_MASK)) + lui $t3, %hi(0xbfe00110) + addiu $t3, $t3, %lo(0xbfe00110) + sw $t2, 0 ($t3) + li $t2, (GRUB_MACHINE_PCI_WIN1_ADDR \ + | (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) + + lui $t3, %hi(GRUB_SM712_REG_BASE) + addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE) + addu $t2, $t2, $t3 + lui $t0, %hi(init_table - 0x20000000) + addiu $t0, $t0, %lo(init_table - 0x20000000) + lui $t1, %hi(init_table_end - 0x20000000) + addiu $t1, $t1, %lo(init_table_end - 0x20000000) + li $t5, 0x80 + addiu $t6, $t2, 0x3c0 + +table_cont: + lb $t3, 0($t0) + andi $t5, $t3, 0x80 + andi $t3, $t3, 0x7f + addu $t3, $t3, $t6 + lb $t4, 1($t0) + + bne $zero, $t5, 1f + addiu $t0, $t0, 2 + b 2f + sb $t4, 0($t3) +1: + lb $t4, 0($t3) +2: + bne $t0, $t1, table_cont + nop + + lui $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE) + addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE) + addu $t1, $t2, $t3 + sw $zero, 0xc ($t1) + sw $zero, 0x40 ($t1) + li $t3, 0x20000 + sw $t3, 0x0 ($t1) + lui $t3, %hi(0x1020100) + addiu $t3, $t3, %lo(0x1020100) + sw $t3, 0x10 ($t1) + + li $t4, 0x16 + sb $t4, GRUB_VGA_IO_SR_INDEX($t2) + + lb $t4, GRUB_VGA_IO_SR_DATA($t2) + + b init_end + nop +init_table: +#include "sm712_start.S" +init_table_end: + .align 4 +init_end: +#endif diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c index dd7e7d273..5f22c4096 100644 --- a/grub-core/video/sm712.c +++ b/grub-core/video/sm712.c @@ -18,6 +18,7 @@ #define grub_video_render_target grub_video_fbrender_target +#if !defined (TEST) && !defined(GENINIT) #include #include #include @@ -28,6 +29,15 @@ #include #include #include +#else +typedef unsigned char grub_uint8_t; +typedef unsigned short grub_uint16_t; +typedef unsigned int grub_uint32_t; +typedef int grub_err_t; +#include +#include +#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) +#endif #include "sm712_init.c" @@ -194,16 +204,20 @@ static struct static struct { +#if !defined (TEST) && !defined(GENINIT) struct grub_video_mode_info mode_info; +#endif volatile grub_uint8_t *ptr; grub_uint8_t *cached_ptr; int mapped; grub_uint32_t base; +#if !defined (TEST) && !defined(GENINIT) grub_pci_device_t dev; +#endif } framebuffer; -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) static grub_err_t grub_video_sm712_video_init (void) { @@ -232,6 +246,10 @@ grub_sm712_write_reg (grub_uint8_t val, grub_uint16_t addr) { #ifdef TEST printf (" {1, 0x%x, 0x%x},\n", addr, val); +#elif defined (GENINIT) + printf (" .byte 0x%02x, 0x%02x\n", (addr - 0x3c0), val); + if ((addr - 0x3c0) & ~0x7f) + printf ("FAIL\n"); #else *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + addr) = val; @@ -243,6 +261,10 @@ grub_sm712_read_reg (grub_uint16_t addr) { #ifdef TEST printf (" {-1, 0x%x, 0x5},\n", addr); +#elif defined (GENINIT) + if ((addr - 0x3c0) & ~0x7f) + printf ("FAIL\n"); + printf (" .byte 0x%04x, 0x00\n", (addr - 0x3c0) | 0x80); #else return *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + addr); @@ -342,12 +364,12 @@ static grub_err_t grub_video_sm712_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) { + unsigned i; +#if !defined (TEST) && !defined(GENINIT) int depth; grub_err_t err; int found = 0; - unsigned i; -#ifndef TEST auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) { @@ -382,7 +404,6 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, grub_pci_iterate (find_card); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); -#endif /* Fill mode info details. */ framebuffer.mode_info.width = 1024; framebuffer.mode_info.height = 600; @@ -401,12 +422,11 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, framebuffer.mode_info.blue_field_pos = 0; framebuffer.mode_info.reserved_mask_size = 0; framebuffer.mode_info.reserved_field_pos = 0; -#ifndef TEST framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); #endif -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) if (found && framebuffer.base == 0) { grub_pci_address_t addr; @@ -427,7 +447,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, #endif /* We can safely discard volatile attribute. */ -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) framebuffer.ptr = grub_pci_device_map_range (framebuffer.dev, framebuffer.base, @@ -440,12 +460,12 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, framebuffer.mapped = 1; /* Initialise SM712. */ -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) /* FIXME */ grub_vga_sr_write (0x11, 0x18); #endif -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) /* Prevent garbage from appearing on the screen. */ grub_memset ((void *) framebuffer.cached_ptr, 0, framebuffer.mode_info.height * framebuffer.mode_info.pitch); @@ -687,7 +707,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, | GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) /* Undocumented? */ *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c00c) = 0; *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c040) = 0; @@ -697,7 +717,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, (void) grub_sm712_sr_read (0x16); -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) err = grub_video_fb_setup (mode_type, mode_mask, &framebuffer.mode_info, framebuffer.cached_ptr, NULL, NULL); @@ -707,11 +727,13 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, grub_video_fbstd_colors); -#endif return err; +#else + return 0; +#endif } -#ifndef TEST +#if !defined (TEST) && !defined(GENINIT) static grub_err_t grub_video_sm712_swap_buffers (void) diff --git a/include/grub/vga.h b/include/grub/vga.h index 58ec3ba15..81d40a1dd 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -26,208 +26,7 @@ #define GRUB_MACHINE_PCI_IO_BASE 0xb4000000 #endif -enum - { - GRUB_VGA_IO_ARX = 0x3c0, - GRUB_VGA_IO_ARX_READ = 0x3c1, - GRUB_VGA_IO_MISC_WRITE = 0x3c2, - GRUB_VGA_IO_SR_INDEX = 0x3c4, - GRUB_VGA_IO_SR_DATA = 0x3c5, - GRUB_VGA_IO_PIXEL_MASK = 0x3c6, - GRUB_VGA_IO_PALLETTE_READ_INDEX = 0x3c7, - GRUB_VGA_IO_PALLETTE_WRITE_INDEX = 0x3c8, - GRUB_VGA_IO_PALLETTE_DATA = 0x3c9, - GRUB_VGA_IO_GR_INDEX = 0x3ce, - GRUB_VGA_IO_GR_DATA = 0x3cf, - GRUB_VGA_IO_CR_INDEX = 0x3d4, - GRUB_VGA_IO_CR_DATA = 0x3d5, - GRUB_VGA_IO_INPUT_STATUS1_REGISTER = 0x3da - }; - -#define GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT 0x08 - -enum - { - GRUB_VGA_CR_HTOTAL = 0x00, - GRUB_VGA_CR_HORIZ_END = 0x01, - GRUB_VGA_CR_HBLANK_START = 0x02, - GRUB_VGA_CR_HBLANK_END = 0x03, - GRUB_VGA_CR_HORIZ_SYNC_PULSE_START = 0x04, - GRUB_VGA_CR_HORIZ_SYNC_PULSE_END = 0x05, - GRUB_VGA_CR_VERT_TOTAL = 0x06, - GRUB_VGA_CR_OVERFLOW = 0x07, - GRUB_VGA_CR_BYTE_PANNING = 0x08, - GRUB_VGA_CR_CELL_HEIGHT = 0x09, - GRUB_VGA_CR_CURSOR_START = 0x0a, - GRUB_VGA_CR_CURSOR_END = 0x0b, - GRUB_VGA_CR_START_ADDR_HIGH_REGISTER = 0x0c, - GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d, - GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e, - GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f, - GRUB_VGA_CR_VSYNC_START = 0x10, - GRUB_VGA_CR_VSYNC_END = 0x11, - GRUB_VGA_CR_VDISPLAY_END = 0x12, - GRUB_VGA_CR_PITCH = 0x13, - GRUB_VGA_CR_UNDERLINE_LOCATION = 0x14, - GRUB_VGA_CR_VERTICAL_BLANK_START = 0x15, - GRUB_VGA_CR_VERTICAL_BLANK_END = 0x16, - GRUB_VGA_CR_MODE = 0x17, - GRUB_VGA_CR_LINE_COMPARE = 0x18, - }; - -enum - { - GRUB_VGA_CR_BYTE_PANNING_NORMAL = 0 - }; - -enum - { - GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE = 0x40 - }; - -enum - { - GRUB_VGA_IO_MISC_COLOR = 0x01, - GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02, - GRUB_VGA_IO_MISC_28MHZ = 0x04, - GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, - GRUB_VGA_IO_MISC_UPPER_64K = 0x20, - GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40, - GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80, - }; - -enum - { - GRUB_VGA_ARX_MODE = 0x10, - GRUB_VGA_ARX_OVERSCAN = 0x11, - GRUB_VGA_ARX_COLOR_PLANE_ENABLE = 0x12, - GRUB_VGA_ARX_HORIZONTAL_PANNING = 0x13, - GRUB_VGA_ARX_COLOR_SELECT = 0x14 - }; - -enum - { - GRUB_VGA_ARX_MODE_TEXT = 0x00, - GRUB_VGA_ARX_MODE_GRAPHICS = 0x01, - GRUB_VGA_ARX_MODE_ENABLE_256COLOR = 0x40 - }; - -#define GRUB_VGA_CR_WIDTH_DIVISOR 8 - -#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7 -#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02 -#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3 -#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40 - -#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8 -#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01 -#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4 -#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20 - -#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6 -#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04 -#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2 -#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80 - -#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7 -#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02 -#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3 -#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0 -#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 -#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 - -#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 -#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 -#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20 -#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4 -#define GRUB_VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80 -enum - { - GRUB_VGA_CR_CURSOR_START_DISABLE = (1 << 5) - }; - -#define GRUB_VGA_CR_PITCH_DIVISOR 8 - -enum - { - GRUB_VGA_CR_MODE_NO_CGA = 0x01, - GRUB_VGA_CR_MODE_NO_HERCULES = 0x02, - GRUB_VGA_CR_MODE_ADDRESS_WRAP = 0x20, - GRUB_VGA_CR_MODE_BYTE_MODE = 0x40, - GRUB_VGA_CR_MODE_TIMING_ENABLE = 0x80 - }; - -enum - { - GRUB_VGA_SR_RESET = 0, - GRUB_VGA_SR_CLOCKING_MODE = 1, - GRUB_VGA_SR_MAP_MASK_REGISTER = 2, - GRUB_VGA_SR_CHAR_MAP_SELECT = 3, - GRUB_VGA_SR_MEMORY_MODE = 4, - }; - -enum - { - GRUB_VGA_SR_RESET_ASYNC = 1, - GRUB_VGA_SR_RESET_SYNC = 2 - }; - -enum - { - GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK = 1 - }; - -enum - { - GRUB_VGA_SR_MEMORY_MODE_NORMAL = 0, - GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY = 2, - GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING = 4, - GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8, - }; - -enum - { - GRUB_VGA_GR_SET_RESET_PLANE = 0, - GRUB_VGA_GR_SET_RESET_PLANE_ENABLE = 1, - GRUB_VGA_GR_COLOR_COMPARE = 2, - GRUB_VGA_GR_DATA_ROTATE = 3, - GRUB_VGA_GR_READ_MAP_REGISTER = 4, - GRUB_VGA_GR_MODE = 5, - GRUB_VGA_GR_GR6 = 6, - GRUB_VGA_GR_COLOR_COMPARE_DISABLE = 7, - GRUB_VGA_GR_BITMASK = 8, - GRUB_VGA_GR_MAX - }; - -#define GRUB_VGA_ALL_PLANES 0xf -#define GRUB_VGA_NO_PLANES 0x0 - -enum - { - GRUB_VGA_GR_DATA_ROTATE_NOP = 0 - }; - -enum - { - GRUB_VGA_TEXT_TEXT_PLANE = 0, - GRUB_VGA_TEXT_ATTR_PLANE = 1, - GRUB_VGA_TEXT_FONT_PLANE = 2 - }; - -enum - { - GRUB_VGA_GR_GR6_GRAPHICS_MODE = 1, - GRUB_VGA_GR_GR6_MMAP_A0 = (1 << 2), - GRUB_VGA_GR_GR6_MMAP_CGA = (3 << 2) - }; - -enum - { - GRUB_VGA_GR_MODE_READ_MODE1 = 0x08, - GRUB_VGA_GR_MODE_ODD_EVEN = 0x10, - GRUB_VGA_GR_MODE_ODD_EVEN_SHIFT = 0x20, - GRUB_VGA_GR_MODE_256_COLOR = 0x40 - }; +#include static inline void grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr) @@ -313,77 +112,4 @@ grub_vga_read_arx (grub_uint8_t addr) return val; } -struct grub_video_hw_config -{ - unsigned vertical_total; - unsigned vertical_blank_start; - unsigned vertical_blank_end; - unsigned vertical_sync_start; - unsigned vertical_sync_end; - unsigned line_compare; - unsigned vdisplay_end; - unsigned pitch; - unsigned horizontal_total; - unsigned horizontal_blank_start; - unsigned horizontal_blank_end; - unsigned horizontal_sync_pulse_start; - unsigned horizontal_sync_pulse_end; - unsigned horizontal_end; -}; - -static inline void -grub_vga_set_geometry (struct grub_video_hw_config *config, - void (*cr_write) (grub_uint8_t val, grub_uint8_t addr)) -{ - unsigned vertical_total = config->vertical_total - 2; - unsigned vertical_blank_start = config->vertical_blank_start - 1; - unsigned vdisplay_end = config->vdisplay_end - 1; - grub_uint8_t overflow, cell_height_reg; - - /* Disable CR0-7 write protection. */ - cr_write (0, GRUB_VGA_CR_VSYNC_END); - - overflow = ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK) - | ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK) - | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK) - | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) - | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK) - | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK) - | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) - & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) - | ((config->line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK); - - cell_height_reg = ((vertical_blank_start - >> GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT) - & GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK) - | ((config->line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK); - - cr_write (config->horizontal_total - 1, GRUB_VGA_CR_HTOTAL); - cr_write (config->horizontal_end - 1, GRUB_VGA_CR_HORIZ_END); - cr_write (config->horizontal_blank_start - 1, GRUB_VGA_CR_HBLANK_START); - cr_write (config->horizontal_blank_end, GRUB_VGA_CR_HBLANK_END); - cr_write (config->horizontal_sync_pulse_start, - GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); - cr_write (config->horizontal_sync_pulse_end, - GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); - cr_write (vertical_total & 0xff, GRUB_VGA_CR_VERT_TOTAL); - cr_write (overflow, GRUB_VGA_CR_OVERFLOW); - cr_write (cell_height_reg, GRUB_VGA_CR_CELL_HEIGHT); - cr_write (config->vertical_sync_start & 0xff, GRUB_VGA_CR_VSYNC_START); - cr_write (config->vertical_sync_end & 0x0f, GRUB_VGA_CR_VSYNC_END); - cr_write (vdisplay_end & 0xff, GRUB_VGA_CR_VDISPLAY_END); - cr_write (config->pitch & 0xff, GRUB_VGA_CR_PITCH); - cr_write (vertical_blank_start & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_START); - cr_write (config->vertical_blank_end & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_END); - cr_write (config->line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); -} - #endif diff --git a/include/grub/vgaregs.h b/include/grub/vgaregs.h new file mode 100644 index 000000000..a7b13eead --- /dev/null +++ b/include/grub/vgaregs.h @@ -0,0 +1,305 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_VGAREGS_HEADER +#define GRUB_VGAREGS_HEADER 1 + +#ifdef ASM_FILE +#define GRUB_VGA_IO_SR_INDEX 0x3c4 +#define GRUB_VGA_IO_SR_DATA 0x3c5 +#else + +enum + { + GRUB_VGA_IO_ARX = 0x3c0, + GRUB_VGA_IO_ARX_READ = 0x3c1, + GRUB_VGA_IO_MISC_WRITE = 0x3c2, + GRUB_VGA_IO_SR_INDEX = 0x3c4, + GRUB_VGA_IO_SR_DATA = 0x3c5, + GRUB_VGA_IO_PIXEL_MASK = 0x3c6, + GRUB_VGA_IO_PALLETTE_READ_INDEX = 0x3c7, + GRUB_VGA_IO_PALLETTE_WRITE_INDEX = 0x3c8, + GRUB_VGA_IO_PALLETTE_DATA = 0x3c9, + GRUB_VGA_IO_GR_INDEX = 0x3ce, + GRUB_VGA_IO_GR_DATA = 0x3cf, + GRUB_VGA_IO_CR_INDEX = 0x3d4, + GRUB_VGA_IO_CR_DATA = 0x3d5, + GRUB_VGA_IO_INPUT_STATUS1_REGISTER = 0x3da + }; + +#define GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT 0x08 + +enum + { + GRUB_VGA_CR_HTOTAL = 0x00, + GRUB_VGA_CR_HORIZ_END = 0x01, + GRUB_VGA_CR_HBLANK_START = 0x02, + GRUB_VGA_CR_HBLANK_END = 0x03, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START = 0x04, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END = 0x05, + GRUB_VGA_CR_VERT_TOTAL = 0x06, + GRUB_VGA_CR_OVERFLOW = 0x07, + GRUB_VGA_CR_BYTE_PANNING = 0x08, + GRUB_VGA_CR_CELL_HEIGHT = 0x09, + GRUB_VGA_CR_CURSOR_START = 0x0a, + GRUB_VGA_CR_CURSOR_END = 0x0b, + GRUB_VGA_CR_START_ADDR_HIGH_REGISTER = 0x0c, + GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d, + GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e, + GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f, + GRUB_VGA_CR_VSYNC_START = 0x10, + GRUB_VGA_CR_VSYNC_END = 0x11, + GRUB_VGA_CR_VDISPLAY_END = 0x12, + GRUB_VGA_CR_PITCH = 0x13, + GRUB_VGA_CR_UNDERLINE_LOCATION = 0x14, + GRUB_VGA_CR_VERTICAL_BLANK_START = 0x15, + GRUB_VGA_CR_VERTICAL_BLANK_END = 0x16, + GRUB_VGA_CR_MODE = 0x17, + GRUB_VGA_CR_LINE_COMPARE = 0x18, + }; + +enum + { + GRUB_VGA_CR_BYTE_PANNING_NORMAL = 0 + }; + +enum + { + GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE = 0x40 + }; + +enum + { + GRUB_VGA_IO_MISC_COLOR = 0x01, + GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02, + GRUB_VGA_IO_MISC_28MHZ = 0x04, + GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, + GRUB_VGA_IO_MISC_UPPER_64K = 0x20, + GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40, + GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80, + }; + +enum + { + GRUB_VGA_ARX_MODE = 0x10, + GRUB_VGA_ARX_OVERSCAN = 0x11, + GRUB_VGA_ARX_COLOR_PLANE_ENABLE = 0x12, + GRUB_VGA_ARX_HORIZONTAL_PANNING = 0x13, + GRUB_VGA_ARX_COLOR_SELECT = 0x14 + }; + +enum + { + GRUB_VGA_ARX_MODE_TEXT = 0x00, + GRUB_VGA_ARX_MODE_GRAPHICS = 0x01, + GRUB_VGA_ARX_MODE_ENABLE_256COLOR = 0x40 + }; + +#define GRUB_VGA_CR_WIDTH_DIVISOR 8 + +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40 + +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20 + +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80 + +#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0 +#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 +#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 + +#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 +#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20 +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4 +#define GRUB_VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80 +enum + { + GRUB_VGA_CR_CURSOR_START_DISABLE = (1 << 5) + }; + +#define GRUB_VGA_CR_PITCH_DIVISOR 8 + +enum + { + GRUB_VGA_CR_MODE_NO_CGA = 0x01, + GRUB_VGA_CR_MODE_NO_HERCULES = 0x02, + GRUB_VGA_CR_MODE_ADDRESS_WRAP = 0x20, + GRUB_VGA_CR_MODE_BYTE_MODE = 0x40, + GRUB_VGA_CR_MODE_TIMING_ENABLE = 0x80 + }; + +enum + { + GRUB_VGA_SR_RESET = 0, + GRUB_VGA_SR_CLOCKING_MODE = 1, + GRUB_VGA_SR_MAP_MASK_REGISTER = 2, + GRUB_VGA_SR_CHAR_MAP_SELECT = 3, + GRUB_VGA_SR_MEMORY_MODE = 4, + }; + +enum + { + GRUB_VGA_SR_RESET_ASYNC = 1, + GRUB_VGA_SR_RESET_SYNC = 2 + }; + +enum + { + GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK = 1 + }; + +enum + { + GRUB_VGA_SR_MEMORY_MODE_NORMAL = 0, + GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY = 2, + GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING = 4, + GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8, + }; + +enum + { + GRUB_VGA_GR_SET_RESET_PLANE = 0, + GRUB_VGA_GR_SET_RESET_PLANE_ENABLE = 1, + GRUB_VGA_GR_COLOR_COMPARE = 2, + GRUB_VGA_GR_DATA_ROTATE = 3, + GRUB_VGA_GR_READ_MAP_REGISTER = 4, + GRUB_VGA_GR_MODE = 5, + GRUB_VGA_GR_GR6 = 6, + GRUB_VGA_GR_COLOR_COMPARE_DISABLE = 7, + GRUB_VGA_GR_BITMASK = 8, + GRUB_VGA_GR_MAX + }; + +#define GRUB_VGA_ALL_PLANES 0xf +#define GRUB_VGA_NO_PLANES 0x0 + +enum + { + GRUB_VGA_GR_DATA_ROTATE_NOP = 0 + }; + +enum + { + GRUB_VGA_TEXT_TEXT_PLANE = 0, + GRUB_VGA_TEXT_ATTR_PLANE = 1, + GRUB_VGA_TEXT_FONT_PLANE = 2 + }; + +enum + { + GRUB_VGA_GR_GR6_GRAPHICS_MODE = 1, + GRUB_VGA_GR_GR6_MMAP_A0 = (1 << 2), + GRUB_VGA_GR_GR6_MMAP_CGA = (3 << 2) + }; + +enum + { + GRUB_VGA_GR_MODE_READ_MODE1 = 0x08, + GRUB_VGA_GR_MODE_ODD_EVEN = 0x10, + GRUB_VGA_GR_MODE_ODD_EVEN_SHIFT = 0x20, + GRUB_VGA_GR_MODE_256_COLOR = 0x40 + }; + +struct grub_video_hw_config +{ + unsigned vertical_total; + unsigned vertical_blank_start; + unsigned vertical_blank_end; + unsigned vertical_sync_start; + unsigned vertical_sync_end; + unsigned line_compare; + unsigned vdisplay_end; + unsigned pitch; + unsigned horizontal_total; + unsigned horizontal_blank_start; + unsigned horizontal_blank_end; + unsigned horizontal_sync_pulse_start; + unsigned horizontal_sync_pulse_end; + unsigned horizontal_end; +}; + +static inline void +grub_vga_set_geometry (struct grub_video_hw_config *config, + void (*cr_write) (grub_uint8_t val, grub_uint8_t addr)) +{ + unsigned vertical_total = config->vertical_total - 2; + unsigned vertical_blank_start = config->vertical_blank_start - 1; + unsigned vdisplay_end = config->vdisplay_end - 1; + grub_uint8_t overflow, cell_height_reg; + + /* Disable CR0-7 write protection. */ + cr_write (0, GRUB_VGA_CR_VSYNC_END); + + overflow = ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK) + | ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((config->line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK); + + cell_height_reg = ((vertical_blank_start + >> GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK) + | ((config->line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK); + + cr_write (config->horizontal_total - 1, GRUB_VGA_CR_HTOTAL); + cr_write (config->horizontal_end - 1, GRUB_VGA_CR_HORIZ_END); + cr_write (config->horizontal_blank_start - 1, GRUB_VGA_CR_HBLANK_START); + cr_write (config->horizontal_blank_end, GRUB_VGA_CR_HBLANK_END); + cr_write (config->horizontal_sync_pulse_start, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); + cr_write (config->horizontal_sync_pulse_end, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); + cr_write (vertical_total & 0xff, GRUB_VGA_CR_VERT_TOTAL); + cr_write (overflow, GRUB_VGA_CR_OVERFLOW); + cr_write (cell_height_reg, GRUB_VGA_CR_CELL_HEIGHT); + cr_write (config->vertical_sync_start & 0xff, GRUB_VGA_CR_VSYNC_START); + cr_write (config->vertical_sync_end & 0x0f, GRUB_VGA_CR_VSYNC_END); + cr_write (vdisplay_end & 0xff, GRUB_VGA_CR_VDISPLAY_END); + cr_write (config->pitch & 0xff, GRUB_VGA_CR_PITCH); + cr_write (vertical_blank_start & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_START); + cr_write (config->vertical_blank_end & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_END); + cr_write (config->line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); +} + +#endif + +#endif