Annotation of qemu/hw/tcx.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  * QEMU TCX Frame buffer
1.1.1.4   root        3:  *
1.1       root        4:  * Copyright (c) 2003-2005 Fabrice Bellard
1.1.1.4   root        5:  *
1.1       root        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:  */
1.1.1.6 ! root       24: 
1.1.1.4   root       25: #include "sun4m.h"
                     26: #include "console.h"
                     27: #include "pixel_ops.h"
1.1.1.6 ! root       28: #include "sysbus.h"
        !            29: #include "qdev-addr.h"
1.1       root       30: 
                     31: #define MAXX 1024
                     32: #define MAXY 768
                     33: #define TCX_DAC_NREGS 16
1.1.1.4   root       34: #define TCX_THC_NREGS_8  0x081c
                     35: #define TCX_THC_NREGS_24 0x1000
                     36: #define TCX_TEC_NREGS    0x1000
1.1       root       37: 
                     38: typedef struct TCXState {
1.1.1.6 ! root       39:     SysBusDevice busdev;
1.1.1.4   root       40:     target_phys_addr_t addr;
1.1       root       41:     DisplayState *ds;
                     42:     uint8_t *vram;
1.1.1.4   root       43:     uint32_t *vram24, *cplane;
                     44:     ram_addr_t vram_offset, vram24_offset, cplane_offset;
1.1.1.6 ! root       45:     uint32_t vram_size;
1.1.1.4   root       46:     uint16_t width, height, depth;
1.1       root       47:     uint8_t r[256], g[256], b[256];
1.1.1.3   root       48:     uint32_t palette[256];
1.1       root       49:     uint8_t dac_index, dac_state;
                     50: } TCXState;
                     51: 
1.1.1.2   root       52: static void tcx_screen_dump(void *opaque, const char *filename);
1.1.1.4   root       53: static void tcx24_screen_dump(void *opaque, const char *filename);
1.1.1.6 ! root       54: 
        !            55: static void tcx_set_dirty(TCXState *s)
        !            56: {
        !            57:     unsigned int i;
        !            58: 
        !            59:     for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
        !            60:         cpu_physical_memory_set_dirty(s->vram_offset + i);
        !            61:     }
        !            62: }
        !            63: 
        !            64: static void tcx24_set_dirty(TCXState *s)
        !            65: {
        !            66:     unsigned int i;
        !            67: 
        !            68:     for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
        !            69:         cpu_physical_memory_set_dirty(s->vram24_offset + i);
        !            70:         cpu_physical_memory_set_dirty(s->cplane_offset + i);
        !            71:     }
        !            72: }
1.1.1.3   root       73: 
                     74: static void update_palette_entries(TCXState *s, int start, int end)
                     75: {
                     76:     int i;
                     77:     for(i = start; i < end; i++) {
1.1.1.5   root       78:         switch(ds_get_bits_per_pixel(s->ds)) {
1.1.1.3   root       79:         default:
                     80:         case 8:
                     81:             s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
                     82:             break;
                     83:         case 15:
1.1.1.5   root       84:             s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       85:             break;
                     86:         case 16:
1.1.1.5   root       87:             s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       88:             break;
                     89:         case 32:
1.1.1.6 ! root       90:             if (is_surface_bgr(s->ds->surface))
        !            91:                 s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
        !            92:             else
        !            93:                 s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       94:             break;
                     95:         }
                     96:     }
1.1.1.6 ! root       97:     if (s->depth == 24) {
        !            98:         tcx24_set_dirty(s);
        !            99:     } else {
        !           100:         tcx_set_dirty(s);
        !           101:     }
1.1.1.3   root      102: }
                    103: 
1.1.1.4   root      104: static void tcx_draw_line32(TCXState *s1, uint8_t *d,
                    105:                             const uint8_t *s, int width)
1.1       root      106: {
                    107:     int x;
                    108:     uint8_t val;
1.1.1.3   root      109:     uint32_t *p = (uint32_t *)d;
1.1       root      110: 
                    111:     for(x = 0; x < width; x++) {
1.1.1.4   root      112:         val = *s++;
1.1.1.3   root      113:         *p++ = s1->palette[val];
1.1       root      114:     }
                    115: }
                    116: 
