www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/10/22/02:14:38

From: "A. Sinan Unur" <asu1 AT cornell DOT edu>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: protected mode -> real mode help.
Date: Mon, 21 Oct 1996 01:33:58 -0400
Organization: Cornell University
Lines: 175
Sender: asu1 AT cornell DOT edu (Verified)
Message-ID: <326B0B46.1D0B@cornell.edu>
References: <326AB9FD DOT 6CDF AT iamerica DOT net>
NNTP-Posting-Host: cu-dialup-0060.cit.cornell.edu
Mime-Version: 1.0
To: Jon Slaughter <lobo AT iamerica DOT net>
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Jon Slaughter wrote:
> 
> I need some help on how to call a real mode interrupt(I think I got
> that, though) and how to allocate a real mode buffer. Heres some code
> that I need it for. I want to read in a sector off the floppy disk to a
> buffer, copy the buffer to the BR struct or just read the sector
> directly into the BR struct... any help would be appreciated. Thanks.
> 
unfortunately, i am in the middle of something right now so i won't be
able to comment specifically on your code. however, i am going to
include some code that i have wrote to do netbios stuff which should
help clarify things. the first thing you should keep in mind is that
djgpp might leave gaps between the elements of a struct so as to be able
align them on 4-byte boundaries. so, any structure that you will be
using with any routines that do not expect such gaps need to be "packed"
as in the example below:

typedef struct {
BYTE	cmd	  __attribute__((packed));
BYTE	ret_code  __attribute__((packed));
BYTE	lsn	  __attribute__((packed));
BYTE	ncb_num	  __attribute__((packed));
WORD	io_off    __attribute__((packed));
WORD	io_seg	  __attribute__((packed));
... etc, etc ...
BYTE	cmp_code  __attribute__((packed));
BYTE	rsrv[14]  __attribute__((packed));
} NCB;

the precise meanings of these fields are not important. what is
important is that each of them is followed by the
__attribute__((packed)) tag so that there are no gaps between them.

my method of passing such a structure to a dos interrupt involves (i)
declaring a variable of of that struct's type, e.g. NCB ncb; (ii)
allocating some dos memory for the struct; (iii) setting the members of
the struct using the local copy and then copying that variable to the
memory area i set up in dos memory. imho, this has the advantage of
minimizing accesses to dos memory. the function i use to allocate dos
memory is:

/*
 * DosMem.H
 */
 
#ifndef DOSMEM_H_INCLUDED
#define DOSMEM_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

#include "types_u.h" /* typdefs BYTE, WORD and DWORD */

typedef struct {
	WORD seg;
	WORD off;
	DWORD addr;
	DWORD laddr;
	DWORD size;} DOSMEM;
	
int DosMemAlloc(DOSMEM *);

#ifdef __cplusplus
}
#endif
#endif /* DOSMEM_H_INCLUDED */

/*
 * DosMem.C
 */
 
#include <dpmi.h>
#include <go32.h>
#include <stdlib.h>
 
#include "dosmem.h"
 
int DosMemAlloc(DOSMEM *dosmem)
{
_go32_dpmi_seginfo info;
DWORD addr, page;
	
info.size = ( (dosmem->size + 15) / 16 );
	
if ( (_go32_dpmi_allocate_dos_memory( &info )) )
	return( EXIT_FAILURE );
	addr = info.rm_segment << 4; /* 20-bit address */
	page = addr & 0xFFFF;
	if ( (page + (dosmem->size) ) > 0xFFFF ) /* Does it cross a 64K
boundary? */
	addr = (addr - page) + 0x10000;
	
	dosmem->seg = (WORD) addr / 16;
	dosmem->off = (WORD) addr % 16;
	dosmem->laddr = addr;
	dosmem->addr = ( (DWORD)(dosmem->seg) << 16) | (dosmem->off);
		
	return( EXIT_SUCCESS );
	}

i learned this method by examining jonipx. i think there is a link to it
on DJ's site. a sample function that calls a DOS interrupt (int 0x5C in
this case) could then be written as (this is an excerpt from a larger
file so there is some more irrelevant stuff):

/*
 * sNet.C
 */

#include <dos.h>
#include <go32.h>
#include <dpmi.h>
#include <stdlib.h>
#include <string.h>
#include <sys/movedata.h>   /* required for dosmemput and dosmemget */

#include "dosmem.h"
#include "snetbios.h"
#include "svcm.h"
#include "snet.h"

_go32_dpmi_registers _regs;

NCB ncb, *pncb = &ncb;
BYTE io_buffer[IOBUFSIZE], *pio_buffer = io_buffer;

DOSMEM NCBinfo;
DOSMEM IOinfo;

/**************************************************************
 SNInit: Initialization
	- Allocate DOS memory for the NCB and the IO buffer
	- Check if NetBIOS services are available by issuing
	  an invalid NetBIOS command and checking if and invalid
	  command error is returned.
 **************************************************************/	

unsigned int SNInit(void) 
{
	NCBinfo.size = sizeof(NCB);
	if ( DosMemAlloc(&NCBinfo) != EXIT_SUCCESS )
		return( EXIT_FAILURE );
	IOinfo.size = IOBUFSIZE;
	if ( DosMemAlloc(&IOinfo) != EXIT_SUCCESS )
		return( EXIT_FAILURE );

	memset(pncb, 0, sizeof(NCB));
	ncb.cmd = NB_INVCMD;

	dosmemput(pncb, sizeof(NCB), NCBinfo.laddr);

	memset(&_regs, 0, sizeof(_regs));
	_regs.x.bx = NCBinfo.off;
	_regs.x.es = NCBinfo.seg;
	
	if ( (_go32_dpmi_simulate_int(0x5C, &_regs)) )
		return( EXIT_FAILURE );

return (((0xFF & _regs.h.al) == E_INVCMD)?EXIT_SUCCESS : EXIT_FAILURE);
}

in the case of SNInit(), i did not require to retrieve the NCB after the
interrupt. however, if that were needed, it could be achieved by calling
dosmemget(NCBinfo.laddr, sizeof(NCB), pncb) after the interrupt call.

hope this helps.
-- 
*******************************************************************
 A. Sinan Unur                                WWWWWW
                                              |--O+O
 mailto:asu1 AT cornell DOT edu                      C   ^ 
 mailto:sinan AT econ DOT cit DOT cornell DOT edu             \  ~/ 
 http://www.bqnet.com/sinan/
*******************************************************************

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019