• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
map_in_conventional_memory(void)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 
ptr2real(void * ptr)53 unsigned int ptr2real(void *ptr)
54 {
55 	map_in_conventional_memory();
56 	return (int)ptr - conventional_memory;
57 }
58 
real2ptr(unsigned int real)59 void *real2ptr(unsigned int real)
60 {
61 	map_in_conventional_memory();
62 	return (void *) (real + conventional_memory);
63 }
64 
far2ptr(unsigned int farptr)65 void *far2ptr(unsigned int farptr)
66 {
67 	return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff));
68 }
69 
ptr2far(void * ptr)70 unsigned int ptr2far(void *ptr)
71 {
72 	return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf);
73 }
74 
dos_inportb(int port)75 int dos_inportb(int port)
76 {
77 	return inportb(port);
78 }
79 
dos_inportw(int port)80 int dos_inportw(int port)
81 {
82 	return inportw(port);
83 }
84 
dos_outportb(int port,int val)85 void dos_outportb(int port, int val)
86 {
87 	outportb(port, val);
88 }
89 
dos_outportw(int port,int val)90 void dos_outportw(int port, int val)
91 {
92 	outportw(port, val);
93 }
94 
dos_irqenable(void)95 void dos_irqenable(void)
96 {
97 	enable();
98 }
99 
dos_irqdisable(void)100 void dos_irqdisable(void)
101 {
102 	disable();
103 }
104 
105 //
106 // Returns 0 on success
107 //
108 
dos_int86(int vec)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 
dos_int386(int vec,regs_t * inregs,regs_t * outregs)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 
dos_getmemory(int size)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 
dos_freememory(void * ptr)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 
dos_registerintr(int intr,void (* handler)(void))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 
dos_restoreintr(int intr)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 
dos_usleep(int usecs)226 void	dos_usleep(int usecs)
227 {
228 	usleep(usecs);
229 }
230 
dos_getheapsize(void)231 int dos_getheapsize(void)
232 {
233 	return _go32_dpmi_remaining_physical_memory();
234 }
235 
dos_lockmem(void * addr,int size)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 
dos_unlockmem(void * addr,int size)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