/** ** u_vesa.c ---- interface utility functions to VESA BIOS inquiry calls ** ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221 ** [e-mail: csaba@vuse.vanderbilt.edu] ** ** This file is part of the GRX graphics library. ** ** The GRX graphics library is free software; you can redistribute it ** and/or modify it under some conditions; see the "copying.grx" file ** for details. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** ** Contributions by: (See "doc/credits.doc" for details) ** Hartmut Schirmer (hsc@xaphod.techfak.uni-kiel.d400.de) **/ #include "libgrx.h" #include "allocate.h" #include "vesa.h" #include "mempeek.h" #include "memfill.h" #include "int86.h" #ifndef IREG_AX int _GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock *ib) { return(FALSE); } int _GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock *ib) { return(FALSE); } VESApmInfoBlock * _GrViDrvVESAgetPMinfo(void) { return(NULL); } #else int _GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock *ib) { static char *nmcopy = NULL; static short *mdcopy = NULL; Int86Regs regs; short *mp; short *modes; char *p1; char *p2; int ii; DECLARE_XFER_BUFFER(1000); /* * copy VBE 2.0 tag into XFER buffer */ setup_far_selector(LINP_SEL(XFER_BUFFER)); p1 = (char *)LINP_PTR(XFER_BUFFER); poke_b_f(p1,'V'); ++p1; poke_b_f(p1,'B'); ++p1; poke_b_f(p1,'E'); ++p1; poke_b_f(p1,'2'); ++p1; /* * set up registers and call interrupt */ sttzero(®s); IREG_AX(regs) = VESA_FUNC + VESA_VGA_INFO; IREG_ES(regs) = FP_SEG(XFER_BUFFER); IREG_DI(regs) = FP_OFF(XFER_BUFFER); int10x(®s); if(IREG_AX(regs) != VESA_SUCCESS) { DELETE_XFER_BUFFER; return(FALSE); } /* * copy VESA info block into accessible memory */ setup_far_selector(LINP_SEL(XFER_BUFFER)); p1 = (char *)LINP_PTR(XFER_BUFFER); p2 = (char *)ib; for(ii = sizeof(*ib); --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1); if ( ib->VESAsignature[0] != 'V' || ib->VESAsignature[1] != 'E' || ib->VESAsignature[2] != 'S' || ib->VESAsignature[3] != 'A' ) { DELETE_XFER_BUFFER; return(FALSE); } /* * allocate space and copy mode list into accessible memory */ mp = LINP_PTR(MK_FP(FP86_SEG(ib->VideoModePtr),FP86_OFF(ib->VideoModePtr))); p1 = (char *)mp; for(ii = 1; (short)peek_w_f(mp) != (short)(-1); mp++,ii++); modes = mdcopy = realloc(mdcopy,ii * sizeof(short)); if(!modes) { DELETE_XFER_BUFFER; return(FALSE); } ib->VideoModePtr = modes; mp = (short *)p1; for( ; --ii >= 0; mp++,modes++) *modes = peek_w_f(mp); /* * allocate space and copy ID string into accessible memory */ p1 = LINP_PTR(MK_FP(FP86_SEG(ib->OEMstringPtr),FP86_OFF(ib->OEMstringPtr))); mp = (short *)p1; for(ii = 1; (char)peek_b_f(p1) != (char)(0); p1++,ii++); p2 = nmcopy = realloc(nmcopy,ii * sizeof(char)); if(!p2) { DELETE_XFER_BUFFER; return(FALSE); } ib->OEMstringPtr = p2; p1 = (char *)mp; for( ; --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1); DELETE_XFER_BUFFER; return(TRUE); } VESApmInfoBlock * _GrViDrvVESAgetPMinfo(void) { Int86Regs r; static VESApmInfoBlock *ib = NULL; unsigned Length, ii; char *p1; char *p2; sttzero(&r); IREG_AX(r) = VESA_FUNC + VESA_PM_INTERF; IREG_BX(r) = 0x0000; DBGPRINTF(DBG_DRIVER,("Getting protected mode interface\n")); int10x(&r); if(IREG_AX(r) != VESA_SUCCESS) return(NULL); /* Now we have : CX = length of table and routines (bytes) ES:DI = pointer to table ES_DI+00: offset PM set window routine +02: offset PM set display start +04: offset PM set primary palette +06: offset PM description table */ Length = (unsigned)IREG_CX(r); if( Length == 0) return(NULL); ib = realloc(ib, Length + VESApmInfoBlock_BASEOFF); if (ib == NULL) return(NULL); ib->RealMode_SEG = IREG_ES(r); ib->RealMode_OFF = IREG_DI(r); ib->PhysicalLength = IREG_CX(r); setup_far_selector(LINP_SEL(MK_FP( IREG_ES(r),IREG_DI(r)))); p1 = LINP_PTR( MK_FP( IREG_ES(r),IREG_DI(r) ) ); p2 = (char *) &(ib->SetWindow_off); for(ii = 0; ii < Length; p1++,ii++) *(p2++) = peek_b_f(p1); DBGPRINTF(DBG_DRIVER,("Protected Mode Interface :-\n" )); DBGPRINTF(DBG_DRIVER,(" Real mode address = 0x%04x:0x%04x\n",ib->RealMode_SEG,ib->RealMode_OFF)); DBGPRINTF(DBG_DRIVER,(" Length = 0x%08x\n",ib->PhysicalLength)); DBGPRINTF(DBG_DRIVER,(" SetWindow function offset = 0x%08x\n",ib->SetWindow_off)); DBGPRINTF(DBG_DRIVER,(" SetDisplayStart function offset = 0x%08x\n",ib->DisplStart_off)); DBGPRINTF(DBG_DRIVER,(" Primary Palette function offset = 0x%08x\n",ib->PPalette_off)); DBGPRINTF(DBG_DRIVER,(" Resource Sub-Table offset = 0x%08x\n",ib->SubTable_off)); #ifdef DUMP_PM_TABLE { static int once = 0; if (!once) { int len; FILE *dump = fopen("vesapm.s", "wt"); once = 1; if (dump) { p2 = (char *) &(ib->SetWindow_off); fprintf(dump, ".text\n_vesa_pm_table:\n"); for (len=0; len < Length; ++len) { fprintf(dump, "\t.byte %u\n", *(unsigned char *)p2); ++p2; } fclose(dump); } dump = fopen("vesapm.dmp", "wb"); if (dump) { p2 = (char *) &(ib->SetWindow_off); fwrite(p2,Length,1,dump); fclose(dump); } } } #endif return(ib); } int _GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock *ib) { Int86Regs regs; char *p1; char *p2; int ii; DECLARE_XFER_BUFFER(1000); /* * set up registers and call interrupt */ sttzero(®s); IREG_AX(regs) = VESA_FUNC + VESA_MODE_INFO; IREG_CX(regs) = mode; IREG_ES(regs) = FP_SEG(XFER_BUFFER); IREG_DI(regs) = FP_OFF(XFER_BUFFER); int10x(®s); if(IREG_AX(regs) != VESA_SUCCESS) { DELETE_XFER_BUFFER; return(FALSE); } /* * copy VESA info block into accessible memory */ setup_far_selector(LINP_SEL(XFER_BUFFER)); p1 = (char *)LINP_PTR(XFER_BUFFER); p2 = (char *)ib; for(ii = sizeof(*ib); --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1); DELETE_XFER_BUFFER; return((ib->ModeAttributes & MODE_SUPPORTED) ? TRUE : FALSE); } #endif