Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / libopenbios / video_common.c
1 /*
2  *   Creation Date: <2002/10/23 20:26:40 samuel>
3  *   Time-stamp: <2004/01/07 19:39:15 samuel>
4  *
5  *     <video_common.c>
6  *
7  *     Shared video routines
8  *
9  *   Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
10  *
11  *   This program is free software; you can redistribute it and/or
12  *   modify it under the terms of the GNU General Public License
13  *   as published by the Free Software Foundation
14  *
15  */
16
17 #include "config.h"
18 #include "libc/vsprintf.h"
19 #include "libopenbios/bindings.h"
20 #include "libopenbios/fontdata.h"
21 #include "libopenbios/ofmem.h"
22 #include "libopenbios/video.h"
23 #include "packages/video.h"
24 #include "drivers/vga.h"
25 #define NO_QEMU_PROTOS
26 #include "arch/common/fw_cfg.h"
27
28 struct video_info video;
29
30 unsigned long
31 video_get_color( int col_ind )
32 {
33         unsigned long col;
34         if( !VIDEO_DICT_VALUE(video.ih) || col_ind < 0 || col_ind > 255 )
35                 return 0;
36         if( VIDEO_DICT_VALUE(video.depth) == 8 )
37                 return col_ind;
38         col = video.pal[col_ind];
39         if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 )
40                 return col;
41         if( VIDEO_DICT_VALUE(video.depth) == 15 )
42                 return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
43         return 0;
44 }
45
46 /* ( fbaddr maskaddr width height fgcolor bgcolor -- ) */
47
48 void
49 video_mask_blit(void)
50 {
51         ucell bgcolor = POP();
52         ucell fgcolor = POP();
53         ucell height = POP();
54         ucell width = POP();
55         unsigned char *mask = (unsigned char *)POP();
56         unsigned char *fbaddr = (unsigned char *)POP();
57
58         ucell color;
59         unsigned char *dst, *rowdst;
60         int x, y, m, b, d, depthbytes;
61
62         fgcolor = video_get_color(fgcolor);
63         bgcolor = video_get_color(bgcolor);
64         d = VIDEO_DICT_VALUE(video.depth);
65         depthbytes = (d + 1) >> 3;
66
67         dst = fbaddr;
68         for( y = 0; y < height; y++) {
69                 rowdst = dst;
70                 for( x = 0; x < (width + 1) >> 3; x++ ) {
71                         for (b = 0; b < 8; b++) {
72                                 m = (1 << (7 - b));
73
74                                 if (*mask & m) {
75                                         color = fgcolor;
76                                 } else {
77                                         color = bgcolor;
78                                 }
79
80                                 if( d >= 24 )
81                                         *((uint32_t*)dst) = color;
82                                 else if( d >= 15 )
83                                         *((uint16_t*)dst) = color;
84                                 else
85                                         *dst = color;
86
87                                 dst += depthbytes;
88                         }
89                         mask++;
90                 }
91                 dst = rowdst;
92                 dst += VIDEO_DICT_VALUE(video.rb);
93         }
94 }
95
96 /* ( x y w h fgcolor bgcolor -- ) */
97
98 void
99 video_invert_rect( void )
100 {
101         ucell bgcolor = POP();
102         ucell fgcolor = POP();
103         int h = POP();
104         int w = POP();
105         int y = POP();
106         int x = POP();
107         char *pp;
108
109         bgcolor = video_get_color(bgcolor);
110         fgcolor = video_get_color(fgcolor);
111
112         if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
113                 x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
114                 return;
115
116         pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
117         for( ; h--; pp += *(video.rb) ) {
118                 int ww = w;
119                 if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
120                         uint32_t *p = (uint32_t*)pp + x;
121                         while( ww-- ) {
122                                 if (*p == fgcolor) {
123                                         *p++ = bgcolor;
124                                 } else if (*p == bgcolor) {
125                                         *p++ = fgcolor;
126                                 }
127                         }
128                 } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
129                         uint16_t *p = (uint16_t*)pp + x;
130                         while( ww-- ) {
131                                 if (*p == (uint16_t)fgcolor) {
132                                         *p++ = bgcolor;
133                                 } else if (*p == (uint16_t)bgcolor) {
134                                         *p++ = fgcolor;
135                                 }
136                         }
137                 } else {
138                         char *p = (char *)(pp + x);
139
140                         while( ww-- ) {
141                                 if (*p == (char)fgcolor) {
142                                         *p++ = bgcolor;
143                                 } else if (*p == (char)bgcolor) {
144                                         *p++ = fgcolor;
145                                 }
146                         }
147                 }
148         }
149 }
150
151 /* ( color_ind x y width height -- ) (?) */
152 void
153 video_fill_rect(void)
154 {
155         int h = POP();
156         int w = POP();
157         int y = POP();
158         int x = POP();
159         int col_ind = POP();
160
161         char *pp;
162         unsigned long col = video_get_color(col_ind);
163
164         if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
165             x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
166                 return;
167
168         pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
169         for( ; h--; pp += VIDEO_DICT_VALUE(video.rb) ) {
170                 int ww = w;
171                 if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
172                         uint32_t *p = (uint32_t*)pp + x;
173                         while( ww-- )
174                                 *p++ = col;
175                 } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
176                         uint16_t *p = (uint16_t*)pp + x;
177                         while( ww-- )
178                                 *p++ = col;
179                 } else {
180                         char *p = (char *)(pp + x);
181
182                         while( ww-- )
183                                 *p++ = col;
184                 }
185         }
186 }
187
188 void setup_video()
189 {
190         /* Make everything inside the video_info structure point to the
191            values in the Forth dictionary. Hence everything is always in
192            sync. */
193         phandle_t options;
194         char buf[6];
195
196         feval("['] display-ih cell+");
197         video.ih = cell2pointer(POP());
198
199         feval("['] frame-buffer-adr cell+");
200         video.mvirt = cell2pointer(POP());
201         feval("['] openbios-video-width cell+");
202         video.w = cell2pointer(POP());
203         feval("['] openbios-video-height cell+");
204         video.h = cell2pointer(POP());
205         feval("['] depth-bits cell+");
206         video.depth = cell2pointer(POP());
207         feval("['] line-bytes cell+");
208         video.rb = cell2pointer(POP());
209         feval("['] color-palette cell+");
210         video.pal = cell2pointer(POP());
211
212         /* Set global variables ready for fb8-install */
213         PUSH( pointer2cell(video_mask_blit) );
214         fword("is-noname-cfunc");
215         feval("to fb8-blitmask");
216         PUSH( pointer2cell(video_fill_rect) );
217         fword("is-noname-cfunc");
218         feval("to fb8-fillrect");
219         PUSH( pointer2cell(video_invert_rect) );
220         fword("is-noname-cfunc");
221         feval("to fb8-invertrect");
222
223         /* Static information */
224         PUSH((ucell)fontdata);
225         feval("to (romfont)");
226         PUSH(FONT_HEIGHT);
227         feval("to (romfont-height)");
228         PUSH(FONT_WIDTH);
229         feval("to (romfont-width)");
230
231         /* Initialise the structure */
232         VIDEO_DICT_VALUE(video.w) = VGA_DEFAULT_WIDTH;
233         VIDEO_DICT_VALUE(video.h) = VGA_DEFAULT_HEIGHT;
234         VIDEO_DICT_VALUE(video.depth) = VGA_DEFAULT_DEPTH;
235         VIDEO_DICT_VALUE(video.rb) = VGA_DEFAULT_LINEBYTES;
236
237 #if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64))
238         /* If running from QEMU, grab the parameters from the firmware interface */
239         int w, h, d;
240
241         w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH);
242         h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT);
243         d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH);
244         if (w && h && d) {
245                 VIDEO_DICT_VALUE(video.w) = w;
246                 VIDEO_DICT_VALUE(video.h) = h;
247                 VIDEO_DICT_VALUE(video.depth) = d;
248                 VIDEO_DICT_VALUE(video.rb) = (w * ((d + 7) / 8));
249         }
250 #endif
251
252         /* Setup screen-#rows/screen-#columns */
253         options = find_dev("/options");
254         snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.w) / FONT_WIDTH);
255         set_property(options, "screen-#columns", buf, strlen(buf) + 1);
256         snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.h) / FONT_HEIGHT);
257         set_property(options, "screen-#rows", buf, strlen(buf) + 1);
258 }