diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/mwave/mwavedd.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/mwave/mwavedd.c')
-rw-r--r-- | drivers/char/mwave/mwavedd.c | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c new file mode 100644 index 000000000000..d37625d47746 --- /dev/null +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -0,0 +1,674 @@ | |||
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/delay.h> | ||
60 | #include "smapi.h" | ||
61 | #include "mwavedd.h" | ||
62 | #include "3780i.h" | ||
63 | #include "tp3780i.h" | ||
64 | |||
65 | MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver"); | ||
66 | MODULE_AUTHOR("Mike Sullivan and Paul Schroeder"); | ||
67 | MODULE_LICENSE("GPL"); | ||
68 | |||
69 | /* | ||
70 | * These parameters support the setting of MWave resources. Note that no | ||
71 | * checks are made against other devices (ie. superio) for conflicts. | ||
72 | * We'll depend on users using the tpctl utility to do that for now | ||
73 | */ | ||
74 | int mwave_debug = 0; | ||
75 | int mwave_3780i_irq = 0; | ||
76 | int mwave_3780i_io = 0; | ||
77 | int mwave_uart_irq = 0; | ||
78 | int mwave_uart_io = 0; | ||
79 | module_param(mwave_debug, int, 0); | ||
80 | module_param(mwave_3780i_irq, int, 0); | ||
81 | module_param(mwave_3780i_io, int, 0); | ||
82 | module_param(mwave_uart_irq, int, 0); | ||
83 | module_param(mwave_uart_io, int, 0); | ||
84 | |||
85 | static int mwave_open(struct inode *inode, struct file *file); | ||
86 | static int mwave_close(struct inode *inode, struct file *file); | ||
87 | static int mwave_ioctl(struct inode *inode, struct file *filp, | ||
88 | unsigned int iocmd, unsigned long ioarg); | ||
89 | |||
90 | MWAVE_DEVICE_DATA mwave_s_mdd; | ||
91 | |||
92 | static int mwave_open(struct inode *inode, struct file *file) | ||
93 | { | ||
94 | unsigned int retval = 0; | ||
95 | |||
96 | PRINTK_3(TRACE_MWAVE, | ||
97 | "mwavedd::mwave_open, entry inode %p file %p\n", | ||
98 | inode, file); | ||
99 | PRINTK_2(TRACE_MWAVE, | ||
100 | "mwavedd::mwave_open, exit return retval %x\n", retval); | ||
101 | |||
102 | return retval; | ||
103 | } | ||
104 | |||
105 | static int mwave_close(struct inode *inode, struct file *file) | ||
106 | { | ||
107 | unsigned int retval = 0; | ||
108 | |||
109 | PRINTK_3(TRACE_MWAVE, | ||
110 | "mwavedd::mwave_close, entry inode %p file %p\n", | ||
111 | inode, file); | ||
112 | |||
113 | PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %x\n", | ||
114 | retval); | ||
115 | |||
116 | return retval; | ||
117 | } | ||
118 | |||
119 | static int mwave_ioctl(struct inode *inode, struct file *file, | ||
120 | unsigned int iocmd, unsigned long ioarg) | ||
121 | { | ||
122 | unsigned int retval = 0; | ||
123 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; | ||
124 | void __user *arg = (void __user *)ioarg; | ||
125 | |||
126 | PRINTK_5(TRACE_MWAVE, | ||
127 | "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n", | ||
128 | inode, file, iocmd, (int) ioarg); | ||
129 | |||
130 | switch (iocmd) { | ||
131 | |||
132 | case IOCTL_MW_RESET: | ||
133 | PRINTK_1(TRACE_MWAVE, | ||
134 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | ||
135 | " calling tp3780I_ResetDSP\n"); | ||
136 | retval = tp3780I_ResetDSP(&pDrvData->rBDData); | ||
137 | PRINTK_2(TRACE_MWAVE, | ||
138 | "mwavedd::mwave_ioctl, IOCTL_MW_RESET" | ||
139 | " retval %x from tp3780I_ResetDSP\n", | ||
140 | retval); | ||
141 | break; | ||
142 | |||
143 | case IOCTL_MW_RUN: | ||
144 | PRINTK_1(TRACE_MWAVE, | ||
145 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | ||
146 | " calling tp3780I_StartDSP\n"); | ||
147 | retval = tp3780I_StartDSP(&pDrvData->rBDData); | ||
148 | PRINTK_2(TRACE_MWAVE, | ||
149 | "mwavedd::mwave_ioctl, IOCTL_MW_RUN" | ||
150 | " retval %x from tp3780I_StartDSP\n", | ||
151 | retval); | ||
152 | break; | ||
153 | |||
154 | case IOCTL_MW_DSP_ABILITIES: { | ||
155 | MW_ABILITIES rAbilities; | ||
156 | |||
157 | PRINTK_1(TRACE_MWAVE, | ||
158 | "mwavedd::mwave_ioctl," | ||
159 | " IOCTL_MW_DSP_ABILITIES calling" | ||
160 | " tp3780I_QueryAbilities\n"); | ||
161 | retval = tp3780I_QueryAbilities(&pDrvData->rBDData, | ||
162 | &rAbilities); | ||
163 | PRINTK_2(TRACE_MWAVE, | ||
164 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" | ||
165 | " retval %x from tp3780I_QueryAbilities\n", | ||
166 | retval); | ||
167 | if (retval == 0) { | ||
168 | if( copy_to_user(arg, &rAbilities, | ||
169 | sizeof(MW_ABILITIES)) ) | ||
170 | return -EFAULT; | ||
171 | } | ||
172 | PRINTK_2(TRACE_MWAVE, | ||
173 | "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" | ||
174 | " exit retval %x\n", | ||
175 | retval); | ||
176 | } | ||
177 | break; | ||
178 | |||
179 | case IOCTL_MW_READ_DATA: | ||
180 | case IOCTL_MW_READCLEAR_DATA: { | ||
181 | MW_READWRITE rReadData; | ||
182 | unsigned short __user *pusBuffer = NULL; | ||
183 | |||
184 | if( copy_from_user(&rReadData, arg, | ||
185 | sizeof(MW_READWRITE)) ) | ||
186 | return -EFAULT; | ||
187 | pusBuffer = (unsigned short __user *) (rReadData.pBuf); | ||
188 | |||
189 | PRINTK_4(TRACE_MWAVE, | ||
190 | "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," | ||
191 | " size %lx, ioarg %lx pusBuffer %p\n", | ||
192 | rReadData.ulDataLength, ioarg, pusBuffer); | ||
193 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | ||
194 | iocmd, | ||
195 | pusBuffer, | ||
196 | rReadData.ulDataLength, | ||
197 | rReadData.usDspAddress); | ||
198 | } | ||
199 | break; | ||
200 | |||
201 | case IOCTL_MW_READ_INST: { | ||
202 | MW_READWRITE rReadData; | ||
203 | unsigned short __user *pusBuffer = NULL; | ||
204 | |||
205 | if( copy_from_user(&rReadData, arg, | ||
206 | sizeof(MW_READWRITE)) ) | ||
207 | return -EFAULT; | ||
208 | pusBuffer = (unsigned short __user *) (rReadData.pBuf); | ||
209 | |||
210 | PRINTK_4(TRACE_MWAVE, | ||
211 | "mwavedd::mwave_ioctl IOCTL_MW_READ_INST," | ||
212 | " size %lx, ioarg %lx pusBuffer %p\n", | ||
213 | rReadData.ulDataLength / 2, ioarg, | ||
214 | pusBuffer); | ||
215 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | ||
216 | iocmd, pusBuffer, | ||
217 | rReadData.ulDataLength / 2, | ||
218 | rReadData.usDspAddress); | ||
219 | } | ||
220 | break; | ||
221 | |||
222 | case IOCTL_MW_WRITE_DATA: { | ||
223 | MW_READWRITE rWriteData; | ||
224 | unsigned short __user *pusBuffer = NULL; | ||
225 | |||
226 | if( copy_from_user(&rWriteData, arg, | ||
227 | sizeof(MW_READWRITE)) ) | ||
228 | return -EFAULT; | ||
229 | pusBuffer = (unsigned short __user *) (rWriteData.pBuf); | ||
230 | |||
231 | PRINTK_4(TRACE_MWAVE, | ||
232 | "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA," | ||
233 | " size %lx, ioarg %lx pusBuffer %p\n", | ||
234 | rWriteData.ulDataLength, ioarg, | ||
235 | pusBuffer); | ||
236 | retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, | ||
237 | iocmd, pusBuffer, | ||
238 | rWriteData.ulDataLength, | ||
239 | rWriteData.usDspAddress); | ||
240 | } | ||
241 | break; | ||
242 | |||
243 | case IOCTL_MW_WRITE_INST: { | ||
244 | MW_READWRITE rWriteData; | ||
245 | unsigned short __user *pusBuffer = NULL; | ||
246 | |||
247 | if( copy_from_user(&rWriteData, arg, | ||
248 | sizeof(MW_READWRITE)) ) | ||
249 | return -EFAULT; | ||
250 | pusBuffer = (unsigned short __user *)(rWriteData.pBuf); | ||
251 | |||
252 | PRINTK_4(TRACE_MWAVE, | ||
253 | "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST," | ||
254 | " size %lx, ioarg %lx pusBuffer %p\n", | ||
255 | rWriteData.ulDataLength, ioarg, | ||
256 | pusBuffer); | ||
257 | retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, | ||
258 | iocmd, pusBuffer, | ||
259 | rWriteData.ulDataLength, | ||
260 | rWriteData.usDspAddress); | ||
261 | } | ||
262 | break; | ||
263 | |||
264 | case IOCTL_MW_REGISTER_IPC: { | ||
265 | unsigned int ipcnum = (unsigned int) ioarg; | ||
266 | |||
267 | PRINTK_3(TRACE_MWAVE, | ||
268 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" | ||
269 | " ipcnum %x entry usIntCount %x\n", | ||
270 | ipcnum, | ||
271 | pDrvData->IPCs[ipcnum].usIntCount); | ||
272 | |||
273 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | ||
274 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
275 | "mwavedd::mwave_ioctl:" | ||
276 | " IOCTL_MW_REGISTER_IPC:" | ||
277 | " Error: Invalid ipcnum %x\n", | ||
278 | ipcnum); | ||
279 | return -EINVAL; | ||
280 | } | ||
281 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; | ||
282 | pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; | ||
283 | |||
284 | PRINTK_2(TRACE_MWAVE, | ||
285 | "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" | ||
286 | " ipcnum %x exit\n", | ||
287 | ipcnum); | ||
288 | } | ||
289 | break; | ||
290 | |||
291 | case IOCTL_MW_GET_IPC: { | ||
292 | unsigned int ipcnum = (unsigned int) ioarg; | ||
293 | |||
294 | PRINTK_3(TRACE_MWAVE, | ||
295 | "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC" | ||
296 | " ipcnum %x, usIntCount %x\n", | ||
297 | ipcnum, | ||
298 | pDrvData->IPCs[ipcnum].usIntCount); | ||
299 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | ||
300 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
301 | "mwavedd::mwave_ioctl:" | ||
302 | " IOCTL_MW_GET_IPC: Error:" | ||
303 | " Invalid ipcnum %x\n", ipcnum); | ||
304 | return -EINVAL; | ||
305 | } | ||
306 | |||
307 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | ||
308 | DECLARE_WAITQUEUE(wait, current); | ||
309 | |||
310 | PRINTK_2(TRACE_MWAVE, | ||
311 | "mwavedd::mwave_ioctl, thread for" | ||
312 | " ipc %x going to sleep\n", | ||
313 | ipcnum); | ||
314 | add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); | ||
315 | pDrvData->IPCs[ipcnum].bIsHere = TRUE; | ||
316 | set_current_state(TASK_INTERRUPTIBLE); | ||
317 | /* check whether an event was signalled by */ | ||
318 | /* the interrupt handler while we were gone */ | ||
319 | if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */ | ||
320 | pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */ | ||
321 | PRINTK_2(TRACE_MWAVE, | ||
322 | "mwavedd::mwave_ioctl" | ||
323 | " IOCTL_MW_GET_IPC ipcnum %x" | ||
324 | " handling first int\n", | ||
325 | ipcnum); | ||
326 | } else { /* either 1st int has not yet occurred, or we have already handled the first int */ | ||
327 | schedule(); | ||
328 | if (pDrvData->IPCs[ipcnum].usIntCount == 1) { | ||
329 | pDrvData->IPCs[ipcnum].usIntCount = 2; | ||
330 | } | ||
331 | PRINTK_2(TRACE_MWAVE, | ||
332 | "mwavedd::mwave_ioctl" | ||
333 | " IOCTL_MW_GET_IPC ipcnum %x" | ||
334 | " woke up and returning to" | ||
335 | " application\n", | ||
336 | ipcnum); | ||
337 | } | ||
338 | pDrvData->IPCs[ipcnum].bIsHere = FALSE; | ||
339 | remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); | ||
340 | set_current_state(TASK_RUNNING); | ||
341 | PRINTK_2(TRACE_MWAVE, | ||
342 | "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC," | ||
343 | " returning thread for ipc %x" | ||
344 | " processing\n", | ||
345 | ipcnum); | ||
346 | } | ||
347 | } | ||
348 | break; | ||
349 | |||
350 | case IOCTL_MW_UNREGISTER_IPC: { | ||
351 | unsigned int ipcnum = (unsigned int) ioarg; | ||
352 | |||
353 | PRINTK_2(TRACE_MWAVE, | ||
354 | "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC" | ||
355 | " ipcnum %x\n", | ||
356 | ipcnum); | ||
357 | if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { | ||
358 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
359 | "mwavedd::mwave_ioctl:" | ||
360 | " IOCTL_MW_UNREGISTER_IPC:" | ||
361 | " Error: Invalid ipcnum %x\n", | ||
362 | ipcnum); | ||
363 | return -EINVAL; | ||
364 | } | ||
365 | if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { | ||
366 | pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; | ||
367 | if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { | ||
368 | wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | break; | ||
373 | |||
374 | default: | ||
375 | PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" | ||
376 | " Error: Unrecognized iocmd %x\n", | ||
377 | iocmd); | ||
378 | return -ENOTTY; | ||
379 | break; | ||
380 | } /* switch */ | ||
381 | |||
382 | PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval); | ||
383 | |||
384 | return retval; | ||
385 | } | ||
386 | |||
387 | |||
388 | static ssize_t mwave_read(struct file *file, char __user *buf, size_t count, | ||
389 | loff_t * ppos) | ||
390 | { | ||
391 | PRINTK_5(TRACE_MWAVE, | ||
392 | "mwavedd::mwave_read entry file %p, buf %p, count %zx ppos %p\n", | ||
393 | file, buf, count, ppos); | ||
394 | |||
395 | return -EINVAL; | ||
396 | } | ||
397 | |||
398 | |||
399 | static ssize_t mwave_write(struct file *file, const char __user *buf, | ||
400 | size_t count, loff_t * ppos) | ||
401 | { | ||
402 | PRINTK_5(TRACE_MWAVE, | ||
403 | "mwavedd::mwave_write entry file %p, buf %p," | ||
404 | " count %zx ppos %p\n", | ||
405 | file, buf, count, ppos); | ||
406 | |||
407 | return -EINVAL; | ||
408 | } | ||
409 | |||
410 | |||
411 | static int register_serial_portandirq(unsigned int port, int irq) | ||
412 | { | ||
413 | struct serial_struct serial; | ||
414 | |||
415 | switch ( port ) { | ||
416 | case 0x3f8: | ||
417 | case 0x2f8: | ||
418 | case 0x3e8: | ||
419 | case 0x2e8: | ||
420 | /* OK */ | ||
421 | break; | ||
422 | default: | ||
423 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
424 | "mwavedd::register_serial_portandirq:" | ||
425 | " Error: Illegal port %x\n", port ); | ||
426 | return -1; | ||
427 | } /* switch */ | ||
428 | /* port is okay */ | ||
429 | |||
430 | switch ( irq ) { | ||
431 | case 3: | ||
432 | case 4: | ||
433 | case 5: | ||
434 | case 7: | ||
435 | /* OK */ | ||
436 | break; | ||
437 | default: | ||
438 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
439 | "mwavedd::register_serial_portandirq:" | ||
440 | " Error: Illegal irq %x\n", irq ); | ||
441 | return -1; | ||
442 | } /* switch */ | ||
443 | /* irq is okay */ | ||
444 | |||
445 | memset(&serial, 0, sizeof(serial)); | ||
446 | serial.port = port; | ||
447 | serial.irq = irq; | ||
448 | serial.flags = ASYNC_SHARE_IRQ; | ||
449 | |||
450 | return register_serial(&serial); | ||
451 | } | ||
452 | |||
453 | |||
454 | static struct file_operations mwave_fops = { | ||
455 | .owner = THIS_MODULE, | ||
456 | .read = mwave_read, | ||
457 | .write = mwave_write, | ||
458 | .ioctl = mwave_ioctl, | ||
459 | .open = mwave_open, | ||
460 | .release = mwave_close | ||
461 | }; | ||
462 | |||
463 | |||
464 | static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops }; | ||
465 | |||
466 | #if 0 /* totally b0rked */ | ||
467 | /* | ||
468 | * sysfs support <paulsch@us.ibm.com> | ||
469 | */ | ||
470 | |||
471 | struct device mwave_device; | ||
472 | |||
473 | /* Prevent code redundancy, create a macro for mwave_show_* functions. */ | ||
474 | #define mwave_show_function(attr_name, format_string, field) \ | ||
475 | static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \ | ||
476 | { \ | ||
477 | DSP_3780I_CONFIG_SETTINGS *pSettings = \ | ||
478 | &mwave_s_mdd.rBDData.rDspSettings; \ | ||
479 | return sprintf(buf, format_string, pSettings->field); \ | ||
480 | } | ||
481 | |||
482 | /* All of our attributes are read attributes. */ | ||
483 | #define mwave_dev_rd_attr(attr_name, format_string, field) \ | ||
484 | mwave_show_function(attr_name, format_string, field) \ | ||
485 | static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL) | ||
486 | |||
487 | mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma); | ||
488 | mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq); | ||
489 | mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO); | ||
490 | mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq); | ||
491 | mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO); | ||
492 | |||
493 | static struct device_attribute * const mwave_dev_attrs[] = { | ||
494 | &dev_attr_3780i_dma, | ||
495 | &dev_attr_3780i_irq, | ||
496 | &dev_attr_3780i_io, | ||
497 | &dev_attr_uart_irq, | ||
498 | &dev_attr_uart_io, | ||
499 | }; | ||
500 | #endif | ||
501 | |||
502 | /* | ||
503 | * mwave_init is called on module load | ||
504 | * | ||
505 | * mwave_exit is called on module unload | ||
506 | * mwave_exit is also used to clean up after an aborted mwave_init | ||
507 | */ | ||
508 | static void mwave_exit(void) | ||
509 | { | ||
510 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; | ||
511 | |||
512 | PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n"); | ||
513 | |||
514 | #if 0 | ||
515 | for (i = 0; i < pDrvData->nr_registered_attrs; i++) | ||
516 | device_remove_file(&mwave_device, mwave_dev_attrs[i]); | ||
517 | pDrvData->nr_registered_attrs = 0; | ||
518 | |||
519 | if (pDrvData->device_registered) { | ||
520 | device_unregister(&mwave_device); | ||
521 | pDrvData->device_registered = FALSE; | ||
522 | } | ||
523 | #endif | ||
524 | |||
525 | if ( pDrvData->sLine >= 0 ) { | ||
526 | unregister_serial(pDrvData->sLine); | ||
527 | } | ||
528 | if (pDrvData->bMwaveDevRegistered) { | ||
529 | misc_deregister(&mwave_misc_dev); | ||
530 | } | ||
531 | if (pDrvData->bDSPEnabled) { | ||
532 | tp3780I_DisableDSP(&pDrvData->rBDData); | ||
533 | } | ||
534 | if (pDrvData->bResourcesClaimed) { | ||
535 | tp3780I_ReleaseResources(&pDrvData->rBDData); | ||
536 | } | ||
537 | if (pDrvData->bBDInitialized) { | ||
538 | tp3780I_Cleanup(&pDrvData->rBDData); | ||
539 | } | ||
540 | |||
541 | PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit exit\n"); | ||
542 | } | ||
543 | |||
544 | module_exit(mwave_exit); | ||
545 | |||
546 | static int __init mwave_init(void) | ||
547 | { | ||
548 | int i; | ||
549 | int retval = 0; | ||
550 | pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; | ||
551 | |||
552 | PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n"); | ||
553 | |||
554 | memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA)); | ||
555 | |||
556 | pDrvData->bBDInitialized = FALSE; | ||
557 | pDrvData->bResourcesClaimed = FALSE; | ||
558 | pDrvData->bDSPEnabled = FALSE; | ||
559 | pDrvData->bDSPReset = FALSE; | ||
560 | pDrvData->bMwaveDevRegistered = FALSE; | ||
561 | pDrvData->sLine = -1; | ||
562 | |||
563 | for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) { | ||
564 | pDrvData->IPCs[i].bIsEnabled = FALSE; | ||
565 | pDrvData->IPCs[i].bIsHere = FALSE; | ||
566 | pDrvData->IPCs[i].usIntCount = 0; /* no ints received yet */ | ||
567 | init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue); | ||
568 | } | ||
569 | |||
570 | retval = tp3780I_InitializeBoardData(&pDrvData->rBDData); | ||
571 | PRINTK_2(TRACE_MWAVE, | ||
572 | "mwavedd::mwave_init, return from tp3780I_InitializeBoardData" | ||
573 | " retval %x\n", | ||
574 | retval); | ||
575 | if (retval) { | ||
576 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
577 | "mwavedd::mwave_init: Error:" | ||
578 | " Failed to initialize board data\n"); | ||
579 | goto cleanup_error; | ||
580 | } | ||
581 | pDrvData->bBDInitialized = TRUE; | ||
582 | |||
583 | retval = tp3780I_CalcResources(&pDrvData->rBDData); | ||
584 | PRINTK_2(TRACE_MWAVE, | ||
585 | "mwavedd::mwave_init, return from tp3780I_CalcResources" | ||
586 | " retval %x\n", | ||
587 | retval); | ||
588 | if (retval) { | ||
589 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
590 | "mwavedd:mwave_init: Error:" | ||
591 | " Failed to calculate resources\n"); | ||
592 | goto cleanup_error; | ||
593 | } | ||
594 | |||
595 | retval = tp3780I_ClaimResources(&pDrvData->rBDData); | ||
596 | PRINTK_2(TRACE_MWAVE, | ||
597 | "mwavedd::mwave_init, return from tp3780I_ClaimResources" | ||
598 | " retval %x\n", | ||
599 | retval); | ||
600 | if (retval) { | ||
601 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
602 | "mwavedd:mwave_init: Error:" | ||
603 | " Failed to claim resources\n"); | ||
604 | goto cleanup_error; | ||
605 | } | ||
606 | pDrvData->bResourcesClaimed = TRUE; | ||
607 | |||
608 | retval = tp3780I_EnableDSP(&pDrvData->rBDData); | ||
609 | PRINTK_2(TRACE_MWAVE, | ||
610 | "mwavedd::mwave_init, return from tp3780I_EnableDSP" | ||
611 | " retval %x\n", | ||
612 | retval); | ||
613 | if (retval) { | ||
614 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
615 | "mwavedd:mwave_init: Error:" | ||
616 | " Failed to enable DSP\n"); | ||
617 | goto cleanup_error; | ||
618 | } | ||
619 | pDrvData->bDSPEnabled = TRUE; | ||
620 | |||
621 | if (misc_register(&mwave_misc_dev) < 0) { | ||
622 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
623 | "mwavedd:mwave_init: Error:" | ||
624 | " Failed to register misc device\n"); | ||
625 | goto cleanup_error; | ||
626 | } | ||
627 | pDrvData->bMwaveDevRegistered = TRUE; | ||
628 | |||
629 | pDrvData->sLine = register_serial_portandirq( | ||
630 | pDrvData->rBDData.rDspSettings.usUartBaseIO, | ||
631 | pDrvData->rBDData.rDspSettings.usUartIrq | ||
632 | ); | ||
633 | if (pDrvData->sLine < 0) { | ||
634 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
635 | "mwavedd:mwave_init: Error:" | ||
636 | " Failed to register serial driver\n"); | ||
637 | goto cleanup_error; | ||
638 | } | ||
639 | /* uart is registered */ | ||
640 | |||
641 | #if 0 | ||
642 | /* sysfs */ | ||
643 | memset(&mwave_device, 0, sizeof (struct device)); | ||
644 | snprintf(mwave_device.bus_id, BUS_ID_SIZE, "mwave"); | ||
645 | |||
646 | if (device_register(&mwave_device)) | ||
647 | goto cleanup_error; | ||
648 | pDrvData->device_registered = TRUE; | ||
649 | for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) { | ||
650 | if(device_create_file(&mwave_device, mwave_dev_attrs[i])) { | ||
651 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
652 | "mwavedd:mwave_init: Error:" | ||
653 | " Failed to create sysfs file %s\n", | ||
654 | mwave_dev_attrs[i]->attr.name); | ||
655 | goto cleanup_error; | ||
656 | } | ||
657 | pDrvData->nr_registered_attrs++; | ||
658 | } | ||
659 | #endif | ||
660 | |||
661 | /* SUCCESS! */ | ||
662 | return 0; | ||
663 | |||
664 | cleanup_error: | ||
665 | PRINTK_ERROR(KERN_ERR_MWAVE | ||
666 | "mwavedd::mwave_init: Error:" | ||
667 | " Failed to initialize\n"); | ||
668 | mwave_exit(); /* clean up */ | ||
669 | |||
670 | return -EIO; | ||
671 | } | ||
672 | |||
673 | module_init(mwave_init); | ||
674 | |||