1 /* hercules.c - hercules console interface */ 2 /* 3 * GRUB -- GRand Unified Bootloader 4 * Copyright (C) 2001,2002 Free Software Foundation, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #ifdef SUPPORT_HERCULES 22 23 #include <shared.h> 24 #include <hercules.h> 25 #include <term.h> 26 27 /* The position of the cursor. */ 28 static int herc_x; 29 static int herc_y; 30 31 static int herc_standard_color = A_NORMAL; 32 static int herc_normal_color = A_NORMAL; 33 static int herc_highlight_color = A_REVERSE; 34 static int herc_current_color = A_NORMAL; 35 static color_state herc_color_state = COLOR_STATE_STANDARD; 36 static int herc_cursor_state = 1; 37 38 /* Write a byte to a port. */ 39 static inline void 40 outb (unsigned short port, unsigned char value) 41 { 42 asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); 43 } 44 45 static void 46 herc_set_cursor (void) 47 { 48 unsigned offset = herc_y * HERCULES_WIDTH + herc_x; 49 50 outb (HERCULES_INDEX_REG, 0x0f); 51 outb (0x80, 0); 52 outb (HERCULES_DATA_REG, offset & 0xFF); 53 outb (0x80, 0); 54 55 outb (HERCULES_INDEX_REG, 0x0e); 56 outb (0x80, 0); 57 outb (HERCULES_DATA_REG, offset >> 8); 58 outb (0x80, 0); 59 } 60 61 void 62 hercules_putchar (int c) 63 { 64 switch (c) 65 { 66 case '\b': 67 if (herc_x > 0) 68 herc_x--; 69 break; 70 71 case '\n': 72 herc_y++; 73 break; 74 75 case '\r': 76 herc_x = 0; 77 break; 78 79 case '\a': 80 break; 81 82 default: 83 { 84 volatile unsigned short *video 85 = (unsigned short *) HERCULES_VIDEO_ADDR; 86 87 video[herc_y * HERCULES_WIDTH + herc_x] 88 = (herc_current_color << 8) | c; 89 herc_x++; 90 if (herc_x >= HERCULES_WIDTH) 91 { 92 herc_x = 0; 93 herc_y++; 94 } 95 } 96 break; 97 } 98 99 if (herc_y >= HERCULES_HEIGHT) 100 { 101 volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; 102 int i; 103 104 herc_y = HERCULES_HEIGHT - 1; 105 grub_memmove ((char *) HERCULES_VIDEO_ADDR, 106 (char *) HERCULES_VIDEO_ADDR + HERCULES_WIDTH * 2, 107 HERCULES_WIDTH * (HERCULES_HEIGHT - 1) * 2); 108 for (i = HERCULES_WIDTH * (HERCULES_HEIGHT - 1) / 2; 109 i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; 110 i++) 111 video[i] = 0x07200720; 112 } 113 } 114 115 void 116 hercules_cls (void) 117 { 118 int i; 119 volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; 120 121 for (i = 0; i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; i++) 122 video[i] = 0x07200720; 123 124 herc_x = herc_y = 0; 125 herc_set_cursor (); 126 } 127 128 int 129 hercules_getxy (void) 130 { 131 return (herc_x << 8) | herc_y; 132 } 133 134 void 135 hercules_gotoxy (int x, int y) 136 { 137 herc_x = x; 138 herc_y = y; 139 herc_set_cursor (); 140 } 141 142 void 143 hercules_setcolorstate (color_state state) 144 { 145 switch (state) { 146 case COLOR_STATE_STANDARD: 147 herc_current_color = herc_standard_color; 148 break; 149 case COLOR_STATE_NORMAL: 150 herc_current_color = herc_normal_color; 151 break; 152 case COLOR_STATE_HIGHLIGHT: 153 herc_current_color = herc_highlight_color; 154 break; 155 default: 156 herc_current_color = herc_standard_color; 157 break; 158 } 159 160 herc_color_state = state; 161 } 162 163 void 164 hercules_setcolor (int normal_color, int highlight_color) 165 { 166 herc_normal_color = normal_color; 167 herc_highlight_color = highlight_color; 168 169 hercules_setcolorstate (herc_color_state); 170 } 171 172 int 173 hercules_setcursor (int on) 174 { 175 int old_state = herc_cursor_state; 176 177 outb (HERCULES_INDEX_REG, 0x0a); 178 outb (0x80, 0); 179 outb (HERCULES_DATA_REG, on ? 0 : (1 << 5)); 180 outb (0x80, 0); 181 herc_cursor_state = on; 182 183 return old_state; 184 } 185 186 #endif /* SUPPORT_HERCULES */ 187