Exemple #1
0
static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
                                 unsigned char ucValue)
{
    DSP_ISA_SLAVE_CONTROL rSlaveControl;
    DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;


    PRINTK_4(TRACE_3780I,
             "3780i::dsp3780i_WriteGenCfg entry usDspBaseIO %x uIndex %x ucValue %x\n",
             usDspBaseIO, uIndex, ucValue);

    MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_WriteGenCfg rSlaveControl %x\n",
             MKBYTE(rSlaveControl));

    rSlaveControl_Save = rSlaveControl;
    rSlaveControl.ConfigMode = TRUE;

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_WriteGenCfg entry rSlaveControl+ConfigMode %x\n",
             MKBYTE(rSlaveControl));

    OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
    OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
    OutByteDsp(DSP_ConfigData, ucValue);
    OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));

    PRINTK_1(TRACE_3780I, "3780i::dsp3780i_WriteGenCfg exit\n");


}
Exemple #2
0
int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
	struct resource *pres;
#endif

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
	pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
	if ( pres == NULL ) retval = -EIO;
#else
	retval = check_region(pSettings->usDspBaseIO, 16);
	if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
#endif
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
		retval = -EIO;
	}

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ClaimResources exit retval %x\n", retval);

	return retval;
}
static irqreturn_t DspInterrupt(int irq, void *dev_id)
{
	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pDrvData->rBDData.rDspSettings;
	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
	unsigned short usIPCSource = 0, usIsolationMask, usPCNum;

	PRINTK_3(TRACE_TP3780I,
		"tp3780i::DspInterrupt entry irq %x dev_id %p\n", irq, dev_id);

	if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
		PRINTK_2(TRACE_TP3780I,
			"tp3780i::DspInterrupt, return from dsp3780i_GetIPCSource, usIPCSource %x\n",
			usIPCSource);
		usIsolationMask = 1;
		for (usPCNum = 1; usPCNum <= 16; usPCNum++) {
			if (usIPCSource & usIsolationMask) {
				usIPCSource &= ~usIsolationMask;
				PRINTK_3(TRACE_TP3780I,
					"tp3780i::DspInterrupt usPCNum %x usIPCSource %x\n",
					usPCNum, usIPCSource);
				if (pDrvData->IPCs[usPCNum - 1].usIntCount == 0) {
					pDrvData->IPCs[usPCNum - 1].usIntCount = 1;
				}
				PRINTK_2(TRACE_TP3780I,
					"tp3780i::DspInterrupt usIntCount %x\n",
					pDrvData->IPCs[usPCNum - 1].usIntCount);
				if (pDrvData->IPCs[usPCNum - 1].bIsEnabled == TRUE) {
					PRINTK_2(TRACE_TP3780I,
						"tp3780i::DspInterrupt, waking up usPCNum %x\n",
						usPCNum - 1);
					wake_up_interruptible(&pDrvData->IPCs[usPCNum - 1].ipc_wait_queue);
				} else {
					PRINTK_2(TRACE_TP3780I,
						"tp3780i::DspInterrupt, no one waiting for IPC %x\n",
						usPCNum - 1);
				}
			}
			if (usIPCSource == 0)
				break;
			/*              */
			usIsolationMask = usIsolationMask << 1;
		}
	} else {
		PRINTK_1(TRACE_TP3780I,
			"tp3780i::DspInterrupt, return false from dsp3780i_GetIPCSource\n");
	}
	PRINTK_1(TRACE_TP3780I, "tp3780i::DspInterrupt exit\n");
	return IRQ_HANDLED;
}
Exemple #4
0
unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
                                  unsigned uIndex)
{
    DSP_ISA_SLAVE_CONTROL rSlaveControl;
    DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
    unsigned char ucValue;


    PRINTK_3(TRACE_3780I,
             "3780i::dsp3780i_ReadGenCfg entry usDspBaseIO %x uIndex %x\n",
             usDspBaseIO, uIndex);

    MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
    rSlaveControl_Save = rSlaveControl;
    rSlaveControl.ConfigMode = TRUE;
    OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
    OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
    ucValue = InByteDsp(DSP_ConfigData);
    OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_ReadGenCfg exit ucValue %x\n", ucValue);


    return ucValue;
}
int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities)
{
	int retval = 0;

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_QueryAbilities entry pBDData %p\n", pBDData);

	/*                                   */
	pAbilities->instr_per_sec = pBDData->rDspSettings.uIps;
	pAbilities->data_size = pBDData->rDspSettings.uDStoreSize;
	pAbilities->inst_size = pBDData->rDspSettings.uIStoreSize;
	pAbilities->bus_dma_bw = pBDData->rDspSettings.uDmaBandwidth;

	/*                                        */
	pAbilities->component_list[0] = 0x00010000 | MW_ADC_MASK;
	pAbilities->component_list[1] = 0x00010000 | MW_ACI_MASK;
	pAbilities->component_list[2] = 0x00010000 | MW_AIC1_MASK;
	pAbilities->component_list[3] = 0x00010000 | MW_AIC2_MASK;
	pAbilities->component_list[4] = 0x00010000 | MW_CDDAC_MASK;
	pAbilities->component_list[5] = 0x00010000 | MW_MIDI_MASK;
	pAbilities->component_list[6] = 0x00010000 | MW_UART_MASK;
	pAbilities->component_count = 7;

	/*                                       */

	memcpy(pAbilities->mwave_os_name, TP_ABILITIES_MWAVEOS_NAME,
		sizeof(TP_ABILITIES_MWAVEOS_NAME));
	memcpy(pAbilities->bios_task_name, TP_ABILITIES_BIOSTASK_NAME,
		sizeof(TP_ABILITIES_BIOSTASK_NAME));

	PRINTK_1(TRACE_TP3780I,
		"tp3780i::tp3780I_QueryAbilities exit retval=SUCCESSFUL\n");

	return retval;
}
int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
                               void __user *pvBuffer, unsigned int uCount,
                               unsigned long ulDSPAddr)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
	unsigned short usDspBaseIO = pSettings->usDspBaseIO;
	BOOLEAN bRC = 0;

	PRINTK_6(TRACE_TP3780I,
		"tp3780i::tp3780I_ReadWriteDspIStore entry pBDData %p, uOpcode %x, pvBuffer %p, uCount %x, ulDSPAddr %lx\n",
		pBDData, uOpcode, pvBuffer, uCount, ulDSPAddr);

	if (pBDData->bDSPEnabled) {
		switch (uOpcode) {
		case IOCTL_MW_READ_INST:
			bRC = dsp3780I_ReadIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
			break;

		case IOCTL_MW_WRITE_INST:
			bRC = dsp3780I_WriteIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
			break;
		}
	}

	retval = (bRC) ? -EIO : 0;

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_ReadWriteDspIStore exit retval %x\n", retval);

	return retval;
}
int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP entry pBDData %p\n", pBDData);

	if (dsp3780I_Run(pSettings) == 0) {
		//                               
	} else {
		retval = -EIO;
	}

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP exit retval %x\n", retval);

	return retval;
}
int tp3780I_Cleanup(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_Cleanup entry and exit pBDData %p\n", pBDData);

	return retval;
}
Exemple #9
0
int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
{
    unsigned long flags;
    unsigned short usDspBaseIO = pSettings->usDspBaseIO;
    DSP_BOOT_DOMAIN rBootDomain;
    DSP_HBRIDGE_CONTROL rHBridgeControl;


    PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset entry\n");

    spin_lock_irqsave(&dsp_lock, flags);
    /* Mask DSP to PC interrupt */
    MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);

    PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rHBridgeControl %x\n",
             MKWORD(rHBridgeControl));

    rHBridgeControl.EnableDspInt = FALSE;
    OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
    spin_unlock_irqrestore(&dsp_lock, flags);

    /* Reset the core via the boot domain register */
    rBootDomain.ResetCore = TRUE;
    rBootDomain.Halt = TRUE;
    rBootDomain.NMI = TRUE;
    rBootDomain.Reserved = 0;

    PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rBootDomain %x\n",
             MKWORD(rBootDomain));

    WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));

    /* Reset all the chiplets and then reactivate them */
    WriteMsaCfg(DSP_ChipReset, 0xFFFF);
    udelay(5);
    WriteMsaCfg(DSP_ChipReset,
                (unsigned short) (~pSettings->usChipletEnable));


    PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset exit bRC=0\n");

    return 0;
}
int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_ReleaseResources entry pBDData %p\n", pBDData);

	release_region(pSettings->usDspBaseIO & (~3), 16);

	if (pSettings->bInterruptClaimed) {
		free_irq(pSettings->usDspIrq, NULL);
		pSettings->bInterruptClaimed = FALSE;
	}

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_ReleaseResources exit retval %x\n", retval);

	return retval;
}
Exemple #11
0
static int mwave_open(struct inode *inode, struct file *file)
{
	unsigned int retval = 0;

	PRINTK_3(TRACE_MWAVE,
		"mwavedd::mwave_open, entry inode %p file %p\n",
		 inode, file);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_open, exit return retval %x\n", retval);

	return retval;
}
int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP entry pBDData %p\n", pBDData);

	if (pBDData->bDSPEnabled) {
		dsp3780I_DisableDSP(&pBDData->rDspSettings);
		if (pSettings->bInterruptClaimed) {
			free_irq(pSettings->usDspIrq, NULL);
			pSettings->bInterruptClaimed = FALSE;
		}
		smapi_set_DSP_power_state(FALSE);
		pBDData->bDSPEnabled = FALSE;
	}

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP exit retval %x\n", retval);

	return retval;
}
static int mwave_open(struct inode *inode, struct file *file)
{
	unsigned int retval = 0;

	PRINTK_3(TRACE_MWAVE,
		"mwavedd::mwave_open, entry inode %x file %x\n",
		(int) inode, (int) file);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_open, exit return retval %x\n", retval);

	MOD_INC_USE_COUNT;
	return retval;
}
int tp3780I_InitializeBoardData(THINKPAD_BD_DATA * pBDData)
{
	int retval = 0;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;


	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData entry pBDData %p\n", pBDData);

	pBDData->bDSPEnabled = FALSE;
	pSettings->bInterruptClaimed = FALSE;

	retval = smapi_init();
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_InitializeBoardData: Error: SMAPI is not available on this machine\n");
	} else {
		if (mwave_3780i_irq || mwave_3780i_io || mwave_uart_irq || mwave_uart_io) {
			retval = smapi_set_DSP_cfg();
		}
	}

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData exit retval %x\n", retval);

	return retval;
}
int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData)
{
	SMAPI_DSP_SETTINGS rSmapiInfo;
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;

	PRINTK_2(TRACE_TP3780I,
		"tp3780i::tp3780I_CalcResources entry pBDData %p\n", pBDData);

	if (smapi_query_DSP_cfg(&rSmapiInfo)) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Could not query DSP config. Aborting.\n");
		return -EIO;
	}

	/*              */
	if (
		( rSmapiInfo.usDspIRQ == 0 )
		|| ( rSmapiInfo.usDspBaseIO ==  0 )
		|| ( rSmapiInfo.usUartIRQ ==  0 )
		|| ( rSmapiInfo.usUartBaseIO ==  0 )
	) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Illegal resource setting. Aborting.\n");
		return -EIO;
	}

	pSettings->bDSPEnabled = (rSmapiInfo.bDSPEnabled && rSmapiInfo.bDSPPresent);
	pSettings->bModemEnabled = rSmapiInfo.bModemEnabled;
	pSettings->usDspIrq = rSmapiInfo.usDspIRQ;
	pSettings->usDspDma = rSmapiInfo.usDspDMA;
	pSettings->usDspBaseIO = rSmapiInfo.usDspBaseIO;
	pSettings->usUartIrq = rSmapiInfo.usUartIRQ;
	pSettings->usUartBaseIO = rSmapiInfo.usUartBaseIO;

	pSettings->uDStoreSize = TP_ABILITIES_DATA_SIZE;
	pSettings->uIStoreSize = TP_ABILITIES_INST_SIZE;
	pSettings->uIps = TP_ABILITIES_INTS_PER_SEC;

	if (pSettings->bDSPEnabled && pSettings->bModemEnabled && pSettings->usDspIrq == pSettings->usUartIrq) {
		pBDData->bShareDspIrq = pBDData->bShareUartIrq = 1;
	} else {
		pBDData->bShareDspIrq = pBDData->bShareUartIrq = 0;
	}

	PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_CalcResources exit\n");

	return 0;
}
Exemple #16
0
int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
{
    unsigned long flags;
    unsigned short usDspBaseIO = pSettings->usDspBaseIO;
    DSP_BOOT_DOMAIN rBootDomain;
    DSP_HBRIDGE_CONTROL rHBridgeControl;


    PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run entry\n");


    /* Transition the core to a running state */
    rBootDomain.ResetCore = TRUE;
    rBootDomain.Halt = FALSE;
    rBootDomain.NMI = TRUE;
    rBootDomain.Reserved = 0;
    WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));

    udelay(5);

    rBootDomain.ResetCore = FALSE;
    WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
    udelay(5);

    rBootDomain.NMI = FALSE;
    WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
    udelay(5);

    /* Enable DSP to PC interrupt */
    spin_lock_irqsave(&dsp_lock, flags);
    MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
    rHBridgeControl.EnableDspInt = TRUE;

    PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Run rHBridgeControl %x\n",
             MKWORD(rHBridgeControl));

    OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
    spin_unlock_irqrestore(&dsp_lock, flags);


    PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run exit bRC=TRUE\n");

    return 0;
}
Exemple #17
0
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
                                   unsigned long ulMsaAddr)
{
    unsigned short val;

    PRINTK_3(TRACE_3780I,
             "3780i::dsp3780I_ReadMsaCfg entry usDspBaseIO %x ulMsaAddr %lx\n",
             usDspBaseIO, ulMsaAddr);

    spin_lock_irqsave(&dsp_lock, flags);
    OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
    OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
    val = InWordDsp(DSP_MsaDataDSISHigh);
    spin_unlock_irqrestore(&dsp_lock, flags);

    PRINTK_2(TRACE_3780I, "3780i::dsp3780I_ReadMsaCfg exit val %x\n", val);

    return val;
}
Exemple #18
0
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
                          unsigned short *pusIPCSource)
{
    unsigned long flags;
    DSP_HBRIDGE_CONTROL rHBridgeControl;
    unsigned short temp;


    PRINTK_3(TRACE_3780I,
             "3780i::dsp3780I_GetIPCSource entry usDspBaseIO %x pusIPCSource %p\n",
             usDspBaseIO, pusIPCSource);

    /*
    * Disable DSP to PC interrupts, read the interrupt register,
    * clear the pending IPC bits, and reenable DSP to PC interrupts
    */
    spin_lock_irqsave(&dsp_lock, flags);
    MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
    rHBridgeControl.EnableDspInt = FALSE;
    OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));

    *pusIPCSource = InWordDsp(DSP_Interrupt);
    temp = (unsigned short) ~(*pusIPCSource);

    PRINTK_3(TRACE_3780I,
             "3780i::dsp3780I_GetIPCSource, usIPCSource %x ~ %x\n",
             *pusIPCSource, temp);

    OutWordDsp(DSP_Interrupt, (unsigned short) ~(*pusIPCSource));

    rHBridgeControl.EnableDspInt = TRUE;
    OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
    spin_unlock_irqrestore(&dsp_lock, flags);


    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780I_GetIPCSource exit usIPCSource %x\n",
             *pusIPCSource);

    return 0;
}
Exemple #19
0
static int __init mwave_init(void)
{
	int i;
	int retval = 0;
	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;

	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");

	memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));

	pDrvData->bBDInitialized = FALSE;
	pDrvData->bResourcesClaimed = FALSE;
	pDrvData->bDSPEnabled = FALSE;
	pDrvData->bDSPReset = FALSE;
	pDrvData->bMwaveDevRegistered = FALSE;
	pDrvData->sLine = -1;

	for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) {
		pDrvData->IPCs[i].bIsEnabled = FALSE;
		pDrvData->IPCs[i].bIsHere = FALSE;
		pDrvData->IPCs[i].usIntCount = 0;	/* no ints received yet */
		init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
	}

	retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_InitializeBoardData"
		" retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd::mwave_init: Error:"
				" Failed to initialize board data\n");
		goto cleanup_error;
	}
	pDrvData->bBDInitialized = TRUE;

	retval = tp3780I_CalcResources(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_CalcResources"
		" retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd:mwave_init: Error:"
				" Failed to calculate resources\n");
		goto cleanup_error;
	}

	retval = tp3780I_ClaimResources(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_ClaimResources"
		" retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd:mwave_init: Error:"
				" Failed to claim resources\n");
		goto cleanup_error;
	}
	pDrvData->bResourcesClaimed = TRUE;

	retval = tp3780I_EnableDSP(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_EnableDSP"
		" retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd:mwave_init: Error:"
				" Failed to enable DSP\n");
		goto cleanup_error;
	}
	pDrvData->bDSPEnabled = TRUE;

	if (misc_register(&mwave_misc_dev) < 0) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd:mwave_init: Error:"
				" Failed to register misc device\n");
		goto cleanup_error;
	}
	pDrvData->bMwaveDevRegistered = TRUE;

	pDrvData->sLine = register_serial_portandirq(
		pDrvData->rBDData.rDspSettings.usUartBaseIO,
		pDrvData->rBDData.rDspSettings.usUartIrq
	);
	if (pDrvData->sLine < 0) {
		PRINTK_ERROR(KERN_ERR_MWAVE
				"mwavedd:mwave_init: Error:"
				" Failed to register serial driver\n");
		goto cleanup_error;
	}
	/* uart is registered */

