#include "sysdeps.h"

#ifdef linux
/* A real real big bad hack. *
 * Never try this at home!   */
# define extern static
# if 0 /* This is required on older Linux versions, not anymore */
#  include <asm/io.h>
#  undef extern
#  include <sys/io.h>
# else
#  include <sys/io.h>
#  undef extern
# endif
# define inportb(x) inb(x)
# define outportb(p,x) outb(x,p)
#endif


#ifdef __GNUC__
# include <unistd.h>
#endif
#if defined(__BORLANDC__) || defined(DJGPP)
# include <dos.h>
#endif

static int DoneIoPerm = 0;
static long OverSleep = 0;

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
void Fmdrv_Outportb(unsigned port, unsigned char value)
{
    if(!DoneIoPerm)
    {
        DoneIoPerm = 1;
        if(ioperm(0x388, 4, 1) < 0)
        {
            fprintf(stderr, "\nDirect port access failed - OPL2 support unavailable.\n");
            perror("ioperm");
            exit(-1);
        }
    }
    
    outportb(port, value);
}

unsigned char Fmdrv_Inportb(unsigned port)
{
    if(!DoneIoPerm)
    {
        DoneIoPerm = 1;
        ioperm(0x388, 4, 1);
    }

    return inportb(port);
}

void Fmdrv_Usleep(unsigned us)
{
    fflush(stdout);
#if defined(__BORLANDC__) || defined(DJGPP)
    delay(us / 1000);
#else
    if(OverSleep >= us)
    {
        OverSleep -= us;
        return;
    }
    us -= OverSleep;
    OverSleep = 0;
    
    struct timeval before, after;
    gettimeofday(&before, NULL);
    usleep(us);
    gettimeofday(&after, NULL);
    
    OverSleep += (after.tv_sec * 1000000L + after.tv_usec)
               - (before.tv_sec * 1000000L + before.tv_usec)
               - us;
#endif
}