1.1.1.4   root      117: static void tcx_draw_line16(TCXState *s1, uint8_t *d,
                    118:                             const uint8_t *s, int width)
1.1       root      119: {
                    120:     int x;
                    121:     uint8_t val;
1.1.1.3   root      122:     uint16_t *p = (uint16_t *)d;
1.1       root      123: 
                    124:     for(x = 0; x < width; x++) {
1.1.1.4   root      125:         val = *s++;
1.1.1.3   root      126:         *p++ = s1->palette[val];
1.1       root      127:     }
                    128: }
                    129: 
1.1.1.4   root      130: static void tcx_draw_line8(TCXState *s1, uint8_t *d,
                    131:                            const uint8_t *s, int width)
1.1       root      132: {
                    133:     int x;
                    134:     uint8_t val;
                    135: 
                    136:     for(x = 0; x < width; x++) {
1.1.1.4   root      137:         val = *s++;
1.1.1.3   root      138:         *d++ = s1->palette[val];
1.1       root      139:     }
                    140: }
                    141: 
1.1.1.5   root      142: /*
                    143:   XXX Could be much more optimal:
                    144:   * detect if line/page/whole screen is in 24 bit mode
                    145:   * if destination is also BGR, use memcpy
                    146:   */
1.1.1.4   root      147: static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
                    148:                                      const uint8_t *s, int width,
                    149:                                      const uint32_t *cplane,
                    150:                                      const uint32_t *s24)
                    151: {
1.1.1.6 ! root      152:     int x, bgr, r, g, b;
1.1.1.5   root      153:     uint8_t val, *p8;
1.1.1.4   root      154:     uint32_t *p = (uint32_t *)d;
                    155:     uint32_t dval;
                    156: 
1.1.1.6 ! root      157:     bgr = is_surface_bgr(s1->ds->surface);
1.1.1.4   root      158:     for(x = 0; x < width; x++, s++, s24++) {
1.1.1.5   root      159:         if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
                    160:             // 24-bit direct, BGR order
                    161:             p8 = (uint8_t *)s24;
                    162:             p8++;
                    163:             b = *p8++;
                    164:             g = *p8++;
                    165:             r = *p8++;
1.1.1.6 ! root      166:             if (bgr)
        !           167:                 dval = rgb_to_pixel32bgr(r, g, b);
        !           168:             else
        !           169:                 dval = rgb_to_pixel32(r, g, b);
1.1.1.4   root      170:         } else {
                    171:             val = *s;
                    172:             dval = s1->palette[val];
                    173:         }
                    174:         *p++ = dval;
                    175:     }
                    176: }
                    177: 
1.1.1.5   root      178: static inline int check_dirty(ram_addr_t page, ram_addr_t page24,
1.1.1.4   root      179:                               ram_addr_t cpage)
                    180: {
                    181:     int ret;
                    182:     unsigned int off;
                    183: 
                    184:     ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
                    185:     for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
                    186:         ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG);
                    187:         ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG);
                    188:     }
                    189:     return ret;
                    190: }
                    191: 
                    192: static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
                    193:                                ram_addr_t page_max, ram_addr_t page24,
                    194:                               ram_addr_t cpage)
                    195: {
                    196:     cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                    197:                                     VGA_DIRTY_FLAG);
                    198:     page_min -= ts->vram_offset;
                    199:     page_max -= ts->vram_offset;
                    200:     cpu_physical_memory_reset_dirty(page24 + page_min * 4,
                    201:                                     page24 + page_max * 4 + TARGET_PAGE_SIZE,
                    202:                                     VGA_DIRTY_FLAG);
                    203:     cpu_physical_memory_reset_dirty(cpage + page_min * 4,
                    204:                                     cpage + page_max * 4 + TARGET_PAGE_SIZE,
                    205:                                     VGA_DIRTY_FLAG);
                    206: }
                    207: 
1.1       root      208: /* Fixed line length 1024 allows us to do nice tricks not possible on
                    209:    VGA... */
