summaryrefslogtreecommitdiffstats
path: root/drivers/video/fbcon-hga.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbcon-hga.c')
-rw-r--r--drivers/video/fbcon-hga.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/drivers/video/fbcon-hga.c b/drivers/video/fbcon-hga.c
new file mode 100644
index 000000000..384e0a917
--- /dev/null
+++ b/drivers/video/fbcon-hga.c
@@ -0,0 +1,245 @@
+/*
+ * linux/drivers/video/fbcon-hga.c -- Low level frame buffer operations for
+ * the Hercules graphics adaptor
+ *
+ * Created 25 Nov 1999 by Ferenc Bakonyi (fero@drama.obuda.kando.hu)
+ * Based on fbcon-mfb.c by Geert Uytterhoeven
+ *
+ * History:
+ *
+ * - Revision 0.1.0 (6 Dec 1999): comment changes
+ * - First release (25 Nov 1999)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-hga.h>
+
+#if 0
+#define DPRINTK(args...) printk(KERN_DEBUG __FILE__": " ##args)
+#else
+#define DPRINTK(args...)
+#endif
+
+#define HGA_ROWADDR(row) ((row%4)*8192 + (row>>2)*90)
+
+ /*
+ * Hercules monochrome
+ */
+
+static inline u8* rowaddr(struct display *p, u_int row)
+{
+ return p->screen_base + HGA_ROWADDR(row);
+}
+
+void fbcon_hga_setup(struct display *p)
+{
+ DPRINTK("fbcon_hga_setup: ll:%d\n", (int)p->line_length);
+
+ p->next_line = p->line_length;
+ p->next_plane = 0;
+}
+
+void fbcon_hga_bmove(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ u8 *src, *dest;
+ u_int rows, y1, y2;
+
+#if 0
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*fontheight(p)*width;
+ dest = p->screen_base+dy*fontheight(p)*width;
+ fb_memmove(dest, src, height*fontheight(p)*width);
+ } else
+#endif
+ if (dy <= sy) {
+ y1 = sy*fontheight(p);
+ y2 = dy*fontheight(p);
+ for (rows = height*fontheight(p); rows--; ) {
+ src = rowaddr(p, y1)+sx;
+ dest = rowaddr(p, y2)+dx;
+ fb_memmove(dest, src, width);
+ y1++;
+ y2++;
+ }
+ } else {
+ y1 = (sy+height)*fontheight(p)-1;
+ y2 = (dy+height)*fontheight(p)-1;
+ for (rows = height*fontheight(p); rows--;) {
+ src = rowaddr(p, y1)+sx;
+ dest = rowaddr(p, y2)+dx;
+ fb_memmove(dest, src, width);
+ y1--;
+ y2--;
+ }
+ }
+}
+
+void fbcon_hga_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ u8 *dest;
+ u_int rows, y;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+ DPRINTK("fbcon_hga_clear: sx:%d, sy:%d, height:%d, width:%d\n", sx, sy, height, width);
+
+ y = sy*fontheight(p);
+#if 0
+ if (sx == 0 && width == p->next_line) {
+ if (inverse) {
+ fb_memset255(dest, height*fontheight(p)*width);
+ } else {
+ fb_memclear(dest, height*fontheight(p)*width);
+ }
+ } else
+#endif
+ for (rows = height*fontheight(p); rows--; y++) {
+ dest = rowaddr(p, y)+sx;
+ if (inverse) {
+ fb_memset255(dest, width);
+ } else {
+ fb_memclear(dest, width);
+ }
+ }
+}
+
+void fbcon_hga_putc(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ u8 *dest, *cdat;
+ u_int rows, y, bold, revs, underl;
+ u8 d;
+
+ cdat = p->fontdata+(c&p->charmask)*fontheight(p);
+ bold = attr_bold(p, c);
+ revs = attr_reverse(p, c);
+ underl = attr_underline(p, c);
+ y = yy*fontheight(p);
+
+ for (rows = fontheight(p); rows--; y++) {
+ d = *cdat++;
+ if (underl && !rows)
+ d = 0xff;
+ else if (bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ dest = rowaddr(p, y)+xx;
+ *dest = d;
+ }
+}
+
+void fbcon_hga_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ u8 *dest, *cdat;
+ u_int rows, y, y0, bold, revs, underl;
+ u8 d;
+ u16 c;
+
+ bold = attr_bold(p,scr_readw(s));
+ revs = attr_reverse(p,scr_readw(s));
+ underl = attr_underline(p,scr_readw(s));
+ y0 = yy*fontheight(p);
+
+ while (count--) {
+ c = scr_readw(s++) & p->charmask;
+ cdat = p->fontdata+c*fontheight(p);
+ y = y0;
+ for (rows = fontheight(p); rows--; y++) {
+ d = *cdat++;
+ if (underl && !rows)
+ d = 0xff;
+ else if (bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ dest = rowaddr(p, y)+xx;
+ *dest = d;
+ }
+ xx++;
+ }
+}
+
+void fbcon_hga_revc(struct display *p, int xx, int yy)
+{
+ u8 *dest;
+ u_int rows, y;
+
+ y = yy*fontheight(p);
+ for (rows = fontheight(p); rows--; y++) {
+ dest = rowaddr(p, y)+xx;
+ *dest = ~*dest;
+ }
+}
+
+void fbcon_hga_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ u8 *dest;
+ u_int height, y;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+ DPRINTK("fbcon_hga_clear_margins: enter\n");
+
+ /* No need to handle right margin. */
+
+ y = conp->vc_rows * fontheight(p);
+ for (height = p->var.yres - y; height-- > 0; y++) {
+ DPRINTK("fbcon_hga_clear_margins: y:%d, height:%d\n", y, height);
+ dest = rowaddr(p, y);
+ if (inverse) {
+ fb_memset255(dest, p->next_line);
+ } else {
+ fb_memclear(dest, p->next_line);
+ }
+ }
+}
+
+
+ /*
+ * `switch' for the low level operations
+ */
+
+struct display_switch fbcon_hga = {
+ fbcon_hga_setup, fbcon_hga_bmove, fbcon_hga_clear, fbcon_hga_putc,
+ fbcon_hga_putcs, fbcon_hga_revc, NULL, NULL, fbcon_hga_clear_margins,
+ FONTWIDTH(8)
+};
+
+
+#ifdef MODULE
+int init_module(void)
+{
+ return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif /* MODULE */
+
+
+ /*
+ * Visible symbols for modules
+ */
+
+EXPORT_SYMBOL(fbcon_hga);
+EXPORT_SYMBOL(fbcon_hga_setup);
+EXPORT_SYMBOL(fbcon_hga_bmove);
+EXPORT_SYMBOL(fbcon_hga_clear);
+EXPORT_SYMBOL(fbcon_hga_putc);
+EXPORT_SYMBOL(fbcon_hga_putcs);
+EXPORT_SYMBOL(fbcon_hga_revc);
+EXPORT_SYMBOL(fbcon_hga_clear_margins);