Listing 2 Attempts to allocate a real-mode DMA buffer

#define BYTE char
typedef unsigned int WORD;
typedef unsigned long BIG;

#define JUNKCHUNK (128)
/* how we will search for physical
bounderies. (Must be >= sizeof(JUNK))
*/

/* produce a big physical address. This
is "large" mode code; " FP_SEG" etc.
are
Turbo C macros which extract the two
parts of an 80x86-style segment-offset
pointer. */

#define PHYSICAL(x) ((BIG)((((BIG)
   (FP_SEG(x)))<<4)+((BIG)FP_OFF(x))))

typedef struct JK
  struct JK *next;
} JUNK;

_f void *mustallocdma(WORD size) {
  BYTE *a;
  JUNK root, *next, *p;
  BIG leftover;
  WORD junksize;
  root.next=NULL;
  next=&root;
  
  while(1) {
    a=mustalloc(size);
    /* mustalloc==malloc,
    but aborts if failure;
    the function exists this
    way or via the break below
    at success.*/
  if (
  (leftover=(PHYSICAL(a) & 0xffff)) +
  ((BIG) size)
  >= 0x10000) {
    /* it's no good. */
    if (
    (junksize = 0x10000-leftover)
    < JUNKCHUNK)
    junksize=JUNKCHUNK;
    /* avoid endless
    teeny-tiny manipulations. */
    
    free(a);
    next->next=mustalloc(junksize);
    next=next->next;
  }
  else
  break; /* success! */
}
/* free debris. */
next=root.next;
while(next)
  p=next;
  next=next->next;
  free(p);
  }
  return a;
}

/* End of File */