source: mainline/fb/ega.c@ e92aabf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e92aabf was ce5bcb4, checked in by Josef Cejka <malyzelenyhnus@…>, 19 years ago

Doxygen comments update.

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