Annotation of qemu/roms/seabios/vgasrc/vgafb.c, revision 1.1.1.2

1.1       root        1: // Code for manipulating VGA framebuffers.
                      2: //
                      3: // Copyright (C) 2009  Kevin O'Connor <[email protected]>
                      4: // Copyright (C) 2001-2008 the LGPL VGABios developers Team
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
1.1.1.2 ! root        8: #include "vgabios.h" // vgafb_scroll
1.1       root        9: #include "biosvar.h" // GET_BDA
                     10: #include "util.h" // memset_far
1.1.1.2 ! root       11: #include "stdvga.h" // stdvga_planar4_plane
1.1       root       12: 
                     13: 
                     14: /****************************************************************
                     15:  * Screen scrolling
                     16:  ****************************************************************/
                     17: 
                     18: static inline void *
                     19: memcpy_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
                     20: {
                     21:     for (; lines; lines--, dst+=stride, src+=stride)
                     22:         memcpy_far(seg, dst, seg, src, copylen);
                     23:     return dst;
                     24: }
                     25: 
                     26: static inline void
                     27: memset_stride(u16 seg, void *dst, u8 val, int setlen, int stride, int lines)
                     28: {
                     29:     for (; lines; lines--, dst+=stride)
                     30:         memset_far(seg, dst, val, setlen);
                     31: }
                     32: 
                     33: static inline void
                     34: memset16_stride(u16 seg, void *dst, u16 val, int setlen, int stride, int lines)
                     35: {
                     36:     for (; lines; lines--, dst+=stride)
                     37:         memset16_far(seg, dst, val, setlen);
                     38: }
                     39: 
                     40: static void
                     41: scroll_pl4(struct vgamode_s *vmode_g, int nblines, int attr
                     42:            , struct cursorpos ul, struct cursorpos lr)
                     43: {
1.1.1.2 ! root       44:     int cheight = GET_GLOBAL(vmode_g->cheight);
        !            45:     int cwidth = 1;
        !            46:     int stride = GET_BDA(video_cols) * cwidth;
1.1       root       47:     void *src_far, *dest_far;
                     48:     if (nblines >= 0) {
1.1.1.2 ! root       49:         dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
1.1       root       50:         src_far = dest_far + nblines * cheight * stride;
                     51:     } else {
                     52:         // Scroll down
                     53:         nblines = -nblines;
1.1.1.2 ! root       54:         dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
1.1       root       55:         src_far = dest_far - nblines * cheight * stride;
                     56:         stride = -stride;
                     57:     }
1.1.1.2 ! root       58:     if (attr < 0)
        !            59:         attr = 0;
1.1       root       60:     int cols = lr.x - ul.x + 1;
                     61:     int rows = lr.y - ul.y + 1;
1.1.1.2 ! root       62:     int i;
        !            63:     for (i=0; i<4; i++) {
        !            64:         stdvga_planar4_plane(i);
        !            65:         void *dest = dest_far;
        !            66:         if (nblines < rows)
        !            67:             dest = memcpy_stride(SEG_GRAPH, dest, src_far, cols * cwidth
        !            68:                                  , stride, (rows - nblines) * cheight);
        !            69:         u8 pixels = (attr & (1<<i)) ? 0xff : 0x00;
        !            70:         memset_stride(SEG_GRAPH, dest, pixels, cols * cwidth
        !            71:                       , stride, nblines * cheight);
1.1       root       72:     }
1.1.1.2 ! root       73:     stdvga_planar4_plane(-1);
1.1       root       74: }
                     75: 
                     76: static void
                     77: scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr
                     78:             , struct cursorpos ul, struct cursorpos lr)
                     79: {
1.1.1.2 ! root       80:     int cheight = GET_GLOBAL(vmode_g->cheight) / 2;
        !            81:     int cwidth = GET_GLOBAL(vmode_g->depth);
        !            82:     int stride = GET_BDA(video_cols) * cwidth;
1.1       root       83:     void *src_far, *dest_far;
                     84:     if (nblines >= 0) {
1.1.1.2 ! root       85:         dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
1.1       root       86:         src_far = dest_far + nblines * cheight * stride;
                     87:     } else {
                     88:         // Scroll down
                     89:         nblines = -nblines;
1.1.1.2 ! root       90:         dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
1.1       root       91:         src_far = dest_far - nblines * cheight * stride;
                     92:         stride = -stride;
                     93:     }
1.1.1.2 ! root       94:     if (attr < 0)
        !            95:         attr = 0;
        !            96:     if (cwidth == 1)
        !            97:         attr = (attr&1) | ((attr&1)<<1);
        !            98:     attr &= 3;
        !            99:     attr |= (attr<<2) | (attr<<4) | (attr<<6);
        !           100:     int cols = lr.x - ul.x + 1;
1.1       root      101:     int rows = lr.y - ul.y + 1;
                    102:     if (nblines < rows) {
1.1.1.2 ! root      103:         memcpy_stride(SEG_CTEXT, dest_far+0x2000, src_far+0x2000, cols * cwidth
        !           104:                       , stride, (rows - nblines) * cheight);
        !           105:         dest_far = memcpy_stride(SEG_CTEXT, dest_far, src_far, cols * cwidth
        !           106:                                  , stride, (rows - nblines) * cheight);
        !           107:     }
        !           108:     memset_stride(SEG_CTEXT, dest_far + 0x2000, attr, cols * cwidth
        !           109:                   , stride, nblines * cheight);
        !           110:     memset_stride(SEG_CTEXT, dest_far, attr, cols * cwidth
        !           111:                   , stride, nblines * cheight);
        !           112: }
        !           113: 
        !           114: static void
        !           115: scroll_lin(struct vgamode_s *vmode_g, int nblines, int attr
        !           116:            , struct cursorpos ul, struct cursorpos lr)
        !           117: {
        !           118:     int cheight = 8;
        !           119:     int cwidth = 8;
        !           120:     int stride = GET_BDA(video_cols) * cwidth;
        !           121:     void *src_far, *dest_far;
        !           122:     if (nblines >= 0) {
        !           123:         dest_far = (void*)(ul.y * cheight * stride + ul.x * cwidth);
        !           124:         src_far = dest_far + nblines * cheight * stride;
        !           125:     } else {
        !           126:         // Scroll down
        !           127:         nblines = -nblines;
        !           128:         dest_far = (void*)(lr.y * cheight * stride + ul.x * cwidth);
        !           129:         src_far = dest_far - nblines * cheight * stride;
        !           130:         stride = -stride;
1.1       root      131:     }
                    132:     if (attr < 0)
                    133:         attr = 0;
1.1.1.2 ! root      134:     int cols = lr.x - ul.x + 1;
        !           135:     int rows = lr.y - ul.y + 1;
        !           136:     if (nblines < rows)
        !           137:         dest_far = memcpy_stride(SEG_GRAPH, dest_far, src_far, cols * cwidth
        !           138:                                  , stride, (rows - nblines) * cheight);
        !           139:     memset_stride(SEG_GRAPH, dest_far, attr, cols * cwidth
        !           140:                   , stride, nblines * cheight);
1.1       root      141: }
                    142: 
                    143: static void
                    144: scroll_text(struct vgamode_s *vmode_g, int nblines, int attr
                    145:             , struct cursorpos ul, struct cursorpos lr)
                    146: {
1.1.1.2 ! root      147:     int cheight = 1;
        !           148:     int cwidth = 2;
        !           149:     int stride = GET_BDA(video_cols) * cwidth;
        !           150:     void *src_far, *dest_far = (void*)(GET_BDA(video_pagesize) * ul.page);
1.1       root      151:     if (nblines >= 0) {
1.1.1.2 ! root      152:         dest_far += ul.y * cheight * stride + ul.x * cwidth;
        !           153:         src_far = dest_far + nblines * cheight * stride;
1.1       root      154:     } else {
                    155:         // Scroll down
                    156:         nblines = -nblines;
1.1.1.2 ! root      157:         dest_far += lr.y * cheight * stride + ul.x * cwidth;
        !           158:         src_far = dest_far - nblines * cheight * stride;
1.1       root      159:         stride = -stride;
                    160:     }
                    161:     if (attr < 0)
                    162:         attr = 0x07;
                    163:     attr = (attr << 8) | ' ';
1.1.1.2 ! root      164:     int cols = lr.x - ul.x + 1;
        !           165:     int rows = lr.y - ul.y + 1;
        !           166:     u16 seg = GET_GLOBAL(vmode_g->sstart);
        !           167:     if (nblines < rows)
        !           168:         dest_far = memcpy_stride(seg, dest_far, src_far, cols * cwidth
        !           169:                                  , stride, (rows - nblines) * cheight);
        !           170:     memset16_stride(seg, dest_far, attr, cols * cwidth
        !           171:                     , stride, nblines * cheight);
1.1       root      172: }
                    173: 
                    174: void
                    175: vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
                    176: {
                    177:     // Get the mode
1.1.1.2 ! root      178:     struct vgamode_s *vmode_g = get_current_mode();
1.1       root      179:     if (!vmode_g)
                    180:         return;
                    181: 
                    182:     // FIXME gfx mode not complete
                    183:     switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root      184:     case MM_TEXT:
1.1       root      185:         scroll_text(vmode_g, nblines, attr, ul, lr);
                    186:         break;
1.1.1.2 ! root      187:     case MM_PLANAR:
1.1       root      188:         scroll_pl4(vmode_g, nblines, attr, ul, lr);
                    189:         break;
1.1.1.2 ! root      190:     case MM_CGA:
1.1       root      191:         scroll_cga(vmode_g, nblines, attr, ul, lr);
                    192:         break;
1.1.1.2 ! root      193:     case MM_DIRECT:
        !           194:     case MM_PACKED:
        !           195:         scroll_lin(vmode_g, nblines, attr, ul, lr);
1.1       root      196:         break;
                    197:     default:
1.1.1.2 ! root      198:         break;
1.1       root      199:     }
                    200: }
                    201: 
                    202: 
                    203: /****************************************************************
                    204:  * Read/write characters to screen
                    205:  ****************************************************************/
                    206: 
                    207: static void
                    208: write_gfx_char_pl4(struct vgamode_s *vmode_g
                    209:                    , struct cursorpos cp, struct carattr ca)
                    210: {
                    211:     u16 nbcols = GET_BDA(video_cols);
                    212:     if (cp.x >= nbcols)
                    213:         return;
                    214: 
1.1.1.2 ! root      215:     u8 cheight = GET_GLOBAL(vmode_g->cheight);
1.1       root      216:     u8 *fdata_g;
                    217:     switch (cheight) {
                    218:     case 14:
                    219:         fdata_g = vgafont14;
                    220:         break;
                    221:     case 16:
                    222:         fdata_g = vgafont16;
                    223:         break;
                    224:     default:
                    225:         fdata_g = vgafont8;
                    226:     }
                    227:     u16 addr = cp.x + cp.y * cheight * nbcols;
                    228:     u16 src = ca.car * cheight;
1.1.1.2 ! root      229:     int i;
        !           230:     for (i=0; i<4; i++) {
        !           231:         stdvga_planar4_plane(i);
        !           232:         u8 colors = ((ca.attr & (1<<i)) ? 0xff : 0x00);
        !           233:         int j;
        !           234:         for (j = 0; j < cheight; j++) {
        !           235:             u8 *dest_far = (void*)(addr + j * nbcols);
        !           236:             u8 pixels = colors & GET_GLOBAL(fdata_g[src + j]);
        !           237:             if (ca.attr & 0x80)
        !           238:                 pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far);
        !           239:             SET_FARVAR(SEG_GRAPH, *dest_far, pixels);
1.1       root      240:         }
                    241:     }
