/* example of PCI config register, IO and memory access under DOS */
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <pc.h>
#include <dpmi.h>
#include <sys\farptr.h>
#include <go32.h>

#define u_int unsigned int
#define u_short unsigned short
#define u_char unsigned char
#define AH r.h.ah
#define AL r.h.al
#define BH r.h.bh
#define BL r.h.bl
#define CH r.h.ch
#define CL r.h.cl
#define CF r.h.cflag
#define ECX r.d.ecx
#define EDX r.d.edx
#define CX r.x.cx
#define DI r.x.di

u_int map(u_int addr, u_int size);

int main()
{
u_int slctr=0;
u_char lastbus;
u_char bus ;
u_char dev ;
u_char fun ;
u_char siz ;
u_char reg ;
union REGS r;
AH = 0xb1 ;
AL = 0x01 ;
int86(0x1a,&r,&r);
lastbus = CL;
if ((EDX == 0x20494350) /*" ICP"*/  && !AH && !CF)
	printf("PCI bios found, version %02x.%02x, last bus # %02x\n",BH,BL,lastbus);
else
	printf("PCI BIOS not found:\nEDX = %04lx\nAH=%02x\nAL=%02x\nBH=%02x\nBL=%02x\nCL=%02x\nCF=%02lx\n",EDX,AH,AL,BH,BL,CL,CF);
bus = 0;
dev = 0; 
fun = 0; 
siz = 0; 
reg = 0; 
AH = 0xb1 ;
AL = 0x0a ;
BH = bus ;
BL = dev << 3 ;
BL &= ~7 ;
BL |= (fun & 7) ;
DI = reg & ~3 ;
int86(0x1a,&r,&r);
if (!CF)
	printf("The value of bus 0 device 0 function 0 register 0 is 0x%08x\n",(u_int)ECX);
else
	printf ("error reading PCI config register\n");
printf("The data at IO address 0x3C2 is 0x%02x\n",inportb(0x3C2));
slctr = _dos_ds;
printf("The data at memory location 4 is %08x\n",(u_int)_farpeekl(slctr,4));
slctr = map(0x100000,0x1000);
if (slctr == -1)
	printf ("error selecting memory\n");
else
	printf("The data at memory location 0x100004 is %08x\n",(u_int)_farpeekl(slctr,4));
return 0;
}

/* map physical memory */
u_int map(u_int addr, u_int size)
{
__dpmi_meminfo mi;
int selector;

/* addr &= (size - 1); */
mi.handle = 0;
mi.address = addr;
mi.size = size;
if (__dpmi_physical_address_mapping(&mi))
	{
	printf ("__dpmi_physical_address_mapping failed\n");
	return -1;
	}
selector = __dpmi_allocate_ldt_descriptors(1);
if (selector == -1)
	{
	printf ("__dpmi_allocate_ldt_descriptors failed\n");
	return -1;
	}
if(__dpmi_set_segment_base_address(selector,mi.address))
	{
	printf ("__dpmi_set_segment_base_address failed\n");
	return -1;
	}
if(__dpmi_set_segment_limit(selector,mi.size-1))
	{
	printf ("__dpmi_set_segment_limit failed\n");
	return -1;
	}
return selector;
}
