XMS.TXT

===============================================================================
     Date: 11-18-95    Time: 04:52p     Number: 1353   
     From: Cliff Rhodes                  Refer: 1287    
       To: Kieran Haughey             Board ID: FIX             Reply: 
  Subject: XMS 1 of 3                      132: fido.en.c_ec   Status: Public 
-------------------------------------------------------------------------------
--> Kieran Haughey wrote to All  <--

KH>I was wondering if anyone might be able to help me here.. I
KH>want to access the EMS or XMS in my computer, and I was
KH>wondering if someone might be able to provide me with some
KH>source code, or an explaination of how to do it...

Kieran, I just posted some EMS routines about 3 days ago. If you didn't see
them, let me know and I'll repost. Here are some XMS routines:

/* XMS.H
 *
 * Header file for Extended Memory routines in XMS.C.
 *
 */

#ifndef _XMS_H
#define _XMS_H

int  XMSinit(void);
int  XMSversion(void);
long XMScoreleft(void);
unsigned int XMSalloc(long size);
int  XMSfree(unsigned int handle);
long XMSmemcpy(unsigned int desthandle, long destoff,
                 unsigned int srchandle, long srcoff, long n);
int  DOStoXMSmove(unsigned int desthandle, long destoff,
                 const char *src, int n);
int  XMStoDOSmove(char *dest, unsigned int srchandle, long srcoff, int n);

#endif
___
 * CMPQwk 1.4 #1692 * "The knowledge of sin is the start of salvation." -
Epicuru

--- Maximus/2 3.00
 * Origin: COMM Port OS/2 (713) 980-9671 (1:106/2000)
===============================================================================
     Date: 11-18-95    Time: 04:55p     Number: 1354   
     From: Cliff Rhodes                  Refer: 1287    
       To: Kieran Haughey             Board ID: FIX             Reply: 
  Subject: XMS 2 of 3                      132: fido.en.c_ec   Status: Public 
-------------------------------------------------------------------------------
/* XMS.C
 *
 * Routines to use Extended Memory from a DOS program.
 * NOTE1: Code has only been tested on a Borland Compiler.
 * NOTE2: Uses inline assembly language--so other compilers beware!
 *
 * Released to the public domain by Cliff Rhodes with no guarantees
 * of any kind.
 *
 */

#include 

#include "xms.h"

#define XMS_INT  0x002f     /* DOS Multiplex interrupt */

static int (_far * XMSDriver)(void);

static int initflag = 0;

static int XMSDriverCall(void)
{
  /* This just checks to insure that we've been initialized. */

  if(initflag)   /* If XMSinit() has been successful */
     return XMSDriver();
  else
     return 0;
}

int XMSinit(void)
{
  /* Verify that an Extended Memory Manager is installed.
   * Returns 1 if manager found, 0 if not.
   * NOTE: This function should be called before any other XMS function!
   */

  union REGS regs;
  struct SREGS sregs;

  regs.x.ax = 0x4300;             /* Verify XMS manager present */
  int86(XMS_INT, ®s, ®s);
  if(regs.h.al == 0)
     return 0;

  regs.x.ax = 0x4310;             /* Get XMS manager entry point */
  int86x(XMS_INT, ®s, ®s, &sregs);

  XMSDriver = MK_FP(sregs.es, regs.x.bx);  /* Save entry point */

  return (initflag = 1);
}

int XMSversion(void)
{
  /* Return version number of XMS driver. */

  _asm mov ax, 0

  return XMSDriverCall();
}

long  XMScoreleft(void)
{
  /* Returns number of bytes available in largest free block. */

  _asm mov ax, 0x0800

  return 1024L * (long) XMSDriverCall();
}

unsigned int XMSalloc(long size)
{
  /* Attempts to allocate size bytes of extended memory.
   * Returns handle if successful, 0 if not.
   * NOTE: Actual size allocated will be the smallest multiple of 1024
   *       that is larger than size.
   */

  /* Get the number of 1024 byte units required by size. */
  int rval = (int) (size / 1024L);
  if(size % 1024L)
     rval++;    /* Add a block for any excess */

  _asm {
     mov dx, rval
     mov ax, 0x0900
  }
  if(XMSDriverCall())
     _asm mov rval, dx
  else
     rval = 0;

  return rval;
}

int XMSfree(unsigned int handle)
{
  /* Attempts to free extended memory referred to by handle. Returns 1
   * if successful, 0 if not.
   */

  _asm {
     mov dx, handle
     mov ax, 0x0a00
  }
  return XMSDriverCall();
}

typedef struct {
   long         nbytes;     /* Number of bytes to move */
   unsigned int shandle;    /* Handle of source memory */
   long         soffset;    /* Offset of source in handle's memory area */
   unsigned int dhandle;    /* Handle of destination memory */
   long         doffset;    /* Offset of destination in memory */
} XMSRequestBlock;

static XMSRequestBlock bd;

static long XMS_Move(long n)
{
  long rval;
  unsigned int segm, offs;
  XMSRequestBlock _far *fptr = (XMSRequestBlock _far *) &bd;

  bd.nbytes = n;

  offs = FP_OFF(fptr);
  segm = FP_SEG(fptr);

  _asm {
     push ds      /* Save DS */
     mov ds, segm
     mov si, offs
     mov ax, 0x0b00
  }
  rval = (XMSDriverCall() == 0) ? 0L : n;

  _asm pop ds    /* Restore DS since we changed it to make this call */

  return rval;
}

