Subversion Repositories HelenOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4377 svoboda 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 <string.h>
48
#include <console/chardev.h>
49
#include <console/console.h>
50
#include <sysinfo/sysinfo.h>
51
#include <ddi/ddi.h>
52
 
53
/*
54
 * The EGA driver.
55
 * Simple and short. Function for displaying characters and "scrolling".
56
 */
57
 
58
SPINLOCK_INITIALIZE(egalock);
59
static uint32_t ega_cursor;
60
static uint8_t *videoram;
61
static uint8_t *backbuf;
62
static ioport8_t *ega_base;
63
 
64
#define SPACE  0x20
65
#define STYLE  0x1e
66
#define INVAL  0x17
67
 
68
#define EMPTY_CHAR  ((STYLE << 8) | SPACE)
69
 
70
static uint16_t ega_oem_glyph(const wchar_t ch)
71
{
72
    if ((ch >= 0x0000) && (ch <= 0x007f))
73
        return ch;
74
 
75
    if (ch == 0x00a0)
76
        return 255;
77
 
78
    if (ch == 0x00a1)
79
        return 173;
80
 
81
    if ((ch >= 0x00a2) && (ch <= 0x00a3))
82
        return (ch - 7);
83
 
84
    if (ch == 0x00a5)
85
        return 157;
86
 
87
    if (ch == 0x00aa)
88
        return 166;
89
 
90
    if (ch == 0x00ab)
91
        return 174;
92
 
93
    if (ch == 0x00ac)
94
        return 170;
95
 
96
    if (ch == 0x00b0)
97
        return 248;
98
 
99
    if (ch == 0x00b1)
100
        return 241;
101
 
102
    if (ch == 0x00b2)
103
        return 253;
104
 
105
    if (ch == 0x00b5)
106
        return 230;
107
 
108
    if (ch == 0x00b7)
109
        return 250;
110
 
111
    if (ch == 0x00ba)
112
        return 167;
113
 
114
    if (ch == 0x00bb)
115
        return 175;
116
 
117
    if (ch == 0x00bc)
118
        return 172;
119
 
120
    if (ch == 0x00bd)
121
        return 171;
122
 
123
    if (ch == 0x00bf)
124
        return 168;
125
 
126
    if ((ch >= 0x00c4) && (ch <= 0x00c5))
127
        return (ch - 54);
128
 
129
    if (ch == 0x00c6)
130
        return 146;
131
 
132
    if (ch == 0x00c7)
133
        return 128;
134
 
135
    if (ch == 0x00c9)
136
        return 144;
137
 
138
    if (ch == 0x00d1)
139
        return 165;
140
 
141
    if (ch == 0x00d6)
142
        return 153;
143
 
144
    if (ch == 0x00dc)
145
        return 154;
146
 
147
    if (ch == 0x00df)
148
        return 225;
149
 
150
    if (ch == 0x00e0)
151
        return 133;
152
 
153
    if (ch == 0x00e1)
154
        return 160;
155
 
156
    if (ch == 0x00e2)
157
        return 131;
158
 
159
    if (ch == 0x00e4)
160
        return 132;
161
 
162
    if (ch == 0x00e5)
163
        return 134;
164
 
165
    if (ch == 0x00e6)
166
        return 145;
167
 
168
    if (ch == 0x00e7)
169
        return 135;
170
 
171
    if (ch == 0x00e8)
172
        return 138;
173
 
174
    if (ch == 0x00e9)
175
        return 130;
176
 
177
    if ((ch >= 0x00ea) && (ch <= 0x00eb))
178
        return (ch - 98);
179
 
180
    if (ch == 0x00ec)
181
        return 141;
182
 
183
    if (ch == 0x00ed)
184
        return 161;
185
 
186
    if (ch == 0x00ee)
187
        return 140;
188
 
189
    if (ch == 0x00ef)
190
        return 139;
191
 
192
    if (ch == 0x00f1)
193
        return 164;
194
 
195
    if (ch == 0x00f2)
196
        return 149;
197
 
198
    if (ch == 0x00f3)
199
        return 162;
200
 
201
    if (ch == 0x00f4)
202
        return 147;
203
 
204
    if (ch == 0x00f6)
205
        return 148;
206
 
207
    if (ch == 0x00f7)
208
        return 246;
209
 
210
    if (ch == 0x00f9)
211
        return 151;
212
 
213
    if (ch == 0x00fa)
214
        return 163;
215
 
216
    if (ch == 0x00fb)
217
        return 150;
218
 
219
    if (ch == 0x00fc)
220
        return 129;
221
 
222
    if (ch == 0x00ff)
223
        return 152;
224
 
225
    if (ch == 0x0192)
226
        return 159;
227
 
228
    if (ch == 0x0393)
229
        return 226;
230
 
231
    if (ch == 0x0398)
232
        return 233;
233
 
234
    if (ch == 0x03a3)
235
        return 228;
236
 
237
    if (ch == 0x03a6)
238
        return 232;
239
 
240
    if (ch == 0x03a9)
241
        return 234;
242
 
243
    if (ch == 0x03b1)
244
        return 224;
245
 
246
    if (ch == 0x03b4)
247
        return 235;
248
 
249
    if (ch == 0x03b5)
250
        return 238;
251
 
252
    if (ch == 0x03c0)
253
        return 227;
254
 
255
    if (ch == 0x03c3)
256
        return 229;
257
 
258
    if (ch == 0x03c4)
259
        return 231;
260
 
261
    if (ch == 0x03c6)
262
        return 237;
263
 
264
    if (ch == 0x207f)
265
        return 252;
266
 
267
    if (ch == 0x20a7)
268
        return 158;
269
 
270
    if (ch == 0x2219)
271
        return 249;
272
 
273
    if (ch == 0x221a)
274
        return 251;
275
 
276
    if (ch == 0x221e)
277
        return 236;
278
 
279
    if (ch == 0x2229)
280
        return 239;
281
 
282
    if (ch == 0x2248)
283
        return 247;
284
 
285
    if (ch == 0x2261)
286
        return 240;
287
 
288
    if (ch == 0x2264)
289
        return 243;
290
 
291
    if (ch == 0x2265)
292
        return 242;
293
 
294
    if (ch == 0x2310)
295
        return 169;
296
 
297
    if ((ch >= 0x2320) && (ch <= 0x2321))
298
        return (ch - 8748);
299
 
300
    if (ch == 0x2500)
301
        return 196;
302
 
303
    if (ch == 0x2502)
304
        return 179;
305
 
306
    if (ch == 0x250c)
307
        return 218;
308
 
309
    if (ch == 0x2510)
310
        return 191;
311
 
312
    if (ch == 0x2514)
313
        return 192;
314
 
315
    if (ch == 0x2518)
316
        return 217;
317
 
318
    if (ch == 0x251c)
319
        return 195;
320
 
321
    if (ch == 0x2524)
322
        return 180;
323
 
324
    if (ch == 0x252c)
325
        return 194;
326
 
327
    if (ch == 0x2534)
328
        return 193;
329
 
330
    if (ch == 0x253c)
331
        return 197;
332
 
333
    if (ch == 0x2550)
334
        return 205;
335
 
336
    if (ch == 0x2551)
337
        return 186;
338
 
339
    if ((ch >= 0x2552) && (ch <= 0x2553))
340
        return (ch - 9341);
341
 
342
    if (ch == 0x2554)
343
        return 201;
344
 
345
    if (ch == 0x2555)
346
        return 184;
347
 
348
    if (ch == 0x2556)
349
        return 183;
350
 
351
    if (ch == 0x2557)
352
        return 187;
353
 
354
    if (ch == 0x2558)
355
        return 212;
356
 
357
    if (ch == 0x2559)
358
        return 211;
359
 
360
    if (ch == 0x255a)
361
        return 200;
362
 
363
    if (ch == 0x255b)
364
        return 190;
365
 
366
    if (ch == 0x255c)
367
        return 189;
368
 
369
    if (ch == 0x255d)
370
        return 188;
371
 
372
    if ((ch >= 0x255e) && (ch <= 0x255f))
373
        return (ch - 9368);
374
 
375
    if (ch == 0x2560)
376
        return 204;
377
 
378
    if ((ch >= 0x2561) && (ch <= 0x2562))
379
        return (ch - 9388);
380
 
381
    if (ch == 0x2563)
382
        return 185;
383
 
384
    if ((ch >= 0x2564) && (ch <= 0x2565))
385
        return (ch - 9363);
386
 
387
    if (ch == 0x2566)
388
        return 203;
389
 
390
    if ((ch >= 0x2567) && (ch <= 0x2568))
391
        return (ch - 9368);
392
 
393
    if (ch == 0x2569)
394
        return 202;
395
 
396
    if (ch == 0x256a)
397
        return 216;
398
 
399
    if (ch == 0x256b)
400
        return 215;
401
 
402
    if (ch == 0x256c)
403
        return 206;
404
 
405
    if (ch == 0x2580)
406
        return 223;
407
 
408
    if (ch == 0x2584)
409
        return 220;
410
 
411
    if (ch == 0x2588)
412
        return 219;
413
 
414
    if (ch == 0x258c)
415
        return 221;
416
 
417
    if (ch == 0x2590)
418
        return 222;
419
 
420
    if ((ch >= 0x2591) && (ch <= 0x2593))
421
        return (ch - 9441);
422
 
423
    return 256;
424
}
425
 
