From 94bf3dd564d4bd4aaebfb69159efb1499fc5a351 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 01:32:07 +0200 Subject: [PATCH 01/10] somewhat working video_cirrus implementation --- conf/i386.rmk | 5 + include/grub/video.h | 3 +- video/cirrus.c | 538 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 video/cirrus.c diff --git a/conf/i386.rmk b/conf/i386.rmk index 02ce39817..ce5d42f0f 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -15,6 +15,11 @@ vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c vga_text_mod_CFLAGS = $(COMMON_CFLAGS) vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += video_cirrus.mod +video_cirrus_mod_SOURCES = video/cirrus.c +video_cirrus_mod_CFLAGS = $(COMMON_CFLAGS) +video_cirrus_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += relocator.mod relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S relocator_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/include/grub/video.h b/include/grub/video.h index 5fd7e0c47..08ee54938 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -182,7 +182,8 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_EFI_UGA, GRUB_VIDEO_DRIVER_EFI_GOP, GRUB_VIDEO_DRIVER_SM712, - GRUB_VIDEO_DRIVER_VGA + GRUB_VIDEO_DRIVER_VGA, + GRUB_VIDEO_DRIVER_CIRRUS } grub_video_driver_id_t; struct grub_video_adapter diff --git a/video/cirrus.c b/video/cirrus.c new file mode 100644 index 000000000..ae1bd9940 --- /dev/null +++ b/video/cirrus.c @@ -0,0 +1,538 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,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 . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct +{ + struct grub_video_mode_info mode_info; + struct grub_video_render_target *render_target; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#define CIRRUS_APERTURE_SIZE 0x200000 + +#define GR_INDEX 0x3ce +#define GR_DATA 0x3cf +#define CR_INDEX 0x3d4 +#define CR_DATA 0x3d5 +#define SR_INDEX 0x3c4 +#define SR_DATA 0x3c5 + +#define CIRRUS_MAX_WIDTH 0x800 +#define CIRRUS_WIDTH_DIVISOR 8 +#define CIRRUS_MAX_HEIGHT 0x800 +#define CIRRUS_MAX_PITCH (0x1ff * CIRRUS_WIDTH_DIVISOR) + +enum + { + CIRRUS_GR_MODE = 5, + CIRRUS_GR_GR6 = 6, + CIRRUS_GR_MAX + }; + +#define CIRRUS_GR_GR6_GRAPHICS_MODE 1 + +#define CIRRUS_GR_MODE_256_COLOR 0x40 +#define CIRRUS_GR_MODE_READ_MODE1 0x08 + +enum + { + CIRRUS_CR_WIDTH = 0x01, + CIRRUS_CR_OVERFLOW = 0x07, + CIRRUS_CR_CELL_HEIGHT = 0x09, + CIRRUS_CR_VSYNC_END = 0x11, + CIRRUS_CR_HEIGHT = 0x12, + CIRRUS_CR_PITCH = 0x13, + CIRRUS_CR_MODE = 0x17, + CIRRUS_CR_LINE_COMPARE = 0x18, + CIRRUS_CR_EXTENDED_DISPLAY = 0x1b, + CIRRUS_CR_MAX + }; + +#define CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 +#define CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 + +#define CIRRUS_CR_OVERFLOW_HEIGHT1_SHIFT 7 +#define CIRRUS_CR_OVERFLOW_HEIGHT1_MASK 0x02 +#define CIRRUS_CR_OVERFLOW_HEIGHT2_SHIFT 3 +#define CIRRUS_CR_OVERFLOW_HEIGHT2_MASK 0xc0 +#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 +#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 + +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 + +#define CIRRUS_CR_MODE_TIMING_ENABLE 0x80 +#define CIRRUS_CR_MODE_BYTE_MODE 0x40 +#define CIRRUS_CR_MODE_NO_HERCULES 0x02 +#define CIRRUS_CR_MODE_NO_CGA 0x01 + +enum + { + CIRRUS_SR_MEMORY_MODE = 4, + CIRRUS_SR_EXTENDED_MODE = 7, + CIRRUS_SR_MAX + }; +#define CIRRUS_SR_MEMORY_MODE_CHAIN4 8 +#define CIRRUS_SR_MEMORY_MODE_NORMAL 0 +#define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0 +#define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01 +#define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04 +#define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06 +#define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08 + +static void +gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GR_INDEX); + grub_outb (val, GR_DATA); +} + +static grub_uint8_t +gr_read (grub_uint8_t addr) +{ + grub_outb (addr, GR_INDEX); + return grub_inb (GR_DATA); +} + +static void +cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, CR_INDEX); + grub_outb (val, CR_DATA); +} + +static grub_uint8_t +cr_read (grub_uint8_t addr) +{ + grub_outb (addr, CR_INDEX); + return grub_inb (CR_DATA); +} + +static void +sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, SR_INDEX); + grub_outb (val, SR_DATA); +} + +static grub_uint8_t +sr_read (grub_uint8_t addr) +{ + grub_outb (addr, SR_INDEX); + return grub_inb (SR_DATA); +} + +static void +write_hidden_dac (grub_uint8_t data) +{ + grub_inb (0x3c8); + grub_inb (0x3c6); + grub_inb (0x3c6); + grub_inb (0x3c6); + grub_inb (0x3c6); + grub_outb (data, 0x3c6); +} + +static grub_uint8_t +read_hidden_dac (void) +{ + grub_inb (0x3c8); + grub_inb (0x3c6); + grub_inb (0x3c6); + grub_inb (0x3c6); + grub_inb (0x3c6); + return grub_inb (0x3c6); +} + +struct saved_state +{ + grub_uint8_t cr[CIRRUS_CR_MAX]; + grub_uint8_t gr[CIRRUS_GR_MAX]; + grub_uint8_t sr[CIRRUS_SR_MAX]; + grub_uint8_t hidden_dac; + /* We need to preserve VGA font and VGA text. */ + grub_uint8_t vram[32 * 4 * 256]; +}; + +static struct saved_state initial_state; +static int state_saved = 0; + +static void +save_state (struct saved_state *st) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + st->cr[i] = cr_read (i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + st->sr[i] = sr_read (i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + st->gr[i] = gr_read (i); + st->hidden_dac = read_hidden_dac (); + sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); +} + +static void +restore_state (struct saved_state *st) +{ + unsigned i; + sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + cr_write (st->cr[i], i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + sr_write (st->sr[i], i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + gr_write (st->gr[i], i); + write_hidden_dac (st->hidden_dac); +} + +static grub_err_t +grub_video_cirrus_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_cirrus_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + CIRRUS_APERTURE_SIZE); + + if (state_saved) + { + restore_state (&initial_state); + state_saved = 0; + } + + return grub_video_fb_fini (); +} + +static grub_err_t +grub_video_cirrus_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) +{ + int depth; + grub_err_t err; + int found = 0; + int pitch, bytes_per_pixel; + + 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) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if (width == 0 || height == 0) + { + width = 800; + height = 600; + } + + if (width & (CIRRUS_WIDTH_DIVISOR - 1)) + return grub_error (GRUB_ERR_IO, + "screen width must be a multiple of %d", + CIRRUS_WIDTH_DIVISOR); + + if (width > CIRRUS_MAX_WIDTH) + return grub_error (GRUB_ERR_IO, + "screen width must be at most %d", CIRRUS_MAX_WIDTH); + + if (height > CIRRUS_MAX_HEIGHT) + return grub_error (GRUB_ERR_IO, + "screen height must be at most %d", CIRRUS_MAX_HEIGHT); + + if (depth == 0) + depth = 24; + + if (depth != 32 && depth != 24 && depth != 16 && depth != 15) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "only 32, 24, 16 and 15-bit bpp are supported"); + + bytes_per_pixel = (depth + 7) / 8; + pitch = width * bytes_per_pixel; + + if (pitch > CIRRUS_MAX_PITCH) + return grub_error (GRUB_ERR_IO, + "screen width must be at most %d at bitdepth %d", + CIRRUS_MAX_PITCH / bytes_per_pixel, depth); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); + + if (found && framebuffer.base == 0) + { + /* FIXME: change framebuffer base */ + } + + /* We can safely discard volatile attribute. */ + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + CIRRUS_APERTURE_SIZE); + framebuffer.mapped = 1; + + if (!state_saved) + { + save_state (&initial_state); + state_saved = 1; + } + + { + int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; + grub_uint8_t sr_ext = 0; + + pitch_reg = pitch / CIRRUS_WIDTH_DIVISOR; + + gr_write (CIRRUS_GR_MODE_256_COLOR | CIRRUS_GR_MODE_READ_MODE1, + CIRRUS_GR_MODE); + gr_write (CIRRUS_GR_GR6_GRAPHICS_MODE, CIRRUS_GR_GR6); + + sr_write (CIRRUS_SR_MEMORY_MODE_NORMAL, CIRRUS_SR_MEMORY_MODE); + + /* Disable CR0-7 write protection. */ + cr_write (0, CIRRUS_CR_VSYNC_END); + + cr_write (width / CIRRUS_WIDTH_DIVISOR - 1, CIRRUS_CR_WIDTH); + cr_write ((height - 1) & 0xff, CIRRUS_CR_HEIGHT); + overflow_reg |= (((height - 1) >> CIRRUS_CR_OVERFLOW_HEIGHT1_SHIFT) & + CIRRUS_CR_OVERFLOW_HEIGHT1_MASK) + | (((height - 1) >> CIRRUS_CR_OVERFLOW_HEIGHT2_SHIFT) & + CIRRUS_CR_OVERFLOW_HEIGHT2_MASK); + + cr_write (pitch_reg & 0xff, CIRRUS_CR_PITCH); + + cr_write (line_compare & 0xff, CIRRUS_CR_LINE_COMPARE); + overflow_reg |= (line_compare >> CIRRUS_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK; + + cr_write (overflow_reg, CIRRUS_CR_OVERFLOW); + + cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) + & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, + CIRRUS_CR_EXTENDED_DISPLAY); + + cr_write ((line_compare >> CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_MASK, CIRRUS_CR_CELL_HEIGHT); + + cr_write (CIRRUS_CR_MODE_TIMING_ENABLE | CIRRUS_CR_MODE_BYTE_MODE + | CIRRUS_CR_MODE_NO_HERCULES | CIRRUS_CR_MODE_NO_CGA, + CIRRUS_CR_MODE); + + sr_ext = CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE + | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT; + switch (depth) + { + case 32: + sr_ext |= CIRRUS_SR_EXTENDED_MODE_32BPP; + break; + case 24: + sr_ext |= CIRRUS_SR_EXTENDED_MODE_24BPP; + break; + case 16: + case 15: + sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; + break; + } + sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); + write_hidden_dac (depth == 16); + } + + /* Fill mode info details. */ + framebuffer.mode_info.width = width; + framebuffer.mode_info.height = height; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = depth; + framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel; + framebuffer.mode_info.pitch = pitch; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; + + switch (depth) + { + case 16: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 15: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 10; + framebuffer.mode_info.green_mask_size = 5; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 32: + framebuffer.mode_info.reserved_mask_size = 8; + framebuffer.mode_info.reserved_field_pos = 24; + + case 24: + framebuffer.mode_info.red_mask_size = 8; + framebuffer.mode_info.red_field_pos = 16; + framebuffer.mode_info.green_mask_size = 8; + framebuffer.mode_info.green_field_pos = 8; + framebuffer.mode_info.blue_mask_size = 8; + framebuffer.mode_info.blue_field_pos = 0; + break; + } + + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; +} + +static grub_err_t +grub_video_cirrus_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + /* if (framebuffer.index_color_mode) */ + { + /* TODO: Implement setting indexed color mode palette to hardware. */ + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_cirrus_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_cirrus_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_cirrus_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + + +static struct grub_video_adapter grub_video_cirrus_adapter = + { + .name = "Cirrus CLGD 5446 PCI Video Driver", + .id = GRUB_VIDEO_DRIVER_CIRRUS, + + .init = grub_video_cirrus_video_init, + .fini = grub_video_cirrus_video_fini, + .setup = grub_video_cirrus_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_cirrus_get_info_and_fini, + .set_palette = grub_video_cirrus_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_cirrus_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_cirrus_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_cirrus) +{ + grub_video_register (&grub_video_cirrus_adapter); +} + +GRUB_MOD_FINI(video_cirrus) +{ + grub_video_unregister (&grub_video_cirrus_adapter); +} From 26162102fa7cd61a20bc9e637330bdfada6e47a6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 14:40:03 +0200 Subject: [PATCH 02/10] Move most framebuffer handling to video_fb.c --- include/grub/video_fb.h | 17 ++- video/fb/video_fb.c | 222 ++++++++++++++++++++++++++++++++++- video/i386/pc/vbe.c | 253 ++++------------------------------------ 3 files changed, 252 insertions(+), 240 deletions(-) diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index 3046a597b..2c1907fdf 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -119,11 +119,18 @@ typedef grub_err_t (*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front, struct grub_video_fbrender_target *back); +typedef grub_err_t (*grub_video_fb_set_page_t) (int page); + grub_err_t -grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, - struct grub_video_fbrender_target **back, - grub_video_fb_doublebuf_update_screen_t *update_screen, - struct grub_video_mode_info mode_info, - void *framebuf); +grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, + struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr); +grub_err_t +grub_video_fb_swap_buffers (void); +grub_err_t +grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf); #endif /* ! GRUB_VIDEO_FB_HEADER */ diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c index 9c5577bb9..6ec61868d 100644 --- a/video/fb/video_fb.c +++ b/video/fb/video_fb.c @@ -26,8 +26,16 @@ #include static struct grub_video_fbrender_target *render_target; +static struct grub_video_fbrender_target *front_target; +static struct grub_video_fbrender_target *back_target; struct grub_video_palette_data *palette; static unsigned int palette_size; +/* For page flipping strategy. */ +static int displayed_page; /* The page # that is the front buffer. */ +static int render_page; /* The page # that is the back buffer. */ +static grub_video_fb_set_page_t set_page; +static char *offscreen_buffer; +static grub_video_fb_doublebuf_update_screen_t update_screen; /* Specify "standard" VGA palette, some video cards may need this and this will also be used when using RGB modes. */ @@ -58,8 +66,11 @@ grub_video_fb_init (void) { grub_free (palette); render_target = 0; + front_target = 0; + back_target = 0; palette = 0; palette_size = 0; + set_page = 0; return GRUB_ERR_NONE; } @@ -68,10 +79,15 @@ grub_video_fb_fini (void) { /* TODO: destroy render targets. */ + grub_free (offscreen_buffer); grub_free (palette); render_target = 0; + front_target = 0; + back_target = 0; palette = 0; palette_size = 0; + set_page = 0; + offscreen_buffer = 0; return GRUB_ERR_NONE; } @@ -1221,6 +1237,10 @@ grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target) grub_err_t grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target) { + if (target == (struct grub_video_fbrender_target *) + GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = back_target; + if (! target->data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid render target given"); @@ -1235,6 +1255,9 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ { *target = render_target; + if (*target == back_target) + *target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY; + return GRUB_ERR_NONE; } @@ -1247,16 +1270,14 @@ doublebuf_blit_update_screen (struct grub_video_fbrender_target *front, return GRUB_ERR_NONE; } -grub_err_t +static grub_err_t grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, struct grub_video_fbrender_target **back, - grub_video_fb_doublebuf_update_screen_t *update_screen, struct grub_video_mode_info mode_info, void *framebuf) { grub_err_t err; int page_size = mode_info.pitch * mode_info.height; - void *offscreen_buffer; err = grub_video_fb_create_render_target_from_pointer (front, &mode_info, framebuf); @@ -1283,7 +1304,200 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, } (*back)->is_allocated = 1; - *update_screen = doublebuf_blit_update_screen; + update_screen = doublebuf_blit_update_screen; + + return GRUB_ERR_NONE; +} + +static grub_err_t +doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front + __attribute__ ((unused)), + struct grub_video_fbrender_target *back + __attribute__ ((unused))) +{ + int new_displayed_page; + struct grub_video_fbrender_target *target; + grub_err_t err; + + /* Swap the page numbers in the framebuffer struct. */ + new_displayed_page = render_page; + render_page = displayed_page; + displayed_page = new_displayed_page; + + err = set_page (displayed_page); + if (err) + { + /* Restore previous state. */ + render_page = displayed_page; + displayed_page = new_displayed_page; + return err; + } + + target = back_target; + back_target = front_target; + front_target = target; + + if (front_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) + grub_memcpy (back_target->data, front_target->data, + back_target->mode_info.pitch * back_target->mode_info.height); + + err = grub_video_fb_get_active_render_target (&target); + if (err) + return err; + + if (render_target == back_target) + render_target = front_target; + else if (target == front_target) + render_target = back_target; + + return err; +} + +static grub_err_t +doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr) +{ + grub_err_t err; + + displayed_page = 0; + render_page = 1; + + update_screen = doublebuf_pageflipping_update_screen; + + err = grub_video_fb_create_render_target_from_pointer (&front_target, + mode_info, + (void *) page0_ptr); + if (err) + return err; + + err = grub_video_fb_create_render_target_from_pointer (&back_target, + mode_info, + (void *) page1_ptr); + if (err) + { + grub_video_fb_delete_render_target (front_target); + return err; + } + + /* Set the framebuffer memory data pointer and display the right page. */ + err = set_page_in (displayed_page); + if (err) + { + grub_video_fb_delete_render_target (front_target); + grub_video_fb_delete_render_target (back_target); + return err; + } + set_page = set_page_in; + + return GRUB_ERR_NONE; +} + +/* Select the best double buffering mode available. */ +grub_err_t +grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, + struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr) +{ + grub_err_t err; + int updating_swap_needed; + + updating_swap_needed + = grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0); + + /* Do double buffering only if it's either requested or efficient. */ + if (set_page_in && grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, + !updating_swap_needed)) + { + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (updating_swap_needed) + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP; + + err = doublebuf_pageflipping_init (mode_info, page0_ptr, + set_page_in, + page1_ptr); + if (!err) + { + render_target = back_target; + return GRUB_ERR_NONE; + } + + mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + grub_errno = GRUB_ERR_NONE; + } + + if (grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, + 0)) + { + mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + err = grub_video_fb_doublebuf_blit_init (&front_target, + &back_target, + *mode_info, + (void *) page0_ptr); + + if (!err) + { + render_target = back_target; + return GRUB_ERR_NONE; + } + + mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + grub_errno = GRUB_ERR_NONE; + } + + /* Fall back to no double buffering. */ + err = grub_video_fb_create_render_target_from_pointer (&front_target, + mode_info, + (void *) page0_ptr); + + if (err) + return err; + + back_target = front_target; + update_screen = 0; + + mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + + render_target = back_target; + + return GRUB_ERR_NONE; +} + + +grub_err_t +grub_video_fb_swap_buffers (void) +{ + grub_err_t err; + if (!update_screen) + return GRUB_ERR_NONE; + + err = update_screen (front_target, back_target); + if (err) + return err; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(front_target->mode_info), sizeof (*mode_info)); + *framebuf = front_target->data; + + grub_video_fb_fini (); return GRUB_ERR_NONE; } diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index 72b8f1831..05c6db736 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -40,25 +40,12 @@ static grub_uint32_t last_set_mode = 3; static struct { struct grub_video_mode_info mode_info; - struct grub_video_render_target *front_target; - struct grub_video_render_target *back_target; unsigned int bytes_per_scan_line; unsigned int bytes_per_pixel; grub_uint32_t active_vbe_mode; grub_uint8_t *ptr; int index_color_mode; - - char *offscreen_buffer; - - grub_size_t page_size; /* The size of a page in bytes. */ - - /* For page flipping strategy. */ - int displayed_page; /* The page # that is the front buffer. */ - int render_page; /* The page # that is the back buffer. */ - - /* Virtual functions. */ - grub_video_fb_doublebuf_update_screen_t update_screen; } framebuffer; static grub_uint32_t initial_vbe_mode; @@ -377,7 +364,6 @@ grub_video_vbe_fini (void) vbe_mode_list = NULL; err = grub_video_fb_fini (); - grub_free (framebuffer.offscreen_buffer); return err; } @@ -387,11 +373,11 @@ grub_video_vbe_fini (void) respectively. */ static grub_err_t -doublebuf_pageflipping_commit (void) +doublebuf_pageflipping_set_page (int page) { /* Tell the video adapter to display the new front page. */ int display_start_line - = framebuffer.mode_info.height * framebuffer.displayed_page; + = framebuffer.mode_info.height * page; grub_vbe_status_t vbe_err = grub_vbe_bios_set_display_start (0, display_start_line); @@ -402,164 +388,6 @@ doublebuf_pageflipping_commit (void) return 0; } -static grub_err_t -doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front - __attribute__ ((unused)), - struct grub_video_fbrender_target *back - __attribute__ ((unused))) -{ - int new_displayed_page; - struct grub_video_fbrender_target *target; - grub_err_t err; - - /* Swap the page numbers in the framebuffer struct. */ - new_displayed_page = framebuffer.render_page; - framebuffer.render_page = framebuffer.displayed_page; - framebuffer.displayed_page = new_displayed_page; - - err = doublebuf_pageflipping_commit (); - if (err) - { - /* Restore previous state. */ - framebuffer.render_page = framebuffer.displayed_page; - framebuffer.displayed_page = new_displayed_page; - return err; - } - - if (framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) - grub_memcpy (framebuffer.ptr + framebuffer.render_page - * framebuffer.page_size, framebuffer.ptr - + framebuffer.displayed_page * framebuffer.page_size, - framebuffer.page_size); - - target = framebuffer.back_target; - framebuffer.back_target = framebuffer.front_target; - framebuffer.front_target = target; - - err = grub_video_fb_get_active_render_target (&target); - if (err) - return err; - - if (target == framebuffer.back_target) - err = grub_video_fb_set_active_render_target (framebuffer.front_target); - else if (target == framebuffer.front_target) - err = grub_video_fb_set_active_render_target (framebuffer.back_target); - - return err; -} - -static grub_err_t -doublebuf_pageflipping_init (void) -{ - /* Get video RAM size in bytes. */ - grub_size_t vram_size = controller_info.total_memory << 16; - grub_err_t err; - - framebuffer.page_size = - framebuffer.mode_info.pitch * framebuffer.mode_info.height; - - if (2 * framebuffer.page_size > vram_size) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Not enough video memory for double buffering."); - - framebuffer.displayed_page = 0; - framebuffer.render_page = 1; - - framebuffer.update_screen = doublebuf_pageflipping_update_screen; - - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr); - if (err) - return err; - - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, &framebuffer.mode_info, framebuffer.ptr + framebuffer.page_size); - if (err) - { - grub_video_fb_delete_render_target (framebuffer.front_target); - return err; - } - - /* Set the framebuffer memory data pointer and display the right page. */ - err = doublebuf_pageflipping_commit (); - if (err) - { - grub_video_fb_delete_render_target (framebuffer.front_target); - grub_video_fb_delete_render_target (framebuffer.back_target); - return err; - } - - return GRUB_ERR_NONE; -} - -/* Select the best double buffering mode available. */ -static grub_err_t -double_buffering_init (unsigned int mode_type, unsigned int mode_mask) -{ - grub_err_t err; - int updating_swap_needed; - - updating_swap_needed - = grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0); - - /* Do double buffering only if it's either requested or efficient. */ - if (grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, - !updating_swap_needed)) - { - framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; - if (updating_swap_needed) - framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP; - err = doublebuf_pageflipping_init (); - if (!err) - return GRUB_ERR_NONE; - - framebuffer.mode_info.mode_type - &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - grub_errno = GRUB_ERR_NONE; - } - - if (grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, - 0)) - { - framebuffer.mode_info.mode_type - |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target, - &framebuffer.back_target, - &framebuffer.update_screen, - framebuffer.mode_info, - framebuffer.ptr); - - if (!err) - return GRUB_ERR_NONE; - - framebuffer.mode_info.mode_type - &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - grub_errno = GRUB_ERR_NONE; - } - - /* Fall back to no double buffering. */ - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr); - - if (err) - return err; - - framebuffer.back_target = framebuffer.front_target; - framebuffer.update_screen = 0; - - framebuffer.mode_info.mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; - - return GRUB_ERR_NONE; -} - - - static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask) @@ -684,15 +512,24 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); - /* Set up double buffering and targets. */ - err = double_buffering_init (mode_type, mode_mask); - if (err) - return err; + { + /* Get video RAM size in bytes. */ + grub_size_t vram_size = controller_info.total_memory << 16; + grub_size_t page_size; /* The size of a page in bytes. */ - err = grub_video_fb_set_active_render_target (framebuffer.back_target); + page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height; - if (err) - return err; + if (vram_size >= 2 * page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); + } /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, @@ -723,59 +560,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count, return grub_video_fb_set_palette (start, count, palette_data); } -static grub_err_t -grub_video_vbe_swap_buffers (void) -{ - grub_err_t err; - if (!framebuffer.update_screen) - return GRUB_ERR_NONE; - - err = framebuffer.update_screen (framebuffer.front_target, - framebuffer.back_target); - if (err) - return err; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_set_active_render_target (struct grub_video_render_target *target) -{ - if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) - target = framebuffer.back_target; - - return grub_video_fb_set_active_render_target (target); -} - -static grub_err_t -grub_video_vbe_get_active_render_target (struct grub_video_render_target **target) -{ - grub_err_t err; - err = grub_video_fb_get_active_render_target (target); - if (err) - return err; - - if (*target == framebuffer.back_target) - *target = GRUB_VIDEO_RENDER_TARGET_DISPLAY; - - return GRUB_ERR_NONE; -} - static grub_err_t grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, void **framebuf) { - grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); - *framebuf = (char *) framebuffer.ptr - + framebuffer.displayed_page * framebuffer.page_size; - grub_free (vbe_mode_list); vbe_mode_list = NULL; - - grub_video_fb_fini (); - grub_free (framebuffer.offscreen_buffer); - - return GRUB_ERR_NONE; + return grub_video_fb_get_info_and_fini (mode_info, framebuf); } static struct grub_video_adapter grub_video_vbe_adapter = @@ -800,11 +591,11 @@ static struct grub_video_adapter grub_video_vbe_adapter = .blit_bitmap = grub_video_fb_blit_bitmap, .blit_render_target = grub_video_fb_blit_render_target, .scroll = grub_video_fb_scroll, - .swap_buffers = grub_video_vbe_swap_buffers, + .swap_buffers = grub_video_fb_swap_buffers, .create_render_target = grub_video_fb_create_render_target, .delete_render_target = grub_video_fb_delete_render_target, - .set_active_render_target = grub_video_vbe_set_active_render_target, - .get_active_render_target = grub_video_vbe_get_active_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, .next = 0 }; From 02aabd9e467744b696878db42adc0acd5a900609 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 15:01:54 +0200 Subject: [PATCH 03/10] Encapsulate video_fb state in a structure --- include/grub/video_fb.h | 4 +- video/fb/video_fb.c | 398 ++++++++++++++++++++-------------------- 2 files changed, 206 insertions(+), 196 deletions(-) diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index 2c1907fdf..6816f6f60 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -89,8 +89,8 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, grub_err_t grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, - enum grub_video_blit_operators oper, - int x, int y, int offset_x, int offset_y, + enum grub_video_blit_operators oper, + int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); grub_err_t diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c index 6ec61868d..69626be5c 100644 --- a/video/fb/video_fb.c +++ b/video/fb/video_fb.c @@ -25,17 +25,20 @@ #include #include -static struct grub_video_fbrender_target *render_target; -static struct grub_video_fbrender_target *front_target; -static struct grub_video_fbrender_target *back_target; -struct grub_video_palette_data *palette; -static unsigned int palette_size; -/* For page flipping strategy. */ -static int displayed_page; /* The page # that is the front buffer. */ -static int render_page; /* The page # that is the back buffer. */ -static grub_video_fb_set_page_t set_page; -static char *offscreen_buffer; -static grub_video_fb_doublebuf_update_screen_t update_screen; +static struct +{ + struct grub_video_fbrender_target *render_target; + struct grub_video_fbrender_target *front_target; + struct grub_video_fbrender_target *back_target; + struct grub_video_palette_data *palette; + unsigned int palette_size; + /* For page flipping strategy. */ + int displayed_page; /* The page # that is the front buffer. */ + int render_page; /* The page # that is the back buffer. */ + grub_video_fb_set_page_t set_page; + char *offscreen_buffer; + grub_video_fb_doublebuf_update_screen_t update_screen; +} framebuffer; /* Specify "standard" VGA palette, some video cards may need this and this will also be used when using RGB modes. */ @@ -64,13 +67,13 @@ struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLOR grub_err_t grub_video_fb_init (void) { - grub_free (palette); - render_target = 0; - front_target = 0; - back_target = 0; - palette = 0; - palette_size = 0; - set_page = 0; + grub_free (framebuffer.palette); + framebuffer.render_target = 0; + framebuffer.front_target = 0; + framebuffer.back_target = 0; + framebuffer.palette = 0; + framebuffer.palette_size = 0; + framebuffer.set_page = 0; return GRUB_ERR_NONE; } @@ -79,15 +82,15 @@ grub_video_fb_fini (void) { /* TODO: destroy render targets. */ - grub_free (offscreen_buffer); - grub_free (palette); - render_target = 0; - front_target = 0; - back_target = 0; - palette = 0; - palette_size = 0; - set_page = 0; - offscreen_buffer = 0; + grub_free (framebuffer.offscreen_buffer); + grub_free (framebuffer.palette); + framebuffer.render_target = 0; + framebuffer.front_target = 0; + framebuffer.back_target = 0; + framebuffer.palette = 0; + framebuffer.palette_size = 0; + framebuffer.set_page = 0; + framebuffer.offscreen_buffer = 0; return GRUB_ERR_NONE; } @@ -95,7 +98,7 @@ grub_err_t grub_video_fb_get_info (struct grub_video_mode_info *mode_info) { /* Copy mode info from active render target. */ - grub_memcpy (mode_info, &render_target->mode_info, + grub_memcpy (mode_info, &framebuffer.render_target->mode_info, sizeof (struct grub_video_mode_info)); return GRUB_ERR_NONE; @@ -108,8 +111,8 @@ grub_video_fb_get_palette (unsigned int start, unsigned int count, unsigned int i; /* Assume that we know everything from index color palette. */ - for (i = 0; (i < count) && ((i + start) < palette_size); i++) - palette_data[i] = palette[start + i]; + for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++) + palette_data[i] = framebuffer.palette[start + i]; return GRUB_ERR_NONE; } @@ -119,18 +122,20 @@ grub_video_fb_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { unsigned i; - if (start + count > palette_size) + if (start + count > framebuffer.palette_size) { - palette_size = start + count; - palette = grub_realloc (palette, sizeof (palette[0]) * palette_size); - if (!palette) + framebuffer.palette_size = start + count; + framebuffer.palette = grub_realloc (framebuffer.palette, + sizeof (framebuffer.palette[0]) + * framebuffer.palette_size); + if (!framebuffer.palette) { grub_video_fb_fini (); return grub_errno; } } - for (i = 0; (i < count) && ((i + start) < palette_size); i++) - palette[start + i] = palette_data[i]; + for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++) + framebuffer.palette[start + i] = palette_data[i]; return GRUB_ERR_NONE; } @@ -140,28 +145,28 @@ grub_video_fb_set_viewport (unsigned int x, unsigned int y, { /* Make sure viewport is withing screen dimensions. If viewport was set to be out of the region, mark its size as zero. */ - if (x > render_target->mode_info.width) + if (x > framebuffer.render_target->mode_info.width) { x = 0; width = 0; } - if (y > render_target->mode_info.height) + if (y > framebuffer.render_target->mode_info.height) { y = 0; height = 0; } - if (x + width > render_target->mode_info.width) - width = render_target->mode_info.width - x; + if (x + width > framebuffer.render_target->mode_info.width) + width = framebuffer.render_target->mode_info.width - x; - if (y + height > render_target->mode_info.height) - height = render_target->mode_info.height - y; + if (y + height > framebuffer.render_target->mode_info.height) + height = framebuffer.render_target->mode_info.height - y; - render_target->viewport.x = x; - render_target->viewport.y = y; - render_target->viewport.width = width; - render_target->viewport.height = height; + framebuffer.render_target->viewport.x = x; + framebuffer.render_target->viewport.y = y; + framebuffer.render_target->viewport.width = width; + framebuffer.render_target->viewport.height = height; return GRUB_ERR_NONE; } @@ -170,10 +175,10 @@ grub_err_t grub_video_fb_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height) { - if (x) *x = render_target->viewport.x; - if (y) *y = render_target->viewport.y; - if (width) *width = render_target->viewport.width; - if (height) *height = render_target->viewport.height; + if (x) *x = framebuffer.render_target->viewport.x; + if (y) *y = framebuffer.render_target->viewport.y; + if (width) *width = framebuffer.render_target->viewport.width; + if (height) *height = framebuffer.render_target->viewport.height; return GRUB_ERR_NONE; } @@ -184,18 +189,18 @@ grub_video_fb_map_color (grub_uint32_t color_name) { /* TODO: implement color theme mapping code. */ - if (color_name < palette_size) + if (color_name < framebuffer.palette_size) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) return color_name; else { grub_video_color_t color; - color = grub_video_fb_map_rgb (palette[color_name].r, - palette[color_name].g, - palette[color_name].b); + color = grub_video_fb_map_rgb (framebuffer.palette[color_name].r, + framebuffer.palette[color_name].g, + framebuffer.palette[color_name].b); return color; } @@ -209,7 +214,7 @@ grub_video_color_t grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { int minindex = 0; @@ -219,13 +224,13 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, unsigned i; /* Find best matching color. */ - for (i = 0; i < palette_size; i++) + for (i = 0; i < framebuffer.palette_size; i++) { - val = palette[i].r - red; + val = framebuffer.palette[i].r - red; tmp = val * val; - val = palette[i].g - green; + val = framebuffer.palette[i].g - green; tmp += val * val; - val = palette[i].b - blue; + val = framebuffer.palette[i].b - blue; tmp += val * val; if (i == 0) @@ -242,12 +247,12 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, return minindex; } - else if ((render_target->mode_info.mode_type + else if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue) + if (red == framebuffer.render_target->mode_info.fg_red + && green == framebuffer.render_target->mode_info.fg_green + && blue == framebuffer.render_target->mode_info.fg_blue) return 1; else return 0; @@ -257,15 +262,15 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint32_t value; grub_uint8_t alpha = 255; /* Opaque color. */ - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; + red >>= 8 - framebuffer.render_target->mode_info.red_mask_size; + green >>= 8 - framebuffer.render_target->mode_info.green_mask_size; + blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size; + alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size; - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; + value = red << framebuffer.render_target->mode_info.red_field_pos; + value |= green << framebuffer.render_target->mode_info.green_field_pos; + value |= blue << framebuffer.render_target->mode_info.blue_field_pos; + value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos; return value; } @@ -277,18 +282,18 @@ grub_video_color_t grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, grub_uint8_t alpha) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) /* No alpha available in index color modes, just use same value as in only RGB modes. */ return grub_video_fb_map_rgb (red, green, blue); - else if ((render_target->mode_info.mode_type + else if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue - && alpha == render_target->mode_info.fg_alpha) + if (red == framebuffer.render_target->mode_info.fg_red + && green == framebuffer.render_target->mode_info.fg_green + && blue == framebuffer.render_target->mode_info.fg_blue + && alpha == framebuffer.render_target->mode_info.fg_alpha) return 1; else return 0; @@ -297,15 +302,15 @@ grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, { grub_uint32_t value; - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; + red >>= 8 - framebuffer.render_target->mode_info.red_mask_size; + green >>= 8 - framebuffer.render_target->mode_info.green_mask_size; + blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size; + alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size; - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; + value = red << framebuffer.render_target->mode_info.red_field_pos; + value |= green << framebuffer.render_target->mode_info.green_field_pos; + value |= blue << framebuffer.render_target->mode_info.blue_field_pos; + value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos; return value; } @@ -319,8 +324,8 @@ grub_video_fb_unmap_color (grub_video_color_t color, { struct grub_video_fbblit_info target_info; - target_info.mode_info = &render_target->mode_info; - target_info.data = render_target->data; + target_info.mode_info = &framebuffer.render_target->mode_info; + target_info.data = framebuffer.render_target->data; grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha); @@ -350,10 +355,10 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source, return; } - *red = palette[color].r; - *green = palette[color].g; - *blue = palette[color].b; - *alpha = palette[color].a; + *red = framebuffer.palette[color].r; + *green = framebuffer.palette[color].g; + *blue = framebuffer.palette[color].b; + *alpha = framebuffer.palette[color].a; return; } else if ((mode_info->mode_type @@ -422,9 +427,9 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, struct grub_video_fbblit_info target; /* Make sure there is something to do. */ - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; /* Do not allow drawing out of viewport. */ @@ -439,18 +444,18 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, y = 0; } - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; /* Try to figure out more optimized version. Note that color is already mapped to target format so we can make assumptions based on that. */ @@ -777,9 +782,9 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) return GRUB_ERR_NONE; - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)bitmap->mode_info.width) < 0) return GRUB_ERR_NONE; @@ -822,10 +827,10 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, } /* Do not allow drawing out of viewport. */ - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; if ((offset_x + width) > bitmap->mode_info.width) width = bitmap->mode_info.width - offset_x; @@ -840,14 +845,14 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, height = bitmap->mode_info.height; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ source.mode_info = &bitmap->mode_info; source.data = bitmap->data; - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; /* Do actual blitting. */ common_blitter (&target, &source, oper, x, y, width, height, @@ -868,9 +873,9 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) return GRUB_ERR_NONE; - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)source->mode_info.width) < 0) return GRUB_ERR_NONE; @@ -913,10 +918,10 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, } /* Do not allow drawing out of viewport. */ - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; if ((offset_x + width) > source->mode_info.width) width = source->mode_info.width - offset_x; @@ -931,14 +936,14 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, height = source->mode_info.height; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ source_info.mode_info = &source->mode_info; source_info.data = source->data; - target_info.mode_info = &render_target->mode_info; - target_info.data = render_target->data; + target_info.mode_info = &framebuffer.render_target->mode_info; + target_info.data = framebuffer.render_target->data; /* Do actual blitting. */ common_blitter (&target_info, &source_info, oper, x, y, width, height, @@ -961,42 +966,42 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) if ((dx == 0) && (dy == 0)) return GRUB_ERR_NONE; - width = render_target->viewport.width - grub_abs (dx); - height = render_target->viewport.height - grub_abs (dy); + width = framebuffer.render_target->viewport.width - grub_abs (dx); + height = framebuffer.render_target->viewport.height - grub_abs (dy); if (dx < 0) { - src_x = render_target->viewport.x - dx; - dst_x = render_target->viewport.x; + src_x = framebuffer.render_target->viewport.x - dx; + dst_x = framebuffer.render_target->viewport.x; } else { - src_x = render_target->viewport.x; - dst_x = render_target->viewport.x + dx; + src_x = framebuffer.render_target->viewport.x; + dst_x = framebuffer.render_target->viewport.x + dx; } if (dy < 0) { - src_y = render_target->viewport.y - dy; - dst_y = render_target->viewport.y; + src_y = framebuffer.render_target->viewport.y - dy; + dst_y = framebuffer.render_target->viewport.y; } else { - src_y = render_target->viewport.y; - dst_y = render_target->viewport.y + dy; + src_y = framebuffer.render_target->viewport.y; + dst_y = framebuffer.render_target->viewport.y + dy; } /* 2. Check if there is need to copy data. */ - if ((grub_abs (dx) < render_target->viewport.width) - && (grub_abs (dy) < render_target->viewport.height)) + if ((grub_abs (dx) < framebuffer.render_target->viewport.width) + && (grub_abs (dy) < framebuffer.render_target->viewport.height)) { /* 3. Move data in render target. */ struct grub_video_fbblit_info target; int i, j; int linedelta, linelen; - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; linedelta = target.mode_info->pitch - width * target.mode_info->bytes_per_pixel; @@ -1079,27 +1084,27 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) /* 4a. Fill top & bottom parts. */ if (dy > 0) - grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy); + grub_video_fb_fill_rect (color, 0, 0, framebuffer.render_target->viewport.width, dy); else if (dy < 0) { - if (render_target->viewport.height < grub_abs (dy)) - dy = -render_target->viewport.height; + if (framebuffer.render_target->viewport.height < grub_abs (dy)) + dy = -framebuffer.render_target->viewport.height; - grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy, - render_target->viewport.width, -dy); + grub_video_fb_fill_rect (color, 0, framebuffer.render_target->viewport.height + dy, + framebuffer.render_target->viewport.width, -dy); } /* 4b. Fill left & right parts. */ if (dx > 0) grub_video_fb_fill_rect (color, 0, 0, - dx, render_target->viewport.height); + dx, framebuffer.render_target->viewport.height); else if (dx < 0) { - if (render_target->viewport.width < grub_abs (dx)) - dx = -render_target->viewport.width; + if (framebuffer.render_target->viewport.width < grub_abs (dx)) + dx = -framebuffer.render_target->viewport.width; - grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0, - -dx, render_target->viewport.height); + grub_video_fb_fill_rect (color, framebuffer.render_target->viewport.width + dx, 0, + -dx, framebuffer.render_target->viewport.height); } return GRUB_ERR_NONE; @@ -1146,7 +1151,7 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, target->mode_info.bpp = 32; target->mode_info.bytes_per_pixel = 4; target->mode_info.pitch = target->mode_info.bytes_per_pixel * width; - target->mode_info.number_of_colors = palette_size; /* Emulated palette. */ + target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette. */ target->mode_info.red_mask_size = 8; target->mode_info.red_field_pos = 0; target->mode_info.green_mask_size = 8; @@ -1239,13 +1244,13 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe { if (target == (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY) - target = back_target; + target = framebuffer.back_target; if (! target->data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid render target given"); - render_target = target; + framebuffer.render_target = target; return GRUB_ERR_NONE; } @@ -1253,9 +1258,9 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe grub_err_t grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target) { - *target = render_target; + *target = framebuffer.render_target; - if (*target == back_target) + if (*target == framebuffer.back_target) *target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY; return GRUB_ERR_NONE; @@ -1284,8 +1289,8 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, if (err) return err; - offscreen_buffer = grub_malloc (page_size); - if (! offscreen_buffer) + framebuffer.offscreen_buffer = grub_malloc (page_size); + if (! framebuffer.offscreen_buffer) { grub_video_fb_delete_render_target (*front); *front = 0; @@ -1293,18 +1298,19 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, } err = grub_video_fb_create_render_target_from_pointer (back, &mode_info, - offscreen_buffer); + framebuffer.offscreen_buffer); if (err) { grub_video_fb_delete_render_target (*front); - grub_free (offscreen_buffer); + grub_free (framebuffer.offscreen_buffer); + framebuffer.offscreen_buffer = 0; *front = 0; return grub_errno; } (*back)->is_allocated = 1; - update_screen = doublebuf_blit_update_screen; + framebuffer.update_screen = doublebuf_blit_update_screen; return GRUB_ERR_NONE; } @@ -1320,35 +1326,37 @@ doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front grub_err_t err; /* Swap the page numbers in the framebuffer struct. */ - new_displayed_page = render_page; - render_page = displayed_page; - displayed_page = new_displayed_page; + new_displayed_page = framebuffer.render_page; + framebuffer.render_page = framebuffer.displayed_page; + framebuffer.displayed_page = new_displayed_page; - err = set_page (displayed_page); + err = framebuffer.set_page (framebuffer.displayed_page); if (err) { /* Restore previous state. */ - render_page = displayed_page; - displayed_page = new_displayed_page; + framebuffer.render_page = framebuffer.displayed_page; + framebuffer.displayed_page = new_displayed_page; return err; } - target = back_target; - back_target = front_target; - front_target = target; + target = framebuffer.back_target; + framebuffer.back_target = framebuffer.front_target; + framebuffer.front_target = target; - if (front_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) - grub_memcpy (back_target->data, front_target->data, - back_target->mode_info.pitch * back_target->mode_info.height); + if (framebuffer.front_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) + grub_memcpy (framebuffer.back_target->data, framebuffer.front_target->data, + framebuffer.back_target->mode_info.pitch + * framebuffer.back_target->mode_info.height); err = grub_video_fb_get_active_render_target (&target); if (err) return err; - if (render_target == back_target) - render_target = front_target; - else if (target == front_target) - render_target = back_target; + if (framebuffer.render_target == framebuffer.back_target) + framebuffer.render_target = framebuffer.front_target; + else if (framebuffer.render_target == framebuffer.front_target) + framebuffer.render_target = framebuffer.back_target; return err; } @@ -1361,35 +1369,35 @@ doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info, { grub_err_t err; - displayed_page = 0; - render_page = 1; + framebuffer.displayed_page = 0; + framebuffer.render_page = 1; - update_screen = doublebuf_pageflipping_update_screen; + framebuffer.update_screen = doublebuf_pageflipping_update_screen; - err = grub_video_fb_create_render_target_from_pointer (&front_target, + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, mode_info, (void *) page0_ptr); if (err) return err; - err = grub_video_fb_create_render_target_from_pointer (&back_target, + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, mode_info, (void *) page1_ptr); if (err) { - grub_video_fb_delete_render_target (front_target); + grub_video_fb_delete_render_target (framebuffer.front_target); return err; } /* Set the framebuffer memory data pointer and display the right page. */ - err = set_page_in (displayed_page); + err = set_page_in (framebuffer.displayed_page); if (err) { - grub_video_fb_delete_render_target (front_target); - grub_video_fb_delete_render_target (back_target); + grub_video_fb_delete_render_target (framebuffer.front_target); + grub_video_fb_delete_render_target (framebuffer.back_target); return err; } - set_page = set_page_in; + framebuffer.set_page = set_page_in; return GRUB_ERR_NONE; } @@ -1423,7 +1431,7 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, page1_ptr); if (!err) { - render_target = back_target; + framebuffer.render_target = framebuffer.back_target; return GRUB_ERR_NONE; } @@ -1440,14 +1448,14 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - err = grub_video_fb_doublebuf_blit_init (&front_target, - &back_target, + err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target, + &framebuffer.back_target, *mode_info, (void *) page0_ptr); if (!err) { - render_target = back_target; + framebuffer.render_target = framebuffer.back_target; return GRUB_ERR_NONE; } @@ -1458,19 +1466,19 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, } /* Fall back to no double buffering. */ - err = grub_video_fb_create_render_target_from_pointer (&front_target, + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, mode_info, (void *) page0_ptr); if (err) return err; - back_target = front_target; - update_screen = 0; + framebuffer.back_target = framebuffer.front_target; + framebuffer.update_screen = 0; mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; - render_target = back_target; + framebuffer.render_target = framebuffer.back_target; return GRUB_ERR_NONE; } @@ -1480,10 +1488,11 @@ grub_err_t grub_video_fb_swap_buffers (void) { grub_err_t err; - if (!update_screen) + if (!framebuffer.update_screen) return GRUB_ERR_NONE; - err = update_screen (front_target, back_target); + err = framebuffer.update_screen (framebuffer.front_target, + framebuffer.back_target); if (err) return err; @@ -1494,8 +1503,9 @@ grub_err_t grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info, void **framebuf) { - grub_memcpy (mode_info, &(front_target->mode_info), sizeof (*mode_info)); - *framebuf = front_target->data; + grub_memcpy (mode_info, &(framebuffer.front_target->mode_info), + sizeof (*mode_info)); + *framebuf = framebuffer.front_target->data; grub_video_fb_fini (); From d00b0b3f4d25e0945d1aadb59afa1752b43b680a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 20:20:31 +0200 Subject: [PATCH 04/10] Support double buffering on video cirrus --- video/cirrus.c | 108 +++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 44 deletions(-) diff --git a/video/cirrus.c b/video/cirrus.c index ae1bd9940..09dbb2c1d 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -30,7 +30,7 @@ static struct { struct grub_video_mode_info mode_info; - struct grub_video_render_target *render_target; + grub_size_t page_size; /* The size of a page in bytes. */ grub_uint8_t *ptr; int mapped; @@ -69,12 +69,15 @@ enum CIRRUS_CR_WIDTH = 0x01, CIRRUS_CR_OVERFLOW = 0x07, CIRRUS_CR_CELL_HEIGHT = 0x09, + CIRRUS_CR_SCREEN_START_HIGH = 0xc, + CIRRUS_CR_SCREEN_START_LOW = 0xd, CIRRUS_CR_VSYNC_END = 0x11, CIRRUS_CR_HEIGHT = 0x12, CIRRUS_CR_PITCH = 0x13, CIRRUS_CR_MODE = 0x17, CIRRUS_CR_LINE_COMPARE = 0x18, CIRRUS_CR_EXTENDED_DISPLAY = 0x1b, + CIRRUS_CR_EXTENDED_OVERLAY = 0x1d, CIRRUS_CR_MAX }; @@ -85,17 +88,25 @@ enum #define CIRRUS_CR_OVERFLOW_HEIGHT1_MASK 0x02 #define CIRRUS_CR_OVERFLOW_HEIGHT2_SHIFT 3 #define CIRRUS_CR_OVERFLOW_HEIGHT2_MASK 0xc0 -#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 #define CIRRUS_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 - -#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 -#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 +#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 #define CIRRUS_CR_MODE_TIMING_ENABLE 0x80 #define CIRRUS_CR_MODE_BYTE_MODE 0x40 #define CIRRUS_CR_MODE_NO_HERCULES 0x02 #define CIRRUS_CR_MODE_NO_CGA 0x01 +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc +#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15 + +#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80 +#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12 + + enum { CIRRUS_SR_MEMORY_MODE = 4, @@ -242,6 +253,33 @@ grub_video_cirrus_video_fini (void) return grub_video_fb_fini (); } +static grub_err_t +doublebuf_pageflipping_set_page (int page) +{ + int start = framebuffer.page_size * page / 4; + grub_uint8_t cr_ext, cr_overlay; + + cr_write (start & 0xff, CIRRUS_CR_SCREEN_START_LOW); + cr_write ((start & 0xff00) >> 8, CIRRUS_CR_SCREEN_START_HIGH); + + cr_ext = cr_read (CIRRUS_CR_EXTENDED_DISPLAY); + cr_ext &= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 + | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); + cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1) + & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1); + cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2) + & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); + cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY); + + cr_overlay = cr_read (CIRRUS_CR_EXTENDED_OVERLAY); + cr_overlay &= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); + cr_overlay |= ((start >> CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT) + & CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); + cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY); + + return GRUB_ERR_NONE; +} + static grub_err_t grub_video_cirrus_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) @@ -310,6 +348,11 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, "screen width must be at most %d at bitdepth %d", CIRRUS_MAX_PITCH / bytes_per_pixel, depth); + framebuffer.page_size = pitch * height; + + if (framebuffer.page_size > CIRRUS_APERTURE_SIZE) + return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); + grub_pci_iterate (find_card); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); @@ -317,6 +360,7 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, if (found && framebuffer.base == 0) { /* FIXME: change framebuffer base */ + return grub_error (GRUB_ERR_IO, "PCI BAR not set"); } /* We can safely discard volatile attribute. */ @@ -372,6 +416,8 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, | CIRRUS_CR_MODE_NO_HERCULES | CIRRUS_CR_MODE_NO_CGA, CIRRUS_CR_MODE); + doublebuf_pageflipping_set_page (0); + sr_ext = CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT; switch (depth) @@ -438,15 +484,17 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); + if (CIRRUS_APERTURE_SIZE >= 2 * framebuffer.page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + framebuffer.page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); - if (err) - return err; - - err = grub_video_fb_set_active_render_target (framebuffer.render_target); - - if (err) - return err; /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, @@ -467,34 +515,6 @@ grub_video_cirrus_set_palette (unsigned int start, unsigned int count, return grub_video_fb_set_palette (start, count, palette_data); } -static grub_err_t -grub_video_cirrus_swap_buffers (void) -{ - /* TODO: Implement buffer swapping. */ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_cirrus_set_active_render_target (struct grub_video_render_target *target) -{ - if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) - target = framebuffer.render_target; - - return grub_video_fb_set_active_render_target (target); -} - -static grub_err_t -grub_video_cirrus_get_info_and_fini (struct grub_video_mode_info *mode_info, - void **framebuf) -{ - grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); - *framebuf = (char *) framebuffer.ptr; - - grub_video_fb_fini (); - - return GRUB_ERR_NONE; -} - static struct grub_video_adapter grub_video_cirrus_adapter = { @@ -505,7 +525,7 @@ static struct grub_video_adapter grub_video_cirrus_adapter = .fini = grub_video_cirrus_video_fini, .setup = grub_video_cirrus_setup, .get_info = grub_video_fb_get_info, - .get_info_and_fini = grub_video_cirrus_get_info_and_fini, + .get_info_and_fini = grub_video_fb_get_info_and_fini, .set_palette = grub_video_cirrus_set_palette, .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, @@ -518,10 +538,10 @@ static struct grub_video_adapter grub_video_cirrus_adapter = .blit_bitmap = grub_video_fb_blit_bitmap, .blit_render_target = grub_video_fb_blit_render_target, .scroll = grub_video_fb_scroll, - .swap_buffers = grub_video_cirrus_swap_buffers, + .swap_buffers = grub_video_fb_swap_buffers, .create_render_target = grub_video_fb_create_render_target, .delete_render_target = grub_video_fb_delete_render_target, - .set_active_render_target = grub_video_cirrus_set_active_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, .next = 0 From 63c1b71cbbbc6468fb98ca63dd4248398fe254d9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 20:44:44 +0200 Subject: [PATCH 05/10] Cleanup hidden DAC part. --- video/cirrus.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/video/cirrus.c b/video/cirrus.c index 09dbb2c1d..2e487311e 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -121,6 +121,15 @@ enum #define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06 #define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08 +#define CIRRUS_HIDDEN_DAC_ENABLE_EXT 0x80 +#define CIRRUS_HIDDEN_DAC_ENABLE_ALL 0x40 +#define CIRRUS_HIDDEN_DAC_15BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 0) +#define CIRRUS_HIDDEN_DAC_16BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 1) +#define CIRRUS_HIDDEN_DAC_888COLOR (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 5) + static void gr_write (grub_uint8_t val, grub_uint8_t addr) { @@ -377,7 +386,7 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, { int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; - grub_uint8_t sr_ext = 0; + grub_uint8_t sr_ext = 0, hidden_dac = 0; pitch_reg = pitch / CIRRUS_WIDTH_DIVISOR; @@ -422,19 +431,26 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT; switch (depth) { + /* FIXME: support 8-bit grayscale and 8-bit RGB. */ case 32: + hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; sr_ext |= CIRRUS_SR_EXTENDED_MODE_32BPP; break; case 24: + hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; sr_ext |= CIRRUS_SR_EXTENDED_MODE_24BPP; break; case 16: + hidden_dac = CIRRUS_HIDDEN_DAC_16BPP; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; + break; case 15: + hidden_dac = CIRRUS_HIDDEN_DAC_15BPP; sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; break; } sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); - write_hidden_dac (depth == 16); + write_hidden_dac (hidden_dac); } /* Fill mode info details. */ From 31e0ce4d105ac35b4f4d1103713bf66518b0fccf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 21:18:40 +0200 Subject: [PATCH 06/10] Support index color in video_cirrus --- video/cirrus.c | 137 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 40 deletions(-) diff --git a/video/cirrus.c b/video/cirrus.c index 2e487311e..1e55770b4 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -40,12 +40,19 @@ static struct #define CIRRUS_APERTURE_SIZE 0x200000 -#define GR_INDEX 0x3ce -#define GR_DATA 0x3cf -#define CR_INDEX 0x3d4 -#define CR_DATA 0x3d5 -#define SR_INDEX 0x3c4 -#define SR_DATA 0x3c5 +enum + { + SR_INDEX = 0x3c4, + SR_DATA = 0x3c5, + CIRRUS_PIXEL_MASK = 0x3c6, + CIRRUS_PALLETTE_READ_INDEX = 0x3c7, + CIRRUS_PALLETTE_WRITE_INDEX = 0x3c8, + CIRRUS_PALLETTE_DATA = 0x3c9, + GR_INDEX = 0x3ce, + GR_DATA = 0x3cf, + CR_INDEX = 0x3d4, + CR_DATA = 0x3d5, + }; #define CIRRUS_MAX_WIDTH 0x800 #define CIRRUS_WIDTH_DIVISOR 8 @@ -117,12 +124,14 @@ enum #define CIRRUS_SR_MEMORY_MODE_NORMAL 0 #define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0 #define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01 -#define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04 +#define CIRRUS_SR_EXTENDED_MODE_8BPP 0x00 #define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06 +#define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04 #define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08 #define CIRRUS_HIDDEN_DAC_ENABLE_EXT 0x80 #define CIRRUS_HIDDEN_DAC_ENABLE_ALL 0x40 +#define CIRRUS_HIDDEN_DAC_8BPP 0 #define CIRRUS_HIDDEN_DAC_15BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 0) #define CIRRUS_HIDDEN_DAC_16BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ @@ -175,23 +184,43 @@ sr_read (grub_uint8_t addr) static void write_hidden_dac (grub_uint8_t data) { - grub_inb (0x3c8); - grub_inb (0x3c6); - grub_inb (0x3c6); - grub_inb (0x3c6); - grub_inb (0x3c6); - grub_outb (data, 0x3c6); + grub_inb (CIRRUS_PALLETTE_WRITE_INDEX); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + grub_outb (data, CIRRUS_PIXEL_MASK); } static grub_uint8_t read_hidden_dac (void) { - grub_inb (0x3c8); - grub_inb (0x3c6); - grub_inb (0x3c6); - grub_inb (0x3c6); - grub_inb (0x3c6); - return grub_inb (0x3c6); + grub_inb (CIRRUS_PALLETTE_WRITE_INDEX); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + grub_inb (CIRRUS_PIXEL_MASK); + return grub_inb (CIRRUS_PIXEL_MASK); +} + +static void +palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, + grub_uint8_t *b) +{ + grub_outb (addr, CIRRUS_PALLETTE_READ_INDEX); + *r = grub_inb (CIRRUS_PALLETTE_DATA); + *g = grub_inb (CIRRUS_PALLETTE_DATA); + *b = grub_inb (CIRRUS_PALLETTE_DATA); +} + +static void +palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, + grub_uint8_t b) +{ + grub_outb (addr, CIRRUS_PALLETTE_READ_INDEX); + grub_outb (r, CIRRUS_PALLETTE_DATA); + grub_outb (g, CIRRUS_PALLETTE_DATA); + grub_outb (b, CIRRUS_PALLETTE_DATA); } struct saved_state @@ -202,6 +231,9 @@ struct saved_state grub_uint8_t hidden_dac; /* We need to preserve VGA font and VGA text. */ grub_uint8_t vram[32 * 4 * 256]; + grub_uint8_t r[256]; + grub_uint8_t g[256]; + grub_uint8_t b[256]; }; static struct saved_state initial_state; @@ -217,6 +249,9 @@ save_state (struct saved_state *st) st->sr[i] = sr_read (i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) st->gr[i] = gr_read (i); + for (i = 0; i < 256; i++) + palette_read (i, st->r + i, st->g + i, st->b + i); + st->hidden_dac = read_hidden_dac (); sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); @@ -234,6 +269,9 @@ restore_state (struct saved_state *st) sr_write (st->sr[i], i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) gr_write (st->gr[i], i); + for (i = 0; i < 256; i++) + palette_write (i, st->r[i], st->g[i], st->b[i]); + write_hidden_dac (st->hidden_dac); } @@ -289,9 +327,30 @@ doublebuf_pageflipping_set_page (int page) return GRUB_ERR_NONE; } +static grub_err_t +grub_video_cirrus_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + unsigned i; + if (start >= 0x100) + return GRUB_ERR_NONE; + if (start + count >= 0x100) + count = 0x100 - start; + + for (i = 0; i < count; i++) + palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + static grub_err_t grub_video_cirrus_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, unsigned int mode_mask) { int depth; grub_err_t err; @@ -342,12 +401,17 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, return grub_error (GRUB_ERR_IO, "screen height must be at most %d", CIRRUS_MAX_HEIGHT); - if (depth == 0) + if (depth == 0 + && !grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0)) depth = 24; - if (depth != 32 && depth != 24 && depth != 16 && depth != 15) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "only 32, 24, 16 and 15-bit bpp are supported"); + if (depth == 0) + depth = 8; + + if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8) + return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bit bpp are" + " supported by cirrus video"); bytes_per_pixel = (depth + 7) / 8; pitch = width * bytes_per_pixel; @@ -448,6 +512,10 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, hidden_dac = CIRRUS_HIDDEN_DAC_15BPP; sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; break; + case 8: + hidden_dac = CIRRUS_HIDDEN_DAC_8BPP; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_8BPP; + break; } sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); write_hidden_dac (hidden_dac); @@ -466,6 +534,9 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, switch (depth) { + case 8: + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; case 16: framebuffer.mode_info.red_mask_size = 5; framebuffer.mode_info.red_field_pos = 11; @@ -513,25 +584,11 @@ grub_video_cirrus_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); + err = grub_video_cirrus_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); return err; } -static grub_err_t -grub_video_cirrus_set_palette (unsigned int start, unsigned int count, - struct grub_video_palette_data *palette_data) -{ - /* if (framebuffer.index_color_mode) */ - { - /* TODO: Implement setting indexed color mode palette to hardware. */ - } - - /* Then set color to emulated palette. */ - return grub_video_fb_set_palette (start, count, palette_data); -} - - static struct grub_video_adapter grub_video_cirrus_adapter = { .name = "Cirrus CLGD 5446 PCI Video Driver", From 9a3e298a7ed8f3c2d22dbbee7fc9ea8e67859b7b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 May 2010 22:20:19 +0200 Subject: [PATCH 07/10] Fix incorrect aperture size --- video/cirrus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/cirrus.c b/video/cirrus.c index 1e55770b4..457f38898 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -38,7 +38,7 @@ static struct grub_pci_device_t dev; } framebuffer; -#define CIRRUS_APERTURE_SIZE 0x200000 +#define CIRRUS_APERTURE_SIZE 0x1000000 enum { From 368e544ba6a5b3099fd48d4f4e08d0858e2e4f2b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 17 May 2010 01:18:50 +0200 Subject: [PATCH 08/10] Add bochs video support --- conf/i386.rmk | 5 + include/grub/video.h | 3 +- video/bochs.c | 500 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 video/bochs.c diff --git a/conf/i386.rmk b/conf/i386.rmk index ce5d42f0f..5e1191c1e 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -20,6 +20,11 @@ video_cirrus_mod_SOURCES = video/cirrus.c video_cirrus_mod_CFLAGS = $(COMMON_CFLAGS) video_cirrus_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += video_bochs.mod +video_bochs_mod_SOURCES = video/bochs.c +video_bochs_mod_CFLAGS = $(COMMON_CFLAGS) +video_bochs_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += relocator.mod relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S relocator_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/include/grub/video.h b/include/grub/video.h index 08ee54938..9ffc58d86 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -183,7 +183,8 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_EFI_GOP, GRUB_VIDEO_DRIVER_SM712, GRUB_VIDEO_DRIVER_VGA, - GRUB_VIDEO_DRIVER_CIRRUS + GRUB_VIDEO_DRIVER_CIRRUS, + GRUB_VIDEO_DRIVER_BOCHS } grub_video_driver_id_t; struct grub_video_adapter diff --git a/video/bochs.c b/video/bochs.c new file mode 100644 index 000000000..da63b2912 --- /dev/null +++ b/video/bochs.c @@ -0,0 +1,500 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,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 . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct +{ + struct grub_video_mode_info mode_info; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#define BOCHS_APERTURE_SIZE 0x800000 +#define BOCHS_MAX_WIDTH 1600 +#define BOCHS_MAX_HEIGHT 1200 +#define BOCHS_WIDTH_ALIGN 8 + +enum + { + CIRRUS_SR_MEMORY_MODE = 4, + CIRRUS_SR_EXTENDED_MODE = 7, + CIRRUS_SR_MAX + }; +#define CIRRUS_SR_MEMORY_MODE_CHAIN4 8 + +enum + { + BOCHS_VBE_INDEX = 0x1ce, + BOCHS_VBE_DATA = 0x1cf, + SR_INDEX = 0x3c4, + SR_DATA = 0x3c5, + BOCHS_PALLETTE_READ_INDEX = 0x3c7, + BOCHS_PALLETTE_WRITE_INDEX = 0x3c8, + BOCHS_PALLETTE_DATA = 0x3c9, + GR_INDEX = 0x3ce, + GR_DATA = 0x3cf, + CR_INDEX = 0x3d4, + CR_DATA = 0x3d5, + }; + +enum + { + BOCHS_VBE_WIDTH = 1, + BOCHS_VBE_HEIGHT = 2, + BOCHS_VBE_BPP = 3, + BOCHS_VBE_ENABLE = 4, + BOCHS_VBE_Y_OFFSET = 9, + BOCHS_VBE_MAX + }; + +static void +vbe_write (grub_uint16_t val, grub_uint16_t addr) +{ + grub_outw (addr, BOCHS_VBE_INDEX); + grub_outw (val, BOCHS_VBE_DATA); +} + +static grub_uint16_t +vbe_read (grub_uint16_t addr) +{ + grub_outw (addr, BOCHS_VBE_INDEX); + return grub_inw (BOCHS_VBE_DATA); +} + +static void +gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GR_INDEX); + grub_outb (val, GR_DATA); +} + +static grub_uint8_t +gr_read (grub_uint8_t addr) +{ + grub_outb (addr, GR_INDEX); + return grub_inb (GR_DATA); +} + +static void +cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, CR_INDEX); + grub_outb (val, CR_DATA); +} + +static grub_uint8_t +cr_read (grub_uint8_t addr) +{ + grub_outb (addr, CR_INDEX); + return grub_inb (CR_DATA); +} + +static void +palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, + grub_uint8_t *b) +{ + grub_outb (addr, BOCHS_PALLETTE_READ_INDEX); + *r = grub_inb (BOCHS_PALLETTE_DATA); + *g = grub_inb (BOCHS_PALLETTE_DATA); + *b = grub_inb (BOCHS_PALLETTE_DATA); +} + +static void +palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, + grub_uint8_t b) +{ + grub_outb (addr, BOCHS_PALLETTE_READ_INDEX); + grub_outb (r, BOCHS_PALLETTE_DATA); + grub_outb (g, BOCHS_PALLETTE_DATA); + grub_outb (b, BOCHS_PALLETTE_DATA); +} +static void +sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, SR_INDEX); + grub_outb (val, SR_DATA); +} + +static grub_uint8_t +sr_read (grub_uint8_t addr) +{ + grub_outb (addr, SR_INDEX); + return grub_inb (SR_DATA); +} + + +struct saved_state +{ + grub_uint8_t cr[256]; + grub_uint8_t gr[256]; + grub_uint8_t sr[256]; + grub_uint8_t r[256]; + grub_uint8_t g[256]; + grub_uint8_t b[256]; + grub_uint8_t vbe[BOCHS_VBE_MAX]; + int vbe_enable; + /* We need to preserve VGA font and VGA text. */ + grub_uint8_t vram[32 * 4 * 256]; +}; + +static struct saved_state initial_state; +static int state_saved = 0; + +static void +save_state (struct saved_state *st) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + st->cr[i] = cr_read (i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + st->gr[i] = gr_read (i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + st->sr[i] = sr_read (i); + grub_printf ("%d\n", st->cr[1]); + + for (i = 0; i < 256; i++) + palette_read (i, st->r + i, st->g + i, st->b + i); + + st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1; + if (st->vbe_enable) + for (i = 0; i < ARRAY_SIZE (st->vbe); i++) + st->vbe[i] = vbe_read (i); + + sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); + sr_write (st->sr[CIRRUS_SR_MEMORY_MODE], CIRRUS_SR_MEMORY_MODE); +} + +static void +restore_state (struct saved_state *st) +{ + unsigned i; + + if (st->vbe_enable) + for (i = 0; i < ARRAY_SIZE (st->vbe); i++) + vbe_write (st->vbe[i], i); + else + vbe_write (0, BOCHS_VBE_ENABLE); + + cr_write (0, 0x11); + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + cr_write (st->cr[i], i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + sr_write (st->sr[i], i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + gr_write (st->gr[i], i); + + for (i = 0; i < 256; i++) + palette_write (i, st->r[i], st->g[i], st->b[i]); + + sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); + sr_write (st->sr[CIRRUS_SR_MEMORY_MODE], CIRRUS_SR_MEMORY_MODE); +} + +static grub_err_t +grub_video_bochs_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_bochs_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + BOCHS_APERTURE_SIZE); + + if (state_saved) + { + restore_state (&initial_state); + state_saved = 0; + } + + return grub_video_fb_fini (); +} + +static grub_err_t +doublebuf_pageflipping_set_page (int page) +{ + int start = framebuffer.mode_info.height * page; + + vbe_write (start, BOCHS_VBE_Y_OFFSET); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_bochs_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + unsigned i; + if (start >= 0x100) + return GRUB_ERR_NONE; + if (start + count >= 0x100) + count = 0x100 - start; + + for (i = 0; i < count; i++) + palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_bochs_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask) +{ + int depth; + grub_err_t err; + int found = 0; + int pitch, bytes_per_pixel; + grub_size_t page_size; /* The size of a page in bytes. */ + + 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) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if (width == 0 || height == 0) + { + width = 800; + height = 600; + } + + if (width > BOCHS_MAX_WIDTH) + return grub_error (GRUB_ERR_IO, "width must be at most", + BOCHS_MAX_WIDTH); + + if (height > BOCHS_MAX_HEIGHT) + return grub_error (GRUB_ERR_IO, "height must be at most", + BOCHS_MAX_HEIGHT); + + if (width & (BOCHS_WIDTH_ALIGN - 1)) + return grub_error (GRUB_ERR_IO, "width must be a multiple of %d", + BOCHS_WIDTH_ALIGN); + + if (depth == 0 + && !grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0)) + depth = 24; + + if (depth == 0) + depth = 8; + + if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8 + && depth != 4) + return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bpp are" + " supported by bochs video"); + + if (depth == 4) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "4-bpp isn't cupported"); + + bytes_per_pixel = (depth + 7) / 8; + if (depth == 4) + pitch = width / 2; + else + pitch = width * bytes_per_pixel; + + page_size = pitch * height; + + if (page_size > BOCHS_APERTURE_SIZE) + return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); + + if (found && framebuffer.base == 0) + { + /* FIXME: change framebuffer base */ + return grub_error (GRUB_ERR_IO, "PCI BAR not set"); + } + + /* We can safely discard volatile attribute. */ + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + BOCHS_APERTURE_SIZE); + framebuffer.mapped = 1; + + if (!state_saved) + { + save_state (&initial_state); + state_saved = 1; + } + + { + vbe_write (0, BOCHS_VBE_ENABLE); + + vbe_write (width, BOCHS_VBE_WIDTH); + vbe_write (height, BOCHS_VBE_HEIGHT); + vbe_write (depth, BOCHS_VBE_BPP); + + vbe_write (1, BOCHS_VBE_ENABLE); + doublebuf_pageflipping_set_page (0); + } + + /* Fill mode info details. */ + framebuffer.mode_info.width = width; + framebuffer.mode_info.height = height; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = depth; + framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel; + framebuffer.mode_info.pitch = pitch; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; + + switch (depth) + { + case 4: + case 8: + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + case 16: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 15: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 10; + framebuffer.mode_info.green_mask_size = 5; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 32: + framebuffer.mode_info.reserved_mask_size = 8; + framebuffer.mode_info.reserved_field_pos = 24; + + case 24: + framebuffer.mode_info.red_mask_size = 8; + framebuffer.mode_info.red_field_pos = 16; + framebuffer.mode_info.green_mask_size = 8; + framebuffer.mode_info.green_field_pos = 8; + framebuffer.mode_info.blue_mask_size = 8; + framebuffer.mode_info.blue_field_pos = 0; + break; + } + + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + + if (BOCHS_APERTURE_SIZE >= 2 * page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); + + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_bochs_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; +} + +static struct grub_video_adapter grub_video_bochs_adapter = + { + .name = "Bochs PCI Video Driver", + .id = GRUB_VIDEO_DRIVER_BOCHS, + + .init = grub_video_bochs_video_init, + .fini = grub_video_bochs_video_fini, + .setup = grub_video_bochs_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_fb_get_info_and_fini, + .set_palette = grub_video_bochs_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_fb_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_bochs) +{ + grub_video_register (&grub_video_bochs_adapter); +} + +GRUB_MOD_FINI(video_bochs) +{ + grub_video_unregister (&grub_video_bochs_adapter); +} From 967828eb5afb0ea7981d39299debc1143960a9cd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 17 May 2010 02:25:37 +0200 Subject: [PATCH 09/10] macroify and share VGA registers --- include/grub/vga.h | 161 +++++++++++++++++++++++++++ term/i386/pc/vga_text.c | 23 +--- video/bochs.c | 111 +++---------------- video/cirrus.c | 239 +++++++++++----------------------------- video/i386/pc/vga.c | 63 ++--------- 5 files changed, 254 insertions(+), 343 deletions(-) create mode 100644 include/grub/vga.h diff --git a/include/grub/vga.h b/include/grub/vga.h new file mode 100644 index 000000000..d05ddd69b --- /dev/null +++ b/include/grub/vga.h @@ -0,0 +1,161 @@ +/* + * 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_VGA_HEADER +#define GRUB_VGA_HEADER 1 + +enum + { + 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_WIDTH = 0x01, + GRUB_VGA_CR_OVERFLOW = 0x07, + GRUB_VGA_CR_CELL_HEIGHT = 0x09, + GRUB_VGA_CR_CURSOR = 0x0a, + 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_END = 0x11, + GRUB_VGA_CR_HEIGHT = 0x12, + GRUB_VGA_CR_PITCH = 0x13, + GRUB_VGA_CR_MODE = 0x17, + GRUB_VGA_CR_LINE_COMPARE = 0x18, + }; + +#define GRUB_VGA_CR_WIDTH_DIVISOR 8 +#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_CURSOR_DISABLE (1 << 5) + +#define GRUB_VGA_CR_PITCH_DIVISOR 8 + +#define GRUB_VGA_CR_MODE_TIMING_ENABLE 0x80 +#define GRUB_VGA_CR_MODE_BYTE_MODE 0x40 +#define GRUB_VGA_CR_MODE_NO_HERCULES 0x02 +#define GRUB_VGA_CR_MODE_NO_CGA 0x01 + +enum + { + GRUB_VGA_SR_MAP_MASK_REGISTER = 0x02, + GRUB_VGA_SR_MEMORY_MODE = 0x04, + }; + +#define GRUB_VGA_SR_MEMORY_MODE_CHAIN4 8 +#define GRUB_VGA_SR_MEMORY_MODE_NORMAL 0 + +enum + { + GRUB_VGA_GR_READ_MAP_REGISTER = 0x04, + GRUB_VGA_GR_MODE = 5, + GRUB_VGA_GR_GR6 = 6, + GRUB_VGA_GR_MAX + }; + +#define GRUB_VGA_GR_GR6_GRAPHICS_MODE 1 + +#define GRUB_VGA_GR_MODE_256_COLOR 0x40 +#define GRUB_VGA_GR_MODE_READ_MODE1 0x08 + +static inline void +grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_GR_INDEX); + grub_outb (val, GRUB_VGA_IO_GR_DATA); +} + +static inline grub_uint8_t +grub_vga_gr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_GR_INDEX); + return grub_inb (GRUB_VGA_IO_GR_DATA); +} + +static inline void +grub_vga_cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_CR_INDEX); + grub_outb (val, GRUB_VGA_IO_CR_DATA); +} + +static inline grub_uint8_t +grub_vga_cr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_CR_INDEX); + return grub_inb (GRUB_VGA_IO_CR_DATA); +} + +static inline void +grub_vga_sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_SR_INDEX); + grub_outb (val, GRUB_VGA_IO_SR_DATA); +} + +static inline grub_uint8_t +grub_vga_sr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_SR_INDEX); + return grub_inb (GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_vga_palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, + grub_uint8_t *b) +{ + grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX); + *r = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + *g = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + *b = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); +} + +static inline void +grub_vga_palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, + grub_uint8_t b) +{ + grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX); + grub_outb (r, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (g, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (b, GRUB_VGA_IO_PALLETTE_DATA); +} + + +#endif diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c index f954cab43..8bc14cb61 100644 --- a/term/i386/pc/vga_text.c +++ b/term/i386/pc/vga_text.c @@ -20,6 +20,7 @@ #include #include #include +#include #define COLS 80 #define ROWS 25 @@ -28,15 +29,6 @@ static int grub_curr_x, grub_curr_y; #define VGA_TEXT_SCREEN 0xb8000 -#define CRTC_ADDR_PORT 0x3D4 -#define CRTC_DATA_PORT 0x3D5 - -#define CRTC_CURSOR 0x0a -#define CRTC_CURSOR_ADDR_HIGH 0x0e -#define CRTC_CURSOR_ADDR_LOW 0x0f - -#define CRTC_CURSOR_DISABLE (1 << 5) - static void screen_write_char (int x, int y, short c) { @@ -53,10 +45,8 @@ static void update_cursor (void) { unsigned int pos = grub_curr_y * COLS + grub_curr_x; - grub_outb (CRTC_CURSOR_ADDR_HIGH, CRTC_ADDR_PORT); - grub_outb (pos >> 8, CRTC_DATA_PORT); - grub_outb (CRTC_CURSOR_ADDR_LOW, CRTC_ADDR_PORT); - grub_outb (pos & 0xFF, CRTC_DATA_PORT); + grub_vga_cr_write (pos >> 8, GRUB_VGA_CR_CURSOR_ADDR_HIGH); + grub_vga_cr_write (pos & 0xFF, GRUB_VGA_CR_CURSOR_ADDR_LOW); } static void @@ -134,12 +124,11 @@ static void grub_vga_text_setcursor (int on) { grub_uint8_t old; - grub_outb (CRTC_CURSOR, CRTC_ADDR_PORT); - old = grub_inb (CRTC_DATA_PORT); + old = grub_vga_cr_read (GRUB_VGA_CR_CURSOR); if (on) - grub_outb (old & ~CRTC_CURSOR_DISABLE, CRTC_DATA_PORT); + grub_vga_cr_write (old & ~GRUB_VGA_CR_CURSOR_DISABLE, GRUB_VGA_CR_CURSOR); else - grub_outb (old | CRTC_CURSOR_DISABLE, CRTC_DATA_PORT); + grub_vga_cr_write (old | GRUB_VGA_CR_CURSOR_DISABLE, GRUB_VGA_CR_CURSOR); } static grub_err_t diff --git a/video/bochs.c b/video/bochs.c index da63b2912..cb04df9fc 100644 --- a/video/bochs.c +++ b/video/bochs.c @@ -26,6 +26,7 @@ #include #include #include +#include static struct { @@ -42,27 +43,10 @@ static struct #define BOCHS_MAX_HEIGHT 1200 #define BOCHS_WIDTH_ALIGN 8 -enum - { - CIRRUS_SR_MEMORY_MODE = 4, - CIRRUS_SR_EXTENDED_MODE = 7, - CIRRUS_SR_MAX - }; -#define CIRRUS_SR_MEMORY_MODE_CHAIN4 8 - enum { BOCHS_VBE_INDEX = 0x1ce, BOCHS_VBE_DATA = 0x1cf, - SR_INDEX = 0x3c4, - SR_DATA = 0x3c5, - BOCHS_PALLETTE_READ_INDEX = 0x3c7, - BOCHS_PALLETTE_WRITE_INDEX = 0x3c8, - BOCHS_PALLETTE_DATA = 0x3c9, - GR_INDEX = 0x3ce, - GR_DATA = 0x3cf, - CR_INDEX = 0x3d4, - CR_DATA = 0x3d5, }; enum @@ -89,68 +73,6 @@ vbe_read (grub_uint16_t addr) return grub_inw (BOCHS_VBE_DATA); } -static void -gr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, GR_INDEX); - grub_outb (val, GR_DATA); -} - -static grub_uint8_t -gr_read (grub_uint8_t addr) -{ - grub_outb (addr, GR_INDEX); - return grub_inb (GR_DATA); -} - -static void -cr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, CR_INDEX); - grub_outb (val, CR_DATA); -} - -static grub_uint8_t -cr_read (grub_uint8_t addr) -{ - grub_outb (addr, CR_INDEX); - return grub_inb (CR_DATA); -} - -static void -palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, - grub_uint8_t *b) -{ - grub_outb (addr, BOCHS_PALLETTE_READ_INDEX); - *r = grub_inb (BOCHS_PALLETTE_DATA); - *g = grub_inb (BOCHS_PALLETTE_DATA); - *b = grub_inb (BOCHS_PALLETTE_DATA); -} - -static void -palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, - grub_uint8_t b) -{ - grub_outb (addr, BOCHS_PALLETTE_READ_INDEX); - grub_outb (r, BOCHS_PALLETTE_DATA); - grub_outb (g, BOCHS_PALLETTE_DATA); - grub_outb (b, BOCHS_PALLETTE_DATA); -} -static void -sr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, SR_INDEX); - grub_outb (val, SR_DATA); -} - -static grub_uint8_t -sr_read (grub_uint8_t addr) -{ - grub_outb (addr, SR_INDEX); - return grub_inb (SR_DATA); -} - - struct saved_state { grub_uint8_t cr[256]; @@ -174,24 +96,23 @@ save_state (struct saved_state *st) unsigned i; for (i = 0; i < ARRAY_SIZE (st->cr); i++) - st->cr[i] = cr_read (i); + st->cr[i] = grub_vga_cr_read (i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) - st->gr[i] = gr_read (i); + st->gr[i] = grub_vga_gr_read (i); for (i = 0; i < ARRAY_SIZE (st->sr); i++) - st->sr[i] = sr_read (i); - grub_printf ("%d\n", st->cr[1]); + st->sr[i] = grub_vga_sr_read (i); for (i = 0; i < 256; i++) - palette_read (i, st->r + i, st->g + i, st->b + i); + grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i); st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1; if (st->vbe_enable) for (i = 0; i < ARRAY_SIZE (st->vbe); i++) st->vbe[i] = vbe_read (i); - sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); - sr_write (st->sr[CIRRUS_SR_MEMORY_MODE], CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE); } static void @@ -205,20 +126,20 @@ restore_state (struct saved_state *st) else vbe_write (0, BOCHS_VBE_ENABLE); - cr_write (0, 0x11); + grub_vga_cr_write (0, 0x11); for (i = 0; i < ARRAY_SIZE (st->cr); i++) - cr_write (st->cr[i], i); + grub_vga_cr_write (st->cr[i], i); for (i = 0; i < ARRAY_SIZE (st->sr); i++) - sr_write (st->sr[i], i); + grub_vga_sr_write (st->sr[i], i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) - gr_write (st->gr[i], i); + grub_vga_gr_write (st->gr[i], i); for (i = 0; i < 256; i++) - palette_write (i, st->r[i], st->g[i], st->b[i]); + grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]); - sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); - sr_write (st->sr[CIRRUS_SR_MEMORY_MODE], CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE); } static grub_err_t @@ -268,8 +189,8 @@ grub_video_bochs_set_palette (unsigned int start, unsigned int count, count = 0x100 - start; for (i = 0; i < count; i++) - palette_write (start + i, palette_data[i].r, palette_data[i].g, - palette_data[i].b); + grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); } /* Then set color to emulated palette. */ diff --git a/video/cirrus.c b/video/cirrus.c index 457f38898..4a3d8243d 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -26,6 +26,7 @@ #include #include #include +#include static struct { @@ -40,69 +41,17 @@ static struct #define CIRRUS_APERTURE_SIZE 0x1000000 -enum - { - SR_INDEX = 0x3c4, - SR_DATA = 0x3c5, - CIRRUS_PIXEL_MASK = 0x3c6, - CIRRUS_PALLETTE_READ_INDEX = 0x3c7, - CIRRUS_PALLETTE_WRITE_INDEX = 0x3c8, - CIRRUS_PALLETTE_DATA = 0x3c9, - GR_INDEX = 0x3ce, - GR_DATA = 0x3cf, - CR_INDEX = 0x3d4, - CR_DATA = 0x3d5, - }; - #define CIRRUS_MAX_WIDTH 0x800 -#define CIRRUS_WIDTH_DIVISOR 8 #define CIRRUS_MAX_HEIGHT 0x800 -#define CIRRUS_MAX_PITCH (0x1ff * CIRRUS_WIDTH_DIVISOR) +#define CIRRUS_MAX_PITCH (0x1ff * GRUB_VGA_CR_PITCH_DIVISOR) enum { - CIRRUS_GR_MODE = 5, - CIRRUS_GR_GR6 = 6, - CIRRUS_GR_MAX - }; - -#define CIRRUS_GR_GR6_GRAPHICS_MODE 1 - -#define CIRRUS_GR_MODE_256_COLOR 0x40 -#define CIRRUS_GR_MODE_READ_MODE1 0x08 - -enum - { - CIRRUS_CR_WIDTH = 0x01, - CIRRUS_CR_OVERFLOW = 0x07, - CIRRUS_CR_CELL_HEIGHT = 0x09, - CIRRUS_CR_SCREEN_START_HIGH = 0xc, - CIRRUS_CR_SCREEN_START_LOW = 0xd, - CIRRUS_CR_VSYNC_END = 0x11, - CIRRUS_CR_HEIGHT = 0x12, - CIRRUS_CR_PITCH = 0x13, - CIRRUS_CR_MODE = 0x17, - CIRRUS_CR_LINE_COMPARE = 0x18, CIRRUS_CR_EXTENDED_DISPLAY = 0x1b, CIRRUS_CR_EXTENDED_OVERLAY = 0x1d, CIRRUS_CR_MAX }; -#define CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 -#define CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 - -#define CIRRUS_CR_OVERFLOW_HEIGHT1_SHIFT 7 -#define CIRRUS_CR_OVERFLOW_HEIGHT1_MASK 0x02 -#define CIRRUS_CR_OVERFLOW_HEIGHT2_SHIFT 3 -#define CIRRUS_CR_OVERFLOW_HEIGHT2_MASK 0xc0 -#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 -#define CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 - -#define CIRRUS_CR_MODE_TIMING_ENABLE 0x80 -#define CIRRUS_CR_MODE_BYTE_MODE 0x40 -#define CIRRUS_CR_MODE_NO_HERCULES 0x02 -#define CIRRUS_CR_MODE_NO_CGA 0x01 - #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1 @@ -113,15 +62,12 @@ enum #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80 #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12 - enum { - CIRRUS_SR_MEMORY_MODE = 4, CIRRUS_SR_EXTENDED_MODE = 7, CIRRUS_SR_MAX }; -#define CIRRUS_SR_MEMORY_MODE_CHAIN4 8 -#define CIRRUS_SR_MEMORY_MODE_NORMAL 0 + #define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0 #define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01 #define CIRRUS_SR_EXTENDED_MODE_8BPP 0x00 @@ -139,94 +85,32 @@ enum #define CIRRUS_HIDDEN_DAC_888COLOR (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 5) -static void -gr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, GR_INDEX); - grub_outb (val, GR_DATA); -} - -static grub_uint8_t -gr_read (grub_uint8_t addr) -{ - grub_outb (addr, GR_INDEX); - return grub_inb (GR_DATA); -} - -static void -cr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, CR_INDEX); - grub_outb (val, CR_DATA); -} - -static grub_uint8_t -cr_read (grub_uint8_t addr) -{ - grub_outb (addr, CR_INDEX); - return grub_inb (CR_DATA); -} - -static void -sr_write (grub_uint8_t val, grub_uint8_t addr) -{ - grub_outb (addr, SR_INDEX); - grub_outb (val, SR_DATA); -} - -static grub_uint8_t -sr_read (grub_uint8_t addr) -{ - grub_outb (addr, SR_INDEX); - return grub_inb (SR_DATA); -} - static void write_hidden_dac (grub_uint8_t data) { - grub_inb (CIRRUS_PALLETTE_WRITE_INDEX); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - grub_outb (data, CIRRUS_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_outb (data, GRUB_VGA_IO_PIXEL_MASK); } static grub_uint8_t read_hidden_dac (void) { - grub_inb (CIRRUS_PALLETTE_WRITE_INDEX); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - grub_inb (CIRRUS_PIXEL_MASK); - return grub_inb (CIRRUS_PIXEL_MASK); -} - -static void -palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, - grub_uint8_t *b) -{ - grub_outb (addr, CIRRUS_PALLETTE_READ_INDEX); - *r = grub_inb (CIRRUS_PALLETTE_DATA); - *g = grub_inb (CIRRUS_PALLETTE_DATA); - *b = grub_inb (CIRRUS_PALLETTE_DATA); -} - -static void -palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, - grub_uint8_t b) -{ - grub_outb (addr, CIRRUS_PALLETTE_READ_INDEX); - grub_outb (r, CIRRUS_PALLETTE_DATA); - grub_outb (g, CIRRUS_PALLETTE_DATA); - grub_outb (b, CIRRUS_PALLETTE_DATA); + grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + return grub_inb (GRUB_VGA_IO_PIXEL_MASK); } struct saved_state { grub_uint8_t cr[CIRRUS_CR_MAX]; - grub_uint8_t gr[CIRRUS_GR_MAX]; + grub_uint8_t gr[GRUB_VGA_GR_MAX]; grub_uint8_t sr[CIRRUS_SR_MAX]; grub_uint8_t hidden_dac; /* We need to preserve VGA font and VGA text. */ @@ -244,16 +128,16 @@ save_state (struct saved_state *st) { unsigned i; for (i = 0; i < ARRAY_SIZE (st->cr); i++) - st->cr[i] = cr_read (i); + st->cr[i] = grub_vga_cr_read (i); for (i = 0; i < ARRAY_SIZE (st->sr); i++) - st->sr[i] = sr_read (i); + st->sr[i] = grub_vga_sr_read (i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) - st->gr[i] = gr_read (i); + st->gr[i] = grub_vga_gr_read (i); for (i = 0; i < 256; i++) - palette_read (i, st->r + i, st->g + i, st->b + i); + grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i); st->hidden_dac = read_hidden_dac (); - sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); } @@ -261,16 +145,16 @@ static void restore_state (struct saved_state *st) { unsigned i; - sr_write (CIRRUS_SR_MEMORY_MODE_CHAIN4, CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); for (i = 0; i < ARRAY_SIZE (st->cr); i++) - cr_write (st->cr[i], i); + grub_vga_cr_write (st->cr[i], i); for (i = 0; i < ARRAY_SIZE (st->sr); i++) - sr_write (st->sr[i], i); + grub_vga_sr_write (st->sr[i], i); for (i = 0; i < ARRAY_SIZE (st->gr); i++) - gr_write (st->gr[i], i); + grub_vga_gr_write (st->gr[i], i); for (i = 0; i < 256; i++) - palette_write (i, st->r[i], st->g[i], st->b[i]); + grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]); write_hidden_dac (st->hidden_dac); } @@ -306,23 +190,24 @@ doublebuf_pageflipping_set_page (int page) int start = framebuffer.page_size * page / 4; grub_uint8_t cr_ext, cr_overlay; - cr_write (start & 0xff, CIRRUS_CR_SCREEN_START_LOW); - cr_write ((start & 0xff00) >> 8, CIRRUS_CR_SCREEN_START_HIGH); + grub_vga_cr_write (start & 0xff, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_vga_cr_write ((start & 0xff00) >> 8, + GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); - cr_ext = cr_read (CIRRUS_CR_EXTENDED_DISPLAY); + cr_ext = grub_vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY); cr_ext &= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1) & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1); cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2) & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); - cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY); + grub_vga_cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY); - cr_overlay = cr_read (CIRRUS_CR_EXTENDED_OVERLAY); + cr_overlay = grub_vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY); cr_overlay &= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); cr_overlay |= ((start >> CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT) & CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); - cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY); + grub_vga_cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY); return GRUB_ERR_NONE; } @@ -340,8 +225,8 @@ grub_video_cirrus_set_palette (unsigned int start, unsigned int count, count = 0x100 - start; for (i = 0; i < count; i++) - palette_write (start + i, palette_data[i].r, palette_data[i].g, - palette_data[i].b); + grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); } /* Then set color to emulated palette. */ @@ -388,10 +273,10 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, height = 600; } - if (width & (CIRRUS_WIDTH_DIVISOR - 1)) + if (width & (GRUB_VGA_CR_WIDTH_DIVISOR - 1)) return grub_error (GRUB_ERR_IO, "screen width must be a multiple of %d", - CIRRUS_WIDTH_DIVISOR); + GRUB_VGA_CR_WIDTH_DIVISOR); if (width > CIRRUS_MAX_WIDTH) return grub_error (GRUB_ERR_IO, @@ -452,42 +337,44 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; grub_uint8_t sr_ext = 0, hidden_dac = 0; - pitch_reg = pitch / CIRRUS_WIDTH_DIVISOR; + pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR; - gr_write (CIRRUS_GR_MODE_256_COLOR | CIRRUS_GR_MODE_READ_MODE1, - CIRRUS_GR_MODE); - gr_write (CIRRUS_GR_GR6_GRAPHICS_MODE, CIRRUS_GR_GR6); + grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1, + GRUB_VGA_GR_MODE); + grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); - sr_write (CIRRUS_SR_MEMORY_MODE_NORMAL, CIRRUS_SR_MEMORY_MODE); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); /* Disable CR0-7 write protection. */ - cr_write (0, CIRRUS_CR_VSYNC_END); + grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END); - cr_write (width / CIRRUS_WIDTH_DIVISOR - 1, CIRRUS_CR_WIDTH); - cr_write ((height - 1) & 0xff, CIRRUS_CR_HEIGHT); - overflow_reg |= (((height - 1) >> CIRRUS_CR_OVERFLOW_HEIGHT1_SHIFT) & - CIRRUS_CR_OVERFLOW_HEIGHT1_MASK) - | (((height - 1) >> CIRRUS_CR_OVERFLOW_HEIGHT2_SHIFT) & - CIRRUS_CR_OVERFLOW_HEIGHT2_MASK); + grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1, + GRUB_VGA_CR_WIDTH); + grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT); + overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & + GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) + | (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) & + GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK); - cr_write (pitch_reg & 0xff, CIRRUS_CR_PITCH); + grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH); - cr_write (line_compare & 0xff, CIRRUS_CR_LINE_COMPARE); - overflow_reg |= (line_compare >> CIRRUS_CR_OVERFLOW_LINE_COMPARE_SHIFT) - & CIRRUS_CR_OVERFLOW_LINE_COMPARE_MASK; + grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); + overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK; - cr_write (overflow_reg, CIRRUS_CR_OVERFLOW); + grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW); - cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) + grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, CIRRUS_CR_EXTENDED_DISPLAY); - cr_write ((line_compare >> CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) - & CIRRUS_CR_CELL_HEIGHT_LINE_COMPARE_MASK, CIRRUS_CR_CELL_HEIGHT); + grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT); - cr_write (CIRRUS_CR_MODE_TIMING_ENABLE | CIRRUS_CR_MODE_BYTE_MODE - | CIRRUS_CR_MODE_NO_HERCULES | CIRRUS_CR_MODE_NO_CGA, - CIRRUS_CR_MODE); + grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE + | GRUB_VGA_CR_MODE_BYTE_MODE + | GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA, + GRUB_VGA_CR_MODE); doublebuf_pageflipping_set_page (0); @@ -517,7 +404,7 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, sr_ext |= CIRRUS_SR_EXTENDED_MODE_8BPP; break; } - sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); + grub_vga_sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); write_hidden_dac (hidden_dac); } diff --git a/video/i386/pc/vga.c b/video/i386/pc/vga.c index 222a71272..7e923bddd 100644 --- a/video/i386/pc/vga.c +++ b/video/i386/pc/vga.c @@ -27,6 +27,7 @@ #include #include #include +#include #define VGA_WIDTH 640 #define VGA_HEIGHT 350 @@ -45,58 +46,26 @@ static struct int back_page; } framebuffer; -#define SEQUENCER_ADDR_PORT 0x3C4 -#define SEQUENCER_DATA_PORT 0x3C5 -#define MAP_MASK_REGISTER 0x02 - -#define CRTC_ADDR_PORT 0x3D4 -#define CRTC_DATA_PORT 0x3D5 -#define START_ADDR_HIGH_REGISTER 0x0C -#define START_ADDR_LOW_REGISTER 0x0D - -#define GRAPHICS_ADDR_PORT 0x3CE -#define GRAPHICS_DATA_PORT 0x3CF -#define READ_MAP_REGISTER 0x04 - -#define INPUT_STATUS1_REGISTER 0x3DA -#define INPUT_STATUS1_VERTR_BIT 0x08 - static inline void wait_vretrace (void) { /* Wait until there is a vertical retrace. */ - while (! (grub_inb (INPUT_STATUS1_REGISTER) & INPUT_STATUS1_VERTR_BIT)); + while (! (grub_inb (GRUB_VGA_IO_INPUT_STATUS1_REGISTER) + & GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT)); } /* Get Map Mask Register. */ static unsigned char get_map_mask (void) { - unsigned char old_addr; - unsigned char old_data; - - old_addr = grub_inb (SEQUENCER_ADDR_PORT); - grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT); - - old_data = grub_inb (SEQUENCER_DATA_PORT); - - grub_outb (old_addr, SEQUENCER_ADDR_PORT); - - return old_data; + return grub_vga_sr_read (GRUB_VGA_SR_MAP_MASK_REGISTER); } /* Set Map Mask Register. */ static void set_map_mask (unsigned char mask) { - unsigned char old_addr; - - old_addr = grub_inb (SEQUENCER_ADDR_PORT); - grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT); - - grub_outb (mask, SEQUENCER_DATA_PORT); - - grub_outb (old_addr, SEQUENCER_ADDR_PORT); + grub_vga_sr_write (mask, GRUB_VGA_SR_MAP_MASK_REGISTER); } #if 0 @@ -104,14 +73,7 @@ set_map_mask (unsigned char mask) static void set_read_map (unsigned char map) { - unsigned char old_addr; - - old_addr = grub_inb (GRAPHICS_ADDR_PORT); - - grub_outb (READ_MAP_REGISTER, GRAPHICS_ADDR_PORT); - grub_outb (map, GRAPHICS_DATA_PORT); - - grub_outb (old_addr, GRAPHICS_ADDR_PORT); + grub_vga_gr_write (map, GRUB_VGA_GR_READ_MAP_REGISTER); } #endif @@ -119,17 +81,8 @@ set_read_map (unsigned char map) static void set_start_address (unsigned int start) { - unsigned char old_addr; - - old_addr = grub_inb (CRTC_ADDR_PORT); - - grub_outb (START_ADDR_LOW_REGISTER, CRTC_ADDR_PORT); - grub_outb (start & 0xFF, CRTC_DATA_PORT); - - grub_outb (START_ADDR_HIGH_REGISTER, CRTC_ADDR_PORT); - grub_outb (start >> 8, CRTC_DATA_PORT); - - grub_outb (old_addr, CRTC_ADDR_PORT); + grub_vga_cr_write (start & 0xFF, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_vga_cr_write (start >> 8, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); } static int setup = 0; From 0e489b823382755c31f3365a400761a34424c408 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 20 Jun 2010 13:44:31 +0200 Subject: [PATCH 10/10] Remove leftover fields in sm712.c --- video/sm712.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/video/sm712.c b/video/sm712.c index 33861beef..c36a19203 100644 --- a/video/sm712.c +++ b/video/sm712.c @@ -32,10 +32,7 @@ static struct struct grub_video_mode_info mode_info; struct grub_video_render_target *render_target; - unsigned int bytes_per_scan_line; - unsigned int bytes_per_pixel; grub_uint8_t *ptr; - int index_color_mode; int mapped; grub_uint32_t base; grub_pci_device_t dev;