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

1.1       root        1: 
                      2: /*
                      3:  *  QEMU model of the Milkymist VGA framebuffer.
                      4:  *
1.1.1.3 ! root        5:  *  Copyright (c) 2010-2012 Michael Walle <[email protected]>
1.1       root        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,
1.1.1.3 ! root       57:     R_DDC,
1.1       root       58:     R_SOURCE_CLOCK,
                     59:     R_MAX
                     60: };
                     61: 
                     62: enum {
                     63:     CTRL_RESET = (1<<0),
                     64: };
                     65: 
                     66: struct MilkymistVgafbState {
                     67:     SysBusDevice busdev;
1.1.1.2   root       68:     MemoryRegion regs_region;
1.1       root       69:     DisplayState *ds;
                     70: 
                     71:     int invalidate;
                     72:     uint32_t fb_offset;
                     73:     uint32_t fb_mask;
                     74: 
                     75:     uint32_t regs[R_MAX];
                     76: };
                     77: typedef struct MilkymistVgafbState MilkymistVgafbState;
                     78: 
                     79: static int vgafb_enabled(MilkymistVgafbState *s)
                     80: {
                     81:     return !(s->regs[R_CTRL] & CTRL_RESET);
                     82: }
                     83: 
                     84: static void vgafb_update_display(void *opaque)
                     85: {
                     86:     MilkymistVgafbState *s = opaque;
                     87:     int first = 0;
                     88:     int last = 0;
                     89:     drawfn fn;
                     90: 
                     91:     if (!vgafb_enabled(s)) {
                     92:         return;
                     93:     }
                     94: 
                     95:     int dest_width = s->regs[R_HRES];
                     96: 
                     97:     switch (ds_get_bits_per_pixel(s->ds)) {
                     98:     case 0:
                     99:         return;
                    100:     case 8:
                    101:         fn = draw_line_8;
                    102:         break;
                    103:     case 15:
                    104:         fn = draw_line_15;
                    105:         dest_width *= 2;
                    106:         break;
                    107:     case 16:
                    108:         fn = draw_line_16;
                    109:         dest_width *= 2;
                    110:         break;
                    111:     case 24:
                    112:         fn = draw_line_24;
                    113:         dest_width *= 3;
                    114:         break;
                    115:     case 32:
                    116:         fn = draw_line_32;
                    117:         dest_width *= 4;
                    118:         break;
                    119:     default:
                    120:         hw_error("milkymist_vgafb: bad color depth\n");
                    121:         break;
                    122:     }
                    123: 
1.1.1.3 ! root      124:     framebuffer_update_display(s->ds, sysbus_address_space(&s->busdev),
1.1       root      125:                                s->regs[R_BASEADDRESS] + s->fb_offset,
                    126:                                s->regs[R_HRES],
                    127:                                s->regs[R_VRES],
                    128:                                s->regs[R_HRES] * 2,
                    129:                                dest_width,
                    130:                                0,
                    131:                                s->invalidate,
                    132:                                fn,
                    133:                                NULL,
                    134:                                &first, &last);
                    135: 
                    136:     if (first >= 0) {
                    137:         dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
                    138:     }
                    139:     s->invalidate = 0;
                    140: }
                    141: 
                    142: static void vgafb_invalidate_display(void *opaque)
                    143: {
                    144:     MilkymistVgafbState *s = opaque;
                    145:     s->invalidate = 1;
                    146: }
                    147: 
                    148: static void vgafb_resize(MilkymistVgafbState *s)
                    149: {
                    150:     if (!vgafb_enabled(s)) {
                    151:         return;
                    152:     }
                    153: 
                    154:     qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
                    155:     s->invalidate = 1;
                    156: }
                    157: 
1.1.1.2   root      158: static uint64_t vgafb_read(void *opaque, target_phys_addr_t addr,
                    159:                            unsigned size)
1.1       root      160: {
                    161:     MilkymistVgafbState *s = opaque;
                    162:     uint32_t r = 0;
                    163: 
                    164:     addr >>= 2;
                    165:     switch (addr) {
                    166:     case R_CTRL:
                    167:     case R_HRES:
                    168:     case R_HSYNC_START:
                    169:     case R_HSYNC_END:
                    170:     case R_HSCAN:
                    171:     case R_VRES:
                    172:     case R_VSYNC_START:
                    173:     case R_VSYNC_END:
                    174:     case R_VSCAN:
                    175:     case R_BASEADDRESS:
                    176:     case R_BURST_COUNT:
1.1.1.3 ! root      177:     case R_DDC:
1.1       root      178:     case R_SOURCE_CLOCK:
                    179:         r = s->regs[addr];
                    180:     break;
                    181:     case R_BASEADDRESS_ACT:
                    182:         r = s->regs[R_BASEADDRESS];
                    183:     break;
                    184: 
                    185:     default:
                    186:         error_report("milkymist_vgafb: read access to unknown register 0x"
                    187:                 TARGET_FMT_plx, addr << 2);
                    188:         break;
                    189:     }
                    190: 
                    191:     trace_milkymist_vgafb_memory_read(addr << 2, r);
                    192: 
                    193:     return r;
                    194: }
                    195: 
1.1.1.2   root      196: static void vgafb_write(void *opaque, target_phys_addr_t addr, uint64_t value,
                    197:                         unsigned size)
1.1       root      198: {
                    199:     MilkymistVgafbState *s = opaque;
                    200: 
                    201:     trace_milkymist_vgafb_memory_write(addr, value);
                    202: 
                    203:     addr >>= 2;
                    204:     switch (addr) {
                    205:     case R_CTRL:
                    206:         s->regs[addr] = value;
                    207:         vgafb_resize(s);
                    208:         break;
                    209:     case R_HSYNC_START:
                    210:     case R_HSYNC_END:
                    211:     case R_HSCAN:
                    212:     case R_VSYNC_START:
                    213:     case R_VSYNC_END:
                    214:     case R_VSCAN:
                    215:     case R_BURST_COUNT:
1.1.1.3 ! root      216:     case R_DDC:
1.1       root      217:     case R_SOURCE_CLOCK:
                    218:         s->regs[addr] = value;
                    219:         break;
                    220:     case R_BASEADDRESS:
                    221:         if (value & 0x1f) {
                    222:             error_report("milkymist_vgafb: framebuffer base address have to "
                    223:                      "be 32 byte aligned");
                    224:             break;
                    225:         }
                    226:         s->regs[addr] = value & s->fb_mask;
                    227:         s->invalidate = 1;
                    228:         break;
                    229:     case R_HRES:
                    230:     case R_VRES:
                    231:         s->regs[addr] = value;
                    232:         vgafb_resize(s);
                    233:         break;
                    234:     case R_BASEADDRESS_ACT:
                    235:         error_report("milkymist_vgafb: write to read-only register 0x"
                    236:                 TARGET_FMT_plx, addr << 2);
                    237:         break;
                    238: 
                    239:     default:
                    240:         error_report("milkymist_vgafb: write access to unknown register 0x"
                    241:                 TARGET_FMT_plx, addr << 2);
                    242:         break;
                    243:     }
                    244: }
                    245: 
1.1.1.2   root      246: static const MemoryRegionOps vgafb_mmio_ops = {
                    247:     .read = vgafb_read,
                    248:     .write = vgafb_write,
                    249:     .valid = {
                    250:         .min_access_size = 4,
                    251:         .max_access_size = 4,
                    252:     },
                    253:     .endianness = DEVICE_NATIVE_ENDIAN,
1.1       root      254: };
                    255: 
                    256: static void milkymist_vgafb_reset(DeviceState *d)
                    257: {
                    258:     MilkymistVgafbState *s = container_of(d, MilkymistVgafbState, busdev.qdev);
                    259:     int i;
                    260: 
                    261:     for (i = 0; i < R_MAX; i++) {
                    262:         s->regs[i] = 0;
                    263:     }
                    264: 
                    265:     /* defaults */
                    266:     s->regs[R_CTRL] = CTRL_RESET;
                    267:     s->regs[R_HRES] = 640;
                    268:     s->regs[R_VRES] = 480;
                    269:     s->regs[R_BASEADDRESS] = 0;
                    270: }
                    271: 
                    272: static int milkymist_vgafb_init(SysBusDevice *dev)
                    273: {
                    274:     MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
                    275: 
1.1.1.2   root      276:     memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s,
                    277:             "milkymist-vgafb", R_MAX * 4);
