Listing 1 A workaround for the EMM386 DMA bug

#define BIG unsigned long
#define WORD unsigned int

void fixems(int is16, BIG *page,
BIG *offset, WORD *count) {
  BIG physical;

  if (is16) {
    /* reconstitute linear address from
    16-bit DMA page and offset form;
    reconstitute count (in 16-bit DMA it's
    the count of 16-bit words); adjust the
    resulting address to anticipate
    HIMEM/EMM386 bug. */

    physical =
    (((*page & 0xFE)<<16) |
    (*offset << 1))
    -
    ( (((BIG)*count)+1) << 1 );

    /* deconstruct the adjusted linear
    address to the page and offset
    form. */

    *page =   (physical & 0xFE0000) >> 16;
    *offset = (physical & 0x1FFFE) >> 1;

    return;
    }

  /* same as above, but considerably
     simpler in 8-bit DMA. */

  physical = ((*page << 16) | (*offset))
  - (((BIG)*count)+1);

  *page = (physical & 0xFF0000) >> 16;
  *offset = physical & 0xFFFF;

}

/* End of File */