char/mwave: drop it

When I tried to clean up the driver a bit, Arnd noted:
> According to thinkwiki.de, the 3780i modem was only used in a
> couple of Thinkpad models that are now over 25 years old, using
> Pentium II processors, and they all have a physical RS232 port
> that can be used to connect an external modem instead.
>
> Maybe we can just retire this driver?

So instead of the clean up, drop the driver altogether.

Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
Suggested-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/all/b8834e5d-fdde-4b1a-8757-288dddc507a9@app.fastmail.com/
Link: https://patch.msgid.link/20251124103952.995229-1-jirislaby@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jiri Slaby (SUSE) 2025-11-24 11:39:52 +01:00 committed by Greg Kroah-Hartman
parent 1f4c9d8a10
commit c0fef45dba
16 changed files with 1 additions and 2642 deletions

View file

@ -352,7 +352,7 @@
216 = /dev/fujitsu/apanel Fujitsu/Siemens application panel
217 = /dev/ni/natmotn National Instruments Motion
218 = /dev/kchuid Inter-process chuid control
219 = /dev/modems/mwave MWave modem firmware upload
219 =
220 = /dev/mptctl Message passing technology (MPT) control
221 = /dev/mvista/hssdsi Montavista PICMG hot swap system driver
222 = /dev/mvista/hasi Montavista PICMG high availability

View file

@ -397,7 +397,6 @@ Code Seq# Include File Comments
0xCD 01 linux/reiserfs_fs.h Dead since 6.13
0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices
0xCF 02 fs/smb/client/cifs_ioctl.h
0xDB 00-0F drivers/char/mwave/mwavepub.h
0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
<mailto:aherrman@de.ibm.com>
0xE5 00-3F linux/fuse.h

View file

@ -249,32 +249,6 @@ config SONYPI
To compile this driver as a module, choose M here: the
module will be called sonypi.
config MWAVE
tristate "ACP Modem (Mwave) support"
depends on X86 && TTY
select SERIAL_8250
help
The ACP modem (Mwave) for Linux is a WinModem. It is composed of a
kernel driver and a user level application. Together these components
support direct attachment to public switched telephone networks (PSTNs)
and support selected world wide countries.
This version of the ACP Modem driver supports the IBM Thinkpad 600E,
600, and 770 that include on board ACP modem hardware.
The modem also supports the standard communications port interface
(ttySx) and is compatible with the Hayes AT Command Set.
The user level application needed to use this driver can be found at
the IBM Linux Technology Center (LTC) web site:
<http://www.ibm.com/linux/ltc/>.
If you own one of the above IBM Thinkpads which has the Mwave chipset
in it, say Y.
To compile this driver as a module, choose M here: the
module will be called mwave.
config SCx200_GPIO
tristate "NatSemi SCx200 GPIO Support"
depends on SCx200

View file

@ -33,7 +33,6 @@ obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
obj-$(CONFIG_MWAVE) += mwave/
obj-y += agp/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o

View file

