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
outb(unsigned short port,unsigned char value)40 outb (unsigned short port, unsigned char value)
41 {
42   asm volatile ("outb	%b0, %w1" : : "a" (value), "Nd" (port));
43 }
44 
45 static void
herc_set_cursor(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
hercules_putchar(int c)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
hercules_cls(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
hercules_getxy(void)129 hercules_getxy (void)
130 {
131   return (herc_x << 8) | herc_y;
132 }
133 
134 void
hercules_gotoxy(int x,int y)135 hercules_gotoxy (int x, int y)
136 {
137   herc_x = x;
138   herc_y = y;
139   herc_set_cursor ();
140 }
141 
142 void
hercules_setcolorstate(color_state state)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
hercules_setcolor(int normal_color,int highlight_color)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
hercules_setcursor(int on)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