Beispiel #1
0
static ssize_t mwave_read(struct file *file, char __user *buf, size_t count,
                          loff_t * ppos)
{
	PRINTK_5(TRACE_MWAVE,
		"mwavedd::mwave_read entry file %p, buf %p, count %zx ppos %p\n",
		file, buf, count, ppos);

	return -EINVAL;
}
static ssize_t mwave_write(struct file *file, const char *buf,
                           size_t count, loff_t * ppos)
{
	PRINTK_5(TRACE_MWAVE,
		"mwavedd::mwave_write entry file %p, buf %p, count %x ppos %p\n",
		file, buf, count, ppos);

	return -EINVAL;
}
Beispiel #3
0
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
{
    unsigned long flags;
    unsigned short __user *pusBuffer = pvBuffer;

    PRINTK_5(TRACE_3780I,
             "3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
             usDspBaseIO, pusBuffer, uCount, ulDSPAddr);


    /*
    * Set the initial MSA address. To convert from an instruction store
    * address to an MSA address
    * shift the address two bits to the left and set bit 22
    */
    ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
    spin_lock_irqsave(&dsp_lock, flags);
    OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
    OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
    spin_unlock_irqrestore(&dsp_lock, flags);

    /* Transfer the memory block */
    while (uCount-- != 0) {
        unsigned short val_lo, val_hi;
        if(get_user(val_lo, pusBuffer++))
            return -EFAULT;
        if(get_user(val_hi, pusBuffer++))
            return -EFAULT;
        spin_lock_irqsave(&dsp_lock, flags);
        OutWordDsp(DSP_MsaDataISLow, val_lo);
        OutWordDsp(DSP_MsaDataDSISHigh, val_hi);
        spin_unlock_irqrestore(&dsp_lock, flags);

        PRINTK_4(TRACE_3780I,
                 "3780I::dsp3780I_WriteIStore uCount %x val_lo %x val_hi %x\n",
                 uCount, val_lo, val_hi);

        PaceMsaAccess(usDspBaseIO);

    }

    PRINTK_1(TRACE_3780I,
             "3780I::dsp3780I_WriteIStore exit bRC=TRUE\n");

    return 0;
}
Beispiel #4
0
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                         unsigned uCount, unsigned long ulDSPAddr)
{
	unsigned long flags;
	unsigned short __user *pusBuffer = pvBuffer;

	PRINTK_5(TRACE_3780I,
		"3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
		usDspBaseIO, pusBuffer, uCount, ulDSPAddr);


	
	ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
	spin_lock_irqsave(&dsp_lock, flags);
	OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
	OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
	spin_unlock_irqrestore(&dsp_lock, flags);

	
	while (uCount-- != 0) {
		unsigned short val_lo, val_hi;
		if(get_user(val_lo, pusBuffer++))
			return -EFAULT;
		if(get_user(val_hi, pusBuffer++))
			return -EFAULT;
		spin_lock_irqsave(&dsp_lock, flags);
		OutWordDsp(DSP_MsaDataISLow, val_lo);
		OutWordDsp(DSP_MsaDataDSISHigh, val_hi);
		spin_unlock_irqrestore(&dsp_lock, flags);

		PRINTK_4(TRACE_3780I,
			"3780I::dsp3780I_WriteIStore uCount %x val_lo %x val_hi %x\n",
			uCount, val_lo, val_hi);

		PaceMsaAccess(usDspBaseIO);

	}

	PRINTK_1(TRACE_3780I,
		"3780I::dsp3780I_WriteIStore exit bRC=TRUE\n");

	return 0;
}
Beispiel #5
0
int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
                                void __user *pvBuffer, unsigned uCount,
                                unsigned long ulDSPAddr)
{
    unsigned long flags;
    unsigned short __user *pusBuffer = pvBuffer;
    unsigned short val;


    PRINTK_5(TRACE_3780I,
             "3780i::dsp3780I_ReadAndDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
             usDspBaseIO, pusBuffer, uCount, ulDSPAddr);


    /* Set the initial MSA address. No adjustments need to be made to data store addresses */
    spin_lock_irqsave(&dsp_lock, flags);
    OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
    OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
    spin_unlock_irqrestore(&dsp_lock, flags);

    /* Transfer the memory block */
    while (uCount-- != 0) {
        spin_lock_irqsave(&dsp_lock, flags);
        val = InWordDsp(DSP_ReadAndClear);
        spin_unlock_irqrestore(&dsp_lock, flags);
        if(put_user(val, pusBuffer++))
            return -EFAULT;

        PRINTK_3(TRACE_3780I,
                 "3780I::dsp3780I_ReadAndCleanDStore uCount %x val %x\n",
                 uCount, val);

        PaceMsaAccess(usDspBaseIO);
    }


    PRINTK_1(TRACE_3780I,
             "3780I::dsp3780I_ReadAndClearDStore exit bRC=TRUE\n");

    return 0;
}
Beispiel #6
0
int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
                        unsigned uCount, unsigned long ulDSPAddr)
{
	unsigned long flags;
	unsigned short __user *pusBuffer = pvBuffer;
	unsigned short val;


	PRINTK_5(TRACE_3780I,
		"3780i::dsp3780I_ReadDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
		usDspBaseIO, pusBuffer, uCount, ulDSPAddr);


	
	spin_lock_irqsave(&dsp_lock, flags);
	OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
	OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
	spin_unlock_irqrestore(&dsp_lock, flags);

	
	while (uCount-- != 0) {
		spin_lock_irqsave(&dsp_lock, flags);
		val = InWordDsp(DSP_MsaDataDSISHigh);
		spin_unlock_irqrestore(&dsp_lock, flags);
		if(put_user(val, pusBuffer++))
			return -EFAULT;

		PRINTK_3(TRACE_3780I,
			"3780I::dsp3780I_ReadDStore uCount %x val %x\n",
			uCount, val);

		PaceMsaAccess(usDspBaseIO);
	}


	PRINTK_1(TRACE_3780I,
		"3780I::dsp3780I_ReadDStore exit bRC=TRUE\n");

	return 0;
}
static int mwave_ioctl(struct inode *inode, struct file *file,
                       unsigned int iocmd, unsigned long ioarg)
{
	unsigned int retval = 0;
	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;

	PRINTK_5(TRACE_MWAVE,
		"mwavedd::mwave_ioctl, entry inode %x file %x cmd %x arg %x\n",
		(int) inode, (int) file, iocmd, (int) ioarg);

	switch (iocmd) {

		case IOCTL_MW_RESET:
			PRINTK_1(TRACE_MWAVE,
				"mwavedd::mwave_ioctl, IOCTL_MW_RESET calling tp3780I_ResetDSP\n");
			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
			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");
			retval = tp3780I_StartDSP(&pDrvData->rBDData);
			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");
			retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities);
			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((char *) ioarg, (char *) &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 *pusBuffer = 0;
	
			if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
				return -EFAULT;
			pusBuffer = (unsigned short *) (rReadData.pBuf);
	
			PRINTK_4(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA, size %lx, ioarg %lx pusBuffer %p\n",
				rReadData.ulDataLength, ioarg, pusBuffer);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
				(void *) pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress);
		}
			break;
	
		case IOCTL_MW_READ_INST: {
			MW_READWRITE rReadData;
			unsigned short *pusBuffer = 0;
	
			if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) )
				return -EFAULT;
			pusBuffer = (unsigned short *) (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);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
				iocmd, pusBuffer,
				rReadData.ulDataLength / 2,
				rReadData.usDspAddress);
		}
			break;
	
		case IOCTL_MW_WRITE_DATA: {
			MW_READWRITE rWriteData;
			unsigned short *pusBuffer = 0;
	
			if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
				return -EFAULT;
			pusBuffer = (unsigned short *) (rWriteData.pBuf);
	
			PRINTK_4(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA, size %lx, ioarg %lx pusBuffer %p\n",
				rWriteData.ulDataLength, ioarg,
				pusBuffer);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd,
				pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
		}
			break;
	
		case IOCTL_MW_WRITE_INST: {
			MW_READWRITE rWriteData;
			unsigned short *pusBuffer = 0;
	
			if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) )
				return -EFAULT;
			pusBuffer = (unsigned short *) (rWriteData.pBuf);
	
			PRINTK_4(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST, size %lx, ioarg %lx pusBuffer %p\n",
				rWriteData.ulDataLength, ioarg,
				pusBuffer);
			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd,
					pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress);
		}
			break;
	
		case IOCTL_MW_REGISTER_IPC: {
			unsigned int ipcnum = (unsigned int) ioarg;
	
			PRINTK_3(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x entry usIntCount %x\n",
				ipcnum,
				pDrvData->IPCs[ipcnum].usIntCount);
	
			if (ipcnum > 16) {
				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum);
				return -EINVAL;
			}
			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
	#else
			current->priority = 0x28;	/* boost to provide priority timing */
	#endif
	
			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;
			spinlock_t ipc_lock = SPIN_LOCK_UNLOCKED;
			unsigned long flags;
	
			PRINTK_3(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x, usIntCount %x\n",
				ipcnum,
				pDrvData->IPCs[ipcnum].usIntCount);
			if (ipcnum > 16) {
				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %x\n", ipcnum);
				return -EINVAL;
			}
	
			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
				PRINTK_2(TRACE_MWAVE,
					"mwavedd::mwave_ioctl, thread for ipc %x going to sleep\n",
					ipcnum);
	
				spin_lock_irqsave(&ipc_lock, flags);
				/* 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 */
					spin_unlock_irqrestore(&ipc_lock, flags);
					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 */
					pDrvData->IPCs[ipcnum].bIsHere = TRUE;
					interruptible_sleep_on(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
					pDrvData->IPCs[ipcnum].bIsHere = FALSE;
					if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
						pDrvData->IPCs[ipcnum].
						usIntCount = 2;
					}
					spin_unlock_irqrestore(&ipc_lock, flags);
					PRINTK_2(TRACE_MWAVE,
						"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x woke up and returning to application\n",
						ipcnum);
				}
				PRINTK_2(TRACE_MWAVE,
					"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC, returning thread for ipc %x processing\n",
					ipcnum);
			}
		}
			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 > 16) {
				PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum);
				return -EINVAL;
			}
			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);
				}
			}
		}
			break;
	
		default:
			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: Error: Unrecognized iocmd %x\n", iocmd);
			return -ENOTTY;
			break;
	} /* switch */

	PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);

	return retval;
}
Beispiel #8
0
static int mwave_ioctl(struct inode *inode, 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_5(TRACE_MWAVE,
		"mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n",
		 inode,  file, iocmd, (int) ioarg);

	switch (iocmd) {

		case IOCTL_MW_RESET:
			PRINTK_1(TRACE_MWAVE,
				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
				" calling tp3780I_ResetDSP\n");
			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
			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");
			retval = tp3780I_StartDSP(&pDrvData->rBDData);
			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");
			retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
					&rAbilities);
			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);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
					iocmd,
					pusBuffer,
					rReadData.ulDataLength,
					rReadData.usDspAddress);
		}
			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);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
				iocmd, pusBuffer,
				rReadData.ulDataLength / 2,
				rReadData.usDspAddress);
		}
			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);
			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
					iocmd, pusBuffer,
					rWriteData.ulDataLength,
					rWriteData.usDspAddress);
		}
			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);
			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
					iocmd, pusBuffer,
					rWriteData.ulDataLength,
					rWriteData.usDspAddress);
		}
			break;
	
		case IOCTL_MW_REGISTER_IPC: {
			unsigned int ipcnum = (unsigned int) ioarg;
	
			PRINTK_3(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
				" ipcnum %x entry usIntCount %x\n",
				ipcnum,
				pDrvData->IPCs[ipcnum].usIntCount);
	
			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;
			}
			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
	
			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;
	
			PRINTK_3(TRACE_MWAVE,
				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
				" ipcnum %x, usIntCount %x\n",
				ipcnum,
				pDrvData->IPCs[ipcnum].usIntCount);
			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;
			}
	
			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);
			}
		}
			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;
			}
			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);
				}
			}
		}
			break;
	
		default:
			PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:"
					" Error: Unrecognized iocmd %x\n",
					iocmd);
			return -ENOTTY;
			break;
	} /* switch */

	PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);

	return retval;
}