@ -1,536 +0,0 @@
/*
*
* 3780i.c -- helper routines for the 3780i DSP
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "3780i: " fmt
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/bitops.h>
#include <linux/sched.h> /* cond_resched() */
#include <asm/io.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
static DEFINE_SPINLOCK(dsp_lock);
static void PaceMsaAccess(unsigned short usDspBaseIO)
{
cond_resched();
udelay(100);
cond_resched();
}
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr)
{
unsigned long flags;
unsigned short val;
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);
return val;
}
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue)
{
unsigned long flags;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
OutWordDsp(DSP_MsaDataDSISHigh, usValue);
spin_unlock_irqrestore(&dsp_lock, flags);
}
static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
unsigned char ucValue)
{
DSP_ISA_SLAVE_CONTROL rSlaveControl;
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
rSlaveControl_Save = rSlaveControl;
rSlaveControl.ConfigMode = true;
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
OutByteDsp(DSP_ConfigData, ucValue);
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
}
int dsp3780I_EnableDSP(struct 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 tval;
if (!pSettings->bDSPEnabled) {
pr_err("%s: Error: DSP not enabled. Aborting.\n", __func__);
return -EIO;
}
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;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
for (i = 0; i < 11; i++)
udelay(2000);
rSlaveControl.SoftReset = false;
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
/* 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;
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));
ReadMsaCfg(DSP_ChipID);
return 0;
}
int dsp3780I_DisableDSP(struct dsp_3780i_config_settings *pSettings)
{
unsigned long flags;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
DSP_ISA_SLAVE_CONTROL rSlaveControl;
rSlaveControl.ClockControl = 0;
rSlaveControl.SoftReset = true;
rSlaveControl.ConfigMode = false;
rSlaveControl.Reserved = 0;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
udelay(5);
rSlaveControl.ClockControl = 1;
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
spin_unlock_irqrestore(&dsp_lock, flags);
udelay(5);
return 0;
}
int dsp3780I_Reset(struct dsp_3780i_config_settings *pSettings)
{
unsigned long flags;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
DSP_BOOT_DOMAIN rBootDomain;
DSP_HBRIDGE_CONTROL rHBridgeControl;
spin_lock_irqsave(&dsp_lock, flags);
/* Mask DSP to PC interrupt */
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
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;
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));
return 0;
}
int dsp3780I_Run(struct dsp_3780i_config_settings *pSettings)
{
unsigned long flags;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
DSP_BOOT_DOMAIN rBootDomain;
DSP_HBRIDGE_CONTROL rHBridgeControl;
/* 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;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
return 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;
/* 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_MsaDataDSISHigh);
spin_unlock_irqrestore(&dsp_lock, flags);
if(put_user(val, pusBuffer++))
return -EFAULT;
PaceMsaAccess(usDspBaseIO);
}
return 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;
/* 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;
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/* 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) {
unsigned short val;
if(get_user(val, pusBuffer++))
return -EFAULT;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaDataDSISHigh, val);
spin_unlock_irqrestore(&dsp_lock, flags);
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/*
* 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;
spin_lock_irqsave(&dsp_lock, flags);
val_lo = InWordDsp(DSP_MsaDataISLow);
val_hi = InWordDsp(DSP_MsaDataDSISHigh);
spin_unlock_irqrestore(&dsp_lock, flags);
if(put_user(val_lo, pusBuffer++))
return -EFAULT;
if(put_user(val_hi, pusBuffer++))
return -EFAULT;
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/*
* 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);
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource)
{
unsigned long flags;
DSP_HBRIDGE_CONTROL rHBridgeControl;
/*
* 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);
OutWordDsp(DSP_Interrupt, (unsigned short) ~(*pusIPCSource));
rHBridgeControl.EnableDspInt = true;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
return 0;
}

View file

@ -1,358 +0,0 @@
/*
*
* 3780i.h -- declarations for 3780i.c
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_3780I_H
#define _LINUX_3780I_H
#include <asm/io.h>
/* DSP I/O port offsets and definitions */
#define DSP_IsaSlaveControl 0x0000 /* ISA slave control register */
#define DSP_IsaSlaveStatus 0x0001 /* ISA slave status register */
#define DSP_ConfigAddress 0x0002 /* General config address register */
#define DSP_ConfigData 0x0003 /* General config data register */
#define DSP_HBridgeControl 0x0002 /* HBridge control register */
#define DSP_MsaAddrLow 0x0004 /* MSP System Address, low word */
#define DSP_MsaAddrHigh 0x0006 /* MSP System Address, high word */
#define DSP_MsaDataDSISHigh 0x0008 /* MSA data register: d-store word or high byte of i-store */
#define DSP_MsaDataISLow 0x000A /* MSA data register: low word of i-store */
#define DSP_ReadAndClear 0x000C /* MSA read and clear data register */
#define DSP_Interrupt 0x000E /* Interrupt register (IPC source) */
typedef struct {
unsigned char ClockControl:1; /* RW: Clock control: 0=normal, 1=stop 3780i clocks */
unsigned char SoftReset:1; /* RW: Soft reset 0=normal, 1=soft reset active */
unsigned char ConfigMode:1; /* RW: Configuration mode, 0=normal, 1=config mode */
unsigned short Reserved:13; /* 0: Reserved */
} DSP_ISA_SLAVE_CONTROL;
typedef struct {
unsigned short EnableDspInt:1; /* RW: Enable DSP to X86 ISA interrupt 0=mask it, 1=enable it */
unsigned short MemAutoInc:1; /* RW: Memory address auto increment, 0=disable, 1=enable */
unsigned short IoAutoInc:1; /* RW: I/O address auto increment, 0=disable, 1=enable */
unsigned short DiagnosticMode:1; /* RW: Disgnostic mode 0=nromal, 1=diagnostic mode */
unsigned short IsaPacingTimer:12; /* R: ISA access pacing timer: count of core cycles stolen */
} DSP_HBRIDGE_CONTROL;
/* DSP register indexes used with the configuration register address (index) register */
#define DSP_UartCfg1Index 0x0003 /* UART config register 1 */
#define DSP_UartCfg2Index 0x0004 /* UART config register 2 */
#define DSP_HBridgeCfg1Index 0x0007 /* HBridge config register 1 */
#define DSP_HBridgeCfg2Index 0x0008 /* HBridge config register 2 */
#define DSP_BusMasterCfg1Index 0x0009 /* ISA bus master config register 1 */
#define DSP_BusMasterCfg2Index 0x000A /* ISA bus master config register 2 */
#define DSP_IsaProtCfgIndex 0x000F /* ISA protocol control register */
#define DSP_PowerMgCfgIndex 0x0010 /* Low poser suspend/resume enable */
#define DSP_HBusTimerCfgIndex 0x0011 /* HBUS timer load value */
typedef struct {
unsigned char IrqActiveLow:1; /* RW: IRQ active high or low: 0=high, 1=low */
unsigned char IrqPulse:1; /* RW: IRQ pulse or level: 0=level, 1=pulse */
unsigned char Irq:3; /* RW: IRQ selection */
unsigned char BaseIO:2; /* RW: Base I/O selection */
unsigned char Reserved:1; /* 0: Reserved */
} DSP_UART_CFG_1;
typedef struct {
unsigned char Enable:1; /* RW: Enable I/O and IRQ: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_UART_CFG_2;
typedef struct {
unsigned char IrqActiveLow:1; /* RW: IRQ active high=0 or low=1 */
unsigned char IrqPulse:1; /* RW: IRQ pulse=1 or level=0 */
unsigned char Irq:3; /* RW: IRQ selection */
unsigned char AccessMode:1; /* RW: 16-bit register access method 0=byte, 1=word */
unsigned char Reserved:2; /* 0: Reserved */
} DSP_HBRIDGE_CFG_1;
typedef struct {
unsigned char Enable:1; /* RW: enable I/O and IRQ: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_HBRIDGE_CFG_2;
typedef struct {
unsigned char Dma:3; /* RW: DMA channel selection */
unsigned char NumTransfers:2; /* RW: Maximum # of transfers once being granted the ISA bus */
unsigned char ReRequest:2; /* RW: Minimum delay between releasing the ISA bus and requesting it again */
unsigned char MEMCS16:1; /* RW: ISA signal MEMCS16: 0=disabled, 1=enabled */
} DSP_BUSMASTER_CFG_1;
typedef struct {
unsigned char IsaMemCmdWidth:2; /* RW: ISA memory command width */
unsigned char Reserved:6; /* 0: Reserved */
} DSP_BUSMASTER_CFG_2;
typedef struct {
unsigned char GateIOCHRDY:1; /* RW: Enable IOCHRDY gating: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_ISA_PROT_CFG;
typedef struct {
unsigned char Enable:1; /* RW: Enable low power suspend/resume 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_POWER_MGMT_CFG;
typedef struct {
unsigned char LoadValue:8; /* RW: HBUS timer load value */
} DSP_HBUS_TIMER_CFG;
/* DSP registers that exist in MSA I/O space */
#define DSP_ChipID 0x80000000
#define DSP_MspBootDomain 0x80000580
#define DSP_LBusTimeoutDisable 0x80000580
#define DSP_ClockControl_1 0x8000058A
#define DSP_ClockControl_2 0x8000058C
#define DSP_ChipReset 0x80000588
#define DSP_GpioModeControl_15_8 0x80000082
#define DSP_GpioDriverEnable_15_8 0x80000076
#define DSP_GpioOutputData_15_8 0x80000072
typedef struct {
unsigned short NMI:1; /* RW: non maskable interrupt */
unsigned short Halt:1; /* RW: Halt MSP clock */
unsigned short ResetCore:1; /* RW: Reset MSP core interface */
unsigned short Reserved:13; /* 0: Reserved */
} DSP_BOOT_DOMAIN;
typedef struct {
unsigned short DisableTimeout:1; /* RW: Disable LBus timeout */
unsigned short Reserved:15; /* 0: Reserved */
} DSP_LBUS_TIMEOUT_DISABLE;
typedef struct {
unsigned short Memory:1; /* RW: Reset memory interface */
unsigned short SerialPort1:1; /* RW: Reset serial port 1 interface */
unsigned short SerialPort2:1; /* RW: Reset serial port 2 interface */
unsigned short SerialPort3:1; /* RW: Reset serial port 3 interface */
unsigned short Gpio:1; /* RW: Reset GPIO interface */
unsigned short Dma:1; /* RW: Reset DMA interface */
unsigned short SoundBlaster:1; /* RW: Reset soundblaster interface */
unsigned short Uart:1; /* RW: Reset UART interface */
unsigned short Midi:1; /* RW: Reset MIDI interface */
unsigned short IsaMaster:1; /* RW: Reset ISA master interface */
unsigned short Reserved:6; /* 0: Reserved */
} DSP_CHIP_RESET;
typedef struct {
unsigned short N_Divisor:6; /* RW: (N) PLL output clock divisor */
unsigned short Reserved1:2; /* 0: reserved */
unsigned short M_Multiplier:6; /* RW: (M) PLL feedback clock multiplier */
unsigned short Reserved2:2; /* 0: reserved */
} DSP_CLOCK_CONTROL_1;
typedef struct {
unsigned short PllBypass:1; /* RW: PLL Bypass */
unsigned short Reserved:15; /* 0: Reserved */
} DSP_CLOCK_CONTROL_2;
typedef struct {
unsigned short Latch8:1;
unsigned short Latch9:1;
unsigned short Latch10:1;
unsigned short Latch11:1;
unsigned short Latch12:1;
unsigned short Latch13:1;
unsigned short Latch14:1;
unsigned short Latch15:1;
unsigned short Mask8:1;
unsigned short Mask9:1;
unsigned short Mask10:1;
unsigned short Mask11:1;
unsigned short Mask12:1;
unsigned short Mask13:1;
unsigned short Mask14:1;
unsigned short Mask15:1;
} DSP_GPIO_OUTPUT_DATA_15_8;
typedef struct {
unsigned short Enable8:1;
unsigned short Enable9:1;
unsigned short Enable10:1;
unsigned short Enable11:1;
unsigned short Enable12:1;
unsigned short Enable13:1;
unsigned short Enable14:1;
unsigned short Enable15:1;
unsigned short Mask8:1;
unsigned short Mask9:1;
unsigned short Mask10:1;
unsigned short Mask11:1;
unsigned short Mask12:1;
unsigned short Mask13:1;
unsigned short Mask14:1;
unsigned short Mask15:1;
} DSP_GPIO_DRIVER_ENABLE_15_8;
typedef struct {
unsigned short GpioMode8:2;
unsigned short GpioMode9:2;
unsigned short GpioMode10:2;
unsigned short GpioMode11:2;
unsigned short GpioMode12:2;
unsigned short GpioMode13:2;
unsigned short GpioMode14:2;
unsigned short GpioMode15:2;
} DSP_GPIO_MODE_15_8;
/* Component masks that are defined in dspmgr.h */
#define MW_ADC_MASK 0x0001
#define MW_AIC2_MASK 0x0006
#define MW_MIDI_MASK 0x0008
#define MW_CDDAC_MASK 0x8001
#define MW_AIC1_MASK 0xE006
#define MW_UART_MASK 0xE00A
#define MW_ACI_MASK 0xE00B
/*
* Definition of 3780i configuration structure. Unless otherwise stated,
* these values are provided as input to the 3780i support layer. At present,
* the only values maintained by the 3780i support layer are the saved UART
* registers.
*/
struct dsp_3780i_config_settings {
/* Location of base configuration register */
unsigned short usBaseConfigIO;
/* Enables for various DSP components */
int bDSPEnabled;
int bModemEnabled;
int bInterruptClaimed;
/* IRQ, DMA, and Base I/O addresses for various DSP components */
unsigned short usDspIrq;
unsigned short usDspDma;
unsigned short usDspBaseIO;
unsigned short usUartIrq;
unsigned short usUartBaseIO;
/* IRQ modes for various DSP components */
int bDspIrqActiveLow;
int bUartIrqActiveLow;
int bDspIrqPulse;
int bUartIrqPulse;
/* Card abilities */
unsigned uIps;
unsigned uDStoreSize;
unsigned uIStoreSize;
unsigned uDmaBandwidth;
/* Adapter specific 3780i settings */
unsigned short usNumTransfers;
unsigned short usReRequest;
int bEnableMEMCS16;
unsigned short usIsaMemCmdWidth;
int bGateIOCHRDY;
int bEnablePwrMgmt;
unsigned short usHBusTimerLoadValue;
int bDisableLBusTimeout;
unsigned short usN_Divisor;
unsigned short usM_Multiplier;
int bPllBypass;
unsigned short usChipletEnable; /* Used with the chip reset register to enable specific chiplets */
/* Saved UART registers. These are maintained by the 3780i support layer. */
int bUartSaved; /* True after a successful save of the UART registers */
unsigned char ucIER; /* Interrupt enable register */
unsigned char ucFCR; /* FIFO control register */
unsigned char ucLCR; /* Line control register */
unsigned char ucMCR; /* Modem control register */
unsigned char ucSCR; /* Scratch register */
unsigned char ucDLL; /* Divisor latch, low byte */
unsigned char ucDLM; /* Divisor latch, high byte */
};
/* 3780i support functions */
int dsp3780I_EnableDSP(struct dsp_3780i_config_settings *pSettings,
unsigned short *pIrqMap,
unsigned short *pDmaMap);
int dsp3780I_DisableDSP(struct dsp_3780i_config_settings *pSettings);
int dsp3780I_Reset(struct dsp_3780i_config_settings *pSettings);
int dsp3780I_Run(struct dsp_3780i_config_settings *pSettings);
int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
void __user *pvBuffer, unsigned uCount,
unsigned long ulDSPAddr);
int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr);
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue);
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource);
/* I/O port access macros */
#define MKWORD(var) (*((unsigned short *)(&var)))
#define MKBYTE(var) (*((unsigned char *)(&var)))
#define WriteMsaCfg(addr,value) dsp3780I_WriteMsaCfg(usDspBaseIO,addr,value)
#define ReadMsaCfg(addr) dsp3780I_ReadMsaCfg(usDspBaseIO,addr)
#define WriteGenCfg(index,value) dsp3780I_WriteGenCfg(usDspBaseIO,index,value)
#define ReadGenCfg(index) dsp3780I_ReadGenCfg(usDspBaseIO,index)
#define InWordDsp(index) inw(usDspBaseIO+index)
#define InByteDsp(index) inb(usDspBaseIO+index)
#define OutWordDsp(index,value) outw(value,usDspBaseIO+index)
#define OutByteDsp(index,value) outb(value,usDspBaseIO+index)
#endif

