DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/voodoo.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #include "dosbox.h"
00024 #include "config.h"
00025 #include "setup.h"
00026 #include "cross.h"
00027 #include "control.h"
00028 
00029 #include "paging.h"
00030 #include "mem.h"
00031 
00032 #include "voodoo.h"
00033 #include "pci_bus.h"
00034 #include "voodoo_interface.h"
00035 
00036 class VOODOO;
00037 static VOODOO* voodoo_dev;
00038 
00039 static Bit32u voodoo_current_lfb=(VOODOO_INITIAL_LFB&0xffff0000);
00040 
00041 static bool voodoo_pci_enabled = false;
00042 static MEM_Callout_t voodoo_lfb_cb = MEM_Callout_t_none;
00043 
00044 PageHandler* voodoo_lfb_memio_cb(MEM_CalloutObject &co,Bitu phys_page) {
00045     (void)phys_page;//UNUSED
00046     (void)co;//UNUSED
00047     if (voodoo_current_lfb == 0)
00048         return NULL;
00049 
00050     return VOODOO_GetPageHandler();
00051 }
00052 
00053 void voodoo_lfb_cb_free(void) {
00054     if (voodoo_lfb_cb != MEM_Callout_t_none) {
00055         MEM_FreeCallout(voodoo_lfb_cb);
00056         voodoo_lfb_cb = MEM_Callout_t_none;
00057     }
00058 }
00059 
00060 void voodoo_lfb_cb_init() {
00061     if (voodoo_lfb_cb == MEM_Callout_t_none) {
00062         voodoo_lfb_cb = MEM_AllocateCallout(MEM_TYPE_PCI);
00063         if (voodoo_lfb_cb == MEM_Callout_t_none) E_Exit("Unable to allocate voodoo cb for LFB");
00064     }
00065 
00066     {
00067         MEM_CalloutObject *cb = MEM_GetCallout(voodoo_lfb_cb);
00068 
00069         assert(cb != NULL);
00070 
00071         cb->Uninstall();
00072 
00073         if (voodoo_current_lfb != 0 && voodoo_pci_enabled) {
00074             /* VOODOO_PAGES is a power of two already */
00075             LOG_MSG("VOODOO LFB now at %x",voodoo_current_lfb);
00076             cb->Install(voodoo_current_lfb>>12UL,MEMMASK_Combine(MEMMASK_FULL,MEMMASK_Range(VOODOO_PAGES)),voodoo_lfb_memio_cb);
00077         }
00078         else {
00079             LOG_MSG("VOODOO LFB disabled");
00080         }
00081 
00082         MEM_PutCallout(cb);
00083     }
00084 }
00085 
00086 class VOODOO:public Module_base{
00087 private:
00088     Bits emulation_type;
00089 public:
00090     VOODOO(Section* configuration):Module_base(configuration){
00091         emulation_type=-1;
00092 
00093         Section_prop * section=static_cast<Section_prop *>(configuration);
00094         std::string voodoo_type_str(section->Get_string("voodoo"));
00095         if (voodoo_type_str=="false") {
00096             emulation_type=0;
00097         } else if (voodoo_type_str=="software") {
00098             emulation_type=1;
00099 #if C_OPENGL
00100         } else if ((voodoo_type_str=="opengl") || (voodoo_type_str=="auto")) {
00101             emulation_type=2;
00102 #else
00103         } else if (voodoo_type_str=="auto") {
00104             emulation_type=1;
00105 #endif
00106         } else {
00107             emulation_type=0;
00108         }
00109 
00110         Bits card_type = 1;
00111         bool max_voodoomem = true;
00112 
00113         bool needs_pci_device = false;
00114 
00115         switch (emulation_type) {
00116             case 1:
00117             case 2:
00118                 Voodoo_Initialize(emulation_type, card_type, max_voodoomem);
00119                 needs_pci_device = true;
00120                 break;
00121             default:
00122                 break;
00123         }
00124 
00125         if (needs_pci_device) PCI_AddSST_Device((Bitu)card_type);
00126     }
00127 
00128     ~VOODOO(){
00129         PCI_RemoveSST_Device();
00130 
00131         if (emulation_type<=0) return;
00132 
00133         switch (emulation_type) {
00134             case 1:
00135             case 2:
00136                 Voodoo_Shut_Down();
00137                 break;
00138             default:
00139                 break;
00140         }
00141 
00142         emulation_type=-1;
00143     }
00144 
00145     void PCI_InitEnable(Bitu val) {
00146         switch (emulation_type) {
00147             case 1:
00148             case 2:
00149                 Voodoo_PCI_InitEnable(val);
00150                 break;
00151             default:
00152                 break;
00153         }
00154     }
00155 
00156     void PCI_Enable(bool enable) {
00157         switch (emulation_type) {
00158             case 1:
00159             case 2:
00160                 Voodoo_PCI_Enable(enable);
00161                 break;
00162             default:
00163                 break;
00164         }
00165     }
00166 
00167     PageHandler* GetPageHandler() {
00168         switch (emulation_type) {
00169             case 1:
00170             case 2:
00171                 return Voodoo_GetPageHandler();
00172             default:
00173                 break;
00174         }
00175         return NULL;
00176     }
00177 
00178 };
00179 
00180 
00181 void VOODOO_PCI_InitEnable(Bitu val) {
00182     if (voodoo_dev!=NULL) {
00183         voodoo_dev->PCI_InitEnable(val);
00184     }
00185 }
00186 
00187 void VOODOO_PCI_Enable(bool enable) {
00188     if (voodoo_dev!=NULL) {
00189         voodoo_dev->PCI_Enable(enable);
00190     }
00191 }
00192 
00193 
00194 void VOODOO_PCI_SetLFB(Bit32u lfbaddr) {
00195     lfbaddr &= 0xFFFF0000UL;
00196 
00197     if (lfbaddr == voodoo_current_lfb)
00198         return;
00199 
00200     voodoo_current_lfb = lfbaddr;
00201     voodoo_lfb_cb_init();
00202 }
00203 
00204 bool VOODOO_PCI_CheckLFBPage(Bitu page) {
00205     if (voodoo_current_lfb != 0 &&
00206         (page>=(voodoo_current_lfb>>12)) &&
00207         (page<(voodoo_current_lfb>>12)+VOODOO_PAGES))
00208         return true;
00209     return false;
00210 }
00211 
00212 PageHandler* VOODOO_GetPageHandler() {
00213     if (voodoo_dev!=NULL) {
00214         return voodoo_dev->GetPageHandler();
00215     }
00216     return NULL;
00217 }
00218 
00219 
00220 void VOODOO_Destroy(Section* /*sec*/) {
00221     delete voodoo_dev;
00222     voodoo_dev=NULL;
00223 }
00224 
00225 void VOODOO_OnPowerOn(Section* /*sec*/) {
00226     if (voodoo_dev == NULL) {
00227         voodoo_pci_enabled = true;
00228         voodoo_current_lfb=(VOODOO_INITIAL_LFB&0xffff0000);
00229         voodoo_dev = new VOODOO(control->GetSection("pci"));
00230 
00231         voodoo_lfb_cb_init();
00232     }
00233 }
00234 
00235 void VOODOO_Init() {
00236     LOG(LOG_MISC,LOG_DEBUG)("Initializing Voodoo/3DFX emulation");
00237 
00238     AddExitFunction(AddExitFunctionFuncPair(VOODOO_Destroy),true);
00239     AddVMEventFunction(VM_EVENT_POWERON,AddVMEventFunctionFuncPair(VOODOO_OnPowerOn));
00240 }