source: mainline/uspace/fb/ega.c@ f3fed18

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

The Ultimate Solution To Illegal Virtual Aliases.
It is better to avoid them completely than to fight them.
Switch the sparc64 port to 16K pages. The TLBs and TSBs
continue to operate with 8K pages only. Page tables and
other generic parts operate with 16K pages.

Because the MMU doesn't support 16K directly, each 16K
page is emulated by a pair of 8K pages. With 16K pages,
illegal aliases cannot be created in 16K D-cache.

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Copyright (c) 2006 Ondrej Palkovsky
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/** @defgroup egafb EGA framebuffer
30 * @brief HelenOS EGA framebuffer.
31 * @ingroup fbs
32 * @{
33 */
34/** @file
35 */
36
37#include <stdlib.h>
38#include <unistd.h>
39#include <align.h>
40#include <async.h>
41#include <ipc/ipc.h>
42#include <errno.h>
43#include <stdio.h>
44#include <ddi.h>
45#include <sysinfo.h>
46#include <as.h>
47#include <ipc/fb.h>
48#include <ipc/ipc.h>
49#include <ipc/ns.h>
50#include <ipc/services.h>
51#include <libarch/ddi.h>
52
53#include "ega.h"
54#include "../console/screenbuffer.h"
55#include "main.h"
56
57#define MAX_SAVED_SCREENS 256
58typedef struct saved_screen {
59 short *data;
60} saved_screen;
61
62saved_screen saved_screens[MAX_SAVED_SCREENS];
63
64#define EGA_IO_ADDRESS 0x3d4
65#define EGA_IO_SIZE 2
66
67#define NORMAL_COLOR 0x0f
68#define INVERTED_COLOR 0xf0
69
70#define EGA_STYLE(fg,bg) ((fg) > (bg) ? NORMAL_COLOR : INVERTED_COLOR)
71
72/* Allow only 1 connection */
73static int client_connected = 0;
74
75static unsigned int scr_width;
76static unsigned int scr_height;
77static char *scr_addr;
78
79static unsigned int style = NORMAL_COLOR;
80
81static void clrscr(void)
82{
83 int i;
84
85 for (i = 0; i < scr_width*scr_height; i++) {
86 scr_addr[i * 2] = ' ';
87 scr_addr[i * 2 + 1] = style;
88 }
89}
90
91static void cursor_goto(unsigned int row, unsigned int col)
92{
93 int ega_cursor;
94
95 ega_cursor = col + scr_width * row;
96
97 outb(EGA_IO_ADDRESS, 0xe);
98 outb(EGA_IO_ADDRESS + 1, (ega_cursor >> 8) & 0xff);
99 outb(EGA_IO_ADDRESS, 0xf);
100 outb(EGA_IO_ADDRESS + 1, ega_cursor & 0xff);
101}
102
103static void cursor_disable(void)
104{
105 uint8_t stat;
106
107 outb(EGA_IO_ADDRESS, 0xa);
108 stat=inb(EGA_IO_ADDRESS + 1);
109 outb(EGA_IO_ADDRESS, 0xa);
110 outb(EGA_IO_ADDRESS + 1, stat | (1 << 5));
111}
112
113static void cursor_enable(void)
114{
115 uint8_t stat;
116
117 outb(EGA_IO_ADDRESS, 0xa);
118 stat=inb(EGA_IO_ADDRESS + 1);
119 outb(EGA_IO_ADDRESS, 0xa);
120 outb(EGA_IO_ADDRESS + 1, stat & (~(1 << 5)));
121}
122
123static void scroll(int rows)
124{
125 int i;
126 if (rows > 0) {
127 memcpy(scr_addr, ((char *) scr_addr) + rows * scr_width * 2,
128 scr_width * scr_height * 2 - rows * scr_width * 2);
129 for (i = 0; i < rows * scr_width; i++)
130 (((short *) scr_addr) + scr_width * scr_height - rows *
131 scr_width)[i] = ((style << 8) + ' ');
132 } else if (rows < 0) {
133 memcpy(((char *)scr_addr) - rows * scr_width * 2, scr_addr,
134 scr_width * scr_height * 2 + rows * scr_width * 2);
135 for (i = 0; i < -rows * scr_width; i++)
136 ((short *)scr_addr)[i] = ((style << 8 ) + ' ');
137 }
138}
139
140static void printchar(char c, unsigned int row, unsigned int col)
141{
142 scr_addr[(row * scr_width + col) * 2] = c;
143 scr_addr[(row * scr_width + col) * 2 + 1] = style;
144
145 cursor_goto(row, col + 1);
146}
147
148static void draw_text_data(keyfield_t *data)
149{
150 int i;
151
152 for (i = 0; i < scr_width * scr_height; i++) {
153 scr_addr[i * 2] = data[i].character;
154 scr_addr[i * 2 + 1] = EGA_STYLE(data[i].style.fg_color,
155 data[i].style.bg_color);
156 }
157}
158
159static int save_screen(void)
160{
161 int i;
162
163 for (i=0; (i < MAX_SAVED_SCREENS) && (saved_screens[i].data); i++)
164 ;
165 if (i == MAX_SAVED_SCREENS)
166 return EINVAL;
167 if (!(saved_screens[i].data = malloc(2 * scr_width * scr_height)))
168 return ENOMEM;
169 memcpy(saved_screens[i].data, scr_addr, 2 * scr_width * scr_height);
170
171 return i;
172}
173
174static int print_screen(int i)
175{
176 if (saved_screens[i].data)
177 memcpy(scr_addr, saved_screens[i].data, 2 * scr_width *
178 scr_height);
179 else
180 return EINVAL;
181 return i;
182}
183
184
185static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
186{
187 int retval;
188 ipc_callid_t callid;
189 ipc_call_t call;
190 char c;
191 unsigned int row, col;
192 int bgcolor,fgcolor;
193 keyfield_t *interbuf = NULL;
194 size_t intersize = 0;
195 int i;
196
197 if (client_connected) {
198 ipc_answer_fast(iid, ELIMIT, 0,0);
199 return;
200 }
201 client_connected = 1;
202 ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
203
204 while (1) {
205 callid = async_get_call(&call);
206 switch (IPC_GET_METHOD(call)) {
207 case IPC_M_PHONE_HUNGUP:
208 client_connected = 0;
209 ipc_answer_fast(callid, 0, 0, 0);
210 return; /* Exit thread */
211 case IPC_M_AS_AREA_SEND:
212 /* We accept one area for data interchange */
213 intersize = IPC_GET_ARG2(call);
214 if (intersize >= scr_width * scr_height *
215 sizeof(*interbuf)) {
216 receive_comm_area(callid, &call, (void *)
217 &interbuf);
218 continue;
219 }
220 retval = EINVAL;
221 break;
222 case FB_DRAW_TEXT_DATA:
223 if (!interbuf) {
224 retval = EINVAL;
225 break;
226 }
227 draw_text_data(interbuf);
228 retval = 0;
229 break;
230 case FB_GET_CSIZE:
231 ipc_answer_fast(callid, 0, scr_height, scr_width);
232 continue;
233 case FB_CLEAR:
234 clrscr();
235 retval = 0;
236 break;
237 case FB_PUTCHAR:
238 c = IPC_GET_ARG1(call);
239 row = IPC_GET_ARG2(call);
240 col = IPC_GET_ARG3(call);
241 if (col >= scr_width || row >= scr_height) {
242 retval = EINVAL;
243 break;
244 }
245 printchar(c, row, col);
246 retval = 0;
247 break;
248 case FB_CURSOR_GOTO:
249 row = IPC_GET_ARG1(call);
250 col = IPC_GET_ARG2(call);
251 if (row >= scr_height || col >= scr_width) {
252 retval = EINVAL;
253 break;
254 }
255 cursor_goto(row, col);
256 retval = 0;
257 break;
258 case FB_SCROLL:
259 i = IPC_GET_ARG1(call);
260 if (i > scr_height || i < -((int) scr_height)) {
261 retval = EINVAL;
262 break;
263 }
264 scroll(i);
265 retval = 0;
266 break;
267 case FB_CURSOR_VISIBILITY:
268 if(IPC_GET_ARG1(call))
269 cursor_enable();
270 else
271 cursor_disable();
272 retval = 0;
273 break;
274 case FB_SET_STYLE:
275 fgcolor = IPC_GET_ARG1(call);
276 bgcolor = IPC_GET_ARG2(call);
277 style = EGA_STYLE(fgcolor, bgcolor);
278 retval = 0;
279 break;
280 case FB_VP_DRAW_PIXMAP:
281 i = IPC_GET_ARG2(call);
282 retval = print_screen(i);
283 break;
284 case FB_VP2PIXMAP:
285 retval = save_screen();
286 break;
287 case FB_DROP_PIXMAP:
288 i = IPC_GET_ARG1(call);
289 if (i >= MAX_SAVED_SCREENS) {
290 retval = EINVAL;
291 break;
292 }
293 if (saved_screens[i].data) {
294 free(saved_screens[i].data);
295 saved_screens[i].data = NULL;
296 }
297 retval = 0;
298 break;
299
300 default:
301 retval = ENOENT;
302 }
303 ipc_answer_fast(callid, retval, 0, 0);
304 }
305}
306
307int ega_init(void)
308{
309 void *ega_ph_addr;
310 size_t sz;
311
312 ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
313 scr_width = sysinfo_value("fb.width");
314 scr_height = sysinfo_value("fb.height");
315 iospace_enable(task_get_id(), (void *) EGA_IO_ADDRESS, 2);
316
317 sz = scr_width * scr_height * 2;
318 scr_addr = as_get_mappable_page(sz);
319
320 physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
321 PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE);
322
323 async_set_client_connection(ega_client_connection);
324
325 return 0;
326}
327
328
329/**
330 * @}
331 */
Note: See TracBrowser for help on using the repository browser.