2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: dpmi.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
17 #pragma on (unreferenced)
33 int dpmi_find_dos_memory()
37 memset(&r,0,sizeof(r));
38 r.x.eax = 0x0100; // DPMI allocate DOS memory
39 r.x.ebx = 0xffff; // Number of paragraphs requested
40 int386 (0x31, &r, &r);
41 //if ( (r.x.eax & 0xffff) == 0x08 )
42 //if ( (r.x.eax & 0xffff) == 0x08 )
44 return ((r.x.ebx & 0xffff)*16);
49 void *dpmi_real_malloc( int size, ushort *selector )
53 memset(&r,0,sizeof(r));
54 r.x.eax = 0x0100; // DPMI allocate DOS memory
55 r.x.ebx = (size + 15) >> 4; // Number of paragraphs requested
56 int386 (0x31, &r, &r);
58 if (r.x.cflag) // Failed
62 *selector = r.x.edx & 0xFFFF;
64 return (void *) ((r.x.eax & 0xFFFF) << 4);
67 void dpmi_real_free( ushort selector )
71 memset(&r,0,sizeof(r));
72 r.x.eax = 0x0101; // DPMI free DOS memory
73 r.x.ebx = selector; // Selector to free
74 int386 (0x31, &r, &r);
78 void dpmi_real_int386x( ubyte intno, dpmi_real_regs * rregs )
83 /* Use DMPI call 300h to issue the DOS interrupt */
85 memset(®s,0,sizeof(regs));
86 memset(&sregs,0,sizeof(sregs));
91 sregs.es = FP_SEG(rregs);
92 regs.x.edi = FP_OFF(rregs);
93 int386x( 0x31, ®s, ®s, &sregs );
96 int dos_stack_initialized = 0;
97 ubyte * dos_stack = NULL;
98 ubyte * dos_stack_top = NULL;
99 #define DOS_STACK_SIZE (4*1024) // A big ol' 4K stack!!!
101 void dpmi_real_call(dpmi_real_regs * rregs)
103 ushort temp_selector;
107 if ( !dos_stack_initialized ) {
108 dos_stack_initialized = 1;
109 dos_stack = dpmi_real_malloc( DOS_STACK_SIZE, &temp_selector );
110 if ( dos_stack == NULL ) {
111 printf( "Error allocating real mode stack!\n" );
112 dos_stack_top = NULL;
114 dos_stack_top = &dos_stack[DOS_STACK_SIZE];
118 // Give this puppy a stack!!!
119 if ( dos_stack_top ) {
120 rregs->ss = DPMI_real_segment(dos_stack_top);
121 rregs->sp = DPMI_real_offset(dos_stack_top);
124 /* Use DMPI call 301h to call real mode procedure */
125 memset(®s,0,sizeof(regs));
126 memset(&sregs,0,sizeof(sregs));
130 sregs.es = FP_SEG(rregs);
131 regs.x.edi = FP_OFF(rregs);
132 int386x( 0x31, ®s, ®s, &sregs );
134 Error("bad return value <%x> in dpmi_call_real()", regs.w.ax);
139 int dpmi_unlock_region(void *address, unsigned length)
144 linear = (unsigned int) address;
146 total_bytes -= length;
147 //mprintf( 1, "DPMI unlocked %d bytes\n", total_bytes );
149 memset(®s,0,sizeof(regs));
150 regs.w.ax = 0x601; // DPMI Unlock Linear Region
151 regs.w.bx = (linear >> 16); // Linear address in BX:CX
152 regs.w.cx = (linear & 0xFFFF);
154 regs.w.si = (length >> 16); // Length in SI:DI
155 regs.w.di = (length & 0xFFFF);
156 int386 (0x31, ®s, ®s);
157 return (! regs.w.cflag); // Return 0 if can't lock
160 int dpmi_lock_region(void *address, unsigned length)
167 linear = (unsigned int) address;
169 total_bytes += length;
170 //mprintf( 1, "DPMI Locked down %d bytes\n", total_bytes );
172 memset(®s,0,sizeof(regs));
173 regs.w.ax = 0x600; // DPMI Lock Linear Region
174 regs.w.bx = (linear >> 16); // Linear address in BX:CX
175 regs.w.cx = (linear & 0xFFFF);
177 regs.w.si = (length >> 16); // Length in SI:DI
178 regs.w.di = (length & 0xFFFF);
179 int386 (0x31, ®s, ®s);
180 return (! regs.w.cflag); // Return 0 if can't lock
184 int dpmi_modify_selector_base( ushort selector, void * address )
189 linear = (unsigned int)address;
191 memset(®s,0,sizeof(regs));
192 regs.w.ax = 0x0007; // DPMI Change Selector Base Addres
193 regs.w.bx = selector; // Selector to change
194 regs.w.cx = (linear >> 16); // Base address
195 regs.w.dx = (linear & 0xFFFF);
196 int386 (0x31, ®s, ®s); // call dpmi
198 return 0; // Return 0 if error
204 int dpmi_modify_selector_limit( ushort selector, int size )
207 unsigned int segment_limit;
209 segment_limit = (unsigned int) size;
211 memset(®s,0,sizeof(regs));
212 regs.w.ax = 0x0008; // DPMI Change Selector Limit
213 regs.w.bx = selector; // Selector to change
214 regs.w.cx = (segment_limit >> 16); // Size of selector
215 regs.w.dx = (segment_limit & 0xFFFF);
216 int386 (0x31, ®s, ®s); // call dpmi
218 return 0; // Return 0 if error
224 int dpmi_allocate_selector( void * address, int size, ushort * selector )
229 memset(®s,0,sizeof(regs));
230 regs.w.ax = 0; // DPMI Allocate Selector
231 regs.w.cx = 1; // Allocate 1 selector
232 int386 (0x31, ®s, ®s); // call dpmi
234 return 0; // Return 0 if error
235 *selector = regs.w.ax;
237 if ( !dpmi_modify_selector_base( *selector, address ) )
240 if ( !dpmi_modify_selector_limit( *selector, size ) )
243 // mprintf( 0, "Selector 0x%4x has base of 0x%8x, size %d bytes\n", *selector, linear,segment_limit);
248 static void * dpmi_dos_buffer = NULL;
249 static ushort dpmi_dos_selector = 0;
253 if (dpmi_dos_selector!=0) {
254 dpmi_dos_buffer = NULL;
255 dpmi_dos_selector = 0;
259 typedef struct mem_data {
260 int largest_block_bytes;
261 int max_unlocked_page_allocation;
262 int largest_lockable_pages;
265 int unused_physical_pages;
266 int total_physical_pages;
267 int free_linear_pages;
268 int paging_size_pages;
272 unsigned int dpmi_virtual_memory=0;
273 unsigned int dpmi_available_memory=0;
274 unsigned int dpmi_physical_memory=0;
275 unsigned int dpmi_dos_memory = 0;
277 extern void cdecl _GETDS();
278 extern void cdecl cstart_();
280 int dpmi_init(int verbose)
286 dpmi_dos_memory = dpmi_find_dos_memory();
288 dpmi_dos_buffer = dpmi_real_malloc( 1024, &dpmi_dos_selector);
289 if (!dpmi_dos_buffer) {
290 dpmi_dos_selector = 0;
291 Error( "Error allocating 1K of DOS memory\n" );
296 memset(®s,0,sizeof(regs));
297 regs.x.eax = 0x400; // DPMI Get Memory Info
298 int386( 0x31, ®s, ®s );
300 if (verbose) printf( "V%d.%d, CPU:%d, VMM:", regs.h.ah, regs.h.al, regs.h.cl );
302 if (verbose) printf( "1" );
303 dpmi_virtual_memory = 1;
305 if (verbose) printf( "0" );
309 //--------- Find available memory
310 memset(®s,0,sizeof(regs));
311 memset(&sregs,0,sizeof(sregs));
312 regs.x.eax = 0x500; // DPMI Get Memory Info
313 sregs.es = FP_SEG(&mi);
314 regs.x.edi = FP_OFF(&mi);
315 int386x( 0x31, ®s, ®s, &sregs );
317 if (verbose) printf( ", P:%dK", mi.largest_lockable_pages*4 );
318 if (dpmi_virtual_memory)
319 if (verbose) printf( ", A:%dK", mi.largest_block_bytes/1024 );
320 //dpmi_physical_memory = mi.largest_lockable_pages*4096;
321 //dpmi_available_memory = mi.largest_block_bytes;
322 dpmi_physical_memory = mi.total_physical_pages*4096;
323 dpmi_available_memory = mi.total_pages * 4096;
325 if (verbose) printf( "MemInfo failed!" );
326 dpmi_physical_memory = 16*1024*1024; // Assume 16 MB
327 dpmi_available_memory = 16*1024*1024; // Assume 16 MB
330 if (!dpmi_lock_region( _GETDS, 4096 )) {
331 Error( "Can't lock _GETDS" );
333 if (!dpmi_lock_region( cstart_, 4096 )) {
334 Error( "Can't lock cstart" );
336 if (!dpmi_lock_region( _chain_intr, 4096 )) {
337 Error( "Can't lock _chain_intr" );
342 void *dpmi_get_temp_low_buffer( int size )
344 if ( dpmi_dos_buffer == NULL ) return NULL;
345 if ( size > 1024 ) return NULL;
347 return dpmi_dos_buffer;
350 int dpmi_set_pm_handler(unsigned intnum, void far * isr )
354 /* Use DMPI call 204h to get pm interrrupt */
355 memset(®s,0,sizeof(regs));
358 regs.w.cx = FP_SEG(isr);
359 regs.x.edx = FP_OFF(isr);
360 int386( 0x31, ®s, ®s );