Annotation of qemu/roms/openbios/drivers/vga_load_regs.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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