426
/*
427
 * This function takes care of scrolling.
428
 */
429
static void ega_check_cursor(bool silent)
430
{
431
    if (ega_cursor < EGA_SCREEN)
432
        return;
433
 
434
    memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
435
        (EGA_SCREEN - EGA_COLS) * 2);
436
    memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
437
 
438
    if (!silent) {
439
        memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
440
            (EGA_SCREEN - EGA_COLS) * 2);
441
        memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
442
    }
443
 
444
    ega_cursor = ega_cursor - EGA_COLS;
445
}
446
 
447
static void ega_show_cursor(bool silent)
448
{
449
    if (!silent) {
450
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
451
        uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
452
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
453
        pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
454
    }
455
}
456
 
457
static void ega_move_cursor(bool silent)
458
{
459
    if (!silent) {
460
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
461
        pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
462
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
463
        pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
464
    }
465
}
466
 
467
static void ega_sync_cursor(bool silent)
468
{
469
    if (!silent) {
470
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
471
        uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
472
        pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
473
        uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
474
 
475
        ega_cursor = (hi << 8) | lo;
476
    } else
477
        ega_cursor = 0;
478
 
479
    if (ega_cursor >= EGA_SCREEN)
480
        ega_cursor = 0;
481
 
482
    if ((ega_cursor % EGA_COLS) != 0)
483
        ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
484
 
485
    memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
486
 
487
    if (!silent)
488
        memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
489
 
490
    ega_check_cursor(silent);
491
    ega_move_cursor(silent);
492
    ega_show_cursor(silent);
493
}
494
 
