xref: /linux/drivers/char/mwave/mwavedd.c (revision 6038f373a3dc1f1c26496e60b6c40b164716f07e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds *
31da177e4SLinus Torvalds * mwavedd.c -- mwave device driver
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Written By: Mike Sullivan IBM Corporation
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * Copyright (C) 1999 IBM Corporation
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify
111da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by
121da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or
131da177e4SLinus Torvalds * (at your option) any later version.
141da177e4SLinus Torvalds *
151da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful,
161da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of
171da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
181da177e4SLinus Torvalds * GNU General Public License for more details.
191da177e4SLinus Torvalds *
201da177e4SLinus Torvalds * NO WARRANTY
211da177e4SLinus Torvalds * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
221da177e4SLinus Torvalds * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
231da177e4SLinus Torvalds * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
241da177e4SLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
251da177e4SLinus Torvalds * solely responsible for determining the appropriateness of using and
261da177e4SLinus Torvalds * distributing the Program and assumes all risks associated with its
271da177e4SLinus Torvalds * exercise of rights under this Agreement, including but not limited to
281da177e4SLinus Torvalds * the risks and costs of program errors, damage to or loss of data,
291da177e4SLinus Torvalds * programs or equipment, and unavailability or interruption of operations.
301da177e4SLinus Torvalds *
311da177e4SLinus Torvalds * DISCLAIMER OF LIABILITY
321da177e4SLinus Torvalds * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
331da177e4SLinus Torvalds * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
341da177e4SLinus Torvalds * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
351da177e4SLinus Torvalds * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
361da177e4SLinus Torvalds * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
371da177e4SLinus Torvalds * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
381da177e4SLinus Torvalds * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
391da177e4SLinus Torvalds *
401da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License
411da177e4SLinus Torvalds * along with this program; if not, write to the Free Software
421da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
431da177e4SLinus Torvalds *
441da177e4SLinus Torvalds *
451da177e4SLinus Torvalds * 10/23/2000 - Alpha Release
461da177e4SLinus Torvalds *	First release to the public
471da177e4SLinus Torvalds */
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds #include <linux/module.h>
501da177e4SLinus Torvalds #include <linux/kernel.h>
511da177e4SLinus Torvalds #include <linux/fs.h>
521da177e4SLinus Torvalds #include <linux/init.h>
531da177e4SLinus Torvalds #include <linux/major.h>
541da177e4SLinus Torvalds #include <linux/miscdevice.h>
551da177e4SLinus Torvalds #include <linux/device.h>
561da177e4SLinus Torvalds #include <linux/serial.h>
571da177e4SLinus Torvalds #include <linux/sched.h>
581da177e4SLinus Torvalds #include <linux/spinlock.h>
59db41bc9cSArnd Bergmann #include <linux/smp_lock.h>
601da177e4SLinus Torvalds #include <linux/delay.h>
615981d644SAlan Cox #include <linux/serial_8250.h>
621da177e4SLinus Torvalds #include "smapi.h"
631da177e4SLinus Torvalds #include "mwavedd.h"
641da177e4SLinus Torvalds #include "3780i.h"
651da177e4SLinus Torvalds #include "tp3780i.h"
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
681da177e4SLinus Torvalds MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
691da177e4SLinus Torvalds MODULE_LICENSE("GPL");
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds /*
721da177e4SLinus Torvalds * These parameters support the setting of MWave resources. Note that no
731da177e4SLinus Torvalds * checks are made against other devices (ie. superio) for conflicts.
741da177e4SLinus Torvalds * We'll depend on users using the tpctl utility to do that for now
751da177e4SLinus Torvalds */
761da177e4SLinus Torvalds int mwave_debug = 0;
771da177e4SLinus Torvalds int mwave_3780i_irq = 0;
781da177e4SLinus Torvalds int mwave_3780i_io = 0;
791da177e4SLinus Torvalds int mwave_uart_irq = 0;
801da177e4SLinus Torvalds int mwave_uart_io = 0;
811da177e4SLinus Torvalds module_param(mwave_debug, int, 0);
821da177e4SLinus Torvalds module_param(mwave_3780i_irq, int, 0);
831da177e4SLinus Torvalds module_param(mwave_3780i_io, int, 0);
841da177e4SLinus Torvalds module_param(mwave_uart_irq, int, 0);
851da177e4SLinus Torvalds module_param(mwave_uart_io, int, 0);
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds static int mwave_open(struct inode *inode, struct file *file);
881da177e4SLinus Torvalds static int mwave_close(struct inode *inode, struct file *file);
89909d145fSAlan Cox static long mwave_ioctl(struct file *filp, unsigned int iocmd,
90909d145fSAlan Cox 							unsigned long ioarg);
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds MWAVE_DEVICE_DATA mwave_s_mdd;
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds static int mwave_open(struct inode *inode, struct file *file)
951da177e4SLinus Torvalds {
961da177e4SLinus Torvalds 	unsigned int retval = 0;
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	PRINTK_3(TRACE_MWAVE,
991da177e4SLinus Torvalds 		"mwavedd::mwave_open, entry inode %p file %p\n",
1001da177e4SLinus Torvalds 		 inode, file);
1011da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE,
1021da177e4SLinus Torvalds 		"mwavedd::mwave_open, exit return retval %x\n", retval);
1031da177e4SLinus Torvalds 
104db41bc9cSArnd Bergmann 	cycle_kernel_lock();
1051da177e4SLinus Torvalds 	return retval;
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds static int mwave_close(struct inode *inode, struct file *file)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds 	unsigned int retval = 0;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds 	PRINTK_3(TRACE_MWAVE,
1131da177e4SLinus Torvalds 		"mwavedd::mwave_close, entry inode %p file %p\n",
1141da177e4SLinus Torvalds 		 inode,  file);
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %x\n",
1171da177e4SLinus Torvalds 		retval);
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 	return retval;
1201da177e4SLinus Torvalds }
1211da177e4SLinus Torvalds 
122909d145fSAlan Cox static long mwave_ioctl(struct file *file, unsigned int iocmd,
123909d145fSAlan Cox 							unsigned long ioarg)
1241da177e4SLinus Torvalds {
1251da177e4SLinus Torvalds 	unsigned int retval = 0;
1261da177e4SLinus Torvalds 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
1271da177e4SLinus Torvalds 	void __user *arg = (void __user *)ioarg;
1281da177e4SLinus Torvalds 
129909d145fSAlan Cox 	PRINTK_4(TRACE_MWAVE,
130909d145fSAlan Cox 		"mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
131909d145fSAlan Cox 		file, iocmd, (int) ioarg);
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	switch (iocmd) {
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds 		case IOCTL_MW_RESET:
1361da177e4SLinus Torvalds 			PRINTK_1(TRACE_MWAVE,
1371da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
1381da177e4SLinus Torvalds 				" calling tp3780I_ResetDSP\n");
139909d145fSAlan Cox 			lock_kernel();
1401da177e4SLinus Torvalds 			retval = tp3780I_ResetDSP(&pDrvData->rBDData);
141909d145fSAlan Cox 			unlock_kernel();
1421da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
1431da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
1441da177e4SLinus Torvalds 				" retval %x from tp3780I_ResetDSP\n",
1451da177e4SLinus Torvalds 				retval);
1461da177e4SLinus Torvalds 			break;
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds 		case IOCTL_MW_RUN:
1491da177e4SLinus Torvalds 			PRINTK_1(TRACE_MWAVE,
1501da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
1511da177e4SLinus Torvalds 				" calling tp3780I_StartDSP\n");
152909d145fSAlan Cox 			lock_kernel();
1531da177e4SLinus Torvalds 			retval = tp3780I_StartDSP(&pDrvData->rBDData);
154909d145fSAlan Cox 			unlock_kernel();
1551da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
1561da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
1571da177e4SLinus Torvalds 				" retval %x from tp3780I_StartDSP\n",
1581da177e4SLinus Torvalds 				retval);
1591da177e4SLinus Torvalds 			break;
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds 		case IOCTL_MW_DSP_ABILITIES: {
1621da177e4SLinus Torvalds 			MW_ABILITIES rAbilities;
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds 			PRINTK_1(TRACE_MWAVE,
1651da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl,"
1661da177e4SLinus Torvalds 				" IOCTL_MW_DSP_ABILITIES calling"
1671da177e4SLinus Torvalds 				" tp3780I_QueryAbilities\n");
168909d145fSAlan Cox 			lock_kernel();
1691da177e4SLinus Torvalds 			retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
1701da177e4SLinus Torvalds 					&rAbilities);
171909d145fSAlan Cox 			unlock_kernel();
1721da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
1731da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
1741da177e4SLinus Torvalds 				" retval %x from tp3780I_QueryAbilities\n",
1751da177e4SLinus Torvalds 				retval);
1761da177e4SLinus Torvalds 			if (retval == 0) {
1771da177e4SLinus Torvalds 				if( copy_to_user(arg, &rAbilities,
1781da177e4SLinus Torvalds 							sizeof(MW_ABILITIES)) )
1791da177e4SLinus Torvalds 					return -EFAULT;
1801da177e4SLinus Torvalds 			}
1811da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
1821da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
1831da177e4SLinus Torvalds 				" exit retval %x\n",
1841da177e4SLinus Torvalds 				retval);
1851da177e4SLinus Torvalds 		}
1861da177e4SLinus Torvalds 			break;
1871da177e4SLinus Torvalds 
1881da177e4SLinus Torvalds 		case IOCTL_MW_READ_DATA:
1891da177e4SLinus Torvalds 		case IOCTL_MW_READCLEAR_DATA: {
1901da177e4SLinus Torvalds 			MW_READWRITE rReadData;
1911da177e4SLinus Torvalds 			unsigned short __user *pusBuffer = NULL;
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 			if( copy_from_user(&rReadData, arg,
1941da177e4SLinus Torvalds 						sizeof(MW_READWRITE)) )
1951da177e4SLinus Torvalds 				return -EFAULT;
1961da177e4SLinus Torvalds 			pusBuffer = (unsigned short __user *) (rReadData.pBuf);
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds 			PRINTK_4(TRACE_MWAVE,
1991da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
2001da177e4SLinus Torvalds 				" size %lx, ioarg %lx pusBuffer %p\n",
2011da177e4SLinus Torvalds 				rReadData.ulDataLength, ioarg, pusBuffer);
202909d145fSAlan Cox 			lock_kernel();
2031da177e4SLinus Torvalds 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
2041da177e4SLinus Torvalds 					iocmd,
2051da177e4SLinus Torvalds 					pusBuffer,
2061da177e4SLinus Torvalds 					rReadData.ulDataLength,
2071da177e4SLinus Torvalds 					rReadData.usDspAddress);
208909d145fSAlan Cox 			unlock_kernel();
2091da177e4SLinus Torvalds 		}
2101da177e4SLinus Torvalds 			break;
2111da177e4SLinus Torvalds 
2121da177e4SLinus Torvalds 		case IOCTL_MW_READ_INST: {
2131da177e4SLinus Torvalds 			MW_READWRITE rReadData;
2141da177e4SLinus Torvalds 			unsigned short __user *pusBuffer = NULL;
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 			if( copy_from_user(&rReadData, arg,
2171da177e4SLinus Torvalds 						sizeof(MW_READWRITE)) )
2181da177e4SLinus Torvalds 				return -EFAULT;
2191da177e4SLinus Torvalds 			pusBuffer = (unsigned short __user *) (rReadData.pBuf);
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 			PRINTK_4(TRACE_MWAVE,
2221da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
2231da177e4SLinus Torvalds 				" size %lx, ioarg %lx pusBuffer %p\n",
2241da177e4SLinus Torvalds 				rReadData.ulDataLength / 2, ioarg,
2251da177e4SLinus Torvalds 				pusBuffer);
226909d145fSAlan Cox 			lock_kernel();
2271da177e4SLinus Torvalds 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
2281da177e4SLinus Torvalds 				iocmd, pusBuffer,
2291da177e4SLinus Torvalds 				rReadData.ulDataLength / 2,
2301da177e4SLinus Torvalds 				rReadData.usDspAddress);
231909d145fSAlan Cox 			unlock_kernel();
2321da177e4SLinus Torvalds 		}
2331da177e4SLinus Torvalds 			break;
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds 		case IOCTL_MW_WRITE_DATA: {
2361da177e4SLinus Torvalds 			MW_READWRITE rWriteData;
2371da177e4SLinus Torvalds 			unsigned short __user *pusBuffer = NULL;
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds 			if( copy_from_user(&rWriteData, arg,
2401da177e4SLinus Torvalds 						sizeof(MW_READWRITE)) )
2411da177e4SLinus Torvalds 				return -EFAULT;
2421da177e4SLinus Torvalds 			pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 			PRINTK_4(TRACE_MWAVE,
2451da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
2461da177e4SLinus Torvalds 				" size %lx, ioarg %lx pusBuffer %p\n",
2471da177e4SLinus Torvalds 				rWriteData.ulDataLength, ioarg,
2481da177e4SLinus Torvalds 				pusBuffer);
249909d145fSAlan Cox 			lock_kernel();
2501da177e4SLinus Torvalds 			retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
2511da177e4SLinus Torvalds 					iocmd, pusBuffer,
2521da177e4SLinus Torvalds 					rWriteData.ulDataLength,
2531da177e4SLinus Torvalds 					rWriteData.usDspAddress);
254909d145fSAlan Cox 			unlock_kernel();
2551da177e4SLinus Torvalds 		}
2561da177e4SLinus Torvalds 			break;
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds 		case IOCTL_MW_WRITE_INST: {
2591da177e4SLinus Torvalds 			MW_READWRITE rWriteData;
2601da177e4SLinus Torvalds 			unsigned short __user *pusBuffer = NULL;
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds 			if( copy_from_user(&rWriteData, arg,
2631da177e4SLinus Torvalds 						sizeof(MW_READWRITE)) )
2641da177e4SLinus Torvalds 				return -EFAULT;
2651da177e4SLinus Torvalds 			pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds 			PRINTK_4(TRACE_MWAVE,
2681da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
2691da177e4SLinus Torvalds 				" size %lx, ioarg %lx pusBuffer %p\n",
2701da177e4SLinus Torvalds 				rWriteData.ulDataLength, ioarg,
2711da177e4SLinus Torvalds 				pusBuffer);
272909d145fSAlan Cox 			lock_kernel();
2731da177e4SLinus Torvalds 			retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
2741da177e4SLinus Torvalds 					iocmd, pusBuffer,
2751da177e4SLinus Torvalds 					rWriteData.ulDataLength,
2761da177e4SLinus Torvalds 					rWriteData.usDspAddress);
277909d145fSAlan Cox 			unlock_kernel();
2781da177e4SLinus Torvalds 		}
2791da177e4SLinus Torvalds 			break;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 		case IOCTL_MW_REGISTER_IPC: {
2821da177e4SLinus Torvalds 			unsigned int ipcnum = (unsigned int) ioarg;
2831da177e4SLinus Torvalds 
284d698f1c7SEric Sesterhenn 			if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
2851da177e4SLinus Torvalds 				PRINTK_ERROR(KERN_ERR_MWAVE
2861da177e4SLinus Torvalds 						"mwavedd::mwave_ioctl:"
2871da177e4SLinus Torvalds 						" IOCTL_MW_REGISTER_IPC:"
2881da177e4SLinus Torvalds 						" Error: Invalid ipcnum %x\n",
2891da177e4SLinus Torvalds 						ipcnum);
2901da177e4SLinus Torvalds 				return -EINVAL;
2911da177e4SLinus Torvalds 			}
292dc80df56SRoel Kluin 			PRINTK_3(TRACE_MWAVE,
293dc80df56SRoel Kluin 				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
294dc80df56SRoel Kluin 				" ipcnum %x entry usIntCount %x\n",
295dc80df56SRoel Kluin 				ipcnum,
296dc80df56SRoel Kluin 				pDrvData->IPCs[ipcnum].usIntCount);
297dc80df56SRoel Kluin 
298909d145fSAlan Cox 			lock_kernel();
2991da177e4SLinus Torvalds 			pDrvData->IPCs[ipcnum].bIsHere = FALSE;
3001da177e4SLinus Torvalds 			pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
301909d145fSAlan Cox 			unlock_kernel();
3021da177e4SLinus Torvalds 
3031da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
3041da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
3051da177e4SLinus Torvalds 				" ipcnum %x exit\n",
3061da177e4SLinus Torvalds 				ipcnum);
3071da177e4SLinus Torvalds 		}
3081da177e4SLinus Torvalds 			break;
3091da177e4SLinus Torvalds 
3101da177e4SLinus Torvalds 		case IOCTL_MW_GET_IPC: {
3111da177e4SLinus Torvalds 			unsigned int ipcnum = (unsigned int) ioarg;
3121da177e4SLinus Torvalds 
313095d030cSEric Sesterhenn 			if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
3141da177e4SLinus Torvalds 				PRINTK_ERROR(KERN_ERR_MWAVE
3151da177e4SLinus Torvalds 						"mwavedd::mwave_ioctl:"
3161da177e4SLinus Torvalds 						" IOCTL_MW_GET_IPC: Error:"
3171da177e4SLinus Torvalds 						" Invalid ipcnum %x\n", ipcnum);
3181da177e4SLinus Torvalds 				return -EINVAL;
3191da177e4SLinus Torvalds 			}
320dc80df56SRoel Kluin 			PRINTK_3(TRACE_MWAVE,
321dc80df56SRoel Kluin 				"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
322dc80df56SRoel Kluin 				" ipcnum %x, usIntCount %x\n",
323dc80df56SRoel Kluin 				ipcnum,
324dc80df56SRoel Kluin 				pDrvData->IPCs[ipcnum].usIntCount);
3251da177e4SLinus Torvalds 
326909d145fSAlan Cox 			lock_kernel();
3271da177e4SLinus Torvalds 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
3281da177e4SLinus Torvalds 				DECLARE_WAITQUEUE(wait, current);
3291da177e4SLinus Torvalds 
3301da177e4SLinus Torvalds 				PRINTK_2(TRACE_MWAVE,
3311da177e4SLinus Torvalds 					"mwavedd::mwave_ioctl, thread for"
3321da177e4SLinus Torvalds 					" ipc %x going to sleep\n",
3331da177e4SLinus Torvalds 					ipcnum);
3341da177e4SLinus Torvalds 				add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
3351da177e4SLinus Torvalds 				pDrvData->IPCs[ipcnum].bIsHere = TRUE;
3361da177e4SLinus Torvalds 				set_current_state(TASK_INTERRUPTIBLE);
3371da177e4SLinus Torvalds 				/* check whether an event was signalled by */
3381da177e4SLinus Torvalds 				/* the interrupt handler while we were gone */
3391da177e4SLinus Torvalds 				if (pDrvData->IPCs[ipcnum].usIntCount == 1) {	/* first int has occurred (race condition) */
3401da177e4SLinus Torvalds 					pDrvData->IPCs[ipcnum].usIntCount = 2;	/* first int has been handled */
3411da177e4SLinus Torvalds 					PRINTK_2(TRACE_MWAVE,
3421da177e4SLinus Torvalds 						"mwavedd::mwave_ioctl"
3431da177e4SLinus Torvalds 						" IOCTL_MW_GET_IPC ipcnum %x"
3441da177e4SLinus Torvalds 						" handling first int\n",
3451da177e4SLinus Torvalds 						ipcnum);
3461da177e4SLinus Torvalds 				} else {	/* either 1st int has not yet occurred, or we have already handled the first int */
3471da177e4SLinus Torvalds 					schedule();
3481da177e4SLinus Torvalds 					if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
3491da177e4SLinus Torvalds 						pDrvData->IPCs[ipcnum].usIntCount = 2;
3501da177e4SLinus Torvalds 					}
3511da177e4SLinus Torvalds 					PRINTK_2(TRACE_MWAVE,
3521da177e4SLinus Torvalds 						"mwavedd::mwave_ioctl"
3531da177e4SLinus Torvalds 						" IOCTL_MW_GET_IPC ipcnum %x"
3541da177e4SLinus Torvalds 						" woke up and returning to"
3551da177e4SLinus Torvalds 						" application\n",
3561da177e4SLinus Torvalds 						ipcnum);
3571da177e4SLinus Torvalds 				}
3581da177e4SLinus Torvalds 				pDrvData->IPCs[ipcnum].bIsHere = FALSE;
3591da177e4SLinus Torvalds 				remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
3601da177e4SLinus Torvalds 				set_current_state(TASK_RUNNING);
3611da177e4SLinus Torvalds 				PRINTK_2(TRACE_MWAVE,
3621da177e4SLinus Torvalds 					"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC,"
3631da177e4SLinus Torvalds 					" returning thread for ipc %x"
3641da177e4SLinus Torvalds 					" processing\n",
3651da177e4SLinus Torvalds 					ipcnum);
3661da177e4SLinus Torvalds 			}
367909d145fSAlan Cox 			unlock_kernel();
3681da177e4SLinus Torvalds 		}
3691da177e4SLinus Torvalds 			break;
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 		case IOCTL_MW_UNREGISTER_IPC: {
3721da177e4SLinus Torvalds 			unsigned int ipcnum = (unsigned int) ioarg;
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds 			PRINTK_2(TRACE_MWAVE,
3751da177e4SLinus Torvalds 				"mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
3761da177e4SLinus Torvalds 				" ipcnum %x\n",
3771da177e4SLinus Torvalds 				ipcnum);
378095d030cSEric Sesterhenn 			if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
3791da177e4SLinus Torvalds 				PRINTK_ERROR(KERN_ERR_MWAVE
3801da177e4SLinus Torvalds 						"mwavedd::mwave_ioctl:"
3811da177e4SLinus Torvalds 						" IOCTL_MW_UNREGISTER_IPC:"
3821da177e4SLinus Torvalds 						" Error: Invalid ipcnum %x\n",
3831da177e4SLinus Torvalds 						ipcnum);
3841da177e4SLinus Torvalds 				return -EINVAL;
3851da177e4SLinus Torvalds 			}
386909d145fSAlan Cox 			lock_kernel();
3871da177e4SLinus Torvalds 			if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
3881da177e4SLinus Torvalds 				pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
3891da177e4SLinus Torvalds 				if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
3901da177e4SLinus Torvalds 					wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
3911da177e4SLinus Torvalds 				}
3921da177e4SLinus Torvalds 			}
393909d145fSAlan Cox 			unlock_kernel();
3941da177e4SLinus Torvalds 		}
3951da177e4SLinus Torvalds 			break;
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 		default:
3981da177e4SLinus Torvalds 			return -ENOTTY;
3991da177e4SLinus Torvalds 			break;
4001da177e4SLinus Torvalds 	} /* switch */
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);
4031da177e4SLinus Torvalds 
4041da177e4SLinus Torvalds 	return retval;
4051da177e4SLinus Torvalds }
4061da177e4SLinus Torvalds 
4071da177e4SLinus Torvalds 
4081da177e4SLinus Torvalds static ssize_t mwave_read(struct file *file, char __user *buf, size_t count,
4091da177e4SLinus Torvalds                           loff_t * ppos)
4101da177e4SLinus Torvalds {
4111da177e4SLinus Torvalds 	PRINTK_5(TRACE_MWAVE,
4121da177e4SLinus Torvalds 		"mwavedd::mwave_read entry file %p, buf %p, count %zx ppos %p\n",
4131da177e4SLinus Torvalds 		file, buf, count, ppos);
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	return -EINVAL;
4161da177e4SLinus Torvalds }
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds static ssize_t mwave_write(struct file *file, const char __user *buf,
4201da177e4SLinus Torvalds                            size_t count, loff_t * ppos)
4211da177e4SLinus Torvalds {
4221da177e4SLinus Torvalds 	PRINTK_5(TRACE_MWAVE,
4231da177e4SLinus Torvalds 		"mwavedd::mwave_write entry file %p, buf %p,"
4241da177e4SLinus Torvalds 		" count %zx ppos %p\n",
4251da177e4SLinus Torvalds 		file, buf, count, ppos);
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 	return -EINVAL;
4281da177e4SLinus Torvalds }
4291da177e4SLinus Torvalds 
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds static int register_serial_portandirq(unsigned int port, int irq)
4321da177e4SLinus Torvalds {
4335981d644SAlan Cox 	struct uart_port uart;
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds 	switch ( port ) {
4361da177e4SLinus Torvalds 		case 0x3f8:
4371da177e4SLinus Torvalds 		case 0x2f8:
4381da177e4SLinus Torvalds 		case 0x3e8:
4391da177e4SLinus Torvalds 		case 0x2e8:
4401da177e4SLinus Torvalds 			/* OK */
4411da177e4SLinus Torvalds 			break;
4421da177e4SLinus Torvalds 		default:
4431da177e4SLinus Torvalds 			PRINTK_ERROR(KERN_ERR_MWAVE
4441da177e4SLinus Torvalds 					"mwavedd::register_serial_portandirq:"
4451da177e4SLinus Torvalds 					" Error: Illegal port %x\n", port );
4461da177e4SLinus Torvalds 			return -1;
4471da177e4SLinus Torvalds 	} /* switch */
4481da177e4SLinus Torvalds 	/* port is okay */
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	switch ( irq ) {
4511da177e4SLinus Torvalds 		case 3:
4521da177e4SLinus Torvalds 		case 4:
4531da177e4SLinus Torvalds 		case 5:
4541da177e4SLinus Torvalds 		case 7:
4551da177e4SLinus Torvalds 			/* OK */
4561da177e4SLinus Torvalds 			break;
4571da177e4SLinus Torvalds 		default:
4581da177e4SLinus Torvalds 			PRINTK_ERROR(KERN_ERR_MWAVE
4591da177e4SLinus Torvalds 					"mwavedd::register_serial_portandirq:"
4601da177e4SLinus Torvalds 					" Error: Illegal irq %x\n", irq );
4611da177e4SLinus Torvalds 			return -1;
4621da177e4SLinus Torvalds 	} /* switch */
4631da177e4SLinus Torvalds 	/* irq is okay */
4641da177e4SLinus Torvalds 
4655981d644SAlan Cox 	memset(&uart, 0, sizeof(struct uart_port));
4661da177e4SLinus Torvalds 
4675981d644SAlan Cox 	uart.uartclk =  1843200;
4685981d644SAlan Cox 	uart.iobase = port;
4695981d644SAlan Cox 	uart.irq = irq;
4705981d644SAlan Cox 	uart.iotype = UPIO_PORT;
4715981d644SAlan Cox 	uart.flags =  UPF_SHARE_IRQ;
4725981d644SAlan Cox 	return serial8250_register_port(&uart);
4731da177e4SLinus Torvalds }
4741da177e4SLinus Torvalds 
4751da177e4SLinus Torvalds 
47662322d25SArjan van de Ven static const struct file_operations mwave_fops = {
4771da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
4781da177e4SLinus Torvalds 	.read		= mwave_read,
4791da177e4SLinus Torvalds 	.write		= mwave_write,
480909d145fSAlan Cox 	.unlocked_ioctl	= mwave_ioctl,
4811da177e4SLinus Torvalds 	.open		= mwave_open,
482*6038f373SArnd Bergmann 	.release	= mwave_close,
483*6038f373SArnd Bergmann 	.llseek		= default_llseek,
4841da177e4SLinus Torvalds };
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
4881da177e4SLinus Torvalds 
4891da177e4SLinus Torvalds #if 0 /* totally b0rked */
4901da177e4SLinus Torvalds /*
4911da177e4SLinus Torvalds  * sysfs support <paulsch@us.ibm.com>
4921da177e4SLinus Torvalds  */
4931da177e4SLinus Torvalds 
4941da177e4SLinus Torvalds struct device mwave_device;
4951da177e4SLinus Torvalds 
4961da177e4SLinus Torvalds /* Prevent code redundancy, create a macro for mwave_show_* functions. */
4971da177e4SLinus Torvalds #define mwave_show_function(attr_name, format_string, field)		\
49874880c06SYani Ioannou static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf)	\
4991da177e4SLinus Torvalds {									\
5001da177e4SLinus Torvalds 	DSP_3780I_CONFIG_SETTINGS *pSettings =				\
5011da177e4SLinus Torvalds 		&mwave_s_mdd.rBDData.rDspSettings;			\
5021da177e4SLinus Torvalds         return sprintf(buf, format_string, pSettings->field);		\
5031da177e4SLinus Torvalds }
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds /* All of our attributes are read attributes. */
5061da177e4SLinus Torvalds #define mwave_dev_rd_attr(attr_name, format_string, field)		\
5071da177e4SLinus Torvalds 	mwave_show_function(attr_name, format_string, field)		\
5081da177e4SLinus Torvalds static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL)
5091da177e4SLinus Torvalds 
5101da177e4SLinus Torvalds mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma);
5111da177e4SLinus Torvalds mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq);
5121da177e4SLinus Torvalds mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO);
5131da177e4SLinus Torvalds mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq);
5141da177e4SLinus Torvalds mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO);
5151da177e4SLinus Torvalds 
5161da177e4SLinus Torvalds static struct device_attribute * const mwave_dev_attrs[] = {
5171da177e4SLinus Torvalds 	&dev_attr_3780i_dma,
5181da177e4SLinus Torvalds 	&dev_attr_3780i_irq,
5191da177e4SLinus Torvalds 	&dev_attr_3780i_io,
5201da177e4SLinus Torvalds 	&dev_attr_uart_irq,
5211da177e4SLinus Torvalds 	&dev_attr_uart_io,
5221da177e4SLinus Torvalds };
5231da177e4SLinus Torvalds #endif
5241da177e4SLinus Torvalds 
5251da177e4SLinus Torvalds /*
5261da177e4SLinus Torvalds * mwave_init is called on module load
5271da177e4SLinus Torvalds *
5281da177e4SLinus Torvalds * mwave_exit is called on module unload
5291da177e4SLinus Torvalds * mwave_exit is also used to clean up after an aborted mwave_init
5301da177e4SLinus Torvalds */
5311da177e4SLinus Torvalds static void mwave_exit(void)
5321da177e4SLinus Torvalds {
5331da177e4SLinus Torvalds 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds 	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n");
5361da177e4SLinus Torvalds 
5371da177e4SLinus Torvalds #if 0
5381da177e4SLinus Torvalds 	for (i = 0; i < pDrvData->nr_registered_attrs; i++)
5391da177e4SLinus Torvalds 		device_remove_file(&mwave_device, mwave_dev_attrs[i]);
5401da177e4SLinus Torvalds 	pDrvData->nr_registered_attrs = 0;
5411da177e4SLinus Torvalds 
5421da177e4SLinus Torvalds 	if (pDrvData->device_registered) {
5431da177e4SLinus Torvalds 		device_unregister(&mwave_device);
5441da177e4SLinus Torvalds 		pDrvData->device_registered = FALSE;
5451da177e4SLinus Torvalds 	}
5461da177e4SLinus Torvalds #endif
5471da177e4SLinus Torvalds 
5481da177e4SLinus Torvalds 	if ( pDrvData->sLine >= 0 ) {
5495981d644SAlan Cox 		serial8250_unregister_port(pDrvData->sLine);
5501da177e4SLinus Torvalds 	}
5511da177e4SLinus Torvalds 	if (pDrvData->bMwaveDevRegistered) {
5521da177e4SLinus Torvalds 		misc_deregister(&mwave_misc_dev);
5531da177e4SLinus Torvalds 	}
5541da177e4SLinus Torvalds 	if (pDrvData->bDSPEnabled) {
5551da177e4SLinus Torvalds 		tp3780I_DisableDSP(&pDrvData->rBDData);
5561da177e4SLinus Torvalds 	}
5571da177e4SLinus Torvalds 	if (pDrvData->bResourcesClaimed) {
5581da177e4SLinus Torvalds 		tp3780I_ReleaseResources(&pDrvData->rBDData);
5591da177e4SLinus Torvalds 	}
5601da177e4SLinus Torvalds 	if (pDrvData->bBDInitialized) {
5611da177e4SLinus Torvalds 		tp3780I_Cleanup(&pDrvData->rBDData);
5621da177e4SLinus Torvalds 	}
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit exit\n");
5651da177e4SLinus Torvalds }
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds module_exit(mwave_exit);
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds static int __init mwave_init(void)
5701da177e4SLinus Torvalds {
5711da177e4SLinus Torvalds 	int i;
5721da177e4SLinus Torvalds 	int retval = 0;
5731da177e4SLinus Torvalds 	pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds 	PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");
5761da177e4SLinus Torvalds 
5771da177e4SLinus Torvalds 	memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds 	pDrvData->bBDInitialized = FALSE;
5801da177e4SLinus Torvalds 	pDrvData->bResourcesClaimed = FALSE;
5811da177e4SLinus Torvalds 	pDrvData->bDSPEnabled = FALSE;
5821da177e4SLinus Torvalds 	pDrvData->bDSPReset = FALSE;
5831da177e4SLinus Torvalds 	pDrvData->bMwaveDevRegistered = FALSE;
5841da177e4SLinus Torvalds 	pDrvData->sLine = -1;
5851da177e4SLinus Torvalds 
5861da177e4SLinus Torvalds 	for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) {
5871da177e4SLinus Torvalds 		pDrvData->IPCs[i].bIsEnabled = FALSE;
5881da177e4SLinus Torvalds 		pDrvData->IPCs[i].bIsHere = FALSE;
5891da177e4SLinus Torvalds 		pDrvData->IPCs[i].usIntCount = 0;	/* no ints received yet */
5901da177e4SLinus Torvalds 		init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
5911da177e4SLinus Torvalds 	}
5921da177e4SLinus Torvalds 
5931da177e4SLinus Torvalds 	retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
5941da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE,
5951da177e4SLinus Torvalds 		"mwavedd::mwave_init, return from tp3780I_InitializeBoardData"
5961da177e4SLinus Torvalds 		" retval %x\n",
5971da177e4SLinus Torvalds 		retval);
5981da177e4SLinus Torvalds 	if (retval) {
5991da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6001da177e4SLinus Torvalds 				"mwavedd::mwave_init: Error:"
6011da177e4SLinus Torvalds 				" Failed to initialize board data\n");
6021da177e4SLinus Torvalds 		goto cleanup_error;
6031da177e4SLinus Torvalds 	}
6041da177e4SLinus Torvalds 	pDrvData->bBDInitialized = TRUE;
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 	retval = tp3780I_CalcResources(&pDrvData->rBDData);
6071da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE,
6081da177e4SLinus Torvalds 		"mwavedd::mwave_init, return from tp3780I_CalcResources"
6091da177e4SLinus Torvalds 		" retval %x\n",
6101da177e4SLinus Torvalds 		retval);
6111da177e4SLinus Torvalds 	if (retval) {
6121da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6131da177e4SLinus Torvalds 				"mwavedd:mwave_init: Error:"
6141da177e4SLinus Torvalds 				" Failed to calculate resources\n");
6151da177e4SLinus Torvalds 		goto cleanup_error;
6161da177e4SLinus Torvalds 	}
6171da177e4SLinus Torvalds 
6181da177e4SLinus Torvalds 	retval = tp3780I_ClaimResources(&pDrvData->rBDData);
6191da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE,
6201da177e4SLinus Torvalds 		"mwavedd::mwave_init, return from tp3780I_ClaimResources"
6211da177e4SLinus Torvalds 		" retval %x\n",
6221da177e4SLinus Torvalds 		retval);
6231da177e4SLinus Torvalds 	if (retval) {
6241da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6251da177e4SLinus Torvalds 				"mwavedd:mwave_init: Error:"
6261da177e4SLinus Torvalds 				" Failed to claim resources\n");
6271da177e4SLinus Torvalds 		goto cleanup_error;
6281da177e4SLinus Torvalds 	}
6291da177e4SLinus Torvalds 	pDrvData->bResourcesClaimed = TRUE;
6301da177e4SLinus Torvalds 
6311da177e4SLinus Torvalds 	retval = tp3780I_EnableDSP(&pDrvData->rBDData);
6321da177e4SLinus Torvalds 	PRINTK_2(TRACE_MWAVE,
6331da177e4SLinus Torvalds 		"mwavedd::mwave_init, return from tp3780I_EnableDSP"
6341da177e4SLinus Torvalds 		" retval %x\n",
6351da177e4SLinus Torvalds 		retval);
6361da177e4SLinus Torvalds 	if (retval) {
6371da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6381da177e4SLinus Torvalds 				"mwavedd:mwave_init: Error:"
6391da177e4SLinus Torvalds 				" Failed to enable DSP\n");
6401da177e4SLinus Torvalds 		goto cleanup_error;
6411da177e4SLinus Torvalds 	}
6421da177e4SLinus Torvalds 	pDrvData->bDSPEnabled = TRUE;
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds 	if (misc_register(&mwave_misc_dev) < 0) {
6451da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6461da177e4SLinus Torvalds 				"mwavedd:mwave_init: Error:"
6471da177e4SLinus Torvalds 				" Failed to register misc device\n");
6481da177e4SLinus Torvalds 		goto cleanup_error;
6491da177e4SLinus Torvalds 	}
6501da177e4SLinus Torvalds 	pDrvData->bMwaveDevRegistered = TRUE;
6511da177e4SLinus Torvalds 
6521da177e4SLinus Torvalds 	pDrvData->sLine = register_serial_portandirq(
6531da177e4SLinus Torvalds 		pDrvData->rBDData.rDspSettings.usUartBaseIO,
6541da177e4SLinus Torvalds 		pDrvData->rBDData.rDspSettings.usUartIrq
6551da177e4SLinus Torvalds 	);
6561da177e4SLinus Torvalds 	if (pDrvData->sLine < 0) {
6571da177e4SLinus Torvalds 		PRINTK_ERROR(KERN_ERR_MWAVE
6581da177e4SLinus Torvalds 				"mwavedd:mwave_init: Error:"
6591da177e4SLinus Torvalds 				" Failed to register serial driver\n");
6601da177e4SLinus Torvalds 		goto cleanup_error;
6611da177e4SLinus Torvalds 	}
6621da177e4SLinus Torvalds 	/* uart is registered */
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds #if 0
6651da177e4SLinus Torvalds 	/* sysfs */
6661da177e4SLinus Torvalds 	memset(&mwave_device, 0, sizeof (struct device));
66724d25475SKay Sievers 	dev_set_name(&mwave_device, "mwave");
6681da177e4SLinus Torvalds 
6691da177e4SLinus Torvalds 	if (device_register(&mwave_device))
6701da177e4SLinus Torvalds 		goto cleanup_error;
6711da177e4SLinus Torvalds 	pDrvData->device_registered = TRUE;
6721da177e4SLinus Torvalds 	for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
6731da177e4SLinus Torvalds 		if(device_create_file(&mwave_device, mwave_dev_attrs[i])) {
6741da177e4SLinus Torvalds 			PRINTK_ERROR(KERN_ERR_MWAVE
6751da177e4SLinus Torvalds 					"mwavedd:mwave_init: Error:"
6761da177e4SLinus Torvalds 					" Failed to create sysfs file %s\n",
6771da177e4SLinus Torvalds 					mwave_dev_attrs[i]->attr.name);
6781da177e4SLinus Torvalds 			goto cleanup_error;
6791da177e4SLinus Torvalds 		}
6801da177e4SLinus Torvalds 		pDrvData->nr_registered_attrs++;
6811da177e4SLinus Torvalds 	}
6821da177e4SLinus Torvalds #endif
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds 	/* SUCCESS! */
6851da177e4SLinus Torvalds 	return 0;
6861da177e4SLinus Torvalds 
6871da177e4SLinus Torvalds cleanup_error:
6881da177e4SLinus Torvalds 	PRINTK_ERROR(KERN_ERR_MWAVE
6891da177e4SLinus Torvalds 			"mwavedd::mwave_init: Error:"
6901da177e4SLinus Torvalds 			" Failed to initialize\n");
6911da177e4SLinus Torvalds 	mwave_exit(); /* clean up */
6921da177e4SLinus Torvalds 
6931da177e4SLinus Torvalds 	return -EIO;
6941da177e4SLinus Torvalds }
6951da177e4SLinus Torvalds 
6961da177e4SLinus Torvalds module_init(mwave_init);
6971da177e4SLinus Torvalds 
698