1.1.1.2 ! root      242:     stdvga_planar4_plane(-1);
1.1       root      243: }
                    244: 
                    245: static void
                    246: write_gfx_char_cga(struct vgamode_s *vmode_g
                    247:                    , struct cursorpos cp, struct carattr ca)
                    248: {
                    249:     u16 nbcols = GET_BDA(video_cols);
                    250:     if (cp.x >= nbcols)
                    251:         return;
                    252: 
                    253:     u8 *fdata_g = vgafont8;
1.1.1.2 ! root      254:     u8 bpp = GET_GLOBAL(vmode_g->depth);
1.1       root      255:     u16 addr = (cp.x * bpp) + cp.y * 320;
                    256:     u16 src = ca.car * 8;
                    257:     u8 i;
                    258:     for (i = 0; i < 8; i++) {
                    259:         u8 *dest_far = (void*)(addr + (i >> 1) * 80);
                    260:         if (i & 1)
                    261:             dest_far += 0x2000;
                    262:         if (bpp == 1) {
1.1.1.2 ! root      263:             u8 colors = (ca.attr & 0x01) ? 0xff : 0x00;
        !           264:             u8 pixels = colors & GET_GLOBAL(fdata_g[src + i]);
1.1       root      265:             if (ca.attr & 0x80)
1.1.1.2 ! root      266:                 pixels ^= GET_FARVAR(SEG_GRAPH, *dest_far);
        !           267:             SET_FARVAR(SEG_CTEXT, *dest_far, pixels);
1.1       root      268:         } else {
1.1.1.2 ! root      269:             u16 pixels = 0;
        !           270:             u8 fontline = GET_GLOBAL(fdata_g[src + i]);
        !           271:             int j;
        !           272:             for (j = 0; j < 8; j++)
        !           273:                 if (fontline & (1<<j))
        !           274:                     pixels |= (ca.attr & 0x03) << (j*2);
        !           275:             pixels = htons(pixels);
        !           276:             if (ca.attr & 0x80)
        !           277:                 pixels ^= GET_FARVAR(SEG_GRAPH, *(u16*)dest_far);
        !           278:             SET_FARVAR(SEG_CTEXT, *(u16*)dest_far, pixels);
1.1       root      279:         }
                    280:     }
                    281: }
                    282: 
                    283: static void
                    284: write_gfx_char_lin(struct vgamode_s *vmode_g
                    285:                    , struct cursorpos cp, struct carattr ca)
                    286: {
                    287:     // Get the dimensions
                    288:     u16 nbcols = GET_BDA(video_cols);
                    289:     if (cp.x >= nbcols)
                    290:         return;
                    291: 
                    292:     u8 *fdata_g = vgafont8;
                    293:     u16 addr = cp.x * 8 + cp.y * nbcols * 64;
                    294:     u16 src = ca.car * 8;
                    295:     u8 i;
                    296:     for (i = 0; i < 8; i++) {
                    297:         u8 *dest_far = (void*)(addr + i * nbcols * 8);
1.1.1.2 ! root      298:         u8 fontline = GET_GLOBAL(fdata_g[src + i]);
1.1       root      299:         u8 j;
                    300:         for (j = 0; j < 8; j++) {
1.1.1.2 ! root      301:             u8 pixel = (fontline & (0x80>>j)) ? ca.attr : 0x00;
        !           302:             SET_FARVAR(SEG_GRAPH, dest_far[j], pixel);
1.1       root      303:         }
                    304:     }
                    305: }
                    306: 
                    307: static void
                    308: write_text_char(struct vgamode_s *vmode_g
                    309:                 , struct cursorpos cp, struct carattr ca)
                    310: {
                    311:     // Compute the address
1.1.1.2 ! root      312:     u16 nbcols = GET_BDA(video_cols);
        !           313:     void *address_far = (void*)(GET_BDA(video_pagesize) * cp.page
1.1       root      314:                                 + (cp.x + cp.y * nbcols) * 2);
                    315: 
                    316:     if (ca.use_attr) {
                    317:         u16 dummy = (ca.attr << 8) | ca.car;
                    318:         SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u16*)address_far, dummy);
                    319:     } else {
                    320:         SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)address_far, ca.car);
                    321:     }
                    322: }
                    323: 
                    324: void
                    325: vgafb_write_char(struct cursorpos cp, struct carattr ca)
                    326: {
                    327:     // Get the mode
1.1.1.2 ! root      328:     struct vgamode_s *vmode_g = get_current_mode();
1.1       root      329:     if (!vmode_g)
                    330:         return;
                    331: 
                    332:     // FIXME gfx mode not complete
                    333:     switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root      334:     case MM_TEXT:
1.1       root      335:         write_text_char(vmode_g, cp, ca);
                    336:         break;
1.1.1.2 ! root      337:     case MM_PLANAR:
1.1       root      338:         write_gfx_char_pl4(vmode_g, cp, ca);
                    339:         break;
1.1.1.2 ! root      340:     case MM_CGA:
1.1       root      341:         write_gfx_char_cga(vmode_g, cp, ca);
                    342:         break;
1.1.1.2 ! root      343:     case MM_DIRECT:
        !           344:     case MM_PACKED:
1.1       root      345:         write_gfx_char_lin(vmode_g, cp, ca);
                    346:         break;
1.1.1.2 ! root      347:     default:
        !           348:         break;
1.1       root      349:     }
                    350: }
                    351: 
                    352: struct carattr
                    353: vgafb_read_char(struct cursorpos cp)
                    354: {
                    355:     // Get the mode
1.1.1.2 ! root      356:     struct vgamode_s *vmode_g = get_current_mode();
1.1       root      357:     if (!vmode_g)
                    358:         goto fail;
                    359: 
1.1.1.2 ! root      360:     if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
1.1       root      361:         // FIXME gfx mode
                    362:         dprintf(1, "Read char in graphics mode\n");
                    363:         goto fail;
                    364:     }
                    365: 
                    366:     // Compute the address
