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

Last change on this file since db9a8464 was 09f41d3, checked in by Jiri Svoboda <jiri@…>, 12 months ago

Tetris should be able to detect screen cursor control capability

  • Property mode set to 100644
File size: 6.1 KB
RevLine 
[7c014d1]1/*
[7dbf1f6]2 * Copyright (c) 2024 Jiri Svoboda
[7c014d1]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
[4122410]30/** @addtogroup output
31 * @{
[7c014d1]32 */
33
[9b2e20c]34#include <codepage/cp437.h>
[7c014d1]35#include <errno.h>
36#include <sysinfo.h>
[6d5e378]37#include <align.h>
38#include <as.h>
[7c014d1]39#include <ddi.h>
[6d5e378]40#include <io/chargrid.h>
41#include "../output.h"
[7c014d1]42#include "ega.h"
43
44#define EGA_IO_BASE ((ioport8_t *) 0x3d4)
45#define EGA_IO_SIZE 2
46
[6d5e378]47#define FB_POS(x, y) (((y) * ega.cols + (x)) << 1)
[7c014d1]48
49typedef struct {
[6d5e378]50 sysarg_t cols;
51 sysarg_t rows;
[a35b458]52
[7c014d1]53 uint8_t style_normal;
54 uint8_t style_inverted;
[a35b458]55
[6d5e378]56 size_t size;
57 uint8_t *addr;
[7c014d1]58} ega_t;
59
60static ega_t ega;
61
62static uint8_t attrs_attr(char_attrs_t attrs)
63{
64 uint8_t attr = 0;
[a35b458]65
[7c014d1]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);
[a35b458]86
[7c014d1]87 if (attrs.val.index.attr & CATTR_BRIGHT)
88 attr |= 0x08;
[a35b458]89
[7c014d1]90 break;
91 case CHAR_ATTR_RGB:
[bdf06ad]92 attr =
[7dbf1f6]93 ((RED(attrs.val.rgb.fgcolor) >= 0x80) ? 0x40 : 0) |
94 ((GREEN(attrs.val.rgb.fgcolor) >= 0x80) ? 0x20 : 0) |
95 ((BLUE(attrs.val.rgb.fgcolor) >= 0x80) ? 0x10 : 0) |
96 ((RED(attrs.val.rgb.bgcolor) >= 0x80) ? 0x04 : 0) |
97 ((GREEN(attrs.val.rgb.bgcolor) >= 0x80) ? 0x02 : 0) |
98 ((BLUE(attrs.val.rgb.bgcolor) >= 0x80) ? 0x01 : 0);
[7c014d1]99 break;
100 }
[a35b458]101
[7c014d1]102 return attr;
103}
104
[6d5e378]105/** Draw the character at the specified position.
[7c014d1]106 *
[6d5e378]107 * @param field Character field.
108 * @param col Horizontal screen position.
109 * @param row Vertical screen position.
[7c014d1]110 *
111 */
[6d5e378]112static void draw_char(charfield_t *field, sysarg_t col, sysarg_t row)
[7c014d1]113{
114 uint8_t glyph;
[9b2e20c]115 errno_t rc;
[a35b458]116
[9b2e20c]117 rc = cp437_encode(field->ch, &glyph);
118 if (rc != EOK)
[7c014d1]119 glyph = '?';
[a35b458]120
[7c014d1]121 uint8_t attr = attrs_attr(field->attrs);
[a35b458]122
[6d5e378]123 ega.addr[FB_POS(col, row)] = glyph;
124 ega.addr[FB_POS(col, row) + 1] = attr;
[7c014d1]125}
126
[b7fd2a0]127static errno_t ega_yield(outdev_t *dev)
[7c014d1]128{
129 return EOK;
130}
131
[b7fd2a0]132static errno_t ega_claim(outdev_t *dev)
[7c014d1]133{
134 return EOK;
135}
136
[6d5e378]137static void ega_get_dimensions(outdev_t *dev, sysarg_t *cols, sysarg_t *rows)
[7c014d1]138{
[6d5e378]139 *cols = ega.cols;
140 *rows = ega.rows;
[7c014d1]141}
142
[6d5e378]143static console_caps_t ega_get_caps(outdev_t *dev)
[7c014d1]144{
[09f41d3]145 return (CONSOLE_CAP_CURSORCTL | CONSOLE_CAP_STYLE |
146 CONSOLE_CAP_INDEXED);
[7c014d1]147}
148
[6d5e378]149static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
[7c014d1]150 sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
151{
152 /* Cursor position */
[6d5e378]153 uint16_t cursor = row * ega.cols + col;
[a35b458]154
[7c014d1]155 pio_write_8(EGA_IO_BASE, 0x0e);
156 pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
157 pio_write_8(EGA_IO_BASE, 0x0f);
158 pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
[a35b458]159
[7c014d1]160 /* Cursor visibility */
161 pio_write_8(EGA_IO_BASE, 0x0a);
162 uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
[a35b458]163
[7c014d1]164 pio_write_8(EGA_IO_BASE, 0x0a);
[a35b458]165
[7c014d1]166 if (visible)
167 pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
168 else
169 pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
170}
171
[6d5e378]172static void ega_char_update(outdev_t *dev, sysarg_t col, sysarg_t row)
[7c014d1]173{
[6d5e378]174 charfield_t *field =
175 chargrid_charfield_at(dev->backbuf, col, row);
[a35b458]176
[6d5e378]177 draw_char(field, col, row);
[7c014d1]178}
179
[bbc6277]180static void ega_flush(outdev_t *dev)
181{
182}
183
[6d5e378]184static outdev_ops_t ega_ops = {
[7c014d1]185 .yield = ega_yield,
186 .claim = ega_claim,
[6d5e378]187 .get_dimensions = ega_get_dimensions,
188 .get_caps = ega_get_caps,
189 .cursor_update = ega_cursor_update,
[bbc6277]190 .char_update = ega_char_update,
191 .flush = ega_flush
[7c014d1]192};
193
[b7fd2a0]194errno_t ega_init(void)
[7c014d1]195{
196 sysarg_t present;
[b7fd2a0]197 errno_t rc = sysinfo_get_value("fb", &present);
[7c014d1]198 if (rc != EOK)
199 present = false;
[a35b458]200
[7c014d1]201 if (!present)
202 return ENOENT;
[a35b458]203
[7c014d1]204 sysarg_t kind;
205 rc = sysinfo_get_value("fb.kind", &kind);
206 if (rc != EOK)
207 kind = (sysarg_t) -1;
[a35b458]208
[7c014d1]209 if (kind != 2)
210 return EINVAL;
[a35b458]211
[7c014d1]212 sysarg_t paddr;
213 rc = sysinfo_get_value("fb.address.physical", &paddr);
214 if (rc != EOK)
215 return rc;
[a35b458]216
[6d5e378]217 rc = sysinfo_get_value("fb.width", &ega.cols);
[7c014d1]218 if (rc != EOK)
219 return rc;
[a35b458]220
[6d5e378]221 rc = sysinfo_get_value("fb.height", &ega.rows);
[7c014d1]222 if (rc != EOK)
223 return rc;
[a35b458]224
[1433ecda]225 rc = pio_enable((void *)EGA_IO_BASE, EGA_IO_SIZE, NULL);
[7c014d1]226 if (rc != EOK)
227 return rc;
[a35b458]228
[6d5e378]229 ega.size = (ega.cols * ega.rows) << 1;
[bf9cb2f]230 ega.addr = AS_AREA_ANY;
[a35b458]231
[8442d10]232 rc = physmem_map(paddr,
[fbcdeb8]233 ALIGN_UP(ega.size, PAGE_SIZE) >> PAGE_WIDTH,
234 AS_AREA_READ | AS_AREA_WRITE, (void *) &ega.addr);
[7c014d1]235 if (rc != EOK)
236 return rc;
[a35b458]237
[7c014d1]238 sysarg_t blinking;
239 rc = sysinfo_get_value("fb.blinking", &blinking);
240 if (rc != EOK)
241 blinking = false;
[a35b458]242
[7c014d1]243 ega.style_normal = 0xf0;
244 ega.style_inverted = 0x0f;
[a35b458]245
[7c014d1]246 if (blinking) {
247 ega.style_normal &= 0x77;
248 ega.style_inverted &= 0x77;
249 }
[a35b458]250
[6d5e378]251 outdev_t *dev = outdev_register(&ega_ops, (void *) &ega);
[7c014d1]252 if (dev == NULL) {
253 as_area_destroy(ega.addr);
254 return EINVAL;
255 }
[a35b458]256
[7c014d1]257 return EOK;
258}
259
[6d5e378]260/** @}
[7c014d1]261 */
Note: See TracBrowser for help on using the repository browser.