Home | History | Annotate | Download | only in WinQuake
      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 *) &regs);
    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