source: mainline/uspace/srv/hid/output/port/ega.c@ be0ec50

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since be0ec50 was 9b2e20c, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Add code page 437 support

EGA driver can now display all 256 characters (provided that the
application uses their proper Unicode code points).

Tester print4 'extended ASCII' demonstration did not work since
the introduction of Unicode, so replaced it with a demonstration
of code page 437 instead.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * Copyright (c) 2011 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup output
31 * @{
32 */
33
34#include <codepage/cp437.h>
35#include <errno.h>
36#include <sysinfo.h>
37#include <align.h>
38#include <as.h>
39#include <ddi.h>
40#include <io/chargrid.h>
41#include "../output.h"
42#include "ega.h"
43
44#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
45#define EGA_IO_SIZE 2
46
47#define FB_POS(x, y) (((y) * ega.cols + (x)) << 1)
48
49typedef struct {
50 sysarg_t cols;
51 sysarg_t rows;
52
53 uint8_t style_normal;
54 uint8_t style_inverted;
55
56 size_t size;
57 uint8_t *addr;
58} ega_t;
59
60static ega_t ega;
61
62static uint8_t attrs_attr(char_attrs_t attrs)
63{
64 uint8_t attr = 0;
65
66 switch (attrs.type) {
67 case CHAR_ATTR_STYLE:
68 switch (attrs.val.style) {
69 case STYLE_NORMAL:
70 attr = ega.style_normal;
71 break;
72 case STYLE_EMPHASIS:
73 attr = (ega.style_normal | 0x04);
74 break;
75 case STYLE_INVERTED:
76 attr = ega.style_inverted;
77 break;
78 case STYLE_SELECTED:
79 attr = (ega.style_inverted | 0x40);
80 break;
81 }
82 break;
83 case CHAR_ATTR_INDEX:
84 attr = ((attrs.val.index.bgcolor & 7) << 4) |
85 (attrs.val.index.fgcolor & 7);
86
87 if (attrs.val.index.attr & CATTR_BRIGHT)
88 attr |= 0x08;
89
90 break;
91 case CHAR_ATTR_RGB:
92 attr = (attrs.val.rgb.bgcolor < attrs.val.rgb.fgcolor) ?
93 ega.style_inverted : ega.style_normal;
94 break;
95 }
96
97 return attr;
98}
99
100/** Draw the character at the specified position.
101 *
102 * @param field Character field.
103 * @param col Horizontal screen position.
104 * @param row Vertical screen position.
105 *
106 */
107static void draw_char(charfield_t *field, sysarg_t col, sysarg_t row)
108{
109 uint8_t glyph;
110 errno_t rc;
111
112 rc = cp437_encode(field->ch, &glyph);
113 if (rc != EOK)
114 glyph = '?';
115
116 uint8_t attr = attrs_attr(field->attrs);
117
118 ega.addr[FB_POS(col, row)] = glyph;
119 ega.addr[FB_POS(col, row) + 1] = attr;
120}
121
122static errno_t ega_yield(outdev_t *dev)
123{
124 return EOK;
125}
126
127static errno_t ega_claim(outdev_t *dev)
128{
129 return EOK;
130}
131
132static void ega_get_dimensions(outdev_t *dev, sysarg_t *cols, sysarg_t *rows)
133{
134 *cols = ega.cols;
135 *rows = ega.rows;
136}
137
138static console_caps_t ega_get_caps(outdev_t *dev)
139{
140 return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
141}
142
143static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
144 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
145{
146 /* Cursor position */
147 uint16_t cursor = row * ega.cols + col;
148
149 pio_write_8(EGA_IO_BASE, 0x0e);
150 pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
151 pio_write_8(EGA_IO_BASE, 0x0f);
152 pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
153
154 /* Cursor visibility */
155 pio_write_8(EGA_IO_BASE, 0x0a);
156 uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
157
158 pio_write_8(EGA_IO_BASE, 0x0a);
159
160 if (visible)
161 pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
162 else
163 pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
164}
165
166static void ega_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
167{
168 charfield_t *field =
169 chargrid_charfield_at(dev->backbuf, col, row);
170
171 draw_char(field, col, row);
172}
173
174static void ega_flush(outdev_t *dev)
175{
176}
177
178static outdev_ops_t ega_ops = {
179 .yield = ega_yield,
180 .claim = ega_claim,
181 .get_dimensions = ega_get_dimensions,
182 .get_caps = ega_get_caps,
183 .cursor_update = ega_cursor_update,
184 .char_update = ega_char_update,
185 .flush = ega_flush
186};
187
188errno_t ega_init(void)
189{
190 sysarg_t present;
191 errno_t rc = sysinfo_get_value("fb", &present);
192 if (rc != EOK)
193 present = false;
194
195 if (!present)
196 return ENOENT;
197
198 sysarg_t kind;
199 rc = sysinfo_get_value("fb.kind", &kind);
200 if (rc != EOK)
201 kind = (sysarg_t) -1;
202
203 if (kind != 2)
204 return EINVAL;
205
206 sysarg_t paddr;
207 rc = sysinfo_get_value("fb.address.physical", &paddr);
208 if (rc != EOK)
209 return rc;
210
211 rc = sysinfo_get_value("fb.width", &ega.cols);
212 if (rc != EOK)
213 return rc;
214
215 rc = sysinfo_get_value("fb.height", &ega.rows);
216 if (rc != EOK)
217 return rc;
218
219 rc = pio_enable((void *)EGA_IO_BASE, EGA_IO_SIZE, NULL);
220 if (rc != EOK)
221 return rc;
222
223 ega.size = (ega.cols * ega.rows) << 1;
224 ega.addr = AS_AREA_ANY;
225
226 rc = physmem_map(paddr,
227 ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
228 AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
229 if (rc != EOK)
230 return rc;
231
232 sysarg_t blinking;
233 rc = sysinfo_get_value("fb.blinking", &blinking);
234 if (rc != EOK)
235 blinking = false;
236
237 ega.style_normal = 0xf0;
238 ega.style_inverted = 0x0f;
239
240 if (blinking) {
241 ega.style_normal &= 0x77;
242 ega.style_inverted &= 0x77;
243 }
244
245 outdev_t *dev = outdev_register(&ega_ops, (void *) &ega);
246 if (dev == NULL) {
247 as_area_destroy(ega.addr);
248 return EINVAL;
249 }
250
251 return EOK;
252}
253
254/** @}
255 */
Note: See TracBrowser for help on using the repository browser.