View file

@ -1,10 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for ACP Modem (Mwave).
#
# See the README file in this directory for more info. <paulsch@us.ibm.com>
#
obj-$(CONFIG_MWAVE) += mwave.o
mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o

View file

@ -1,37 +0,0 @@
Module options
--------------
The mwave module takes the following options. Note that these options
are not saved by the BIOS and so do not persist after unload and reload.
mwave_3780i_irq=5/7/10/11/15
If the dsp irq has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
irq used by the dsp to be configured.
mwave_3780i_io=0x130/0x350/0x0070/0xDB0
If the dsp io range has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
io range used by the dsp to be configured.
mwave_uart_irq=3/4
If the mwave's uart irq has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
irq used by the mwave uart to be configured.
mwave_uart_io=0x3f8/0x2f8/0x3E8/0x2E8
If the uart io range has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
io range used by the mwave uart to be configured.
Example to enable the 3780i DSP using ttyS1 resources:
insmod mwave mwave_3780i_irq=10 mwave_3780i_io=0x0130 mwave_uart_irq=3 mwave_uart_io=0x2f8
Accessing the driver
--------------------
You must also create a node for the driver:
mkdir -p /dev/modems
mknod --mode=660 /dev/modems/mwave c 10 219

View file

@ -1,432 +0,0 @@
/*
*
* mwavedd.c -- mwave device driver
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "mwavedd: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/serial_8250.h>
#include <linux/nospec.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
#include "tp3780i.h"
MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
MODULE_LICENSE("GPL");
/*
* These parameters support the setting of MWave resources. Note that no
* checks are made against other devices (ie. superio) for conflicts.
* We'll depend on users using the tpctl utility to do that for now
*/
static DEFINE_MUTEX(mwave_mutex);
int mwave_3780i_irq = 0;
int mwave_3780i_io = 0;
int mwave_uart_irq = 0;
int mwave_uart_io = 0;
module_param_hw(mwave_3780i_irq, int, irq, 0);
module_param_hw(mwave_3780i_io, int, ioport, 0);
module_param_hw(mwave_uart_irq, int, irq, 0);
module_param_hw(mwave_uart_io, int, ioport, 0);
struct mwave_device_data mwave_s_mdd;
static long mwave_ioctl(struct file *file, unsigned int iocmd,
unsigned long ioarg)
{
unsigned int retval = 0;
struct mwave_device_data *pDrvData = &mwave_s_mdd;
void __user *arg = (void __user *)ioarg;
switch (iocmd) {
case IOCTL_MW_RESET:
mutex_lock(&mwave_mutex);
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
break;
case IOCTL_MW_RUN:
mutex_lock(&mwave_mutex);
retval = tp3780I_StartDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
break;
case IOCTL_MW_DSP_ABILITIES: {
struct mw_abilities rAbilities;
mutex_lock(&mwave_mutex);
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
mutex_unlock(&mwave_mutex);
if (retval == 0) {
if (copy_to_user(arg, &rAbilities, sizeof(rAbilities)))
return -EFAULT;
}
}
break;
case IOCTL_MW_READ_DATA:
case IOCTL_MW_READCLEAR_DATA: {
struct mw_readwrite rReadData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rReadData, arg,
sizeof(struct mw_readwrite)) )
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
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: {
struct mw_readwrite rReadData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rReadData, arg, sizeof(rReadData)))
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
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: {
struct mw_readwrite rWriteData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
return -EFAULT;
pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
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: {
struct mw_readwrite rWriteData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
return -EFAULT;
pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
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)) {
pr_err("%s: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %x\n",
__func__, ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
mutex_lock(&mwave_mutex);
pDrvData->IPCs[ipcnum].bIsHere = false;
pDrvData->IPCs[ipcnum].bIsEnabled = true;
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_GET_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
pr_err("%s: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %x\n", __func__,
ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
DECLARE_WAITQUEUE(wait, current);
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 */
} 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;
}
}
pDrvData->IPCs[ipcnum].bIsHere = false;
remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
set_current_state(TASK_RUNNING);
}
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_UNREGISTER_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
pr_err("%s: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n",
__func__, 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 */
return retval;
}
static int register_serial_portandirq(unsigned int port, int irq)
{
struct uart_8250_port uart;
switch ( port ) {
case 0x3f8:
case 0x2f8:
case 0x3e8:
case 0x2e8:
/* OK */
break;
default:
pr_err("%s: Error: Illegal port %x\n", __func__, port);
return -1;
} /* switch */
/* port is okay */
switch ( irq ) {
case 3:
case 4:
case 5:
case 7:
/* OK */
break;
default:
pr_err("%s: Error: Illegal irq %x\n", __func__, irq);
return -1;
} /* switch */
/* irq is okay */
memset(&uart, 0, sizeof(uart));
uart.port.uartclk = 1843200;
uart.port.iobase = port;
uart.port.irq = irq;
uart.port.iotype = UPIO_PORT;
uart.port.flags = UPF_SHARE_IRQ;
return serial8250_register_8250_port(&uart);
}
static const struct file_operations mwave_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = mwave_ioctl,
.llseek = default_llseek,
};
static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
/*
* mwave_init is called on module load
*
* mwave_exit is called on module unload
* mwave_exit is also used to clean up after an aborted mwave_init
*/
static void mwave_exit(void)
{
struct mwave_device_data *pDrvData = &mwave_s_mdd;
if ( pDrvData->sLine >= 0 ) {
serial8250_unregister_port(pDrvData->sLine);
}
if (pDrvData->bMwaveDevRegistered) {
misc_deregister(&mwave_misc_dev);
}
if (pDrvData->bDSPEnabled) {
tp3780I_DisableDSP(&pDrvData->rBDData);
}
if (pDrvData->bResourcesClaimed) {
tp3780I_ReleaseResources(&pDrvData->rBDData);
}
if (pDrvData->bBDInitialized) {
tp3780I_Cleanup(&pDrvData->rBDData);
}
}
module_exit(mwave_exit);
static int __init mwave_init(void)
{
int i;
int retval = 0;
struct mwave_device_data *pDrvData = &mwave_s_mdd;
memset(&mwave_s_mdd, 0, sizeof(mwave_s_mdd));
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);
if (retval) {
pr_err("%s: Error: Failed to initialize board data\n", __func__);
goto cleanup_error;
}
pDrvData->bBDInitialized = true;
retval = tp3780I_CalcResources(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to calculate resources\n", __func__);
goto cleanup_error;
}
retval = tp3780I_ClaimResources(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to claim resources\n", __func__);
goto cleanup_error;
}
pDrvData->bResourcesClaimed = true;
retval = tp3780I_EnableDSP(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to enable DSP\n", __func__);
goto cleanup_error;
}
pDrvData->bDSPEnabled = true;
if (misc_register(&mwave_misc_dev) < 0) {
pr_err("%s: Error: Failed to register misc device\n", __func__);
goto cleanup_error;
}
pDrvData->bMwaveDevRegistered = true;
pDrvData->sLine = register_serial_portandirq(
pDrvData->rBDData.rDspSettings.usUartBaseIO,
pDrvData->rBDData.rDspSettings.usUartIrq
);
if (pDrvData->sLine < 0) {
pr_err("%s: Error: Failed to register serial driver\n", __func__);
goto cleanup_error;
}
/* uart is registered */
/* SUCCESS! */
return 0;
cleanup_error:
pr_err("%s: Error: Failed to initialize\n", __func__);
mwave_exit(); /* clean up */
return -EIO;
}
module_init(mwave_init);

