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

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

improve the API of physmem_map(), dmamem_map() and dmamem_map_anonymous()
the "constraint" argument of dmamem_map_anonymous() should be used to specify bits disallowed in the physical frame address

  • Property mode set to 100644
File size: 5.6 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 <align.h>
36#include <as.h>
37#include <ddi.h>
38#include <io/chargrid.h>
39#include "../output.h"
40#include "ega.h"
41
42#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
43#define EGA_IO_SIZE 2
44
45#define FB_POS(x, y) (((y) * ega.cols + (x)) << 1)
46
47typedef struct {
48 sysarg_t cols;
49 sysarg_t rows;
50
51 uint8_t style_normal;
52 uint8_t style_inverted;
53
54 size_t size;
55 uint8_t *addr;
56} ega_t;
57
58static ega_t ega;
59
60static uint8_t attrs_attr(char_attrs_t attrs)
61{
62 uint8_t attr = 0;
63
64 switch (attrs.type) {
65 case CHAR_ATTR_STYLE:
66 switch (attrs.val.style) {
67 case STYLE_NORMAL:
68 attr = ega.style_normal;
69 break;
70 case STYLE_EMPHASIS:
71 attr = (ega.style_normal | 0x04);
72 break;
73 case STYLE_INVERTED:
74 attr = ega.style_inverted;
75 break;
76 case STYLE_SELECTED:
77 attr = (ega.style_inverted | 0x40);
78 break;
79 }
80 break;
81 case CHAR_ATTR_INDEX:
82 attr = ((attrs.val.index.bgcolor & 7) << 4) |
83 (attrs.val.index.fgcolor & 7);
84
85 if (attrs.val.index.attr & CATTR_BRIGHT)
86 attr |= 0x08;
87
88 break;
89 case CHAR_ATTR_RGB:
90 attr = (attrs.val.rgb.bgcolor < attrs.val.rgb.fgcolor) ?
91 ega.style_inverted : ega.style_normal;
92 break;
93 }
94
95 return attr;
96}
97
98/** Draw the character at the specified position.
99 *
100 * @param field Character field.
101 * @param col Horizontal screen position.
102 * @param row Vertical screen position.
103 *
104 */
105static void draw_char(charfield_t *field, sysarg_t col, sysarg_t row)
106{
107 uint8_t glyph;
108
109 if (ascii_check(field->ch))
110 glyph = field->ch;
111 else
112 glyph = '?';
113
114 uint8_t attr = attrs_attr(field->attrs);
115
116 ega.addr[FB_POS(col, row)] = glyph;
117 ega.addr[FB_POS(col, row) + 1] = attr;
118}
119
120static int ega_yield(outdev_t *dev)
121{
122 return EOK;
123}
124
125static int ega_claim(outdev_t *dev)
126{
127 return EOK;
128}
129
130static void ega_get_dimensions(outdev_t *dev, sysarg_t *cols, sysarg_t *rows)
131{
132 *cols = ega.cols;
133 *rows = ega.rows;
134}
135
136static console_caps_t ega_get_caps(outdev_t *dev)
137{
138 return (CONSOLE_CAP_STYLE | CONSOLE_CAP_INDEXED);
139}
140
141static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
142 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
143{
144 /* Cursor position */
145 uint16_t cursor = row * ega.cols + col;
146
147 pio_write_8(EGA_IO_BASE, 0x0e);
148 pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
149 pio_write_8(EGA_IO_BASE, 0x0f);
150 pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
151
152 /* Cursor visibility */
153 pio_write_8(EGA_IO_BASE, 0x0a);
154 uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
155
156 pio_write_8(EGA_IO_BASE, 0x0a);
157
158 if (visible)
159 pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
160 else
161 pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
162}
163
164static void ega_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
165{
166 charfield_t *field =
167 chargrid_charfield_at(dev->backbuf, col, row);
168
169 draw_char(field, col, row);
170}
171
172static outdev_ops_t ega_ops = {
173 .yield = ega_yield,
174 .claim = ega_claim,
175 .get_dimensions = ega_get_dimensions,
176 .get_caps = ega_get_caps,
177 .cursor_update = ega_cursor_update,
178 .char_update = ega_char_update
179};
180
181int ega_init(void)
182{
183 sysarg_t present;
184 int rc = sysinfo_get_value("fb", &present);
185 if (rc != EOK)
186 present = false;
187
188 if (!present)
189 return ENOENT;
190
191 sysarg_t kind;
192 rc = sysinfo_get_value("fb.kind", &kind);
193 if (rc != EOK)
194 kind = (sysarg_t) -1;
195
196 if (kind != 2)
197 return EINVAL;
198
199 sysarg_t paddr;
200 rc = sysinfo_get_value("fb.address.physical", &paddr);
201 if (rc != EOK)
202 return rc;
203
204 rc = sysinfo_get_value("fb.width", &ega.cols);
205 if (rc != EOK)
206 return rc;
207
208 rc = sysinfo_get_value("fb.height", &ega.rows);
209 if (rc != EOK)
210 return rc;
211
212 rc = pio_enable((void*)EGA_IO_BASE, EGA_IO_SIZE, NULL);
213 if (rc != EOK)
214 return rc;
215
216 ega.size = (ega.cols * ega.rows) << 1;
217
218 rc = physmem_map(paddr,
219 ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
220 AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
221 if (rc != EOK)
222 return rc;
223
224 sysarg_t blinking;
225 rc = sysinfo_get_value("fb.blinking", &blinking);
226 if (rc != EOK)
227 blinking = false;
228
229 ega.style_normal = 0xf0;
230 ega.style_inverted = 0x0f;
231
232 if (blinking) {
233 ega.style_normal &= 0x77;
234 ega.style_inverted &= 0x77;
235 }
236
237 outdev_t *dev = outdev_register(&ega_ops, (void *) &ega);
238 if (dev == NULL) {
239 as_area_destroy(ega.addr);
240 return EINVAL;
241 }
242
243 return EOK;
244}
245
246/** @}
247 */
Note: See TracBrowser for help on using the repository browser.