blob: 81824f314457f859a6f1aebfed6ef6ab61941edc [file] [log] [blame]
wdenk7a8e9bed2003-05-31 18:35:21 +00001/*
2 * (C) Copyright 2002
Albert ARIBAUDfa82f872011-08-04 18:45:45 +02003 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
wdenk7a8e9bed2003-05-31 18:35:21 +00004 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
wdenk8bde7f72003-06-27 21:31:46 +000024#include <common.h>
25#include <pci.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020026#include <stdio_dev.h>
wdenk7a8e9bed2003-05-31 18:35:21 +000027#include <i8042.h>
wdenk8bde7f72003-06-27 21:31:46 +000028#include <asm/ptrace.h>
wdenk8bde7f72003-06-27 21:31:46 +000029#include <asm/io.h>
30#include <asm/pci.h>
wdenk7a8e9bed2003-05-31 18:35:21 +000031
wdenk7a8e9bed2003-05-31 18:35:21 +000032/* basic textmode I/O from linux kernel */
33static char *vidmem = (char *)0xb8000;
34static int vidport;
35static int lines, cols;
36static int orig_x, orig_y;
37
38static void beep(int dur)
39{
40 int i;
wdenk8bde7f72003-06-27 21:31:46 +000041
wdenk7a8e9bed2003-05-31 18:35:21 +000042 outb_p(3, 0x61);
Graeme Russdbf71152011-04-13 19:43:26 +100043 for (i = 0; i < 10*dur; i++)
wdenk7a8e9bed2003-05-31 18:35:21 +000044 udelay(1000);
Graeme Russdbf71152011-04-13 19:43:26 +100045
wdenk7a8e9bed2003-05-31 18:35:21 +000046 outb_p(0, 0x61);
47}
48
49static void scroll(void)
50{
51 int i;
52
Graeme Russdbf71152011-04-13 19:43:26 +100053 memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
54 for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
wdenk7a8e9bed2003-05-31 18:35:21 +000055 vidmem[i] = ' ';
56}
57
58static void __video_putc(const char c, int *x, int *y)
59{
60 if (c == '\n') {
wdenk8bde7f72003-06-27 21:31:46 +000061 (*x) = 0;
Graeme Russdbf71152011-04-13 19:43:26 +100062 if (++(*y) >= lines) {
wdenk7a8e9bed2003-05-31 18:35:21 +000063 scroll();
64 (*y)--;
65 }
wdenk8bde7f72003-06-27 21:31:46 +000066 } else if (c == '\b') {
wdenk7a8e9bed2003-05-31 18:35:21 +000067 if ((*x) != 0) {
68 --(*x);
Graeme Russdbf71152011-04-13 19:43:26 +100069 vidmem[((*x) + cols * (*y)) * 2] = ' ';
wdenk7a8e9bed2003-05-31 18:35:21 +000070 }
wdenk8bde7f72003-06-27 21:31:46 +000071 } else if (c == '\r') {
wdenk7a8e9bed2003-05-31 18:35:21 +000072 (*x) = 0;
wdenk8bde7f72003-06-27 21:31:46 +000073
74 } else if (c == '\a') {
wdenk7a8e9bed2003-05-31 18:35:21 +000075 beep(3);
wdenk8bde7f72003-06-27 21:31:46 +000076
77 } else if (c == '\t') {
wdenk7a8e9bed2003-05-31 18:35:21 +000078 __video_putc(' ', x, y);
79 __video_putc(' ', x, y);
80 __video_putc(' ', x, y);
81 __video_putc(' ', x, y);
82 __video_putc(' ', x, y);
83 __video_putc(' ', x, y);
84 __video_putc(' ', x, y);
85 __video_putc(' ', x, y);
wdenk8bde7f72003-06-27 21:31:46 +000086 } else if (c == '\v') {
wdenk7a8e9bed2003-05-31 18:35:21 +000087 switch ((*x) % 8) {
88 case 0:
89 __video_putc(' ', x, y);
90 case 7:
91 __video_putc(' ', x, y);
92 case 6:
93 __video_putc(' ', x, y);
94 case 5:
95 __video_putc(' ', x, y);
96 case 4:
97 __video_putc(' ', x, y);
98 case 3:
99 __video_putc(' ', x, y);
100 case 2:
101 __video_putc(' ', x, y);
102 case 1:
103 __video_putc(' ', x, y);
104 }
wdenk8bde7f72003-06-27 21:31:46 +0000105 } else if (c == '\f') {
wdenk7a8e9bed2003-05-31 18:35:21 +0000106 int i;
Graeme Russdbf71152011-04-13 19:43:26 +1000107 for (i = 0; i < lines * cols * 2; i += 2)
wdenk7a8e9bed2003-05-31 18:35:21 +0000108 vidmem[i] = 0;
wdenk7a8e9bed2003-05-31 18:35:21 +0000109 (*x) = 0;
110 (*y) = 0;
111 } else {
Graeme Russdbf71152011-04-13 19:43:26 +1000112 vidmem[((*x) + cols * (*y)) * 2] = c;
113 if (++(*x) >= cols) {
wdenk7a8e9bed2003-05-31 18:35:21 +0000114 (*x) = 0;
Graeme Russdbf71152011-04-13 19:43:26 +1000115 if (++(*y) >= lines) {
wdenk7a8e9bed2003-05-31 18:35:21 +0000116 scroll();
117 (*y)--;
118 }
119 }
120 }
121}
122
123static void video_putc(const char c)
124{
Graeme Russ83088af2011-11-08 02:33:15 +0000125 int x, y, pos;
wdenk8bde7f72003-06-27 21:31:46 +0000126
wdenk7a8e9bed2003-05-31 18:35:21 +0000127 x = orig_x;
128 y = orig_y;
wdenk8bde7f72003-06-27 21:31:46 +0000129
wdenk7a8e9bed2003-05-31 18:35:21 +0000130 __video_putc(c, &x, &y);
131
132 orig_x = x;
133 orig_y = y;
wdenk8bde7f72003-06-27 21:31:46 +0000134
wdenk7a8e9bed2003-05-31 18:35:21 +0000135 pos = (x + cols * y) * 2; /* Update cursor position */
136 outb_p(14, vidport);
137 outb_p(0xff & (pos >> 9), vidport+1);
138 outb_p(15, vidport);
139 outb_p(0xff & (pos >> 1), vidport+1);
140}
141
142static void video_puts(const char *s)
143{
Graeme Russ83088af2011-11-08 02:33:15 +0000144 int x, y, pos;
wdenk7a8e9bed2003-05-31 18:35:21 +0000145 char c;
146
147 x = orig_x;
148 y = orig_y;
149
Graeme Russdbf71152011-04-13 19:43:26 +1000150 while ((c = *s++) != '\0')
wdenk7a8e9bed2003-05-31 18:35:21 +0000151 __video_putc(c, &x, &y);
wdenk7a8e9bed2003-05-31 18:35:21 +0000152
153 orig_x = x;
154 orig_y = y;
155
156 pos = (x + cols * y) * 2; /* Update cursor position */
157 outb_p(14, vidport);
158 outb_p(0xff & (pos >> 9), vidport+1);
159 outb_p(15, vidport);
160 outb_p(0xff & (pos >> 1), vidport+1);
161}
162
163int video_init(void)
164{
165 u16 pos;
wdenk8bde7f72003-06-27 21:31:46 +0000166
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200167 static struct stdio_dev vga_dev;
168 static struct stdio_dev kbd_dev;
wdenk8bde7f72003-06-27 21:31:46 +0000169
wdenk7a8e9bed2003-05-31 18:35:21 +0000170 vidmem = (char *) 0xb8000;
171 vidport = 0x3d4;
172
173 lines = 25;
174 cols = 80;
wdenk8bde7f72003-06-27 21:31:46 +0000175
wdenk7a8e9bed2003-05-31 18:35:21 +0000176 outb_p(14, vidport);
177 pos = inb_p(vidport+1);
178 pos <<= 8;
179 outb_p(15, vidport);
180 pos |= inb_p(vidport+1);
wdenk8bde7f72003-06-27 21:31:46 +0000181
wdenk7a8e9bed2003-05-31 18:35:21 +0000182 orig_x = pos%cols;
183 orig_y = pos/cols;
184
wdenk8bde7f72003-06-27 21:31:46 +0000185#if 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000186 printf("pos %x %d %d\n", pos, orig_x, orig_y);
wdenk8bde7f72003-06-27 21:31:46 +0000187#endif
Graeme Russdbf71152011-04-13 19:43:26 +1000188 if (orig_y > lines)
Graeme Russ83088af2011-11-08 02:33:15 +0000189 orig_x = orig_y = 0;
wdenk8bde7f72003-06-27 21:31:46 +0000190
191 memset(&vga_dev, 0, sizeof(vga_dev));
192 strcpy(vga_dev.name, "vga");
193 vga_dev.ext = 0;
194 vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
195 vga_dev.putc = video_putc; /* 'putc' function */
196 vga_dev.puts = video_puts; /* 'puts' function */
197 vga_dev.tstc = NULL; /* 'tstc' function */
198 vga_dev.getc = NULL; /* 'getc' function */
199
Graeme Russdbf71152011-04-13 19:43:26 +1000200 if (stdio_register(&vga_dev) == 0)
wdenk7a8e9bed2003-05-31 18:35:21 +0000201 return 1;
Graeme Russdbf71152011-04-13 19:43:26 +1000202
203 if (i8042_kbd_init())
204 return 1;
wdenk7a8e9bed2003-05-31 18:35:21 +0000205
wdenk8bde7f72003-06-27 21:31:46 +0000206 memset(&kbd_dev, 0, sizeof(kbd_dev));
207 strcpy(kbd_dev.name, "kbd");
208 kbd_dev.ext = 0;
209 kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
210 kbd_dev.putc = NULL; /* 'putc' function */
211 kbd_dev.puts = NULL; /* 'puts' function */
212 kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
213 kbd_dev.getc = i8042_getc; /* 'getc' function */
214
Graeme Russdbf71152011-04-13 19:43:26 +1000215 if (stdio_register(&kbd_dev) == 0)
216 return 1;
217
wdenk7a8e9bed2003-05-31 18:35:21 +0000218 return 0;
219}
220
221
wdenk8bde7f72003-06-27 21:31:46 +0000222int drv_video_init(void)
wdenk7a8e9bed2003-05-31 18:35:21 +0000223{
wdenk8bde7f72003-06-27 21:31:46 +0000224 return video_init();
wdenk7a8e9bed2003-05-31 18:35:21 +0000225}