#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>

#define BASE 0x9000

struct xyd {
  unsigned char id[0x40];
  unsigned char unused1[0x40];
  unsigned char intin;
  unsigned char csr;
#define XYD_RED       0x01
#define XYD_RED_ON    0x00
#define XYD_RED_OFF   0x01
#define XYD_GREEN     0x02
#define XYD_GREEN_ON  0x02
#define XYD_GREEN_OFF 0x00
#define XYD_INTPEND   0x04
#define XYD_INTENB    0x08
#define XYD_RESET     0x10
#define XYD_USER      0xe0
  unsigned char intpend;
  unsigned char intmask;
  unsigned char intclear;
  unsigned char vector;
  unsigned char out;
  unsigned char dirs;
  unsigned char ports[8];
  unsigned char unused2[0x370];
  } ;
typedef struct xyd XYD;

char *memdev = "/dev/mmem";

int fd;
unsigned char *addr;
XYD *xyd;

main()
{
 fd = open(memdev,O_RDWR,0);
 if (fd < 0)
  { perror(memdev);
    exit(1);
  }
 addr = mmap(0,0x10000,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0xbd000000);
 if (addr == (unsigned char *)-1)
  { perror("mmap");
    exit(1);
  }
 xyd = (XYD *) (addr + BASE);
 checkid();
 while (1) docmd();
}

checkid()
{
 static char want[] = "VMEIDXYC240    1 11 ";
 int i;

 for (i=0;i<20;i++)
  { if (xyd->id[i+i+1] != want[i])
     { fprintf(stderr,"Module ID check error\n");
       for (i=0;i<20;i++) fprintf(stderr," %02x",xyd->id[i+i+1]);
       fprintf(stderr,"\n");
       exit(1);
     }
  }
}

initcard()
{
}

docmd()
{
 unsigned char v;
 int i;
 char line[256];
 char key[256];

 v = xyd->csr;
 printf("csr=%02x: user %d%d%d reset %d intenb %d intpend %d green %s red %s\n",
	v,
	(v>>7)&1,(v>>6)&1,(v>>5)&1,
	(v&XYD_RESET)?1:0,
	(v&XYD_INTENB)?1:0,
	(v&XYD_INTPEND)?1:0,
	((v&XYD_GREEN)==XYD_GREEN_ON)?"on":"off",
	((v&XYD_RED)==XYD_RED_ON)?"on":"off" );
 printf("intin=%02x intpend=%02x intmask=%02x vector=%02x\n",xyd->intin,xyd->intpend,xyd->intmask,xyd->vector);
 v = xyd->dirs;
 printf("dirs=%02x flags=%02x\n",v,xyd->out);
 for (i=0;i<8;i++)
  { if (v & (1 << i))
     { printf("port%d=%02x (out)\n",i,xyd->ports[i]);
     }
    else
     { printf("port%d=%02x (in)\n",i,xyd->ports[i]);
     }
  }
 if (fgets(&line[0],sizeof(line),stdin) != &line[0]) exit(1);
 if (sscanf(&line[0],"%s%x",&key[0],&i) == 2)
  { v = i;
    if (!strcmp(&key[0],"csr"))
     { printf("[csr = %02x]\n",v);
       xyd->csr = v;
     }
    else if (!strcmp(&key[0],"intmask"))
     { printf("[intmask = %02x]\n",v);
       xyd->intmask = v;
     }
    else if (!strcmp(&key[0],"intclear") || !strcmp(&key[0],"intclr"))
     { printf("[intclear = %02x]\n",v);
       xyd->intclear = v;
     }
    else if (!strcmp(&key[0],"vector"))
     { printf("[vector = %02x]\n",v);
       xyd->vector = v;
     }
    else if (!strcmp(&key[0],"flags"))
     { printf("[flags = %02x]\n",v);
       xyd->out = v;
     }
    else if (!strcmp(&key[0],"dirs"))
     { printf("[dirs = %02x]\n",v);
       xyd->dirs = v;
     }
    else if (!strcmp(&key[0],"port0"))
     { printf("[port0 = %02x]\n",v);
       xyd->ports[0] = v;
     }
    else if (!strcmp(&key[0],"port1"))
     { printf("[port1 = %02x]\n",v);
       xyd->ports[1] = v;
     }
    else if (!strcmp(&key[0],"port2"))
     { printf("[port2 = %02x]\n",v);
       xyd->ports[2] = v;
     }
    else if (!strcmp(&key[0],"port3"))
     { printf("[port3 = %02x]\n",v);
       xyd->ports[3] = v;
     }
    else if (!strcmp(&key[0],"port4"))
     { printf("[port4 = %02x]\n",v);
       xyd->ports[4] = v;
     }
    else if (!strcmp(&key[0],"port5"))
     { printf("[port5 = %02x]\n",v);
       xyd->ports[5] = v;
     }
    else if (!strcmp(&key[0],"port6"))
     { printf("[port6 = %02x]\n",v);
       xyd->ports[6] = v;
     }
    else if (!strcmp(&key[0],"port7"))
     { printf("[port7 = %02x]\n",v);
       xyd->ports[7] = v;
     }
  }
}

/*
	      	Even                  Odd
	       +------------+------------+
	+0x000 |            |            | +0x001
	       | Undefined  | Module ID  |
	+0x03e |            |            | +0x03f
	       +------------+------------+
	+0x040 |                         |
	       |        Undefined        |
	       |                         | +0x07f
	       +------------+------------+
	+0x080 |Intr. Inputs| Status/Ctl | +0x081
	       +------------+------------+
	+0x082 |Intr. Pend. |Intr. Mask  | +0x083
	       +------------+------------+
	+0x084 |Intr. Clear |Intr. Vector| +0x085
	       +------------+------------+
	+0x086 |Flag Outputs|Port Direc. | +0x087
	       +------------+------------+
	+0x088 | I/O Port 0 | I/O Port 1 | +0x089
	       +------------+------------+
	+0x08a | I/O Port 2 | I/O Port 3 | +0x08b
	       +------------+------------+
	+0x08c | I/O Port 4 | I/O Port 5 | +0x08d
	       +------------+------------+
	+0x08e | I/O Port 6 | I/O Port 7 | +0x08f
	       +------------+------------+
	+0x090 |                         |
	       |        Reserved         |
	       |                         | +0x3ff
	       +-------------------------+

  RCI uses port-direction value 0xf2: 0/2/3 input, others output.
  In terms of fake DRV11:
  Port 0 is protocol in, port 1 protocol out.
  Port 2/3 is input.
  Port 4/5 is output.
*/