View file

@ -1,90 +0,0 @@
/*
*
* mwavedd.h -- declarations for mwave device driver
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_MWAVEDD_H
#define _LINUX_MWAVEDD_H
#include "3780i.h"
#include "tp3780i.h"
#include "smapi.h"
#include "mwavepub.h"
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
extern int mwave_3780i_irq;
extern int mwave_3780i_io;
extern int mwave_uart_irq;
extern int mwave_uart_io;
struct mwave_ipc {
unsigned short usIntCount; /* 0=none, 1=first, 2=greater than 1st */
bool bIsEnabled;
bool bIsHere;
/* entry spin lock */
wait_queue_head_t ipc_wait_queue;
};
struct mwave_device_data {
struct thinkpad_bd_data rBDData; /* board driver's data area */
unsigned long ulIPCSource_ISR; /* IPC source bits for recently processed intr, set during ISR processing */
unsigned long ulIPCSource_DPC; /* IPC source bits for recently processed intr, set during DPC processing */
bool bBDInitialized;
bool bResourcesClaimed;
bool bDSPEnabled;
bool bDSPReset;
struct mwave_ipc IPCs[16];
bool bMwaveDevRegistered;
short sLine;
int nr_registered_attrs;
int device_registered;
};
extern struct mwave_device_data mwave_s_mdd;
#endif

