Annotation of qemu/roms/SLOF/clients/net-snk/app/biosemu/vbe.c, revision 1.1.1.2

1.1       root        1: /******************************************************************************
                      2:  * Copyright (c) 2004, 2008 IBM Corporation
                      3:  * All rights reserved.
                      4:  * This program and the accompanying materials
                      5:  * are made available under the terms of the BSD License
                      6:  * which accompanies this distribution, and is available at
                      7:  * http://www.opensource.org/licenses/bsd-license.php
                      8:  *
                      9:  * Contributors:
                     10:  *     IBM Corporation - initial implementation
                     11:  *****************************************************************************/
                     12: 
                     13: #include <stdio.h>
                     14: #include <stdlib.h>
                     15: #include <string.h>
                     16: 
                     17: #include <stdint.h>
                     18: #include <cpu.h>
                     19: 
                     20: #include "debug.h"
                     21: 
                     22: #include <x86emu/x86emu.h>
                     23: #include <x86emu/regs.h>
                     24: #include <x86emu/prim_ops.h>   // for push_word
                     25: 
                     26: #include "biosemu.h"
                     27: #include "io.h"
                     28: #include "mem.h"
                     29: #include "interrupt.h"
                     30: #include "device.h"
                     31: 
                     32: static X86EMU_memFuncs my_mem_funcs = {
                     33:        my_rdb, my_rdw, my_rdl,
                     34:        my_wrb, my_wrw, my_wrl
                     35: };
                     36: 
                     37: static X86EMU_pioFuncs my_pio_funcs = {
                     38:        my_inb, my_inw, my_inl,
                     39:        my_outb, my_outw, my_outl
                     40: };
                     41: 
                     42: // pointer to VBEInfoBuffer, set by vbe_prepare
                     43: uint8_t *vbe_info_buffer = 0;
                     44: // virtual BIOS Memory
                     45: uint8_t *biosmem;
                     46: uint32_t biosmem_size;
                     47: 
                     48: // these structs are for input from and output to OF
                     49: typedef struct {
                     50:        uint8_t display_type;   // 0=NONE, 1= analog, 2=digital
                     51:        uint16_t screen_width;
                     52:        uint16_t screen_height;
                     53:        uint16_t screen_linebytes;      // bytes per line in framebuffer, may be more than screen_width
                     54:        uint8_t color_depth;    // color depth in bpp
                     55:        uint32_t framebuffer_address;
                     56:        uint8_t edid_block_zero[128];
                     57: } __attribute__ ((__packed__)) screen_info_t;
                     58: 
                     59: typedef struct {
                     60:        uint8_t signature[4];
                     61:        uint16_t size_reserved;
                     62:        uint8_t monitor_number;
                     63:        uint16_t max_screen_width;
                     64:        uint8_t color_depth;
                     65: } __attribute__ ((__packed__)) screen_info_input_t;
                     66: 
                     67: // these structs only store a subset of the VBE defined fields
                     68: // only those needed.
                     69: typedef struct {
                     70:        char signature[4];
                     71:        uint16_t version;
                     72:        uint8_t *oem_string_ptr;
                     73:        uint32_t capabilities;
                     74:        uint16_t video_mode_list[256];  // lets hope we never have more than 256 video modes...
                     75:        uint16_t total_memory;
                     76: } vbe_info_t;
                     77: 
                     78: typedef struct {
                     79:        uint16_t video_mode;
                     80:        uint8_t mode_info_block[256];
                     81:        uint16_t attributes;
                     82:        uint16_t linebytes;
                     83:        uint16_t x_resolution;
                     84:        uint16_t y_resolution;
                     85:        uint8_t x_charsize;
                     86:        uint8_t y_charsize;
                     87:        uint8_t bits_per_pixel;
                     88:        uint8_t memory_model;
                     89:        uint32_t framebuffer_address;
                     90: } vbe_mode_info_t;
                     91: 
                     92: typedef struct {
                     93:        uint8_t port_number;    // i.e. monitor number
                     94:        uint8_t edid_transfer_time;
                     95:        uint8_t ddc_level;
                     96:        uint8_t edid_block_zero[128];
                     97: } vbe_ddc_info_t;
                     98: 
                     99: static inline uint8_t
                    100: vbe_prepare()
                    101: {
                    102:        vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area
                    103:        //clear buffer
                    104:        memset(vbe_info_buffer, 0, 512);
                    105:        //set VbeSignature to "VBE2" to indicate VBE 2.0+ request
                    106:        vbe_info_buffer[0] = 'V';
                    107:        vbe_info_buffer[0] = 'B';
                    108:        vbe_info_buffer[0] = 'E';
                    109:        vbe_info_buffer[0] = '2';
                    110:        // ES:DI store pointer to buffer in virtual mem see vbe_info_buffer above...
                    111:        M.x86.R_EDI = 0x0;
                    112:        M.x86.R_ES = VBE_SEGMENT;
                    113: 
                    114:        return 0;               // successfull init
                    115: }
                    116: 
                    117: // VBE Function 00h
                    118: uint8_t
                    119: vbe_info(vbe_info_t * info)
                    120: {
                    121:        vbe_prepare();
                    122:        // call VBE function 00h (Info Function)
                    123:        M.x86.R_EAX = 0x4f00;
                    124: 
                    125:        // enable trace
                    126:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    127:                X86EMU_trace_on();
                    128:        }
                    129:        // run VESA Interrupt
                    130:        runInt10();
                    131: 
                    132:        if (M.x86.R_AL != 0x4f) {
                    133:                DEBUG_PRINTF_VBE("%s: VBE Info Function NOT supported! AL=%x\n",
                    134:                                 __FUNCTION__, M.x86.R_AL);
                    135:                return -1;
                    136:        }
                    137: 
                    138:        if (M.x86.R_AH != 0x0) {
                    139:                DEBUG_PRINTF_VBE
                    140:                    ("%s: VBE Info Function Return Code NOT OK! AH=%x\n",
                    141:                     __FUNCTION__, M.x86.R_AH);
                    142:                return M.x86.R_AH;
                    143:        }
                    144:        //printf("VBE Info Dump:");
                    145:        //dump(vbe_info_buffer, 64);
                    146: 
                    147:        //offset 0: signature
                    148:        info->signature[0] = vbe_info_buffer[0];
                    149:        info->signature[1] = vbe_info_buffer[1];
                    150:        info->signature[2] = vbe_info_buffer[2];
                    151:        info->signature[3] = vbe_info_buffer[3];
                    152: 
                    153:        // offset 4: 16bit le containing VbeVersion
                    154:        info->version = in16le(vbe_info_buffer + 4);
                    155: 
                    156:        // offset 6: 32bit le containg segment:offset of OEM String in virtual Mem.
                    157:        info->oem_string_ptr =
                    158:            biosmem + ((in16le(vbe_info_buffer + 8) << 4) +
                    159:                       in16le(vbe_info_buffer + 6));
                    160: 
                    161:        // offset 10: 32bit le capabilities
                    162:        info->capabilities = in32le(vbe_info_buffer + 10);
                    163: 
                    164:        // offset 14: 32 bit le containing segment:offset of supported video mode table
                    165:        uint16_t *video_mode_ptr;
                    166:        video_mode_ptr =
                    167:            (uint16_t *) (biosmem +
                    168:                          ((in16le(vbe_info_buffer + 16) << 4) +
                    169:                           in16le(vbe_info_buffer + 14)));
                    170:        uint32_t i = 0;
                    171:        do {
                    172:                info->video_mode_list[i] = in16le(video_mode_ptr + i);
                    173:                i++;
                    174:        }
                    175:        while ((i <
                    176:                (sizeof(info->video_mode_list) /
                    177:                 sizeof(info->video_mode_list[0])))
                    178:               && (info->video_mode_list[i - 1] != 0xFFFF));
                    179: 
                    180:        //offset 18: 16bit le total memory in 64KB blocks
                    181:        info->total_memory = in16le(vbe_info_buffer + 18);
                    182: 
                    183:        return 0;
                    184: }
                    185: 
                    186: // VBE Function 01h
                    187: uint8_t
                    188: vbe_get_mode_info(vbe_mode_info_t * mode_info)
                    189: {
                    190:        vbe_prepare();
                    191:        // call VBE function 01h (Return VBE Mode Info Function)
                    192:        M.x86.R_EAX = 0x4f01;
                    193:        M.x86.R_CX = mode_info->video_mode;
                    194: 
                    195:        // enable trace
                    196:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    197:                X86EMU_trace_on();
                    198:        }
                    199:        // run VESA Interrupt
                    200:        runInt10();
                    201: 
                    202:        if (M.x86.R_AL != 0x4f) {
                    203:                DEBUG_PRINTF_VBE
                    204:                    ("%s: VBE Return Mode Info Function NOT supported! AL=%x\n",
                    205:                     __FUNCTION__, M.x86.R_AL);
                    206:                return -1;
                    207:        }
                    208: 
                    209:        if (M.x86.R_AH != 0x0) {
                    210:                DEBUG_PRINTF_VBE
                    211:                    ("%s: VBE Return Mode Info (mode: %04x) Function Return Code NOT OK! AH=%02x\n",
                    212:                     __FUNCTION__, mode_info->video_mode, M.x86.R_AH);
                    213:                return M.x86.R_AH;
                    214:        }
                    215:        //pointer to mode_info_block is in ES:DI
                    216:        memcpy(mode_info->mode_info_block,
                    217:               biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI),
                    218:               sizeof(mode_info->mode_info_block));
                    219: 
                    220:        //printf("Mode Info Dump:");
                    221:        //dump(mode_info_block, 64);
                    222: 
                    223:        // offset 0: 16bit le mode attributes
                    224:        mode_info->attributes = in16le(mode_info->mode_info_block);
                    225: 
                    226:        // offset 16: 16bit le bytes per scan line
                    227:        mode_info->linebytes = in16le(mode_info->mode_info_block + 16);
                    228: 
                    229:        // offset 18: 16bit le x resolution
                    230:        mode_info->x_resolution = in16le(mode_info->mode_info_block + 18);
                    231: 
                    232:        // offset 20: 16bit le y resolution
                    233:        mode_info->y_resolution = in16le(mode_info->mode_info_block + 20);
                    234: 
                    235:        // offset 22: 8bit le x charsize
                    236:        mode_info->x_charsize = *(mode_info->mode_info_block + 22);
                    237: 
                    238:        // offset 23: 8bit le y charsize
                    239:        mode_info->y_charsize = *(mode_info->mode_info_block + 23);
                    240: 
                    241:        // offset 25: 8bit le bits per pixel
                    242:        mode_info->bits_per_pixel = *(mode_info->mode_info_block + 25);
                    243: 
                    244:        // offset 27: 8bit le memory model
                    245:        mode_info->memory_model = *(mode_info->mode_info_block + 27);
                    246: 
                    247:        // offset 40: 32bit le containg offset of frame buffer memory ptr
                    248:        mode_info->framebuffer_address =
                    249:            in32le(mode_info->mode_info_block + 40);
                    250: 
                    251:        return 0;
                    252: }
                    253: 
                    254: // VBE Function 02h
                    255: uint8_t
                    256: vbe_set_mode(vbe_mode_info_t * mode_info)
                    257: {
                    258:        vbe_prepare();
                    259:        // call VBE function 02h (Set VBE Mode Function)
                    260:        M.x86.R_EAX = 0x4f02;
                    261:        M.x86.R_BX = mode_info->video_mode;
                    262:        M.x86.R_BX |= 0x4000;   // set bit 14 to request linear framebuffer mode
                    263:        M.x86.R_BX &= 0x7FFF;   // clear bit 15 to request clearing of framebuffer
                    264: 
                    265:        DEBUG_PRINTF_VBE("%s: setting mode: 0x%04x\n", __FUNCTION__,
                    266:                         M.x86.R_BX);
                    267: 
                    268:        // enable trace
                    269:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    270:                X86EMU_trace_on();
                    271:        }
                    272:        // run VESA Interrupt
                    273:        runInt10();
                    274: 
                    275:        if (M.x86.R_AL != 0x4f) {
                    276:                DEBUG_PRINTF_VBE
                    277:                    ("%s: VBE Set Mode Function NOT supported! AL=%x\n",
                    278:                     __FUNCTION__, M.x86.R_AL);
                    279:                return -1;
                    280:        }
                    281: 
                    282:        if (M.x86.R_AH != 0x0) {
                    283:                DEBUG_PRINTF_VBE
                    284:                    ("%s: mode: %x VBE Set Mode Function Return Code NOT OK! AH=%x\n",
                    285:                     __FUNCTION__, mode_info->video_mode, M.x86.R_AH);
                    286:                return M.x86.R_AH;
                    287:        }
                    288:        return 0;
                    289: }
                    290: 
                    291: //VBE Function 08h
                    292: uint8_t
                    293: vbe_set_palette_format(uint8_t format)
                    294: {
                    295:        vbe_prepare();
                    296:        // call VBE function 09h (Set/Get Palette Data Function)
                    297:        M.x86.R_EAX = 0x4f08;
                    298:        M.x86.R_BL = 0x00;      // set format
                    299:        M.x86.R_BH = format;
                    300: 
                    301:        DEBUG_PRINTF_VBE("%s: setting palette format: %d\n", __FUNCTION__,
                    302:                         format);
                    303: 
                    304:        // enable trace
                    305:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    306:                X86EMU_trace_on();
                    307:        }
                    308:        // run VESA Interrupt
                    309:        runInt10();
                    310: 
                    311:        if (M.x86.R_AL != 0x4f) {
                    312:                DEBUG_PRINTF_VBE
                    313:                    ("%s: VBE Set Palette Format Function NOT supported! AL=%x\n",
                    314:                     __FUNCTION__, M.x86.R_AL);
                    315:                return -1;
                    316:        }
                    317: 
                    318:        if (M.x86.R_AH != 0x0) {
                    319:                DEBUG_PRINTF_VBE
                    320:                    ("%s: VBE Set Palette Format Function Return Code NOT OK! AH=%x\n",
                    321:                     __FUNCTION__, M.x86.R_AH);
                    322:                return M.x86.R_AH;
                    323:        }
                    324:        return 0;
                    325: }
                    326: 
                    327: // VBE Function 09h
                    328: uint8_t
                    329: vbe_set_color(uint16_t color_number, uint32_t color_value)
                    330: {
                    331:        vbe_prepare();
                    332:        // call VBE function 09h (Set/Get Palette Data Function)
                    333:        M.x86.R_EAX = 0x4f09;
                    334:        M.x86.R_BL = 0x00;      // set color
                    335:        M.x86.R_CX = 0x01;      // set only one entry
                    336:        M.x86.R_DX = color_number;
                    337:        // ES:DI is address where color_value is stored, we store it at 2000:0000
                    338:        M.x86.R_ES = 0x2000;
                    339:        M.x86.R_DI = 0x0;
                    340: 
                    341:        // store color value at ES:DI
                    342:        out32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, color_value);
                    343: 
                    344:        DEBUG_PRINTF_VBE("%s: setting color #%x: 0x%04x\n", __FUNCTION__,
                    345:                         color_number, color_value);
                    346: 
                    347:        // enable trace
                    348:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    349:                X86EMU_trace_on();
                    350:        }
                    351:        // run VESA Interrupt
                    352:        runInt10();
                    353: 
                    354:        if (M.x86.R_AL != 0x4f) {
                    355:                DEBUG_PRINTF_VBE
                    356:                    ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
                    357:                     __FUNCTION__, M.x86.R_AL);
                    358:                return -1;
                    359:        }
                    360: 
                    361:        if (M.x86.R_AH != 0x0) {
                    362:                DEBUG_PRINTF_VBE
                    363:                    ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
                    364:                     __FUNCTION__, M.x86.R_AH);
                    365:                return M.x86.R_AH;
                    366:        }
                    367:        return 0;
                    368: }
                    369: 
                    370: uint8_t
                    371: vbe_get_color(uint16_t color_number, uint32_t * color_value)
                    372: {
                    373:        vbe_prepare();
                    374:        // call VBE function 09h (Set/Get Palette Data Function)
                    375:        M.x86.R_EAX = 0x4f09;
                    376:        M.x86.R_BL = 0x00;      // get color
                    377:        M.x86.R_CX = 0x01;      // get only one entry
                    378:        M.x86.R_DX = color_number;
                    379:        // ES:DI is address where color_value is stored, we store it at 2000:0000
                    380:        M.x86.R_ES = 0x2000;
                    381:        M.x86.R_DI = 0x0;
                    382: 
                    383:        // enable trace
                    384:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    385:                X86EMU_trace_on();
                    386:        }
                    387:        // run VESA Interrupt
                    388:        runInt10();
                    389: 
                    390:        if (M.x86.R_AL != 0x4f) {
                    391:                DEBUG_PRINTF_VBE
                    392:                    ("%s: VBE Set Palette Function NOT supported! AL=%x\n",
                    393:                     __FUNCTION__, M.x86.R_AL);
                    394:                return -1;
                    395:        }
                    396: 
                    397:        if (M.x86.R_AH != 0x0) {
                    398:                DEBUG_PRINTF_VBE
                    399:                    ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n",
                    400:                     __FUNCTION__, M.x86.R_AH);
                    401:                return M.x86.R_AH;
                    402:        }
                    403:        // read color value from ES:DI
                    404:        *color_value = in32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI);
                    405: 
                    406:        DEBUG_PRINTF_VBE("%s: getting color #%x --> 0x%04x\n", __FUNCTION__,
                    407:                         color_number, *color_value);
                    408: 
                    409:        return 0;
                    410: }
                    411: 
                    412: // VBE Function 15h
                    413: uint8_t
                    414: vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
                    415: {
                    416:        vbe_prepare();
                    417:        // call VBE function 15h (DDC Info Function)
                    418:        M.x86.R_EAX = 0x4f15;
                    419:        M.x86.R_BL = 0x00;      // get DDC Info
                    420:        M.x86.R_CX = ddc_info->port_number;
                    421:        M.x86.R_ES = 0x0;
                    422:        M.x86.R_DI = 0x0;
                    423: 
                    424:        // enable trace
                    425:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    426:                X86EMU_trace_on();
                    427:        }
                    428:        // run VESA Interrupt
                    429:        runInt10();
                    430: 
                    431:        if (M.x86.R_AL != 0x4f) {
                    432:                DEBUG_PRINTF_VBE
                    433:                    ("%s: VBE Get DDC Info Function NOT supported! AL=%x\n",
                    434:                     __FUNCTION__, M.x86.R_AL);
                    435:                return -1;
                    436:        }
                    437: 
                    438:        if (M.x86.R_AH != 0x0) {
                    439:                DEBUG_PRINTF_VBE
                    440:                    ("%s: port: %x VBE Get DDC Info Function Return Code NOT OK! AH=%x\n",
                    441:                     __FUNCTION__, ddc_info->port_number, M.x86.R_AH);
                    442:                return M.x86.R_AH;
                    443:        }
                    444:        // BH = approx. time in seconds to transfer one EDID block
                    445:        ddc_info->edid_transfer_time = M.x86.R_BH;
                    446:        // BL = DDC Level
                    447:        ddc_info->ddc_level = M.x86.R_BL;
                    448: 
                    449:        vbe_prepare();
                    450:        // call VBE function 15h (DDC Info Function)
                    451:        M.x86.R_EAX = 0x4f15;
                    452:        M.x86.R_BL = 0x01;      // read EDID
                    453:        M.x86.R_CX = ddc_info->port_number;
                    454:        M.x86.R_DX = 0x0;       // block number
                    455:        // ES:DI is address where EDID is stored, we store it at 2000:0000
                    456:        M.x86.R_ES = 0x2000;
                    457:        M.x86.R_DI = 0x0;
                    458: 
                    459:        // enable trace
                    460:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    461:                X86EMU_trace_on();
                    462:        }
                    463:        // run VESA Interrupt
                    464:        runInt10();
                    465: 
                    466:        if (M.x86.R_AL != 0x4f) {
                    467:                DEBUG_PRINTF_VBE
                    468:                    ("%s: VBE Read EDID Function NOT supported! AL=%x\n",
                    469:                     __FUNCTION__, M.x86.R_AL);
                    470:                return -1;
                    471:        }
                    472: 
                    473:        if (M.x86.R_AH != 0x0) {
                    474:                DEBUG_PRINTF_VBE
                    475:                    ("%s: port: %x VBE Read EDID Function Return Code NOT OK! AH=%x\n",
                    476:                     __FUNCTION__, ddc_info->port_number, M.x86.R_AH);
                    477:                return M.x86.R_AH;
                    478:        }
                    479: 
                    480:        memcpy(ddc_info->edid_block_zero,
                    481:               biosmem + (M.x86.R_ES << 4) + M.x86.R_DI,
                    482:               sizeof(ddc_info->edid_block_zero));
                    483: 
                    484:        return 0;
                    485: }
                    486: 
                    487: uint32_t
                    488: vbe_get_info(uint8_t argc, char ** argv)
                    489: {
                    490:        uint8_t rval;
1.1.1.2 ! root      491:        static const uint8_t valid_edid_sig[] = {
        !           492:                0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
        !           493:        };
1.1       root      494:        uint32_t i;
1.1.1.2 ! root      495: 
1.1       root      496:        if (argc < 4) {
                    497:                printf
                    498:                    ("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n",
                    499:                     argv[0]);
                    500:                int i = 0;
                    501:                for (i = 0; i < argc; i++) {
                    502:                        printf("argv[%d]: %s\n", i, argv[i]);
                    503:                }
                    504:                return -1;
                    505:        }
                    506:        // get a copy of input struct...
                    507:        screen_info_input_t input =
                    508:            *((screen_info_input_t *) strtoul((char *) argv[4], 0, 16));
                    509:        // output is pointer to the address passed as argv[4]
                    510:        screen_info_t *output =
                    511:            (screen_info_t *) strtoul((char *) argv[4], 0, 16);
                    512:        // zero output
                    513:        memset(output, 0, sizeof(screen_info_t));
                    514: 
                    515:        // argv[1] is address of virtual BIOS mem...
                    516:        // argv[2] is the size
                    517:        biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
                    518:        biosmem_size = strtoul(argv[2], 0, 16);;
                    519:        if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
                    520:                printf("Error: Not enough virtual memory: %x, required: %x!\n",
                    521:                       biosmem_size, MIN_REQUIRED_VMEM_SIZE);
                    522:                return -1;
                    523:        }
                    524:        // argv[3] is the device to open and use...
                    525:        if (dev_init((char *) argv[3]) != 0) {
                    526:                printf("Error initializing device!\n");
                    527:                return -1;
                    528:        }
                    529:        //setup interrupt handler
                    530:        X86EMU_intrFuncs intrFuncs[256];
                    531:        for (i = 0; i < 256; i++)
                    532:                intrFuncs[i] = handleInterrupt;
                    533:        X86EMU_setupIntrFuncs(intrFuncs);
                    534:        X86EMU_setupPioFuncs(&my_pio_funcs);
                    535:        X86EMU_setupMemFuncs(&my_mem_funcs);
                    536: 
                    537:        // set mem_base
                    538:        M.mem_base = (long) biosmem;
                    539:        M.mem_size = biosmem_size;
                    540:        DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base,
                    541:                         (int) M.mem_size);
                    542: 
                    543:        vbe_info_t info;
                    544:        rval = vbe_info(&info);
                    545:        if (rval != 0)
                    546:                return rval;
                    547: 
                    548:        DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
                    549:        DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
                    550:        DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
                    551:        DEBUG_PRINTF_VBE("Capabilities:\n");
                    552:        DEBUG_PRINTF_VBE("\tDAC: %s\n",
                    553:                         (info.capabilities & 0x1) ==
                    554:                         0 ? "fixed 6bit" : "switchable 6/8bit");
                    555:        DEBUG_PRINTF_VBE("\tVGA: %s\n",
                    556:                         (info.capabilities & 0x2) ==
                    557:                         0 ? "compatible" : "not compatible");
                    558:        DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
                    559:                         (info.capabilities & 0x4) ==
                    560:                         0 ? "normal" : "use blank bit in Function 09h");
                    561: 
                    562:        // argv[4] may be a pointer with enough space to return screen_info_t
                    563:        // as input, it must contain a screen_info_input_t with the following content:
                    564:        // byte[0:3] = "DDC\0" (zero-terminated signature header)
                    565:        // byte[4:5] = reserved space for the return struct... just in case we ever change
                    566:        //             the struct and dont have reserved enough memory (and let's hope the struct
                    567:        //             never gets larger than 64KB)
                    568:        // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors...
                    569:        // byte[7:8] = max. screen width (OF may want to limit this)
                    570:        // byte[9] = required color depth in bpp
                    571:        if (strncmp((char *) input.signature, "DDC", 4) != 0) {
                    572:                printf
                    573:                    ("%s: Invalid input signature! expected: %s, is: %s\n",
                    574:                     __FUNCTION__, "DDC", input.signature);
                    575:                return -1;
                    576:        }
                    577:        if (input.size_reserved != sizeof(screen_info_t)) {
                    578:                printf
                    579:                    ("%s: Size of return struct is wrong, required: %d, available: %d\n",
                    580:                     __FUNCTION__, (int) sizeof(screen_info_t),
                    581:                     input.size_reserved);
                    582:                return -1;
                    583:        }
                    584: 
                    585:        vbe_ddc_info_t ddc_info;
                    586:        ddc_info.port_number = input.monitor_number;
                    587:        vbe_get_ddc_info(&ddc_info);
                    588: 
                    589: #if 0
                    590:        DEBUG_PRINTF_VBE("DDC: edid_tranfer_time: %d\n",
                    591:                         ddc_info.edid_transfer_time);
                    592:        DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level);
                    593:        DEBUG_PRINTF_VBE("DDC: EDID: \n");
                    594:        CHECK_DBG(DEBUG_VBE) {
                    595:                dump(ddc_info.edid_block_zero,
                    596:                     sizeof(ddc_info.edid_block_zero));
                    597:        }
                    598: #endif
