in mwave/mwavedd.c [123:411]
static long mwave_ioctl(struct file *file, unsigned int iocmd,
unsigned long ioarg)
{
unsigned int retval = 0;
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
void __user *arg = (void __user *)ioarg;
PRINTK_4(TRACE_MWAVE,
"mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
file, iocmd, (int) ioarg);
switch (iocmd) {
case IOCTL_MW_RESET:
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" calling tp3780I_ResetDSP\n");
mutex_lock(&mwave_mutex);
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" retval %x from tp3780I_ResetDSP\n",
retval);
break;
case IOCTL_MW_RUN:
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" calling tp3780I_StartDSP\n");
mutex_lock(&mwave_mutex);
retval = tp3780I_StartDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" retval %x from tp3780I_StartDSP\n",
retval);
break;
case IOCTL_MW_DSP_ABILITIES: {
MW_ABILITIES rAbilities;
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl,"
" IOCTL_MW_DSP_ABILITIES calling"
" tp3780I_QueryAbilities\n");
mutex_lock(&mwave_mutex);
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
" retval %x from tp3780I_QueryAbilities\n",
retval);
if (retval == 0) {
if( copy_to_user(arg, &rAbilities,
sizeof(MW_ABILITIES)) )
return -EFAULT;
}
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
" exit retval %x\n",
retval);
}
break;
case IOCTL_MW_READ_DATA:
case IOCTL_MW_READCLEAR_DATA: {
MW_READWRITE rReadData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rReadData, arg,
sizeof(MW_READWRITE)) )
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
PRINTK_4(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength, ioarg, pusBuffer);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd,
pusBuffer,
rReadData.ulDataLength,
rReadData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_READ_INST: {
MW_READWRITE rReadData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rReadData, arg,
sizeof(MW_READWRITE)) )
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
PRINTK_4(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength / 2, ioarg,
pusBuffer);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rReadData.ulDataLength / 2,
rReadData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_WRITE_DATA: {
MW_READWRITE rWriteData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rWriteData, arg,
sizeof(MW_READWRITE)) )
return -EFAULT;
pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
PRINTK_4(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_WRITE_INST: {
MW_READWRITE rWriteData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rWriteData, arg,
sizeof(MW_READWRITE)) )
return -EFAULT;
pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
PRINTK_4(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_REGISTER_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
PRINTK_ERROR(KERN_ERR_MWAVE
"mwavedd::mwave_ioctl:"
" IOCTL_MW_REGISTER_IPC:"
" Error: Invalid ipcnum %x\n",
ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
PRINTK_3(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
" ipcnum %x entry usIntCount %x\n",
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
mutex_lock(&mwave_mutex);
pDrvData->IPCs[ipcnum].bIsHere = false;
pDrvData->IPCs[ipcnum].bIsEnabled = true;
mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
" ipcnum %x exit\n",
ipcnum);
}
break;
case IOCTL_MW_GET_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
PRINTK_ERROR(KERN_ERR_MWAVE
"mwavedd::mwave_ioctl:"
" IOCTL_MW_GET_IPC: Error:"
" Invalid ipcnum %x\n", ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
PRINTK_3(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
" ipcnum %x, usIntCount %x\n",
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
DECLARE_WAITQUEUE(wait, current);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, thread for"
" ipc %x going to sleep\n",
ipcnum);
add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
pDrvData->IPCs[ipcnum].bIsHere = true;
set_current_state(TASK_INTERRUPTIBLE);
/* check whether an event was signalled by */
/* the interrupt handler while we were gone */
if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */
pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl"
" IOCTL_MW_GET_IPC ipcnum %x"
" handling first int\n",
ipcnum);
} else { /* either 1st int has not yet occurred, or we have already handled the first int */
schedule();
if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
pDrvData->IPCs[ipcnum].usIntCount = 2;
}
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl"
" IOCTL_MW_GET_IPC ipcnum %x"
" woke up and returning to"
" application\n",
ipcnum);
}
pDrvData->IPCs[ipcnum].bIsHere = false;
remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
set_current_state(TASK_RUNNING);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC,"
" returning thread for ipc %x"
" processing\n",
ipcnum);
}
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_UNREGISTER_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
" ipcnum %x\n",
ipcnum);
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
PRINTK_ERROR(KERN_ERR_MWAVE
"mwavedd::mwave_ioctl:"
" IOCTL_MW_UNREGISTER_IPC:"
" Error: Invalid ipcnum %x\n",
ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
pDrvData->IPCs[ipcnum].bIsEnabled = false;
if (pDrvData->IPCs[ipcnum].bIsHere == true) {
wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
}
}
mutex_unlock(&mwave_mutex);
}
break;
default:
return -ENOTTY;
} /* switch */
PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);
return retval;
}