1.1.1.3 ! root      278:     sysbus_init_mmio(dev, &s->regs_region);
1.1       root      279: 
                    280:     s->ds = graphic_console_init(vgafb_update_display,
                    281:                                  vgafb_invalidate_display,
                    282:                                  NULL, NULL, s);
                    283: 
                    284:     return 0;
                    285: }
                    286: 
                    287: static int vgafb_post_load(void *opaque, int version_id)
                    288: {
                    289:     vgafb_invalidate_display(opaque);
                    290:     return 0;
                    291: }
                    292: 
                    293: static const VMStateDescription vmstate_milkymist_vgafb = {
                    294:     .name = "milkymist-vgafb",
                    295:     .version_id = 1,
                    296:     .minimum_version_id = 1,
                    297:     .minimum_version_id_old = 1,
                    298:     .post_load = vgafb_post_load,
                    299:     .fields      = (VMStateField[]) {
                    300:         VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX),
                    301:         VMSTATE_END_OF_LIST()
                    302:     }
                    303: };
                    304: 
1.1.1.3 ! root      305: static Property milkymist_vgafb_properties[] = {
        !           306:     DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
        !           307:     DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
        !           308:     DEFINE_PROP_END_OF_LIST(),
        !           309: };
        !           310: 
        !           311: static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
        !           312: {
        !           313:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           314:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
        !           315: 
        !           316:     k->init = milkymist_vgafb_init;
        !           317:     dc->reset = milkymist_vgafb_reset;
        !           318:     dc->vmsd = &vmstate_milkymist_vgafb;
        !           319:     dc->props = milkymist_vgafb_properties;
        !           320: }
        !           321: 
        !           322: static TypeInfo milkymist_vgafb_info = {
        !           323:     .name          = "milkymist-vgafb",
        !           324:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           325:     .instance_size = sizeof(MilkymistVgafbState),
        !           326:     .class_init    = milkymist_vgafb_class_init,
1.1       root      327: };
                    328: 
1.1.1.3 ! root      329: static void milkymist_vgafb_register_types(void)
1.1       root      330: {
1.1.1.3 ! root      331:     type_register_static(&milkymist_vgafb_info);
1.1       root      332: }
                    333: 
1.1.1.3 ! root      334: type_init(milkymist_vgafb_register_types)

unix.superglobalmegacorp.com

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