Same comments as on others. Gedare just pushed this. Do the fixes I noted across the file set in another round of patches. It is easier for all involved. :)
--joel On 11/20/2014 8:00 AM, Jan Dolezal wrote: > --- > c/src/lib/libbsp/i386/pc386/Makefile.am | 5 + > c/src/lib/libbsp/i386/pc386/configure.ac | 13 + > c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c | 858 > +++++++++++++++++++++++ > c/src/lib/libbsp/i386/pc386/include/fb_vesa.h | 131 ++++ > c/src/lib/libbsp/i386/pc386/preinstall.am | 6 + > c/src/lib/libbsp/i386/pc386/start/start.S | 8 + > 6 files changed, 1021 insertions(+) > create mode 100644 c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c > create mode 100644 c/src/lib/libbsp/i386/pc386/include/fb_vesa.h > > diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am > b/c/src/lib/libbsp/i386/pc386/Makefile.am > index de970a3..391bfa9 100644 > --- a/c/src/lib/libbsp/i386/pc386/Makefile.am > +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am > @@ -106,13 +106,18 @@ libbsp_a_SOURCES += console/printk_support.c > libbsp_a_SOURCES += console/vgacons.c > libbsp_a_SOURCES += console/exar17d15x.c > libbsp_a_SOURCES += console/rtd316.c > +if USE_VBE_RM > include_bsp_HEADERS += include/vbe3.h > include_HEADERS += include/edid.h > +include_bsp_HEADERS += include/fb_vesa.h > +libbsp_a_SOURCES += console/fb_vesa_rm.c > +else > if USE_CIRRUS_GD5446 > libbsp_a_SOURCES += console/fb_cirrus.c > else > libbsp_a_SOURCES += console/fb_vga.c > endif > +endif > > # gdb > libbsp_a_SOURCES += ../../i386/shared/comm/i386-stub.c > diff --git a/c/src/lib/libbsp/i386/pc386/configure.ac > b/c/src/lib/libbsp/i386/pc386/configure.ac > index ecec056..a74d6cb 100644 > --- a/c/src/lib/libbsp/i386/pc386/configure.ac > +++ b/c/src/lib/libbsp/i386/pc386/configure.ac > @@ -82,6 +82,19 @@ RTEMS_BSPOPTS_HELP([USE_CIRRUS_GD5446], > NOTE: This has only been tested on Qemu.]) > AM_CONDITIONAL(USE_CIRRUS_GD5446,test "$USE_CIRRUS_GD5446" = "1") > > +RTEMS_BSPOPTS_SET([USE_VBE_RM],[*],[0]) > +RTEMS_BSPOPTS_HELP([USE_VBE_RM], > +[If defined, enables use of the Vesa Bios Extensions - real mode interface, > + which enables graphical mode and introduce it upon bootup.]) > +AM_CONDITIONAL(USE_VBE_RM,test "$USE_VBE_RM" = "1") > + > +if test "${USE_VBE_RM}" = "1" ; then > + if test -z "${NUM_APP_DRV_GDT_DESCRIPTORS}"; then > + NUM_APP_DRV_GDT_DESCRIPTORS=2 ; > + else > + NUM_APP_DRV_GDT_DESCRIPTORS+=2 ; > + fi > +fi > RTEMS_BSPOPTS_SET([NUM_APP_DRV_GDT_DESCRIPTORS],[*],[0]) > RTEMS_BSPOPTS_HELP([NUM_APP_DRV_GDT_DESCRIPTORS], > [Defines how many descriptors in GDT may be allocated for application or > diff --git a/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c > b/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c > new file mode 100644 > index 0000000..6b26d35 > --- /dev/null > +++ b/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c > @@ -0,0 +1,858 @@ > +/* > + * FB driver for graphic hardware compatible with VESA Bios Extension > + * Real mode interface utilized > + * Tested on real HW. > + * Needs file head and this should be in it. > + * Copyright (c) 2014 - CTU in Prague > + * Jan Doležal ( dolez...@fel.cvut.cz ) > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + * > + * The code for rtems_buffer_* functions were greatly > + * inspired or coppied from: > + * - RTEMS fb_cirrus.c - Alexandru-Sever Horin (alex.seve...@gmail.com) > + * The following should be in the file header block. > + * Public sources related: > + * - VESA BIOS EXTENSION (VBE) Core Function Standard, Ver: 3.0, Sep 16, > 1998 > + * - VESA Enhanced Extended Display Identification Data (E-EDID) Standard > + * Release A, Revision 2, September 25, 2006 > + */ > + Maybe even this block? > +/* > + * Hardware is completely initialized upon boot of the system. > + * Therefore there is no way to change graphics mode later. > + * > + * Interrupt 0x10 is used for entering graphics BIOS. > + * > + * Driver reads parameter from multiboot command line to setup video: > + * "--video=<resX>x<resY>[-<bpp>]" > + * If cmdline parameter is not specified an attempt for obtaining > + * resolution from display attached is made. > + */ > + > +#include <bsp.h> > + > +#include <bsp/fb_vesa.h> > +#include <bsp/realmode_int.h> > + > +#include <pthread.h> > + > +#include <rtems/libio.h> > + > +#include <rtems/fb.h> > +#include <rtems/framebuffer.h> > + > +#include <stdlib.h> > + > +#define FB_VESA_NAME "FB_VESA_RM" > + > +void vesa_realmode_bootup_init(void); > + > +/* mutex for protection against multiple opens, when called > frame_buffer_open */ > +static pthread_mutex_t vesa_mutex = PTHREAD_MUTEX_INITIALIZER; > + > +/* screen information for the VGA driver > + * standard structures - from RTEMS fb interface > + */ > +static struct fb_var_screeninfo fb_var; > +static struct fb_fix_screeninfo fb_fix; > + > +static uint16_t vbe_usedMode; > + > +inline uint32_t VBEControllerInformation( struct VBE_VbeInfoBlock > *infoBlock, > + uint16_t queriedVBEVersion) > +{ > + uint16_t size; > + struct VBE_VbeInfoBlock *VBE_buffer = > + (struct VBE_VbeInfoBlock *)i386_get_default_rm_buffer(&size); > + i386_realmode_interrupt_registers parret; > + parret.reg_eax = VBE_RetVBEConInf; > + uint16_t seg, off; > + i386_Physical_to_real(VBE_buffer, &seg, &off); > + parret.reg_edi = (uint32_t)off; > + parret.reg_es = seg; > + /* indicate to graphic's bios that VBE2.0 extended information is > desired */ > + if (queriedVBEVersion >= 0x200) > + { > + strncpy( > + (char *)&VBE_buffer->VbeSignature, > + VBE20plus_SIGNATURE, > + 4*sizeof(size_t) > + ); > + } > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + if ((parret.reg_eax & 0xFFFF) == > + (VBE_callSuccessful<<8 | VBE_functionSupported)) > + { > + *infoBlock = *VBE_buffer; > + } > + return (parret.reg_eax & 0xFFFF); > +} > + > +inline uint32_t VBEModeInformation( struct VBE_ModeInfoBlock *infoBlock, > + uint16_t modeNumber) > +{ > + uint16_t size; > + struct VBE_ModeInfoBlock *VBE_buffer = > + (struct VBE_ModeInfoBlock *)i386_get_default_rm_buffer(&size); > + i386_realmode_interrupt_registers parret; > + parret.reg_eax = VBE_RetVBEModInf; > + parret.reg_ecx = modeNumber; > + uint16_t seg, off; > + i386_Physical_to_real(VBE_buffer, &seg, &off); > + parret.reg_edi = (uint32_t)off; > + parret.reg_es = seg; > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + if ((parret.reg_eax & 0xFFFF) == > + (VBE_callSuccessful<<8 | VBE_functionSupported)) > + { > + *infoBlock = *VBE_buffer; > + } > + return (parret.reg_eax & 0xFFFF); > +} > + > +inline uint32_t VBESetMode( uint16_t modeNumber, > + struct VBE_CRTCInfoBlock *infoBlock) > +{ > + uint16_t size; > + struct VBE_CRTCInfoBlock *VBE_buffer = > + (struct VBE_CRTCInfoBlock *)i386_get_default_rm_buffer(&size); > + i386_realmode_interrupt_registers parret; > + /* copy CRTC */ > + *VBE_buffer = *infoBlock; > + parret.reg_eax = VBE_SetVBEMod; > + parret.reg_ebx = modeNumber; > + uint16_t seg, off; > + i386_Physical_to_real(VBE_buffer, &seg, &off); > + parret.reg_edi = (uint32_t)off; > + parret.reg_es = seg; > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + return (parret.reg_eax & 0xFFFF); > +} > + > +inline uint32_t VBECurrentMode(uint16_t *modeNumber) > +{ > + i386_realmode_interrupt_registers parret; > + parret.reg_eax = VBE_RetCurVBEMod; > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + *modeNumber = (uint16_t)parret.reg_ebx; > + return (parret.reg_eax & 0xFFFF); > +} > + > +inline uint32_t VBEReportDDCCapabilities( uint16_t controllerUnitNumber, > + uint8_t > *secondsToTransferEDIDBlock, > + uint8_t *DDCLevelSupported) > +{ > + i386_realmode_interrupt_registers parret; > + parret.reg_eax = VBE_DisDatCha; > + parret.reg_ebx = VBEDDC_Capabilities; > + parret.reg_ecx = controllerUnitNumber; > + parret.reg_edi = 0; > + parret.reg_es = 0; > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + *secondsToTransferEDIDBlock = (uint8_t)parret.reg_ebx >> 8; > + *DDCLevelSupported = (uint8_t)parret.reg_ebx; > + return (parret.reg_eax & 0xFFFF); > +} > + > +inline uint32_t VBEReadEDID(uint16_t controllerUnitNumber, > + uint16_t EDIDBlockNumber, > + struct edid1 *buffer) > +{ > + uint16_t size; > + struct edid1 *VBE_buffer = (struct edid1 > *)i386_get_default_rm_buffer(&size); > + i386_realmode_interrupt_registers parret; > + parret.reg_eax = VBE_DisDatCha; > + parret.reg_ebx = VBEDDC_ReadEDID; > + parret.reg_ecx = controllerUnitNumber; > + parret.reg_edx = EDIDBlockNumber; > + uint16_t seg, off; > + i386_Physical_to_real(VBE_buffer, &seg, &off); > + parret.reg_edi = (uint32_t)off; > + parret.reg_es = seg; > + if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0) > + return -1; > + if ((parret.reg_eax & 0xFFFF) == > + (VBE_callSuccessful<<8 | VBE_functionSupported)) > + { > + *buffer = *VBE_buffer; > + } > + return (parret.reg_eax & 0xFFFF); > +} > + > +typedef struct { > + uint16_t modeNumber; > + uint16_t resX; > + uint16_t resY; > + uint8_t bpp; > +} modeParams; > + > +/* finds mode in 'modeList' of 'listLength' length according to resolution > + given in 'searchedResolution'. If bpp is given in that struct as well > + mode with such color depth and resolution is searched for. Otherwise bpp > + has to be zero. Mode number found is returned and also filled into > + 'searchedResolution'. bpp is also filled into 'searchedResolution' if it > + was 0 before call. */ > +static uint16_t findModeByResolution( modeParams *modeList, > + uint8_t listLength, > + modeParams *searchedResolution) > +{ > + uint8_t i = 0; > + while (i < listLength) > + { > + if (searchedResolution->resX == modeList[i].resX && > + searchedResolution->resY == modeList[i].resY) > + { > + if (searchedResolution->bpp==0 || > + searchedResolution->bpp==modeList[i].bpp) > + { > + searchedResolution->bpp = modeList[i].bpp; > + searchedResolution->modeNumber = modeList[i].modeNumber; > + return modeList[i].modeNumber; > + } > + } > + i++; > + } > + return -1; > +} > + > +/* > + * Parse comandline option "--video=" if available. > + * expected format > + * --video=<resX>x<resY>[-<bpp>] > + * numbers <resX>, <resY> and <bpp> are decadic > + * > + * @retval video mode number to be set > + * -1 on parsing error or when no suitable mode found > + */ > +static uint16_t findModeUsingCmdline( modeParams *modeList, > + uint8_t listLength) > +{ > + const char* opt; > + modeParams cmdlineMode; > + char* endptr; > + cmdlineMode.bpp = 0; > + opt = bsp_cmdline_arg("--video="); > + if (opt) > + { > + opt += sizeof("--video=")-1; > + cmdlineMode.resX = strtol(opt, &endptr, 10); > + if (*endptr != 'x') > + { > + return -1; > + } > + opt = endptr+1; > + cmdlineMode.resY = strtol(opt, &endptr, 10); > + switch (*endptr) > + { > + case '-': > + opt = endptr+1; > + if (strlen(opt) <= 2) > + cmdlineMode.bpp = strtol(opt, &endptr, 10); > + else > + { > + cmdlineMode.bpp = strtol(opt, &endptr, 10); > + if (*endptr != ' ') > + { > + return -1; > + } > + } > + case ' ': > + case 0: > + break; > + default: > + return -1; > + } > + > + if (findModeByResolution(modeList, listLength, &cmdlineMode) != > + (uint16_t)-1) > + return cmdlineMode.modeNumber; > + } > + return -1; > +} > + > +/* > + * returns mode number best fitting to monitor attached > + * > + * @retval video mode number to be set > + * -1 on parsing error or when no suitable mode found > + */ > +static uint16_t findModeUsingEDID( modeParams *modeList, > + uint8_t listLength) > +{ > + struct edid1 edid; > + uint8_t checksum, iterator; > + uint8_t index, j; > + modeParams EDIDmode; > + checksum = 0; > + iterator = 0; > + EDIDmode.bpp = 0; > + if (VBEReadEDID(0, 0, &edid) != > + (VBE_callSuccessful<<8 | VBE_functionSupported)) > + { > + printk(FB_VESA_NAME " Function 15h (read EDID) not supported.\n"); > + return -1; > + } > +/* version of EDID structure */ > + if (edid.Version == 1) > + { /* EDID version 1 */ > + while (iterator < sizeof(struct edid1)) > + { > + checksum += *((uint8_t *)&edid+iterator); > + iterator++; > + } > + if (checksum) > + /* not implemented: try to read EDID again */ > + printk(FB_VESA_NAME " EDID v1 checksum failed\n"); > + > + /* try to find Detailed Timing Descriptor (defined in BASE EDID) > + in controller mode list; first should be preffered mode */ > + index = 0; > + while (index < 4) > + { > + /* skip if it is monitor descriptor */ > + if (edid.dtd_md[index].md.Flag0[0] == 0 && > + edid.dtd_md[index].md.Flag0[1] == 0 && > + edid.dtd_md[index].md.Flag1 == 0) > + { > + index++; > + continue; > + } > + EDIDmode.resX = DTD_HorizontalActive(&edid.dtd_md[0].dtd); > + EDIDmode.resY = DTD_VerticalActive(&edid.dtd_md[0].dtd); > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + > + index++; > + } > + /* try to find Detailed Timing Descriptor (defined in optional > EXTENSION > + Blocks) in controller mode list */ > + if (edid.ExtensionFlag > 0) > + { > + /* not implemented */ > + } > + /* try to find CVT (defined in BASE EDID) in controller mode list */ > + index = 1; > + while (index < 4) > + { > + if (edid.dtd_md[index].md.DataTypeTag == > + EDID_DTT_CVT3ByteTimingCodes && > + edid.dtd_md[index].md.Flag0[0] == 0 && > + edid.dtd_md[index].md.Flag0[1] == 0 && > + edid.dtd_md[index].md.Flag1 == 0 && > + edid.dtd_md[index].md.Flag2 == 0) > + { > + struct CVTTimingCodes3B *cvt = (struct CVTTimingCodes3B *) > + &edid.dtd_md[index].md.DescriptorData[0]; > + j = 0; > + while (j < 4) > + { > + EDIDmode.resY = > edid1_CVT_AddressableLinesHigh(&cvt->cvt[j]); > + switch (edid1_CVT_AspectRatio(&cvt->cvt[j])) > + { > + case EDID_CVT_AspectRatio_4_3: > + EDIDmode.resX = (EDIDmode.resY*4)/3; > + break; > + case EDID_CVT_AspectRatio_16_9: > + EDIDmode.resX = (EDIDmode.resY*16)/9; > + break; > + case EDID_CVT_AspectRatio_16_10: > + EDIDmode.resX = (EDIDmode.resY*16)/10; > + break; > + case EDID_CVT_AspectRatio_15_9: > + EDIDmode.resX = (EDIDmode.resY*15)/9; > + break; > + } > + EDIDmode.resX = (EDIDmode.resX/8)*8; > + if (findModeByResolution(modeList, listLength, > &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + > + j++; > + } > + } > + index++; > + } > + /* try to find CVT (defined in optional EXTENSION Blocks) > + in controller mode list */ > + /* not implemented */ > + /* try to find Standard Timings (listed in BASE EDID) > + in controller mode list */ > + index = 0; > + while (index < 8) > + { > + /* check if descriptor is unused */ > + if (*(uint16_t*)&edid.STI[index] == EDID_STI_DescriptorUnused) > + { > + index++; > + continue; > + } > + EDIDmode.resX = (edid.STI[index].HorizontalActivePixels+31)*8; > + switch (edid.STI[index].ImageAspectRatio_RefreshRate & > EDID1_STI_ImageAspectRatioMask) > + { > + case EDID_STI_AspectRatio_16_10: > + EDIDmode.resY = (EDIDmode.resX*10)/16; > + break; > + case EDID_STI_AspectRatio_4_3: > + EDIDmode.resY = (EDIDmode.resX*3)/4; > + break; > + case EDID_STI_AspectRatio_5_4: > + EDIDmode.resY = (EDIDmode.resX*4)/5; > + break; > + case EDID_STI_AspectRatio_16_9: > + EDIDmode.resY = (EDIDmode.resX*9)/16; > + break; > + } > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + > + index++; > + } > + /* try to find Standard Timings (listed in optional EXTENSION Blocks) > + in controller mode list */ > + /* not implemented */ > + /* use Established Timings */ > + if (edid1_EstablishedTim(&edid, EST_1280x1024_75Hz)) > + { > + EDIDmode.resX = 1280; > + EDIDmode.resY = 1024; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_1152x870_75Hz)) > + { > + EDIDmode.resX = 1152; > + EDIDmode.resY = 870; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_1024x768_75Hz) || > + edid1_EstablishedTim(&edid, EST_1024x768_70Hz) || > + edid1_EstablishedTim(&edid, EST_1024x768_60Hz) || > + edid1_EstablishedTim(&edid, EST_1024x768_87Hz)) > + { > + EDIDmode.resX = 1024; > + EDIDmode.resY = 768; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_832x624_75Hz)) > + { > + EDIDmode.resX = 832; > + EDIDmode.resY = 624; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_800x600_60Hz) || > + edid1_EstablishedTim(&edid, EST_800x600_56Hz) || > + edid1_EstablishedTim(&edid, EST_800x600_75Hz) || > + edid1_EstablishedTim(&edid, EST_800x600_72Hz)) > + { > + EDIDmode.resX = 800; > + EDIDmode.resY = 600; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_720x400_88Hz) || > + edid1_EstablishedTim(&edid, EST_720x400_70Hz)) > + { > + EDIDmode.resX = 720; > + EDIDmode.resY = 400; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + if (edid1_EstablishedTim(&edid, EST_640x480_75Hz) || > + edid1_EstablishedTim(&edid, EST_640x480_72Hz) || > + edid1_EstablishedTim(&edid, EST_640x480_67Hz) || > + edid1_EstablishedTim(&edid, EST_640x480_60Hz)) > + { > + EDIDmode.resX = 640; > + EDIDmode.resY = 480; > + EDIDmode.bpp = 0; > + if (findModeByResolution(modeList, listLength, &EDIDmode) != > + (uint16_t)-1) > + return EDIDmode.modeNumber; > + } > + } > + else > + printk(FB_VESA_NAME " error reading EDID: unsupported version\n"); > + return (uint16_t)-1; > +} > + > +void vesa_realmode_bootup_init(void) > +{ > + uint32_t vbe_ret_val; > + uint16_t size; > + struct VBE_VbeInfoBlock *vib = (struct VBE_VbeInfoBlock *) > + i386_get_default_rm_buffer(&size); > + vbe_ret_val = VBEControllerInformation(vib, 0x300); > + if (vbe_ret_val == -1) > + { > + printk(FB_VESA_NAME " error calling real mode interrupt.\n"); > + return; > + } > + if (vbe_ret_val != (VBE_callSuccessful<<8 | VBE_functionSupported)) > + { > + printk(FB_VESA_NAME " Function 00h (read VBE info block)" > + "not supported.\n"); > + } > +/* Helper array is later filled with mode numbers and their parameters > + sorted from the biggest values to the smalest where priorities of > + parameters are from the highest to the lowest: resolution X, > + resolution Y, bits per pixel. > + The array is used for search the monitor provided parameters in EDID > + structure and if found we set such mode using corresponding > + VESA function. */ > +#define MAX_NO_OF_SORTED_MODES 100 > + modeParams sortModeParams[MAX_NO_OF_SORTED_MODES]; > + > + uint16_t *vmpSegOff = (uint16_t *)&vib->VideoModePtr; > + uint16_t *modeNOPtr = (uint16_t*) > + i386_Real_to_physical(*(vmpSegOff+1), *vmpSegOff); > + uint16_t iterator = 0; > + if (*(uint16_t*)vib->VideoModePtr == VBE_STUB_VideoModeList) > + { > + printk(FB_VESA_NAME " VBE Core not implemented!\n"); > + } > + else > + { > + /* prepare list of modes */ > + while (*(modeNOPtr+iterator) != VBE_END_OF_VideoModeList && > + *(modeNOPtr+iterator) != 0) > + { /* some bios implementations ends the list incorrectly with 0 */ > + if (iterator < MAX_NO_OF_SORTED_MODES) > + { > + sortModeParams[iterator].modeNumber = *(modeNOPtr+iterator); > + iterator ++; > + } > + else > + break; > + } > + if (iterator < MAX_NO_OF_SORTED_MODES) > + sortModeParams[iterator].modeNumber = 0; > + } > + > + struct VBE_ModeInfoBlock *mib = (struct VBE_ModeInfoBlock *) > + i386_get_default_rm_buffer(&size); > + iterator = 0; > + uint8_t nextFilteredMode = 0; > + uint16_t required_mode_attributes = VBE_modSupInHWMask | > + VBE_ColorModeMask | VBE_GraphicsModeMask | VBE_LinFraBufModeAvaiMask; > + /* get parameters of modes and filter modes according to set > + required parameters */ > + while (iterator < MAX_NO_OF_SORTED_MODES && > + sortModeParams[iterator].modeNumber!=0) > + { > + VBEModeInformation(mib, sortModeParams[iterator].modeNumber); > + if ((mib->ModeAttributes&required_mode_attributes) == > + required_mode_attributes) > + { > + sortModeParams[nextFilteredMode].modeNumber = > + sortModeParams[iterator].modeNumber; > + sortModeParams[nextFilteredMode].resX = mib->XResolution; > + sortModeParams[nextFilteredMode].resY = mib->YResolution; > + sortModeParams[nextFilteredMode].bpp = mib->BitsPerPixel; > + nextFilteredMode ++; > + } > + iterator ++; > + } > + sortModeParams[nextFilteredMode].modeNumber = 0; > + > + uint8_t numberOfModes = nextFilteredMode; > + /* sort filtered modes */ > + modeParams modeXchgPlace; > + iterator = 0; > + uint8_t j; > + uint8_t idxBestMode; > + while (iterator < numberOfModes) > + { > + idxBestMode = iterator; > + j = iterator+1; > + while (j < numberOfModes) > + { > + if (sortModeParams[j].resX > sortModeParams[idxBestMode].resX) > + idxBestMode = j; > + else if (sortModeParams[j].resX == > sortModeParams[idxBestMode].resX) > + { > + if (sortModeParams[j].resY > > sortModeParams[idxBestMode].resY) > + idxBestMode = j; > + else if (sortModeParams[j].resY == > + sortModeParams[idxBestMode].resY) > + { > + if (sortModeParams[j].bpp > > sortModeParams[idxBestMode].bpp) > + idxBestMode = j; > + } > + } > + j++; > + } > + if (idxBestMode != iterator) > + { > + modeXchgPlace = sortModeParams[iterator]; > + sortModeParams[iterator] = sortModeParams[idxBestMode]; > + sortModeParams[idxBestMode] = modeXchgPlace; > + } > + iterator++; > + } > + > + /* first search for video argument in multiboot options */ > + vbe_usedMode = findModeUsingCmdline(sortModeParams, numberOfModes); > + if (vbe_usedMode == (uint16_t)-1) > + { > + printk(FB_VESA_NAME " video on command line not provided" > + "\n\ttrying EDID ...\n"); > + /* second search monitor for good resolution */ > + vbe_usedMode = findModeUsingEDID(sortModeParams, numberOfModes); > + if (vbe_usedMode == (uint16_t)-1) > + { > + printk(FB_VESA_NAME" monitor's EDID video parameters not > supported" > + "\n\tusing mode with highest resolution, > bpp\n"); > + /* third set highest values */ > + vbe_usedMode = sortModeParams[0].modeNumber; > + } > + } > + > + /* fill framebuffer structs with info about selected mode */ > + vbe_ret_val = VBEModeInformation(mib, vbe_usedMode); > + if ((vbe_ret_val&0xff)!=VBE_functionSupported || > + (vbe_ret_val>>8)!=VBE_callSuccessful) > + { > + printk(FB_VESA_NAME " Cannot get mode info anymore. ax=0x%x\n", > + vbe_ret_val); > + } > + > + fb_var.xres = mib->XResolution; > + fb_var.yres = mib->YResolution; > + fb_var.bits_per_pixel = mib->BitsPerPixel; > + fb_var.red.offset = mib->LinRedFieldPosition; > + fb_var.red.length = mib->LinRedMaskSize; > + fb_var.red.msb_right = 0; > + fb_var.green.offset = mib->LinGreenFieldPosition; > + fb_var.green.length = mib->LinGreenMaskSize; > + fb_var.green.msb_right = 0; > + fb_var.blue.offset = mib->LinBlueFieldPosition; > + fb_var.blue.length = mib->LinBlueMaskSize; > + fb_var.blue.msb_right = 0; > + fb_var.transp.offset = mib->LinRsvdFieldPosition; > + fb_var.transp.length = mib->LinRsvdMaskSize; > + fb_var.transp.msb_right =0; > + > + fb_fix.smem_start = (char *)mib->PhysBasePtr; > + fb_fix.line_length = mib->LinBytesPerScanLine; > + fb_fix.smem_len = fb_fix.line_length*fb_var.yres; > + fb_fix.type = FB_TYPE_PACKED_PIXELS; > + if (fb_var.bits_per_pixel < 24) > + fb_fix.visual = FB_VISUAL_DIRECTCOLOR; > + else > + fb_fix.visual = FB_VISUAL_TRUECOLOR; > + > + /* set selected mode */ > + vbe_ret_val = VBESetMode(vbe_usedMode | VBE_linearFlatFrameBufMask, > + (struct VBE_CRTCInfoBlock *)(i386_get_default_rm_buffer(&size))); > + if (vbe_ret_val>>8 == VBE_callFailed) > + printk(FB_VESA_NAME " VBE: Requested mode is not available."); > + > + if ((vbe_ret_val&0xff)!= (VBE_functionSupported | VBE_callSuccessful<<8)) > + printk(FB_VESA_NAME " Call to function 2h (set VBE mode) failed. " > + "ax=0x%x\n", vbe_ret_val); > + > + vib = (void *) 0; > + mib = (void *) 0; > +} > + > +/* > + * fb_vesa device driver INITIALIZE entry point. > + */ > +rtems_device_driver > +frame_buffer_initialize( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + rtems_status_code status; > + > + printk(FB_VESA_NAME " frame buffer -- driver initializing..\n" ); > + > +/* > + * Register the device. > + */ > + status = rtems_io_register_name(FRAMEBUFFER_DEVICE_0_NAME, major, 0); > + if (status != RTEMS_SUCCESSFUL) > + { > + printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME > + " - " FB_VESA_NAME " frame buffer device!\n"); > + rtems_fatal_error_occurred( status ); > + } > + > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * fb_vesa device driver OPEN entry point > + */ > +rtems_device_driver > +frame_buffer_open( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + printk( FB_VESA_NAME " open device\n" ); > + > + if (pthread_mutex_trylock(&vesa_mutex) != 0) > + { > + printk( FB_VESA_NAME " could not lock vesa_mutex\n" ); > + > + return RTEMS_UNSATISFIED; > + } > + > + return RTEMS_SUCCESSFUL; > + > +} > + > +/* > + * fb_vesa device driver CLOSE entry point > + */ > +rtems_device_driver > +frame_buffer_close( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + printk( FB_VESA_NAME " close device\n" ); > + if (pthread_mutex_unlock(&vesa_mutex) == 0) > + { > + /* restore previous state. for VGA this means return to text mode. > + * leave out if graphics hardware has been initialized in > + * frame_buffer_initialize() */ > + > + printk(FB_VESA_NAME ": close called.\n" ); > + return RTEMS_SUCCESSFUL; > + } > + > + return RTEMS_UNSATISFIED; > +} > + > +/* > + * fb_vesa device driver READ entry point. > + */ > +rtems_device_driver > +frame_buffer_read( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + printk( FB_VESA_NAME " read device\n" ); > + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; > + rw_args->bytes_moved = > + ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? > + (fb_fix.smem_len - rw_args->offset) : > + rw_args->count; > + memcpy(rw_args->buffer, (const void *) > + (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved); > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * frame_vesa device driver WRITE entry point. > + */ > +rtems_device_driver > +frame_buffer_write( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + printk( FB_VESA_NAME " write device\n" ); > + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; > + rw_args->bytes_moved = > + ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? > + (fb_fix.smem_len - rw_args->offset) : > + rw_args->count; > + memcpy( (void *) (fb_fix.smem_start + rw_args->offset), > + rw_args->buffer, rw_args->bytes_moved); > + return RTEMS_SUCCESSFUL; > +} > + > +static int get_fix_screen_info( struct fb_fix_screeninfo *info ) > +{ > + printk("get_fix_screen_info\n"); > + *info = fb_fix; > + return 0; > +} > + > +static int get_var_screen_info( struct fb_var_screeninfo *info ) > +{ > + printk("get_var_screen_info\n"); > + *info = fb_var; > + return 0; > +} > + > +/* > + * IOCTL entry point -- This method is called to carry > + * all services of this interface. > + */ > +rtems_device_driver > +frame_buffer_control( > + rtems_device_major_number major, > + rtems_device_minor_number minor, > + void *arg > +) > +{ > + rtems_libio_ioctl_args_t *args = arg; > + > + printk( FB_VESA_NAME " ioctl called, cmd=%x\n", args->command ); > + printk("fbxres %d, fbyres %d\n", fb_var.xres, fb_var.yres); > + printk("fbbpp %d\n", fb_var.bits_per_pixel); > + > + switch (args->command) > + { > + case FBIOGET_FSCREENINFO: > + args->ioctl_return = > + get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer ); > + break; > + case FBIOGET_VSCREENINFO: > + args->ioctl_return = > + get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer ); > + break; > + case FBIOPUT_VSCREENINFO: > + /* not implemented yet */ > + args->ioctl_return = -1; > + return RTEMS_UNSATISFIED; > + case FBIOGETCMAP: > + /* no palette - truecolor mode */ > + args->ioctl_return = -1; > + return RTEMS_UNSATISFIED; > + case FBIOPUTCMAP: > + /* no palette - truecolor mode */ > + args->ioctl_return = -1; > + return RTEMS_UNSATISFIED; > + default: > + args->ioctl_return = 0; > + break; > + } > + return RTEMS_SUCCESSFUL; > +} > diff --git a/c/src/lib/libbsp/i386/pc386/include/fb_vesa.h > b/c/src/lib/libbsp/i386/pc386/include/fb_vesa.h > new file mode 100644 > index 0000000..5638b50 > --- /dev/null > +++ b/c/src/lib/libbsp/i386/pc386/include/fb_vesa.h > @@ -0,0 +1,131 @@ > +/** > + * @file fb_vesa.h > + * > + * @ingroup i386_pc386 > + * > + * @brief Definitioins for vesa based framebuffer drivers. > + */ > + > +/* > + * Headers specific for framebuffer drivers utilizing VESA VBE. > + * > + * Copyright (C) 2014 Jan Doležal (dolez...@fel.cvut.cz) > + * CTU in Prague. > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ > + > +#include <bsp/vbe3.h> > +#include <edid.h> > + > +#ifndef _FB_VESA_H > +#define _FB_VESA_H > + > +#ifndef ASM /* ASM */ > + > +#include <stdint.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif /* __cplusplus */ > + > + > +/* ----- Prototypes ----- */ > + > +/** > + * Returns information about graphic's controller in the infoBlock structure. > + * > + * @param infoBlock pointer to the struct to be filled with > + controller information > + * @param queriedVBEVersion if >0x200 then video bios is asked to fill in > + * parameters which appeared with second version > + * of VBE. > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBEControllerInformation ( > + struct VBE_VbeInfoBlock *infoBlock, > + uint16_t queriedVBEVersion > +); > + > +/** > + * Fills structure infoBlock with informations about selected mode in > + * modeNumber variable. > + * > + * @param infoBlock pointer to the struct to be filled with mode information > + * @param modeNumber detailes of this mode to be filled > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBEModeInformation ( > + struct VBE_ModeInfoBlock *infoBlock, > + uint16_t modeNumber > +); > + > +/** > + * Sets graphics mode selected. If mode has refreshRateCtrl bit set, than the > + * infoBlock must be filled accordingly. > + * > + * @param modeNumber number of mode to be set > + * @param infoBlock pointer to struct containing refresh rate control info > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBESetMode ( > + uint16_t modeNumber, > + struct VBE_CRTCInfoBlock *infoBlock > +); > + > +/** > + * Get currently set mode number. > + * > + * @param modeNumber variable to be filled with current mode number > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBECurrentMode ( > + uint16_t *modeNumber > +); > + > +/** > + * Gets information about display data channel implemented in the > + * graphic's controller. > + * > + * @param controllerUnitNumber > + * @param secondsToTransferEDIDBlock approximate time to transfer one EDID > block > + * rounded up to seconds > + * @param DDCLevelSupported after call contains DDC version supported and > + * screen blanking state during transfer > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBEReportDDCCapabilities ( > + uint16_t controllerUnitNumber, > + uint8_t *secondsToTransferEDIDBlock, > + uint8_t *DDCLevelSupported > +); > + > +/** > + * Reads selected EDID block from display attached to controller's interface. > + * > + * @param controllerUnitNumber > + * @param EDIDBlockNumber block no. to be read from the display > + * @param buffer place to store block fetched from the display > + * @retval register ax content as defined in VBE RETURN STATUS paragraph > + * -1 error calling graphical bios > + */ > +uint32_t VBEReadEDID ( > + uint16_t controllerUnitNumber, > + uint16_t EDIDBlockNumber, > + struct edid1 *buffer > +); > + > +#ifdef __cplusplus > +} > +#endif /* __cplusplus */ > + > +#endif /* ASM */ > + > +#endif /* _FB_VESA_H */ > diff --git a/c/src/lib/libbsp/i386/pc386/preinstall.am > b/c/src/lib/libbsp/i386/pc386/preinstall.am > index b4ac86b..33a230c 100644 > --- a/c/src/lib/libbsp/i386/pc386/preinstall.am > +++ b/c/src/lib/libbsp/i386/pc386/preinstall.am > @@ -147,6 +147,7 @@ $(PROJECT_INCLUDE)/i386_io.h: > ../../i386/shared/comm/i386_io.h $(PROJECT_INCLUDE > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i386_io.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/i386_io.h > > +if USE_VBE_RM > $(PROJECT_INCLUDE)/bsp/vbe3.h: include/vbe3.h > $(PROJECT_INCLUDE)/bsp/$(dirstamp) > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vbe3.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vbe3.h > @@ -155,6 +156,11 @@ $(PROJECT_INCLUDE)/edid.h: include/edid.h > $(PROJECT_INCLUDE)/$(dirstamp) > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/edid.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/edid.h > > +$(PROJECT_INCLUDE)/bsp/fb_vesa.h: include/fb_vesa.h > $(PROJECT_INCLUDE)/bsp/$(dirstamp) > + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/fb_vesa.h > +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/fb_vesa.h > +endif > + > $(PROJECT_INCLUDE)/pcibios.h: ../../i386/shared/pci/pcibios.h > $(PROJECT_INCLUDE)/$(dirstamp) > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pcibios.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/pcibios.h > diff --git a/c/src/lib/libbsp/i386/pc386/start/start.S > b/c/src/lib/libbsp/i386/pc386/start/start.S > index 1cba124..ab92a4f 100644 > --- a/c/src/lib/libbsp/i386/pc386/start/start.S > +++ b/c/src/lib/libbsp/i386/pc386/start/start.S > @@ -41,6 +41,7 @@ > > #include <rtems/asm.h> > #include <rtems/score/cpu.h> > +#include <bspopts.h> > > > /*----------------------------------------------------------------------------+ > | Size of heap and stack: > @@ -61,6 +62,9 @@ BEGIN_CODE > PUBLIC (start) # GNU default entry point > > EXTERN (boot_card) > +#ifdef USE_VBE_RM > + EXTERN (vesa_realmode_bootup_init) > +#endif > EXTERN (_load_segments) > EXTERN (_return_to_monitor) > EXTERN (_IBMPC_initVideo) > @@ -201,6 +205,10 @@ SYM (zero_bss): > +-------------------------------------------------------------------*/ > call _IBMPC_initVideo > > +#ifdef USE_VBE_RM > + call vesa_realmode_bootup_init > +#endif > + > /*---------------------------------------------------------------------+ > | Check CPU type. Enable Cache and init coprocessor if needed. > +---------------------------------------------------------------------*/ > -- > 1.9.1 > > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel -- Joel Sherrill, Ph.D. Director of Research & Development joel.sherr...@oarcorp.com On-Line Applications Research Ask me about RTEMS: a free RTOS Huntsville AL 35805 Support Available (256) 722-9985 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel