Annotation of qemu/hw/jazz_led.c, revision 1.1.1.5

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: 
1.1.1.5 ! root       32: #ifdef DEBUG_LED
        !            33: #define DPRINTF(fmt, ...) \
        !            34: do { printf("jazz led: " fmt , ## __VA_ARGS__); } while (0)
        !            35: #else
        !            36: #define DPRINTF(fmt, ...) do {} while (0)
        !            37: #endif
        !            38: #define BADF(fmt, ...) \
        !            39: do { fprintf(stderr, "jazz led ERROR: " fmt , ## __VA_ARGS__);} while (0)
        !            40: 
1.1       root       41: typedef enum {
                     42:     REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
                     43: } screen_state_t;
                     44: 
                     45: typedef struct LedState {
                     46:     uint8_t segments;
                     47:     DisplayState *ds;
                     48:     screen_state_t state;
                     49: } LedState;
                     50: 
                     51: static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
                     52: {
                     53:     LedState *s = opaque;
                     54:     uint32_t val;
                     55: 
1.1.1.2   root       56:     switch (addr) {
1.1       root       57:         case 0:
                     58:             val = s->segments;
                     59:             break;
                     60:         default:
1.1.1.5 ! root       61:             BADF("invalid read at [" TARGET_FMT_plx "]\n", addr);
1.1       root       62:             val = 0;
                     63:     }
                     64: 
1.1.1.5 ! root       65:     DPRINTF("read addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
        !            66: 
1.1       root       67:     return val;
                     68: }
                     69: 
                     70: static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
                     71: {
                     72:     uint32_t v;
                     73: #ifdef TARGET_WORDS_BIGENDIAN
                     74:     v = led_readb(opaque, addr) << 8;
                     75:     v |= led_readb(opaque, addr + 1);
                     76: #else
                     77:     v = led_readb(opaque, addr);
                     78:     v |= led_readb(opaque, addr + 1) << 8;
                     79: #endif
                     80:     return v;
                     81: }
                     82: 
                     83: static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
                     84: {
                     85:     uint32_t v;
                     86: #ifdef TARGET_WORDS_BIGENDIAN
                     87:     v = led_readb(opaque, addr) << 24;
                     88:     v |= led_readb(opaque, addr + 1) << 16;
                     89:     v |= led_readb(opaque, addr + 2) << 8;
                     90:     v |= led_readb(opaque, addr + 3);
                     91: #else
                     92:     v = led_readb(opaque, addr);
                     93:     v |= led_readb(opaque, addr + 1) << 8;
                     94:     v |= led_readb(opaque, addr + 2) << 16;
                     95:     v |= led_readb(opaque, addr + 3) << 24;
                     96: #endif
                     97:     return v;
                     98: }
                     99: 
                    100: static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    101: {
                    102:     LedState *s = opaque;
                    103: 
1.1.1.5 ! root      104:     DPRINTF("write addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
        !           105: 
1.1.1.2   root      106:     switch (addr) {
1.1       root      107:         case 0:
                    108:             s->segments = val;
                    109:             s->state |= REDRAW_SEGMENTS;
                    110:             break;
                    111:         default:
1.1.1.5 ! root      112:             BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr);
1.1       root      113:             break;
                    114:     }
                    115: }
                    116: 
                    117: static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
                    118: {
                    119: #ifdef TARGET_WORDS_BIGENDIAN
                    120:     led_writeb(opaque, addr, (val >> 8) & 0xff);
                    121:     led_writeb(opaque, addr + 1, val & 0xff);
                    122: #else
                    123:     led_writeb(opaque, addr, val & 0xff);
                    124:     led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
                    125: #endif
                    126: }
                    127: 
                    128: static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    129: {
                    130: #ifdef TARGET_WORDS_BIGENDIAN
                    131:     led_writeb(opaque, addr, (val >> 24) & 0xff);
                    132:     led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
                    133:     led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
                    134:     led_writeb(opaque, addr + 3, val & 0xff);
                    135: #else
                    136:     led_writeb(opaque, addr, val & 0xff);
                    137:     led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
                    138:     led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
                    139:     led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
                    140: #endif
                    141: }
                    142: 
1.1.1.4   root      143: static CPUReadMemoryFunc * const led_read[3] = {
1.1       root      144:     led_readb,
                    145:     led_readw,
                    146:     led_readl,
                    147: };
                    148: 
1.1.1.4   root      149: static CPUWriteMemoryFunc * const led_write[3] = {
1.1       root      150:     led_writeb,
                    151:     led_writew,
                    152:     led_writel,
                    153: };
                    154: 
                    155: /***********************************************************/
                    156: /* jazz_led display */
                    157: 
                    158: static void draw_horizontal_line(DisplayState *ds, int posy, int posx1, int posx2, uint32_t color)
                    159: {
                    160:     uint8_t *d;
                    161:     int x, bpp;
                    162: 
1.1.1.2   root      163:     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
                    164:     d = ds_get_data(ds) + ds_get_linesize(ds) * posy + bpp * posx1;
1.1       root      165:     switch(bpp) {
                    166:         case 1:
                    167:             for (x = posx1; x <= posx2; x++) {
                    168:                 *((uint8_t *)d) = color;
                    169:                 d++;
                    170:             }
                    171:             break;
                    172:         case 2:
                    173:             for (x = posx1; x <= posx2; x++) {
                    174:                 *((uint16_t *)d) = color;
                    175:                 d += 2;
                    176:             }
                    177:             break;
                    178:         case 4:
                    179:             for (x = posx1; x <= posx2; x++) {
                    180:                 *((uint32_t *)d) = color;
                    181:                 d += 4;
                    182:             }
                    183:             break;
                    184:     }
                    185: }
                    186: 
                    187: static void draw_vertical_line(DisplayState *ds, int posx, int posy1, int posy2, uint32_t color)
                    188: {
                    189:     uint8_t *d;
                    190:     int y, bpp;
                    191: 
1.1.1.2   root      192:     bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
                    193:     d = ds_get_data(ds) + ds_get_linesize(ds) * posy1 + bpp * posx;
1.1       root      194:     switch(bpp) {
                    195:         case 1:
                    196:             for (y = posy1; y <= posy2; y++) {
                    197:                 *((uint8_t *)d) = color;
1.1.1.2   root      198:                 d += ds_get_linesize(ds);
1.1       root      199:             }
                    200:             break;
                    201:         case 2:
                    202:             for (y = posy1; y <= posy2; y++) {
                    203:                 *((uint16_t *)d) = color;
1.1.1.2   root      204:                 d += ds_get_linesize(ds);
1.1       root      205:             }
                    206:             break;
                    207:         case 4:
                    208:             for (y = posy1; y <= posy2; y++) {
                    209:                 *((uint32_t *)d) = color;
1.1.1.2   root      210:                 d += ds_get_linesize(ds);
1.1       root      211:             }
                    212:             break;
                    213:     }
                    214: }
                    215: 
                    216: static void jazz_led_update_display(void *opaque)
                    217: {
                    218:     LedState *s = opaque;
                    219:     DisplayState *ds = s->ds;
                    220:     uint8_t *d1;
                    221:     uint32_t color_segment, color_led;
                    222:     int y, bpp;
                    223: 
                    224:     if (s->state & REDRAW_BACKGROUND) {
                    225:         /* clear screen */
1.1.1.2   root      226:         bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
                    227:         d1 = ds_get_data(ds);
                    228:         for (y = 0; y < ds_get_height(ds); y++) {
                    229:             memset(d1, 0x00, ds_get_width(ds) * bpp);
                    230:             d1 += ds_get_linesize(ds);
1.1       root      231:         }
                    232:     }
                    233: 
                    234:     if (s->state & REDRAW_SEGMENTS) {
                    235:         /* set colors according to bpp */
1.1.1.2   root      236:         switch (ds_get_bits_per_pixel(ds)) {
1.1       root      237:             case 8:
                    238:                 color_segment = rgb_to_pixel8(0xaa, 0xaa, 0xaa);
                    239:                 color_led = rgb_to_pixel8(0x00, 0xff, 0x00);
                    240:                 break;
                    241:             case 15:
                    242:                 color_segment = rgb_to_pixel15(0xaa, 0xaa, 0xaa);
                    243:                 color_led = rgb_to_pixel15(0x00, 0xff, 0x00);
                    244:                 break;
                    245:             case 16:
                    246:                 color_segment = rgb_to_pixel16(0xaa, 0xaa, 0xaa);
                    247:                 color_led = rgb_to_pixel16(0x00, 0xff, 0x00);
                    248:             case 24:
                    249:                 color_segment = rgb_to_pixel24(0xaa, 0xaa, 0xaa);
                    250:                 color_led = rgb_to_pixel24(0x00, 0xff, 0x00);
                    251:                 break;
                    252:             case 32:
                    253:                 color_segment = rgb_to_pixel32(0xaa, 0xaa, 0xaa);
                    254:                 color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
                    255:                 break;
                    256:             default:
                    257:                 return;
                    258:         }
                    259: 
                    260:         /* display segments */
                    261:         draw_horizontal_line(ds, 40, 10, 40, (s->segments & 0x02) ? color_segment : 0);
                    262:         draw_vertical_line(ds, 10, 10, 40, (s->segments & 0x04) ? color_segment : 0);
                    263:         draw_vertical_line(ds, 10, 40, 70, (s->segments & 0x08) ? color_segment : 0);
                    264:         draw_horizontal_line(ds, 70, 10, 40, (s->segments & 0x10) ? color_segment : 0);
                    265:         draw_vertical_line(ds, 40, 40, 70, (s->segments & 0x20) ? color_segment : 0);
                    266:         draw_vertical_line(ds, 40, 10, 40, (s->segments & 0x40) ? color_segment : 0);
                    267:         draw_horizontal_line(ds, 10, 10, 40, (s->segments & 0x80) ? color_segment : 0);
                    268: 
                    269:         /* display led */
                    270:         if (!(s->segments & 0x01))
                    271:             color_led = 0; /* black */
                    272:         draw_horizontal_line(ds, 68, 50, 50, color_led);
                    273:         draw_horizontal_line(ds, 69, 49, 51, color_led);
                    274:         draw_horizontal_line(ds, 70, 48, 52, color_led);
                    275:         draw_horizontal_line(ds, 71, 49, 51, color_led);
                    276:         draw_horizontal_line(ds, 72, 50, 50, color_led);
                    277:     }
                    278: 
                    279:     s->state = REDRAW_NONE;
1.1.1.2   root      280:     dpy_update(ds, 0, 0, ds_get_width(ds), ds_get_height(ds));
1.1       root      281: }
                    282: 
                    283: static void jazz_led_invalidate_display(void *opaque)
                    284: {
                    285:     LedState *s = opaque;
                    286:     s->state |= REDRAW_SEGMENTS | REDRAW_BACKGROUND;
                    287: }
                    288: 
                    289: static void jazz_led_screen_dump(void *opaque, const char *filename)
                    290: {
                    291:     printf("jazz_led_screen_dump() not implemented\n");
                    292: }
                    293: 
1.1.1.2   root      294: static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
                    295: {
                    296:     LedState *s = opaque;
                    297:     char buf[2];
                    298: 
                    299:     dpy_cursor(s->ds, -1, -1);
                    300:     qemu_console_resize(s->ds, 2, 1);
                    301: 
                    302:     /* TODO: draw the segments */
                    303:     snprintf(buf, 2, "%02hhx\n", s->segments);
                    304:     console_write_ch(chardata++, 0x00200100 | buf[0]);
                    305:     console_write_ch(chardata++, 0x00200100 | buf[1]);
                    306: 
                    307:     dpy_update(s->ds, 0, 0, 2, 1);
                    308: }
                    309: 
                    310: void jazz_led_init(target_phys_addr_t base)
1.1       root      311: {
                    312:     LedState *s;
                    313:     int io;
                    314: 
                    315:     s = qemu_mallocz(sizeof(LedState));
                    316: 
                    317:     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
                    318: 
1.1.1.5 ! root      319:     io = cpu_register_io_memory(led_read, led_write, s,
        !           320:                                 DEVICE_NATIVE_ENDIAN);
1.1.1.2   root      321:     cpu_register_physical_memory(base, 1, io);
1.1       root      322: 
1.1.1.2   root      323:     s->ds = graphic_console_init(jazz_led_update_display,
                    324:                                  jazz_led_invalidate_display,
                    325:                                  jazz_led_screen_dump,
                    326:                                  jazz_led_text_update, s);
                    327:     qemu_console_resize(s->ds, 60, 80);
1.1       root      328: }

unix.superglobalmegacorp.com