1.1.1.2   root      210: static void tcx_update_display(void *opaque)
1.1       root      211: {
                    212:     TCXState *ts = opaque;
1.1.1.3   root      213:     ram_addr_t page, page_min, page_max;
                    214:     int y, y_start, dd, ds;
1.1       root      215:     uint8_t *d, *s;
1.1.1.4   root      216:     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
1.1       root      217: 
1.1.1.5   root      218:     if (ds_get_bits_per_pixel(ts->ds) == 0)
1.1.1.4   root      219:         return;
1.1       root      220:     page = ts->vram_offset;
                    221:     y_start = -1;
1.1.1.6 ! root      222:     page_min = -1;
1.1.1.3   root      223:     page_max = 0;
1.1.1.5   root      224:     d = ds_get_data(ts->ds);
1.1       root      225:     s = ts->vram;
1.1.1.5   root      226:     dd = ds_get_linesize(ts->ds);
1.1       root      227:     ds = 1024;
                    228: 
1.1.1.5   root      229:     switch (ds_get_bits_per_pixel(ts->ds)) {
1.1       root      230:     case 32:
1.1.1.4   root      231:         f = tcx_draw_line32;
                    232:         break;
1.1.1.3   root      233:     case 15:
                    234:     case 16:
1.1.1.4   root      235:         f = tcx_draw_line16;
                    236:         break;
1.1       root      237:     default:
                    238:     case 8:
1.1.1.4   root      239:         f = tcx_draw_line8;
                    240:         break;
1.1       root      241:     case 0:
1.1.1.4   root      242:         return;
1.1       root      243:     }
1.1.1.4   root      244: 
1.1       root      245:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
1.1.1.4   root      246:         if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
                    247:             if (y_start < 0)
1.1       root      248:                 y_start = y;
                    249:             if (page < page_min)
                    250:                 page_min = page;
                    251:             if (page > page_max)
                    252:                 page_max = page;
1.1.1.4   root      253:             f(ts, d, s, ts->width);
                    254:             d += dd;
                    255:             s += ds;
                    256:             f(ts, d, s, ts->width);
                    257:             d += dd;
                    258:             s += ds;
                    259:             f(ts, d, s, ts->width);
                    260:             d += dd;
                    261:             s += ds;
                    262:             f(ts, d, s, ts->width);
                    263:             d += dd;
                    264:             s += ds;
                    265:         } else {
1.1       root      266:             if (y_start >= 0) {
                    267:                 /* flush to display */
1.1.1.4   root      268:                 dpy_update(ts->ds, 0, y_start,
1.1       root      269:                            ts->width, y - y_start);
                    270:                 y_start = -1;
                    271:             }
1.1.1.4   root      272:             d += dd * 4;
                    273:             s += ds * 4;
                    274:         }
1.1       root      275:     }
                    276:     if (y_start >= 0) {
1.1.1.4   root      277:         /* flush to display */
                    278:         dpy_update(ts->ds, 0, y_start,
                    279:                    ts->width, y - y_start);
1.1       root      280:     }
                    281:     /* reset modified pages */
1.1.1.6 ! root      282:     if (page_max >= page_min) {
1.1       root      283:         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                    284:                                         VGA_DIRTY_FLAG);
                    285:     }
                    286: }
                    287: 
1.1.1.4   root      288: static void tcx24_update_display(void *opaque)
                    289: {
                    290:     TCXState *ts = opaque;
                    291:     ram_addr_t page, page_min, page_max, cpage, page24;
                    292:     int y, y_start, dd, ds;
                    293:     uint8_t *d, *s;
                    294:     uint32_t *cptr, *s24;
                    295: 
1.1.1.5   root      296:     if (ds_get_bits_per_pixel(ts->ds) != 32)
1.1.1.4   root      297:             return;
                    298:     page = ts->vram_offset;
                    299:     page24 = ts->vram24_offset;
                    300:     cpage = ts->cplane_offset;
                    301:     y_start = -1;
1.1.1.6 ! root      302:     page_min = -1;
1.1.1.4   root      303:     page_max = 0;
1.1.1.5   root      304:     d = ds_get_data(ts->ds);
1.1.1.4   root      305:     s = ts->vram;
                    306:     s24 = ts->vram24;
                    307:     cptr = ts->cplane;
1.1.1.5   root      308:     dd = ds_get_linesize(ts->ds);
1.1.1.4   root      309:     ds = 1024;
                    310: 
                    311:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
                    312:             page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
1.1.1.5   root      313:         if (check_dirty(page, page24, cpage)) {
1.1.1.4   root      314:             if (y_start < 0)
                    315:                 y_start = y;
                    316:             if (page < page_min)
                    317:                 page_min = page;
                    318:             if (page > page_max)
                    319:                 page_max = page;
                    320:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    321:             d += dd;
                    322:             s += ds;
                    323:             cptr += ds;
                    324:             s24 += ds;
                    325:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    326:             d += dd;
                    327:             s += ds;
                    328:             cptr += ds;
                    329:             s24 += ds;
                    330:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    331:             d += dd;
                    332:             s += ds;
                    333:             cptr += ds;
                    334:             s24 += ds;
                    335:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    336:             d += dd;
                    337:             s += ds;
                    338:             cptr += ds;
                    339:             s24 += ds;
                    340:         } else {
                    341:             if (y_start >= 0) {
                    342:                 /* flush to display */
                    343:                 dpy_update(ts->ds, 0, y_start,
                    344:                            ts->width, y - y_start);
                    345:                 y_start = -1;
                    346:             }
                    347:             d += dd * 4;
                    348:             s += ds * 4;
                    349:             cptr += ds * 4;
                    350:             s24 += ds * 4;
                    351:         }
                    352:     }
                    353:     if (y_start >= 0) {
                    354:         /* flush to display */
                    355:         dpy_update(ts->ds, 0, y_start,
                    356:                    ts->width, y - y_start);
                    357:     }
                    358:     /* reset modified pages */
