Subversion Repositories HelenOS

Rev

Rev 4346 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 jermar 1
/*
2071 jermar 2
 * Copyright (c) 2001-2004 Jakub Jermar
1 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
 
4344 svoboda 29
/** @addtogroup genarch_drivers
1702 cejka 30
 * @{
31
 */
1754 jermar 32
/**
33
 * @file
34
 * @brief EGA driver.
1702 cejka 35
 */
36
 
3779 jermar 37
#include <genarch/drivers/ega/ega.h>
1 jermar 38
#include <putchar.h>
39
#include <mm/page.h>
755 jermar 40
#include <mm/as.h>
3751 svoboda 41
#include <mm/slab.h>
167 jermar 42
#include <arch/mm/page.h>
1 jermar 43
#include <synch/spinlock.h>
44
#include <arch/types.h>
45
#include <arch/asm.h>
195 vana 46
#include <memstr.h>
575 palkovsky 47
#include <console/chardev.h>
48
#include <console/console.h>
1473 decky 49
#include <sysinfo/sysinfo.h>
2015 jermar 50
#include <ddi/ddi.h>
1 jermar 51
 
52
/*
53
 * The EGA driver.
54
 * Simple and short. Function for displaying characters and "scrolling".
55
 */
56
 
623 jermar 57
SPINLOCK_INITIALIZE(egalock);
1780 jermar 58
static uint32_t ega_cursor;
59
static uint8_t *videoram;
3751 svoboda 60
static uint8_t *backbuf;
4344 svoboda 61
static ioport8_t *ega_base;
1 jermar 62
 
4346 svoboda 63
#define SPACE  0x20
4347 svoboda 64
#define STYLE  0x1e
65
#define INVAL  0x17
4345 svoboda 66
 
4347 svoboda 67
#define EMPTY_CHAR  ((STYLE << 8) | SPACE)
575 palkovsky 68
 
4347 svoboda 69
static 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
 
1 jermar 425
/*
426
 * This function takes care of scrolling.
427
 */
452 decky 428
static void ega_check_cursor(void)
1 jermar 429
{
4344 svoboda 430
    if (ega_cursor < EGA_SCREEN)
125 jermar 431
        return;
4345 svoboda 432
 
4344 svoboda 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);
4345 svoboda 437
    memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
438
    memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
4344 svoboda 439
    ega_cursor = ega_cursor - EGA_COLS;
1 jermar 440
}
441
 
4344 svoboda 442
static 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
 
4341 svoboda 450
static void ega_move_cursor(void)
1 jermar 451
{
4344 svoboda 452
    pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
4343 svoboda 453
    pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
4344 svoboda 454
    pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
455
    pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
4341 svoboda 456
}
457
 
4344 svoboda 458
static 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;
4345 svoboda 466
 
467
    if (ega_cursor >= EGA_SCREEN)
468
        ega_cursor = 0;
469
 
4344 svoboda 470
    if ((ega_cursor % EGA_COLS) != 0)
471
        ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
472
 
4345 svoboda 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
 
4344 svoboda 476
    ega_check_cursor();
477
    ega_move_cursor();
478
    ega_show_cursor();
479
}
480
 
4347 svoboda 481
static void ega_display_char(wchar_t ch, bool silent)
4341 svoboda 482
{
4347 svoboda 483
    uint16_t index = ega_oem_glyph(ch);
484
    uint8_t glyph;
485
    uint8_t style;
4341 svoboda 486
 
4347 svoboda 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
 
4346 svoboda 498
    if (!silent) {
4347 svoboda 499
        videoram[ega_cursor * 2] = glyph;
500
        videoram[ega_cursor * 2 + 1] = style;
4346 svoboda 501
    }
4341 svoboda 502
}
503
 
4347 svoboda 504
static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
4341 svoboda 505
{
413 jermar 506
    ipl_t ipl;
4341 svoboda 507
 
413 jermar 508
    ipl = interrupts_disable();
1 jermar 509
    spinlock_lock(&egalock);
4341 svoboda 510
 
1 jermar 511
    switch (ch) {
2065 jermar 512
    case '\n':
4344 svoboda 513
        ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
2065 jermar 514
        break;
515
    case '\t':
516
        ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
4347 svoboda 517
        break;
2065 jermar 518
    case '\b':
4344 svoboda 519
        if (ega_cursor % EGA_COLS)
2065 jermar 520
            ega_cursor--;
521
        break;
522
    default:
4341 svoboda 523
        ega_display_char(ch, silent);
2065 jermar 524
        ega_cursor++;
525
        break;
1473 decky 526
    }
1 jermar 527
    ega_check_cursor();
4341 svoboda 528
 
529
    if (!silent)
530
        ega_move_cursor();
531
 
1 jermar 532
    spinlock_unlock(&egalock);
413 jermar 533
    interrupts_restore(ipl);
1 jermar 534
}
535
 
4346 svoboda 536
static outdev_t ega_console;
537
static outdev_operations_t ega_ops = {
4341 svoboda 538
    .write = ega_putchar
539
};
540
 
4344 svoboda 541
void ega_init(ioport8_t *base, uintptr_t videoram_phys)
1 jermar 542
{
4344 svoboda 543
    /* Initialize the software structure. */
4341 svoboda 544
    ega_base = base;
545
 
4344 svoboda 546
    backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
4341 svoboda 547
    if (!backbuf)
548
        panic("Unable to allocate backbuffer.");
549
 
4344 svoboda 550
    videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
4341 svoboda 551
 
4344 svoboda 552
    /* Synchronize the back buffer and cursor position. */
553
    memcpy(backbuf, videoram, EGA_VRAM_SIZE);
554
    ega_sync_cursor();
4341 svoboda 555
 
4346 svoboda 556
    outdev_initialize("ega", &ega_console, &ega_ops);
4341 svoboda 557
    stdout = &ega_console;
558
 
559
    sysinfo_set_item_val("fb", NULL, true);
560
    sysinfo_set_item_val("fb.kind", NULL, 2);
4344 svoboda 561
    sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
562
    sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
4341 svoboda 563
    sysinfo_set_item_val("fb.blinking", NULL, true);
564
    sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
1 jermar 565
}
1702 cejka 566
 
3751 svoboda 567
void ega_redraw(void)
568
{
4344 svoboda 569
    memcpy(videoram, backbuf, EGA_VRAM_SIZE);
3751 svoboda 570
    ega_move_cursor();
4344 svoboda 571
    ega_show_cursor();
3751 svoboda 572
}
573
 
1754 jermar 574
/** @}
1702 cejka 575
 */