static SkelUserReturn mtt_gs_program(struct udata *udata, MttDrvrInstruction *u_prog, MttDrvrInstruction *io_prog, unsigned int elems, int set) { void *bounce; ssize_t size = elems * sizeof(MttDrvrInstruction); bounce = (void *)sysbrk(size); if (bounce == NULL) { SK_ERROR("%s: -ENOMEM", __FUNCTION__); pseterr(ENOMEM); goto out_err; } if (set) { if (cdcm_copy_from_user(bounce, u_prog, size)) { pseterr(EFAULT); goto out_err; } cdcm_mutex_lock(&udata->lock); __mtt_set_program(udata, io_prog, bounce, elems); cdcm_mutex_unlock(&udata->lock); } else { cdcm_mutex_lock(&udata->lock); __mtt_get_program(udata, bounce, io_prog, elems); cdcm_mutex_unlock(&udata->lock); if (cdcm_copy_to_user(u_prog, bounce, size)) { pseterr(EFAULT); goto out_err; } } sysfree(bounce, size); return SkelUserReturnOK; out_err: if (bounce) sysfree(bounce, size); 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; }
static SkelUserReturn mtt_gs_trval_ioctl(SkelDrvrClientContext *ccon, void *arg, int set) { struct udata *udata = get_udata_ccon(ccon); MttDrvrMap *map = udata->iomap; MttDrvrTaskRegBuf *trbuf = arg; int tasknum = trbuf->Task; unsigned long *mttmem = map->LocalMem[tasknum - 1]; int i; /* sanity check */ if (!WITHIN_RANGE(1, tasknum, MttDrvrTASKS)) { pseterr(EINVAL); return SkelUserReturnFAILED; } if (set) { int regmask; for (i = 0; i < MttDrvrLRAM_SIZE; i++) { regmask = 1 << i; if (!(regmask & trbuf->RegMask)) continue; cdcm_mutex_lock(&udata->lock); cdcm_iowrite32be(trbuf->RegVals[i], &mttmem[i]); cdcm_mutex_unlock(&udata->lock); return OK; } pseterr(EINVAL); return SkelUserReturnFAILED; } cdcm_mutex_lock(&udata->lock); for (i = 0; i < MttDrvrLRAM_SIZE; i++) trbuf->RegVals[i] = cdcm_ioread32be(&mttmem[i]); cdcm_mutex_unlock(&udata->lock); trbuf->RegMask = 0xffffffff; return OK; }
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_tasks_start_ioctl(SkelDrvrClientContext *ccon, void *arg) { SkelDrvrModuleContext *mcon = get_mcon(ccon->ModuleNumber); struct udata *udata = mcon->UserData; uint32_t *valp = arg; uint32_t tmask, mask; int i; mask = *valp & MttDrvrTASK_MASK; if (!mask) { pseterr(EINVAL); return SkelUserReturnFAILED; } for (i = 0; i < MttDrvrTASKS; i++) { tmask = 1 << i; if (!(*valp & tmask)) { continue; } else { struct mtt_task *localtask = &udata->Tasks[i]; MttDrvrMap *map = get_iomap_ccon(ccon); MttDrvrTaskBlock *task = &map->Tasks[i]; /* * Ensure no one else alters the state of the device * while we modify the task. * NOTE: udata->lock is always acquired BEFORE * task->lock. */ cdcm_mutex_lock(&udata->lock); mtt_writew(mcon, MTT_TASKS_STOP, tmask); cdcm_mutex_lock(&localtask->lock); cdcm_iowrite32be(localtask->PcStart, &task->Pc); cdcm_mutex_unlock(&localtask->lock); mtt_writew(mcon, MTT_TASKS_START, tmask); cdcm_mutex_unlock(&udata->lock); } } return SkelUserReturnOK; }
/*----------------------------------------------------------------------------- * FUNCTION: CtcUserInst. * DESCRIPTION: User entry point in driver/simulator installation routine. * It's up to user to set kernel-level errno (by means of * 'pseterr' call). 'proceed' parameter denotes if further * standard execution should be proceed after function returns. * FALSE - means that user-desired operation done all that user * wants and there is no further necessaty to perfom any standard * operations that follow function call. TRUE - means that code * that follows function call will be executed. * RETURNS: return value is the same as in entry point function. * pointer to a statics data structure - if succeed. * SYSERR - in case of failure. *----------------------------------------------------------------------------- */ char* CtcUserInst( int *proceed, /* if standard code execution should be proceed */ register DevInfo_t *info, /* */ register CTCStatics_t *sptr) /* */ { CTCUserStatics_t *usp; /* user statistics table */ int iVec = 0; /* interrupt vector */ usp = sptr->usrst; iVec = info->iVector; /* set up interrupt vector */ #if 0 /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-= | user-defined code is here. | -=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Uncomment the following code to register ISR: !WARNING! It's worth to do 'man iointset' before to start. */ if (iVec > 0) { int coco = 0; /* completion code */ DBG_install(("ISR ( vector number [%d] ) installation - ", iVec)); #ifdef __powerpc__ /* in this case we are using CES BSP */ coco = vme_intset(iVec, (int (*)())CtcISR, (char*)sptr, 0); #else /* use standard system call otherwise */ coco = iointset(iVec, (int (*)())CtcISR, (char*)sptr); #endif if (coco < 0) { DBG_install(("Failed.\n")); pseterr(EFAULT); /* TODO. what error to set? */ return((char*)SYSERR); /* -1 */ } DBG_install(("interrupt vector managed.\n")); } #endif if (proceed) *proceed = TRUE; /* continue standard code execution */ return((char*)sptr); /* succeed */ }
/** * @brief User entry point in driver/simulator installation routine. * * @param proceed -- if standard code execution should be proceed * @param info -- driver info table * @param sptr -- statics table * * It's up to user to set kernel-level errno (by means of @e pseterr call). * @e proceed parameter denotes if further standard actions should be proceed * after function returns. @b FALSE - means that user-desired operation done * all that user wants and there is no further necessaty to perfom any standard * operations that follow function call. @b TRUE - means that code that follows * function call will be executed. * * @return return value is the same as in entry point function.\n * pointer to a statics data structure - if succeed.\n * SYSERR - in case of failure. */ char* GfaschannelUserInst(int *proceed, register DevInfo_t *info, register GFASCHANNELStatics_t *sptr) { GFASCHANNELUserStatics_t *usp; /* user statistics table */ int iVec = 0; /* interrupt vector */ usp = sptr->usrst; iVec = info->iVector; /* set up interrupt vector */ /* Uncomment the following code to register ISR */ #if 0 if (iVec > 0) { int cc = 0; /* completion code */ kkprintf("ISR ( vector number [%d] ) installation - ", iVec); #ifdef __Lynx__ #ifdef __powerpc__ /* in this case we are using CES BSP */ cc = vme_intset(iVec, (int (*)())GfaschannelISR, (char*)sptr, 0); #else /* use standard system call otherwise */ cc = iointset(iVec, (int (*)())GfaschannelISR, (char*)sptr); #endif #else /* __linux__ */ cc = vme_request_irq(iVec, (int (*)(void *))GfaschannelISR, (char *)sptr, "GfaschannelD"); #endif /* __Lynx__ */ if (cc < 0) { kkprintf("Failed.\n"); pseterr(EFAULT); /* TODO. what error to set? */ return (char*)SYSERR; /* -1 */ } kkprintf("interrupt vector managed.\n"); } #endif if (proceed) *proceed = TRUE; /* continue standard code execution */ return (char *)sptr; /* succeed */ }
static SkelUserReturn mtt_gs_grval_ioctl(SkelDrvrClientContext *ccon, void *arg, int set) { struct udata *udata = get_udata_ccon(ccon); MttDrvrMap *map = udata->iomap; MttDrvrGlobalRegBuf *regbuf = arg; int regnum = regbuf->RegNum; if (regnum >= MttDrvrGRAM_SIZE) { pseterr(EINVAL); return SkelUserReturnFAILED; } cdcm_mutex_lock(&udata->lock); if (set) cdcm_iowrite32be(regbuf->RegVal, &map->GlobalMem[regnum]); else regbuf->RegVal = cdcm_ioread32be(&map->GlobalMem[regnum]); cdcm_mutex_unlock(&udata->lock); return SkelUserReturnOK; }
static SkelUserReturn mtt_send_event_ioctl(SkelDrvrClientContext *ccon, void *arg) { SkelDrvrModuleContext *mcon = get_mcon(ccon->ModuleNumber); MttDrvrEvent *event = arg; uint32_t cmd; if (!WITHIN_RANGE(0, event->Priority, 1)) { pseterr(EINVAL); return SkelUserReturnFAILED; } /* make sure thats the module supports prioritisation */ cmd = MttDrvrCommandSEND_EVENT; if (event->Priority && mtt_supports_prio(mcon)) cmd = MttDrvrCommandSEND_EVENT_LOW; mtt_cmd(mcon, cmd, event->Frame); return SkelUserReturnOK; }
static SkelUserReturn mtt_gs_tasks_ioctl(SkelDrvrClientContext *ccon, void *arg, int reg, int set) { SkelDrvrModuleContext *mcon = get_mcon(ccon->ModuleNumber); struct udata *udata = mcon->UserData; uint32_t *valp = arg; uint32_t mask; if (set) { mask = *valp & MttDrvrTASK_MASK; if (!mask) { pseterr(EINVAL); return SkelUserReturnFAILED; } cdcm_mutex_lock(&udata->lock); mtt_writew(mcon, reg, mask); cdcm_mutex_unlock(&udata->lock); } else { cdcm_mutex_lock(&udata->lock); *valp = mtt_readw(mcon, reg) & MttDrvrTASK_MASK; cdcm_mutex_unlock(&udata->lock); } return SkelUserReturnOK; }
/** * @brief User entry point in driver/simulator installation routine. * * @param proceed -- if standard code execution should be proceed * @param info -- driver info table * @param sptr -- statics table * * It's up to user to set kernel-level errno (by means of @e pseterr call). * @e proceed parameter denotes if further standard actions should be proceed * after function returns. @b FALSE - means that user-desired operation done * all that user wants and there is no further necessaty to perfom any standard * operations that follow function call. @b TRUE - means that code that follows * function call will be executed. * * @return return value is the same as in entry point function.\n * pointer to a statics data structure - if succeed.\n * SYSERR - in case of failure. */ char* CvorbUserInst(int *proceed, register DevInfo_t *info, register CVORBStatics_t *sptr) { CVORBUserStatics_t *usp = sptr->usrst; /* user statistics table */ int iVec = 0; /* interrupt vector */ int m, c; iVec = info->iVector; /* set up interrupt vector */ /* map submodule address pointers */ usp->md = (struct cvorb_module *)sysbrk(sizeof(_m)); usp->md[0].md = (mod *)sptr->card->block00; usp->md[1].md = (mod *)((long)sptr->card->block00 + 0x200); if (!firmware_ok(usp, info->mlun)) { sysfree((char *)usp->md, sizeof(_m)); return (char *)SYSERR; } for (m = 0; m < SMAM; m++) { /* reset subModules */ _wr(m, SOFT_PULSE, SPR_FGR); /* initialize iolock mutex */ cdcm_mutex_init(&usp->md[m].iol); /* set submodule channels addresses */ for (c = 0; c < CHAM; c++) usp->md[m].cd[c] = (chd *) ((long)usp->md[m].md + _ch_offset[c]); } /* init on-board DAC */ ad9516o_init(usp); /* disable on-board clock generator */ _wr(0, CLK_GEN_CNTL, AD9516_OFF); /* set normal mode operation, enable all channels and set recurrent cycles to 1 (i.e. play function once) */ enable_modules(usp); /* Uncomment the following code to register ISR */ #if 0 if (iVec > 0) { int cc = 0; /* completion code */ kkprintf("ISR ( vector number [%d] ) installation - ", iVec); #ifdef __Lynx__ #ifdef __powerpc__ /* in this case we are using CES BSP */ cc = vme_intset(iVec, (int (*)())CvorbISR, (char*)sptr, 0); #else /* use standard system call otherwise */ cc = iointset(iVec, (int (*)())CvorbISR, (char*)sptr); #endif #else /* __linux__ */ cc = vme_request_irq(iVec, (int (*)(void *))CvorbISR, (char *)sptr, "CvorbD"); #endif /* __Lynx__ */ if (cc < 0) { kkprintf("Failed.\n"); pseterr(EFAULT); /* TODO. what error to set? */ return (char*)SYSERR; /* -1 */ } kkprintf("interrupt vector managed.\n"); } #endif if (proceed) *proceed = TRUE; /* continue standard code execution */ return (char *)sptr; /* succeed */ }