Annotation of qemu/hw/jazz_led.c, revision 1.1.1.1
1.1 root 1: /*
2: * QEMU JAZZ LED emulator.
3: *
4: * Copyright (c) 2007 Hervé Poussineau
5: *
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:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
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.
23: */
24:
25: #include "hw.h"
26: #include "mips.h"
27: #include "console.h"
28: #include "pixel_ops.h"
29:
30: //#define DEBUG_LED
31:
32: typedef enum {
33: REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
34: } screen_state_t;
35:
36: typedef struct LedState {
37: target_phys_addr_t base;
38: uint8_t segments;
39: DisplayState *ds;
40: screen_state_t state;
41: } LedState;
42:
43: static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
44: {
45: LedState *s = opaque;
46: int relative_addr = addr - s->base;
47: uint32_t val;
48:
49: switch (relative_addr) {
50: case 0:
51: val = s->segments;
52: break;
53: default:
54: #ifdef DEBUG_LED
55: printf("jazz led: invalid read [0x%x]\n", relative_addr);
56: #endif
57: val = 0;
58: }
59:
60: return val;
61: }
62:
63: static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
64: {
65: uint32_t v;
66: #ifdef TARGET_WORDS_BIGENDIAN
67: v = led_readb(opaque, addr) << 8;
68: v |= led_readb(opaque, addr + 1);
69: #else
70: v = led_readb(opaque, addr);
71: v |= led_readb(opaque, addr + 1) << 8;
72: #endif
73: return v;
74: }
75:
76: static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
77: {
78: uint32_t v;
79: #ifdef TARGET_WORDS_BIGENDIAN
80: v = led_readb(opaque, addr) << 24;
81: v |= led_readb(opaque, addr + 1) << 16;
82: v |= led_readb(opaque, addr + 2) << 8;
83: v |= led_readb(opaque, addr + 3);
84: #else
85: v = led_readb(opaque, addr);
86: v |= led_readb(opaque, addr + 1) << 8;
87: v |= led_readb(opaque, addr + 2) << 16;
88: v |= led_readb(opaque, addr + 3) << 24;
89: #endif
90: return v;
91: }
92:
93: static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
94: {
95: LedState *s = opaque;
96: int relative_addr = addr - s->base;
97:
98: switch (relative_addr) {
99: case 0:
100: s->segments = val;
101: s->state |= REDRAW_SEGMENTS;
102: break;
103: default:
104: #ifdef DEBUG_LED
105: printf("jazz led: invalid write of 0x%02x at [0x%x]\n", val, relative_addr);
106: #endif
107: break;
108: }
109: }
110:
111: static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
112: {
113: #ifdef TARGET_WORDS_BIGENDIAN
114: led_writeb(opaque, addr, (val >> 8) & 0xff);
115: led_writeb(opaque, addr + 1, val & 0xff);
116: #else
117: led_writeb(opaque, addr, val & 0xff);
118: led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
119: #endif
120: }
121:
122: static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
123: {
124: #ifdef TARGET_WORDS_BIGENDIAN
125: led_writeb(opaque, addr, (val >> 24) & 0xff);
126: led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
127: led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
128: led_writeb(opaque, addr + 3, val & 0xff);
129: #else
130: led_writeb(opaque, addr, val & 0xff);
131: led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
132: led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
133: led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
134: #endif
135: }
136:
137: static CPUReadMemoryFunc *led_read[3] = {
138: led_readb,
139: led_readw,
140: led_readl,
141: };
142:
143: static CPUWriteMemoryFunc *led_write[3] = {
144: led_writeb,
145: led_writew,
146: led_writel,
147: };
148:
149: /***********************************************************/
150: /* jazz_led display */
151:
152: static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
153: {
154: uint8_t *d;
155: int x, bpp;
156:
157: bpp = (ds->depth + 7) >> 3;
158: d = ds->data + ds->linesize * posy + bpp * posx1;
159: switch(bpp) {
160: case 1:
161: for (x = posx1; x <= posx2; x++) {
162: *((uint8_t *)d) = color;
163: d++;
164: }
165: break;
166: case 2:
167: for (x = posx1; x <= posx2; x++) {
168: *((uint16_t *)d) = color;
169: d += 2;
170: }
171: break;
172: case 4:
173: for (x = posx1; x <= posx2; x++) {
174: *((uint32_t *)d) = color;
175: d += 4;
176: }
177: break;
178: }
179: }
180:
181: static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
182: {
183: uint8_t *d;
184: int y, bpp;
185:
186: bpp = (ds->depth + 7) >> 3;
187: d = ds->data + ds->linesize * posy1 + bpp * posx;
188: switch(bpp) {
189: case 1:
190: for (y = posy1; y <= posy2; y++) {
191: *((uint8_t *)d) = color;
192: d += ds->linesize;
193: }
194: break;
195: case 2:
196: for (y = posy1; y <= posy2; y++) {
197: *((uint16_t *)d) = color;
198: d += ds->linesize;
199: }
200: break;
201: case 4:
202: for (y = posy1; y <= posy2; y++) {
203: *((uint32_t *)d) = color;
204: d += ds->linesize;
205: }
206: break;
207: }
208: }
209:
210: static void jazz_led_update_display(void *opaque)
211: {
212: LedState *s = opaque;
213: DisplayState *ds = s->ds;
214: uint8_t *d1;
215: uint32_t color_segment, color_led;
216: int y, bpp;
217:
218: if (s->state & REDRAW_BACKGROUND) {
219: /* clear screen */
220: bpp = (ds->depth + 7) >> 3;
221: d1 = ds->data;
222: for (y = 0; y < ds->height; y++) {
223: memset(d1, 0x00, ds->width * bpp);
224: d1 += ds->linesize;
225: }
226: }
227:
228: if (s->state & REDRAW_SEGMENTS) {
229: /* set colors according to bpp */
230: switch (ds->depth) {
231: case 8:
232: color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
233: color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
234: break;
235: case 15:
236: color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
237: color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
238: break;
239: case 16:
240: color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
241: color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
242: case 24:
243: color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
244: color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
245: break;
246: case 32:
247: color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
248: color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
249: break;
250: default:
251: return;
252: }
253:
254: /* display segments */
255: draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
256: draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
257: draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
258: draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
259: draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
260: draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
261: draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
262:
263: /* display led */
264: if (!(s->segments & 0x01))
265: color_led = 0; /* black */
266: draw_horizontal_line(ds, 68, 50, 50, color_led);
267: draw_horizontal_line(ds, 69, 49, 51, color_led);
268: draw_horizontal_line(ds, 70, 48, 52, color_led);
269: draw_horizontal_line(ds, 71, 49, 51, color_led);
270: draw_horizontal_line(ds, 72, 50, 50, color_led);
271: }
272:
273: s->state = REDRAW_NONE;
274: dpy_update(ds, 0, 0, ds->width, ds->height);
275: }
276:
277: static void jazz_led_invalidate_display(void *opaque)
278: {
279: LedState *s = opaque;
280: s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
281: }
282:
283: static void jazz_led_screen_dump(void *opaque, const char *filename)
284: {
285: printf("jazz_led_screen_dump() not implemented\n");
286: }
287:
288: void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
289: {
290: LedState *s;
291: int io;
292:
293: s = qemu_mallocz(sizeof(LedState));
294: if (!s)
295: return;
296:
297: s->base = base;
298: s->ds = ds;
299: s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
300:
301: io = cpu_register_io_memory(0, led_read, led_write, s);
302: cpu_register_physical_memory(s->base, 1, io);
303:
304: graphic_console_init(ds, jazz_led_update_display, jazz_led_invalidate_display, jazz_led_screen_dump, s);
305: }
unix.superglobalmegacorp.com