|
|
1.1 ! root 1: #include "asm/io.h" ! 2: #include "drivers/vga.h" ! 3: #include "vga.h" ! 4: ! 5: /* ! 6: * $Id$ ! 7: * $Source$ ! 8: * ! 9: * from the Linux kernel code base. ! 10: * orig by Ben Pfaff and Petr Vandrovec. ! 11: * ! 12: * modified by ! 13: * Steve M. Gehlbach <[email protected]> ! 14: * ! 15: * NOTE: to change the horiz and vertical pixels, ! 16: * change the xres,yres,xres_virt,yres_virt setting ! 17: * in the screeninfo structure below. You may also need ! 18: * to change the border settings as well. ! 19: * ! 20: * Convert the screeninfo structure to data for ! 21: * writing to the vga registers ! 22: * ! 23: */ ! 24: ! 25: // prototypes ! 26: static int vga_decode_var(const struct screeninfo *var, struct vga_par *par); ! 27: static int vga_set_regs(const struct vga_par *par); ! 28: ! 29: u8 read_seq_b(u16 addr) { ! 30: outb(addr,SEQ_I); ! 31: return inb(SEQ_D); ! 32: } ! 33: u8 read_gra_b(u16 addr) { ! 34: outb(addr,GRA_I); ! 35: return inb(GRA_D); ! 36: } ! 37: u8 read_crtc_b(u16 addr) { ! 38: outb(addr,CRT_IC); ! 39: return inb(CRT_DC); ! 40: } ! 41: u8 read_att_b(u16 addr) { ! 42: inb(IS1_RC); ! 43: inb(0x80); ! 44: outb(addr,ATT_IW); ! 45: return inb(ATT_R); ! 46: } ! 47: ! 48: ! 49: /* ! 50: From: The Frame Buffer Device ! 51: by Geert Uytterhoeven <[email protected]> ! 52: in the linux kernel docs. ! 53: ! 54: The following picture summarizes all timings. The horizontal retrace time is ! 55: the sum of the left margin, the right margin and the hsync length, while the ! 56: vertical retrace time is the sum of the upper margin, the lower margin and the ! 57: vsync length. ! 58: ! 59: +----------+---------------------------------------------+----------+-------+ ! 60: | | ^ | | | ! 61: | | |upper_margin | | | ! 62: | | | | | | ! 63: +----------###############################################----------+-------+ ! 64: | # ^ # | | ! 65: | # | # | | ! 66: | # | # | | ! 67: | # | # | | ! 68: | left # | # right | hsync | ! 69: | margin # | xres # margin | len | ! 70: |<-------->#<---------------+--------------------------->#<-------->|<----->| ! 71: | # | # | | ! 72: | # | # | | ! 73: | # | # | | ! 74: | # |yres # | | ! 75: | # | # | | ! 76: | # | # | | ! 77: | # | # | | ! 78: | # | # | | ! 79: | # | # | | ! 80: | # | # | | ! 81: | # | # | | ! 82: | # | # | | ! 83: | # | # | | ! 84: +----------###############################################----------+-------+ ! 85: | | ^ | | | ! 86: | | |lower_margin | | | ! 87: | | | | | | ! 88: +----------+---------------------------------------------+----------+-------+ ! 89: | | ^ | | | ! 90: | | |vsync_len | | | ! 91: | | | | | | ! 92: +----------+---------------------------------------------+----------+-------+ ! 93: ! 94: All horizontal timings are in number of dotclocks ! 95: (in picoseconds, 1E-12 s), and vertical timings in number of scanlines. ! 96: ! 97: The vga uses the following fields: ! 98: ! 99: - pixclock: pixel clock in ps (pico seconds) ! 100: - xres,yres,xres_v,yres_v ! 101: - left_margin: time from sync to picture ! 102: - right_margin: time from picture to sync ! 103: - upper_margin: time from sync to picture ! 104: - lower_margin: time from picture to sync ! 105: - hsync_len: length of horizontal sync ! 106: - vsync_len: length of vertical sync ! 107: ! 108: */ ! 109: ! 110: /* our display parameters per the above */ ! 111: ! 112: static const struct screeninfo vga_settings = { ! 113: 640,400,640,400,/* xres,yres,xres_virt,yres_virt */ ! 114: 0,0, /* xoffset,yoffset */ ! 115: 4, /* bits_per_pixel NOT USED*/ ! 116: 0, /* greyscale ? */ ! 117: {0,0,0}, /* R */ ! 118: {0,0,0}, /* G */ ! 119: {0,0,0}, /* B */ ! 120: {0,0,0}, /* transparency */ ! 121: 0, /* standard pixel format */ ! 122: 0, // activate now ! 123: -1,-1, // height and width in mm ! 124: 0, // accel flags ! 125: 39721, // pixclock: 79442 -> 12.587 Mhz (NOT USED) ! 126: // 70616 -> 14.161 ! 127: // 39721 -> 25.175 ! 128: // 35308 -> 28.322 ! 129: ! 130: 48, 16, 39, 8, // margins left,right,upper,lower ! 131: 96, // hsync length ! 132: 2, // vsync length ! 133: 0, // sync polarity ! 134: 0, // non interlaced, single mode ! 135: {0,0,0,0,0,0} // compatibility ! 136: }; ! 137: ! 138: // ALPHA-MODE ! 139: // Hard coded to BIOS VGA mode 3 (alpha color text) ! 140: // screen size settable in screeninfo structure ! 141: ! 142: static int vga_decode_var(const struct screeninfo *var, ! 143: struct vga_par *par) ! 144: { ! 145: u8 VgaAttributeTable[16] = ! 146: { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x014, 0x007, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F}; ! 147: ! 148: u32 xres, right, hslen, left, xtotal; ! 149: u32 yres, lower, vslen, upper, ytotal; ! 150: u32 vxres, xoffset, vyres, yoffset; ! 151: u32 pos; ! 152: u8 r7, rMode; ! 153: int i; ! 154: ! 155: xres = (var->xres + 7) & ~7; ! 156: vxres = (var->xres_virtual + 0xF) & ~0xF; ! 157: xoffset = (var->xoffset + 7) & ~7; ! 158: left = (var->left_margin + 7) & ~7; ! 159: right = (var->right_margin + 7) & ~7; ! 160: hslen = (var->hsync_len + 7) & ~7; ! 161: ! 162: if (vxres < xres) ! 163: vxres = xres; ! 164: if (xres + xoffset > vxres) ! 165: xoffset = vxres - xres; ! 166: ! 167: xres >>= 3; ! 168: right >>= 3; ! 169: hslen >>= 3; ! 170: left >>= 3; ! 171: vxres >>= 3; ! 172: xtotal = xres + right + hslen + left; ! 173: if (xtotal >= 256) ! 174: return VERROR; //xtotal too big ! 175: if (hslen > 32) ! 176: return VERROR; //hslen too big ! 177: if (right + hslen + left > 64) ! 178: return VERROR; //hblank too big ! 179: par->crtc[CRTC_H_TOTAL] = xtotal - 5; ! 180: par->crtc[CRTC_H_BLANK_START] = xres - 1; ! 181: par->crtc[CRTC_H_DISP] = xres - 1; ! 182: pos = xres + right; ! 183: par->crtc[CRTC_H_SYNC_START] = pos; ! 184: pos += hslen; ! 185: par->crtc[CRTC_H_SYNC_END] = (pos & 0x1F) | 0x20 ; //<--- stpc text mode p178 ! 186: pos += left - 2; /* blank_end + 2 <= total + 5 */ ! 187: par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; ! 188: if (pos & 0x20) ! 189: par->crtc[CRTC_H_SYNC_END] |= 0x80; ! 190: ! 191: yres = var->yres; ! 192: lower = var->lower_margin; ! 193: vslen = var->vsync_len; ! 194: upper = var->upper_margin; ! 195: vyres = var->yres_virtual; ! 196: yoffset = var->yoffset; ! 197: ! 198: if (yres > vyres) ! 199: vyres = yres; ! 200: if (vxres * vyres > 65536) { ! 201: vyres = 65536 / vxres; ! 202: if (vyres < yres) ! 203: return VERROR; // out of memory ! 204: } ! 205: if (yoffset + yres > vyres) ! 206: yoffset = vyres - yres; ! 207: ! 208: if (var->vmode & VMODE_DOUBLE) { ! 209: yres <<= 1; ! 210: lower <<= 1; ! 211: vslen <<= 1; ! 212: upper <<= 1; ! 213: } ! 214: ytotal = yres + lower + vslen + upper; ! 215: if (ytotal > 1024) { ! 216: ytotal >>= 1; ! 217: yres >>= 1; ! 218: lower >>= 1; ! 219: vslen >>= 1; ! 220: upper >>= 1; ! 221: rMode = 0x04; ! 222: } else ! 223: rMode = 0x00; ! 224: if (ytotal > 1024) ! 225: return VERROR; //ytotal too big ! 226: if (vslen > 16) ! 227: return VERROR; //vslen too big ! 228: par->crtc[CRTC_V_TOTAL] = ytotal - 2; ! 229: r7 = 0x10; /* disable linecompare */ ! 230: if (ytotal & 0x100) r7 |= 0x01; ! 231: if (ytotal & 0x200) r7 |= 0x20; ! 232: par->crtc[CRTC_PRESET_ROW] = 0; ! 233: ! 234: ! 235: // GMODE <--> ALPHA-MODE ! 236: // default using alpha mode so we need to set char rows= CHAR_HEIGHT-1 ! 237: par->crtc[CRTC_MAX_SCAN] = 0x40 | (CHAR_HEIGHT-1); /* 16 scanlines, linecmp max*/ ! 238: ! 239: if (var->vmode & VMODE_DOUBLE) ! 240: par->crtc[CRTC_MAX_SCAN] |= 0x80; ! 241: par->crtc[CRTC_CURSOR_START] = 0x00; // curs enabled, start line = 0 ! 242: par->crtc[CRTC_CURSOR_END] = CHAR_HEIGHT-1; // end line = 12 ! 243: pos = yoffset * vxres + (xoffset >> 3); ! 244: par->crtc[CRTC_START_HI] = pos >> 8; ! 245: par->crtc[CRTC_START_LO] = pos & 0xFF; ! 246: par->crtc[CRTC_CURSOR_HI] = 0x00; ! 247: par->crtc[CRTC_CURSOR_LO] = 0x00; ! 248: pos = yres - 1; ! 249: par->crtc[CRTC_V_DISP_END] = pos & 0xFF; ! 250: par->crtc[CRTC_V_BLANK_START] = pos & 0xFF; ! 251: if (pos & 0x100) ! 252: r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */ ! 253: if (pos & 0x200) { ! 254: r7 |= 0x40; /* 0x40 -> DISP_END */ ! 255: par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ ! 256: } ! 257: pos += lower; ! 258: par->crtc[CRTC_V_SYNC_START] = pos & 0xFF; ! 259: if (pos & 0x100) ! 260: r7 |= 0x04; ! 261: if (pos & 0x200) ! 262: r7 |= 0x80; ! 263: pos += vslen; ! 264: par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled reg write prot, IRQ */ ! 265: pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ ! 266: par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, ! 267: but some SVGA chips requires all 8 bits to set */ ! 268: if (vxres >= 512) ! 269: return VERROR; //vxres too long ! 270: par->crtc[CRTC_OFFSET] = vxres >> 1; ! 271: ! 272: // put the underline off of the character, necessary in alpha color mode ! 273: par->crtc[CRTC_UNDERLINE] = 0x1f; ! 274: ! 275: par->crtc[CRTC_MODE] = rMode | 0xA3; // word mode ! 276: par->crtc[CRTC_LINE_COMPARE] = 0xFF; ! 277: par->crtc[CRTC_OVERFLOW] = r7; ! 278: ! 279: ! 280: // not used ?? ! 281: par->vss = 0x00; /* 3DA */ ! 282: ! 283: for (i = 0x00; i < 0x10; i++) { ! 284: par->atc[i] = VgaAttributeTable[i]; ! 285: } ! 286: // GMODE <--> ALPHA-MODE ! 287: par->atc[ATC_MODE] = 0x0c; // text mode ! 288: ! 289: par->atc[ATC_OVERSCAN] = 0x00; // no border ! 290: par->atc[ATC_PLANE_ENABLE] = 0x0F; ! 291: par->atc[ATC_PEL] = xoffset & 7; ! 292: par->atc[ATC_COLOR_PAGE] = 0x00; ! 293: ! 294: par->misc = 0x67; /* enable CPU, ports 0x3Dx, positive sync*/ ! 295: if (var->sync & SYNC_HOR_HIGH_ACT) ! 296: par->misc &= ~0x40; ! 297: if (var->sync & SYNC_VERT_HIGH_ACT) ! 298: par->misc &= ~0x80; ! 299: ! 300: par->seq[SEQ_CLOCK_MODE] = 0x01; //8-bit char; 0x01=alpha mode ! 301: par->seq[SEQ_PLANE_WRITE] = 0x03; // just char/attr plane ! 302: par->seq[SEQ_CHARACTER_MAP] = 0x00; ! 303: par->seq[SEQ_MEMORY_MODE] = 0x02; // A/G bit not used in stpc; O/E on, C4 off ! 304: ! 305: par->gdc[GDC_SR_VALUE] = 0x00; ! 306: // bits set in the SR_EN regs will enable set/reset action ! 307: // based on the bit settings in the SR_VAL register ! 308: par->gdc[GDC_SR_ENABLE] = 0x00; ! 309: par->gdc[GDC_COMPARE_VALUE] = 0x00; ! 310: par->gdc[GDC_DATA_ROTATE] = 0x00; ! 311: par->gdc[GDC_PLANE_READ] = 0; ! 312: par->gdc[GDC_MODE] = 0x10; //Okay ! 313: ! 314: // GMODE <--> ALPHA-MMODE ! 315: par->gdc[GDC_MISC] = 0x0e; // b0=0 ->alpha mode; memory at 0xb8000 ! 316: ! 317: par->gdc[GDC_COMPARE_MASK] = 0x00; ! 318: par->gdc[GDC_BIT_MASK] = 0xFF; ! 319: ! 320: return 0; ! 321: } ! 322: ! 323: // ! 324: // originally from the stpc web site ! 325: // ! 326: static const unsigned char VgaLookupTable[3 * 0x3f + 3] = { ! 327: // Red Green Blue ! 328: 0x000, 0x000, 0x000, // 00h ! 329: 0x000, 0x000, 0x02A, // 01h ! 330: 0x000, 0x02A, 0x000, // 02h ! 331: 0x000, 0x02A, 0x02A, // 03h ! 332: 0x02A, 0x000, 0x000, // 04h ! 333: 0x02A, 0x000, 0x02A, // 05h ! 334: 0x02A, 0x02A, 0x000, // 06h ! 335: 0x02A, 0x02A, 0x02A, // 07h ! 336: 0x000, 0x000, 0x015, // 08h ! 337: 0x000, 0x000, 0x03F, // 09h ! 338: 0x000, 0x02A, 0x015, // 0Ah ! 339: 0x000, 0x02A, 0x03F, // 0Bh ! 340: 0x02A, 0x000, 0x015, // 0Ch ! 341: 0x02A, 0x000, 0x03F, // 0Dh ! 342: 0x02A, 0x02A, 0x015, // 0Eh ! 343: 0x02A, 0x02A, 0x03F, // 0Fh ! 344: 0x000, 0x015, 0x000, // 10h ! 345: 0x000, 0x015, 0x02A, // 11h ! 346: 0x000, 0x03F, 0x000, // 12h ! 347: 0x000, 0x03F, 0x02A, // 13h ! 348: 0x02A, 0x015, 0x000, // 14h ! 349: 0x02A, 0x015, 0x02A, // 15h ! 350: 0x02A, 0x03F, 0x000, // 16h ! 351: 0x02A, 0x03F, 0x02A, // 17h ! 352: 0x000, 0x015, 0x015, // 18h ! 353: 0x000, 0x015, 0x03F, // 19h ! 354: 0x000, 0x03F, 0x015, // 1Ah ! 355: 0x000, 0x03F, 0x03F, // 1Bh ! 356: 0x02A, 0x015, 0x015, // 1Ch ! 357: 0x02A, 0x015, 0x03F, // 1Dh ! 358: 0x02A, 0x03F, 0x015, // 1Eh ! 359: 0x02A, 0x03F, 0x03F, // 1Fh ! 360: 0x015, 0x000, 0x000, // 20h ! 361: 0x015, 0x000, 0x02A, // 21h ! 362: 0x015, 0x02A, 0x000, // 22h ! 363: 0x015, 0x02A, 0x02A, // 23h ! 364: 0x03F, 0x000, 0x000, // 24h ! 365: 0x03F, 0x000, 0x02A, // 25h ! 366: 0x03F, 0x02A, 0x000, // 26h ! 367: 0x03F, 0x02A, 0x02A, // 27h ! 368: 0x015, 0x000, 0x015, // 28h ! 369: 0x015, 0x000, 0x03F, // 29h ! 370: 0x015, 0x02A, 0x015, // 2Ah ! 371: 0x015, 0x02A, 0x03F, // 2Bh ! 372: 0x03F, 0x000, 0x015, // 2Ch ! 373: 0x03F, 0x000, 0x03F, // 2Dh ! 374: 0x03F, 0x02A, 0x015, // 2Eh ! 375: 0x03F, 0x02A, 0x03F, // 2Fh ! 376: 0x015, 0x015, 0x000, // 30h ! 377: 0x015, 0x015, 0x02A, // 31h ! 378: 0x015, 0x03F, 0x000, // 32h ! 379: 0x015, 0x03F, 0x02A, // 33h ! 380: 0x03F, 0x015, 0x000, // 34h ! 381: 0x03F, 0x015, 0x02A, // 35h ! 382: 0x03F, 0x03F, 0x000, // 36h ! 383: 0x03F, 0x03F, 0x02A, // 37h ! 384: 0x015, 0x015, 0x015, // 38h ! 385: 0x015, 0x015, 0x03F, // 39h ! 386: 0x015, 0x03F, 0x015, // 3Ah ! 387: 0x015, 0x03F, 0x03F, // 3Bh ! 388: 0x03F, 0x015, 0x015, // 3Ch ! 389: 0x03F, 0x015, 0x03F, // 3Dh ! 390: 0x03F, 0x03F, 0x015, // 3Eh ! 391: 0x03F, 0x03F, 0x03F, // 3Fh ! 392: }; ! 393: ! 394: /* ! 395: * From the Linux kernel. ! 396: * orig by Ben Pfaff and Petr Vandrovec. ! 397: * see the note in the vga.h for attribution. ! 398: * ! 399: * modified by ! 400: * Steve M. Gehlbach <[email protected]> ! 401: * for the linuxbios project ! 402: * ! 403: * Write the data in the vga parameter structure ! 404: * to the vga registers, along with other default ! 405: * settings. ! 406: * ! 407: */ ! 408: static int vga_set_regs(const struct vga_par *par) ! 409: { ! 410: int i; ! 411: ! 412: /* update misc output register */ ! 413: outb(par->misc, MIS_W); ! 414: ! 415: /* synchronous reset on */ ! 416: outb(0x00, SEQ_I); ! 417: outb(0x00, SEQ_D); ! 418: ! 419: /* write sequencer registers */ ! 420: outb(1, SEQ_I); ! 421: outb(par->seq[1] | 0x20, SEQ_D); // blank display ! 422: for (i = 2; i < SEQ_C; i++) { ! 423: outb(i, SEQ_I); ! 424: outb(par->seq[i], SEQ_D); ! 425: } ! 426: ! 427: /* synchronous reset off */ ! 428: outb(0x00, SEQ_I); ! 429: outb(0x03, SEQ_D); ! 430: ! 431: /* deprotect CRT registers 0-7 */ ! 432: outb(0x11, CRT_IC); ! 433: outb(par->crtc[0x11], CRT_DC); ! 434: ! 435: /* write CRT registers */ ! 436: for (i = 0; i < CRTC_C; i++) { ! 437: outb(i, CRT_IC); ! 438: outb(par->crtc[i], CRT_DC); ! 439: } ! 440: /* write graphics controller registers */ ! 441: for (i = 0; i < GRA_C; i++) { ! 442: outb(i, GRA_I); ! 443: outb(par->gdc[i], GRA_D); ! 444: } ! 445: ! 446: /* write attribute controller registers */ ! 447: for (i = 0; i < ATT_C; i++) { ! 448: inb(IS1_RC); /* reset flip-flop */ ! 449: inb(0x80); //delay ! 450: outb(i, ATT_IW); ! 451: inb(0x80); //delay ! 452: ! 453: outb(par->atc[i], ATT_IW); ! 454: inb(0x80); //delay ! 455: } ! 456: ! 457: // initialize the color table ! 458: outb(0, PEL_IW); ! 459: i = 0; ! 460: // length is a magic number right now ! 461: while ( i < (0x3f*3 + 3) ) { ! 462: outb(VgaLookupTable[i++], PEL_D); ! 463: outb(VgaLookupTable[i++], PEL_D); ! 464: outb(VgaLookupTable[i++], PEL_D); ! 465: } ! 466: ! 467: outb(0x0ff, PEL_MSK); // palette mask ! 468: ! 469: // very important ! 470: // turn on video, disable palette access ! 471: inb(IS1_RC); /* reset flip-flop */ ! 472: inb(0x80); //delay ! 473: outb(0x20, ATT_IW); ! 474: ! 475: /* Wait for screen to stabilize. */ ! 476: //for(i=0;i<1000;i++) { inb(0x80); } ! 477: ! 478: outb(0x01, SEQ_I); // unblank display ! 479: outb(par->seq[1], SEQ_D); ! 480: ! 481: // turn on display, disable access to attr palette ! 482: inb(IS1_RC); ! 483: outb(0x20, ATT_IW); ! 484: ! 485: return 0; ! 486: } ! 487: ! 488: void ! 489: vga_load_regs(void) ! 490: { ! 491: struct vga_par par; ! 492: ! 493: if (vga_decode_var(&vga_settings, &par) == 0) { ! 494: vga_set_regs(&par); ! 495: } ! 496: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.