source: mainline/fb/ega.c@ d3f2cad

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d3f2cad was d3f2cad, checked in by Ondrej Palkovsky <ondrap@…>, 20 years ago

Better colors for ega.
Small updates to initialization code to use only async api.

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