initial commit of s3load origin/HEAD origin/master
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Thu, 19 Jun 2008 03:01:59 +0000 (23:01 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Thu, 19 Jun 2008 03:01:59 +0000 (23:01 -0400)
Makefile [new file with mode: 0644]
libnexys.c [new file with mode: 0644]
libnexys.h [new file with mode: 0644]
libnexys.parport.c [new file with mode: 0644]
libnexys.win32.c [new file with mode: 0644]
s3load.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c0bdb7d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+s3load: s3load.c libnexys.c libnexys.h
+       gcc -o s3load s3load.c libnexys.c -lusb
+
+s3load-pp: s3load.c libnexys.parport.c libnexys.h
+       gcc -o s3load-pp -DPARPORT s3load.c libnexys.parport.c
+
+s3load-win32.exe: s3load.c libnexys.win32.c libnexys.h
+       gcc -o s3load-win32.exe s3load.c libnexys.win32.c dpcutil.lib
diff --git a/libnexys.c b/libnexys.c
new file mode 100644 (file)
index 0000000..9fbf833
--- /dev/null
@@ -0,0 +1,405 @@
+#ifdef WIN32_NATIVE
+#include "libnexys.win32.c"
+#else
+#define LIBNEXYS_INTERNAL
+#include "libnexys.h"
+#include <stdio.h>
+#include <usb.h>
+
+#define NEXYS2_VENDOR 0x1443
+#define NEXYS2_DEVICE 0x0005
+
+nexys2_t nexys2_init(void) {
+       struct usb_bus *bus;
+       struct usb_device *dev;
+       usb_dev_handle *udev;
+       int dev_found, ret;
+       unsigned char buf[15];
+       
+       usb_init();
+
+       usb_find_busses();
+       usb_find_devices();
+
+       udev = NULL;
+       for (bus = usb_get_busses(); bus && !udev; bus = bus->next)
+               for (dev = bus->devices; dev && !udev; dev = dev->next)
+                       if ((dev->descriptor.idVendor == NEXYS2_VENDOR) && (dev->descriptor.idProduct == NEXYS2_DEVICE))
+                               udev = usb_open(dev);
+
+       if (!udev)
+       {
+               fprintf(stderr, "nexys2_init: no device found or device open failed\n");
+               return NULL;
+       }
+       
+       if (usb_set_configuration(udev, 1) < 0)
+       {
+               fprintf(stderr, "nexys2_init: failed to set configuration 1 -- check your permissions\n");
+               return NULL;
+       }
+       
+       if (usb_claim_interface(udev, 0) < 0)   /* Needed for libusb on win32.  This code somehow crashes win32 libusb/kernel anyway, but... */
+       {
+               fprintf(stderr, "nexys2_init: failed to claim interface 0 -- check your permissions\n");
+               return NULL;
+       }
+       
+       if (usb_clear_halt(udev, 0x01) < 0)     /* Sometimes the board locks up when you close it, so send this. */
+       {
+               fprintf(stderr, "nexys2_init: failed to clear halt on interface 0x01\n");
+               return NULL;
+       }
+       
+       ret = usb_control_msg(udev, 0x00, 0x09, 1, 0, NULL, 0, 1000);
+       if (ret < 0)
+       {
+               fprintf(stderr, "nexys2_init: failed to send setup control message\n");
+               return NULL;
+       }
+       
+       ret = usb_control_msg(udev, 0xC0, 0xE4, 0, 0, buf, 14, 1000);
+       if (ret < 0)
+       {
+               fprintf(stderr, "nexys2_init: failed to send serial number control message\n");
+               return NULL;
+       }
+       
+       buf[ret] = 0;
+       fprintf(stderr, "nexys2_init: got serial number \"%s\" (%d bytes)\n", buf, ret);
+       
+       ret = usb_control_msg(udev, 0xC0, 0xE6, 0, 0, buf, 4, 1000);
+       if (ret < 0)
+       {
+               fprintf(stderr, "nexys2_init: failed to send magic goo message\n");
+               return NULL;
+       }
+       if (memcmp(buf, "\x01\x00\x02\x00", 4))
+       {
+               fprintf(stderr, "nexys2_init: magic goo did not return what we expected (%d, %02x %02x %02x %02x)\n", ret, buf[0], buf[1], buf[2], buf[3]);
+               return NULL;
+       }
+       
+       return udev;
+}
+
+static unsigned char common_response[64] =
+       { 0x00, 0x03, 0xf3, 0x77, 0x9f, 0xf5, 0xdf, 0xdd,
+         0xdf, 0xfe, 0x5f, 0xac, 0xff, 0xad, 0xf3, 0x34,
+         0xaf, 0xf5, 0xac, 0xf7, 0xca, 0xb7, 0xf7, 0x6f,
+         0xff, 0x5e, 0x5e, 0xf7, 0xfb, 0xfd, 0xfb, 0x37,
+         0x81, 0x53, 0xbf, 0x64, 0x59, 0x47, 0x59, 0x2d,
+         0xe8, 0x30, 0x77, 0xda, 0x4f, 0xaf, 0x7f, 0xd7,
+         0x5f, 0xee, 0xc7, 0x3b, 0xdf, 0x3e, 0xbf, 0x35,
+         0xd1, 0xdf, 0xef, 0x3f, 0x9f, 0xde, 0xfa, 0xe2
+       };
+
+int nexys2_jtag_enable(usb_dev_handle *udev)
+{
+       int ret;
+       unsigned char message[64] =
+               { 0x07, 0x01, 0x00, 0x00, 0xdc, 0xff, 0xd3, 0x00,
+                 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+                 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+                 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+                 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+                 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+                 0x02, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11        /* XXX does this need to be sequenced? */
+               };
+       unsigned char resp[64];
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_enable: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+       if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_enable: short read on response: %d\n", ret);
+               return -1;
+       }
+       
+       if (memcmp(resp, common_response, 64))
+       {
+               fprintf(stderr, "nexys2_jtag_enable: incorrect response?\n");
+//             return -1;
+       }
+       
+       return 0;
+}
+
+int nexys2_jtag_disable(usb_dev_handle *udev)
+{
+       int ret;
+       unsigned char message[64] =
+               { 0x07, 0x00, 0xf3, 0x76, 0xdc, 0xff, 0xd3, 0x00,
+                 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+                 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+                 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+                 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+                 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+                 0x05, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11        /* XXX does this need to be sequenced? */
+               };
+       unsigned char resp[64];
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_disable: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+       if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_disable: short read on response: %d\n", ret);
+               return -1;
+       }
+       
+       if (memcmp(resp, common_response, 64))
+       {
+               fprintf(stderr, "nexys2_jtag_disable: incorrect response?\n");
+//             return -1;
+       }
+       
+       return 0;
+}
+
+int nexys2_jtag_setbits(usb_dev_handle *udev, int tms, int tdi, int tck)
+{
+       int ret;
+       unsigned char message[64] =
+               { 0x08, !!tms, !!tdi, !!tck, 0xdc, 0xff, 0xd3, 0x00,
+                 0xf3, 0x99, 0x83, 0x7c, 0x08, 0x26, 0x80, 0x7c,
+                 0xff, 0xff, 0xff, 0xff, 0x00, 0x26, 0x80, 0x7c,
+                 0xf1, 0xe2, 0x90, 0x7c, 0xb7, 0x24, 0x80, 0x7c,
+                 0x14, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x2a, 0x95, 0x80, 0x7c, 0x5b, 0x3d, 0x00, 0x11,
+                 0x14, 0x07, 0x00, 0x00, 0xe8, 0x22, 0xa0, 0x00,
+                 0x03, 0x00, 0x00, 0x00, 0xb3, 0x9e, 0x01, 0x11        /* XXX does this need to be sequenced? */
+               };
+       unsigned char resp[64];
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_setbits: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+/*     if ((ret = usb_bulk_read(udev, 0x81, resp, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_setbits: short read on response: %d\n", ret);
+               return -1;
+       }
+       
+       if (memcmp(resp, common_response, 64))
+       {
+               fprintf(stderr, "nexys2_jtag_setbits: incorrect response?\n");
+               return -1;
+       }*/
+       
+       return 0;
+}
+
+int nexys2_jtag_puttdi(usb_dev_handle *udev, int tms, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       int wanttdo = obits ? 1 : 0;
+       int bytesrem;
+       int ret;
+       
+       unsigned char message[64] =
+               { 0x09, wanttdo, !!tms, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x7C,
+                 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+                 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+               };
+       
+       if (nbits > 0xFFFF)
+       {
+               fprintf(stderr, "nexys2_jtag_puttdi: too many bits!\n");
+               return -1;
+       }
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_puttdi: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+       bytesrem = nbits / 8 + ((nbits % 8) != 0);
+       while (bytesrem)
+       {
+               int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+               if ((ret = usb_bulk_write(udev, 0x02, bits, nbytes, 1000)) < nbytes)
+               {
+                       fprintf(stderr, "nexys2_jtag_puttdi: data write failed: %d (%s)\n", ret, usb_strerror());
+                       return -1;
+               }
+               bits += nbytes;
+               bytesrem -= nbytes;
+       }
+       
+       if (obits)
+       {
+               bytesrem = nbits / 8 + ((nbits % 8) != 0);
+               while (bytesrem)
+               {
+                       int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+                       if ((ret = usb_bulk_read(udev, 0x86, obits, nbytes, 1000)) < nbytes)
+                       {
+                               fprintf(stderr, "nexys2_jtag_puttdi: data read failed: %d (%s)\n", ret, usb_strerror());
+                               return -1;
+                       }
+                       obits += nbytes;
+                       bytesrem -= nbytes;
+               }
+       }
+       
+       return 0;
+}
+
+int nexys2_jtag_puttmstdi(usb_dev_handle *udev, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       int wanttdo = obits ? 1 : 0;
+       int bytesrem;
+       int ret;
+       
+       unsigned char message[64] =
+               { 0x0a, wanttdo, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x91, 0x7C,
+                 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+                 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+               };
+       
+       if (nbits > 0xFFFF)
+       {
+               fprintf(stderr, "nexys2_jtag_puttmstdi: too many bits!\n");
+               return -1;
+       }
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_puttmstdi: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+       bytesrem = nbits / 4 + ((nbits % 4) != 0);
+       while (bytesrem)
+       {
+               int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+               if ((ret = usb_bulk_write(udev, 0x02, bits, nbytes, 1000)) < nbytes)
+               {
+                       fprintf(stderr, "nexys2_jtag_puttmstdi: data write failed: %d (%s)\n", ret, usb_strerror());
+                       return -1;
+               }
+               if (obits)
+               {
+                       int nrbytes = nbytes/2 + (nbytes % 2);
+                       if ((ret = usb_bulk_read(udev, 0x86, obits, nrbytes, 1000)) < nrbytes)
+                       {
+                               fprintf(stderr, "nexys2_jtag_puttmstdi: data read failed: %d (%s)\n", ret, usb_strerror());
+                               return -1;
+                       }
+                       obits += nrbytes;
+               }
+               bits += nbytes;
+               bytesrem -= nbytes;
+       }
+       
+       return 0;
+}
+
+int nexys2_jtag_gettdo(usb_dev_handle *udev, int tdi, int tms, int nbits, unsigned char *obits)
+{
+       int wanttdo = obits ? 1 : 0;
+       int bytesrem;
+       int ret;
+       
+       unsigned char message[64] =
+               { 0x0B, !!tdi, !!tms, 0x00, 0x00, (nbits >> 8) & 0xFF, nbits & 0xFF, 0x7C,
+                 0xeb, 0x06, 0x91, 0x7c, 0x28, 0xfa, 0xd3, 0x00,
+                 0xec, 0xfc, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+               };
+       
+       if (nbits > 0xFFFF)
+       {
+               fprintf(stderr, "nexys2_jtag_puttdo: too many bits!\n");
+               return -1;
+       }
+       
+       if ((ret = usb_bulk_write(udev, 0x01, message, 64, 1000)) < 64)
+       {
+               fprintf(stderr, "nexys2_jtag_gettdo: write failed: %d (%s)\n", ret, usb_strerror());
+               return -1;
+       }
+       
+       bytesrem = nbits / 8 + ((nbits % 8) != 0);
+       while (bytesrem)
+       {
+               int nbytes = (bytesrem > 512) ? 512 : bytesrem;
+               if ((ret = usb_bulk_read(udev, 0x86, obits, nbytes, 1000)) < nbytes)
+               {
+                       fprintf(stderr, "nexys2_jtag_gettdo: data read failed: %d (%s)\n", ret, usb_strerror());
+                       return -1;
+               }
+               obits += nbytes;
+               bytesrem -= nbytes;
+       }
+       
+       return 0;
+}
+
+#endif
+
+#ifdef TEST_DRIVER
+
+void poke_idcode(nexys2_t nexys)
+{
+       unsigned char seq1[] = { 0xaa, 0x22};
+       unsigned char seq2[] = { 0xaa, 0x02};
+       unsigned int idcode = 0;
+       
+//     while(1)
+       {
+               while (nexys2_jtag_enable(nexys) < 0)
+                       ;
+               if (nexys2_jtag_puttmstdi(nexys, 8, seq1, NULL) < 0)
+                       return;
+               do
+               {
+                       if (nexys2_jtag_gettdo(nexys, 0, 0, 32, &idcode) < 0)
+                               return;
+                       printf("IDCODE: %08x\n", idcode);
+               } while(idcode && (idcode != 0xFFFFFFFF));
+               if (nexys2_jtag_puttmstdi(nexys, 8, seq2, NULL) < 0)
+                       return;
+               if (nexys2_jtag_disable(nexys) < 0)
+                       return;
+       }
+}
+
+void main()
+{
+       nexys2_t nexys;
+       nexys = nexys2_init();
+       if (!nexys)
+               return;
+       poke_idcode(nexys);
+}
+
+#endif
+
diff --git a/libnexys.h b/libnexys.h
new file mode 100644 (file)
index 0000000..581aa10
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _LIBNEXYS_H
+#define _LIBNEXYS_H
+
+#ifdef LIBNEXYS_INTERNAL
+#ifdef WIN32_NATIVE
+#      include <windows.h>
+#      include "gendefs.h"
+#      include "dpcdefs.h"
+#      include "dpcutil.h"
+       typedef HANDLE nexys2_t;
+#else
+#ifdef PARPORT
+       typedef int nexys2_t;
+#else
+#      include <usb.h>
+       typedef usb_dev_handle *nexys2_t;
+#endif
+#endif
+#else
+       typedef void *nexys2_t;
+#endif
+
+extern nexys2_t nexys2_init(void);
+extern int nexys2_jtag_enable(nexys2_t dev);
+extern int nexys2_jtag_disable(nexys2_t dev);
+extern int nexys2_jtag_setbits(nexys2_t dev, int tms, int tdi, int tck);
+extern int nexys2_jtag_puttdi(nexys2_t dev, int tms, int nbits, unsigned char *bits, unsigned char *obits);
+extern int nexys2_jtag_puttmstdi(nexys2_t dev, int nbits, unsigned char *bits, unsigned char *obits);
+extern int nexys2_jtag_gettdo(nexys2_t dev, int tdi, int tms, int nbits, unsigned char *obits);
+
+#endif
diff --git a/libnexys.parport.c b/libnexys.parport.c
new file mode 100644 (file)
index 0000000..be739a4
--- /dev/null
@@ -0,0 +1,181 @@
+#ifdef WIN32
+#include "libnexys.win32.c"
+#else
+#define LIBNEXYS_INTERNAL
+#ifndef PARPORT
+#  define PARPORT
+#endif
+#include "libnexys.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/ioctl.h>
+#include <linux/ppdev.h>
+#include <string.h>
+
+#define TDI     0
+#define TCK     1
+#define TMS     2
+#define TDO     4
+
+
+nexys2_t nexys2_init(void) {
+       int pfd = open("/dev/parport0", O_RDWR);
+       if (pfd < 0)
+       {
+               perror("open /dev/parport0");
+               return -1;
+       }
+       
+       if ((ioctl(pfd, PPEXCL) < 0) || (ioctl(pfd, PPCLAIM) < 0))
+       {
+               perror("lock /dev/parport0");
+               return -1;
+       }
+       
+       return pfd;
+}
+
+int nexys2_jtag_enable(int pfd)
+{
+       return 0;
+}
+
+int nexys2_jtag_disable(int pfd)
+{
+       return 0;
+}
+
+int nexys2_jtag_setbits(int pfd, int tms, int tdi, int tck)
+{
+       unsigned char data;
+       int i;
+       
+       data = ((!!tms) << TMS) | ((!!tdi) << TDI) | ((!!tck) << TCK);
+       
+       if (ioctl(pfd, PPWDATA, &data) < 0)
+       {
+               perror("nexys2_jtag_setbits: ioctl");
+               return -1;
+       }
+       
+       return 0;
+}
+
+int _gettdo(int pfd)
+{
+       unsigned char data;
+       
+       if (ioctl(pfd, PPRSTATUS, &data) < 0)
+       {
+               perror("_gettdi: PPRSTATUS");
+               return -1;
+       }
+       
+       data ^= 0x80;
+       data >>= TDO;
+       data &= 1;
+       
+       return data;
+}
+
+int nexys2_jtag_puttdi(int pfd, int tms, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       int i;
+       
+       if (obits)
+               memset(obits, 0, (nbits / 8) + ((nbits % 8) != 0));
+       
+       for (i = 0; i < nbits; i++)
+       {
+               int bit;
+               
+               bit = bits[i / 8] & (1 << (i % 8));
+               nexys2_jtag_setbits(pfd, tms, bit, 1);
+               nexys2_jtag_setbits(pfd, tms, bit, 0);
+               if (obits)
+                       obits[i/8] |= _gettdo(pfd) << (i % 8);
+       }
+       return 0;
+}
+
+int nexys2_jtag_puttmstdi(int pfd, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       int i;
+       
+       if (obits)
+               memset(obits, 0, (nbits / 8) + ((nbits % 8) != 0));
+       
+       for (i = 0; i < nbits; i++)
+       {
+               int tdi, tms;
+               
+               tdi = bits[i / 4] & (1 << ((i % 4) * 2));
+               tms = bits[i / 4] & (2 << ((i % 4) * 2));
+               nexys2_jtag_setbits(pfd, tms, tdi, 0);
+               nexys2_jtag_setbits(pfd, tms, tdi, 1);
+               nexys2_jtag_setbits(pfd, tms, tdi, 0);
+               if (obits)
+                       obits[i/8] |= _gettdo(pfd) << (i % 8);
+       }
+       return 0;
+}
+
+int nexys2_jtag_gettdo(int pfd, int tdi, int tms, int nbits, unsigned char *obits)
+{
+       int i;
+       
+       if (obits)
+               memset(obits, 0, (nbits / 8) + ((nbits % 8) != 0));
+       
+       for (i = 0; i < nbits; i++)
+       {
+               nexys2_jtag_setbits(pfd, tms, tdi, 0);
+               nexys2_jtag_setbits(pfd, tms, tdi, 1);
+               nexys2_jtag_setbits(pfd, tms, tdi, 0);
+               if (obits)
+                       obits[i/8] |= _gettdo(pfd) << (i % 8);
+       }
+       return 0;
+}
+
+#endif
+
+#ifdef TEST_DRIVER
+
+void poke_idcode(nexys2_t nexys)
+{
+       unsigned char seq1[] = { 0xaa, 0x22};
+       unsigned char seq2[] = { 0xaa, 0x02};
+       unsigned int idcode = 0;
+       unsigned int woop = 0x12345678;
+       
+//     while(1)
+       {
+               while (nexys2_jtag_enable(nexys) < 0)
+                       ;
+               if (nexys2_jtag_puttmstdi(nexys, 8, seq1, NULL) < 0)
+                       return;
+               do
+               {
+                       if (nexys2_jtag_gettdo(nexys, 0, 0, 32, &idcode) < 0)
+                               return;
+                       printf("IDCODE: %08x\n", idcode);
+               } while(idcode && (idcode != 0xFFFFFFFF));
+               if (nexys2_jtag_puttmstdi(nexys, 8, seq2, NULL) < 0)
+                       return;
+               if (nexys2_jtag_disable(nexys) < 0)
+                       return;
+       }
+}
+
+void main()
+{
+       nexys2_t nexys;
+       nexys = nexys2_init();
+       if (!nexys)
+               return;
+       poke_idcode(nexys);
+}
+
+#endif
+
diff --git a/libnexys.win32.c b/libnexys.win32.c
new file mode 100644 (file)
index 0000000..083e105
--- /dev/null
@@ -0,0 +1,68 @@
+#define LIBNEXYS_INTERNAL
+#include "libnexys.h"
+#include <stdio.h>
+
+nexys2_t nexys2_init(void) {
+       int device;
+       char devname[32];
+       HANDLE hand;
+       ERC erc;
+       
+       if (!DpcInit(&erc))
+       {
+               printf("DpcInit failed\n");
+               return NULL;
+       }
+       
+       if ((device = DvmgGetDefaultDev(&erc)) == -1)
+       {
+               printf("We appear to lack a default device. Sadface :(\n");
+               return NULL;
+       }
+       
+       DvmgGetDevName(device, devname, &erc);
+       printf("Interacting with device %d (%s)\n", device, devname);
+       
+       if (!DpcOpenJtag(&hand, devname, &erc, NULL))
+       {
+               printf("JTAG open failed\n");
+               return NULL;
+       }
+       return hand;
+}
+
+int nexys2_jtag_enable(HANDLE hand)
+{
+       ERC erc;
+       return DpcEnableJtag(hand, &erc, NULL) ? 0 : -1;
+}
+
+int nexys2_jtag_disable(HANDLE hand)
+{
+       ERC erc;
+       return DpcDisableJtag(hand, &erc, NULL) ? 0 : -1;
+}
+
+int nexys2_jtag_setbits(HANDLE hand, int tms, int tdi, int tck)
+{
+       ERC erc;
+       return DpcSetTmsTdiTck(hand, tms, tdi, tck, &erc, NULL) ? 0 : -1;
+}
+
+int nexys2_jtag_puttdi(HANDLE hand, int tms, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       ERC erc;
+       return DpcPutTdiBits(hand, nbits, bits, tms, obits ? 1 : 0, obits, &erc, NULL) ? 0 : -1;
+}
+
+int nexys2_jtag_puttmstdi(HANDLE hand, int nbits, unsigned char *bits, unsigned char *obits)
+{
+       ERC erc;
+       return DpcPutTmsTdiBits(hand, nbits, bits, obits ? 1 : 0, obits, &erc, NULL) ? 0 : -1;
+}
+
+int nexys2_jtag_gettdo(HANDLE hand, int tdi, int tms, int nbits, unsigned char *obits)
+{
+       ERC erc;
+       return DpcGetTdoBits(hand, nbits, tdi, tms, obits, &erc, NULL) ? 0 : -1;
+}
diff --git a/s3load.c b/s3load.c
new file mode 100644 (file)
index 0000000..5b047fb
--- /dev/null
+++ b/s3load.c
@@ -0,0 +1,545 @@
+#include "libnexys.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+enum TAPSTATE {
+       TAP_UNKNOWN,
+       TAP_RESET,
+       TAP_IDLE,
+       TAP_DRSEL,
+       TAP_DRCAP,
+       TAP_DRSHIFT,
+       TAP_DREXIT1,
+       TAP_DRPAUSE,
+       TAP_DREXIT2,
+       TAP_DRUPDATE,
+       TAP_IRSEL,
+       TAP_IRCAP,
+       TAP_IRSHIFT,
+       TAP_IREXIT1,
+       TAP_IRPAUSE,
+       TAP_IREXIT2,
+       TAP_IRUPDATE,
+};
+
+typedef struct tap {
+       nexys2_t nexys;
+       int tapstate;
+} tap_t;
+
+int s3l_tap_reset(tap_t *tap)
+{
+       unsigned char reset[] = {0xAA, 0x02};
+       tap->tapstate = TAP_RESET;
+       return nexys2_jtag_puttmstdi(tap->nexys, 5, reset, NULL);
+}
+
+int s3l_tap_idle(tap_t *tap)
+{
+       switch (tap->tapstate)
+       {
+       case TAP_UNKNOWN:
+               printf("Resetting TAP from unknown state...\n");
+               s3l_tap_reset(tap);
+       case TAP_RESET:
+       {
+               unsigned char idle[] = {0x00};
+               printf("Placing TAP in idle state...\n");
+               tap->tapstate = TAP_IDLE;
+               return nexys2_jtag_puttmstdi(tap->nexys, 1, idle, NULL);
+       }
+       case TAP_IDLE:
+               return 0;
+       default:
+               printf("cannot transition to idle from %d\n", tap->tapstate);
+               abort();
+       }
+}
+
+enum TOKENTYPE {
+       TOK_TRST = 0,
+       TOK_OFF = 1,
+       TOK_ENDIR = 2,
+       TOK_IDLE = 3,
+       TOK_ENDDR = 4,
+       TOK_STATE = 5,
+       TOK_RESET = 6,
+       TOK_FREQUENCY = 7,
+       TOK_1E6 = 8,
+       TOK_HZ = 9,
+       TOK_SEMICOLON = 10,
+       TOK_TIR = 11,
+       TOK_HIR = 12,
+       TOK_TDR = 13,
+       TOK_HDR = 14,
+       TOK_SIR = 15,
+       TOK_SDR = 16,
+       TOK_TDI = 17,
+       TOK_TDO = 18, 
+       TOK_MASK = 19,
+       TOK_SMASK = 20,
+       TOK_NUMBER = 21,
+       TOK_BITSTRING = 22,
+       TOK_RUNTEST = 23,
+       TOK_TCK = 24,
+};
+
+typedef struct token {
+       int token;
+       union {
+               int i;
+               char *s;
+       } data;
+       struct token *next;
+} token_t;
+
+int hex2nyb(char c)
+{
+       if (c >= '0' && c <= '9')
+               return c-'0';
+       if (c >= 'a' && c <= 'f')
+               return c-'a'+10;
+       if (c >= 'A' && c <= 'F')
+               return c-'A'+10;
+       printf("Bad hex nybble %c\n", c);
+       abort();
+}
+
+token_t *tokenize(int fd)
+{
+       /* First off, suck in ALL of the file */
+       char *f = NULL, *fst;
+       int sz = 0;
+       token_t *start = NULL, *cur = NULL;
+       
+       while (1)
+       {
+               int rsz;
+               f = realloc(f, sz + 16385);
+               if ((rsz = read(fd, &(f[sz]), 16384)) < 16384)
+               {
+                       sz += rsz;
+                       break;
+               }
+               sz += rsz;
+       }
+       f[sz] = 0;
+       fst = f;
+       
+       while (f && *f)
+       {
+               if (!strncmp(f, "//", 2))
+               {
+                       // Comment, eat the rest of the line
+                       f = strchr(f, '\n');
+                       if (f && f[1] == '\r')
+                               f += 2;
+                       else if (f)
+                               f++;
+               } else if (*f == '\n' || *f == '\r' || *f == '\t' || *f == ' ')
+                       f++;
+#define NEWTOKEN \
+       if (!cur) \
+       { \
+               start = cur = malloc(sizeof(*cur)); \
+               start->next = NULL; \
+       } else { \
+               cur->next = malloc(sizeof(*cur)); \
+               cur = cur->next; \
+               cur->next = NULL; \
+       }
+#define MATCHSTRING(str, tok) \
+       if (!strncmp(f, str, strlen(str))) { \
+               NEWTOKEN \
+               cur->token = tok; \
+               f += strlen(str); \
+       }
+               else MATCHSTRING("TRST", TOK_TRST)
+               else MATCHSTRING("OFF", TOK_OFF)
+               else MATCHSTRING("ENDIR", TOK_ENDIR)
+               else MATCHSTRING("IDLE", TOK_IDLE)
+               else MATCHSTRING("ENDDR", TOK_ENDDR)
+               else MATCHSTRING("STATE", TOK_STATE)
+               else MATCHSTRING("RESET", TOK_RESET)
+               else MATCHSTRING("FREQUENCY", TOK_FREQUENCY)
+               else MATCHSTRING("1E6", TOK_1E6)
+               else MATCHSTRING("HZ", TOK_HZ)
+               else MATCHSTRING(";", TOK_SEMICOLON)
+               else MATCHSTRING("TIR", TOK_TIR)
+               else MATCHSTRING("HIR", TOK_HIR)
+               else MATCHSTRING("TDR", TOK_TDR)
+               else MATCHSTRING("HDR", TOK_HDR)
+               else MATCHSTRING("TDI", TOK_TDI)
+               else MATCHSTRING("SMASK", TOK_SMASK)
+               else MATCHSTRING("SIR", TOK_SIR)
+               else MATCHSTRING("MASK", TOK_MASK)
+               else MATCHSTRING("TDO", TOK_TDO)
+               else MATCHSTRING("SDR", TOK_SDR)
+               else MATCHSTRING("RUNTEST", TOK_RUNTEST)
+               else MATCHSTRING("TCK", TOK_TCK)
+               else if (isdigit(*f)) {
+                       NEWTOKEN
+                       cur->token = TOK_NUMBER;
+                       cur->data.i = *f - '0';
+                       f++;
+                       while (isdigit(*f))
+                       {
+                               cur->data.i *= 10;
+                               cur->data.i += *f - '0';
+                               f++;
+                       }
+               } else if (*f == '(') {
+                       int asz = 0;
+                       int l = 0;
+                       NEWTOKEN
+                       cur->token = TOK_BITSTRING;
+                       cur->data.s = NULL;
+                       f++;
+                       while (*f && *f != ')')
+                       {
+                               char c1, c2;
+                               while (isspace(*f) && *f && *f != ')')
+                                       f++;
+                               if (!*f || *f == ')')
+                                       break;
+                               c1 = *(f++);
+                               
+                               while (isspace(*f) && *f && *f != ')')
+                                       f++;
+                               if (!*f || *f == ')')
+                               {
+                                       printf("Unpaired hex digit in bitstring\n");
+                                       abort();
+                               }
+                               c2 = *(f++);
+                               
+                               if (l == asz)
+                               {
+                                       asz += 128;
+                                       cur->data.s = realloc(cur->data.s, asz);
+                               }
+                               cur->data.s[l++] = hex2nyb(c1) << 4 | hex2nyb(c2);
+                       } 
+                       f++;
+               } else {
+                       printf("Tokenizing error, unhandled: %s\n", f);
+                       abort();
+               }
+       }
+       
+       free(fst);
+       
+       return start;
+}
+
+typedef struct blitval {
+       int len;
+       char *tdi, *tdo, *mask, *smask;
+} blitval_t;
+
+/* Copies bits from an input in format:
+ *  (msb first) 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | ...
+ * To an output in format:
+ *  7 6 5 4 3 2 1 0 | 15 14 13 12 11 10 9 8 | ...
+ */
+void bitcopy(int len, unsigned char *inbits, int inpos, int indir, unsigned char *outbits, int outpos, int outdir)
+{
+       int i;
+       if (!inbits || !outbits)
+               return;
+       for (i = 0; i < len; i++)
+       {
+               int inbit;
+               inbit = inbits[(inpos + i * indir) / 8] & (1 << (7 - ((inpos + i * indir) % 8)));
+               outbits[(outpos + i * outdir) / 8] |= inbit ? (1 << ((outpos + i * outdir) % 8)) : 0;
+       }
+}
+
+void printprog(int done, int total)
+{
+       int i;
+       int progresscounter = done * 32 / total;
+       static int spinnerstate;
+       char *spinner = "_.oOo.";
+       
+       printf("[");
+       for (i=0; i < progresscounter; i++)
+               printf("=");
+       if (progresscounter != 32)
+               printf(">");
+       for (i=0; i < (31 - progresscounter); i++)
+               printf(" ");
+       printf("] %c %d/%d", spinner[(spinnerstate++) % 6], done, total);
+}
+
+void pokethrough(tap_t *tap, blitval_t *tbv, blitval_t *sbv, blitval_t *hbv)
+{
+       int totlen = tbv->len + sbv->len + hbv->len;
+       int lenb = (totlen / 4) + ((totlen % 4) != 0) + 1;      // Number of nexys2_* bytes
+       unsigned char *inb = calloc(lenb, 1);                   // Bitstream to be fed to nexys2_*
+       unsigned char *outb = calloc(lenb, 1);
+       unsigned char *expoutb = calloc(lenb, 1);
+       int bitp = 0;                                   // Position in the "inb" bitstream
+       int txp = 0;
+       int needout = 0;
+       
+       if (!totlen)
+               return;
+       
+       printf("t:%d, s:%d, h:%d\n", tbv->len, sbv->len, hbv->len);
+       
+       bitp = 0;
+#define ROUNDUP(x) (((x / 8) + ((x % 8) != 0)) * 8 - 1)
+       bitcopy(hbv->len, hbv->tdi, ROUNDUP(hbv->len), -1, inb, bitp*2, 2); bitp += hbv->len;
+       bitcopy(sbv->len, sbv->tdi, ROUNDUP(sbv->len), -1, inb, bitp*2, 2); bitp += sbv->len;
+       bitcopy(tbv->len, tbv->tdi, ROUNDUP(tbv->len), -1, inb, bitp*2, 2); bitp += tbv->len;
+       inb[(bitp*2-2)/8] |= 2 << ((bitp*2-2) % 8);
+       assert(bitp == totlen);
+       
+       if (sbv->tdo)
+               needout = 1;
+       bitp = 0;       /* Have to throw away one bit :( */
+       bitcopy(tbv->len, tbv->tdo, ROUNDUP(tbv->len), -1, expoutb, bitp, 1); bitp += tbv->len;
+       bitcopy(sbv->len, sbv->tdo, ROUNDUP(sbv->len), -1, expoutb, bitp, 1); bitp += sbv->len;
+       bitcopy(hbv->len, hbv->tdo, ROUNDUP(hbv->len), -1, expoutb, bitp, 1); bitp += hbv->len;
+       
+       
+       for (txp = 0; txp < totlen; txp += 0x8000)
+       {
+               int len = (((txp + 0x8000) > totlen) ? totlen : (txp + 0x8000)) - txp;
+               printf("Shifting: "); printprog(txp + len, totlen); printf("\r");
+               fflush(stdout);
+               nexys2_jtag_puttmstdi(tap->nexys, len, inb + ((txp * 2) / 8), needout ? (outb + (txp / 8)) : NULL);
+       }
+       printf("\n");
+       
+       printf("I: %02x, %02x, %02x, %02x\n", (int)inb[0], (int)inb[1], (int) inb[2], (int)inb[3]);
+       printf("O: %02x, %02x, %02x, %02x\n", (int)outb[0], (int)outb[1], (int)outb[2], (int)outb[3]);
+       printf("X: %02x, %02x, %02x, %02x\n", (int)expoutb[0], (int)expoutb[1], (int)expoutb[2], (int)expoutb[3]);
+       
+       free(inb);
+       free(outb);
+       free(expoutb);
+}
+
+void runsvf(tap_t *tap, token_t *tlist)
+{
+       int trst = 0;
+       int endir = TOK_IDLE, enddr = TOK_IDLE;
+       blitval_t tir, tdr, hir, hdr;
+       
+       tir.len = 0;
+       tdr.len = 0;
+       hir.len = 0;
+       hdr.len = 0;
+       
+#define NEXT tlist = tlist->next
+#define REQUIRENEXT do { NEXT; if (!tlist) { printf("Unexpected end of stream\n"); abort(); } } while(0)
+#define EXPECT(tok) \
+               if (tlist->token != tok) \
+               { \
+                       printf("Expected " #tok ", got %d\n", tok); \
+                       abort(); \
+               }
+       
+       while (tlist)
+       {
+               switch (tlist->token)
+               {
+               case TOK_TRST:
+                       REQUIRENEXT; EXPECT(TOK_OFF);
+                       trst = 0;
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       break;
+               case TOK_ENDIR:
+                       REQUIRENEXT; EXPECT(TOK_IDLE);
+                       endir = TOK_IDLE;
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       break;
+               case TOK_ENDDR:
+                       REQUIRENEXT; EXPECT(TOK_IDLE);
+                       enddr = TOK_IDLE;
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       break;
+               case TOK_STATE:
+                       REQUIRENEXT;
+                       printf("Changing state...\n");
+                       if (tlist->token == TOK_RESET)
+                               s3l_tap_reset(tap);
+                       else if (tlist->token == TOK_IDLE)
+                               s3l_tap_idle(tap);
+                       else {
+                               printf("Unknown token after TOK_STATE\n");
+                               abort();
+                       }
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       break;
+               case TOK_FREQUENCY:
+                       REQUIRENEXT; EXPECT(TOK_1E6);
+                       REQUIRENEXT; EXPECT(TOK_HZ);
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       break;
+               case TOK_TIR:
+               case TOK_TDR:
+               case TOK_HIR:
+               case TOK_HDR:
+               case TOK_SIR:
+               case TOK_SDR:
+               {
+                       int oldtok = tlist->token;
+                       blitval_t *bv;
+                       blitval_t s;
+                                               
+                       if (oldtok == TOK_TIR)
+                               bv = &tir;
+                       else if (oldtok == TOK_HIR)
+                               bv = &hir;
+                       else if (oldtok == TOK_TDR)
+                               bv = &tdr;
+                       else if (oldtok == TOK_HDR)
+                               bv = &hdr;
+                       else
+                               bv = &s;
+                       
+                       REQUIRENEXT; EXPECT(TOK_NUMBER);
+                       bv->len = tlist->data.i;
+                       bv->tdi = NULL;
+                       bv->tdo = NULL;
+                       bv->mask = NULL;
+                       bv->smask = NULL;
+                       REQUIRENEXT;
+                       
+                       while (tlist->token != TOK_SEMICOLON)
+                       {
+                               switch (tlist->token)
+                               {
+                               case TOK_TDI:
+                                       REQUIRENEXT; EXPECT(TOK_BITSTRING);
+                                       bv->tdi = tlist->data.s;
+                                       REQUIRENEXT;
+                                       break;
+                               case TOK_TDO:
+                                       REQUIRENEXT; EXPECT(TOK_BITSTRING);
+                                       bv->tdo = tlist->data.s;
+                                       REQUIRENEXT;
+                                       break;
+                               case TOK_MASK:
+                                       REQUIRENEXT; EXPECT(TOK_BITSTRING);
+                                       bv->mask = tlist->data.s;
+                                       REQUIRENEXT;
+                                       break;
+                               case TOK_SMASK:
+                                       REQUIRENEXT; EXPECT(TOK_BITSTRING);
+                                       bv->smask = tlist->data.s;
+                                       REQUIRENEXT;
+                                       break;
+                               default:
+                                       abort();
+                               }
+                       }
+                       EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       
+                       if (oldtok == TOK_SIR || oldtok == TOK_SDR)
+                       {
+                               char *capturedr = "\x02";
+                               char *captureir = "\x0A";
+                               char *returnidle = "\x02";
+                               s3l_tap_idle(tap);
+                               /* Enter capture DR is TMS 1 0  */
+                               /* Enter capture IR is TMS 1 1 0 */
+                               /* Return to RTI is TMS 1 0 */
+                               
+                               if (oldtok == TOK_SIR)
+                               {
+                                       printf("Shifting IR (%d bits)...\n", tir.len + s.len + hdr.len);
+                                       nexys2_jtag_puttmstdi(tap->nexys, 4, captureir, NULL);
+                                       pokethrough(tap, &tir, &s, &hir);
+                               } else {
+                                       printf("Shifting DR (%d bits)...\n", tdr.len + s.len + hdr.len);
+                                       nexys2_jtag_puttmstdi(tap->nexys, 3, capturedr, NULL);
+                                       pokethrough(tap, &tdr, &s, &hdr);
+                               }
+                               nexys2_jtag_puttmstdi(tap->nexys, 2, returnidle, NULL);
+                       }
+                       break;
+               }
+               case TOK_RUNTEST:
+               {
+                       int n;
+                       char *loss;
+                       
+                       REQUIRENEXT; EXPECT(TOK_NUMBER);
+                       n = tlist->data.i;
+                       REQUIRENEXT; EXPECT(TOK_TCK);
+                       REQUIRENEXT; EXPECT(TOK_SEMICOLON);
+                       NEXT;
+                       
+                       loss = malloc(64);
+                       memset(loss, 0, 64);
+                       s3l_tap_idle(tap);
+                       
+                       printf("Going RTI for %d clocks...\n", n);
+                       
+                       while (n)
+                       {
+                               int b = (n < 512) ? n : 512;
+                               nexys2_jtag_puttdi(tap->nexys, 0, n, loss, NULL);
+                               n -= b;
+                       }
+                       free(loss);
+                       
+                       break;
+               }
+               default:
+                       printf("Unknown top level token %d\n", tlist->token);
+                       abort();
+               }
+       }
+}
+
+int main(int argc, char **argv)
+{
+       tap_t tap;
+       token_t *tlist;
+       int fd;
+       
+       if (argc < 2)
+       {
+               printf("usage: s3load <file.svf>\n");
+               return 1;
+       }
+       if ((fd = open(argv[1], O_RDONLY)) < 0)
+       {
+               perror("open");
+               return 1;
+       }
+       tlist = tokenize(fd);
+       close(fd);
+       
+       
+       tap.tapstate = TAP_UNKNOWN;
+       tap.nexys = nexys2_init();
+       if (!tap.nexys)
+       {
+               fprintf(stderr, "Board init failed :(\n");
+               return 1;
+       }
+       
+       if (nexys2_jtag_enable(tap.nexys) < 0)
+               return 1;
+       
+       runsvf(&tap, tlist);
+       
+       nexys2_jtag_disable(tap.nexys);
+       
+       return 0;
+}
This page took 0.110167 seconds and 4 git commands to generate.