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,
|
||||
* Init() returns an error. Real implementation lands in subsequent steps.
|
||||
* Talks to Digilent JTAG modules through libdjtg / libdmgr, loaded via
|
||||
* 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 <string.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
@@ -18,56 +21,193 @@
|
||||
|
||||
#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
|
||||
{
|
||||
char drv_id[64];
|
||||
char drv_id[64]; /* szName from DVC; passed to DmgrOpen as szSel */
|
||||
char drv_desc[128];
|
||||
int sub_drv_id;
|
||||
} digilent_drv_desc;
|
||||
|
||||
static digilent_drv_desc subdrv_list[MAX_PROBES_DIGILENT] = {
|
||||
{"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},
|
||||
{"DIGILENT_SMT_PROBE", "DIGILENT JTAG-SMT PROBE", 0},
|
||||
};
|
||||
static digilent_drv_desc subdrv_list[MAX_PROBES_DIGILENT];
|
||||
static int g_dj_num_probes = 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. */
|
||||
return 0;
|
||||
int cdvc = 0;
|
||||
int i;
|
||||
|
||||
if (digilent_load(jc) < 0) {
|
||||
g_dj_num_probes = 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,
|
||||
"drv_Digilent_Init : Digilent backend not yet implemented\r\n");
|
||||
"drv_Digilent_Init : not yet implemented (step 3)\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int drv_Digilent_DeInit(jtag_core * jc)
|
||||
static int drv_Digilent_DeInit(jtag_core *jc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int drv_Digilent_TDOTDI_xfer(jtag_core * jc,
|
||||
unsigned char * str_out,
|
||||
unsigned char * str_in,
|
||||
static int drv_Digilent_TDOTDI_xfer(jtag_core *jc,
|
||||
unsigned char *str_out,
|
||||
unsigned char *str_in,
|
||||
int size)
|
||||
{
|
||||
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_DETECT) drv_Digilent_Detect,
|
||||
|
||||
Reference in New Issue
Block a user