495
static void ega_display_char(wchar_t ch, bool silent)
496
{
497
    uint16_t index = ega_oem_glyph(ch);
498
    uint8_t glyph;
499
    uint8_t style;
500
 
501
    if ((index >> 8)) {
502
        glyph = U_SPECIAL;
503
        style = INVAL;
504
    } else {
505
        glyph = index & 0xff;
506
        style = STYLE;
507
    }
508
 
509
    backbuf[ega_cursor * 2] = glyph;
510
    backbuf[ega_cursor * 2 + 1] = style;
511
 
512
    if (!silent) {
513
        videoram[ega_cursor * 2] = glyph;
514
        videoram[ega_cursor * 2 + 1] = style;
515
    }
516
}
517
 
518
static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
519
{
520
    ipl_t ipl;
521
 
522
    ipl = interrupts_disable();
523
    spinlock_lock(&egalock);
524
 
525
    switch (ch) {
526
    case '\n':
527
        ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
528
        break;
529
    case '\t':
530
        ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
531
        break;
532
    case '\b':
533
        if (ega_cursor % EGA_COLS)
534
            ega_cursor--;
535
        break;
536
    default:
537
        ega_display_char(ch, silent);
538
        ega_cursor++;
539
        break;
540
    }
541
    ega_check_cursor(silent);
542
    ega_move_cursor(silent);
543
 
544
    spinlock_unlock(&egalock);
545
    interrupts_restore(ipl);
546
}
547
 
548
static outdev_t ega_console;
549
static outdev_operations_t ega_ops = {
550
    .write = ega_putchar
551
};
552
 
553
void ega_init(ioport8_t *base, uintptr_t videoram_phys)
554
{
555
    /* Initialize the software structure. */
556
    ega_base = base;
557
 
558
    backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
559
    if (!backbuf)
560
        panic("Unable to allocate backbuffer.");
561
 
562
    videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
563
 
564
    /* Synchronize the back buffer and cursor position. */
565
    memcpy(backbuf, videoram, EGA_VRAM_SIZE);
566
    ega_sync_cursor(silent);
567
 
568
    outdev_initialize("ega", &ega_console, &ega_ops);
569
    stdout = &ega_console;
570
 
571
    sysinfo_set_item_val("fb", NULL, true);
572
    sysinfo_set_item_val("fb.kind", NULL, 2);
573
    sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
574
    sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
575
    sysinfo_set_item_val("fb.blinking", NULL, true);
576
    sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
577
}
578
 
579
void ega_redraw(void)
580
{
581
    memcpy(videoram, backbuf, EGA_VRAM_SIZE);
582
    ega_move_cursor(silent);
583
    ega_show_cursor(silent);
584
}
585
 
586
/** @}
587
 */