1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 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 35 regs_t regs; 36 void (*dos_error_func)(char *msg, ...); 37 38 static unsigned conventional_memory = -1; 39 40 __dpmi_regs callback_regs; 41 42 void 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 53 unsigned int ptr2real(void *ptr) 54 { 55 map_in_conventional_memory(); 56 return (int)ptr - conventional_memory; 57 } 58 59 void *real2ptr(unsigned int real) 60 { 61 map_in_conventional_memory(); 62 return (void *) (real + conventional_memory); 63 } 64 65 void *far2ptr(unsigned int farptr) 66 { 67 return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff)); 68 } 69 70 unsigned int ptr2far(void *ptr) 71 { 72 return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf); 73 } 74 75 int dos_inportb(int port) 76 { 77 return inportb(port); 78 } 79 80 int dos_inportw(int port) 81 { 82 return inportw(port); 83 } 84 85 void dos_outportb(int port, int val) 86 { 87 outportb(port, val); 88 } 89 90 void dos_outportw(int port, int val) 91 { 92 outportw(port, val); 93 } 94 95 void dos_irqenable(void) 96 { 97 enable(); 98 } 99 100 void dos_irqdisable(void) 101 { 102 disable(); 103 } 104 105 // 106 // Returns 0 on success 107 // 108 109 int 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 117 int 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 131 static _go32_dpmi_seginfo seginfo[10]; 132 133 void *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 159 void 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 176 static struct handlerhistory_s 177 { 178 int intr; 179 _go32_dpmi_seginfo pm_oldvec; 180 } handlerhistory[4]; 181 182 static int handlercount=0; 183 184 void 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 205 void 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 226 void dos_usleep(int usecs) 227 { 228 usleep(usecs); 229 } 230 231 int dos_getheapsize(void) 232 { 233 return _go32_dpmi_remaining_physical_memory(); 234 } 235 236 int 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 247 int 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