View file

@ -1,89 +0,0 @@
/*
*
* mwavepub.h -- PUBLIC declarations for the mwave driver
* and applications using it
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_MWAVEPUB_H
#define _LINUX_MWAVEPUB_H
#include <linux/miscdevice.h>
struct mw_abilities {
unsigned long instr_per_sec;
unsigned long data_size;
unsigned long inst_size;
unsigned long bus_dma_bw;
unsigned short uart_enable;
short component_count;
unsigned long component_list[7];
char mwave_os_name[16];
char bios_task_name[16];
};
struct mw_readwrite {
unsigned short usDspAddress; /* The dsp address */
unsigned long ulDataLength; /* The size in bytes of the data or user buffer */
void __user *pBuf; /* Input:variable sized buffer */
};
#define IOCTL_MW_RESET _IO(MWAVE_MINOR,1)
#define IOCTL_MW_RUN _IO(MWAVE_MINOR,2)
#define IOCTL_MW_DSP_ABILITIES _IOR(MWAVE_MINOR,3,struct mw_abilities)
#define IOCTL_MW_READ_DATA _IOR(MWAVE_MINOR,4,struct mw_readwrite)
#define IOCTL_MW_READCLEAR_DATA _IOR(MWAVE_MINOR,5,struct mw_readwrite)
#define IOCTL_MW_READ_INST _IOR(MWAVE_MINOR,6,struct mw_readwrite)
#define IOCTL_MW_WRITE_DATA _IOW(MWAVE_MINOR,7,struct mw_readwrite)
#define IOCTL_MW_WRITE_INST _IOW(MWAVE_MINOR,8,struct mw_readwrite)
#define IOCTL_MW_REGISTER_IPC _IOW(MWAVE_MINOR,9,int)
#define IOCTL_MW_UNREGISTER_IPC _IOW(MWAVE_MINOR,10,int)
#define IOCTL_MW_GET_IPC _IOW(MWAVE_MINOR,11,int)
#define IOCTL_MW_TRACE _IOR(MWAVE_MINOR,12,struct mw_readwrite)
#endif

View file

