Mail Archives: djgpp/1993/08/11/14:30:16
To someone who knows the DPMI API,
I am trying to write some code that can access an extended memory mapped
display addaptor (Cornerstone DualPage 150I mapped at C00000 (12 Meg mark))
that can run under djgpp under DPMI. However every thing I've tried to access
the memory has failed. I was wondering if someone familiar with the DPMI API
might be able to tell me what I'm doing wrong.
The DPMI routines that I've written so far simply use the int86() function
call. I plan to rewrite these functions in assemby after I get this working.
When I run the test program under windows the DOS windows closes without any
messages. When I run the test program under QDPMI I get the following output:
test
graphics_screen = 80413000
graphics_selector = 107
fill
QDPMI: Unrecoverable Exception: 000D at 00EF:0000-138B. Error Code = 0000
The code follows. I have tried DPMI_SetSegmentBaseAddress w/ 0xC00000 and with
graphics_screen as returned from DPMI_PhysicalAddressMapping. I have tried
with and without the DPMI_SetDescriptorAccessRights. If anyone can tell me
what I have done wrong or have left out I would appreciat it. Thanks.
Potter
rri!potter AT vtserf DOT cc DOT vt DOT edu
/* FILE: test.c */
#include <pc.h>
#include <stdio.h>
#include "cstone.h"
#include <dpmi.h>
#define LINES 1664
#define COLS (256*8)
char *graphics_screen;
DPMI_Selector_t graphics_selector;
#define DPMI_try( op ) { \
if ( DPMI_STAT_OK != (op) ) { \
printf( "Failed " #op ); \
exit(1); \
} \
}
int init( void ) {
DPMI_AccessRights_t access;
access.accessed = 1; /* has been accessed */
access.read_write__readable = 1; /* is read/write */
access.expand_down__conforming = 0; /* expands up */
access.code = 0; /* is a data block */
access.memory_segment = 1; /* memory segment (DPMI must be 1) */
access.privilege = 3; /* privilege level of segment */
access.present = 1; /* block is present */
access.limit = 0; /* limit high bits (DPMI reserved) */
access.available = 1; /* available bit */
access.zero = 0; /* must be 0 */
access.thirty_two_bit = 1; /* a 32-bit segment */
access.page_granular = 0; /* uses byte granularity */
DPMI_try( DPMI_PhysicalAddressMapping ( (void**)&graphics_screen,
0xC00000, 1664 * 256 ) );
printf( "graphics_screen = %X\n", (int)graphics_screen );
DPMI_try( DPMI_AllocLDTDesciptors ( &graphics_selector, 1 ) );
printf( "graphics_selector = %X\n", graphics_selector );
DPMI_try( DPMI_SetSegmentBaseAddress ( graphics_selector,
graphics_screen ) );
/* DPMI_try( DPMI_SetSegmentBaseAddress ( graphics_selector,
(void*)0xC00000 ) ); */
DPMI_try( DPMI_SetSegmentLimit ( graphics_selector,
1664 * 256 ) );
DPMI_try( DPMI_SetDescriptorAccessRights ( graphics_selector,
access ) );
return 1;
}
void fill( void ) {
/*
int i;
*/
printf( "fill\n" );
/*
for (i=0;i<COLS;i++)
graphics_screen[i/256 + i*LINES] = 0xFF;
*/
graphics_screen[0] = 0xFF;
printf( "fill end\n" );
}
int main() {
printf( "test\n" );
if ( init() ) {
/*
CornerstoneSetGraphics();
CornerstoneEnableScreen();
*/
fill();
getkey();
/*
CornerstoneSetText();
*/
printf( "OK\n" );
} else {
printf( "init Error\n" );
}
return 0;
}
/* END: test.c */
/* FILE: partial dpmi.h */
#if !defined( dpmi_h )
#define dpmi_h
#define DPMI_STAT_OK 1
typedef int DPMI_Stat_t; /* <=0 -> error, >0 OK */
typedef unsigned short DPMI_Selector_t;
typedef unsigned short DPMI_Segment_t;
typedef struct {
unsigned int accessed : 1;
unsigned int read_write__readable : 1;
unsigned int expand_down__conforming : 1;
unsigned int code : 1;
unsigned int memory_segment : 1;
unsigned int privilege : 2;
unsigned int present : 1;
unsigned int limit : 4;
unsigned int available : 1;
unsigned int zero : 1;
unsigned int thirty_two_bit : 1;
unsigned int page_granular : 1;
} DPMI_AccessRights_t;
DPMI_Stat_t DPMI_AllocLDTDesciptors( /* 31-0000 */
DPMI_Selector_t *base_selector,
int num_descriptors
);
DPMI_Stat_t DPMI_SetSegmentBaseAddress( /* 31-0007 */
DPMI_Selector_t selector,
void* base_address
);
DPMI_Stat_t DPMI_SetSegmentLimit( /* 31-0008 */
DPMI_Selector_t selector,
unsigned long limit
);
DPMI_Stat_t DPMI_SetDescriptorAccessRights( /* 31-0009 */
DPMI_Selector_t selector,
DPMI_AccessRights_t rights
);
DPMI_Stat_t DPMI_PhysicalAddressMapping( /* 31-0800 */
void* *address,
unsigned long physical_address,
unsigned size
);
#endif
/* END: dpmi.h */
/* FILE: dpmiret.h */
#if !defined( dpmiret_h )
#define dpmiret_h
#define DPMI_ret( regs ) { \
if ( (regs).x.cflag == 0 ) { \
return DPMI_STAT_OK; \
} else \
return -(long int)((unsigned short)((regs).x.ax)); \
}
#define DPMI_op_ret( regs, op ) { \
if ( (regs).x.cflag == 0 ) { \
(op); \
return DPMI_STAT_OK; \
} else \
return -(long int)((unsigned short)((regs).x.ax)); \
}
#endif
/* END: dpmiret.h */
/* FILE: phyadmap.c */
#include <dos.h>
#include "dpmi.h"
#include "dpmiret.h"
/*
* Physical Address Mapping - Converts a physical address into a linear
* address. This function allows device drivers running under DPMI hosts
* which use paging to reach physical memory that is associated with their
* devices above the 1 MB boundary. Examples of such devices are the
* Weitek numeric coprocessor (usually mapped at 3 GB), butters that hold
* scanner bit maps, and high-end displays that can be configured to make
* display memory appear in extended memory.
*/
extern
DPMI_Stat_t DPMI_PhysicalAddressMapping(
void* *address,
unsigned long physical_address,
unsigned size
) {
union REGS regs;
regs.x.ax = 0x0800;
regs.x.bx = physical_address >> 16 & 0xFFFF;
regs.x.cx = physical_address & 0xFFFF;
regs.x.si = size >> 16 & 0xFFFF;
regs.x.di = size & 0xFFFF;
int86( 0x31, ®s, ®s );
DPMI_op_ret( regs,
(*address = (void*)( (unsigned long)regs.x.bx << 16
| regs.x.cx )) );
}
/* END: phyadmap.c */
/* FILE: ldtalloc.c */
#include <dos.h>
#include "dpmi.h"
#include "dpmiret.h"
/*
* Allocate LDT Descriptors - allocates on or more descriptors in the task's
* Local Descriptor Table (LDT). the descriptor(s) allocated must be
* initialized by the application with other function calls.
*/
extern
DPMI_Stat_t DPMI_AllocLDTDesciptors(
DPMI_Selector_t *base_selector,
int num_descriptors
) {
union REGS regs;
regs.x.ax = 0x0000;
regs.x.cx = num_descriptors;
int86( 0x31, ®s, ®s );
DPMI_op_ret( regs, (*base_selector = regs.x.ax) );
}
/* END: ldtalloc.c */
/* FILE: stsegba.c */
#include <dos.h>
#include "dpmi.h"
#include "dpmiret.h"
/*
* Set Segment Base Address - Sets the 32-bit linear base address field in the
* LDT descriptor for the specified segment
*/
extern
DPMI_Stat_t DPMI_SetSegmentBaseAddress(
DPMI_Selector_t selector,
void* base_address
) {
union REGS regs;
regs.x.ax = 0x0007;
regs.x.bx = selector;
regs.x.cx = ((unsigned long)base_address >> 16) & 0xFFFF;
regs.x.dx = (unsigned long)base_address & 0xFFFF;
int86( 0x31, ®s, ®s );
DPMI_ret( regs );
}
/* END: stsegba.c */
/* FILE: stseglim.c */
#include <dos.h>
#include "dpmi.h"
#include "dpmiret.h"
/* Set Segment Limit - Sets the limit field in the LDT descriptor for the
* specified segment
*/
extern
DPMI_Stat_t DPMI_SetSegmentLimit(
DPMI_Selector_t selector,
unsigned long limit
) {
union REGS regs;
regs.x.ax = 0x0008;
regs.x.bx = selector;
regs.x.cx = ((unsigned long)limit >> 16) & 0xFFFF;
regs.x.dx = (unsigned long)limit & 0xFFFF;
int86( 0x31, ®s, ®s );
DPMI_ret( regs );
}
/* END: stseglim.c */
/* FILE: stdescar.c */
#include <dos.h>
#include "dpmi.h"
#include "dpmiret.h"
/* Set Descriptor Access Right - Modifies the access rights and type fields in
* the LDT descriptor for the specified segment.
*/
extern
DPMI_Stat_t DPMI_SetDescriptorAccessRights(
DPMI_Selector_t selector,
DPMI_AccessRights_t rights
) {
union REGS regs;
regs.x.ax = 0x0009;
regs.x.bx = selector;
regs.x.cx = *(unsigned short*)&rights;
int86( 0x31, ®s, ®s );
DPMI_ret( regs );
}
/* END: stdescar.c */
- Raw text -