|  | /* hercules.c - hercules console interface */ | 
|  | /* | 
|  | *  GRUB  --  GRand Unified Bootloader | 
|  | *  Copyright (C) 2001  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> | 
|  |  | 
|  | /* The position of the cursor.  */ | 
|  | static unsigned hercx, hercy; | 
|  |  | 
|  | /* 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 = hercy * HERCULES_WIDTH + hercx; | 
|  |  | 
|  | outb (HERCULES_INDEX_REG, 0x0f); | 
|  | outb (0x80, 0x0f); | 
|  | outb (HERCULES_DATA_REG, offset & 0xFF); | 
|  | outb (0x80, offset & 0xFF); | 
|  |  | 
|  | outb (HERCULES_INDEX_REG, 0x0e); | 
|  | outb (0x80, 0x0e); | 
|  | outb (HERCULES_DATA_REG, offset >> 8); | 
|  | outb (0x80, offset >> 8); | 
|  | } | 
|  |  | 
|  | void | 
|  | herc_putchar (int c) | 
|  | { | 
|  |  | 
|  | switch (c) | 
|  | { | 
|  | case '\b': | 
|  | if (hercx) | 
|  | hercx--; | 
|  | break; | 
|  |  | 
|  | case '\n': | 
|  | hercy++; | 
|  | break; | 
|  |  | 
|  | case '\r': | 
|  | hercx = 0; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | { | 
|  | volatile unsigned short *video | 
|  | = (unsigned short *) HERCULES_VIDEO_ADDR; | 
|  |  | 
|  | video[hercy * HERCULES_WIDTH + hercx] = 0x0700 | c; | 
|  | hercx++; | 
|  | if (hercx >= HERCULES_WIDTH) | 
|  | { | 
|  | hercx = 0; | 
|  | hercy++; | 
|  | } | 
|  | } | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (hercy >= HERCULES_HEIGHT) | 
|  | { | 
|  | int i; | 
|  | volatile unsigned long *video = (unsigned long *) HERCULES_VIDEO_ADDR; | 
|  |  | 
|  | hercy = 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 | 
|  | herc_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; | 
|  |  | 
|  | hercx = hercy = 0; | 
|  | herc_set_cursor (); | 
|  | } | 
|  |  | 
|  | int | 
|  | herc_getxy (void) | 
|  | { | 
|  | return (hercx << 8) | hercy; | 
|  | } | 
|  |  | 
|  | void | 
|  | herc_gotoxy (int x, int y) | 
|  | { | 
|  | hercx = x; | 
|  | hercy = y; | 
|  | herc_set_cursor (); | 
|  | } | 
|  |  | 
|  | void | 
|  | herc_set_attrib (int attr) | 
|  | { | 
|  | volatile unsigned char *video = (unsigned char *) HERCULES_VIDEO_ADDR; | 
|  |  | 
|  | if (attr & 0xF0) | 
|  | attr = 0x70; | 
|  | else | 
|  | attr = 0x07; | 
|  |  | 
|  | video[((hercy * HERCULES_WIDTH + hercx) << 1) + 1] = attr; | 
|  | } | 
|  |  | 
|  | #endif /* SUPPORT_HERCULES */ |