source: mainline/uspace/srv/hid/fb/port/ega.c@ 05fb96b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 05fb96b was 7c014d1, checked in by Martin Decky <martin@…>, 14 years ago

console and framebuffer server rewrite

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Decky
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/** @file
30 */
31
32#include <sys/types.h>
33#include <errno.h>
34#include <sysinfo.h>
35#include <task.h>
36#include <ddi.h>
37#include <libarch/ddi.h>
38#include <as.h>
39#include <malloc.h>
40#include <align.h>
41#include <screenbuffer.h>
42#include "../fb.h"
43#include "ega.h"
44
45#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
46#define EGA_IO_SIZE 2
47
48#define FB_POS(x, y) (((y) * ega.width + (x)) << 1)
49
50typedef struct {
51 sysarg_t width;
52 sysarg_t height;
53
54 size_t size;
55 uint8_t *addr;
56
57 uint8_t style_normal;
58 uint8_t style_inverted;
59
60 uint8_t *backbuf;
61} ega_t;
62
63static ega_t ega;
64
65static uint8_t attrs_attr(char_attrs_t attrs)
66{
67 uint8_t attr = 0;
68
69 switch (attrs.type) {
70 case CHAR_ATTR_STYLE:
71 switch (attrs.val.style) {
72 case STYLE_NORMAL:
73 attr = ega.style_normal;
74 break;
75 case STYLE_EMPHASIS:
76 attr = (ega.style_normal | 0x04);
77 break;
78 case STYLE_INVERTED:
79 attr = ega.style_inverted;
80 break;
81 case STYLE_SELECTED:
82 attr = (ega.style_inverted | 0x40);
83 break;
84 }
85 break;
86 case CHAR_ATTR_INDEX:
87 attr = ((attrs.val.index.bgcolor & 7) << 4) |
88 (attrs.val.index.fgcolor & 7);
89
90 if (attrs.val.index.attr & CATTR_BRIGHT)
91 attr |= 0x08;
92
93 break;
94 case CHAR_ATTR_RGB:
95 attr = (attrs.val.rgb.bgcolor < attrs.val.rgb.fgcolor) ?
96 ega.style_inverted : ega.style_normal;
97 break;
98 }
99
100 return attr;
101}
102
103/** Draw the character at the specified position in viewport.
104 *
105 * @param vp Viewport.
106 * @param col Screen position relative to viewport.
107 * @param row Screen position relative to viewport.
108 *
109 */
110static void draw_vp_char(fbvp_t *vp, sysarg_t col, sysarg_t row)
111{
112 sysarg_t x = vp->x + col;
113 sysarg_t y = vp->y + row;
114
115 charfield_t *field = screenbuffer_field_at(vp->backbuf, col, row);
116
117 uint8_t glyph;
118
119 if ((field->ch >= 0) && (field->ch < 128))
120 glyph = field->ch;
121 else
122 glyph = '?';
123
124 uint8_t attr = attrs_attr(field->attrs);
125
126 ega.addr[FB_POS(x, y)] = glyph;
127 ega.addr[FB_POS(x, y) + 1] = attr;
128}
129
130static int ega_yield(fbdev_t *dev)
131{
132 if (ega.backbuf == NULL) {
133 ega.backbuf = malloc(ega.size);
134 if (ega.backbuf == NULL)
135 return ENOMEM;
136 }
137
138 memcpy(ega.backbuf, ega.addr, ega.size);
139 return EOK;
140}
141
142static int ega_claim(fbdev_t *dev)
143{
144 if (ega.backbuf == NULL)
145 return ENOENT;
146
147 memcpy(ega.addr, ega.backbuf, ega.size);
148 return EOK;
149}
150
151static int ega_get_resolution(fbdev_t *dev, sysarg_t *width, sysarg_t *height)
152{
153 *width = ega.width;
154 *height = ega.height;
155 return EOK;
156}
157
158static void ega_font_metrics(fbdev_t *dev, sysarg_t width, sysarg_t height,
159 sysarg_t *cols, sysarg_t *rows)
160{
161 *cols = width;
162 *rows = height;
163}
164
165static int ega_vp_create(fbdev_t *dev, fbvp_t *vp)
166{
167 vp->attrs.type = CHAR_ATTR_STYLE;
168 vp->attrs.val.style = STYLE_NORMAL;
169 vp->data = NULL;
170
171 return EOK;
172}
173
174static void ega_vp_destroy(fbdev_t *dev, fbvp_t *vp)
175{
176 /* No-op */
177}
178
179static void ega_vp_clear(fbdev_t *dev, fbvp_t *vp)
180{
181 for (sysarg_t row = 0; row < vp->rows; row++) {
182 for (sysarg_t col = 0; col < vp->cols; col++) {
183 charfield_t *field =
184 screenbuffer_field_at(vp->backbuf, col, row);
185
186 field->ch = 0;
187 field->attrs = vp->attrs;
188
189 draw_vp_char(vp, col, row);
190 }
191 }
192}
193
194static console_caps_t ega_vp_get_caps(fbdev_t *dev, fbvp_t *vp)
195{
196 return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
197}
198
199static void ega_vp_cursor_update(fbdev_t *dev, fbvp_t *vp, sysarg_t prev_col,
200 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
201{
202 /* Cursor position */
203 uint16_t cursor = row * ega.width + col;
204
205 pio_write_8(EGA_IO_BASE, 0x0e);
206 pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
207 pio_write_8(EGA_IO_BASE, 0x0f);
208 pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
209
210 /* Cursor visibility */
211 pio_write_8(EGA_IO_BASE, 0x0a);
212 uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
213
214 pio_write_8(EGA_IO_BASE, 0x0a);
215
216 if (visible)
217 pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
218 else
219 pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
220}
221
222static void ega_vp_char_update(fbdev_t *dev, fbvp_t *vp, sysarg_t col,
223 sysarg_t row)
224{
225 draw_vp_char(vp, col, row);
226}
227
228static fbdev_ops_t ega_ops = {
229 .yield = ega_yield,
230 .claim = ega_claim,
231 .get_resolution = ega_get_resolution,
232 .font_metrics = ega_font_metrics,
233 .vp_create = ega_vp_create,
234 .vp_destroy = ega_vp_destroy,
235 .vp_clear = ega_vp_clear,
236 .vp_get_caps = ega_vp_get_caps,
237 .vp_cursor_update = ega_vp_cursor_update,
238 .vp_char_update = ega_vp_char_update
239};
240
241int ega_init(void)
242{
243 sysarg_t present;
244 int rc = sysinfo_get_value("fb", &present);
245 if (rc != EOK)
246 present = false;
247
248 if (!present)
249 return ENOENT;
250
251 sysarg_t kind;
252 rc = sysinfo_get_value("fb.kind", &kind);
253 if (rc != EOK)
254 kind = (sysarg_t) -1;
255
256 if (kind != 2)
257 return EINVAL;
258
259 sysarg_t paddr;
260 rc = sysinfo_get_value("fb.address.physical", &paddr);
261 if (rc != EOK)
262 return rc;
263
264 sysarg_t width;
265 rc = sysinfo_get_value("fb.width", &width);
266 if (rc != EOK)
267 return rc;
268
269 sysarg_t height;
270 rc = sysinfo_get_value("fb.height", &height);
271 if (rc != EOK)
272 return rc;
273
274 rc = iospace_enable(task_get_id(), (void *) EGA_IO_BASE, EGA_IO_SIZE);
275 if (rc != EOK)
276 return rc;
277
278 ega.width = width;
279 ega.height = height;
280
281 ega.size = (width * height) << 1;
282 ega.addr = as_get_mappable_page(ega.size);
283 if (ega.addr == NULL)
284 return ENOMEM;
285
286 rc = physmem_map((void *) paddr, ega.addr,
287 ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
288 if (rc != EOK)
289 return rc;
290
291 sysarg_t blinking;
292 rc = sysinfo_get_value("fb.blinking", &blinking);
293 if (rc != EOK)
294 blinking = false;
295
296 ega.style_normal = 0xf0;
297 ega.style_inverted = 0x0f;
298
299 if (blinking) {
300 ega.style_normal &= 0x77;
301 ega.style_inverted &= 0x77;
302 }
303
304 ega.backbuf = NULL;
305
306 fbdev_t *dev = fbdev_register(&ega_ops, (void *) &ega);
307 if (dev == NULL) {
308 as_area_destroy(ega.addr);
309 return EINVAL;
310 }
311
312 return EOK;
313}
314
315/**
316 * @}
317 */
Note: See TracBrowser for help on using the repository browser.