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

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

unix.superglobalmegacorp.com

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