home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cdisk.zip
/
MMAP
/
MMAP.DAT
< prev
next >
Wrap
Text File
|
1991-07-11
|
27KB
|
853 lines
// OS/2 Device Driver for memory mapped I/O
//
// Steve Mastrianni
// 15 Great Oak Lane
// Unionville, CT 06085
// (203) 693-0404 voice
// (203) 693-9042 data
// CI$ 71501,1652
// BIX smastrianni
// Internet 6099225@mcimail.com
//
// This driver is loaded in the config.sys file with the DEVICE=
// statement. For ISA configuration, the first parameter to the "DEVICE="
// is the board base memory address in hex.
//
// This driver also returns a boolean to the calling application to
// inform it of the bus type (Micro Channel or ISA).
//
// All numbers are in hex. For MCA configuration, the board address
// is read from the board POS regs. The POS regs data is specific for
// each adapter, so the address calculations here may not work with
// your specific adapter. Refer to the hardware tech reference for the
// particular adapter to determine where and how the address appears
// in the POS registers.
//
//
// This driver allows the application I/O to run in Ring 2 with IOPL.
// The CONFIG.SYS files *must* contain the IOPL=YES statement.
//
// This driver supports 4 IOCtls, Category 0x90.
//
// IOCtl 0x01 test for MCA or ISA bus
// IOCtl 0x02 gets and returns a selector to fabricated board memory
// IOCtl 0x03 gets the value of a selected POS register
// IOCtl 0x04 gets the board address that the driver found
//
// The driver is made by using the make file mmap.mak.
#include "drvlib.h"
#include "mmap.h"
extern void near STRATEGY(); // name of strat rout. in DDSTART
DEVICEHDR devhdr = {
(void far *) 0xFFFFFFFF, // link
(DAW_CHR | DAW_OPN | DAW_LEVEL1),// attribute
(OFF) STRATEGY, // &strategy
(OFF) 0, // &IDCroutine
"MMAP$ "
};
FPFUNCTION DevHlp=0; // storage area for DevHlp calls
LHANDLE lock_seg_han; // handle for locking appl. segment
PHYSADDR appl_buffer=0; // address of caller's buffer
PREQPACKET p=0L; // pointer to request packet
ERRCODE err=0; // error return
void far *ptr; // temp far pointer
USHORT i,j; // general counters
PHYSADDR board_address; // base board address
USHORT opencount; // count of DosOpens
USHORT savepid; // save the caller's PID
USHORT cntr = 0; // misc counter
USHORT bus = 0; // default ISA bus
REQBLK ABIOS_r_blk; // ABIOS request block
LIDBLK ABIOS_l_blk; // ABIOS LID block
USHORT lid_blk_size; // size of LID block
CARD card[MAX_NUM_SLOTS+1]; // array for IDs and POS reg values
CARD *pcard; // pointer to card array
USHORT matches = 0; // match flag for card ID
POS_STRUCT pos_struct; // struct to get POS reg
ADDR_STRUCT addr_struct; // struct for passing addresses
USHORT chunk1,chunk2; // temp variables for address calc
char arguments[64]={0}; // save command line args in dgroup
char NoMatchMsg[] = " no match for selected Micro Channel card ID found.\r\n";
char MainMsgMCA[] = "\r\nOS/2 Micro Channel memory-mapped driver installed.\r\n";
char MainMsgISA[] = "\r\nOS/2 ISA bus memory-mapped driver installed.\r\n";
// prototypes
int hex2bin(char c);
USHORT get_POS();
UCHAR get_pos_data();
UCHAR nget_pos_data();
// common entry point for calls to Strategy routines
int main(PREQPACKET rp )
{
void far *ptr;
int far *pptr;
PLINFOSEG liptr; // pointer to local info seg
int i;
ULONG addr;
USHORT in_data;
switch(rp->RPcommand)
{
case RPINIT: // 0x00
// init called by kernel in protected mode ring 3 with IOPL
return Init(rp);
case RPOPEN: // 0x0d
// get current processes id
if (GetDOSVar(2,&ptr))
return (RPDONE | RPERR | ERROR_BAD_COMMAND);
// get process info
liptr = *((PLINFOSEG far *) ptr);
// if this device never opened, can be opened by any process
if (opencount == 0) // first time this device opened
{
opencount=1; // set open counter
savepid = liptr->pidCurrent; // save current process id
}
else
{
if (savepid != liptr->pidCurrent) // another proc tried to open
return (RPDONE | RPERR | RPBUSY ); // so return error
++opencount; // bump counter, same pid
}
return (RPDONE);
case RPCLOSE: // 0x0e
// get process info of caller
if (GetDOSVar(2,&ptr))
return (RPDONE | RPERR | ERROR_BAD_COMMAND); // no info
// get process info from os/2
liptr= *((PLINFOSEG far *) ptr); // ptr to process info seg
//
// make sure that process attempting to close this device
// one that originally opened it and the device was open in
// first place.
//
if (savepid != liptr->pidCurrent || opencount == 0)
return (RPDONE | RPERR | ERROR_BAD_COMMAND);
// if an LDT selector was allocated, free it
PhysToUVirt(board_address,0x8000,2,&addr_struct.mapped_addr);
--opencount; // close counts down open counter
return (RPDONE); // return 'done' status to caller
case RPREAD: // 0x04
return(RPDONE);
case RPWRITE: // 0x08
return (RPDONE);
case RPIOCTL: // 0x10
if (rp->s.IOCtl.category != OUR_CAT) // only our category
return (RPDONE);
switch (rp->s.IOCtl.function)
{
// this IOCtl returns the bus type. If the type is Micro Channel
// the return is 0xff01. If ISA, the return is ff00
case 0x01: // check if MCA or ISA
return (RPDONE | RPERR | bus);
// this IOCtl maps an adapter memory to an LDT selector:offset,
// and sends it to the application for direct application reads
// and writes
case 0x02: // send memory-mapped addr to app
// verify caller owns this buffer area
if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.buffer), // selector
OFFSETOF(rp->s.IOCtl.buffer), // offset
8, // 8 bytes
1) ) // read write
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// lock the segment down temp
if(LockSeg(
SELECTOROF(rp->s.IOCtl.buffer), // selector
0, // lock < 2 sec
0, // wait for seg lock
(PLHANDLE) &lock_seg_han)) // handle returned
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// map the board address to an LDT entry
if ( PhysToUVirt(board_address,0x8000,1,&addr_struct.mapped_addr))
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// move data to users buffer
if(MoveBytes(
&addr_struct, // source
rp->s.IOCtl.buffer, // dest
8)) // 8 bytes
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// unlock segment
if(UnLockSeg(lock_seg_han))
return(RPDONE | RPERR | ERROR_GEN_FAILURE);
return (RPDONE);
// this IOCtl demonstrates how an application program can get the
// contents of a Micro Channel Adapter's POS registers
case 0x03: // get pos reg data
// verify caller owns this buffer area
if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.buffer), // selector
OFFSETOF(rp->s.IOCtl.buffer), // offset
6, // 6 bytes
1) ) // read write
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// lock the segment down temp
if(LockSeg(
SELECTOROF(rp->s.IOCtl.buffer), // selector
0, // lock < 2 sec
0, // wait for seg lock
(PLHANDLE) &lock_seg_han)) // handle returned
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// move slot data to driver buffer
if(MoveBytes(
(FARPOINTER) appl_buffer, // source
&pos_struct, // for pos data
6)) // 6 bytes
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
pos_struct.data = get_pos_data(pos_struct.slot,pos_struct.reg);
// move POS reg data to users buffer
if(MoveBytes(
&pos_struct, // for pos data
(FARPOINTER) appl_buffer, // source
6)) // 6 bytes
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// unlock segment
if(UnLockSeg(lock_seg_han))
return(RPDONE | RPERR | ERROR_GEN_FAILURE);
return (RPDONE);
// this IOCtl is essentially the same as 0x02, except the
// user virtual address is mapped to a linear address in the
// process address range and then sent to the application. This
// save the SelToFlat and FlatToSel each time the pointer is
// referenced.
case 0x04: // 32-bit memory-mapped addr to app
// verify caller owns this buffer area
if(VerifyAccess(
SELECTOROF(rp->s.IOCtl.buffer), // selector
OFFSETOF(rp->s.IOCtl.buffer), // offset
8, // 8 bytes
1) ) // read write
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// lock the segment down temp
if(LockSeg(
SELECTOROF(rp->s.IOCtl.buffer), // selector
0, // lock < 2 sec
0, // wait for seg lock
(PLHANDLE) &lock_seg_han)) // handle returned
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// map the board address to an LDT entry
if ( PhysToUVirt(board_address,0x8000,1,&addr_struct.mapped_addr))
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// now convert it to a linear address
if (VirtToLin(SELECTOROF(addr_struct.mapped_addr),
(ULONG)(OFFSETOF(addr_struct.mapped_addr)),
(PLINADDR)&addr_struct.mapped_addr))
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// move data to users buffer
if(MoveBytes(
&addr_struct, // source
rp->s.IOCtl.buffer, // dest
8)) // 8 bytes
return (RPDONE | RPERR | ERROR_GEN_FAILURE);
// unlock segment
if(UnLockSeg(lock_seg_han))
return(RPDONE | RPERR | ERROR_GEN_FAILURE);
return (RPDONE);
} // switch (rp->s.IOCtl.function
case RPDEINSTALL: // 0x14
return(RPDONE | RPERR | ERROR_BAD_COMMAND);
// all other commands are ignored
default:
return(RPDONE);
}
}
int hex2bin(char c)
{
if(c < 0x3a)
return (c - 48);
else
return (( c & 0xdf) - 55);
}
USHORT get_POS(USHORT slot_num,USHORT far *card_ID,UCHAR far *pos_regs)
{
USHORT rc, i, lid;
if (GetLIDEntry(0x10, 0, 1, &lid)) // get LID for POS
return (1);
// Get the size of the LID request block
ABIOS_l_blk.f_parms.req_blk_len = sizeof(struct lid_block_def);
ABIOS_l_blk.f_parms.LID = lid;
ABIOS_l_blk.f_parms.unit = 0;;
ABIOS_l_blk.f_parms.function = GET_LID_BLOCK_SIZE;
ABIOS_l_blk.f_parms.ret_code = 0x5a5a;
ABIOS_l_blk.f_parms.time_out = 0;
if (ABIOSCall(lid,0,(void far *)&ABIOS_l_blk))
return (1);
lid_blk_size = ABIOS_l_blk.s_parms.blk_size; // Get the block size
// Fill POS regs and card ID with FF in case this does not work
*card_ID = 0xFFFF;
for (i=0; i<NUM_POS_BYTES; i++) { pos_regs[i] = 0x00; };
// Get the POS registers and card ID for the commanded slot
ABIOS_r_blk.f_parms.req_blk_len = lid_blk_size;
ABIOS_r_blk.f_parms.LID = lid;
ABIOS_r_blk.f_parms.unit = 0;;
ABIOS_r_blk.f_parms.function = READ_POS_REGS_CARD;
ABIOS_r_blk.f_parms.ret_code = 0x5a5a;
ABIOS_r_blk.f_parms.time_out = 0;
ABIOS_r_blk.s_parms.slot_num = (UCHAR)slot_num & 0x0F;
ABIOS_r_blk.s_parms.pos_buf = (void far *)pos_regs;
ABIOS_r_blk.s_parms.card_ID = 0xFFFF;
if (ABIOSCall(lid,0,(void far *)&ABIOS_r_blk))
rc = 1;
else { // Else
*card_ID = ABIOS_r_blk.s_parms.card_ID; // Set the card ID value
rc = 0;
}
FreeLIDEntry(lid);
return(rc);
}
UCHAR get_pos_data (int slot, int reg)
{
UCHAR pos;
CARD *cptr;
cptr = &card[slot-1]; // set pointer to beg of card array
if (reg == 0) // card ID
pos = LOUSHORT(cptr->card_ID);
else
if ( reg == 1)
pos = HIUSHORT(cptr->card_ID);
else
pos = cptr->pos_regs[reg-2]; // POS data register
return (pos);
}
// Device Initialization Routine
int Init(PREQPACKET rp)
{
USHORT lid;
register char far *p;
// store DevHlp entry point
DevHlp = rp->s.Init.DevHlp; // save DevHlp entry point
if (!(GetLIDEntry(0x10, 0, 1, &lid))) { // get LID for POS
FreeLIDEntry(lid);
// Micro Channel (tm) setup section
bus = 1; // MCA bus
// Get the POS data and card ID for each of 8 possible slots
for (i=0;i <= MAX_NUM_SLOTS; i++)
get_POS(i+1,(FARPOINTER)&card[i].card_ID,(FARPOINTER)card[i].pos_regs);
matches = 0;
for (i=0, pcard = card; i <= MAX_NUM_SLOTS; i++, pcard++) {
if (pcard->card_ID == TARGET_ID) {
matches = 1;
break;
}
}
if (matches == 0) { // at least one board found
DosPutMessage(1, 8, devhdr.DHname);
DosPutMessage(1,strlen(NoMatchMsg),NoMatchMsg);
rp->s.InitExit.finalCS = (OFF) 0;
rp->s.InitExit.finalDS = (OFF) 0;
return (RPDONE | RPERR | ERROR_BAD_COMMAND);
}
// calculate the board address from the POS regs
board_address = ((unsigned long) get_pos_data(i+1, 4) << 16) |
((unsigned long)(get_pos_data(i+1, 3) & 1) << 15);
}
else
// ISA bus setup
{
bus = 0; // ISA bus
// get parameters, IRQ (not used yet), port addr and base mem addr
for (p = rp->s.Init.args; *p && *p != ' ';++p);// skip driver name
for (; *p == ' '; ++p); // skip blanks following driver name
if (*p)
{
board_address=0; // i/o port address
for (; *p != '\0'; ++p) // get board address
board_address = (board_address << 4) + (hex2bin(*p));
addr_struct.board_addr = board_address;
}
}
if (bus)
DosPutMessage(1,strlen(MainMsgMCA),MainMsgMCA);
else
DosPutMessage(1,strlen(MainMsgISA),MainMsgISA);
// send back our cs and ds end values to os/2
if (SegLimit(HIUSHORT((void far *) Init), &rp->s.InitExit.finalCS) ||
SegLimit(HIUSHORT((void far *) MainMsgISA), &rp->s.InitExit.finalDS))
Abort();
Beep(200,500);
Beep(200,500);
Beep(250,500);
Beep(300,500);
Beep(250,500);
Beep(300,500);
return (RPDONE);
}
LIBRARY PAC
PROTMODE
# makefile for memory mapped driver
mmap.sys: ddstart.obj mmap.obj
link /nod /noi /map ddstart+mmap,mmap.sys,mmap,c:\os2\doscalls+d:\lib\slibcep+\
d:\drvlib\drvlib\drvlib,mmap.def
mapsym mmap
ddstart.obj: ddstart.asm
masm -Mx -t -L -N ddstart;
mmap.obj: mmap.c drvlib.h mmap.h
cl -Fa -c -Asnw -Gs -G2 -Zl -Zp -Ox mmap.c
/*
include file for memory-mapped driver
*/
#define OUR_CAT 0x91 /* category for DosDevIOCtl */
#define MEMSIZE 32800 /* 32 K bytes per adapter */
#define POS_BASE 0x100 /* MCA adapter base */
#define TARGET_ID 0x6CFD /* adapter ID */
#define NUM_POS_BYTES 64
#define MAX_NUM_SLOTS 8
#define MAX_DEV_NUMS 8
#define MAX_NUM_DSPS 5
#define READY 0xFFFF /* dsp read */
#define POS_PORT 0x96
#define POS_BASE 0x100
/* Constants used by ABIOS calls */
#define GET_LID_BLOCK_SIZE 0x01
#define POS_LID 0x10
#define READ_POS_REGS 0x0B
#define READ_POS_REGS_RAM 0x0B
#define READ_POS_REGS_CARD 0x0D
typedef struct _POS_STRUCT {
USHORT slot;
USHORT reg;
USHORT data;
} POS_STRUCT;
typedef POS_STRUCT far *PPOS_STRUCT;
typedef struct _ADDR_STRUCT {
void far *mapped_addr;
ULONG board_addr;
} ADDR_STRUCT;
typedef ADDR_STRUCT far *PADDR_STRUCT;
typedef struct function_parms_def {
USHORT req_blk_len;
USHORT LID;
USHORT unit;
USHORT function;
USHORT resvd1;
USHORT resvd2;
USHORT ret_code;
USHORT time_out;
} function_parms_type;
typedef struct service_parms_def {
UCHAR slot_num; /* 10h */
UCHAR resvd3; /* 11h */
USHORT card_ID; /* 12h */
USHORT resvd4; /* 14h */
UCHAR far *pos_buf; /* 16h */
USHORT resvd5; /* 1Ah */
USHORT resvd6; /* 1Ch */
UCHAR resvd7[40]; /* 1Eh */
} service_parms_type;
typedef struct lid_service_parms_def {
UCHAR irpt_level; /* 10h */
UCHAR arb_level; /* 11h */
USHORT device_id; /* 12h */
USHORT unit_count; /* 14h */
USHORT flags; /* 16h */
USHORT blk_size; /* 18h */
USHORT secnd_id; /* 1Ah */
USHORT resvd6; /* 1Ch */
USHORT resvd7; /* 1Eh */
} lid_service_parms_type;
typedef struct req_block_def {
function_parms_type f_parms;
service_parms_type s_parms;
} REQBLK;
typedef struct lid_block_def {
function_parms_type f_parms;
lid_service_parms_type s_parms;
} LIDBLK;
typedef struct card_def {
USHORT card_ID; /* ID of the card in this slot */
UCHAR pos_regs[NUM_POS_BYTES];
} CARD;
#define INCL_DOSFILEMGR
#define INCL_DOS
#define INCL_DOSDEVICES
#define INCL_DOSDEVIOCTL
#include <os2.h>
#include <stdio.h>
#include "test.h"
HFILE driver_handle=0;
USHORT err;
UCHAR far *myptr=0;
USHORT ActionTaken;
USHORT rc;
ULONG FileSize=0;
USHORT FileAttribute;
ULONG Reserved=0L;
UCHAR Data1[8]={0};
UCHAR Data2=0;
PADDR_STRUCT paddr_ptr;
void main()
{
// open the driver
if ((rc = DosOpen("MMAP$ ",
&driver_handle,
&ActionTaken,
FileSize,
FileAttribute,
FILE_OPEN,
OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_ACCESS_READWRITE,
Reserved)) !=0)
{
printf("\nDosOpen failed, error = %d",rc);
DosExit(EXIT_PROCESS,0);
}
printf ("Bus Type = ");
rc = DosDevIOCtl(&Data1,&Data2,0x01,OUR_CAT,driver_handle);
if (rc & 0x01)
printf ("Micro Channel (tm)\n");
else
printf ("ISA\n");
if (rc = DosDevIOCtl(&Data1,&Data2,0x02,OUR_CAT,driver_handle))
{
printf ("DevIOCtl failed, error code = %d\n",rc);
DosExit(EXIT_PROCESS,0);
}
// pointer to data buffer
paddr_ptr = (PADDR_STRUCT) Data1;
printf ("Memory Mapped Address = %p\nPhysical Address = %lx\n",
paddr_ptr->mapped_addr,paddr_ptr->board_addr);
myptr = (void far *) paddr_ptr->mapped_addr;
printf ("First Byte Of Adapter = %x\n",*myptr);
// close driver
DosClose(driver_handle);
}
// include file for test.c
#define OUR_CAT 0x91 // category for DosDevIOCtl
#define DRIVER_BASE 0xD8000 // board address
#define BASE_LENGTH 0x1000 // length of memory map
typedef struct _ADDR_STRUCT {
void far *mapped_addr;
ULONG board_addr;
} ADDR_STRUCT;
typedef ADDR_STRUCT far *PADDR_STRUCT;
protmode
test.exe: test.obj
link16 test,test,test,+c:\os2\doscalls+d:\lib\llibcep,,test.def
test.obj: test.c
cl -AL -G2 -c test.c
#define INCL_DOS
#include <os2.h>
#define EABUF 0L
#define OUR_CAT 0x91L
#define BUS_TYPE 0x01L
#define GET_PTR 0x02L
#define GET_POS 0x03L
typedef struct _ADDR_STRUCT {
void * _Seg16 mapped_addr;
ULONG board_addr;
} ADDR_STRUCT;
typedef ADDR_STRUCT *PADDR_STRUCT;
char buf[100] = {0};
USHORT BytesRead;
ULONG ActionTaken; /* for file opens */
APIRET rc; /* return code for driver open */
ULONG FileSize=0; /* NULL file size */
ULONG FileAttribute; /* attribute bits */
HFILE handle=0;
UCHAR parmbuf [20];
UCHAR databuf[20];
ULONG plength,dlength;
PADDR_STRUCT paddr_ptr;
UCHAR * _Seg16 myptr;
main()
{
rc = DosOpen("MMAP$ ",
&handle,
&ActionTaken,
FileSize,
FileAttribute,
OPEN_ACTION_OPEN_IF_EXISTS,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT,
EABUF);
if (rc) {
printf("\nDosOpen failed, error = %ld",rc);
DosExit(EXIT_PROCESS,0); /* exit gracefully */
}
printf ("Bus Type = ");
rc = DosDevIOCtl(handle,OUR_CAT,BUS_TYPE,0,0L,&plength,databuf,8L,&dlength);
if (rc & 0x01)
printf ("Micro Channel (tm)\n");
else
printf ("ISA\n");
rc = DosDevIOCtl(handle,OUR_CAT,GET_PTR,0,0L,&plength,databuf,8L,&dlength);
if (rc)
{
printf ("DevIOCtl failed, error code = %ld\n",rc);
DosExit(EXIT_PROCESS,0);
}
paddr_ptr = (PADDR_STRUCT) databuf;
printf ("Memory Mapped Address = %p\nPhysical Address = %lx\n",
paddr_ptr->mapped_addr,paddr_ptr->board_addr);
myptr = paddr_ptr->mapped_addr;
printf ("First Byte Of Adapter = %x\n",*myptr);
DosClose(handle);
}
name test32
protmode
test32.exe: test32.obj
link386 /MAP /NOI /PM:vio test32,test32,test32,,,test32.def
test32.obj: test32.c
icc /c /Gt+ test32.c
#define INCL_DOS
#include <os2.h>
#define EABUF 0L
#define OUR_CAT 0x91L
#define BUS_TYPE 0x01L
#define GET_PTR 0x02L
#define GET_POS 0x03L
#define GET_LIN 0x04L
typedef struct _ADDR_STRUCT {
void *mapped_addr;
ULONG board_addr;
} ADDR_STRUCT;
typedef ADDR_STRUCT *PADDR_STRUCT;
char buf[100] = {0};
USHORT BytesRead;
ULONG ActionTaken; /* for file opens */
APIRET rc; /* return code for driver open */
ULONG FileSize=0; /* NULL file size */
ULONG FileAttribute; /* attribute bits */
HFILE handle=0;
UCHAR parmbuf [20];
UCHAR databuf[20];
ULONG plength,dlength;
PADDR_STRUCT paddr_ptr;
UCHAR *myptr;
main()
{
rc = DosOpen("MMAP$ ",
&handle,
&ActionTaken,
FileSize,
FileAttribute,
OPEN_ACTION_OPEN_IF_EXISTS,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT,
EABUF);
if (rc) {
printf("\nDosOpen failed, error = %ld",rc);
DosExit(EXIT_PROCESS,0); /* exit gracefully */
}
printf ("Bus Type = ");
rc = DosDevIOCtl(handle,OUR_CAT,BUS_TYPE,0,0L,&plength,databuf,8L,&dlength);
if (rc & 0x01)
printf ("Micro Channel (tm)\n");
else
printf ("ISA\n");
rc = DosDevIOCtl(handle,OUR_CAT,GET_LIN,0,0L,&plength,databuf,8L,&dlength);
if (rc)
{
printf ("DevIOCtl failed, error code = %ld\n",rc);
DosExit(EXIT_PROCESS,0);
}
paddr_ptr = (PADDR_STRUCT) databuf;
printf ("Memory Mapped Address = %p\nPhysical Address = %lx\n",
paddr_ptr->mapped_addr,paddr_ptr->board_addr);
myptr = paddr_ptr->mapped_addr;
printf ("First Byte Of Adapter = %x\n",*myptr);
DosClose(handle);
}
protmode
test32a.exe: test32a.obj
link386 /MAP /NOI /PM:vio test32a,test32a,test32a,,,test32a.def
test32a.obj: test32a.c
icc /c /Gt+ test32a.c