/* hercules.c - hercules console interface */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2001,2002 Free Software Foundation, Inc. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef SUPPORT_HERCULES #include <shared.h> #include <hercules.h> #include <term.h> /* The position of the cursor. */ static int herc_x; static int herc_y; static int herc_standard_color = A_NORMAL; static int herc_normal_color = A_NORMAL; static int herc_highlight_color = A_REVERSE; static int herc_current_color = A_NORMAL; static color_state herc_color_state = COLOR_STATE_STANDARD; static int herc_cursor_state = 1; /* Write a byte to a port. */ static inline void outb (unsigned short port, unsigned char value) { asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); } static void herc_set_cursor (void) { unsigned offset = herc_y * HERCULES_WIDTH + herc_x; outb (HERCULES_INDEX_REG, 0x0f); outb (0x80, 0); outb (HERCULES_DATA_REG, offset & 0xFF); outb (0x80, 0); outb (HERCULES_INDEX_REG, 0x0e); outb (0x80, 0); outb (HERCULES_DATA_REG, offset >> 8); outb (0x80, 0); } void hercules_putchar (int c) { switch (c) { case '\b': if (herc_x > 0) herc_x--; break; case '\n': herc_y++; break; case '\r': herc_x = 0; break; case '\a': break; default: { volatile unsigned short *video = (unsigned short *) HERCULES_VIDEO_ADDR; video[herc_y * HERCULES_WIDTH + herc_x] = (herc_current_color << 8) | c; herc_x++; if (herc_x >= HERCULES_WIDTH) { herc_x = 0; herc_y++; } } break; } if (herc_y >= HERCULES_HEIGHT) { volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; int i; herc_y = HERCULES_HEIGHT - 1; grub_memmove ((char *) HERCULES_VIDEO_ADDR, (char *) HERCULES_VIDEO_ADDR + HERCULES_WIDTH * 2, HERCULES_WIDTH * (HERCULES_HEIGHT - 1) * 2); for (i = HERCULES_WIDTH * (HERCULES_HEIGHT - 1) / 2; i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; i++) video[i] = 0x07200720; } } void hercules_cls (void) { int i; volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; for (i = 0; i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; i++) video[i] = 0x07200720; herc_x = herc_y = 0; herc_set_cursor (); } int hercules_getxy (void) { return (herc_x << 8) | herc_y; } void hercules_gotoxy (int x, int y) { herc_x = x; herc_y = y; herc_set_cursor (); } void hercules_setcolorstate (color_state state) { switch (state) { case COLOR_STATE_STANDARD: herc_current_color = herc_standard_color; break; case COLOR_STATE_NORMAL: herc_current_color = herc_normal_color; break; case COLOR_STATE_HIGHLIGHT: herc_current_color = herc_highlight_color; break; default: herc_current_color = herc_standard_color; break; } herc_color_state = state; } void hercules_setcolor (int normal_color, int highlight_color) { herc_normal_color = normal_color; herc_highlight_color = highlight_color; hercules_setcolorstate (herc_color_state); } int hercules_setcursor (int on) { int old_state = herc_cursor_state; outb (HERCULES_INDEX_REG, 0x0a); outb (0x80, 0); outb (HERCULES_DATA_REG, on ? 0 : (1 << 5)); outb (0x80, 0); herc_cursor_state = on; return old_state; } #endif /* SUPPORT_HERCULES */