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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since adc68de was 7ee7e6a, checked in by Jakub Jermar <jakub@…>, 8 years ago

Further reduce the number of inclusions of sys/types.h

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