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

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;
        !           491:        uint32_t i;
        !           492:        if (argc < 4) {
        !           493:                printf
        !           494:                    ("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n",
        !           495:                     argv[0]);
        !           496:                int i = 0;
        !           497:                for (i = 0; i < argc; i++) {
        !           498:                        printf("argv[%d]: %s\n", i, argv[i]);
        !           499:                }
        !           500:                return -1;
        !           501:        }
        !           502:        // get a copy of input struct...
        !           503:        screen_info_input_t input =
        !           504:            *((screen_info_input_t *) strtoul((char *) argv[4], 0, 16));
        !           505:        // output is pointer to the address passed as argv[4]
        !           506:        screen_info_t *output =
        !           507:            (screen_info_t *) strtoul((char *) argv[4], 0, 16);
        !           508:        // zero output
        !           509:        memset(output, 0, sizeof(screen_info_t));
        !           510: 
        !           511:        // argv[1] is address of virtual BIOS mem...
        !           512:        // argv[2] is the size
        !           513:        biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
        !           514:        biosmem_size = strtoul(argv[2], 0, 16);;
        !           515:        if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
        !           516:                printf("Error: Not enough virtual memory: %x, required: %x!\n",
        !           517:                       biosmem_size, MIN_REQUIRED_VMEM_SIZE);
        !           518:                return -1;
        !           519:        }
        !           520:        // argv[3] is the device to open and use...
        !           521:        if (dev_init((char *) argv[3]) != 0) {
        !           522:                printf("Error initializing device!\n");
        !           523:                return -1;
        !           524:        }
        !           525:        //setup interrupt handler
        !           526:        X86EMU_intrFuncs intrFuncs[256];
        !           527:        for (i = 0; i < 256; i++)
        !           528:                intrFuncs[i] = handleInterrupt;
        !           529:        X86EMU_setupIntrFuncs(intrFuncs);
        !           530:        X86EMU_setupPioFuncs(&my_pio_funcs);
        !           531:        X86EMU_setupMemFuncs(&my_mem_funcs);
        !           532: 
        !           533:        // set mem_base
        !           534:        M.mem_base = (long) biosmem;
        !           535:        M.mem_size = biosmem_size;
        !           536:        DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base,
        !           537:                         (int) M.mem_size);
        !           538: 
        !           539:        vbe_info_t info;
        !           540:        rval = vbe_info(&info);
        !           541:        if (rval != 0)
        !           542:                return rval;
        !           543: 
        !           544:        DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature);
        !           545:        DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version);
        !           546:        DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr);
        !           547:        DEBUG_PRINTF_VBE("Capabilities:\n");
        !           548:        DEBUG_PRINTF_VBE("\tDAC: %s\n",
        !           549:                         (info.capabilities & 0x1) ==
        !           550:                         0 ? "fixed 6bit" : "switchable 6/8bit");
        !           551:        DEBUG_PRINTF_VBE("\tVGA: %s\n",
        !           552:                         (info.capabilities & 0x2) ==
        !           553:                         0 ? "compatible" : "not compatible");
        !           554:        DEBUG_PRINTF_VBE("\tRAMDAC: %s\n",
        !           555:                         (info.capabilities & 0x4) ==
        !           556:                         0 ? "normal" : "use blank bit in Function 09h");
        !           557: 
        !           558:        // argv[4] may be a pointer with enough space to return screen_info_t
        !           559:        // as input, it must contain a screen_info_input_t with the following content:
        !           560:        // byte[0:3] = "DDC\0" (zero-terminated signature header)
        !           561:        // byte[4:5] = reserved space for the return struct... just in case we ever change
        !           562:        //             the struct and dont have reserved enough memory (and let's hope the struct
        !           563:        //             never gets larger than 64KB)
        !           564:        // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors...
        !           565:        // byte[7:8] = max. screen width (OF may want to limit this)
        !           566:        // byte[9] = required color depth in bpp
        !           567:        if (strncmp((char *) input.signature, "DDC", 4) != 0) {
        !           568:                printf
        !           569:                    ("%s: Invalid input signature! expected: %s, is: %s\n",
        !           570:                     __FUNCTION__, "DDC", input.signature);
        !           571:                return -1;
        !           572:        }
        !           573:        if (input.size_reserved != sizeof(screen_info_t)) {
        !           574:                printf
        !           575:                    ("%s: Size of return struct is wrong, required: %d, available: %d\n",
        !           576:                     __FUNCTION__, (int) sizeof(screen_info_t),
        !           577:                     input.size_reserved);
        !           578:                return -1;
        !           579:        }
        !           580: 
        !           581:        vbe_ddc_info_t ddc_info;
        !           582:        ddc_info.port_number = input.monitor_number;
        !           583:        vbe_get_ddc_info(&ddc_info);
        !           584: 
        !           585: #if 0
        !           586:        DEBUG_PRINTF_VBE("DDC: edid_tranfer_time: %d\n",
        !           587:                         ddc_info.edid_transfer_time);
        !           588:        DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level);
        !           589:        DEBUG_PRINTF_VBE("DDC: EDID: \n");
        !           590:        CHECK_DBG(DEBUG_VBE) {
        !           591:                dump(ddc_info.edid_block_zero,
        !           592:                     sizeof(ddc_info.edid_block_zero));
        !           593:        }
        !           594: #endif
        !           595:        if (*((uint64_t *) ddc_info.edid_block_zero) !=
        !           596:            (uint64_t) 0x00FFFFFFFFFFFF00) {
        !           597:                // invalid EDID signature... probably no monitor
        !           598: 
        !           599:                output->display_type = 0x0;
        !           600:                return 0;
        !           601:        } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) {
        !           602:                // digital display
        !           603:                output->display_type = 2;
        !           604:        } else {
        !           605:                // analog
        !           606:                output->display_type = 1;
        !           607:        }
        !           608:        DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type);
        !           609:        memcpy(output->edid_block_zero, ddc_info.edid_block_zero,
        !           610:               sizeof(ddc_info.edid_block_zero));
        !           611:        i = 0;
        !           612:        vbe_mode_info_t mode_info;
        !           613:        vbe_mode_info_t best_mode_info;
        !           614:        // initialize best_mode to 0
        !           615:        memset(&best_mode_info, 0, sizeof(best_mode_info));
        !           616:        while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) {
        !           617:                //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode);
        !           618:                vbe_get_mode_info(&mode_info);
        !           619: #if 0
        !           620:                DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n",
        !           621:                                 mode_info.video_mode,
        !           622:                                 (mode_info.attributes & 0x1) ==
        !           623:                                 0 ? "not supported" : "supported");
        !           624:                DEBUG_PRINTF_VBE("\tTTY: %s\n",
        !           625:                                 (mode_info.attributes & 0x4) ==
        !           626:                                 0 ? "no" : "yes");
        !           627:                DEBUG_PRINTF_VBE("\tMode: %s %s\n",
        !           628:                                 (mode_info.attributes & 0x8) ==
        !           629:                                 0 ? "monochrome" : "color",
        !           630:                                 (mode_info.attributes & 0x10) ==
        !           631:                                 0 ? "text" : "graphics");
        !           632:                DEBUG_PRINTF_VBE("\tVGA: %s\n",
        !           633:                                 (mode_info.attributes & 0x20) ==
        !           634:                                 0 ? "compatible" : "not compatible");
        !           635:                DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n",
        !           636:                                 (mode_info.attributes & 0x40) ==
        !           637:                                 0 ? "yes" : "no");
        !           638:                DEBUG_PRINTF_VBE("\tFramebuffer: %s\n",
        !           639:                                 (mode_info.attributes & 0x80) ==
        !           640:                                 0 ? "no" : "yes");
        !           641:                DEBUG_PRINTF_VBE("\tResolution: %dx%d\n",
        !           642:                                 mode_info.x_resolution,
        !           643:                                 mode_info.y_resolution);
        !           644:                DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n",
        !           645:                                 mode_info.x_charsize, mode_info.y_charsize);
        !           646:                DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n",
        !           647:                                 mode_info.bits_per_pixel);
        !           648:                DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n",
        !           649:                                 mode_info.memory_model);
        !           650:                DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n",
        !           651:                                 mode_info.framebuffer_address);
        !           652: #endif
        !           653:                if ((mode_info.bits_per_pixel == input.color_depth)
        !           654:                    && (mode_info.x_resolution <= input.max_screen_width)
        !           655:                    && ((mode_info.attributes & 0x80) != 0)     // framebuffer mode
        !           656:                    && ((mode_info.attributes & 0x10) != 0)     // graphics
        !           657:                    && ((mode_info.attributes & 0x8) != 0)      // color
        !           658:                    && (mode_info.x_resolution > best_mode_info.x_resolution))  // better than previous best_mode
        !           659:                {
        !           660:                        // yiiiihaah... we found a new best mode
        !           661:                        memcpy(&best_mode_info, &mode_info, sizeof(mode_info));
        !           662:                }
        !           663:                i++;
        !           664:        }
        !           665: 
        !           666:        if (best_mode_info.video_mode != 0) {
        !           667:                DEBUG_PRINTF_VBE
        !           668:                    ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n",
        !           669:                     best_mode_info.video_mode,
        !           670:                     best_mode_info.x_resolution,
        !           671:                     best_mode_info.y_resolution,
        !           672:                     best_mode_info.bits_per_pixel,
        !           673:                     best_mode_info.framebuffer_address);
        !           674: 
        !           675:                //printf("Mode Info Dump:");
        !           676:                //dump(best_mode_info.mode_info_block, 64);
        !           677: 
        !           678:                // set the video mode
        !           679:                vbe_set_mode(&best_mode_info);
        !           680: 
        !           681:                if ((info.capabilities & 0x1) != 0) {
        !           682:                        // switch to 8 bit palette format
        !           683:                        vbe_set_palette_format(8);
        !           684:                }
        !           685:                // setup a palette:
        !           686:                // - first 216 colors are mixed colors for each component in 6 steps
        !           687:                //   (6*6*6=216)
        !           688:                // - then 10 shades of the three primary colors
        !           689:                // - then 10 shades of grey
        !           690:                // -------
        !           691:                // = 256 colors
        !           692:                //
        !           693:                // - finally black is color 0 and white color FF (because SLOF expects it
        !           694:                //   this way...)
        !           695:                // this resembles the palette that the kernel/X Server seems to expect...
        !           696: 
        !           697:                uint8_t mixed_color_values[6] =
        !           698:                    { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 };
        !           699:                uint8_t primary_color_values[10] =
        !           700:                    { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F,
        !           701:                        0x27
        !           702:                };
        !           703:                uint8_t mc_size = sizeof(mixed_color_values);
        !           704:                uint8_t prim_size = sizeof(primary_color_values);
        !           705: 
        !           706:                uint8_t curr_color_index;
        !           707:                uint32_t curr_color;
        !           708: 
        !           709:                uint8_t r, g, b;
        !           710:                // 216 mixed colors
        !           711:                for (r = 0; r < mc_size; r++) {
        !           712:                        for (g = 0; g < mc_size; g++) {
        !           713:                                for (b = 0; b < mc_size; b++) {
        !           714:                                        curr_color_index =
        !           715:                                            (r * mc_size * mc_size) +
        !           716:                                            (g * mc_size) + b;
        !           717:                                        curr_color = 0;
        !           718:                                        curr_color |= ((uint32_t) mixed_color_values[r]) << 16; //red value
        !           719:                                        curr_color |= ((uint32_t) mixed_color_values[g]) << 8;  //green value
        !           720:                                        curr_color |= (uint32_t) mixed_color_values[b]; //blue value
        !           721:                                        vbe_set_color(curr_color_index,
        !           722:                                                      curr_color);
        !           723:                                }
        !           724:                        }
        !           725:                }
        !           726: 
        !           727:                // 10 shades of each primary color
        !           728:                // red
        !           729:                for (r = 0; r < prim_size; r++) {
        !           730:                        curr_color_index = mc_size * mc_size * mc_size + r;
        !           731:                        curr_color = ((uint32_t) primary_color_values[r]) << 16;
        !           732:                        vbe_set_color(curr_color_index, curr_color);
        !           733:                }
        !           734:                //green
        !           735:                for (g = 0; g < prim_size; g++) {
        !           736:                        curr_color_index =
        !           737:                            mc_size * mc_size * mc_size + prim_size + g;
        !           738:                        curr_color = ((uint32_t) primary_color_values[g]) << 8;
        !           739:                        vbe_set_color(curr_color_index, curr_color);
        !           740:                }
        !           741:                //blue
        !           742:                for (b = 0; b < prim_size; b++) {
        !           743:                        curr_color_index =
        !           744:                            mc_size * mc_size * mc_size + prim_size * 2 + b;
        !           745:                        curr_color = (uint32_t) primary_color_values[b];
        !           746:                        vbe_set_color(curr_color_index, curr_color);
        !           747:                }
        !           748:                // 10 shades of grey
        !           749:                for (i = 0; i < prim_size; i++) {
        !           750:                        curr_color_index =
        !           751:                            mc_size * mc_size * mc_size + prim_size * 3 + i;
        !           752:                        curr_color = 0;
        !           753:                        curr_color |= ((uint32_t) primary_color_values[i]) << 16;       //red
        !           754:                        curr_color |= ((uint32_t) primary_color_values[i]) << 8;        //green
        !           755:                        curr_color |= ((uint32_t) primary_color_values[i]);     //blue
        !           756:                        vbe_set_color(curr_color_index, curr_color);
        !           757:                }
        !           758: 
        !           759:                // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen...
        !           760:                vbe_set_color(0x00, 0x00000000);
        !           761:                vbe_set_color(0xFF, 0x00FFFFFF);
        !           762: 
        !           763:                output->screen_width = best_mode_info.x_resolution;
        !           764:                output->screen_height = best_mode_info.y_resolution;
        !           765:                output->screen_linebytes = best_mode_info.linebytes;
        !           766:                output->color_depth = best_mode_info.bits_per_pixel;
        !           767:                output->framebuffer_address =
        !           768:                    best_mode_info.framebuffer_address;
        !           769:        } else {
        !           770:                printf("%s: No suitable video mode found!\n", __FUNCTION__);
        !           771:                //unset display_type...
        !           772:                output->display_type = 0;
        !           773:        }
        !           774:        return 0;
        !           775: }

unix.superglobalmegacorp.com

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