#if 0
	/* sysfs */
	memset(&mwave_device, 0, sizeof (struct device));
	dev_set_name(&mwave_device, "mwave");

	if (device_register(&mwave_device))
		goto cleanup_error;
	pDrvData->device_registered = TRUE;
	for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
		if(device_create_file(&mwave_device, mwave_dev_attrs[i])) {
			PRINTK_ERROR(KERN_ERR_MWAVE
					"mwavedd:mwave_init: Error:"
					" Failed to create sysfs file %s\n",
					mwave_dev_attrs[i]->attr.name);
			goto cleanup_error;
		}
		pDrvData->nr_registered_attrs++;
	}
#endif

	/* SUCCESS! */
	return 0;

cleanup_error:
	PRINTK_ERROR(KERN_ERR_MWAVE
			"mwavedd::mwave_init: Error:"
			" Failed to initialize\n");
	mwave_exit(); /* clean up */

	return -EIO;
}
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;
}
static int __init mwave_init(void)
{
	int i;
	int retval = 0;
	int resultMiscRegister;
	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;

	memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));

	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");

	pDrvData->bBDInitialized = FALSE;
	pDrvData->bResourcesClaimed = FALSE;
	pDrvData->bDSPEnabled = FALSE;
	pDrvData->bDSPReset = FALSE;
	pDrvData->bMwaveDevRegistered = FALSE;
	pDrvData->sLine = -1;
	pDrvData->bProcEntryCreated = FALSE;

	for (i = 0; i < 16; i++) {
		pDrvData->IPCs[i].bIsEnabled = FALSE;
		pDrvData->IPCs[i].bIsHere = FALSE;
		pDrvData->IPCs[i].usIntCount = 0;	/* no ints received yet */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
		init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
#endif
	}

	retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_InitializeBoardData retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize board data\n");
		goto cleanup_error;
	}
	pDrvData->bBDInitialized = TRUE;

	retval = tp3780I_CalcResources(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_CalcResources retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to calculate resources\n");
		goto cleanup_error;
	}

	retval = tp3780I_ClaimResources(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_ClaimResources retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to claim resources\n");
		goto cleanup_error;
	}
	pDrvData->bResourcesClaimed = TRUE;

	retval = tp3780I_EnableDSP(&pDrvData->rBDData);
	PRINTK_2(TRACE_MWAVE,
		"mwavedd::mwave_init, return from tp3780I_EnableDSP retval %x\n",
		retval);
	if (retval) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to enable DSP\n");
		goto cleanup_error;
	}
	pDrvData->bDSPEnabled = TRUE;

	resultMiscRegister = misc_register(&mwave_misc_dev);
	if (resultMiscRegister < 0) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register misc device\n");
		goto cleanup_error;
	}
	pDrvData->bMwaveDevRegistered = TRUE;

	pDrvData->sLine = register_serial_portandirq(
		pDrvData->rBDData.rDspSettings.usUartBaseIO,
		pDrvData->rBDData.rDspSettings.usUartIrq
	);
	if (pDrvData->sLine < 0) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register serial driver\n");
		goto cleanup_error;
	}
	/* uart is registered */

	if (
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
		!create_proc_info_entry("mwave", 0, NULL, mwave_get_info)
#else
		proc_register(&proc_root, &mwave_proc)
#endif
	) {
		PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to register /proc/mwave\n");
		goto cleanup_error;
	}
	pDrvData->bProcEntryCreated = TRUE;

	/* SUCCESS! */
	return 0;

	cleanup_error:
	PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize\n");
	mwave_exit(); /* clean up */

	return -EIO;
}
Exemple #22
0
int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
                       unsigned short *pIrqMap,
                       unsigned short *pDmaMap)
{
    unsigned long flags;
    unsigned short usDspBaseIO = pSettings->usDspBaseIO;
    int i;
    DSP_UART_CFG_1 rUartCfg1;
    DSP_UART_CFG_2 rUartCfg2;
    DSP_HBRIDGE_CFG_1 rHBridgeCfg1;
    DSP_HBRIDGE_CFG_2 rHBridgeCfg2;
    DSP_BUSMASTER_CFG_1 rBusmasterCfg1;
    DSP_BUSMASTER_CFG_2 rBusmasterCfg2;
    DSP_ISA_PROT_CFG rIsaProtCfg;
    DSP_POWER_MGMT_CFG rPowerMgmtCfg;
    DSP_HBUS_TIMER_CFG rHBusTimerCfg;
    DSP_LBUS_TIMEOUT_DISABLE rLBusTimeoutDisable;
    DSP_CHIP_RESET rChipReset;
    DSP_CLOCK_CONTROL_1 rClockControl1;
    DSP_CLOCK_CONTROL_2 rClockControl2;
    DSP_ISA_SLAVE_CONTROL rSlaveControl;
    DSP_HBRIDGE_CONTROL rHBridgeControl;
    unsigned short ChipID = 0;
    unsigned short tval;


    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780I_EnableDSP entry pSettings->bDSPEnabled %x\n",
             pSettings->bDSPEnabled);


    if (!pSettings->bDSPEnabled) {
        PRINTK_ERROR( KERN_ERR "3780i::dsp3780I_EnableDSP: Error: DSP not enabled. Aborting.\n" );
        return -EIO;
    }


    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP entry pSettings->bModemEnabled %x\n",
             pSettings->bModemEnabled);

    if (pSettings->bModemEnabled) {
        rUartCfg1.Reserved = rUartCfg2.Reserved = 0;
        rUartCfg1.IrqActiveLow = pSettings->bUartIrqActiveLow;
        rUartCfg1.IrqPulse = pSettings->bUartIrqPulse;
        rUartCfg1.Irq =
            (unsigned char) pIrqMap[pSettings->usUartIrq];
        switch (pSettings->usUartBaseIO) {
        case 0x03F8:
            rUartCfg1.BaseIO = 0;
            break;
        case 0x02F8:
            rUartCfg1.BaseIO = 1;
            break;
        case 0x03E8:
            rUartCfg1.BaseIO = 2;
            break;
        case 0x02E8:
            rUartCfg1.BaseIO = 3;
            break;
        }
        rUartCfg2.Enable = TRUE;
    }

    rHBridgeCfg1.Reserved = rHBridgeCfg2.Reserved = 0;
    rHBridgeCfg1.IrqActiveLow = pSettings->bDspIrqActiveLow;
    rHBridgeCfg1.IrqPulse = pSettings->bDspIrqPulse;
    rHBridgeCfg1.Irq = (unsigned char) pIrqMap[pSettings->usDspIrq];
    rHBridgeCfg1.AccessMode = 1;
    rHBridgeCfg2.Enable = TRUE;


    rBusmasterCfg2.Reserved = 0;
    rBusmasterCfg1.Dma = (unsigned char) pDmaMap[pSettings->usDspDma];
    rBusmasterCfg1.NumTransfers =
        (unsigned char) pSettings->usNumTransfers;
    rBusmasterCfg1.ReRequest = (unsigned char) pSettings->usReRequest;
    rBusmasterCfg1.MEMCS16 = pSettings->bEnableMEMCS16;
    rBusmasterCfg2.IsaMemCmdWidth =
        (unsigned char) pSettings->usIsaMemCmdWidth;


    rIsaProtCfg.Reserved = 0;
    rIsaProtCfg.GateIOCHRDY = pSettings->bGateIOCHRDY;

    rPowerMgmtCfg.Reserved = 0;
    rPowerMgmtCfg.Enable = pSettings->bEnablePwrMgmt;

    rHBusTimerCfg.LoadValue =
        (unsigned char) pSettings->usHBusTimerLoadValue;

    rLBusTimeoutDisable.Reserved = 0;
    rLBusTimeoutDisable.DisableTimeout =
        pSettings->bDisableLBusTimeout;

    MKWORD(rChipReset) = ~pSettings->usChipletEnable;

    rClockControl1.Reserved1 = rClockControl1.Reserved2 = 0;
    rClockControl1.N_Divisor = pSettings->usN_Divisor;
    rClockControl1.M_Multiplier = pSettings->usM_Multiplier;

    rClockControl2.Reserved = 0;
    rClockControl2.PllBypass = pSettings->bPllBypass;

    /* Issue a soft reset to the chip */
    /* Note: Since we may be coming in with 3780i clocks suspended, we must keep
    * soft-reset active for 10ms.
    */
    rSlaveControl.ClockControl = 0;
    rSlaveControl.SoftReset = TRUE;
    rSlaveControl.ConfigMode = FALSE;
    rSlaveControl.Reserved = 0;

    PRINTK_4(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP usDspBaseIO %x index %x taddr %x\n",
             usDspBaseIO, DSP_IsaSlaveControl,
             usDspBaseIO + DSP_IsaSlaveControl);

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP rSlaveContrl %x\n",
             MKWORD(rSlaveControl));

    spin_lock_irqsave(&dsp_lock, flags);
    OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
    MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP rSlaveControl 2 %x\n", tval);


    for (i = 0; i < 11; i++)
        udelay(2000);

    rSlaveControl.SoftReset = FALSE;
    OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));

    MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP rSlaveControl 3 %x\n", tval);


    /* Program our general configuration registers */
    WriteGenCfg(DSP_HBridgeCfg1Index, MKBYTE(rHBridgeCfg1));
    WriteGenCfg(DSP_HBridgeCfg2Index, MKBYTE(rHBridgeCfg2));
    WriteGenCfg(DSP_BusMasterCfg1Index, MKBYTE(rBusmasterCfg1));
    WriteGenCfg(DSP_BusMasterCfg2Index, MKBYTE(rBusmasterCfg2));
    WriteGenCfg(DSP_IsaProtCfgIndex, MKBYTE(rIsaProtCfg));
    WriteGenCfg(DSP_PowerMgCfgIndex, MKBYTE(rPowerMgmtCfg));
    WriteGenCfg(DSP_HBusTimerCfgIndex, MKBYTE(rHBusTimerCfg));

    if (pSettings->bModemEnabled) {
        WriteGenCfg(DSP_UartCfg1Index, MKBYTE(rUartCfg1));
        WriteGenCfg(DSP_UartCfg2Index, MKBYTE(rUartCfg2));
    }


    rHBridgeControl.EnableDspInt = FALSE;
    rHBridgeControl.MemAutoInc = TRUE;
    rHBridgeControl.IoAutoInc = FALSE;
    rHBridgeControl.DiagnosticMode = FALSE;

    PRINTK_3(TRACE_3780I,
             "3780i::dsp3780i_EnableDSP DSP_HBridgeControl %x rHBridgeControl %x\n",
             DSP_HBridgeControl, MKWORD(rHBridgeControl));

    OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
    spin_unlock_irqrestore(&dsp_lock, flags);
    WriteMsaCfg(DSP_LBusTimeoutDisable, MKWORD(rLBusTimeoutDisable));
    WriteMsaCfg(DSP_ClockControl_1, MKWORD(rClockControl1));
    WriteMsaCfg(DSP_ClockControl_2, MKWORD(rClockControl2));
    WriteMsaCfg(DSP_ChipReset, MKWORD(rChipReset));

    ChipID = ReadMsaCfg(DSP_ChipID);

    PRINTK_2(TRACE_3780I,
             "3780i::dsp3780I_EnableDSP exiting bRC=TRUE, ChipID %x\n",
             ChipID);

    return 0;
}
int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
{
	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
	BOOLEAN bDSPPoweredUp = FALSE, bInterruptAllocated = FALSE;

	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);

	if (pBDData->bDSPEnabled) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: DSP already enabled!\n");
		goto exit_cleanup;
	}

	if (!pSettings->bDSPEnabled) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780::tp3780I_EnableDSP: Error: pSettings->bDSPEnabled not set\n");
		goto exit_cleanup;
	}

	if (
		(pSettings->usDspIrq >= s_numIrqs)
		|| (pSettings->usDspDma >= s_numDmas)
		|| (s_ausThinkpadIrqToField[pSettings->usDspIrq] == 0xFFFF)
		|| (s_ausThinkpadDmaToField[pSettings->usDspDma] == 0xFFFF)
	) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: invalid irq %x\n", pSettings->usDspIrq);
		goto exit_cleanup;
	}

	if (
		((pSettings->usDspBaseIO & 0xF00F) != 0)
		|| (pSettings->usDspBaseIO & 0x0FF0) == 0
	) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid DSP base I/O address %x\n", pSettings->usDspBaseIO);
		goto exit_cleanup;
	}

	if (pSettings->bModemEnabled) {
		if (
			pSettings->usUartIrq >= s_numIrqs
			|| s_ausThinkpadIrqToField[pSettings->usUartIrq] == 0xFFFF
		) {
			PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid UART IRQ %x\n", pSettings->usUartIrq);
			goto exit_cleanup;
		}
		switch (pSettings->usUartBaseIO) {
			case 0x03F8:
			case 0x02F8:
			case 0x03E8:
			case 0x02E8:
				break;

			default:
				PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Invalid UART base I/O address %x\n", pSettings->usUartBaseIO);
				goto exit_cleanup;
		}
	}

	pSettings->bDspIrqActiveLow = pSettings->bDspIrqPulse = TRUE;
	pSettings->bUartIrqActiveLow = pSettings->bUartIrqPulse = TRUE;

	if (pBDData->bShareDspIrq) {
		pSettings->bDspIrqActiveLow = FALSE;
	}
	if (pBDData->bShareUartIrq) {
		pSettings->bUartIrqActiveLow = FALSE;
	}

	pSettings->usNumTransfers = TP_CFG_NumTransfers;
	pSettings->usReRequest = TP_CFG_RerequestTimer;
	pSettings->bEnableMEMCS16 = TP_CFG_MEMCS16;
	pSettings->usIsaMemCmdWidth = TP_CFG_IsaMemCmdWidth;
	pSettings->bGateIOCHRDY = TP_CFG_GateIOCHRDY;
	pSettings->bEnablePwrMgmt = TP_CFG_EnablePwrMgmt;
	pSettings->usHBusTimerLoadValue = TP_CFG_HBusTimerValue;
	pSettings->bDisableLBusTimeout = TP_CFG_DisableLBusTimeout;
	pSettings->usN_Divisor = TP_CFG_N_Divisor;
	pSettings->usM_Multiplier = TP_CFG_M_Multiplier;
	pSettings->bPllBypass = TP_CFG_PllBypass;
	pSettings->usChipletEnable = TP_CFG_ChipletEnable;

	if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart", NULL)) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Could not get UART IRQ %x\n", pSettings->usUartIrq);
		goto exit_cleanup;
	} else {		/*                          */
		free_irq(pSettings->usUartIrq, NULL);
	}

	if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i", NULL)) {
		PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Could not get 3780i IRQ %x\n", pSettings->usDspIrq);
		goto exit_cleanup;
	} else {
		PRINTK_3(TRACE_TP3780I,
			"tp3780i::tp3780I_EnableDSP, got interrupt %x bShareDspIrq %x\n",
			pSettings->usDspIrq, pBDData->bShareDspIrq);
		bInterruptAllocated = TRUE;
		pSettings->bInterruptClaimed = TRUE;
	}

	smapi_set_DSP_power_state(FALSE);
	if (smapi_set_DSP_power_state(TRUE)) {
		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: smapi_set_DSP_power_state(TRUE) failed\n");
		goto exit_cleanup;
	} else {
		bDSPPoweredUp = TRUE;
	}

	if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
		PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
		goto exit_cleanup;
	}

	EnableSRAM(pBDData);

	pBDData->bDSPEnabled = TRUE;

	PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP exit\n");

	return 0;

exit_cleanup:
	PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
	if (bDSPPoweredUp)
		smapi_set_DSP_power_state(FALSE);
	if (bInterruptAllocated) {
		free_irq(pSettings->usDspIrq, NULL);
		pSettings->bInterruptClaimed = FALSE;
	}
	return -EIO;
}
Exemple #24
0
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;
			}
			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;
			}
			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;
			}
			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;
			break;
	} /* switch */

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

	return retval;
}