Mail Archives: djgpp/1996/10/22/02:14:38
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 -