source: mainline/kernel/genarch/src/drivers/ega/ega.c@ 2398ee9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2398ee9 was accc088, checked in by Martin Decky <martin@…>, 17 years ago

convert Unicode characters to OEM (a.k.a. 437) code page
add colors to EGA output

  • Property mode set to 100644
File size: 10.1 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup genarch_drivers
30 * @{
31 */
32/**
33 * @file
34 * @brief EGA driver.
35 */
36
37#include <genarch/drivers/ega/ega.h>
38#include <putchar.h>
39#include <mm/page.h>
40#include <mm/as.h>
41#include <mm/slab.h>
42#include <arch/mm/page.h>
43#include <synch/spinlock.h>
44#include <arch/types.h>
45#include <arch/asm.h>
46#include <memstr.h>
47#include <console/chardev.h>
48#include <console/console.h>
49#include <sysinfo/sysinfo.h>
50#include <ddi/ddi.h>
51
52/*
53 * The EGA driver.
54 * Simple and short. Function for displaying characters and "scrolling".
55 */
56
57SPINLOCK_INITIALIZE(egalock);
58static uint32_t ega_cursor;
59static uint8_t *videoram;
60static uint8_t *backbuf;
61static ioport8_t *ega_base;
62
63#define SPACE 0x20
64#define STYLE 0x1e
65#define INVAL 0x17
66
67#define EMPTY_CHAR ((STYLE << 8) | SPACE)
68
69static uint16_t ega_oem_glyph(const wchar_t ch)
70{
71 if ((ch >= 0x0000) && (ch <= 0x007f))
72 return ch;
73
74 if (ch == 0x00a0)
75 return 255;
76
77 if (ch == 0x00a1)
78 return 173;
79
80 if ((ch >= 0x00a2) && (ch <= 0x00a3))
81 return (ch - 7);
82
83 if (ch == 0x00a5)
84 return 157;
85
86 if (ch == 0x00aa)
87 return 166;
88
89 if (ch == 0x00ab)
90 return 174;
91
92 if (ch == 0x00ac)
93 return 170;
94
95 if (ch == 0x00b0)
96 return 248;
97
98 if (ch == 0x00b1)
99 return 241;
100
101 if (ch == 0x00b2)
102 return 253;
103
104 if (ch == 0x00b5)
105 return 230;
106
107 if (ch == 0x00b7)
108 return 250;
109
110 if (ch == 0x00ba)
111 return 167;
112
113 if (ch == 0x00bb)
114 return 175;
115
116 if (ch == 0x00bc)
117 return 172;
118
119 if (ch == 0x00bd)
120 return 171;
121
122 if (ch == 0x00bf)
123 return 168;
124
125 if ((ch >= 0x00c4) && (ch <= 0x00c5))
126 return (ch - 54);
127
128 if (ch == 0x00c6)
129 return 146;
130
131 if (ch == 0x00c7)
132 return 128;
133
134 if (ch == 0x00c9)
135 return 144;
136
137 if (ch == 0x00d1)
138 return 165;
139
140 if (ch == 0x00d6)
141 return 153;
142
143 if (ch == 0x00dc)
144 return 154;
145
146 if (ch == 0x00df)
147 return 225;
148
149 if (ch == 0x00e0)
150 return 133;
151
152 if (ch == 0x00e1)
153 return 160;
154
155 if (ch == 0x00e2)
156 return 131;
157
158 if (ch == 0x00e4)
159 return 132;
160
161 if (ch == 0x00e5)
162 return 134;
163
164 if (ch == 0x00e6)
165 return 145;
166
167 if (ch == 0x00e7)
168 return 135;
169
170 if (ch == 0x00e8)
171 return 138;
172
173 if (ch == 0x00e9)
174 return 130;
175
176 if ((ch >= 0x00ea) && (ch <= 0x00eb))
177 return (ch - 98);
178
179 if (ch == 0x00ec)
180 return 141;
181
182 if (ch == 0x00ed)
183 return 161;
184
185 if (ch == 0x00ee)
186 return 140;
187
188 if (ch == 0x00ef)
189 return 139;
190
191 if (ch == 0x00f1)
192 return 164;
193
194 if (ch == 0x00f2)
195 return 149;
196
197 if (ch == 0x00f3)
198 return 162;
199
200 if (ch == 0x00f4)
201 return 147;
202
203 if (ch == 0x00f6)
204 return 148;
205
206 if (ch == 0x00f7)
207 return 246;
208
209 if (ch == 0x00f9)
210 return 151;
211
212 if (ch == 0x00fa)
213 return 163;
214
215 if (ch == 0x00fb)
216 return 150;
217
218 if (ch == 0x00fc)
219 return 129;
220
221 if (ch == 0x00ff)
222 return 152;
223
224 if (ch == 0x0192)
225 return 159;
226
227 if (ch == 0x0393)
228 return 226;
229
230 if (ch == 0x0398)
231 return 233;
232
233 if (ch == 0x03a3)
234 return 228;
235
236 if (ch == 0x03a6)
237 return 232;
238
239 if (ch == 0x03a9)
240 return 234;
241
242 if (ch == 0x03b1)
243 return 224;
244
245 if (ch == 0x03b4)
246 return 235;
247
248 if (ch == 0x03b5)
249 return 238;
250
251 if (ch == 0x03c0)
252 return 227;
253
254 if (ch == 0x03c3)
255 return 229;
256
257 if (ch == 0x03c4)
258 return 231;
259
260 if (ch == 0x03c6)
261 return 237;
262
263 if (ch == 0x207f)
264 return 252;
265
266 if (ch == 0x20a7)
267 return 158;
268
269 if (ch == 0x2219)
270 return 249;
271
272 if (ch == 0x221a)
273 return 251;
274
275 if (ch == 0x221e)
276 return 236;
277
278 if (ch == 0x2229)
279 return 239;
280
281 if (ch == 0x2248)
282 return 247;
283
284 if (ch == 0x2261)
285 return 240;
286
287 if (ch == 0x2264)
288 return 243;
289
290 if (ch == 0x2265)
291 return 242;
292
293 if (ch == 0x2310)
294 return 169;
295
296 if ((ch >= 0x2320) && (ch <= 0x2321))
297 return (ch - 8748);
298
299 if (ch == 0x2500)
300 return 196;
301
302 if (ch == 0x2502)
303 return 179;
304
305 if (ch == 0x250c)
306 return 218;
307
308 if (ch == 0x2510)
309 return 191;
310
311 if (ch == 0x2514)
312 return 192;
313
314 if (ch == 0x2518)
315 return 217;
316
317 if (ch == 0x251c)
318 return 195;
319
320 if (ch == 0x2524)
321 return 180;
322
323 if (ch == 0x252c)
324 return 194;
325
326 if (ch == 0x2534)
327 return 193;
328
329 if (ch == 0x253c)
330 return 197;
331
332 if (ch == 0x2550)
333 return 205;
334
335 if (ch == 0x2551)
336 return 186;
337
338 if ((ch >= 0x2552) && (ch <= 0x2553))
339 return (ch - 9341);
340
341 if (ch == 0x2554)
342 return 201;
343
344 if (ch == 0x2555)
345 return 184;
346
347 if (ch == 0x2556)
348 return 183;
349
350 if (ch == 0x2557)
351 return 187;
352
353 if (ch == 0x2558)
354 return 212;
355
356 if (ch == 0x2559)
357 return 211;
358
359 if (ch == 0x255a)
360 return 200;
361
362 if (ch == 0x255b)
363 return 190;
364
365 if (ch == 0x255c)
366 return 189;
367
368 if (ch == 0x255d)
369 return 188;
370
371 if ((ch >= 0x255e) && (ch <= 0x255f))
372 return (ch - 9368);
373
374 if (ch == 0x2560)
375 return 204;
376
377 if ((ch >= 0x2561) && (ch <= 0x2562))
378 return (ch - 9388);
379
380 if (ch == 0x2563)
381 return 185;
382
383 if ((ch >= 0x2564) && (ch <= 0x2565))
384 return (ch - 9363);
385
386 if (ch == 0x2566)
387 return 203;
388
389 if ((ch >= 0x2567) && (ch <= 0x2568))
390 return (ch - 9368);
391
392 if (ch == 0x2569)
393 return 202;
394
395 if (ch == 0x256a)
396 return 216;
397
398 if (ch == 0x256b)
399 return 215;
400
401 if (ch == 0x256c)
402 return 206;
403
404 if (ch == 0x2580)
405 return 223;
406
407 if (ch == 0x2584)
408 return 220;
409
410 if (ch == 0x2588)
411 return 219;
412
413 if (ch == 0x258c)
414 return 221;
415
416 if (ch == 0x2590)
417 return 222;
418
419 if ((ch >= 0x2591) && (ch <= 0x2593))
420 return (ch - 9441);
421
422 return 256;
423}
424
425/*
426 * This function takes care of scrolling.
427 */
428static void ega_check_cursor(void)
429{
430 if (ega_cursor < EGA_SCREEN)
431 return;
432
433 memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
434 (EGA_SCREEN - EGA_COLS) * 2);
435 memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
436 (EGA_SCREEN - EGA_COLS) * 2);
437 memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
438 memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
439 ega_cursor = ega_cursor - EGA_COLS;
440}
441
442static void ega_show_cursor(void)
443{
444 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
445 uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
446 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
447 pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
448}
449
450static void ega_move_cursor(void)
451{
452 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
453 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
454 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
455 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
456}
457
458static void ega_sync_cursor(void)
459{
460 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
461 uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
462 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
463 uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
464
465 ega_cursor = (hi << 8) | lo;
466
467 if (ega_cursor >= EGA_SCREEN)
468 ega_cursor = 0;
469
470 if ((ega_cursor % EGA_COLS) != 0)
471 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
472
473 memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
474 memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
475
476 ega_check_cursor();
477 ega_move_cursor();
478 ega_show_cursor();
479}
480
481static void ega_display_char(wchar_t ch, bool silent)
482{
483 uint16_t index = ega_oem_glyph(ch);
484 uint8_t glyph;
485 uint8_t style;
486
487 if ((index >> 8)) {
488 glyph = '?';
489 style = INVAL;
490 } else {
491 glyph = index & 0xff;
492 style = STYLE;
493 }
494
495 backbuf[ega_cursor * 2] = glyph;
496 backbuf[ega_cursor * 2 + 1] = style;
497
498 if (!silent) {
499 videoram[ega_cursor * 2] = glyph;
500 videoram[ega_cursor * 2 + 1] = style;
501 }
502}
503
504static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
505{
506 ipl_t ipl;
507
508 ipl = interrupts_disable();
509 spinlock_lock(&egalock);
510
511 switch (ch) {
512 case '\n':
513 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
514 break;
515 case '\t':
516 ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
517 break;
518 case '\b':
519 if (ega_cursor % EGA_COLS)
520 ega_cursor--;
521 break;
522 default:
523 ega_display_char(ch, silent);
524 ega_cursor++;
525 break;
526 }
527 ega_check_cursor();
528
529 if (!silent)
530 ega_move_cursor();
531
532 spinlock_unlock(&egalock);
533 interrupts_restore(ipl);
534}
535
536static outdev_t ega_console;
537static outdev_operations_t ega_ops = {
538 .write = ega_putchar
539};
540
541void ega_init(ioport8_t *base, uintptr_t videoram_phys)
542{
543 /* Initialize the software structure. */
544 ega_base = base;
545
546 backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
547 if (!backbuf)
548 panic("Unable to allocate backbuffer.");
549
550 videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
551
552 /* Synchronize the back buffer and cursor position. */
553 memcpy(backbuf, videoram, EGA_VRAM_SIZE);
554 ega_sync_cursor();
555
556 outdev_initialize("ega", &ega_console, &ega_ops);
557 stdout = &ega_console;
558
559 sysinfo_set_item_val("fb", NULL, true);
560 sysinfo_set_item_val("fb.kind", NULL, 2);
561 sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
562 sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
563 sysinfo_set_item_val("fb.blinking", NULL, true);
564 sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
565}
566
567void ega_redraw(void)
568{
569 memcpy(videoram, backbuf, EGA_VRAM_SIZE);
570 ega_move_cursor();
571 ega_show_cursor();
572}
573
574/** @}
575 */
Note: See TracBrowser for help on using the repository browser.