1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20#include <sys/segments.h> 21#include <go32.h> 22#include <unistd.h> 23#include <sys/nearptr.h> 24#include <dos.h> 25#include <string.h> 26#include <dpmi.h> 27// #include <osfcn.h> 28#include <bios.h> 29 30#include "dosisms.h" 31 32_go32_dpmi_registers hmm; 33 34// globals 35regs_t regs; 36void (*dos_error_func)(char *msg, ...); 37 38static unsigned conventional_memory = -1; 39 40__dpmi_regs callback_regs; 41 42void map_in_conventional_memory(void) 43{ 44 if (conventional_memory == -1) 45 { 46 if (__djgpp_nearptr_enable()) 47 { 48 conventional_memory = __djgpp_conventional_base; 49 } 50 } 51} 52 53unsigned int ptr2real(void *ptr) 54{ 55 map_in_conventional_memory(); 56 return (int)ptr - conventional_memory; 57} 58 59void *real2ptr(unsigned int real) 60{ 61 map_in_conventional_memory(); 62 return (void *) (real + conventional_memory); 63} 64 65void *far2ptr(unsigned int farptr) 66{ 67 return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff)); 68} 69 70unsigned int ptr2far(void *ptr) 71{ 72 return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf); 73} 74 75int dos_inportb(int port) 76{ 77 return inportb(port); 78} 79 80int dos_inportw(int port) 81{ 82 return inportw(port); 83} 84 85void dos_outportb(int port, int val) 86{ 87 outportb(port, val); 88} 89 90void dos_outportw(int port, int val) 91{ 92 outportw(port, val); 93} 94 95void dos_irqenable(void) 96{ 97 enable(); 98} 99 100void dos_irqdisable(void) 101{ 102 disable(); 103} 104 105// 106// Returns 0 on success 107// 108 109int dos_int86(int vec) 110{ 111 int rc; 112 regs.x.ss = regs.x.sp = 0; 113 rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) ®s); 114 return rc || (regs.x.flags & 1); 115} 116 117int dos_int386(int vec, regs_t *inregs, regs_t *outregs) 118{ 119 int rc; 120 memcpy(outregs, inregs, sizeof(regs_t)); 121 outregs->x.ss = outregs->x.sp = 0; 122 rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs); 123 return rc || (outregs->x.flags & 1); 124} 125 126// 127// Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep 128// the seginfo structure around for when you free the mem. 129// 130 131static _go32_dpmi_seginfo seginfo[10]; 132 133void *dos_getmemory(int size) 134{ 135 136 int rc; 137 _go32_dpmi_seginfo info; 138 static int firsttime=1; 139 int i; 140 141 if (firsttime) 142 { 143 memset(seginfo, 0, sizeof(seginfo)); 144 firsttime = 0; 145 } 146 147 info.size = (size+15) / 16; 148 rc = _go32_dpmi_allocate_dos_memory(&info); 149 if (rc) 150 return 0; 151 152 for (i=0;i<10;i++) 153 if (!seginfo[i].rm_segment) break; 154 seginfo[i] = info; 155 return real2ptr((int) info.rm_segment << 4); 156 157} 158 159void dos_freememory(void *ptr) 160{ 161 162 int i; 163 int segment; 164 165 segment = ptr2real(ptr) >> 4; 166 for (i=0 ; i<10 ; i++) 167 if (seginfo[i].rm_segment == segment) 168 { 169 _go32_dpmi_free_dos_memory(&seginfo[i]); 170 seginfo[i].rm_segment = 0; 171 break; 172 } 173 174} 175 176static struct handlerhistory_s 177{ 178 int intr; 179 _go32_dpmi_seginfo pm_oldvec; 180} handlerhistory[4]; 181 182static int handlercount=0; 183 184void dos_registerintr(int intr, void (*handler)(void)) 185{ 186 _go32_dpmi_seginfo info; 187 struct handlerhistory_s *oldstuff; 188 189 oldstuff = &handlerhistory[handlercount]; 190 191// remember old handler 192 _go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec); 193 oldstuff->intr = intr; 194 195 info.pm_offset = (int) handler; 196 _go32_dpmi_allocate_iret_wrapper(&info); 197 198// set new protected mode handler 199 _go32_dpmi_set_protected_mode_interrupt_vector(intr, &info); 200 201 handlercount++; 202 203} 204 205void dos_restoreintr(int intr) 206{ 207 208 int i; 209 struct handlerhistory_s *oldstuff; 210 211// find and reinstall previous interrupt 212 for (i=0 ; i<handlercount ; i++) 213 { 214 oldstuff = &handlerhistory[i]; 215 if (oldstuff->intr == intr) 216 { 217 _go32_dpmi_set_protected_mode_interrupt_vector(intr, 218 &oldstuff->pm_oldvec); 219 oldstuff->intr = -1; 220 break; 221 } 222 } 223 224} 225 226void dos_usleep(int usecs) 227{ 228 usleep(usecs); 229} 230 231int dos_getheapsize(void) 232{ 233 return _go32_dpmi_remaining_physical_memory(); 234} 235 236int dos_lockmem(void *addr, int size) 237{ 238 __dpmi_meminfo info; 239 info.address = (long) addr + __djgpp_base_address; 240 info.size = size; 241 if (__dpmi_lock_linear_region(&info)) 242 return __dpmi_error; 243 else 244 return 0; 245} 246 247int dos_unlockmem(void *addr, int size) 248{ 249 __dpmi_meminfo info; 250 info.address = (long) addr + __djgpp_base_address; 251 info.size = size; 252 if (__dpmi_unlock_linear_region(&info)) 253 return __dpmi_error; 254 else 255 return 0; 256} 257 258