long XMSmemcpy(unsigned int desthandle, long destoff,
               unsigned int srchandle, long srcoff, long n)
{
  /* Attempts to copy n bytes from srchandle to desthandle memory areas.
   * Returns number of bytes copied, or 0 on error.
   */

  bd.shandle = srchandle;
  bd.soffset = srcoff;
  bd.dhandle = desthandle;
  bd.doffset = destoff;

  return XMS_Move(n);
}

int DOStoXMSmove(unsigned int desthandle, long destoff,
                 const char *src, int n)
{
  /* Attempts to copy n bytes from DOS src buffer to desthandle memory area.
   * Returns number of bytes copied, or 0 on error.
   */

  bd.shandle = 0;
  bd.soffset = (long) ((char _far *) src);
  bd.dhandle = desthandle;
  bd.doffset = destoff;

  return (int) XMS_Move((long) n);
}

int XMStoDOSmove(char *dest, unsigned int srchandle, long srcoff, int n)
{
  /* Attempts to copy n bytes to DOS dest buffer from srchandle memory area.
   * Returns number of bytes copied, or 0 on error.
   */

  bd.shandle = srchandle;
  bd.soffset = srcoff;
  bd.dhandle = 0;
  bd.doffset = (long) ((char _far *) dest);

  return (int) XMS_Move((long) n);
}
___
 * CMPQwk 1.4 #1692 * "Time is the best medicine." - Ovid

--- Maximus/2 3.00
 * Origin: COMM Port OS/2 (713) 980-9671 (1:106/2000)
===============================================================================
     Date: 11-18-95    Time: 04:56p     Number: 1355   
     From: Cliff Rhodes                  Refer: 1287    
       To: Kieran Haughey             Board ID: FIX             Reply: 
  Subject: XMS 3 of 3                      132: fido.en.c_ec   Status: Public 
-------------------------------------------------------------------------------
/* XMSTEST.C
 *
 * Test extended memory routines in file XMS.C
 *
 */

#include 
#include 

#include "xms.h"

#define BufSize            30000
#define BlockSize  (long) 130000L

int main(void)
{
  int i;
  unsigned int handle1, handle2;       /* XMS handles */
  char *buf1, *buf2;

  if((i = XMSinit()) == 0)
  {
     printf("Extended Memory Manager not found, terminating program\n");
     return 1;
  }
  i = XMSversion();
  printf("Extended Memory Manager Version %d.%d is installed\n",
         i >> 8, (i & 0xff));

  printf("There are %ld extended memory bytes available\n", XMScoreleft());

  buf1 = malloc(BufSize);
  buf2 = malloc(BufSize);
  if(buf1 == NULL || buf2 == NULL)
  {
     printf("Error allocating conventional memory\n");
     return 1;
  }
  for(i = 0; i < BufSize; i++)   /* Fill buf1 with some values */
  {
     buf1[i] = i % 255;
     buf2[i] = 0;
  }
  handle1 = XMSalloc(BlockSize);
  if(handle1 == 0)
  {
     printf("Error allocating XMS memory for handle 1\n");
     return 1;
  }
  printf("Handle 1 is %u and represents %ld bytes\n", handle1, BlockSize);
  printf("There are %ld extended memory bytes available\n", XMScoreleft());

  handle2 = XMSalloc(BlockSize);
  if(handle2 == 0)
  {
     XMSfree(handle1);
     printf("Error allocating XMS memory for handle 2\n");
     return 1;
  }
  printf("Handle 2 is %u and represents %ld bytes\n", handle2, BlockSize);
  printf("There are %ld extended memory bytes available\n", XMScoreleft());

  /* Copy data from DOS buf1 to XMS memory of handle1 */
  if(DOStoXMSmove(handle1, 0L, buf1, (long) BufSize) != BufSize)
     printf("DOStoXMS copy failed\n");

  /* Copy XMS handle1 data to XMS handle2 */
  if(XMSmemcpy(handle2, 0L, handle1, 0L, BlockSize) != BlockSize)
     printf("XMS copy failed\n");

  /* Copy XMS handle2 data to DOS buf2 */
  if(XMStoDOSmove(buf2, handle1, 0L, (long) BufSize) != BufSize)
     printf("XMStoDOS copy failed\n");

  /* buf1 data should now == buf2 data */
  for(i = 0; i < BufSize; i++)
  {
     if(buf1[i] != buf2[i])
     {
        printf("*** ERROR: Mismatch in DOS buffers at location %d ***\n",
i);
        break;
     }
  }
  free(buf1);
  free(buf2);

  XMSfree(handle2);
  printf("There are %ld bytes available after freeing handle 2\n",
         XMScoreleft());

  XMSfree(handle1);
  printf("There are %ld bytes available after freeing handle 1\n",
         XMScoreleft());

  return 0;
}
___
 * CMPQwk 1.4 #1692 * "I would sooner fail than not be among the greatest." -
Joh

--- Maximus/2 3.00
 * Origin: COMM Port OS/2 (713) 980-9671 (1:106/2000)
===============================================================================