DOSBox-X
|
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 }