@ -1,404 +0,0 @@
/*
*
* smapi.c -- SMAPI interface routines
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "smapi: " fmt
#include <linux/kernel.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
#include "smapi.h"
#include "mwavedd.h"
static unsigned short g_usSmapiPort = 0;
static int smapi_request(unsigned short inBX, unsigned short inCX,
unsigned short inDI, unsigned short inSI,
unsigned short *outAX, unsigned short *outBX,
unsigned short *outCX, unsigned short *outDX,
unsigned short *outDI, unsigned short *outSI)
{
unsigned short myoutAX = 2, *pmyoutAX = &myoutAX;
unsigned short myoutBX = 3, *pmyoutBX = &myoutBX;
unsigned short myoutCX = 4, *pmyoutCX = &myoutCX;
unsigned short myoutDX = 5, *pmyoutDX = &myoutDX;
unsigned short myoutDI = 6, *pmyoutDI = &myoutDI;
unsigned short myoutSI = 7, *pmyoutSI = &myoutSI;
unsigned short usSmapiOK = -EIO, *pusSmapiOK = &usSmapiOK;
unsigned int inBXCX = (inBX << 16) | inCX;
unsigned int inDISI = (inDI << 16) | inSI;
__asm__ __volatile__("movw $0x5380,%%ax\n\t"
"movl %7,%%ebx\n\t"
"shrl $16, %%ebx\n\t"
"movw %7,%%cx\n\t"
"movl %8,%%edi\n\t"
"shrl $16,%%edi\n\t"
"movw %8,%%si\n\t"
"movw %9,%%dx\n\t"
"out %%al,%%dx\n\t"
"out %%al,$0x4F\n\t"
"cmpb $0x53,%%ah\n\t"
"je 2f\n\t"
"1:\n\t"
"orb %%ah,%%ah\n\t"
"jnz 2f\n\t"
"movw %%ax,%0\n\t"
"movw %%bx,%1\n\t"
"movw %%cx,%2\n\t"
"movw %%dx,%3\n\t"
"movw %%di,%4\n\t"
"movw %%si,%5\n\t"
"movw $1,%6\n\t"
"2:\n\t":"=m"(*(unsigned short *) pmyoutAX),
"=m"(*(unsigned short *) pmyoutBX),
"=m"(*(unsigned short *) pmyoutCX),
"=m"(*(unsigned short *) pmyoutDX),
"=m"(*(unsigned short *) pmyoutDI),
"=m"(*(unsigned short *) pmyoutSI),
"=m"(*(unsigned short *) pusSmapiOK)
:"m"(inBXCX), "m"(inDISI), "m"(g_usSmapiPort)
:"%eax", "%ebx", "%ecx", "%edx", "%edi",
"%esi");
*outAX = myoutAX;
*outBX = myoutBX;
*outCX = myoutCX;
*outDX = myoutDX;
*outDI = myoutDI;
*outSI = myoutSI;
return usSmapiOK == 1 ? 0 : -EIO;
}
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings)
{
int bRC;
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
static const unsigned short ausDspBases[] = {
0x0030, 0x4E30, 0x8E30, 0xCE30,
0x0130, 0x0350, 0x0070, 0x0DB0 };
static const unsigned short ausUartBases[] = {
0x03F8, 0x02F8, 0x03E8, 0x02E8 };
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) {
pr_err("%s: Error: Could not get DSP Settings. Aborting.\n", __func__);
return bRC;
}
pSettings->bDSPPresent = ((usBX & 0x0100) != 0);
pSettings->bDSPEnabled = ((usCX & 0x0001) != 0);
pSettings->usDspIRQ = usSI & 0x00FF;
pSettings->usDspDMA = (usSI & 0xFF00) >> 8;
if ((usDI & 0x00FF) < ARRAY_SIZE(ausDspBases)) {
pSettings->usDspBaseIO = ausDspBases[usDI & 0x00FF];
} else {
pSettings->usDspBaseIO = 0;
}
/* check for illegal values */
if ( pSettings->usDspBaseIO == 0 )
pr_err("%s: Worry: DSP base I/O address is 0\n", __func__);
if ( pSettings->usDspIRQ == 0 )
pr_err("%s: Worry: DSP IRQ line is 0\n", __func__);
bRC = smapi_request(0x1804, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) {
pr_err("%s: Error: Could not get DSP modem settings. Aborting.\n", __func__);
return bRC;
}
pSettings->bModemEnabled = ((usCX & 0x0001) != 0);
pSettings->usUartIRQ = usSI & 0x000F;
if (((usSI & 0xFF00) >> 8) < ARRAY_SIZE(ausUartBases)) {
pSettings->usUartBaseIO = ausUartBases[(usSI & 0xFF00) >> 8];
} else {
pSettings->usUartBaseIO = 0;
}
/* check for illegal values */
if ( pSettings->usUartBaseIO == 0 )
pr_err("%s: Worry: UART base I/O address is 0\n", __func__);
if ( pSettings->usUartIRQ == 0 )
pr_err("%s: Worry: UART IRQ line is 0\n", __func__);
return bRC;
}
int smapi_set_DSP_cfg(void)
{
int bRC = -EIO;
int i;
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
static const unsigned short ausDspBases[] = {
0x0030, 0x4E30, 0x8E30, 0xCE30,
0x0130, 0x0350, 0x0070, 0x0DB0 };
static const unsigned short ausUartBases[] = {
0x03F8, 0x02F8, 0x03E8, 0x02E8 };
static const unsigned short ausDspIrqs[] = {
5, 7, 10, 11, 15 };
static const unsigned short ausUartIrqs[] = {
3, 4 };
unsigned short dspio_index = 0, uartio_index = 0;
if (mwave_3780i_io) {
for (i = 0; i < ARRAY_SIZE(ausDspBases); i++) {
if (mwave_3780i_io == ausDspBases[i])
break;
}
if (i == ARRAY_SIZE(ausDspBases)) {
pr_err("%s: Error: Invalid mwave_3780i_io address %x. Aborting.\n",
__func__, mwave_3780i_io);
return bRC;
}
dspio_index = i;
}
if (mwave_3780i_irq) {
for (i = 0; i < ARRAY_SIZE(ausDspIrqs); i++) {
if (mwave_3780i_irq == ausDspIrqs[i])
break;
}
if (i == ARRAY_SIZE(ausDspIrqs)) {
pr_err("%s: Error: Invalid mwave_3780i_irq %x. Aborting.\n", __func__,
mwave_3780i_irq);
return bRC;
}
}
if (mwave_uart_io) {
for (i = 0; i < ARRAY_SIZE(ausUartBases); i++) {
if (mwave_uart_io == ausUartBases[i])
break;
}
if (i == ARRAY_SIZE(ausUartBases)) {
pr_err("%s: Error: Invalid mwave_uart_io address %x. Aborting.\n", __func__,
mwave_uart_io);
return bRC;
}
uartio_index = i;
}
if (mwave_uart_irq) {
for (i = 0; i < ARRAY_SIZE(ausUartIrqs); i++) {
if (mwave_uart_irq == ausUartIrqs[i])
break;
}
if (i == ARRAY_SIZE(ausUartIrqs)) {
pr_err("%s: Error: Invalid mwave_uart_irq %x. Aborting.\n", __func__,
mwave_uart_irq);
return bRC;
}
}
if (mwave_uart_irq || mwave_uart_io) {
/* Check serial port A */
bRC = smapi_request(0x1402, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* bRC == 0 */
if (usBX & 0x0100) { /* serial port A is present */
if (usCX & 1) { /* serial port is enabled */
if ((usSI & 0xFF) == mwave_uart_irq) {
pr_err("%s: Serial port A irq %x conflicts with mwave_uart_irq %x\n",
__func__, usSI & 0xFF, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI >> 8) == uartio_index) {
pr_err("%s: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n",
__func__, ausUartBases[usSI >> 8],
ausUartBases[uartio_index]);
goto exit_conflict;
}
}
}
}
/* Check serial port B */
bRC = smapi_request(0x1404, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* bRC == 0 */
if (usBX & 0x0100) { /* serial port B is present */
if (usCX & 1) { /* serial port is enabled */
if ((usSI & 0xFF) == mwave_uart_irq) {
pr_err("%s: Serial port B irq %x conflicts with mwave_uart_irq %x\n",
__func__, usSI & 0xFF, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI >> 8) == uartio_index) {
pr_err("%s: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n",
__func__, ausUartBases[usSI >> 8],
ausUartBases[uartio_index]);
goto exit_conflict;
}
}
}
}
/* Check IR port */
bRC = smapi_request(0x1700, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1704, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* bRC == 0 */
if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
if ((usCX & 0xff) == mwave_uart_irq) {
pr_err("%s: IR port irq %x conflicts with mwave_uart_irq %x\n",
__func__, usCX & 0xff, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI & 0xff) == uartio_index) {
pr_err("%s: IR port base I/O address %x conflicts with mwave uart I/O %x\n",
__func__, ausUartBases[usSI & 0xff],
ausUartBases[uartio_index]);
goto exit_conflict;
}
}
}
}
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
if (mwave_3780i_io) {
usDI = dspio_index;
}
if (mwave_3780i_irq) {
usSI = (usSI & 0xff00) | mwave_3780i_irq;
}
bRC = smapi_request(0x1803, 0x0101, usDI, usSI,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1804, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
if (mwave_uart_io) {
usSI = (usSI & 0x00ff) | (uartio_index << 8);
}
if (mwave_uart_irq) {
usSI = (usSI & 0xff00) | mwave_uart_irq;
}
bRC = smapi_request(0x1805, 0x0101, 0, usSI,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1804, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* normal exit: */
return 0;
exit_conflict:
/* Message has already been printed */
return -EIO;
exit_smapi_request_error:
pr_err("%s: exit on smapi_request error bRC %x\n", __func__, bRC);
return bRC;
}
int smapi_set_DSP_power_state(bool bOn)
{
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
unsigned short usPowerFunction;
usPowerFunction = (bOn) ? 1 : 0;
return smapi_request(0x4901, 0x0000, 0, usPowerFunction, &usAX, &usBX, &usCX, &usDX, &usDI,
&usSI);
}
int smapi_init(void)
{
int retval = -EIO;
unsigned short usSmapiID = 0;
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
usSmapiID = CMOS_READ(0x7C);
usSmapiID |= (CMOS_READ(0x7D) << 8);
spin_unlock_irqrestore(&rtc_lock, flags);
if (usSmapiID == 0x5349) {
spin_lock_irqsave(&rtc_lock, flags);
g_usSmapiPort = CMOS_READ(0x7E);
g_usSmapiPort |= (CMOS_READ(0x7F) << 8);
spin_unlock_irqrestore(&rtc_lock, flags);
if (g_usSmapiPort == 0) {
pr_err("%s: ERROR unable to read from SMAPI port\n", __func__);
} else {
retval = 0;
//SmapiQuerySystemID();
}
} else {
pr_err("%s: ERROR invalid usSmapiID\n", __func__);
retval = -ENXIO;
}
return retval;
}

View file

@ -1,76 +0,0 @@
/*
*
* smapi.h -- declarations for SMAPI interface routines
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_SMAPI_H
#define _LINUX_SMAPI_H
struct smapi_dsp_settings {
int bDSPPresent;
int bDSPEnabled;
int bModemEnabled;
int bMIDIEnabled;
int bSblstEnabled;
unsigned short usDspIRQ;
unsigned short usDspDMA;
unsigned short usDspBaseIO;
unsigned short usUartIRQ;
unsigned short usUartBaseIO;
unsigned short usMidiIRQ;
unsigned short usMidiBaseIO;
unsigned short usSndblstIRQ;
unsigned short usSndblstDMA;
unsigned short usSndblstBaseIO;
};
int smapi_init(void);
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings);
int smapi_set_DSP_cfg(void);
int smapi_set_DSP_power_state(bool bOn);
#endif

View file

@ -1,477 +0,0 @@
/*
*
* tp3780i.c -- board driver for 3780i on ThinkPads
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "tp3780i: " fmt
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include "smapi.h"
#include "mwavedd.h"
#include "tp3780i.h"
#include "3780i.h"
#include "mwavepub.h"
static unsigned short s_ausThinkpadIrqToField[16] =
{ 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004,
0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 };
static unsigned short s_ausThinkpadDmaToField[8] =
{ 0x0001, 0x0002, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0003, 0x0004 };
static unsigned short s_numIrqs = 16, s_numDmas = 8;
static void EnableSRAM(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
DSP_GPIO_OUTPUT_DATA_15_8 rGpioOutputData;
DSP_GPIO_DRIVER_ENABLE_15_8 rGpioDriverEnable;
DSP_GPIO_MODE_15_8 rGpioMode;
MKWORD(rGpioMode) = ReadMsaCfg(DSP_GpioModeControl_15_8);
rGpioMode.GpioMode10 = 0;
WriteMsaCfg(DSP_GpioModeControl_15_8, MKWORD(rGpioMode));
MKWORD(rGpioDriverEnable) = 0;
rGpioDriverEnable.Enable10 = true;
rGpioDriverEnable.Mask10 = true;
WriteMsaCfg(DSP_GpioDriverEnable_15_8, MKWORD(rGpioDriverEnable));
MKWORD(rGpioOutputData) = 0;
rGpioOutputData.Latch10 = 0;
rGpioOutputData.Mask10 = true;
WriteMsaCfg(DSP_GpioOutputData_15_8, MKWORD(rGpioOutputData));
}
static irqreturn_t UartInterrupt(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
static irqreturn_t DspInterrupt(int irq, void *dev_id)
{
struct mwave_device_data *pDrvData = &mwave_s_mdd;
struct dsp_3780i_config_settings *pSettings = &pDrvData->rBDData.rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
unsigned short usIPCSource = 0, usIsolationMask, usPCNum;
if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
usIsolationMask = 1;
for (usPCNum = 1; usPCNum <= 16; usPCNum++) {
if (usIPCSource & usIsolationMask) {
usIPCSource &= ~usIsolationMask;
if (pDrvData->IPCs[usPCNum - 1].usIntCount == 0) {
pDrvData->IPCs[usPCNum - 1].usIntCount = 1;
}
if (pDrvData->IPCs[usPCNum - 1].bIsEnabled == true) {
wake_up_interruptible(&pDrvData->IPCs[usPCNum - 1].ipc_wait_queue);
}
}
if (usIPCSource == 0)
break;
/* try next IPC */
usIsolationMask = usIsolationMask << 1;
}
}
return IRQ_HANDLED;
}
int tp3780I_InitializeBoardData(struct thinkpad_bd_data *pBDData)
{
int retval = 0;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
pBDData->bDSPEnabled = false;
pSettings->bInterruptClaimed = false;
retval = smapi_init();
if (retval) {
pr_err("%s: Error: SMAPI is not available on this machine\n", __func__);
} else {
if (mwave_3780i_irq || mwave_3780i_io || mwave_uart_irq || mwave_uart_io) {
retval = smapi_set_DSP_cfg();
}
}
return retval;
}
void tp3780I_Cleanup(struct thinkpad_bd_data *pBDData)
{
}
int tp3780I_CalcResources(struct thinkpad_bd_data *pBDData)
{
struct smapi_dsp_settings rSmapiInfo;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (smapi_query_DSP_cfg(&rSmapiInfo)) {
pr_err("%s: Error: Could not query DSP config. Aborting.\n", __func__);
return -EIO;
}
/* Sanity check */
if (
( rSmapiInfo.usDspIRQ == 0 )
|| ( rSmapiInfo.usDspBaseIO == 0 )
|| ( rSmapiInfo.usUartIRQ == 0 )
|| ( rSmapiInfo.usUartBaseIO == 0 )
) {
pr_err("%s: Error: Illegal resource setting. Aborting.\n", __func__);
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;
}
return 0;
}
int tp3780I_ClaimResources(struct thinkpad_bd_data *pBDData)
{
int retval = 0;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
struct resource *pres;
pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
if ( pres == NULL ) retval = -EIO;
if (retval) {
pr_err("%s: Error: Could not claim I/O region starting at %x\n", __func__,
pSettings->usDspBaseIO);
return -EIO;
}
return retval;
}
int tp3780I_ReleaseResources(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
release_region(pSettings->usDspBaseIO & (~3), 16);
if (pSettings->bInterruptClaimed) {
free_irq(pSettings->usDspIrq, NULL);
pSettings->bInterruptClaimed = false;
}
return 0;
}
int tp3780I_EnableDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
bool bDSPPoweredUp = false, bInterruptAllocated = false;
if (pBDData->bDSPEnabled) {
pr_err("%s: Error: DSP already enabled!\n", __func__);
goto exit_cleanup;
}
if (!pSettings->bDSPEnabled) {
pr_err("%s: Error: pSettings->bDSPEnabled not set\n", __func__);
goto exit_cleanup;
}
if (
(pSettings->usDspIrq >= s_numIrqs)
|| (pSettings->usDspDma >= s_numDmas)
|| (s_ausThinkpadIrqToField[pSettings->usDspIrq] == 0xFFFF)
|| (s_ausThinkpadDmaToField[pSettings->usDspDma] == 0xFFFF)
) {
pr_err("%s: Error: invalid irq %x\n", __func__, pSettings->usDspIrq);
goto exit_cleanup;
}
if (
((pSettings->usDspBaseIO & 0xF00F) != 0)
|| (pSettings->usDspBaseIO & 0x0FF0) == 0
) {
pr_err("%s: Error: Invalid DSP base I/O address %x\n", __func__,
pSettings->usDspBaseIO);
goto exit_cleanup;
}
if (pSettings->bModemEnabled) {
if (
pSettings->usUartIrq >= s_numIrqs
|| s_ausThinkpadIrqToField[pSettings->usUartIrq] == 0xFFFF
) {
pr_err("%s: Error: Invalid UART IRQ %x\n", __func__, pSettings->usUartIrq);
goto exit_cleanup;
}
switch (pSettings->usUartBaseIO) {
case 0x03F8:
case 0x02F8:
case 0x03E8:
case 0x02E8:
break;
default:
pr_err("%s: Error: Invalid UART base I/O address %x\n", __func__,
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)) {
pr_err("%s: Error: Could not get UART IRQ %x\n", __func__, pSettings->usUartIrq);
goto exit_cleanup;
} else { /* no conflict just release */
free_irq(pSettings->usUartIrq, NULL);
}
if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i", NULL)) {
pr_err("%s: Error: Could not get 3780i IRQ %x\n", __func__, pSettings->usDspIrq);
goto exit_cleanup;
} else {
bInterruptAllocated = true;
pSettings->bInterruptClaimed = true;
}
smapi_set_DSP_power_state(false);
if (smapi_set_DSP_power_state(true)) {
pr_err("%s: Error: smapi_set_DSP_power_state(true) failed\n", __func__);
goto exit_cleanup;
} else {
bDSPPoweredUp = true;
}
if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
pr_err("%s: Error: dsp7880I_EnableDSP() failed\n", __func__);
goto exit_cleanup;
}
EnableSRAM(pBDData);
pBDData->bDSPEnabled = true;
return 0;
exit_cleanup:
pr_err("%s: Cleaning up\n", __func__);
if (bDSPPoweredUp)
smapi_set_DSP_power_state(false);
if (bInterruptAllocated) {
free_irq(pSettings->usDspIrq, NULL);
pSettings->bInterruptClaimed = false;
}
return -EIO;
}
int tp3780I_DisableDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
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;
}
return 0;
}
int tp3780I_ResetDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (dsp3780I_Reset(pSettings) == 0) {
EnableSRAM(pBDData);
return 0;
}
return -EIO;
}
int tp3780I_StartDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (dsp3780I_Run(pSettings) == 0) {
// @BUG @TBD EnableSRAM(pBDData);
} else {
return -EIO;
}
return 0;
}
int tp3780I_QueryAbilities(struct thinkpad_bd_data *pBDData, struct mw_abilities *pAbilities)
{
memset(pAbilities, 0, sizeof(*pAbilities));
/* fill out standard constant fields */
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;
/* fill out dynamically determined fields */
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;
/* Fill out Mwave OS and BIOS task names */
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));
return 0;
}
int tp3780I_ReadWriteDspDStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
bool bRC = 0;
if (pBDData->bDSPEnabled) {
switch (uOpcode) {
case IOCTL_MW_READ_DATA:
bRC = dsp3780I_ReadDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
case IOCTL_MW_READCLEAR_DATA:
bRC = dsp3780I_ReadAndClearDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
case IOCTL_MW_WRITE_DATA:
bRC = dsp3780I_WriteDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
}
}
return bRC ? -EIO : 0;
}
int tp3780I_ReadWriteDspIStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
bool bRC = 0;
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;
}
}
return bRC ? -EIO : 0;
}

