diff --git a/modules/drivers/digilent_jtag/digilent_jtag_drv.c b/modules/drivers/digilent_jtag/digilent_jtag_drv.c index 5184732..f8a166b 100644 --- a/modules/drivers/digilent_jtag/digilent_jtag_drv.c +++ b/modules/drivers/digilent_jtag/digilent_jtag_drv.c @@ -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 #include +#include +#include #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,