/* ** DPMI services for GNU_C ** ** (c) Rainer Schnitker 1994 */ #include #define INLINE static inline typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef struct { WORD lim_lo; WORD base_lo; BYTE base_mi,access,lim_hi,base_hi; } DESCRIPTOR ; typedef DESCRIPTOR *PDESCRIPTOR; typedef struct { DWORD LargestFree; DWORD MaxUnlockedPages; DWORD MaxLockedPages; DWORD AddressSpacePages; DWORD UnlockedPages; DWORD UnusedPages; DWORD PhysicalPages; DWORD FreeAddressSpacePages; DWORD PagingFilePages; /* or partition size */ DWORD reserved[3]; } FREEMEMINFO ; typedef FREEMEMINFO *PFREEMEMINFO; /* descriptor makros */ #define DESC_BASE(d) (((((DWORD)d.base_hi<<8)|(DWORD)d.base_mi)<<16)|(DWORD)d.base_lo) #define DESC_LIMIT(d) ((((DWORD)(d.lim_hi&15))<<16)|(DWORD)d.lim_lo) #define GATE_OFFSET(d) (((((DWORD)d.base_hi<<8)|(DWORD)d.lim_hi)<<16)|(DWORD)d.lim_lo) /* descriptor fields */ #define ACCESS_BIT 1 #define READ_BIT 2 #define WRITE_BIT 2 #define CONFIRMING_BIT 4 #define EXPAND_BIT 4 #define CODE_BIT 8 #define SEGMENT_BIT 16 #define PRESENT_BIT 128 #define AVL_BIT 16 #define DEFAULT_BIT 64 #define BIG_BIT 64 #define GRANULAR_BIT 128 #define DPL_MASK 96 #define TYPE_MASK 15 #define LIMIT_HI_MASK 15 #define APP_CODE_SEL 250 /* dpl=3 , read */ #define APP_DATA_SEL 242 /* dpl=3 ,write */ #define TYPE_CODE 10 #define TYPE_CONFIRM_CODE 14 #define TYPE_DATA 2 #define TYPE_EXPAND_DATA 6 #define TYPE_286TSS 1 #define TYPE_LDT 2 #define TYPE_BUSY286TSS 3 #define TYPE_286CALLGATE 4 #define TYPE_TASKGATE 5 #define TYPE_286INTGATE 6 #define TYPE_286TRAPGATE 7 #define TYPE_386TSS 9 #define TYPE_BUSY386TSS 11 #define TYPE_386CALLGATE 12 #define TYPE_386INTGATE 14 #define TYPE_386TRAPGATE 15 /* breakpoints-types */ #define BREAK_CODE 0x0001 #define BREAK_DATA_W1 0x0101 #define BREAK_DATA_RW1 0x0201 #define BREAK_DATA_W2 0x0102 #define BREAK_DATA_RW2 0x0202 #define BREAK_DATA_W4 0x0104 #define BREAK_DATA_RW4 0x0204 #define CHECKERR "jnc 1f\n\tmovl $-1, %0 \n\tjmp 2f \n\t1: \n\t" #define CHECK_ERR_DPMI10 "jc 2f\n\t" #define OKEAX0 "xorl %0, %0 \n\t2: \n\t" INLINE int GetDescriptor(int sel, DESCRIPTOR *desc) { register int _v; __asm__ __volatile__( "int $0x31 \n\t" CHECKERR OKEAX0 : "=r" (_v) : "b" (sel) , "D" ((long)desc) , "a" (0x0B) ); return _v ; } INLINE int GetFreeMemInfo(FREEMEMINFO *info) { register int _v; __asm__ __volatile__( "int $0x31 \n\t" CHECKERR OKEAX0 : "=r" (_v) : "D" ((long)info), "a" (0x500) ); return _v ; } int is_emx_exe(void) { register int ver; #ifdef __EMX__ /* os_version() uses ebx */ __asm__ ("pushl %ebx \n\t"); ver = __os_version(); __asm__ ("popl %ebx \n\t"); #else __asm__ __volatile__( "movb $0x30, %%ah \n\t" "int $0x21 \n\t" : "=a" (ver) : : "ax","bx"); #endif /* EMX set high eax to "em" */ if (ver >> 16 == 0x6d65) return 1; else return 0; } void PrintFreeMemInfo() { FREEMEMINFO fmi; FREEMEMINFO *fm = &fmi; if (is_emx_exe()) { puts("emx is running; no DPMI services"); return; } if (GetFreeMemInfo(fm)) return; printf("Largest available block : %lu Bytes = %lu KB\n", fm->LargestFree, fm->LargestFree >> 10); printf("Number free pages : %4lu = %4lu KB\n" ,fm->MaxUnlockedPages, fm->MaxUnlockedPages * 4); printf("Number free pages to lock : %4lu = %4lu KB\n" ,fm->MaxLockedPages, fm->MaxLockedPages * 4); printf("Number pages of linear addr space : %4lu = %4lu KB\n" ,fm->AddressSpacePages, fm->AddressSpacePages * 4); printf("Number pages not locked : %4lu = %4lu KB\n" ,fm->UnlockedPages, fm->UnlockedPages * 4); printf("Number pages not used : %4lu = %4lu KB\n" ,fm->UnusedPages, fm->UnusedPages * 4); printf("Number pages managed by the Dpmi : %4lu = %4lu KB\n" ,fm->PhysicalPages, fm->PhysicalPages * 4); printf("Number pages free addr space : %4lu = %4lu KB\n" ,fm->FreeAddressSpacePages, fm->FreeAddressSpacePages * 4); if (fm->PagingFilePages <= 0xFFFFFL) printf("Number pages in swapfile : %4lu = %4lu KB\n" ,fm->PagingFilePages, fm->PagingFilePages * 4); else printf("DPMI host paging partition : %lu Bytes = %lu MB\n" ,fm->PagingFilePages, fm->PagingFilePages >> 20); } static void PrintDescriptor(DESCRIPTOR *d) { BYTE flag; if (!(d->access & PRESENT_BIT)) { printf("Not Present\n"); return; } if (d->access & SEGMENT_BIT)/* code or data selector */ printf("Base=%02X%02X%04X Limit=%01X%04X %s DPL=%u %s %s %s %s\n", d->base_hi, d->base_mi, d->base_lo, d->lim_hi & LIMIT_HI_MASK, d->lim_lo, (d->lim_hi & GRANULAR_BIT) ? "Pages" : "Bytes", (d->access & DPL_MASK) >> 5, (d->lim_hi & DEFAULT_BIT) ? "32bit" : "16bit", (d->access & CODE_BIT) ? (d->access & CONFIRMING_BIT) ? "CONF" : "CODE" : (d->access & EXPAND_BIT) ? "EXPD" : "DATA", (d->access & WRITE_BIT) ? (d->access & CODE_BIT) ? "R" : "W" : "-", (d->access & ACCESS_BIT) ? "ACC" : " "); else { /* system selector */ flag = d->access & (BYTE) 7; switch (flag) { case 0: break; case 1: printf("TSS%s ", (d->access & 8) ? "386" : "286"); break; case 2: printf("LDT "); break; case 3: printf("BUSYTSS%s ", (d->access & 8) ? "386" : "286"); break; case 4: printf("CALLGATE%s ", (d->access & 8) ? "386" : "286"); break; case 5: printf("TASKGATE "); break; case 6: printf("INT_GATE%s ", (d->access & 8) ? "386" : "286"); break; case 7: printf("TRAPGATE%s ", (d->access & 8) ? "386" : "286"); break; } if (flag <= 3) { printf("Base=%02X%02X%04X Limit=%01X%04X DPL=%u\n", d->base_hi, d->base_mi, d->base_lo, d->lim_hi & LIMIT_HI_MASK, d->lim_lo, (d->access & DPL_MASK) >> 5); } else { printf("Sel=%04X Offset=%02X%02X%04X DPL=%u\n", d->base_lo, d->base_hi, d->lim_hi, d->lim_lo, (d->access & DPL_MASK) >> 5); } } /* else system descriptor */ } void show_descriptor(int sel, int number) { DESCRIPTOR desc; int i; if (is_emx_exe()) { puts("emx is running; no DPMI services"); return; } for (i = 1; i <= number; i++) { printf("sel %X: ", sel); if (GetDescriptor(sel, &desc)) { printf("- invalid -\n"); break; } PrintDescriptor(&desc); sel += 8; } }