1.1.1.2 ! root      367:     u16 nbcols = GET_BDA(video_cols);
        !           368:     u16 *address_far = (void*)(GET_BDA(video_pagesize) * cp.page
1.1       root      369:                                + (cp.x + cp.y * nbcols) * 2);
                    370:     u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *address_far);
                    371:     struct carattr ca = {v, v>>8, 0};
                    372:     return ca;
                    373: 
                    374: fail: ;
                    375:     struct carattr ca2 = {0, 0, 0};
                    376:     return ca2;
                    377: }
                    378: 
                    379: 
                    380: /****************************************************************
                    381:  * Read/write pixels
                    382:  ****************************************************************/
                    383: 
                    384: void
                    385: vgafb_write_pixel(u8 color, u16 x, u16 y)
                    386: {
                    387:     // Get the mode
1.1.1.2 ! root      388:     struct vgamode_s *vmode_g = get_current_mode();
1.1       root      389:     if (!vmode_g)
                    390:         return;
                    391: 
1.1.1.2 ! root      392:     u8 *addr_far, mask, attr, data, i;
1.1       root      393:     switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root      394:     case MM_PLANAR:
1.1       root      395:         addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
                    396:         mask = 0x80 >> (x & 0x07);
1.1.1.2 ! root      397:         for (i=0; i<4; i++) {
        !           398:             stdvga_planar4_plane(i);
        !           399:             u8 colors = (color & (1<<i)) ? 0xff : 0x00;
        !           400:             u8 orig = GET_FARVAR(SEG_GRAPH, *addr_far);
        !           401:             if (color & 0x80)
        !           402:                 colors ^= orig;
        !           403:             SET_FARVAR(SEG_GRAPH, *addr_far, (colors & mask) | (orig & ~mask));
        !           404:         }
        !           405:         stdvga_planar4_plane(-1);
1.1       root      406:         break;
1.1.1.2 ! root      407:     case MM_CGA:
        !           408:         if (GET_GLOBAL(vmode_g->depth) == 2)
1.1       root      409:             addr_far = (void*)((x >> 2) + (y >> 1) * 80);
                    410:         else
                    411:             addr_far = (void*)((x >> 3) + (y >> 1) * 80);
                    412:         if (y & 1)
                    413:             addr_far += 0x2000;
                    414:         data = GET_FARVAR(SEG_CTEXT, *addr_far);
1.1.1.2 ! root      415:         if (GET_GLOBAL(vmode_g->depth) == 2) {
1.1       root      416:             attr = (color & 0x03) << ((3 - (x & 0x03)) * 2);
                    417:             mask = 0x03 << ((3 - (x & 0x03)) * 2);
                    418:         } else {
                    419:             attr = (color & 0x01) << (7 - (x & 0x07));
                    420:             mask = 0x01 << (7 - (x & 0x07));
                    421:         }
                    422:         if (color & 0x80) {
                    423:             data ^= attr;
                    424:         } else {
                    425:             data &= ~mask;
                    426:             data |= attr;
                    427:         }
                    428:         SET_FARVAR(SEG_CTEXT, *addr_far, data);
                    429:         break;
1.1.1.2 ! root      430:     case MM_DIRECT:
        !           431:     case MM_PACKED:
1.1       root      432:         addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
                    433:         SET_FARVAR(SEG_GRAPH, *addr_far, color);
                    434:         break;
1.1.1.2 ! root      435:     default:
        !           436:     case MM_TEXT:
        !           437:         return;
1.1       root      438:     }
                    439: }
                    440: 
                    441: u8
                    442: vgafb_read_pixel(u16 x, u16 y)
                    443: {
                    444:     // Get the mode
1.1.1.2 ! root      445:     struct vgamode_s *vmode_g = get_current_mode();
1.1       root      446:     if (!vmode_g)
                    447:         return 0;
                    448: 
                    449:     u8 *addr_far, mask, attr=0, data, i;
                    450:     switch (GET_GLOBAL(vmode_g->memmodel)) {
1.1.1.2 ! root      451:     case MM_PLANAR:
1.1       root      452:         addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
                    453:         mask = 0x80 >> (x & 0x07);
                    454:         attr = 0x00;
                    455:         for (i = 0; i < 4; i++) {
1.1.1.2 ! root      456:             stdvga_planar4_plane(i);
1.1       root      457:             data = GET_FARVAR(SEG_GRAPH, *addr_far) & mask;
                    458:             if (data > 0)
                    459:                 attr |= (0x01 << i);
                    460:         }
1.1.1.2 ! root      461:         stdvga_planar4_plane(-1);
1.1       root      462:         break;
1.1.1.2 ! root      463:     case MM_CGA:
1.1       root      464:         addr_far = (void*)((x >> 2) + (y >> 1) * 80);
                    465:         if (y & 1)
                    466:             addr_far += 0x2000;
                    467:         data = GET_FARVAR(SEG_CTEXT, *addr_far);
1.1.1.2 ! root      468:         if (GET_GLOBAL(vmode_g->depth) == 2)
1.1       root      469:             attr = (data >> ((3 - (x & 0x03)) * 2)) & 0x03;
                    470:         else
                    471:             attr = (data >> (7 - (x & 0x07))) & 0x01;
                    472:         break;
1.1.1.2 ! root      473:     case MM_DIRECT:
        !           474:     case MM_PACKED:
1.1       root      475:         addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
                    476:         attr = GET_FARVAR(SEG_GRAPH, *addr_far);
                    477:         break;
1.1.1.2 ! root      478:     default:
        !           479:     case MM_TEXT:
        !           480:         return 0;
1.1       root      481:     }
                    482:     return attr;
                    483: }

unix.superglobalmegacorp.com

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