17c478bd9Sstevel@tonic-gate /* hercules.c - hercules console interface */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  *  GRUB  --  GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate  *  Copyright (C) 2001,2002  Free Software Foundation, Inc.
57c478bd9Sstevel@tonic-gate  *
67c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
77c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
87c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
97c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
127c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
137c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
147c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
157c478bd9Sstevel@tonic-gate  *
167c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
177c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
187c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
197c478bd9Sstevel@tonic-gate  */
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate #ifdef SUPPORT_HERCULES
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate #include <shared.h>
247c478bd9Sstevel@tonic-gate #include <hercules.h>
257c478bd9Sstevel@tonic-gate #include <term.h>
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /* The position of the cursor.  */
287c478bd9Sstevel@tonic-gate static int herc_x;
297c478bd9Sstevel@tonic-gate static int herc_y;
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate static int herc_standard_color = A_NORMAL;
327c478bd9Sstevel@tonic-gate static int herc_normal_color = A_NORMAL;
337c478bd9Sstevel@tonic-gate static int herc_highlight_color = A_REVERSE;
347c478bd9Sstevel@tonic-gate static int herc_current_color = A_NORMAL;
357c478bd9Sstevel@tonic-gate static color_state herc_color_state = COLOR_STATE_STANDARD;
367c478bd9Sstevel@tonic-gate static int herc_cursor_state = 1;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* Write a byte to a port.  */
397c478bd9Sstevel@tonic-gate static inline void
outb(unsigned short port,unsigned char value)407c478bd9Sstevel@tonic-gate outb (unsigned short port, unsigned char value)
417c478bd9Sstevel@tonic-gate {
427c478bd9Sstevel@tonic-gate   asm volatile ("outb	%b0, %w1" : : "a" (value), "Nd" (port));
437c478bd9Sstevel@tonic-gate }
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate static void
herc_set_cursor(void)467c478bd9Sstevel@tonic-gate herc_set_cursor (void)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate   unsigned offset = herc_y * HERCULES_WIDTH + herc_x;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate   outb (HERCULES_INDEX_REG, 0x0f);
517c478bd9Sstevel@tonic-gate   outb (0x80, 0);
527c478bd9Sstevel@tonic-gate   outb (HERCULES_DATA_REG, offset & 0xFF);
537c478bd9Sstevel@tonic-gate   outb (0x80, 0);
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate   outb (HERCULES_INDEX_REG, 0x0e);
567c478bd9Sstevel@tonic-gate   outb (0x80, 0);
577c478bd9Sstevel@tonic-gate   outb (HERCULES_DATA_REG, offset >> 8);
587c478bd9Sstevel@tonic-gate   outb (0x80, 0);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate void
hercules_putchar(int c)627c478bd9Sstevel@tonic-gate hercules_putchar (int c)
637c478bd9Sstevel@tonic-gate {
647c478bd9Sstevel@tonic-gate   switch (c)
657c478bd9Sstevel@tonic-gate     {
667c478bd9Sstevel@tonic-gate     case '\b':
677c478bd9Sstevel@tonic-gate       if (herc_x > 0)
687c478bd9Sstevel@tonic-gate 	herc_x--;
697c478bd9Sstevel@tonic-gate       break;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate     case '\n':
727c478bd9Sstevel@tonic-gate       herc_y++;
737c478bd9Sstevel@tonic-gate       break;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate     case '\r':
767c478bd9Sstevel@tonic-gate       herc_x = 0;
777c478bd9Sstevel@tonic-gate       break;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate     case '\a':
807c478bd9Sstevel@tonic-gate       break;
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate     default:
837c478bd9Sstevel@tonic-gate       {
847c478bd9Sstevel@tonic-gate 	volatile unsigned short *video
857c478bd9Sstevel@tonic-gate 	  = (unsigned short *) HERCULES_VIDEO_ADDR;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	video[herc_y * HERCULES_WIDTH + herc_x]
887c478bd9Sstevel@tonic-gate 	  = (herc_current_color << 8) | c;
897c478bd9Sstevel@tonic-gate 	herc_x++;
907c478bd9Sstevel@tonic-gate 	if (herc_x >= HERCULES_WIDTH)
917c478bd9Sstevel@tonic-gate 	  {
927c478bd9Sstevel@tonic-gate 	    herc_x = 0;
937c478bd9Sstevel@tonic-gate 	    herc_y++;
947c478bd9Sstevel@tonic-gate 	  }
957c478bd9Sstevel@tonic-gate       }
967c478bd9Sstevel@tonic-gate       break;
977c478bd9Sstevel@tonic-gate     }
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate   if (herc_y >= HERCULES_HEIGHT)
1007c478bd9Sstevel@tonic-gate     {
1017c478bd9Sstevel@tonic-gate       volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR;
1027c478bd9Sstevel@tonic-gate       int i;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate       herc_y = HERCULES_HEIGHT - 1;
1057c478bd9Sstevel@tonic-gate       grub_memmove ((char *) HERCULES_VIDEO_ADDR,
1067c478bd9Sstevel@tonic-gate 		    (char *) HERCULES_VIDEO_ADDR + HERCULES_WIDTH * 2,
1077c478bd9Sstevel@tonic-gate 		    HERCULES_WIDTH * (HERCULES_HEIGHT - 1) * 2);
1087c478bd9Sstevel@tonic-gate       for (i = HERCULES_WIDTH * (HERCULES_HEIGHT - 1) / 2;
1097c478bd9Sstevel@tonic-gate 	   i < HERCULES_WIDTH * HERCULES_HEIGHT / 2;
1107c478bd9Sstevel@tonic-gate 	   i++)
1117c478bd9Sstevel@tonic-gate 	video[i] = 0x07200720;
1127c478bd9Sstevel@tonic-gate     }
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate void
hercules_cls(void)1167c478bd9Sstevel@tonic-gate hercules_cls (void)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate   int i;
1197c478bd9Sstevel@tonic-gate   volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate   for (i = 0; i < HERCULES_WIDTH * HERCULES_HEIGHT / 2; i++)
1227c478bd9Sstevel@tonic-gate     video[i] = 0x07200720;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate   herc_x = herc_y = 0;
1257c478bd9Sstevel@tonic-gate   herc_set_cursor ();
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate int
hercules_getxy(void)1297c478bd9Sstevel@tonic-gate hercules_getxy (void)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate   return (herc_x << 8) | herc_y;
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate void
hercules_gotoxy(int x,int y)1357c478bd9Sstevel@tonic-gate hercules_gotoxy (int x, int y)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate   herc_x = x;
1387c478bd9Sstevel@tonic-gate   herc_y = y;
1397c478bd9Sstevel@tonic-gate   herc_set_cursor ();
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate void
hercules_setcolorstate(color_state state)1437c478bd9Sstevel@tonic-gate hercules_setcolorstate (color_state state)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate   switch (state) {
1467c478bd9Sstevel@tonic-gate     case COLOR_STATE_STANDARD:
1477c478bd9Sstevel@tonic-gate       herc_current_color = herc_standard_color;
1487c478bd9Sstevel@tonic-gate       break;
1497c478bd9Sstevel@tonic-gate     case COLOR_STATE_NORMAL:
1507c478bd9Sstevel@tonic-gate       herc_current_color = herc_normal_color;
1517c478bd9Sstevel@tonic-gate       break;
1527c478bd9Sstevel@tonic-gate     case COLOR_STATE_HIGHLIGHT:
1537c478bd9Sstevel@tonic-gate       herc_current_color = herc_highlight_color;
1547c478bd9Sstevel@tonic-gate       break;
1557c478bd9Sstevel@tonic-gate     default:
1567c478bd9Sstevel@tonic-gate       herc_current_color = herc_standard_color;
1577c478bd9Sstevel@tonic-gate       break;
1587c478bd9Sstevel@tonic-gate   }
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate   herc_color_state = state;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate void
hercules_setcolor(int normal_color,int highlight_color)1647c478bd9Sstevel@tonic-gate hercules_setcolor (int normal_color, int highlight_color)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate   herc_normal_color = normal_color;
1677c478bd9Sstevel@tonic-gate   herc_highlight_color = highlight_color;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate   hercules_setcolorstate (herc_color_state);
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
hercules_setcursor(int on)1737c478bd9Sstevel@tonic-gate hercules_setcursor (int on)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate   int old_state = herc_cursor_state;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate   outb (HERCULES_INDEX_REG, 0x0a);
1787c478bd9Sstevel@tonic-gate   outb (0x80, 0);
1797c478bd9Sstevel@tonic-gate   outb (HERCULES_DATA_REG, on ? 0 : (1 << 5));
1807c478bd9Sstevel@tonic-gate   outb (0x80, 0);
1817c478bd9Sstevel@tonic-gate   herc_cursor_state = on;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate   return old_state;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate #endif /* SUPPORT_HERCULES */
187