#ifndef __QNXNTO__

#include "driver.h"

/* usec delay timing stuff */

#define Freq  (1193182L/100)
static unsigned bias = 50;
static unsigned cpuspeed = 800;  /* assume the worst */
extern void _aamloop(unsigned n);
#pragma aux _aamloop = "l1: aam" "loop l1" \
        parm [ecx] modify [ecx eax];

void    loop (unsigned n)
{
        _aamloop(n);
}

#define loop(n) _aamloop(n)

void    initloop (struct _osinfo *o)

{
        switch (o->cpu/100)
	  {
	  case 3: bias = 32; break;
	  case 4: bias = 22; break;
	  case 5: bias = 23; break;
	  case 6: bias = 16; break;
	  default:
                        if (o->cpu/100 > 6)
                                bias = 8;
                        else
                                bias = 50;
	  }
        if (o->cpu_features & 0xffff) {
                cpuspeed = o->cpu_features & 0xffff;
	      }
      }

void    nanospin_ns(unsigned nsec)
{
        loop((nsec/1000)*cpuspeed/bias);
}

#define nanospin_ns(u)  loop((u)*cpuspeed/bias)


/* */
inline void snd_print_nothing(char *fmt,...)
{
	fmt = fmt;
	return;
}

/* mphys functionality */

/*
 There are two access points possible for privity 1 programs:
Segment 0x20 is a linear map of memory 20:0 -> 0; 20:0xf0000 ->0xf0000.
Segment 0x58 is a map of the page table structure.

Here is some code snipped from the system debugger (sys/Debugger) for
traversing the page tables.
You will probably have to massacre^H^H^H^H^H^H^H^H massage it to compile.
*/
#include <sys/types.h>
#include <sys/mman.h>
/*-
 * quick note: watcom makes better code if you want to clear
 * or set bits by using the union.
 * Logical operations on bitfields cause the compiler to have a
 * little caniption,
 * do multiple loads and stores and temporarily corrupt the field.
 * so: if you are doing arithmetic/logical use pg_uint,
 *     if you are doing straight assignment/comparison, use the 
 *     exact field, or add one to your liking. [ pray we never have
 *     to go to a compiler without un-named structs. ]
 */
typedef union {
	ulong_t               pg_uint;
	struct {
		ulong_t       pg_flags      :12,
		              pg_frameno    :20;
	};
	struct {
		ulong_t       pg_valid      :1;
	};
} pte_t;

/*-
 extracted from debugger/cpu.c
 */
/*****************************************************************************
 * memory access.  some QNX rules:
 *
 * The pagedirectory is constructed so that the last 4M vaddress
 * (2^32-2^22..2^32-1) alias the page tables themselves; so to
 * extract a pte from a given virtual address, you shift the address
 * down 10 bits, map out the bottom two bits and add 0xffc00000 to
 * it.  This points at the pte itself.  This requires the pdir entry
 * to be valid for this region, so you can similiarly get the pdir
 * pointer by shifting the address down 20 bits; masking the bottom
 * two bits and adding to 0xfffff000.
 *****************************************************************************/

#define PAGE_SIZE 4096
#define PTAB_SIZE (PAGE_SIZE*(PAGESIZE/sizeof(pte_t)))
#define PMEM_SLOT 4
#define itosel(x) ((x)<<3)
typedef pte_t __far *fpte_t;

#define vmem    ((char __far *) MK_FP(itosel(PMEM_SLOT),0))
#define PDIR    ((fpte_t)(vmem+0xfffff000))
#define PTEP()  ((fpte_t)(vmem+0xffc00000))

ulong_t
get_pte(ulong_t va, pte_t *p)
{
	fpte_t     pt = PDIR;
	if (pt[va/PTAB_SIZE].pg_valid == 0) {
		return -1;
	}
	pt = PTEP() + va/PAGE_SIZE;
	*p = *pt;
	return 0;
}

typedef struct {
	unsigned    lim0:16,
	            base0:16,
	            base1:8,
	            type:4,
	            seg:1,
	            dpl:2,
	            present:1,
	            lim1:4,
	            notalloc:1,
	            :1,
	            big:1,
	            large:1,
	            base2:8;
} seg_t;

typedef struct {
	unsigned    lim0:16,
	            base0:16,
	            base1:8,
	            type:4,
	            gate:1,
	            dpl:2,
	            present:1,
	            lim1:4,
	            :3,
	            large:1,
	            base2:8;
} gate_t;


#define gdt   ((seg_t __far *)MK_FP(0x8, 0))

static paddr_t
base(seg_t __far *p)
{
	return p->base0 + (p->base1<<16) + (p->base2 << 24);
}
static paddr_t
limit(seg_t __far *p)
{
	return (p->lim0 + (p->lim1<<16)) << (p->large?12:0);
}
extern unsigned sldt(void);
#pragma aux sldt = "sldt ax";

paddr_t
virt_to_bus(void *x)
{
	pte_t    p;
	int      seg = base(gdt+(sldt()>>3)) - base(gdt+1) + _ds()>>3;
	unsigned ux = (unsigned) x;
	if (limit(gdt+seg) < ux)
		return -1;
	if (get_pte(base(gdt+seg)+(ux&~(PAGESIZE-1)), &p) == 0 && p.pg_valid) {
		return p.pg_frameno*PAGESIZE+(ux&PAGESIZE-1);
	}
	return -1;
}


/* gettimeofday */

int
gettimeofday (struct timeval *tv, void *tzp)
{
	struct timespec ts;
	int status;
  	status = clock_gettime (CLOCK_REALTIME, &ts);
	if (status < 0)
		return status;
	tv->tv_sec = ts.tv_sec;
	tv->tv_usec = ts.tv_nsec / 1000;
	return 0;
}

/* signal handling funcs */

static int signal_table[] = {
  SIGILL,
  SIGTERM,
  SIGHUP,
  SIGQUIT,
  SIGINT,
  SIGABRT,
  SIGKILL,
  SIGSEGV,
  0
  };


void
setup_signal_handling(void (*handler)())
{
	struct sigaction 		sa;
	int				*p;

        memset(&sa, 0, sizeof(struct sigaction));
        sa.sa_handler = handler;

        for (p = &signal_table[0]; *p; p++) 
                sigaction(*p, &sa, NULL);

        
}







#endif