1.1.1.6 ! root      359:     if (page_max >= page_min) {
1.1.1.4   root      360:         reset_dirty(ts, page_min, page_max, page24, cpage);
                    361:     }
                    362: }
                    363: 
1.1.1.2   root      364: static void tcx_invalidate_display(void *opaque)
1.1       root      365: {
                    366:     TCXState *s = opaque;
                    367: 
1.1.1.6 ! root      368:     tcx_set_dirty(s);
        !           369:     qemu_console_resize(s->ds, s->width, s->height);
1.1.1.4   root      370: }
                    371: 
                    372: static void tcx24_invalidate_display(void *opaque)
                    373: {
                    374:     TCXState *s = opaque;
                    375: 
1.1.1.6 ! root      376:     tcx_set_dirty(s);
        !           377:     tcx24_set_dirty(s);
        !           378:     qemu_console_resize(s->ds, s->width, s->height);
1.1       root      379: }
                    380: 
                    381: static void tcx_save(QEMUFile *f, void *opaque)
                    382: {
                    383:     TCXState *s = opaque;
1.1.1.4   root      384: 
1.1.1.5   root      385:     qemu_put_be16s(f, &s->height);
                    386:     qemu_put_be16s(f, &s->width);
                    387:     qemu_put_be16s(f, &s->depth);
1.1       root      388:     qemu_put_buffer(f, s->r, 256);
                    389:     qemu_put_buffer(f, s->g, 256);
                    390:     qemu_put_buffer(f, s->b, 256);
                    391:     qemu_put_8s(f, &s->dac_index);
                    392:     qemu_put_8s(f, &s->dac_state);
                    393: }
                    394: 
                    395: static int tcx_load(QEMUFile *f, void *opaque, int version_id)
                    396: {
                    397:     TCXState *s = opaque;
1.1.1.4   root      398:     uint32_t dummy;
                    399: 
                    400:     if (version_id != 3 && version_id != 4)
1.1       root      401:         return -EINVAL;
                    402: 
1.1.1.4   root      403:     if (version_id == 3) {
1.1.1.5   root      404:         qemu_get_be32s(f, &dummy);
                    405:         qemu_get_be32s(f, &dummy);
                    406:         qemu_get_be32s(f, &dummy);
                    407:     }
                    408:     qemu_get_be16s(f, &s->height);
                    409:     qemu_get_be16s(f, &s->width);
                    410:     qemu_get_be16s(f, &s->depth);
1.1       root      411:     qemu_get_buffer(f, s->r, 256);
                    412:     qemu_get_buffer(f, s->g, 256);
                    413:     qemu_get_buffer(f, s->b, 256);
                    414:     qemu_get_8s(f, &s->dac_index);
                    415:     qemu_get_8s(f, &s->dac_state);
1.1.1.3   root      416:     update_palette_entries(s, 0, 256);
1.1.1.6 ! root      417:     if (s->depth == 24) {
        !           418:         tcx24_set_dirty(s);
        !           419:     } else {
        !           420:         tcx_set_dirty(s);
        !           421:     }
1.1.1.4   root      422: 
1.1       root      423:     return 0;
                    424: }
                    425: 
                    426: static void tcx_reset(void *opaque)
                    427: {
                    428:     TCXState *s = opaque;
                    429: 
                    430:     /* Initialize palette */
                    431:     memset(s->r, 0, 256);
                    432:     memset(s->g, 0, 256);
                    433:     memset(s->b, 0, 256);
                    434:     s->r[255] = s->g[255] = s->b[255] = 255;
1.1.1.3   root      435:     update_palette_entries(s, 0, 256);
1.1       root      436:     memset(s->vram, 0, MAXX*MAXY);
1.1.1.4   root      437:     cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset +
                    438:                                     MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG);
