Annotation of qemu/hw/milkymist-vgafb.c, revision 1.1.1.2

1.1       root        1: 
                      2: /*
                      3:  *  QEMU model of the Milkymist VGA framebuffer.
                      4:  *
                      5:  *  Copyright (c) 2010 Michael Walle <[email protected]>
                      6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * Lesser General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
                     18:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
                     19:  *
                     20:  *
                     21:  * Specification available at:
                     22:  *   http://www.milkymist.org/socdoc/vgafb.pdf
                     23:  */
                     24: 
                     25: #include "hw.h"
                     26: #include "sysbus.h"
                     27: #include "trace.h"
                     28: #include "console.h"
                     29: #include "framebuffer.h"
                     30: #include "pixel_ops.h"
                     31: #include "qemu-error.h"
                     32: 
                     33: #define BITS 8
                     34: #include "milkymist-vgafb_template.h"
                     35: #define BITS 15
                     36: #include "milkymist-vgafb_template.h"
                     37: #define BITS 16
                     38: #include "milkymist-vgafb_template.h"
                     39: #define BITS 24
                     40: #include "milkymist-vgafb_template.h"
                     41: #define BITS 32
                     42: #include "milkymist-vgafb_template.h"
                     43: 
                     44: enum {
                     45:     R_CTRL = 0,
                     46:     R_HRES,
                     47:     R_HSYNC_START,
                     48:     R_HSYNC_END,
                     49:     R_HSCAN,
                     50:     R_VRES,
                     51:     R_VSYNC_START,
                     52:     R_VSYNC_END,
                     53:     R_VSCAN,
                     54:     R_BASEADDRESS,
                     55:     R_BASEADDRESS_ACT,
                     56:     R_BURST_COUNT,
                     57:     R_SOURCE_CLOCK,
                     58:     R_MAX
                     59: };
                     60: 
                     61: enum {
                     62:     CTRL_RESET = (1<<0),
                     63: };
                     64: 
                     65: struct MilkymistVgafbState {
                     66:     SysBusDevice busdev;
1.1.1.2 ! root       67:     MemoryRegion regs_region;
1.1       root       68:     DisplayState *ds;
                     69: 
                     70:     int invalidate;
                     71:     uint32_t fb_offset;
                     72:     uint32_t fb_mask;
                     73: 
                     74:     uint32_t regs[R_MAX];
                     75: };
                     76: typedef struct MilkymistVgafbState MilkymistVgafbState;
                     77: 
                     78: static int vgafb_enabled(MilkymistVgafbState *s)
                     79: {
                     80:     return !(s->regs[R_CTRL] & CTRL_RESET);
                     81: }
                     82: 
                     83: static void vgafb_update_display(void *opaque)
                     84: {
                     85:     MilkymistVgafbState *s = opaque;
                     86:     int first = 0;
                     87:     int last = 0;
                     88:     drawfn fn;
                     89: 
                     90:     if (!vgafb_enabled(s)) {
                     91:         return;
                     92:     }
                     93: 
                     94:     int dest_width = s->regs[R_HRES];
                     95: 
                     96:     switch (ds_get_bits_per_pixel(s->ds)) {
                     97:     case 0:
                     98:         return;
                     99:     case 8:
                    100:         fn = draw_line_8;
                    101:         break;
                    102:     case 15:
                    103:         fn = draw_line_15;
                    104:         dest_width *= 2;
                    105:         break;
                    106:     case 16:
                    107:         fn = draw_line_16;
                    108:         dest_width *= 2;
                    109:         break;
                    110:     case 24:
                    111:         fn = draw_line_24;
                    112:         dest_width *= 3;
                    113:         break;
                    114:     case 32:
                    115:         fn = draw_line_32;
                    116:         dest_width *= 4;
                    117:         break;
                    118:     default:
                    119:         hw_error("milkymist_vgafb: bad color depth\n");
                    120:         break;
                    121:     }
                    122: 
                    123:     framebuffer_update_display(s->ds,
                    124:                                s->regs[R_BASEADDRESS] + s->fb_offset,
                    125:                                s->regs[R_HRES],
                    126:                                s->regs[R_VRES],
                    127:                                s->regs[R_HRES] * 2,
                    128:                                dest_width,
                    129:                                0,
                    130:                                s->invalidate,
                    131:                                fn,
                    132:                                NULL,
                    133:                                &first, &last);
                    134: 
                    135:     if (first >= 0) {
                    136:         dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
                    137:     }
                    138:     s->invalidate = 0;
                    139: }
                    140: 
                    141: static void vgafb_invalidate_display(void *opaque)
                    142: {
                    143:     MilkymistVgafbState *s = opaque;
                    144:     s->invalidate = 1;
                    145: }
                    146: 
                    147: static void vgafb_resize(MilkymistVgafbState *s)
                    148: {
                    149:     if (!vgafb_enabled(s)) {
                    150:         return;
                    151:     }
                    152: 
                    153:     qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
                    154:     s->invalidate = 1;
                    155: }
                    156: 
1.1.1.2 ! root      157: static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr,
        !           158:                            unsigned size)