View file

@ -1,103 +0,0 @@
/*
*
* tp3780i.h -- declarations for tp3780i.c
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_TP3780I_H
#define _LINUX_TP3780I_H
#include <asm/io.h>
#include "mwavepub.h"
/* DSP abilities constants for 3780i based Thinkpads */
#define TP_ABILITIES_INTS_PER_SEC 39160800
#define TP_ABILITIES_DATA_SIZE 32768
#define TP_ABILITIES_INST_SIZE 32768
#define TP_ABILITIES_MWAVEOS_NAME "mwaveos0700.dsp"
#define TP_ABILITIES_BIOSTASK_NAME "mwbio701.dsp"
/* DSP configuration values for 3780i based Thinkpads */
#define TP_CFG_NumTransfers 3 /* 16 transfers */
#define TP_CFG_RerequestTimer 1 /* 2 usec */
#define TP_CFG_MEMCS16 0 /* Disabled, 16-bit memory assumed */
#define TP_CFG_IsaMemCmdWidth 3 /* 295 nsec (16-bit) */
#define TP_CFG_GateIOCHRDY 0 /* No IOCHRDY gating */
#define TP_CFG_EnablePwrMgmt 1 /* Enable low poser suspend/resume */
#define TP_CFG_HBusTimerValue 255 /* HBus timer load value */
#define TP_CFG_DisableLBusTimeout 0 /* Enable LBus timeout */
#define TP_CFG_N_Divisor 32 /* Clock = 39.1608 Mhz */
#define TP_CFG_M_Multiplier 37 /* " */
#define TP_CFG_PllBypass 0 /* don't bypass */
#define TP_CFG_ChipletEnable 0xFFFF /* Enable all chiplets */
struct thinkpad_bd_data {
int bDSPEnabled;
int bShareDspIrq;
int bShareUartIrq;
struct dsp_3780i_config_settings rDspSettings;
};
int tp3780I_InitializeBoardData(struct thinkpad_bd_data *pBDData);
int tp3780I_CalcResources(struct thinkpad_bd_data *pBDData);
int tp3780I_ClaimResources(struct thinkpad_bd_data *pBDData);
int tp3780I_ReleaseResources(struct thinkpad_bd_data *pBDData);
int tp3780I_EnableDSP(struct thinkpad_bd_data *pBDData);
int tp3780I_DisableDSP(struct thinkpad_bd_data *pBDData);
int tp3780I_ResetDSP(struct thinkpad_bd_data *pBDData);
int tp3780I_StartDSP(struct thinkpad_bd_data *pBDData);
int tp3780I_QueryAbilities(struct thinkpad_bd_data *pBDData, struct mw_abilities *pAbilities);
void tp3780I_Cleanup(struct thinkpad_bd_data *pBDData);
int tp3780I_ReadWriteDspDStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr);
int tp3780I_ReadWriteDspIStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr);
#endif

View file

@ -52,7 +52,6 @@
#define PXA3XX_GCU_MINOR 197
#define TUN_MINOR 200
#define CUSE_MINOR 203
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */
#define MPT_MINOR 220
#define MPT2SAS_MINOR 221
#define MPT3SAS_MINOR 222