1.1       root      439:     s->dac_index = 0;
                    440:     s->dac_state = 0;
                    441: }
                    442: 
                    443: static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
                    444: {
                    445:     return 0;
                    446: }
                    447: 
                    448: static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    449: {
                    450:     TCXState *s = opaque;
                    451: 
1.1.1.5   root      452:     switch (addr) {
1.1       root      453:     case 0:
1.1.1.4   root      454:         s->dac_index = val >> 24;
                    455:         s->dac_state = 0;
                    456:         break;
1.1.1.5   root      457:     case 4:
1.1.1.4   root      458:         switch (s->dac_state) {
                    459:         case 0:
                    460:             s->r[s->dac_index] = val >> 24;
1.1.1.3   root      461:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      462:             s->dac_state++;
                    463:             break;
                    464:         case 1:
                    465:             s->g[s->dac_index] = val >> 24;
1.1.1.3   root      466:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      467:             s->dac_state++;
                    468:             break;
                    469:         case 2:
                    470:             s->b[s->dac_index] = val >> 24;
1.1.1.3   root      471:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      472:             s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
                    473:         default:
                    474:             s->dac_state = 0;
                    475:             break;
                    476:         }
                    477:         break;
1.1       root      478:     default:
1.1.1.4   root      479:         break;
1.1       root      480:     }
                    481:     return;
                    482: }
                    483: 
                    484: static CPUReadMemoryFunc *tcx_dac_read[3] = {
1.1.1.4   root      485:     NULL,
                    486:     NULL,
1.1       root      487:     tcx_dac_readl,
                    488: };
                    489: 
                    490: static CPUWriteMemoryFunc *tcx_dac_write[3] = {
1.1.1.4   root      491:     NULL,
                    492:     NULL,
1.1       root      493:     tcx_dac_writel,
                    494: };
                    495: 
1.1.1.4   root      496: static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
                    497: {
                    498:     return 0;
                    499: }
                    500: 
                    501: static void tcx_dummy_writel(void *opaque, target_phys_addr_t addr,
                    502:                              uint32_t val)
                    503: {
                    504: }
                    505: 
                    506: static CPUReadMemoryFunc *tcx_dummy_read[3] = {
                    507:     NULL,
                    508:     NULL,
                    509:     tcx_dummy_readl,
                    510: };
                    511: 
                    512: static CPUWriteMemoryFunc *tcx_dummy_write[3] = {
                    513:     NULL,
                    514:     NULL,
                    515:     tcx_dummy_writel,
                    516: };
                    517: 
