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 *) ®s);
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