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; }
/** * @brief User entry point in driver/simulator ioctl routine. * * @param proceed -- if standard code execution should be proceed * @param sptr -- statics table pointer * @param f -- file pointer. Lynx/Linux specific. * See (sys/file.h) for Lynx and (linux/fs.h) for Linux. * @param lun -- minor number (LUN) * @param com -- ioctl number * @param arg -- ioctl arguments * * 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 * OK - if succeed.\n * SYSERR - in case of failure. */ int CvorbUserIoctl(int *proceed, register CVORBStatics_t *sptr, struct file *f, int lun, int com, char *arg) { CVORBUserStatics_t *usp = sptr->usrst; /* user statistics table */ ushort edp[3]; /* [select/get function] ioctl parameters [0] -- module idx [1] -- chan idx [2] -- func idx */ *proceed = FALSE; switch (com) { case CVORB_VHDL: return read_vhdl(usp, arg); case CVORB_PCB: return read_pcb(usp, arg); case CVORB_TEMP: return read_temp(usp, arg); case CVORB_MOD_CFG_RD: return read_mod_config_reg(usp, arg); case CVORB_MOD_CFG_WR: return write_mod_config_reg(usp, arg); case CVORB_CH_CFG_RD: return read_ch_config_reg(usp, arg); case CVORB_CH_CFG_WR: return write_ch_config_reg(usp, arg); case CVORB_MOD_STAT: return read_mod_stat(usp, arg); case CVORB_CH_STAT: return read_ch_stat(usp, arg); case CVORB_LOAD_SRAM: return load_sram(usp, arg); case CVORB_READ_SRAM: return read_sram(usp, arg); case CVORB_FEN: /* enable function in the function bitmask */ return enable_function(usp, arg); case CVORB_FDIS: /* disable function in the function bitmask */ return disable_function(usp, arg); case CVORB_FEN_RD: /* read Funciton Enable Mask */ { uint m[2]; /* [0] -- bits[63-32] [1] -- bits[31-0] */ /* ioctl parameters */ struct { ushort m; /* module idx */ ushort c; /* channel idx */ uint *p; /* results goes here */ } par; if (cdcm_copy_from_user(&par, arg, sizeof(par))) return SYSERR; m[0] = _rcr(par.m, par.c, FCT_EM_H); m[1] = _rcr(par.m, par.c, FCT_EM_L); return cdcm_copy_to_user(par.p, m, sizeof(m)); } case CVORB_FEN_WR: /* write Function Enable Mask */ return write_fem_regs(usp, arg); case CVORB_FUNC_SEL: /* select function to be played */ if (cdcm_copy_from_user(&edp, arg, sizeof(edp))) return SYSERR; _wcr(edp[0], edp[1], FUNC_SEL, edp[2]); /* Should wait on Channel Status register bit[9] -- function copy in progress, when data is copying into local SRAM. */ while(_rcr(edp[0], edp[1], CH_STAT) & 1<<9) usec_sleep(1); return OK; case CVORB_FUNC_GET: /* get currently selected function */ if (cdcm_copy_from_user(&edp, arg, sizeof(edp))) return SYSERR; return _rcr(edp[0], edp[1], FUNC_SEL); case CVORB_WRSWP: /* action register. Simulate front panel pulse inputs */ return write_swp(usp, arg); case CVORB_RC_RD: return read_recurrent_cycles_reg(usp, arg); case CVORB_RC_WR: return write_recurrent_cycles_reg(usp, arg); case CVORB_DAC_ON: return dac_on(usp, arg); case CVORB_DAC_OFF: /* disable on-board clock generator */ _wr(0, CLK_GEN_CNTL, AD9516_OFF); return OK; case AD9516_GET_PLL: return get_pll(usp, arg); case CVORB_WR_SAR: return write_sar(usp, arg); default: *proceed = TRUE; /* continue standard code execution */ } return OK; }