move vga_io_address to VGA State (Glauber Costa)
[qemu/qemu-JZ.git] / hw / jazz_led.c
blobc8ac26372f65175eb7cb2b14c1fc96a597795668
1 /*
2 * QEMU JAZZ LED emulator.
4 * Copyright (c) 2007 Hervé Poussineau
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "hw.h"
26 #include "mips.h"
27 #include "console.h"
28 #include "pixel_ops.h"
30 //#define DEBUG_LED
32 typedef enum {
33 REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
34 } screen_state_t;
36 typedef struct LedState {
37 target_phys_addr_t base;
38 uint8_t segments;
39 DisplayState *ds;
40 QEMUConsole *console;
41 screen_state_t state;
42 } LedState;
44 static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
46 LedState *s = opaque;
47 int relative_addr = addr - s->base;
48 uint32_t val;
50 switch (relative_addr) {
51 case 0:
52 val = s->segments;
53 break;
54 default:
55 #ifdef DEBUG_LED
56 printf("jazz led: invalid read [0x%x]\n", relative_addr);
57 #endif
58 val = 0;
61 return val;
64 static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
66 uint32_t v;
67 #ifdef TARGET_WORDS_BIGENDIAN
68 v = led_readb(opaque, addr) << 8;
69 v |= led_readb(opaque, addr + 1);
70 #else
71 v = led_readb(opaque, addr);
72 v |= led_readb(opaque, addr + 1) << 8;
73 #endif
74 return v;
77 static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
79 uint32_t v;
80 #ifdef TARGET_WORDS_BIGENDIAN
81 v = led_readb(opaque, addr) << 24;
82 v |= led_readb(opaque, addr + 1) << 16;
83 v |= led_readb(opaque, addr + 2) << 8;
84 v |= led_readb(opaque, addr + 3);
85 #else
86 v = led_readb(opaque, addr);
87 v |= led_readb(opaque, addr + 1) << 8;
88 v |= led_readb(opaque, addr + 2) << 16;
89 v |= led_readb(opaque, addr + 3) << 24;
90 #endif
91 return v;
94 static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
96 LedState *s = opaque;
97 int relative_addr = addr - s->base;
99 switch (relative_addr) {
100 case 0:
101 s->segments = val;
102 s->state |= REDRAW_SEGMENTS;
103 break;
104 default:
105 #ifdef DEBUG_LED
106 printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
107 #endif
108 break;
112 static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
114 #ifdef TARGET_WORDS_BIGENDIAN
115 led_writeb(opaque, addr, (val >> 8) & 0xff);
116 led_writeb(opaque, addr + 1, val & 0xff);
117 #else
118 led_writeb(opaque, addr, val & 0xff);
119 led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
120 #endif
123 static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
125 #ifdef TARGET_WORDS_BIGENDIAN
126 led_writeb(opaque, addr, (val >> 24) & 0xff);
127 led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
128 led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
129 led_writeb(opaque, addr + 3, val & 0xff);
130 #else
131 led_writeb(opaque, addr, val & 0xff);
132 led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
133 led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
134 led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
135 #endif
138 static CPUReadMemoryFunc *led_read[3] = {
139 led_readb,
140 led_readw,
141 led_readl,
144 static CPUWriteMemoryFunc *led_write[3] = {
145 led_writeb,
146 led_writew,
147 led_writel,
150 /***********************************************************/
151 /* jazz_led display */
153 static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
155 uint8_t *d;
156 int x, bpp;
158 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
159 d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
160 switch(bpp) {
161 case 1:
162 for (x = posx1; x <= posx2; x++) {
163 *((uint8_t *)d) = color;
164 d++;
166 break;
167 case 2:
168 for (x = posx1; x <= posx2; x++) {
169 *((uint16_t *)d) = color;
170 d += 2;
172 break;
173 case 4:
174 for (x = posx1; x <= posx2; x++) {
175 *((uint32_t *)d) = color;
176 d += 4;
178 break;
182 static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
184 uint8_t *d;
185 int y, bpp;
187 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
188 d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
189 switch(bpp) {
190 case 1:
191 for (y = posy1; y <= posy2; y++) {
192 *((uint8_t *)d) = color;
193 d += ds_get_linesize(ds);
195 break;
196 case 2:
197 for (y = posy1; y <= posy2; y++) {
198 *((uint16_t *)d) = color;
199 d += ds_get_linesize(ds);
201 break;
202 case 4:
203 for (y = posy1; y <= posy2; y++) {
204 *((uint32_t *)d) = color;
205 d += ds_get_linesize(ds);
207 break;
211 static void jazz_led_update_display(void *opaque)
213 LedState *s = opaque;
214 DisplayState *ds = s->ds;
215 uint8_t *d1;
216 uint32_t color_segment, color_led;
217 int y, bpp;
219 if (s->state & REDRAW_BACKGROUND) {
220 /* clear screen */
221 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
222 d1 = ds_get_data(ds);
223 for (y = 0; y < ds_get_height(ds); y++) {
224 memset(d1, 0x00, ds_get_width(ds) * bpp);
225 d1 += ds_get_linesize(ds);
229 if (s->state & REDRAW_SEGMENTS) {
230 /* set colors according to bpp */
231 switch (ds_get_bits_per_pixel(ds)) {
232 case 8:
233 color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
234 color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
235 break;
236 case 15:
237 color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
238 color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
239 break;
240 case 16:
241 color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
242 color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
243 case 24:
244 color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
245 color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
246 break;
247 case 32:
248 color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
249 color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
250 break;
251 default:
252 return;
255 /* display segments */
256 draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
257 draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
258 draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
259 draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
260 draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
261 draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
262 draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
264 /* display led */
265 if (!(s->segments & 0x01))
266 color_led = 0; /* black */
267 draw_horizontal_line(ds, 68, 50, 50, color_led);
268 draw_horizontal_line(ds, 69, 49, 51, color_led);
269 draw_horizontal_line(ds, 70, 48, 52, color_led);
270 draw_horizontal_line(ds, 71, 49, 51, color_led);
271 draw_horizontal_line(ds, 72, 50, 50, color_led);
274 s->state = REDRAW_NONE;
275 dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
278 static void jazz_led_invalidate_display(void *opaque)
280 LedState *s = opaque;
281 s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
284 static void jazz_led_screen_dump(void *opaque, const char *filename)
286 printf("jazz_led_screen_dump() not implemented\n");
289 static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
291 LedState *s = opaque;
292 char buf[2];
294 dpy_cursor(s->ds, -1, -1);
295 qemu_console_resize(s->console, 2, 1);
297 /* TODO: draw the segments */
298 snprintf(buf, 2, "%02hhx\n", s->segments);
299 console_write_ch(chardata++, 0x00200100 | buf[0]);
300 console_write_ch(chardata++, 0x00200100 | buf[1]);
302 dpy_update(s->ds, 0, 0, 2, 1);
305 void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
307 LedState *s;
308 int io;
310 s = qemu_mallocz(sizeof(LedState));
311 if (!s)
312 return;
314 s->base = base;
315 s->ds = ds;
316 s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
318 io = cpu_register_io_memory(0, led_read, led_write, s);
319 cpu_register_physical_memory(s->base, 1, io);
321 s->console = graphic_console_init(ds, jazz_led_update_display,
322 jazz_led_invalidate_display,
323 jazz_led_screen_dump,
324 jazz_led_text_update, s);
325 qemu_console_resize(s->console, 60, 80);