Annotation of qemu/hw/milkymist-vgafb.c, revision 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.