digilent: dlopen libdjtg/libdmgr + implement Detect
Loads the Adept .so files lazily and resolves the symbols we need. Detect() enumerates devices via DmgrEnumDevices/DmgrGetDvc and exposes each as a Viveris probe slot. If Adept Runtime is missing, the driver silently reports 0 probes.
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Boundary-Scan Explorer - Digilent JTAG-SMT* driver (skeleton)
|
* Boundary-Scan Explorer - Digilent JTAG-SMT* driver
|
||||||
*
|
*
|
||||||
* Step 1: build wiring + driver registration only. Detect() returns 0,
|
* Talks to Digilent JTAG modules through libdjtg / libdmgr, loaded via
|
||||||
* Init() returns an error. Real implementation lands in subsequent steps.
|
* dlopen at runtime. No Digilent binary or header is embedded in this
|
||||||
|
* repository; the typedefs below mirror the public Adept SDK ABI.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
#include "jtag_core/dbg_logs.h"
|
#include "jtag_core/dbg_logs.h"
|
||||||
@@ -18,56 +21,193 @@
|
|||||||
|
|
||||||
#define MAX_PROBES_DIGILENT 8
|
#define MAX_PROBES_DIGILENT 8
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Adept SDK ABI mirrors (no Digilent headers included) */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef int DJ_BOOL;
|
||||||
|
typedef uint8_t DJ_BYTE;
|
||||||
|
typedef uint32_t DJ_DWORD;
|
||||||
|
typedef int32_t DJ_INT32;
|
||||||
|
typedef DJ_DWORD DJ_HIF;
|
||||||
|
typedef DJ_DWORD DJ_DTP;
|
||||||
|
|
||||||
|
#define DJ_CCH_DVC_NAME_MAX 64
|
||||||
|
#define DJ_CCH_CONN_MAX 261 /* MAX_PATH(260) + 1 in dpcdecl.h */
|
||||||
|
|
||||||
|
#pragma pack(push, 16)
|
||||||
|
typedef struct dj_dvc {
|
||||||
|
char szName[DJ_CCH_DVC_NAME_MAX];
|
||||||
|
char szConn[DJ_CCH_CONN_MAX];
|
||||||
|
DJ_DTP dtp;
|
||||||
|
} DJ_DVC;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef DJ_BOOL (*pfn_DmgrEnumDevices)(int *pcdvc);
|
||||||
|
typedef DJ_BOOL (*pfn_DmgrGetDvc)(int idvc, DJ_DVC *pdvc);
|
||||||
|
typedef DJ_BOOL (*pfn_DmgrOpen)(DJ_HIF *phif, char *szSel);
|
||||||
|
typedef DJ_BOOL (*pfn_DmgrClose)(DJ_HIF hif);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgEnable)(DJ_HIF hif);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgDisable)(DJ_HIF hif);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgSetSpeed)(DJ_HIF hif, DJ_DWORD frqReq, DJ_DWORD *pfrqSet);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgPutTdiBits)(DJ_HIF hif, DJ_BOOL fTms, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbits, DJ_BOOL fOverlap);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgPutTmsBits)(DJ_HIF hif, DJ_BOOL fTdi, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbits, DJ_BOOL fOverlap);
|
||||||
|
typedef DJ_BOOL (*pfn_DjtgPutTmsTdiBits)(DJ_HIF hif, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbitpairs, DJ_BOOL fOverlap);
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
void *libmgr;
|
||||||
|
void *libjtg;
|
||||||
|
pfn_DmgrEnumDevices EnumDevices;
|
||||||
|
pfn_DmgrGetDvc GetDvc;
|
||||||
|
pfn_DmgrOpen Open;
|
||||||
|
pfn_DmgrClose Close;
|
||||||
|
pfn_DjtgEnable Enable;
|
||||||
|
pfn_DjtgDisable Disable;
|
||||||
|
pfn_DjtgSetSpeed SetSpeed;
|
||||||
|
pfn_DjtgPutTdiBits PutTdiBits;
|
||||||
|
pfn_DjtgPutTmsBits PutTmsBits;
|
||||||
|
pfn_DjtgPutTmsTdiBits PutTmsTdiBits;
|
||||||
|
} g_dj;
|
||||||
|
|
||||||
|
static int g_dj_loaded = 0; /* 0 = not tried, 1 = ok, -1 = failed */
|
||||||
|
|
||||||
|
static int digilent_load(jtag_core *jc)
|
||||||
|
{
|
||||||
|
if (g_dj_loaded > 0) return 0;
|
||||||
|
if (g_dj_loaded < 0) return -1;
|
||||||
|
|
||||||
|
g_dj.libmgr = dlopen("libdmgr.so", RTLD_LAZY);
|
||||||
|
if (!g_dj.libmgr) {
|
||||||
|
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||||
|
"drv_Digilent : libdmgr.so not loadable (Adept Runtime not installed?) : %s\r\n",
|
||||||
|
dlerror());
|
||||||
|
g_dj_loaded = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
g_dj.libjtg = dlopen("libdjtg.so", RTLD_LAZY);
|
||||||
|
if (!g_dj.libjtg) {
|
||||||
|
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||||
|
"drv_Digilent : libdjtg.so not loadable : %s\r\n", dlerror());
|
||||||
|
dlclose(g_dj.libmgr); g_dj.libmgr = NULL;
|
||||||
|
g_dj_loaded = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RESOLVE(field, lib, name) \
|
||||||
|
do { \
|
||||||
|
g_dj.field = (pfn_##name)dlsym(g_dj.lib, #name); \
|
||||||
|
if (!g_dj.field) { \
|
||||||
|
jtagcore_logs_printf(jc, MSG_ERROR, \
|
||||||
|
"drv_Digilent : dlsym(%s) failed\r\n", #name); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
RESOLVE(EnumDevices, libmgr, DmgrEnumDevices);
|
||||||
|
RESOLVE(GetDvc, libmgr, DmgrGetDvc);
|
||||||
|
RESOLVE(Open, libmgr, DmgrOpen);
|
||||||
|
RESOLVE(Close, libmgr, DmgrClose);
|
||||||
|
RESOLVE(Enable, libjtg, DjtgEnable);
|
||||||
|
RESOLVE(Disable, libjtg, DjtgDisable);
|
||||||
|
RESOLVE(SetSpeed, libjtg, DjtgSetSpeed);
|
||||||
|
RESOLVE(PutTdiBits, libjtg, DjtgPutTdiBits);
|
||||||
|
RESOLVE(PutTmsBits, libjtg, DjtgPutTmsBits);
|
||||||
|
RESOLVE(PutTmsTdiBits, libjtg, DjtgPutTmsTdiBits);
|
||||||
|
#undef RESOLVE
|
||||||
|
|
||||||
|
g_dj_loaded = 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (g_dj.libjtg) dlclose(g_dj.libjtg);
|
||||||
|
if (g_dj.libmgr) dlclose(g_dj.libmgr);
|
||||||
|
memset(&g_dj, 0, sizeof(g_dj));
|
||||||
|
g_dj_loaded = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Probe registry */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
typedef struct _digilent_drv_desc
|
typedef struct _digilent_drv_desc
|
||||||
{
|
{
|
||||||
char drv_id[64];
|
char drv_id[64]; /* szName from DVC; passed to DmgrOpen as szSel */
|
||||||
char drv_desc[128];
|
char drv_desc[128];
|
||||||
int sub_drv_id;
|
int sub_drv_id;
|
||||||
} digilent_drv_desc;
|
} digilent_drv_desc;
|
||||||
|
|
||||||
static digilent_drv_desc subdrv_list[MAX_PROBES_DIGILENT] = {
|
static digilent_drv_desc subdrv_list[MAX_PROBES_DIGILENT];
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
static int g_dj_num_probes = 0;
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int drv_Digilent_Detect(jtag_core * jc)
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* Viveris driver interface */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static int drv_Digilent_Detect(jtag_core *jc)
|
||||||
{
|
{
|
||||||
/* Step 2 will populate subdrv_list via DmgrEnumDevices. */
|
int cdvc = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (digilent_load(jc) < 0) {
|
||||||
|
g_dj_num_probes = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_dj.EnumDevices(&cdvc)) {
|
||||||
|
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||||
|
"drv_Digilent_Detect : DmgrEnumDevices failed\r\n");
|
||||||
|
g_dj_num_probes = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdvc > MAX_PROBES_DIGILENT) cdvc = MAX_PROBES_DIGILENT;
|
||||||
|
|
||||||
|
for (i = 0; i < cdvc; i++) {
|
||||||
|
DJ_DVC dvc;
|
||||||
|
memset(&dvc, 0, sizeof(dvc));
|
||||||
|
if (!g_dj.GetDvc(i, &dvc)) {
|
||||||
|
snprintf(subdrv_list[i].drv_id, sizeof(subdrv_list[i].drv_id), "unknown%d", i);
|
||||||
|
snprintf(subdrv_list[i].drv_desc, sizeof(subdrv_list[i].drv_desc), "Digilent (idx %d - DmgrGetDvc failed)", i);
|
||||||
|
} else {
|
||||||
|
snprintf(subdrv_list[i].drv_id, sizeof(subdrv_list[i].drv_id), "%s", dvc.szName);
|
||||||
|
snprintf(subdrv_list[i].drv_desc, sizeof(subdrv_list[i].drv_desc), "Digilent: %s", dvc.szName);
|
||||||
|
}
|
||||||
|
subdrv_list[i].sub_drv_id = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dj_num_probes = cdvc;
|
||||||
|
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||||
|
"drv_Digilent_Detect : %d device(s) found\r\n", cdvc);
|
||||||
|
return cdvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drv_Digilent_Init(jtag_core * jc, int sub_drv, char * params)
|
static int drv_Digilent_Init(jtag_core *jc, int sub_drv, char *params)
|
||||||
{
|
{
|
||||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||||
"drv_Digilent_Init : Digilent backend not yet implemented\r\n");
|
"drv_Digilent_Init : not yet implemented (step 3)\r\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drv_Digilent_DeInit(jtag_core * jc)
|
static int drv_Digilent_DeInit(jtag_core *jc)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drv_Digilent_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size)
|
static int drv_Digilent_TMS_xfer(jtag_core *jc, unsigned char *str_out, int size)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drv_Digilent_TDOTDI_xfer(jtag_core * jc,
|
static int drv_Digilent_TDOTDI_xfer(jtag_core *jc,
|
||||||
unsigned char * str_out,
|
unsigned char *str_out,
|
||||||
unsigned char * str_in,
|
unsigned char *str_in,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int drv_Digilent_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype, void * returnvalue)
|
int drv_Digilent_libGetDrv(jtag_core *jc, int sub_drv, unsigned int infotype, void *returnvalue)
|
||||||
{
|
{
|
||||||
drv_ptr drv_funcs = {
|
drv_ptr drv_funcs = {
|
||||||
(DRV_DETECT) drv_Digilent_Detect,
|
(DRV_DETECT) drv_Digilent_Detect,
|
||||||
|
|||||||
Reference in New Issue
Block a user