From: "A. Sinan Unur" 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 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: Jon Slaughter 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 #include #include #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 #include #include #include #include #include /* 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/ *******************************************************************