Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / video / i386 / pc / vga.c
blob08c9ca37df70383d6164b49e7995787a3e97eac2
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #define grub_video_render_target grub_video_fbrender_target
21 #include <grub/i386/pc/int.h>
22 #include <grub/machine/console.h>
23 #include <grub/cpu/io.h>
24 #include <grub/mm.h>
25 #include <grub/video.h>
26 #include <grub/video_fb.h>
27 #include <grub/types.h>
28 #include <grub/dl.h>
29 #include <grub/misc.h>
30 #include <grub/vga.h>
32 GRUB_MOD_LICENSE ("GPLv3+");
34 #define VGA_WIDTH 640
35 #define VGA_HEIGHT 350
36 #define VGA_MEM ((grub_uint8_t *) 0xa0000)
37 #define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8))
39 static unsigned char text_mode;
40 static unsigned char saved_map_mask;
42 static struct
44 struct grub_video_mode_info mode_info;
45 struct grub_video_render_target *render_target;
46 grub_uint8_t *temporary_buffer;
47 int front_page;
48 int back_page;
49 } framebuffer;
51 static unsigned char
52 grub_vga_set_mode (unsigned char mode)
54 struct grub_bios_int_registers regs;
55 unsigned char ret;
56 /* get current mode */
57 regs.eax = 0x0f00;
58 regs.ebx = 0;
59 regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
60 grub_bios_interrupt (0x10, &regs);
62 ret = regs.eax & 0xff;
63 regs.eax = mode;
64 regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
65 grub_bios_interrupt (0x10, &regs);
67 return ret;
70 static inline void
71 wait_vretrace (void)
73 /* Wait until there is a vertical retrace. */
74 while (! (grub_inb (GRUB_VGA_IO_INPUT_STATUS1_REGISTER)
75 & GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT));
78 /* Get Map Mask Register. */
79 static unsigned char
80 get_map_mask (void)
82 return grub_vga_sr_read (GRUB_VGA_SR_MAP_MASK_REGISTER);
85 /* Set Map Mask Register. */
86 static void
87 set_map_mask (unsigned char mask)
89 grub_vga_sr_write (mask, GRUB_VGA_SR_MAP_MASK_REGISTER);
92 #if 0
93 /* Set Read Map Register. */
94 static void
95 set_read_map (unsigned char map)
97 grub_vga_gr_write (map, GRUB_VGA_GR_READ_MAP_REGISTER);
99 #endif
101 /* Set start address. */
102 static void
103 set_start_address (unsigned int start)
105 grub_vga_cr_write (start & 0xFF, GRUB_VGA_CR_START_ADDR_LOW_REGISTER);
106 grub_vga_cr_write (start >> 8, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER);
109 static int setup = 0;
110 static int is_target = 0;
112 static grub_err_t
113 grub_video_vga_init (void)
115 return GRUB_ERR_NONE;
118 static grub_err_t
119 grub_video_vga_setup (unsigned int width, unsigned int height,
120 grub_video_mode_type_t mode_type,
121 grub_video_mode_type_t mode_mask)
123 grub_err_t err;
125 if ((width && width != VGA_WIDTH) || (height && height != VGA_HEIGHT))
126 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
128 framebuffer.temporary_buffer = grub_malloc (VGA_HEIGHT * VGA_WIDTH);
129 framebuffer.front_page = 0;
130 framebuffer.back_page = 0;
131 if (!framebuffer.temporary_buffer)
132 return grub_errno;
134 saved_map_mask = get_map_mask ();
136 text_mode = grub_vga_set_mode (0x10);
137 setup = 1;
138 set_map_mask (0x0f);
139 set_start_address (PAGE_OFFSET (framebuffer.front_page));
141 framebuffer.mode_info.width = VGA_WIDTH;
142 framebuffer.mode_info.height = VGA_HEIGHT;
144 framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
146 if (grub_video_check_mode_flag (mode_type, mode_mask,
147 GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, 1))
149 framebuffer.back_page = 1;
150 framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
153 framebuffer.mode_info.bpp = 8;
154 framebuffer.mode_info.bytes_per_pixel = 1;
155 framebuffer.mode_info.pitch = VGA_WIDTH;
156 framebuffer.mode_info.number_of_colors = 16;
157 framebuffer.mode_info.red_mask_size = 0;
158 framebuffer.mode_info.red_field_pos = 0;
159 framebuffer.mode_info.green_mask_size = 0;
160 framebuffer.mode_info.green_field_pos = 0;
161 framebuffer.mode_info.blue_mask_size = 0;
162 framebuffer.mode_info.blue_field_pos = 0;
163 framebuffer.mode_info.reserved_mask_size = 0;
164 framebuffer.mode_info.reserved_field_pos = 0;
166 framebuffer.mode_info.blit_format
167 = grub_video_get_blit_format (&framebuffer.mode_info);
169 err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target,
170 &framebuffer.mode_info,
171 framebuffer.temporary_buffer);
173 if (err)
175 grub_dprintf ("video", "Couldn't create FB target\n");
176 return err;
179 is_target = 1;
180 err = grub_video_fb_set_active_render_target (framebuffer.render_target);
182 if (err)
183 return err;
185 err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
186 grub_video_fbstd_colors);
188 return GRUB_ERR_NONE;
191 static grub_err_t
192 grub_video_vga_fini (void)
194 if (setup)
196 set_map_mask (saved_map_mask);
197 grub_vga_set_mode (text_mode);
199 setup = 0;
200 grub_free (framebuffer.temporary_buffer);
201 framebuffer.temporary_buffer = 0;
202 return GRUB_ERR_NONE;
205 static inline void
206 update_target (void)
208 int plane;
210 if (!is_target)
211 return;
213 for (plane = 0x01; plane <= 0x08; plane <<= 1)
215 grub_uint8_t *ptr;
216 volatile grub_uint8_t *ptr2;
217 unsigned cbyte = 0;
218 int shift = 7;
219 set_map_mask (plane);
220 for (ptr = framebuffer.temporary_buffer,
221 ptr2 = VGA_MEM + PAGE_OFFSET (framebuffer.back_page);
222 ptr < framebuffer.temporary_buffer + VGA_WIDTH * VGA_HEIGHT; ptr++)
224 cbyte |= (!!(plane & *ptr)) << shift;
225 shift--;
226 if (shift == -1)
228 *ptr2++ = cbyte;
229 shift = 7;
230 cbyte = 0;
236 static grub_err_t
237 grub_video_vga_blit_bitmap (struct grub_video_bitmap *bitmap,
238 enum grub_video_blit_operators oper, int x, int y,
239 int offset_x, int offset_y,
240 unsigned int width, unsigned int height)
242 grub_err_t ret;
243 ret = grub_video_fb_blit_bitmap (bitmap, oper, x, y, offset_x, offset_y,
244 width, height);
245 update_target ();
246 return ret;
249 static grub_err_t
250 grub_video_vga_blit_render_target (struct grub_video_fbrender_target *source,
251 enum grub_video_blit_operators oper,
252 int x, int y, int offset_x, int offset_y,
253 unsigned int width, unsigned int height)
255 grub_err_t ret;
257 ret = grub_video_fb_blit_render_target (source, oper, x, y,
258 offset_x, offset_y, width, height);
259 update_target ();
261 return ret;
264 static grub_err_t
265 grub_video_vga_set_active_render_target (struct grub_video_render_target *target)
267 if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
269 is_target = 1;
270 target = framebuffer.render_target;
272 else
273 is_target = 0;
275 return grub_video_fb_set_active_render_target (target);
278 static grub_err_t
279 grub_video_vga_get_active_render_target (struct grub_video_render_target **target)
281 grub_err_t err;
282 err = grub_video_fb_get_active_render_target (target);
283 if (err)
284 return err;
286 if (*target == framebuffer.render_target)
287 *target = GRUB_VIDEO_RENDER_TARGET_DISPLAY;
289 return GRUB_ERR_NONE;
292 static grub_err_t
293 grub_video_vga_swap_buffers (void)
295 if (!(framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED))
296 return GRUB_ERR_NONE;
298 /* Activate the other page. */
299 framebuffer.front_page = !framebuffer.front_page;
300 framebuffer.back_page = !framebuffer.back_page;
301 wait_vretrace ();
302 set_start_address (PAGE_OFFSET (framebuffer.front_page));
304 return GRUB_ERR_NONE;
307 static grub_err_t
308 grub_video_vga_set_palette (unsigned int start __attribute__ ((unused)),
309 unsigned int count __attribute__ ((unused)),
310 struct grub_video_palette_data *palette_data __attribute__ ((unused)))
312 return grub_error (GRUB_ERR_IO, "can't change palette");
315 static grub_err_t
316 grub_video_vga_get_info_and_fini (struct grub_video_mode_info *mode_info,
317 void **framebuf)
319 set_map_mask (0xf);
321 grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
322 mode_info->bpp = 1;
323 mode_info->bytes_per_pixel = 0;
324 mode_info->pitch = VGA_WIDTH / 8;
325 mode_info->number_of_colors = 1;
327 mode_info->bg_red = 0;
328 mode_info->bg_green = 0;
329 mode_info->bg_blue = 0;
330 mode_info->bg_alpha = 255;
332 mode_info->fg_red = 255;
333 mode_info->fg_green = 255;
334 mode_info->fg_blue = 255;
335 mode_info->fg_alpha = 255;
337 *framebuf = VGA_MEM + PAGE_OFFSET (framebuffer.front_page);
339 grub_video_fb_fini ();
340 grub_free (framebuffer.temporary_buffer);
341 framebuffer.temporary_buffer = 0;
342 setup = 0;
344 return GRUB_ERR_NONE;
348 static struct grub_video_adapter grub_video_vga_adapter =
350 .name = "VGA Video Driver",
351 .id = GRUB_VIDEO_DRIVER_VGA,
353 .prio = GRUB_VIDEO_ADAPTER_PRIO_FALLBACK,
355 .init = grub_video_vga_init,
356 .fini = grub_video_vga_fini,
357 .setup = grub_video_vga_setup,
358 .get_info = grub_video_fb_get_info,
359 .get_info_and_fini = grub_video_vga_get_info_and_fini,
360 .set_palette = grub_video_vga_set_palette,
361 .get_palette = grub_video_fb_get_palette,
362 .set_viewport = grub_video_fb_set_viewport,
363 .get_viewport = grub_video_fb_get_viewport,
364 .map_color = grub_video_fb_map_color,
365 .map_rgb = grub_video_fb_map_rgb,
366 .map_rgba = grub_video_fb_map_rgba,
367 .unmap_color = grub_video_fb_unmap_color,
368 .fill_rect = grub_video_fb_fill_rect,
369 .blit_bitmap = grub_video_vga_blit_bitmap,
370 .blit_render_target = grub_video_vga_blit_render_target,
371 .scroll = grub_video_fb_scroll,
372 .swap_buffers = grub_video_vga_swap_buffers,
373 .create_render_target = grub_video_fb_create_render_target,
374 .delete_render_target = grub_video_fb_delete_render_target,
375 .set_active_render_target = grub_video_vga_set_active_render_target,
376 .get_active_render_target = grub_video_vga_get_active_render_target,
378 .next = 0
381 GRUB_MOD_INIT(vga)
383 grub_video_register (&grub_video_vga_adapter);
386 GRUB_MOD_FINI(vga)
388 grub_video_unregister (&grub_video_vga_adapter);