1.1.1.6 ! root      518: void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height,
1.1.1.4   root      519:               int depth)
1.1       root      520: {
1.1.1.6 ! root      521:     DeviceState *dev;
        !           522:     SysBusDevice *s;
        !           523: 
        !           524:     dev = qdev_create(NULL, "SUNW,tcx");
        !           525:     qdev_prop_set_taddr(dev, "addr", addr);
        !           526:     qdev_prop_set_uint32(dev, "vram_size", vram_size);
        !           527:     qdev_prop_set_uint16(dev, "width", width);
        !           528:     qdev_prop_set_uint16(dev, "height", height);
        !           529:     qdev_prop_set_uint16(dev, "depth", depth);
        !           530:     qdev_init(dev);
        !           531:     s = sysbus_from_qdev(dev);
        !           532:     /* 8-bit plane */
        !           533:     sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
        !           534:     /* DAC */
        !           535:     sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
        !           536:     /* TEC (dummy) */
        !           537:     sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
        !           538:     /* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
        !           539:     sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
        !           540:     if (depth == 24) {
        !           541:         /* 24-bit plane */
        !           542:         sysbus_mmio_map(s, 4, addr + 0x02000000ULL);
        !           543:         /* Control plane */
        !           544:         sysbus_mmio_map(s, 5, addr + 0x0a000000ULL);
        !           545:     } else {
        !           546:         /* THC 8 bit (dummy) */
        !           547:         sysbus_mmio_map(s, 4, addr + 0x00300000ULL);
        !           548:     }
        !           549: }
        !           550: 
        !           551: static void tcx_init1(SysBusDevice *dev)
        !           552: {
        !           553:     TCXState *s = FROM_SYSBUS(TCXState, dev);
1.1.1.4   root      554:     int io_memory, dummy_memory;
1.1.1.6 ! root      555:     ram_addr_t vram_offset;
1.1.1.4   root      556:     int size;
1.1.1.6 ! root      557:     uint8_t *vram_base;
1.1       root      558: 
1.1.1.6 ! root      559:     vram_offset = qemu_ram_alloc(s->vram_size * (1 + 4 + 4));
        !           560:     vram_base = qemu_get_ram_ptr(vram_offset);
1.1       root      561:     s->vram_offset = vram_offset;
1.1.1.4   root      562: 
1.1.1.6 ! root      563:     /* 8-bit plane */
1.1.1.4   root      564:     s->vram = vram_base;
1.1.1.6 ! root      565:     size = s->vram_size;
        !           566:     sysbus_init_mmio(dev, size, s->vram_offset);
1.1.1.4   root      567:     vram_offset += size;
                    568:     vram_base += size;
1.1       root      569: 
1.1.1.6 ! root      570:     /* DAC */
        !           571:     io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s);
        !           572:     sysbus_init_mmio(dev, TCX_DAC_NREGS, io_memory);
1.1       root      573: 
1.1.1.6 ! root      574:     /* TEC (dummy) */
        !           575:     dummy_memory = cpu_register_io_memory(tcx_dummy_read, tcx_dummy_write,
1.1.1.4   root      576:                                           s);
1.1.1.6 ! root      577:     sysbus_init_mmio(dev, TCX_TEC_NREGS, dummy_memory);
        !           578:     /* THC: NetBSD writes here even with 8-bit display: dummy */
        !           579:     sysbus_init_mmio(dev, TCX_THC_NREGS_24, dummy_memory);
        !           580: 
        !           581:     if (s->depth == 24) {
        !           582:         /* 24-bit plane */
        !           583:         size = s->vram_size * 4;
1.1.1.4   root      584:         s->vram24 = (uint32_t *)vram_base;
                    585:         s->vram24_offset = vram_offset;
1.1.1.6 ! root      586:         sysbus_init_mmio(dev, size, vram_offset);
1.1.1.4   root      587:         vram_offset += size;
                    588:         vram_base += size;
                    589: 
1.1.1.6 ! root      590:         /* Control plane */
        !           591:         size = s->vram_size * 4;
1.1.1.4   root      592:         s->cplane = (uint32_t *)vram_base;
                    593:         s->cplane_offset = vram_offset;
1.1.1.6 ! root      594:         sysbus_init_mmio(dev, size, vram_offset);
        !           595: 
1.1.1.5   root      596:         s->ds = graphic_console_init(tcx24_update_display,
                    597:                                      tcx24_invalidate_display,
                    598:                                      tcx24_screen_dump, NULL, s);
1.1.1.4   root      599:     } else {
1.1.1.6 ! root      600:         /* THC 8 bit (dummy) */
        !           601:         sysbus_init_mmio(dev, TCX_THC_NREGS_8, dummy_memory);
        !           602: 
1.1.1.5   root      603:         s->ds = graphic_console_init(tcx_update_display,
                    604:                                      tcx_invalidate_display,
                    605:                                      tcx_screen_dump, NULL, s);
1.1.1.4   root      606:     }
                    607: 
1.1.1.6 ! root      608:     register_savevm("tcx", -1, 4, tcx_save, tcx_load, s);
1.1       root      609:     qemu_register_reset(tcx_reset, s);
                    610:     tcx_reset(s);
