|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.