Root/drivers/char/mwave/mwavedd.c

1/*
2*
3* mwavedd.c -- mwave device driver
4*
5*
6* Written By: Mike Sullivan IBM Corporation
7*
8* Copyright (C) 1999 IBM Corporation
9*
10* This program is free software; you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation; either version 2 of the License, or
13* (at your option) any later version.
14*
15* This program is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* NO WARRANTY
21* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25* solely responsible for determining the appropriateness of using and
26* distributing the Program and assumes all risks associated with its
27* exercise of rights under this Agreement, including but not limited to
28* the risks and costs of program errors, damage to or loss of data,
29* programs or equipment, and unavailability or interruption of operations.
30*
31* DISCLAIMER OF LIABILITY
32* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39*
40* You should have received a copy of the GNU General Public License
41* along with this program; if not, write to the Free Software
42* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*
44*
45* 10/23/2000 - Alpha Release
46* First release to the public
47*/
48
49#include <linux/module.h>
50#include <linux/kernel.h>
51#include <linux/fs.h>
52#include <linux/init.h>
53#include <linux/major.h>
54#include <linux/miscdevice.h>
55#include <linux/device.h>
56#include <linux/serial.h>
57#include <linux/sched.h>
58#include <linux/spinlock.h>
59#include <linux/mutex.h>
60#include <linux/delay.h>
61#include <linux/serial_8250.h>
62#include "smapi.h"
63#include "mwavedd.h"
64#include "3780i.h"
65#include "tp3780i.h"
66
67MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
68MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
69MODULE_LICENSE("GPL");
70
71/*
72* These parameters support the setting of MWave resources. Note that no
73* checks are made against other devices (ie. superio) for conflicts.
74* We'll depend on users using the tpctl utility to do that for now
75*/
76static DEFINE_MUTEX(mwave_mutex);
77int mwave_debug = 0;
78int mwave_3780i_irq = 0;
79int mwave_3780i_io = 0;
80int mwave_uart_irq = 0;
81int mwave_uart_io = 0;
82module_param(mwave_debug, int, 0);
83module_param(mwave_3780i_irq, int, 0);
84module_param(mwave_3780i_io, int, 0);
85module_param(mwave_uart_irq, int, 0);
86module_param(mwave_uart_io, int, 0);
87
88static int mwave_open(struct inode *inode, struct file *file);
89static int mwave_close(struct inode *inode, struct file *file);
90static long mwave_ioctl(struct file *filp, unsigned int iocmd,
91                            unsigned long ioarg);
92
93MWAVE_DEVICE_DATA mwave_s_mdd;
94
95static int mwave_open(struct inode *inode, struct file *file)
96{
97    unsigned int retval = 0;
98
99    PRINTK_3(TRACE_MWAVE,
100        "mwavedd::mwave_open, entry inode %p file %p\n",
101         inode, file);
102    PRINTK_2(TRACE_MWAVE,
103        "mwavedd::mwave_open, exit return retval %x\n", retval);
104
105    return retval;
106}
107
108static int mwave_close(struct inode *inode, struct file *file)
109{
110    unsigned int retval = 0;
111
112    PRINTK_3(TRACE_MWAVE,
113        "mwavedd::mwave_close, entry inode %p file %p\n",
114         inode, file);
115
116    PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %x\n",
117        retval);
118
119    return retval;
120}
121
122static long mwave_ioctl(struct file *file, unsigned int iocmd,
123                            unsigned long ioarg)
124{
125    unsigned int retval = 0;
126    pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
127    void __user *arg = (void __user *)ioarg;
128
129    PRINTK_4(TRACE_MWAVE,
130        "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
131        file, iocmd, (int) ioarg);
132
133    switch (iocmd) {
134
135        case IOCTL_MW_RESET:
136            PRINTK_1(TRACE_MWAVE,
137                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
138                " calling tp3780I_ResetDSP\n");
139            mutex_lock(&mwave_mutex);
140            retval = tp3780I_ResetDSP(&pDrvData->rBDData);
141            mutex_unlock(&mwave_mutex);
142            PRINTK_2(TRACE_MWAVE,
143                "mwavedd::mwave_ioctl, IOCTL_MW_RESET"
144                " retval %x from tp3780I_ResetDSP\n",
145                retval);
146            break;
147    
148        case IOCTL_MW_RUN:
149            PRINTK_1(TRACE_MWAVE,
150                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
151                " calling tp3780I_StartDSP\n");
152            mutex_lock(&mwave_mutex);
153            retval = tp3780I_StartDSP(&pDrvData->rBDData);
154            mutex_unlock(&mwave_mutex);
155            PRINTK_2(TRACE_MWAVE,
156                "mwavedd::mwave_ioctl, IOCTL_MW_RUN"
157                " retval %x from tp3780I_StartDSP\n",
158                retval);
159            break;
160    
161        case IOCTL_MW_DSP_ABILITIES: {
162            MW_ABILITIES rAbilities;
163    
164            PRINTK_1(TRACE_MWAVE,
165                "mwavedd::mwave_ioctl,"
166                " IOCTL_MW_DSP_ABILITIES calling"
167                " tp3780I_QueryAbilities\n");
168            mutex_lock(&mwave_mutex);
169            retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
170                    &rAbilities);
171            mutex_unlock(&mwave_mutex);
172            PRINTK_2(TRACE_MWAVE,
173                "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
174                " retval %x from tp3780I_QueryAbilities\n",
175                retval);
176            if (retval == 0) {
177                if( copy_to_user(arg, &rAbilities,
178                            sizeof(MW_ABILITIES)) )
179                    return -EFAULT;
180            }
181            PRINTK_2(TRACE_MWAVE,
182                "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
183                " exit retval %x\n",
184                retval);
185        }
186            break;
187    
188        case IOCTL_MW_READ_DATA:
189        case IOCTL_MW_READCLEAR_DATA: {
190            MW_READWRITE rReadData;
191            unsigned short __user *pusBuffer = NULL;
192    
193            if( copy_from_user(&rReadData, arg,
194                        sizeof(MW_READWRITE)) )
195                return -EFAULT;
196            pusBuffer = (unsigned short __user *) (rReadData.pBuf);
197    
198            PRINTK_4(TRACE_MWAVE,
199                "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
200                " size %lx, ioarg %lx pusBuffer %p\n",
201                rReadData.ulDataLength, ioarg, pusBuffer);
202            mutex_lock(&mwave_mutex);
203            retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
204                    iocmd,
205                    pusBuffer,
206                    rReadData.ulDataLength,
207                    rReadData.usDspAddress);
208            mutex_unlock(&mwave_mutex);
209        }
210            break;
211    
212        case IOCTL_MW_READ_INST: {
213            MW_READWRITE rReadData;
214            unsigned short __user *pusBuffer = NULL;
215    
216            if( copy_from_user(&rReadData, arg,
217                        sizeof(MW_READWRITE)) )
218                return -EFAULT;
219            pusBuffer = (unsigned short __user *) (rReadData.pBuf);
220    
221            PRINTK_4(TRACE_MWAVE,
222                "mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
223                " size %lx, ioarg %lx pusBuffer %p\n",
224                rReadData.ulDataLength / 2, ioarg,
225                pusBuffer);
226            mutex_lock(&mwave_mutex);
227            retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
228                iocmd, pusBuffer,
229                rReadData.ulDataLength / 2,
230                rReadData.usDspAddress);
231            mutex_unlock(&mwave_mutex);
232        }
233            break;
234    
235        case IOCTL_MW_WRITE_DATA: {
236            MW_READWRITE rWriteData;
237            unsigned short __user *pusBuffer = NULL;
238    
239            if( copy_from_user(&rWriteData, arg,
240                        sizeof(MW_READWRITE)) )
241                return -EFAULT;
242            pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
243    
244            PRINTK_4(TRACE_MWAVE,
245                "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
246                " size %lx, ioarg %lx pusBuffer %p\n",
247                rWriteData.ulDataLength, ioarg,
248                pusBuffer);
249            mutex_lock(&mwave_mutex);
250            retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
251                    iocmd, pusBuffer,
252                    rWriteData.ulDataLength,
253                    rWriteData.usDspAddress);
254            mutex_unlock(&mwave_mutex);
255        }
256            break;
257    
258        case IOCTL_MW_WRITE_INST: {
259            MW_READWRITE rWriteData;
260            unsigned short __user *pusBuffer = NULL;
261    
262            if( copy_from_user(&rWriteData, arg,
263                        sizeof(MW_READWRITE)) )
264                return -EFAULT;
265            pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
266    
267            PRINTK_4(TRACE_MWAVE,
268                "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
269                " size %lx, ioarg %lx pusBuffer %p\n",
270                rWriteData.ulDataLength, ioarg,
271                pusBuffer);
272            mutex_lock(&mwave_mutex);
273            retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
274                    iocmd, pusBuffer,
275                    rWriteData.ulDataLength,
276                    rWriteData.usDspAddress);
277            mutex_unlock(&mwave_mutex);
278        }
279            break;
280    
281        case IOCTL_MW_REGISTER_IPC: {
282            unsigned int ipcnum = (unsigned int) ioarg;
283    
284            if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
285                PRINTK_ERROR(KERN_ERR_MWAVE
286                        "mwavedd::mwave_ioctl:"
287                        " IOCTL_MW_REGISTER_IPC:"
288                        " Error: Invalid ipcnum %x\n",
289                        ipcnum);
290                return -EINVAL;
291            }
292            PRINTK_3(TRACE_MWAVE,
293                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
294                " ipcnum %x entry usIntCount %x\n",
295                ipcnum,
296                pDrvData->IPCs[ipcnum].usIntCount);
297
298            mutex_lock(&mwave_mutex);
299            pDrvData->IPCs[ipcnum].bIsHere = FALSE;
300            pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
301            mutex_unlock(&mwave_mutex);
302    
303            PRINTK_2(TRACE_MWAVE,
304                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
305                " ipcnum %x exit\n",
306                ipcnum);
307        }
308            break;
309    
310        case IOCTL_MW_GET_IPC: {
311            unsigned int ipcnum = (unsigned int) ioarg;
312    
313            if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
314                PRINTK_ERROR(KERN_ERR_MWAVE
315                        "mwavedd::mwave_ioctl:"
316                        " IOCTL_MW_GET_IPC: Error:"
317                        " Invalid ipcnum %x\n", ipcnum);
318                return -EINVAL;
319            }
320            PRINTK_3(TRACE_MWAVE,
321                "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
322                " ipcnum %x, usIntCount %x\n",
323                ipcnum,
324                pDrvData->IPCs[ipcnum].usIntCount);
325    
326            mutex_lock(&mwave_mutex);
327            if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
328                DECLARE_WAITQUEUE(wait, current);
329
330                PRINTK_2(TRACE_MWAVE,
331                    "mwavedd::mwave_ioctl, thread for"
332                    " ipc %x going to sleep\n",
333                    ipcnum);
334                add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
335                pDrvData->IPCs[ipcnum].bIsHere = TRUE;
336                set_current_state(TASK_INTERRUPTIBLE);
337                /* check whether an event was signalled by */
338                /* the interrupt handler while we were gone */
339                if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */
340                    pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */
341                    PRINTK_2(TRACE_MWAVE,
342                        "mwavedd::mwave_ioctl"
343                        " IOCTL_MW_GET_IPC ipcnum %x"
344                        " handling first int\n",
345                        ipcnum);
346                } else { /* either 1st int has not yet occurred, or we have already handled the first int */
347                    schedule();
348                    if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
349                        pDrvData->IPCs[ipcnum].usIntCount = 2;
350                    }
351                    PRINTK_2(TRACE_MWAVE,
352                        "mwavedd::mwave_ioctl"
353                        " IOCTL_MW_GET_IPC ipcnum %x"
354                        " woke up and returning to"
355                        " application\n",
356                        ipcnum);
357                }
358                pDrvData->IPCs[ipcnum].bIsHere = FALSE;
359                remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
360                set_current_state(TASK_RUNNING);
361                PRINTK_2(TRACE_MWAVE,
362                    "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC,"
363                    " returning thread for ipc %x"
364                    " processing\n",
365                    ipcnum);
366            }
367            mutex_unlock(&mwave_mutex);
368        }
369            break;
370    
371        case IOCTL_MW_UNREGISTER_IPC: {
372            unsigned int ipcnum = (unsigned int) ioarg;
373    
374            PRINTK_2(TRACE_MWAVE,
375                "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
376                " ipcnum %x\n",
377                ipcnum);
378            if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
379                PRINTK_ERROR(KERN_ERR_MWAVE
380                        "mwavedd::mwave_ioctl:"
381                        " IOCTL_MW_UNREGISTER_IPC:"
382                        " Error: Invalid ipcnum %x\n",
383                        ipcnum);
384                return -EINVAL;
385            }
386            mutex_lock(&mwave_mutex);
387            if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
388                pDrvData->IPCs[ipcnum].bIsEnabled = FALSE;
389                if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) {
390                    wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
391                }
392            }
393            mutex_unlock(&mwave_mutex);
394        }
395            break;
396    
397        default:
398            return -ENOTTY;
399            break;
400    } /* switch */
401
402    PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);
403
404    return retval;
405}
406
407
408static ssize_t mwave_read(struct file *file, char __user *buf, size_t count,
409                          loff_t * ppos)
410{
411    PRINTK_5(TRACE_MWAVE,
412        "mwavedd::mwave_read entry file %p, buf %p, count %zx ppos %p\n",
413        file, buf, count, ppos);
414
415    return -EINVAL;
416}
417
418
419static ssize_t mwave_write(struct file *file, const char __user *buf,
420                           size_t count, loff_t * ppos)
421{
422    PRINTK_5(TRACE_MWAVE,
423        "mwavedd::mwave_write entry file %p, buf %p,"
424        " count %zx ppos %p\n",
425        file, buf, count, ppos);
426
427    return -EINVAL;
428}
429
430
431static int register_serial_portandirq(unsigned int port, int irq)
432{
433    struct uart_port uart;
434    
435    switch ( port ) {
436        case 0x3f8:
437        case 0x2f8:
438        case 0x3e8:
439        case 0x2e8:
440            /* OK */
441            break;
442        default:
443            PRINTK_ERROR(KERN_ERR_MWAVE
444                    "mwavedd::register_serial_portandirq:"
445                    " Error: Illegal port %x\n", port );
446            return -1;
447    } /* switch */
448    /* port is okay */
449
450    switch ( irq ) {
451        case 3:
452        case 4:
453        case 5:
454        case 7:
455            /* OK */
456            break;
457        default:
458            PRINTK_ERROR(KERN_ERR_MWAVE
459                    "mwavedd::register_serial_portandirq:"
460                    " Error: Illegal irq %x\n", irq );
461            return -1;
462    } /* switch */
463    /* irq is okay */
464
465    memset(&uart, 0, sizeof(struct uart_port));
466    
467    uart.uartclk = 1843200;
468    uart.iobase = port;
469    uart.irq = irq;
470    uart.iotype = UPIO_PORT;
471    uart.flags = UPF_SHARE_IRQ;
472    return serial8250_register_port(&uart);
473}
474
475
476static const struct file_operations mwave_fops = {
477    .owner = THIS_MODULE,
478    .read = mwave_read,
479    .write = mwave_write,
480    .unlocked_ioctl = mwave_ioctl,
481    .open = mwave_open,
482    .release = mwave_close,
483    .llseek = default_llseek,
484};
485
486
487static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
488
489#if 0 /* totally b0rked */
490/*
491 * sysfs support <paulsch@us.ibm.com>
492 */
493
494struct device mwave_device;
495
496/* Prevent code redundancy, create a macro for mwave_show_* functions. */
497#define mwave_show_function(attr_name, format_string, field) \
498static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
499{ \
500    DSP_3780I_CONFIG_SETTINGS *pSettings = \
501        &mwave_s_mdd.rBDData.rDspSettings; \
502        return sprintf(buf, format_string, pSettings->field); \
503}
504
505/* All of our attributes are read attributes. */
506#define mwave_dev_rd_attr(attr_name, format_string, field) \
507    mwave_show_function(attr_name, format_string, field) \
508static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL)
509
510mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma);
511mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq);
512mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO);
513mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq);
514mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO);
515
516static struct device_attribute * const mwave_dev_attrs[] = {
517    &dev_attr_3780i_dma,
518    &dev_attr_3780i_irq,
519    &dev_attr_3780i_io,
520    &dev_attr_uart_irq,
521    &dev_attr_uart_io,
522};
523#endif
524
525/*
526* mwave_init is called on module load
527*
528* mwave_exit is called on module unload
529* mwave_exit is also used to clean up after an aborted mwave_init
530*/
531static void mwave_exit(void)
532{
533    pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
534
535    PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n");
536
537#if 0
538    for (i = 0; i < pDrvData->nr_registered_attrs; i++)
539        device_remove_file(&mwave_device, mwave_dev_attrs[i]);
540    pDrvData->nr_registered_attrs = 0;
541
542    if (pDrvData->device_registered) {
543        device_unregister(&mwave_device);
544        pDrvData->device_registered = FALSE;
545    }
546#endif
547
548    if ( pDrvData->sLine >= 0 ) {
549        serial8250_unregister_port(pDrvData->sLine);
550    }
551    if (pDrvData->bMwaveDevRegistered) {
552        misc_deregister(&mwave_misc_dev);
553    }
554    if (pDrvData->bDSPEnabled) {
555        tp3780I_DisableDSP(&pDrvData->rBDData);
556    }
557    if (pDrvData->bResourcesClaimed) {
558        tp3780I_ReleaseResources(&pDrvData->rBDData);
559    }
560    if (pDrvData->bBDInitialized) {
561        tp3780I_Cleanup(&pDrvData->rBDData);
562    }
563
564    PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit exit\n");
565}
566
567module_exit(mwave_exit);
568
569static int __init mwave_init(void)
570{
571    int i;
572    int retval = 0;
573    pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
574
575    PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");
576
577    memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
578
579    pDrvData->bBDInitialized = FALSE;
580    pDrvData->bResourcesClaimed = FALSE;
581    pDrvData->bDSPEnabled = FALSE;
582    pDrvData->bDSPReset = FALSE;
583    pDrvData->bMwaveDevRegistered = FALSE;
584    pDrvData->sLine = -1;
585
586    for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) {
587        pDrvData->IPCs[i].bIsEnabled = FALSE;
588        pDrvData->IPCs[i].bIsHere = FALSE;
589        pDrvData->IPCs[i].usIntCount = 0; /* no ints received yet */
590        init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
591    }
592
593    retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
594    PRINTK_2(TRACE_MWAVE,
595        "mwavedd::mwave_init, return from tp3780I_InitializeBoardData"
596        " retval %x\n",
597        retval);
598    if (retval) {
599        PRINTK_ERROR(KERN_ERR_MWAVE
600                "mwavedd::mwave_init: Error:"
601                " Failed to initialize board data\n");
602        goto cleanup_error;
603    }
604    pDrvData->bBDInitialized = TRUE;
605
606    retval = tp3780I_CalcResources(&pDrvData->rBDData);
607    PRINTK_2(TRACE_MWAVE,
608        "mwavedd::mwave_init, return from tp3780I_CalcResources"
609        " retval %x\n",
610        retval);
611    if (retval) {
612        PRINTK_ERROR(KERN_ERR_MWAVE
613                "mwavedd:mwave_init: Error:"
614                " Failed to calculate resources\n");
615        goto cleanup_error;
616    }
617
618    retval = tp3780I_ClaimResources(&pDrvData->rBDData);
619    PRINTK_2(TRACE_MWAVE,
620        "mwavedd::mwave_init, return from tp3780I_ClaimResources"
621        " retval %x\n",
622        retval);
623    if (retval) {
624        PRINTK_ERROR(KERN_ERR_MWAVE
625                "mwavedd:mwave_init: Error:"
626                " Failed to claim resources\n");
627        goto cleanup_error;
628    }
629    pDrvData->bResourcesClaimed = TRUE;
630
631    retval = tp3780I_EnableDSP(&pDrvData->rBDData);
632    PRINTK_2(TRACE_MWAVE,
633        "mwavedd::mwave_init, return from tp3780I_EnableDSP"
634        " retval %x\n",
635        retval);
636    if (retval) {
637        PRINTK_ERROR(KERN_ERR_MWAVE
638                "mwavedd:mwave_init: Error:"
639                " Failed to enable DSP\n");
640        goto cleanup_error;
641    }
642    pDrvData->bDSPEnabled = TRUE;
643
644    if (misc_register(&mwave_misc_dev) < 0) {
645        PRINTK_ERROR(KERN_ERR_MWAVE
646                "mwavedd:mwave_init: Error:"
647                " Failed to register misc device\n");
648        goto cleanup_error;
649    }
650    pDrvData->bMwaveDevRegistered = TRUE;
651
652    pDrvData->sLine = register_serial_portandirq(
653        pDrvData->rBDData.rDspSettings.usUartBaseIO,
654        pDrvData->rBDData.rDspSettings.usUartIrq
655    );
656    if (pDrvData->sLine < 0) {
657        PRINTK_ERROR(KERN_ERR_MWAVE
658                "mwavedd:mwave_init: Error:"
659                " Failed to register serial driver\n");
660        goto cleanup_error;
661    }
662    /* uart is registered */
663
664#if 0
665    /* sysfs */
666    memset(&mwave_device, 0, sizeof (struct device));
667    dev_set_name(&mwave_device, "mwave");
668
669    if (device_register(&mwave_device))
670        goto cleanup_error;
671    pDrvData->device_registered = TRUE;
672    for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
673        if(device_create_file(&mwave_device, mwave_dev_attrs[i])) {
674            PRINTK_ERROR(KERN_ERR_MWAVE
675                    "mwavedd:mwave_init: Error:"
676                    " Failed to create sysfs file %s\n",
677                    mwave_dev_attrs[i]->attr.name);
678            goto cleanup_error;
679        }
680        pDrvData->nr_registered_attrs++;
681    }
682#endif
683
684    /* SUCCESS! */
685    return 0;
686
687cleanup_error:
688    PRINTK_ERROR(KERN_ERR_MWAVE
689            "mwavedd::mwave_init: Error:"
690            " Failed to initialize\n");
691    mwave_exit(); /* clean up */
692
693    return -EIO;
694}
695
696module_init(mwave_init);
697
698

Archive Download this file



interactive