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

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;
                     67:     DisplayState *ds;
                     68: 
                     69:     int invalidate;
                     70:     uint32_t fb_offset;
                     71:     uint32_t fb_mask;
                     72: 
                     73:     uint32_t regs[R_MAX];
                     74: };
                     75: typedef struct MilkymistVgafbState MilkymistVgafbState;
                     76: 
                     77: static int vgafb_enabled(MilkymistVgafbState *s)
                     78: {
                     79:     return !(s->regs[R_CTRL] & CTRL_RESET);
                     80: }
                     81: 
                     82: static void vgafb_update_display(void *opaque)
                     83: {
                     84:     MilkymistVgafbState *s = opaque;
                     85:     int first = 0;
                     86:     int last = 0;
                     87:     drawfn fn;
                     88: 
                     89:     if (!vgafb_enabled(s)) {
                     90:         return;
                     91:     }
                     92: 
                     93:     int dest_width = s->regs[R_HRES];
                     94: 
                     95:     switch (ds_get_bits_per_pixel(s->ds)) {
                     96:     case 0:
                     97:         return;
                     98:     case 8:
                     99:         fn = draw_line_8;
                    100:         break;
                    101:     case 15:
                    102:         fn = draw_line_15;
                    103:         dest_width *= 2;
                    104:         break;
                    105:     case 16:
                    106:         fn = draw_line_16;
                    107:         dest_width *= 2;
                    108:         break;
                    109:     case 24:
                    110:         fn = draw_line_24;
                    111:         dest_width *= 3;
                    112:         break;
                    113:     case 32:
                    114:         fn = draw_line_32;
                    115:         dest_width *= 4;
                    116:         break;
                    117:     default:
                    118:         hw_error("milkymist_vgafb: bad color depth\n");
                    119:         break;
                    120:     }
                    121: 
                    122:     framebuffer_update_display(s->ds,
                    123:                                s->regs[R_BASEADDRESS] + s->fb_offset,
                    124:                                s->regs[R_HRES],
                    125:                                s->regs[R_VRES],
                    126:                                s->regs[R_HRES] * 2,
                    127:                                dest_width,
                    128:                                0,
                    129:                                s->invalidate,
                    130:                                fn,
                    131:                                NULL,
                    132:                                &first, &last);
                    133: 
                    134:     if (first >= 0) {
                    135:         dpy_update(s->ds, 0, first, s->regs[R_HRES], last - first + 1);
                    136:     }
                    137:     s->invalidate = 0;
                    138: }
                    139: 
                    140: static void vgafb_invalidate_display(void *opaque)
                    141: {
                    142:     MilkymistVgafbState *s = opaque;
                    143:     s->invalidate = 1;
                    144: }
                    145: 
                    146: static void vgafb_resize(MilkymistVgafbState *s)
                    147: {
                    148:     if (!vgafb_enabled(s)) {
                    149:         return;
                    150:     }
                    151: 
                    152:     qemu_console_resize(s->ds, s->regs[R_HRES], s->regs[R_VRES]);
                    153:     s->invalidate = 1;
                    154: }
                    155: 
                    156: static uint32_t vgafb_read(void *opaque, target_phys_addr_t addr)
                    157: {
                    158:     MilkymistVgafbState *s = opaque;
                    159:     uint32_t r = 0;
                    160: 
                    161:     addr >>= 2;
                    162:     switch (addr) {
                    163:     case R_CTRL:
                    164:     case R_HRES:
                    165:     case R_HSYNC_START:
                    166:     case R_HSYNC_END:
                    167:     case R_HSCAN:
                    168:     case R_VRES:
                    169:     case R_VSYNC_START:
                    170:     case R_VSYNC_END:
                    171:     case R_VSCAN:
                    172:     case R_BASEADDRESS:
                    173:     case R_BURST_COUNT:
                    174:     case R_SOURCE_CLOCK:
                    175:         r = s->regs[addr];
                    176:     break;
                    177:     case R_BASEADDRESS_ACT:
                    178:         r = s->regs[R_BASEADDRESS];
                    179:     break;
                    180: 
                    181:     default:
                    182:         error_report("milkymist_vgafb: read access to unknown register 0x"
                    183:                 TARGET_FMT_plx, addr << 2);
                    184:         break;
                    185:     }
                    186: 
                    187:     trace_milkymist_vgafb_memory_read(addr << 2, r);
                    188: 
                    189:     return r;
                    190: }
                    191: 
                    192: static void
                    193: vgafb_write(void *opaque, target_phys_addr_t addr, uint32_t value)
                    194: {
                    195:     MilkymistVgafbState *s = opaque;
                    196: 
                    197:     trace_milkymist_vgafb_memory_write(addr, value);
                    198: 
                    199:     addr >>= 2;
                    200:     switch (addr) {
                    201:     case R_CTRL:
                    202:         s->regs[addr] = value;
                    203:         vgafb_resize(s);
                    204:         break;
                    205:     case R_HSYNC_START:
                    206:     case R_HSYNC_END:
                    207:     case R_HSCAN:
                    208:     case R_VSYNC_START:
                    209:     case R_VSYNC_END:
                    210:     case R_VSCAN:
                    211:     case R_BURST_COUNT:
                    212:     case R_SOURCE_CLOCK:
                    213:         s->regs[addr] = value;
                    214:         break;
                    215:     case R_BASEADDRESS:
                    216:         if (value & 0x1f) {
                    217:             error_report("milkymist_vgafb: framebuffer base address have to "
                    218:                      "be 32 byte aligned");
                    219:             break;
                    220:         }
                    221:         s->regs[addr] = value & s->fb_mask;
                    222:         s->invalidate = 1;
                    223:         break;
                    224:     case R_HRES:
                    225:     case R_VRES:
                    226:         s->regs[addr] = value;
                    227:         vgafb_resize(s);
                    228:         break;
                    229:     case R_BASEADDRESS_ACT:
                    230:         error_report("milkymist_vgafb: write to read-only register 0x"
                    231:                 TARGET_FMT_plx, addr << 2);
                    232:         break;
                    233: 
                    234:     default:
                    235:         error_report("milkymist_vgafb: write access to unknown register 0x"
                    236:                 TARGET_FMT_plx, addr << 2);
                    237:         break;
                    238:     }
                    239: }
                    240: 
                    241: static CPUReadMemoryFunc * const vgafb_read_fn[] = {
                    242:    NULL,
                    243:    NULL,
                    244:    &vgafb_read
                    245: };
                    246: 
                    247: static CPUWriteMemoryFunc * const vgafb_write_fn[] = {
                    248:    NULL,
                    249:    NULL,
                    250:    &vgafb_write
                    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:     int vgafb_regs;
                    273: 
                    274:     vgafb_regs = cpu_register_io_memory(vgafb_read_fn, vgafb_write_fn, s,
                    275:             DEVICE_NATIVE_ENDIAN);
                    276:     sysbus_init_mmio(dev, R_MAX * 4, vgafb_regs);
                    277: 
                    278:     s->ds = graphic_console_init(vgafb_update_display,
                    279:                                  vgafb_invalidate_display,
                    280:                                  NULL, NULL, s);
                    281: 
                    282:     return 0;
                    283: }
                    284: 
                    285: static int vgafb_post_load(void *opaque, int version_id)
                    286: {
                    287:     vgafb_invalidate_display(opaque);
                    288:     return 0;
                    289: }
                    290: 
                    291: static const VMStateDescription vmstate_milkymist_vgafb = {
                    292:     .name = "milkymist-vgafb",
                    293:     .version_id = 1,
                    294:     .minimum_version_id = 1,
                    295:     .minimum_version_id_old = 1,
                    296:     .post_load = vgafb_post_load,
                    297:     .fields      = (VMStateField[]) {
                    298:         VMSTATE_UINT32_ARRAY(regs, MilkymistVgafbState, R_MAX),
                    299:         VMSTATE_END_OF_LIST()
                    300:     }
                    301: };
                    302: 
                    303: static SysBusDeviceInfo milkymist_vgafb_info = {
                    304:     .init = milkymist_vgafb_init,
                    305:     .qdev.name  = "milkymist-vgafb",
                    306:     .qdev.size  = sizeof(MilkymistVgafbState),
                    307:     .qdev.vmsd  = &vmstate_milkymist_vgafb,
                    308:     .qdev.reset = milkymist_vgafb_reset,
                    309:     .qdev.props = (Property[]) {
                    310:         DEFINE_PROP_UINT32("fb_offset", MilkymistVgafbState, fb_offset, 0x0),
                    311:         DEFINE_PROP_UINT32("fb_mask", MilkymistVgafbState, fb_mask, 0xffffffff),
                    312:         DEFINE_PROP_END_OF_LIST(),
                    313:     }
                    314: };
                    315: 
                    316: static void milkymist_vgafb_register(void)
                    317: {
                    318:     sysbus_register_withprop(&milkymist_vgafb_info);
                    319: }
                    320: 
                    321: 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.