1.1.1.2 ! root      599:        if (memcmp(ddc_info.edid_block_zero, valid_edid_sig, 8) != 0) {
1.1       root      600:                // invalid EDID signature... probably no monitor
                    601:                output->display_type = 0x0;
                    602:                return 0;
                    603:        } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) {
                    604:                // digital display
                    605:                output->display_type = 2;
                    606:        } else {
                    607:                // analog
                    608:                output->display_type = 1;
                    609:        }
                    610:        DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type);
                    611:        memcpy(output->edid_block_zero, ddc_info.edid_block_zero,
                    612:               sizeof(ddc_info.edid_block_zero));
                    613:        i = 0;
                    614:        vbe_mode_info_t mode_info;
                    615:        vbe_mode_info_t best_mode_info;
                    616:        // initialize best_mode to 0
                    617:        memset(&best_mode_info, 0, sizeof(best_mode_info));
                    618:        while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) {
                    619:                //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode);
                    620:                vbe_get_mode_info(&mode_info);
                    621: #if 0
                    622:                DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n",
                    623:                                 mode_info.video_mode,
                    624:                                 (mode_info.attributes & 0x1) ==
                    625:                                 0 ? "not supported" : "supported");
                    626:                DEBUG_PRINTF_VBE("\tTTY: %s\n",
                    627:                                 (mode_info.attributes & 0x4) ==
                    628:                                 0 ? "no" : "yes");
                    629:                DEBUG_PRINTF_VBE("\tMode: %s %s\n",
                    630:                                 (mode_info.attributes & 0x8) ==
                    631:                                 0 ? "monochrome" : "color",
                    632:                                 (mode_info.attributes & 0x10) ==
                    633:                                 0 ? "text" : "graphics");
                    634:                DEBUG_PRINTF_VBE("\tVGA: %s\n",
                    635:                                 (mode_info.attributes & 0x20) ==
                    636:                                 0 ? "compatible" : "not compatible");
                    637:                DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n",
                    638:                                 (mode_info.attributes & 0x40) ==
                    639:                                 0 ? "yes" : "no");
                    640:                DEBUG_PRINTF_VBE("\tFramebuffer: %s\n",
                    641:                                 (mode_info.attributes & 0x80) ==
                    642:                                 0 ? "no" : "yes");
                    643:                DEBUG_PRINTF_VBE("\tResolution: %dx%d\n",
                    644:                                 mode_info.x_resolution,
                    645:                                 mode_info.y_resolution);
                    646:                DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n",
                    647:                                 mode_info.x_charsize, mode_info.y_charsize);
                    648:                DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n",
                    649:                                 mode_info.bits_per_pixel);
                    650:                DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n",
                    651:                                 mode_info.memory_model);
                    652:                DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n",
                    653:                                 mode_info.framebuffer_address);
                    654: #endif
                    655:                if ((mode_info.bits_per_pixel == input.color_depth)
                    656:                    && (mode_info.x_resolution <= input.max_screen_width)
                    657:                    && ((mode_info.attributes & 0x80) != 0)     // framebuffer mode
                    658:                    && ((mode_info.attributes & 0x10) != 0)     // graphics
                    659:                    && ((mode_info.attributes & 0x8) != 0)      // color
                    660:                    && (mode_info.x_resolution > best_mode_info.x_resolution))  // better than previous best_mode
                    661:                {
                    662:                        // yiiiihaah... we found a new best mode
                    663:                        memcpy(&best_mode_info, &mode_info, sizeof(mode_info));
                    664:                }
                    665:                i++;
                    666:        }
                    667: 
                    668:        if (best_mode_info.video_mode != 0) {
                    669:                DEBUG_PRINTF_VBE
                    670:                    ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n",
                    671:                     best_mode_info.video_mode,
                    672:                     best_mode_info.x_resolution,
                    673:                     best_mode_info.y_resolution,
                    674:                     best_mode_info.bits_per_pixel,
                    675:                     best_mode_info.framebuffer_address);
                    676: 
                    677:                //printf("Mode Info Dump:");
                    678:                //dump(best_mode_info.mode_info_block, 64);
                    679: 
                    680:                // set the video mode
                    681:                vbe_set_mode(&best_mode_info);
                    682: 
                    683:                if ((info.capabilities & 0x1) != 0) {
                    684:                        // switch to 8 bit palette format
                    685:                        vbe_set_palette_format(8);
                    686:                }
                    687:                // setup a palette:
                    688:                // - first 216 colors are mixed colors for each component in 6 steps
                    689:                //   (6*6*6=216)
                    690:                // - then 10 shades of the three primary colors
                    691:                // - then 10 shades of grey
                    692:                // -------
                    693:                // = 256 colors
                    694:                //
                    695:                // - finally black is color 0 and white color FF (because SLOF expects it
                    696:                //   this way...)
                    697:                // this resembles the palette that the kernel/X Server seems to expect...
                    698: 
                    699:                uint8_t mixed_color_values[6] =
                    700:                    { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 };
                    701:                uint8_t primary_color_values[10] =
                    702:                    { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F,
                    703:                        0x27
                    704:                };
                    705:                uint8_t mc_size = sizeof(mixed_color_values);
                    706:                uint8_t prim_size = sizeof(primary_color_values);
                    707: 
                    708:                uint8_t curr_color_index;
                    709:                uint32_t curr_color;
                    710: 
                    711:                uint8_t r, g, b;
                    712:                // 216 mixed colors
                    713:                for (r = 0; r < mc_size; r++) {
                    714:                        for (g = 0; g < mc_size; g++) {
                    715:                                for (b = 0; b < mc_size; b++) {
                    716:                                        curr_color_index =
                    717:                                            (r * mc_size * mc_size) +
                    718:                                            (g * mc_size) + b;
                    719:                                        curr_color = 0;
                    720:                                        curr_color |= ((uint32_t) mixed_color_values[r]) << 16; //red value
                    721:                                        curr_color |= ((uint32_t) mixed_color_values[g]) << 8;  //green value
                    722:                                        curr_color |= (uint32_t) mixed_color_values[b]; //blue value
                    723:                                        vbe_set_color(curr_color_index,
                    724:                                                      curr_color);
                    725:                                }
                    726:                        }
                    727:                }
                    728: 
                    729:                // 10 shades of each primary color
                    730:                // red
                    731:                for (r = 0; r < prim_size; r++) {
                    732:                        curr_color_index = mc_size * mc_size * mc_size + r;
                    733:                        curr_color = ((uint32_t) primary_color_values[r]) << 16;
                    734:                        vbe_set_color(curr_color_index, curr_color);
                    735:                }
                    736:                //green
                    737:                for (g = 0; g < prim_size; g++) {
                    738:                        curr_color_index =
                    739:                            mc_size * mc_size * mc_size + prim_size + g;
                    740:                        curr_color = ((uint32_t) primary_color_values[g]) << 8;
                    741:                        vbe_set_color(curr_color_index, curr_color);
                    742:                }
                    743:                //blue
                    744:                for (b = 0; b < prim_size; b++) {
                    745:                        curr_color_index =
                    746:                            mc_size * mc_size * mc_size + prim_size * 2 + b;
                    747:                        curr_color = (uint32_t) primary_color_values[b];
                    748:                        vbe_set_color(curr_color_index, curr_color);
                    749:                }
                    750:                // 10 shades of grey
                    751:                for (i = 0; i < prim_size; i++) {
                    752:                        curr_color_index =
                    753:                            mc_size * mc_size * mc_size + prim_size * 3 + i;
                    754:                        curr_color = 0;
                    755:                        curr_color |= ((uint32_t) primary_color_values[i]) << 16;       //red
                    756:                        curr_color |= ((uint32_t) primary_color_values[i]) << 8;        //green
                    757:                        curr_color |= ((uint32_t) primary_color_values[i]);     //blue
                    758:                        vbe_set_color(curr_color_index, curr_color);
                    759:                }
                    760: 
                    761:                // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen...
                    762:                vbe_set_color(0x00, 0x00000000);
                    763:                vbe_set_color(0xFF, 0x00FFFFFF);
                    764: 
                    765:                output->screen_width = best_mode_info.x_resolution;
                    766:                output->screen_height = best_mode_info.y_resolution;
                    767:                output->screen_linebytes = best_mode_info.linebytes;
                    768:                output->color_depth = best_mode_info.bits_per_pixel;
                    769:                output->framebuffer_address =
                    770:                    best_mode_info.framebuffer_address;
                    771:        } else {
                    772:                printf("%s: No suitable video mode found!\n", __FUNCTION__);
                    773:                //unset display_type...
                    774:                output->display_type = 0;
                    775:        }
                    776:        return 0;
                    777: }

unix.superglobalmegacorp.com

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