Annotation of qemu/roms/seabios/vgasrc/vgafb.c, revision 1.1.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.