/* * Get the VME address of a given VME region. * return 0 if the VME address is found, -1 otherwise. */ int get_vme_addr(SkelDrvrModuleContext * mcon, int am, int dw, uint32_t * addr) { InsLibVmeModuleAddress *vma; InsLibVmeAddressSpace *vas; if (!mcon->Modld) { report_module(mcon, SkelDrvrDebugFlagWARNING, "NULL module descriptor"); return -1; } vma = mcon->Modld->ModuleAddress; if (!vma) { report_module(mcon, SkelDrvrDebugFlagWARNING, "NULL module address"); return -1; } vas = vma->VmeAddressSpace; while (vas) { if (vas->AddressModifier == am && vas->DataWidth == dw) { *addr = vas->BaseAddress; return 0; } vas = vas->Next; } report_module(mcon, SkelDrvrDebugFlagWARNING, "Region with am 0x%x and dw %d not found", am, dw); return -1; }
/** * @brief get the virtual address of a VME address space * * @param mcon - module context * @param am - address modifier * @param dw - data width * * Avoid open coding the retrieval of a particular VME address space, * since this has to be done on every user's driver * * @return virtual address of the VME mapping - on success * @return NULL - on failure */ void *get_vmemap_addr(SkelDrvrModuleContext * mcon, int am, int dw) { InsLibVmeModuleAddress *vma; InsLibVmeAddressSpace *vas; if (!mcon->Modld) { report_module(mcon, SkelDrvrDebugFlagWARNING, "NULL module descriptor"); return NULL; } vma = mcon->Modld->ModuleAddress; if (!vma) { report_module(mcon, SkelDrvrDebugFlagWARNING, "NULL module address"); return NULL; } vas = vma->VmeAddressSpace; while (vas) { if (vas->AddressModifier == am && vas->DataWidth == dw) return vas->Mapped; vas = vas->Next; } report_module(mcon, SkelDrvrDebugFlagWARNING, "Address modifier 0x%X not found", am); return NULL; }
static int mtt_ping(SkelDrvrModuleContext *mcon) { struct udata *udata = mcon->UserData; int ret = OK; /* read the version and check for any bus errors */ if (!recoset()) { mtt_readw(mcon, MTT_VHDL); cdcm_mb(); } else { report_module(mcon, SkelDrvrDebugFlagASSERTION, "Bus Error"); udata->BusError = 1; pseterr(ENXIO); ret = SYSERR; } noreco(); return ret; }
SkelUserReturn SkelUserModuleInit(SkelDrvrModuleContext *mcon) { struct udata *udata; udata = (void *)sysbrk(sizeof(struct udata)); if (udata == NULL) { report_module(mcon, SkelDrvrDebugFlagASSERTION, "Not enough memory for the module's data"); pseterr(ENOMEM); return SkelUserReturnFAILED; } bzero((void *)udata, sizeof(struct udata)); mcon->UserData = udata; /* initialise the iomap address */ udata->iomap = get_vmemap_addr(mcon, 0x39, 32); if (!udata->iomap) { SK_WARN("Could not find VME address space (0x39, 32)"); goto out_free; } /* initialise the jtag address */ udata->jtag = get_vmemap_addr(mcon, 0x29, 16); if (!udata->jtag) { SK_WARN("Could not find VME address space (0x29, 16)"); goto out_free; } /* initialise locking fields */ cdcm_spin_lock_init(&udata->iolock); cdcm_mutex_init(&udata->lock); /* initialise the tasks */ mtt_tasks_init(udata); /* module software reset */ SkelUserHardwareReset(mcon); return SkelUserReturnOK; out_free: sysfree((void*)udata, sizeof(struct udata)); return SkelUserReturnFAILED; }
static SkelUserReturn __mtt_io(SkelDrvrModuleContext *mcon, void *u_addr, void *ioaddr, ssize_t size, int write) { struct udata *udata = mcon->UserData; void *bounce; bounce = (void *)sysbrk(size); if (bounce == NULL) { report_module(mcon, SkelDrvrDebugFlagASSERTION, "%s: -ENOMEM", __FUNCTION__); pseterr(ENOMEM); goto out_err; } if (write) { if (cdcm_copy_from_user(bounce, u_addr, size)) { pseterr(EFAULT); goto out_err; } cdcm_mutex_lock(&udata->lock); mtt_iowritew_r(ioaddr, bounce, size); cdcm_mutex_unlock(&udata->lock); } else { cdcm_mutex_lock(&udata->lock); mtt_ioreadw_r(bounce, ioaddr, size); cdcm_mutex_unlock(&udata->lock); if (cdcm_copy_to_user(u_addr, bounce, size)) { pseterr(EFAULT); goto out_err; } } sysfree(bounce, size); return SkelUserReturnOK; out_err: if (bounce) sysfree(bounce, size); return SkelUserReturnFAILED; }