Home | History | Annotate | Download | only in stage2
      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