1.1       root      159: {
                    160:     MilkymistVgafbState *s = opaque;
                    161:     uint32_t r = 0;
                    162: 
                    163:     addr >>= 2;
                    164:     switch (addr) {
                    165:     case R_CTRL:
                    166:     case R_HRES:
                    167:     case R_HSYNC_START:
                    168:     case R_HSYNC_END:
                    169:     case R_HSCAN:
                    170:     case R_VRES:
                    171:     case R_VSYNC_START:
                    172:     case R_VSYNC_END:
                    173:     case R_VSCAN:
                    174:     case R_BASEADDRESS:
                    175:     case R_BURST_COUNT:
                    176:     case R_SOURCE_CLOCK:
                    177:         r = s->regs[addr];
                    178:     break;
                    179:     case R_BASEADDRESS_ACT:
                    180:         r = s->regs[R_BASEADDRESS];
                    181:     break;
                    182: 
                    183:     default:
                    184:         error_report("milkymist_vgafb: read access to unknown register 0x"
                    185:                 TARGET_FMT_plx, addr << 2);
                    186:         break;
                    187:     }
                    188: 
                    189:     trace_milkymist_vgafb_memory_read(addr << 2, r);
                    190: 
                    191:     return r;
                    192: }
                    193: 
1.1.1.2 ! root      194: static void vgafb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
        !           195:                         unsigned size)
1.1       root      196: {
                    197:     MilkymistVgafbState *s = opaque;
                    198: 
                    199:     trace_milkymist_vgafb_memory_write(addr, value);
                    200: 
                    201:     addr >>= 2;
                    202:     switch (addr) {
                    203:     case R_CTRL:
                    204:         s->regs[addr] = value;
                    205:         vgafb_resize(s);
                    206:         break;
                    207:     case R_HSYNC_START:
                    208:     case R_HSYNC_END:
                    209:     case R_HSCAN:
                    210:     case R_VSYNC_START:
                    211:     case R_VSYNC_END:
                    212:     case R_VSCAN:
                    213:     case R_BURST_COUNT:
                    214:     case R_SOURCE_CLOCK:
                    215:         s->regs[addr] = value;
                    216:         break;
                    217:     case R_BASEADDRESS:
                    218:         if (value & 0x1f) {
                    219:             error_report("milkymist_vgafb: framebuffer base address have to "
                    220:                      "be 32 byte aligned");
                    221:             break;
                    222:         }
                    223:         s->regs[addr] = value & s->fb_mask;
                    224:         s->invalidate = 1;
                    225:         break;
                    226:     case R_HRES:
                    227:     case R_VRES:
                    228:         s->regs[addr] = value;
                    229:         vgafb_resize(s);
                    230:         break;
                    231:     case R_BASEADDRESS_ACT:
                    232:         error_report("milkymist_vgafb: write to read-only register 0x"
                    233:                 TARGET_FMT_plx, addr << 2);
                    234:         break;
                    235: 
                    236:     default:
                    237:         error_report("milkymist_vgafb: write access to unknown register 0x"
                    238:                 TARGET_FMT_plx, addr << 2);
                    239:         break;
                    240:     }
                    241: }
                    242: 
1.1.1.2 ! root      243: static const MemoryRegionOps vgafb_mmio_ops = {
        !           244:     .read = vgafb_read,
        !           245:     .write = vgafb_write,
        !           246:     .valid = {
        !           247:         .min_access_size = 4,
        !           248:         .max_access_size = 4,
        !           249:     },
        !           250:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      251: };
                    252: 
                    253: static void milkymist_vgafb_reset(DeviceState *d)
                    254: {
                    255:     MilkymistVgafbState *s = container_of(d, MilkymistVgafbState, busdev.qdev);
                    256:     int i;
                    257: 
                    258:     for (i = 0; i < R_MAX; i++) {
                    259:         s->regs[i] = 0;
                    260:     }
                    261: 
                    262:     /* defaults */
                    263:     s->regs[R_CTRL] = CTRL_RESET;
                    264:     s->regs[R_HRES] = 640;
                    265:     s->regs[R_VRES] = 480;
                    266:     s->regs[R_BASEADDRESS] = 0;
                    267: }
                    268: 
                    269: static int milkymist_vgafb_init(SysBusDevice *dev)
                    270: {
                    271:     MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
                    272: 
1.1.1.2 ! root      273:     memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
        !           274:             "milkymist-vgafb", R_MAX * 4);
        !           275:     sysbus_init_mmio_region(dev, &s->regs_region);
1.1       root      276: 
                    277:     s->ds = graphic_console_init(vgafb_update_display,
                    278:                                  vgafb_invalidate_display,
                    279:                                  NULL, NULL, s);
                    280: 
                    281:     return 0;
                    282: }
                    283: 
                    284: static int vgafb_post_load(void *opaque, int version_id)
                    285: {
                    286:     vgafb_invalidate_display(opaque);
                    287:     return 0;
                    288: }
                    289: 
                    290: static const VMStateDescription vmstate_milkymist_vgafb = {
                    291:     .name = "milkymist-vgafb",
                    292:     .version_id = 1,
                    293:     .minimum_version_id = 1,
                    294:     .minimum_version_id_old = 1,
                    295:     .post_load = vgafb_post_load,
                    296:     .fields      = (VMStateField[]) {
                    297:         VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX),
                    298:         VMSTATE_END_OF_LIST()
                    299:     }
                    300: };
                    301: 
                    302: static SysBusDeviceInfo milkymist_vgafb_info = {
                    303:     .init = milkymist_vgafb_init,
                    304:     .qdev.name  = "milkymist-vgafb",
                    305:     .qdev.size  = sizeof(MilkymistVgafbState),
                    306:     .qdev.vmsd  = &vmstate_milkymist_vgafb,
                    307:     .qdev.reset = milkymist_vgafb_reset,
                    308:     .qdev.props = (Property[]) {
                    309:         DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
                    310:         DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
                    311:         DEFINE_PROP_END_OF_LIST(),
                    312:     }
                    313: };
                    314: 
                    315: static void milkymist_vgafb_register(void)
                    316: {
                    317:     sysbus_register_withprop(&milkymist_vgafb_info);
                    318: }
                    319: 
                    320: device_init(milkymist_vgafb_register)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.