1.1.1.6 ! root      611:     qemu_console_resize(s->ds, s->width, s->height);
1.1       root      612: }
                    613: 
1.1.1.2   root      614: static void tcx_screen_dump(void *opaque, const char *filename)
1.1       root      615: {
                    616:     TCXState *s = opaque;
                    617:     FILE *f;
                    618:     uint8_t *d, *d1, v;
                    619:     int y, x;
                    620: 
                    621:     f = fopen(filename, "wb");
                    622:     if (!f)
                    623:         return;
                    624:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
                    625:     d1 = s->vram;
                    626:     for(y = 0; y < s->height; y++) {
                    627:         d = d1;
                    628:         for(x = 0; x < s->width; x++) {
                    629:             v = *d;
                    630:             fputc(s->r[v], f);
                    631:             fputc(s->g[v], f);
                    632:             fputc(s->b[v], f);
                    633:             d++;
                    634:         }
                    635:         d1 += MAXX;
                    636:     }
                    637:     fclose(f);
                    638:     return;
                    639: }
                    640: 
1.1.1.4   root      641: static void tcx24_screen_dump(void *opaque, const char *filename)
                    642: {
                    643:     TCXState *s = opaque;
                    644:     FILE *f;
                    645:     uint8_t *d, *d1, v;
                    646:     uint32_t *s24, *cptr, dval;
                    647:     int y, x;
1.1       root      648: 
1.1.1.4   root      649:     f = fopen(filename, "wb");
                    650:     if (!f)
                    651:         return;
                    652:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
                    653:     d1 = s->vram;
                    654:     s24 = s->vram24;
                    655:     cptr = s->cplane;
                    656:     for(y = 0; y < s->height; y++) {
                    657:         d = d1;
                    658:         for(x = 0; x < s->width; x++, d++, s24++) {
                    659:             if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
                    660:                 dval = *s24 & 0x00ffffff;
                    661:                 fputc((dval >> 16) & 0xff, f);
                    662:                 fputc((dval >> 8) & 0xff, f);
                    663:                 fputc(dval & 0xff, f);
                    664:             } else {
                    665:                 v = *d;
                    666:                 fputc(s->r[v], f);
                    667:                 fputc(s->g[v], f);
                    668:                 fputc(s->b[v], f);
                    669:             }
                    670:         }
                    671:         d1 += MAXX;
                    672:     }
                    673:     fclose(f);
                    674:     return;
                    675: }
1.1.1.6 ! root      676: 
        !           677: static SysBusDeviceInfo tcx_info = {
        !           678:     .init = tcx_init1,
        !           679:     .qdev.name  = "SUNW,tcx",
        !           680:     .qdev.size  = sizeof(TCXState),
        !           681:     .qdev.props = (Property[]) {
        !           682:         {
        !           683:             .name   = "addr",
        !           684:             .info   = &qdev_prop_taddr,
        !           685:             .offset = offsetof(TCXState, addr),
        !           686:             .defval = (target_phys_addr_t[]) { -1 },
        !           687:         },{
        !           688:             .name   = "vram_size",
        !           689:             .info   = &qdev_prop_hex32,
        !           690:             .offset = offsetof(TCXState, vram_size),
        !           691:             .defval = (uint32_t[]) { -1 },
        !           692:         },{
        !           693:             .name   = "width",
        !           694:             .info   = &qdev_prop_uint16,
        !           695:             .offset = offsetof(TCXState, width),
        !           696:             .defval = (uint16_t[]) { -1 },
        !           697:         },{
        !           698:             .name   = "height",
        !           699:             .info   = &qdev_prop_uint16,
        !           700:             .offset = offsetof(TCXState, height),
        !           701:             .defval = (uint16_t[]) { -1 },
        !           702:         },{
        !           703:             .name   = "depth",
        !           704:             .info   = &qdev_prop_uint16,
        !           705:             .offset = offsetof(TCXState, depth),
        !           706:             .defval = (uint16_t[]) { -1 },
        !           707:         },
        !           708:         {/* end of list */}
        !           709:     }
        !           710: };
        !           711: 
        !           712: static void tcx_register_devices(void)
        !           713: {
        !           714:     sysbus_register_withprop(&tcx_info);
        !           715: }
        !           716: 
        !           717: device_init(tcx_register_devices)

unix.superglobalmegacorp.com

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