aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mwave
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/mwave')
-rw-r--r--drivers/char/mwave/3780i.c727
-rw-r--r--drivers/char/mwave/3780i.h362
-rw-r--r--drivers/char/mwave/Makefile15
-rw-r--r--drivers/char/mwave/README50
-rw-r--r--drivers/char/mwave/mwavedd.c674
-rw-r--r--drivers/char/mwave/mwavedd.h150
-rw-r--r--drivers/char/mwave/mwavepub.h89
-rw-r--r--drivers/char/mwave/smapi.c570
-rw-r--r--drivers/char/mwave/smapi.h80
-rw-r--r--drivers/char/mwave/tp3780i.c592
-rw-r--r--drivers/char/mwave/tp3780i.h103
11 files changed, 3412 insertions, 0 deletions
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
new file mode 100644
index 000000000000..ab00f51475df
--- /dev/null
+++ b/drivers/char/mwave/3780i.c
@@ -0,0 +1,727 @@
1/*
2*
3* 3780i.c -- helper routines for the 3780i DSP
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/config.h>
50#include <linux/kernel.h>
51#include <linux/unistd.h>
52#include <linux/delay.h>
53#include <linux/ioport.h>
54#include <linux/init.h>
55#include <linux/bitops.h>
56#include <asm/io.h>
57#include <asm/uaccess.h>
58#include <asm/system.h>
59#include <asm/irq.h>
60#include "smapi.h"
61#include "mwavedd.h"
62#include "3780i.h"
63
64static DEFINE_SPINLOCK(dsp_lock);
65static unsigned long flags;
66
67
68static void PaceMsaAccess(unsigned short usDspBaseIO)
69{
70 cond_resched();
71 udelay(100);
72 cond_resched();
73}
74
75unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
76 unsigned long ulMsaAddr)
77{
78 unsigned short val;
79
80 PRINTK_3(TRACE_3780I,
81 "3780i::dsp3780I_ReadMsaCfg entry usDspBaseIO %x ulMsaAddr %lx\n",
82 usDspBaseIO, ulMsaAddr);
83
84 spin_lock_irqsave(&dsp_lock, flags);
85 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
86 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
87 val = InWordDsp(DSP_MsaDataDSISHigh);
88 spin_unlock_irqrestore(&dsp_lock, flags);
89
90 PRINTK_2(TRACE_3780I, "3780i::dsp3780I_ReadMsaCfg exit val %x\n", val);
91
92 return val;
93}
94
95void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
96 unsigned long ulMsaAddr, unsigned short usValue)
97{
98
99 PRINTK_4(TRACE_3780I,
100 "3780i::dsp3780i_WriteMsaCfg entry usDspBaseIO %x ulMsaAddr %lx usValue %x\n",
101 usDspBaseIO, ulMsaAddr, usValue);
102
103 spin_lock_irqsave(&dsp_lock, flags);
104 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
105 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
106 OutWordDsp(DSP_MsaDataDSISHigh, usValue);
107 spin_unlock_irqrestore(&dsp_lock, flags);
108}
109
110void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
111 unsigned char ucValue)
112{
113 DSP_ISA_SLAVE_CONTROL rSlaveControl;
114 DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
115
116
117 PRINTK_4(TRACE_3780I,
118 "3780i::dsp3780i_WriteGenCfg entry usDspBaseIO %x uIndex %x ucValue %x\n",
119 usDspBaseIO, uIndex, ucValue);
120
121 MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
122
123 PRINTK_2(TRACE_3780I,
124 "3780i::dsp3780i_WriteGenCfg rSlaveControl %x\n",
125 MKBYTE(rSlaveControl));
126
127 rSlaveControl_Save = rSlaveControl;
128 rSlaveControl.ConfigMode = TRUE;
129
130 PRINTK_2(TRACE_3780I,
131 "3780i::dsp3780i_WriteGenCfg entry rSlaveControl+ConfigMode %x\n",
132 MKBYTE(rSlaveControl));
133
134 OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
135 OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
136 OutByteDsp(DSP_ConfigData, ucValue);
137 OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
138
139 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_WriteGenCfg exit\n");
140
141
142}
143
144unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
145 unsigned uIndex)
146{
147 DSP_ISA_SLAVE_CONTROL rSlaveControl;
148 DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
149 unsigned char ucValue;
150
151
152 PRINTK_3(TRACE_3780I,
153 "3780i::dsp3780i_ReadGenCfg entry usDspBaseIO %x uIndex %x\n",
154 usDspBaseIO, uIndex);
155
156 MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
157 rSlaveControl_Save = rSlaveControl;
158 rSlaveControl.ConfigMode = TRUE;
159 OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
160 OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
161 ucValue = InByteDsp(DSP_ConfigData);
162 OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
163
164 PRINTK_2(TRACE_3780I,
165 "3780i::dsp3780i_ReadGenCfg exit ucValue %x\n", ucValue);
166
167
168 return ucValue;
169}
170
171int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
172 unsigned short *pIrqMap,
173 unsigned short *pDmaMap)
174{
175 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
176 int i;
177 DSP_UART_CFG_1 rUartCfg1;
178 DSP_UART_CFG_2 rUartCfg2;
179 DSP_HBRIDGE_CFG_1 rHBridgeCfg1;
180 DSP_HBRIDGE_CFG_2 rHBridgeCfg2;
181 DSP_BUSMASTER_CFG_1 rBusmasterCfg1;
182 DSP_BUSMASTER_CFG_2 rBusmasterCfg2;
183 DSP_ISA_PROT_CFG rIsaProtCfg;
184 DSP_POWER_MGMT_CFG rPowerMgmtCfg;
185 DSP_HBUS_TIMER_CFG rHBusTimerCfg;
186 DSP_LBUS_TIMEOUT_DISABLE rLBusTimeoutDisable;
187 DSP_CHIP_RESET rChipReset;
188 DSP_CLOCK_CONTROL_1 rClockControl1;
189 DSP_CLOCK_CONTROL_2 rClockControl2;
190 DSP_ISA_SLAVE_CONTROL rSlaveControl;
191 DSP_HBRIDGE_CONTROL rHBridgeControl;
192 unsigned short ChipID = 0;
193 unsigned short tval;
194
195
196 PRINTK_2(TRACE_3780I,
197 "3780i::dsp3780I_EnableDSP entry pSettings->bDSPEnabled %x\n",
198 pSettings->bDSPEnabled);
199
200
201 if (!pSettings->bDSPEnabled) {
202 PRINTK_ERROR( KERN_ERR "3780i::dsp3780I_EnableDSP: Error: DSP not enabled. Aborting.\n" );
203 return -EIO;
204 }
205
206
207 PRINTK_2(TRACE_3780I,
208 "3780i::dsp3780i_EnableDSP entry pSettings->bModemEnabled %x\n",
209 pSettings->bModemEnabled);
210
211 if (pSettings->bModemEnabled) {
212 rUartCfg1.Reserved = rUartCfg2.Reserved = 0;
213 rUartCfg1.IrqActiveLow = pSettings->bUartIrqActiveLow;
214 rUartCfg1.IrqPulse = pSettings->bUartIrqPulse;
215 rUartCfg1.Irq =
216 (unsigned char) pIrqMap[pSettings->usUartIrq];
217 switch (pSettings->usUartBaseIO) {
218 case 0x03F8:
219 rUartCfg1.BaseIO = 0;
220 break;
221 case 0x02F8:
222 rUartCfg1.BaseIO = 1;
223 break;
224 case 0x03E8:
225 rUartCfg1.BaseIO = 2;
226 break;
227 case 0x02E8:
228 rUartCfg1.BaseIO = 3;
229 break;
230 }
231 rUartCfg2.Enable = TRUE;
232 }
233
234 rHBridgeCfg1.Reserved = rHBridgeCfg2.Reserved = 0;
235 rHBridgeCfg1.IrqActiveLow = pSettings->bDspIrqActiveLow;
236 rHBridgeCfg1.IrqPulse = pSettings->bDspIrqPulse;
237 rHBridgeCfg1.Irq = (unsigned char) pIrqMap[pSettings->usDspIrq];
238 rHBridgeCfg1.AccessMode = 1;
239 rHBridgeCfg2.Enable = TRUE;
240
241
242 rBusmasterCfg2.Reserved = 0;
243 rBusmasterCfg1.Dma = (unsigned char) pDmaMap[pSettings->usDspDma];
244 rBusmasterCfg1.NumTransfers =
245 (unsigned char) pSettings->usNumTransfers;
246 rBusmasterCfg1.ReRequest = (unsigned char) pSettings->usReRequest;
247 rBusmasterCfg1.MEMCS16 = pSettings->bEnableMEMCS16;
248 rBusmasterCfg2.IsaMemCmdWidth =
249 (unsigned char) pSettings->usIsaMemCmdWidth;
250
251
252 rIsaProtCfg.Reserved = 0;
253 rIsaProtCfg.GateIOCHRDY = pSettings->bGateIOCHRDY;
254
255 rPowerMgmtCfg.Reserved = 0;
256 rPowerMgmtCfg.Enable = pSettings->bEnablePwrMgmt;
257
258 rHBusTimerCfg.LoadValue =
259 (unsigned char) pSettings->usHBusTimerLoadValue;
260
261 rLBusTimeoutDisable.Reserved = 0;
262 rLBusTimeoutDisable.DisableTimeout =
263 pSettings->bDisableLBusTimeout;
264
265 MKWORD(rChipReset) = ~pSettings->usChipletEnable;
266
267 rClockControl1.Reserved1 = rClockControl1.Reserved2 = 0;
268 rClockControl1.N_Divisor = pSettings->usN_Divisor;
269 rClockControl1.M_Multiplier = pSettings->usM_Multiplier;
270
271 rClockControl2.Reserved = 0;
272 rClockControl2.PllBypass = pSettings->bPllBypass;
273
274 /* Issue a soft reset to the chip */
275 /* Note: Since we may be coming in with 3780i clocks suspended, we must keep
276 * soft-reset active for 10ms.
277 */
278 rSlaveControl.ClockControl = 0;
279 rSlaveControl.SoftReset = TRUE;
280 rSlaveControl.ConfigMode = FALSE;
281 rSlaveControl.Reserved = 0;
282
283 PRINTK_4(TRACE_3780I,
284 "3780i::dsp3780i_EnableDSP usDspBaseIO %x index %x taddr %x\n",
285 usDspBaseIO, DSP_IsaSlaveControl,
286 usDspBaseIO + DSP_IsaSlaveControl);
287
288 PRINTK_2(TRACE_3780I,
289 "3780i::dsp3780i_EnableDSP rSlaveContrl %x\n",
290 MKWORD(rSlaveControl));
291
292 spin_lock_irqsave(&dsp_lock, flags);
293 OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
294 MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
295
296 PRINTK_2(TRACE_3780I,
297 "3780i::dsp3780i_EnableDSP rSlaveControl 2 %x\n", tval);
298
299
300 for (i = 0; i < 11; i++)
301 udelay(2000);
302
303 rSlaveControl.SoftReset = FALSE;
304 OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
305
306 MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
307
308 PRINTK_2(TRACE_3780I,
309 "3780i::dsp3780i_EnableDSP rSlaveControl 3 %x\n", tval);
310
311
312 /* Program our general configuration registers */
313 WriteGenCfg(DSP_HBridgeCfg1Index, MKBYTE(rHBridgeCfg1));
314 WriteGenCfg(DSP_HBridgeCfg2Index, MKBYTE(rHBridgeCfg2));
315 WriteGenCfg(DSP_BusMasterCfg1Index, MKBYTE(rBusmasterCfg1));
316 WriteGenCfg(DSP_BusMasterCfg2Index, MKBYTE(rBusmasterCfg2));
317 WriteGenCfg(DSP_IsaProtCfgIndex, MKBYTE(rIsaProtCfg));
318 WriteGenCfg(DSP_PowerMgCfgIndex, MKBYTE(rPowerMgmtCfg));
319 WriteGenCfg(DSP_HBusTimerCfgIndex, MKBYTE(rHBusTimerCfg));
320
321 if (pSettings->bModemEnabled) {
322 WriteGenCfg(DSP_UartCfg1Index, MKBYTE(rUartCfg1));
323 WriteGenCfg(DSP_UartCfg2Index, MKBYTE(rUartCfg2));
324 }
325
326
327 rHBridgeControl.EnableDspInt = FALSE;
328 rHBridgeControl.MemAutoInc = TRUE;
329 rHBridgeControl.IoAutoInc = FALSE;
330 rHBridgeControl.DiagnosticMode = FALSE;
331
332 PRINTK_3(TRACE_3780I,
333 "3780i::dsp3780i_EnableDSP DSP_HBridgeControl %x rHBridgeControl %x\n",
334 DSP_HBridgeControl, MKWORD(rHBridgeControl));
335
336 OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
337 spin_unlock_irqrestore(&dsp_lock, flags);
338 WriteMsaCfg(DSP_LBusTimeoutDisable, MKWORD(rLBusTimeoutDisable));
339 WriteMsaCfg(DSP_ClockControl_1, MKWORD(rClockControl1));
340 WriteMsaCfg(DSP_ClockControl_2, MKWORD(rClockControl2));
341 WriteMsaCfg(DSP_ChipReset, MKWORD(rChipReset));
342
343 ChipID = ReadMsaCfg(DSP_ChipID);
344
345 PRINTK_2(TRACE_3780I,
346 "3780i::dsp3780I_EnableDSP exiting bRC=TRUE, ChipID %x\n",
347 ChipID);
348
349 return 0;
350}
351
352int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
353{
354 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
355 DSP_ISA_SLAVE_CONTROL rSlaveControl;
356
357
358 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_DisableDSP entry\n");
359
360 rSlaveControl.ClockControl = 0;
361 rSlaveControl.SoftReset = TRUE;
362 rSlaveControl.ConfigMode = FALSE;
363 rSlaveControl.Reserved = 0;
364 spin_lock_irqsave(&dsp_lock, flags);
365 OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
366
367 udelay(5);
368
369 rSlaveControl.ClockControl = 1;
370 OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
371 spin_unlock_irqrestore(&dsp_lock, flags);
372
373 udelay(5);
374
375
376 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_DisableDSP exit\n");
377
378 return 0;
379}
380
381int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
382{
383 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
384 DSP_BOOT_DOMAIN rBootDomain;
385 DSP_HBRIDGE_CONTROL rHBridgeControl;
386
387
388 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset entry\n");
389
390 spin_lock_irqsave(&dsp_lock, flags);
391 /* Mask DSP to PC interrupt */
392 MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
393
394 PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rHBridgeControl %x\n",
395 MKWORD(rHBridgeControl));
396
397 rHBridgeControl.EnableDspInt = FALSE;
398 OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
399 spin_unlock_irqrestore(&dsp_lock, flags);
400
401 /* Reset the core via the boot domain register */
402 rBootDomain.ResetCore = TRUE;
403 rBootDomain.Halt = TRUE;
404 rBootDomain.NMI = TRUE;
405 rBootDomain.Reserved = 0;
406
407 PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rBootDomain %x\n",
408 MKWORD(rBootDomain));
409
410 WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
411
412 /* Reset all the chiplets and then reactivate them */
413 WriteMsaCfg(DSP_ChipReset, 0xFFFF);
414 udelay(5);
415 WriteMsaCfg(DSP_ChipReset,
416 (unsigned short) (~pSettings->usChipletEnable));
417
418
419 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset exit bRC=0\n");
420
421 return 0;
422}
423
424
425int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
426{
427 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
428 DSP_BOOT_DOMAIN rBootDomain;
429 DSP_HBRIDGE_CONTROL rHBridgeControl;
430
431
432 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run entry\n");
433
434
435 /* Transition the core to a running state */
436 rBootDomain.ResetCore = TRUE;
437 rBootDomain.Halt = FALSE;
438 rBootDomain.NMI = TRUE;
439 rBootDomain.Reserved = 0;
440 WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
441
442 udelay(5);
443
444 rBootDomain.ResetCore = FALSE;
445 WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
446 udelay(5);
447
448 rBootDomain.NMI = FALSE;
449 WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
450 udelay(5);
451
452 /* Enable DSP to PC interrupt */
453 spin_lock_irqsave(&dsp_lock, flags);
454 MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
455 rHBridgeControl.EnableDspInt = TRUE;
456
457 PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Run rHBridgeControl %x\n",
458 MKWORD(rHBridgeControl));
459
460 OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
461 spin_unlock_irqrestore(&dsp_lock, flags);
462
463
464 PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run exit bRC=TRUE\n");
465
466 return 0;
467}
468
469
470int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
471 unsigned uCount, unsigned long ulDSPAddr)
472{
473 unsigned short __user *pusBuffer = pvBuffer;
474 unsigned short val;
475
476
477 PRINTK_5(TRACE_3780I,
478 "3780i::dsp3780I_ReadDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
479 usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
480
481
482 /* Set the initial MSA address. No adjustments need to be made to data store addresses */
483 spin_lock_irqsave(&dsp_lock, flags);
484 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
485 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
486 spin_unlock_irqrestore(&dsp_lock, flags);
487
488 /* Transfer the memory block */
489 while (uCount-- != 0) {
490 spin_lock_irqsave(&dsp_lock, flags);
491 val = InWordDsp(DSP_MsaDataDSISHigh);
492 spin_unlock_irqrestore(&dsp_lock, flags);
493 if(put_user(val, pusBuffer++))
494 return -EFAULT;
495
496 PRINTK_3(TRACE_3780I,
497 "3780I::dsp3780I_ReadDStore uCount %x val %x\n",
498 uCount, val);
499
500 PaceMsaAccess(usDspBaseIO);
501 }
502
503
504 PRINTK_1(TRACE_3780I,
505 "3780I::dsp3780I_ReadDStore exit bRC=TRUE\n");
506
507 return 0;
508}
509
510int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
511 void __user *pvBuffer, unsigned uCount,
512 unsigned long ulDSPAddr)
513{
514 unsigned short __user *pusBuffer = pvBuffer;
515 unsigned short val;
516
517
518 PRINTK_5(TRACE_3780I,
519 "3780i::dsp3780I_ReadAndDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
520 usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
521
522
523 /* Set the initial MSA address. No adjustments need to be made to data store addresses */
524 spin_lock_irqsave(&dsp_lock, flags);
525 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
526 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
527 spin_unlock_irqrestore(&dsp_lock, flags);
528
529 /* Transfer the memory block */
530 while (uCount-- != 0) {
531 spin_lock_irqsave(&dsp_lock, flags);
532 val = InWordDsp(DSP_ReadAndClear);
533 spin_unlock_irqrestore(&dsp_lock, flags);
534 if(put_user(val, pusBuffer++))
535 return -EFAULT;
536
537 PRINTK_3(TRACE_3780I,
538 "3780I::dsp3780I_ReadAndCleanDStore uCount %x val %x\n",
539 uCount, val);
540
541 PaceMsaAccess(usDspBaseIO);
542 }
543
544
545 PRINTK_1(TRACE_3780I,
546 "3780I::dsp3780I_ReadAndClearDStore exit bRC=TRUE\n");
547
548 return 0;
549}
550
551
552int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
553 unsigned uCount, unsigned long ulDSPAddr)
554{
555 unsigned short __user *pusBuffer = pvBuffer;
556
557
558 PRINTK_5(TRACE_3780I,
559 "3780i::dsp3780D_WriteDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
560 usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
561
562
563 /* Set the initial MSA address. No adjustments need to be made to data store addresses */
564 spin_lock_irqsave(&dsp_lock, flags);
565 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
566 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
567 spin_unlock_irqrestore(&dsp_lock, flags);
568
569 /* Transfer the memory block */
570 while (uCount-- != 0) {
571 unsigned short val;
572 if(get_user(val, pusBuffer++))
573 return -EFAULT;
574 spin_lock_irqsave(&dsp_lock, flags);
575 OutWordDsp(DSP_MsaDataDSISHigh, val);
576 spin_unlock_irqrestore(&dsp_lock, flags);
577
578 PRINTK_3(TRACE_3780I,
579 "3780I::dsp3780I_WriteDStore uCount %x val %x\n",
580 uCount, val);
581
582 PaceMsaAccess(usDspBaseIO);
583 }
584
585
586 PRINTK_1(TRACE_3780I,
587 "3780I::dsp3780D_WriteDStore exit bRC=TRUE\n");
588
589 return 0;
590}
591
592
593int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
594 unsigned uCount, unsigned long ulDSPAddr)
595{
596 unsigned short __user *pusBuffer = pvBuffer;
597
598 PRINTK_5(TRACE_3780I,
599 "3780i::dsp3780I_ReadIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
600 usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
601
602 /*
603 * Set the initial MSA address. To convert from an instruction store
604 * address to an MSA address
605 * shift the address two bits to the left and set bit 22
606 */
607 ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
608 spin_lock_irqsave(&dsp_lock, flags);
609 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
610 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
611 spin_unlock_irqrestore(&dsp_lock, flags);
612
613 /* Transfer the memory block */
614 while (uCount-- != 0) {
615 unsigned short val_lo, val_hi;
616 spin_lock_irqsave(&dsp_lock, flags);
617 val_lo = InWordDsp(DSP_MsaDataISLow);
618 val_hi = InWordDsp(DSP_MsaDataDSISHigh);
619 spin_unlock_irqrestore(&dsp_lock, flags);
620 if(put_user(val_lo, pusBuffer++))
621 return -EFAULT;
622 if(put_user(val_hi, pusBuffer++))
623 return -EFAULT;
624
625 PRINTK_4(TRACE_3780I,
626 "3780I::dsp3780I_ReadIStore uCount %x val_lo %x val_hi %x\n",
627 uCount, val_lo, val_hi);
628
629 PaceMsaAccess(usDspBaseIO);
630
631 }
632
633 PRINTK_1(TRACE_3780I,
634 "3780I::dsp3780I_ReadIStore exit bRC=TRUE\n");
635
636 return 0;
637}
638
639
640int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
641 unsigned uCount, unsigned long ulDSPAddr)
642{
643 unsigned short __user *pusBuffer = pvBuffer;
644
645 PRINTK_5(TRACE_3780I,
646 "3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
647 usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
648
649
650 /*
651 * Set the initial MSA address. To convert from an instruction store
652 * address to an MSA address
653 * shift the address two bits to the left and set bit 22
654 */
655 ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
656 spin_lock_irqsave(&dsp_lock, flags);
657 OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
658 OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
659 spin_unlock_irqrestore(&dsp_lock, flags);
660
661 /* Transfer the memory block */
662 while (uCount-- != 0) {
663 unsigned short val_lo, val_hi;
664 if(get_user(val_lo, pusBuffer++))
665 return -EFAULT;
666 if(get_user(val_hi, pusBuffer++))
667 return -EFAULT;
668 spin_lock_irqsave(&dsp_lock, flags);
669 OutWordDsp(DSP_MsaDataISLow, val_lo);
670 OutWordDsp(DSP_MsaDataDSISHigh, val_hi);
671 spin_unlock_irqrestore(&dsp_lock, flags);
672
673 PRINTK_4(TRACE_3780I,
674 "3780I::dsp3780I_WriteIStore uCount %x val_lo %x val_hi %x\n",
675 uCount, val_lo, val_hi);
676
677 PaceMsaAccess(usDspBaseIO);
678
679 }
680
681 PRINTK_1(TRACE_3780I,
682 "3780I::dsp3780I_WriteIStore exit bRC=TRUE\n");
683
684 return 0;
685}
686
687
688int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
689 unsigned short *pusIPCSource)
690{
691 DSP_HBRIDGE_CONTROL rHBridgeControl;
692 unsigned short temp;
693
694
695 PRINTK_3(TRACE_3780I,
696 "3780i::dsp3780I_GetIPCSource entry usDspBaseIO %x pusIPCSource %p\n",
697 usDspBaseIO, pusIPCSource);
698
699 /*
700 * Disable DSP to PC interrupts, read the interrupt register,
701 * clear the pending IPC bits, and reenable DSP to PC interrupts
702 */
703 spin_lock_irqsave(&dsp_lock, flags);
704 MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
705 rHBridgeControl.EnableDspInt = FALSE;
706 OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
707
708 *pusIPCSource = InWordDsp(DSP_Interrupt);
709 temp = (unsigned short) ~(*pusIPCSource);
710
711 PRINTK_3(TRACE_3780I,
712 "3780i::dsp3780I_GetIPCSource, usIPCSource %x ~ %x\n",
713 *pusIPCSource, temp);
714
715 OutWordDsp(DSP_Interrupt, (unsigned short) ~(*pusIPCSource));
716
717 rHBridgeControl.EnableDspInt = TRUE;
718 OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
719 spin_unlock_irqrestore(&dsp_lock, flags);
720
721
722 PRINTK_2(TRACE_3780I,
723 "3780i::dsp3780I_GetIPCSource exit usIPCSource %x\n",
724 *pusIPCSource);
725
726 return 0;
727}
diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
new file mode 100644
index 000000000000..3e7d020d1bf4
--- /dev/null
+++ b/drivers/char/mwave/3780i.h
@@ -0,0 +1,362 @@
1/*
2*
3* 3780i.h -- declarations for 3780i.c
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#ifndef _LINUX_3780I_H
50#define _LINUX_3780I_H
51
52#include <asm/io.h>
53
54/* DSP I/O port offsets and definitions */
55#define DSP_IsaSlaveControl 0x0000 /* ISA slave control register */
56#define DSP_IsaSlaveStatus 0x0001 /* ISA slave status register */
57#define DSP_ConfigAddress 0x0002 /* General config address register */
58#define DSP_ConfigData 0x0003 /* General config data register */
59#define DSP_HBridgeControl 0x0002 /* HBridge control register */
60#define DSP_MsaAddrLow 0x0004 /* MSP System Address, low word */
61#define DSP_MsaAddrHigh 0x0006 /* MSP System Address, high word */
62#define DSP_MsaDataDSISHigh 0x0008 /* MSA data register: d-store word or high byte of i-store */
63#define DSP_MsaDataISLow 0x000A /* MSA data register: low word of i-store */
64#define DSP_ReadAndClear 0x000C /* MSA read and clear data register */
65#define DSP_Interrupt 0x000E /* Interrupt register (IPC source) */
66
67typedef struct {
68 unsigned char ClockControl:1; /* RW: Clock control: 0=normal, 1=stop 3780i clocks */
69 unsigned char SoftReset:1; /* RW: Soft reset 0=normal, 1=soft reset active */
70 unsigned char ConfigMode:1; /* RW: Configuration mode, 0=normal, 1=config mode */
71 unsigned char Reserved:5; /* 0: Reserved */
72} DSP_ISA_SLAVE_CONTROL;
73
74
75typedef struct {
76 unsigned short EnableDspInt:1; /* RW: Enable DSP to X86 ISA interrupt 0=mask it, 1=enable it */
77 unsigned short MemAutoInc:1; /* RW: Memory address auto increment, 0=disable, 1=enable */
78 unsigned short IoAutoInc:1; /* RW: I/O address auto increment, 0=disable, 1=enable */
79 unsigned short DiagnosticMode:1; /* RW: Disgnostic mode 0=nromal, 1=diagnostic mode */
80 unsigned short IsaPacingTimer:12; /* R: ISA access pacing timer: count of core cycles stolen */
81} DSP_HBRIDGE_CONTROL;
82
83
84/* DSP register indexes used with the configuration register address (index) register */
85#define DSP_UartCfg1Index 0x0003 /* UART config register 1 */
86#define DSP_UartCfg2Index 0x0004 /* UART config register 2 */
87#define DSP_HBridgeCfg1Index 0x0007 /* HBridge config register 1 */
88#define DSP_HBridgeCfg2Index 0x0008 /* HBridge config register 2 */
89#define DSP_BusMasterCfg1Index 0x0009 /* ISA bus master config register 1 */
90#define DSP_BusMasterCfg2Index 0x000A /* ISA bus master config register 2 */
91#define DSP_IsaProtCfgIndex 0x000F /* ISA protocol control register */
92#define DSP_PowerMgCfgIndex 0x0010 /* Low poser suspend/resume enable */
93#define DSP_HBusTimerCfgIndex 0x0011 /* HBUS timer load value */
94
95typedef struct {
96 unsigned char IrqActiveLow:1; /* RW: IRQ active high or low: 0=high, 1=low */
97 unsigned char IrqPulse:1; /* RW: IRQ pulse or level: 0=level, 1=pulse */
98 unsigned char Irq:3; /* RW: IRQ selection */
99 unsigned char BaseIO:2; /* RW: Base I/O selection */
100 unsigned char Reserved:1; /* 0: Reserved */
101} DSP_UART_CFG_1;
102
103typedef struct {
104 unsigned char Enable:1; /* RW: Enable I/O and IRQ: 0=FALSE, 1=TRUE */
105 unsigned char Reserved:7; /* 0: Reserved */
106} DSP_UART_CFG_2;
107
108typedef struct {
109 unsigned char IrqActiveLow:1; /* RW: IRQ active high=0 or low=1 */
110 unsigned char IrqPulse:1; /* RW: IRQ pulse=1 or level=0 */
111 unsigned char Irq:3; /* RW: IRQ selection */
112 unsigned char AccessMode:1; /* RW: 16-bit register access method 0=byte, 1=word */
113 unsigned char Reserved:2; /* 0: Reserved */
114} DSP_HBRIDGE_CFG_1;
115
116typedef struct {
117 unsigned char Enable:1; /* RW: enable I/O and IRQ: 0=FALSE, 1=TRUE */
118 unsigned char Reserved:7; /* 0: Reserved */
119} DSP_HBRIDGE_CFG_2;
120
121
122typedef struct {
123 unsigned char Dma:3; /* RW: DMA channel selection */
124 unsigned char NumTransfers:2; /* RW: Maximum # of transfers once being granted the ISA bus */
125 unsigned char ReRequest:2; /* RW: Minumum delay between releasing the ISA bus and requesting it again */
126 unsigned char MEMCS16:1; /* RW: ISA signal MEMCS16: 0=disabled, 1=enabled */
127} DSP_BUSMASTER_CFG_1;
128
129typedef struct {
130 unsigned char IsaMemCmdWidth:2; /* RW: ISA memory command width */
131 unsigned char Reserved:6; /* 0: Reserved */
132} DSP_BUSMASTER_CFG_2;
133
134
135typedef struct {
136 unsigned char GateIOCHRDY:1; /* RW: Enable IOCHRDY gating: 0=FALSE, 1=TRUE */
137 unsigned char Reserved:7; /* 0: Reserved */
138} DSP_ISA_PROT_CFG;
139
140typedef struct {
141 unsigned char Enable:1; /* RW: Enable low power suspend/resume 0=FALSE, 1=TRUE */
142 unsigned char Reserved:7; /* 0: Reserved */
143} DSP_POWER_MGMT_CFG;
144
145typedef struct {
146 unsigned char LoadValue:8; /* RW: HBUS timer load value */
147} DSP_HBUS_TIMER_CFG;
148
149
150
151/* DSP registers that exist in MSA I/O space */
152#define DSP_ChipID 0x80000000
153#define DSP_MspBootDomain 0x80000580
154#define DSP_LBusTimeoutDisable 0x80000580
155#define DSP_ClockControl_1 0x8000058A
156#define DSP_ClockControl_2 0x8000058C
157#define DSP_ChipReset 0x80000588
158#define DSP_GpioModeControl_15_8 0x80000082
159#define DSP_GpioDriverEnable_15_8 0x80000076
160#define DSP_GpioOutputData_15_8 0x80000072
161
162typedef struct {
163 unsigned short NMI:1; /* RW: non maskable interrupt */
164 unsigned short Halt:1; /* RW: Halt MSP clock */
165 unsigned short ResetCore:1; /* RW: Reset MSP core interface */
166 unsigned short Reserved:13; /* 0: Reserved */
167} DSP_BOOT_DOMAIN;
168
169typedef struct {
170 unsigned short DisableTimeout:1; /* RW: Disable LBus timeout */
171 unsigned short Reserved:15; /* 0: Reserved */
172} DSP_LBUS_TIMEOUT_DISABLE;
173
174typedef struct {
175 unsigned short Memory:1; /* RW: Reset memory interface */
176 unsigned short SerialPort1:1; /* RW: Reset serial port 1 interface */
177 unsigned short SerialPort2:1; /* RW: Reset serial port 2 interface */
178 unsigned short SerialPort3:1; /* RW: Reset serial port 3 interface */
179 unsigned short Gpio:1; /* RW: Reset GPIO interface */
180 unsigned short Dma:1; /* RW: Reset DMA interface */
181 unsigned short SoundBlaster:1; /* RW: Reset soundblaster interface */
182 unsigned short Uart:1; /* RW: Reset UART interface */
183 unsigned short Midi:1; /* RW: Reset MIDI interface */
184 unsigned short IsaMaster:1; /* RW: Reset ISA master interface */
185 unsigned short Reserved:6; /* 0: Reserved */
186} DSP_CHIP_RESET;
187
188typedef struct {
189 unsigned short N_Divisor:6; /* RW: (N) PLL output clock divisor */
190 unsigned short Reserved1:2; /* 0: reserved */
191 unsigned short M_Multiplier:6; /* RW: (M) PLL feedback clock multiplier */
192 unsigned short Reserved2:2; /* 0: reserved */
193} DSP_CLOCK_CONTROL_1;
194
195typedef struct {
196 unsigned short PllBypass:1; /* RW: PLL Bypass */
197 unsigned short Reserved:15; /* 0: Reserved */
198} DSP_CLOCK_CONTROL_2;
199
200typedef struct {
201 unsigned short Latch8:1;
202 unsigned short Latch9:1;
203 unsigned short Latch10:1;
204 unsigned short Latch11:1;
205 unsigned short Latch12:1;
206 unsigned short Latch13:1;
207 unsigned short Latch14:1;
208 unsigned short Latch15:1;
209 unsigned short Mask8:1;
210 unsigned short Mask9:1;
211 unsigned short Mask10:1;
212 unsigned short Mask11:1;
213 unsigned short Mask12:1;
214 unsigned short Mask13:1;
215 unsigned short Mask14:1;
216 unsigned short Mask15:1;
217} DSP_GPIO_OUTPUT_DATA_15_8;
218
219typedef struct {
220 unsigned short Enable8:1;
221 unsigned short Enable9:1;
222 unsigned short Enable10:1;
223 unsigned short Enable11:1;
224 unsigned short Enable12:1;
225 unsigned short Enable13:1;
226 unsigned short Enable14:1;
227 unsigned short Enable15:1;
228 unsigned short Mask8:1;
229 unsigned short Mask9:1;
230 unsigned short Mask10:1;
231 unsigned short Mask11:1;
232 unsigned short Mask12:1;
233 unsigned short Mask13:1;
234 unsigned short Mask14:1;
235 unsigned short Mask15:1;
236} DSP_GPIO_DRIVER_ENABLE_15_8;
237
238typedef struct {
239 unsigned short GpioMode8:2;
240 unsigned short GpioMode9:2;
241 unsigned short GpioMode10:2;
242 unsigned short GpioMode11:2;
243 unsigned short GpioMode12:2;
244 unsigned short GpioMode13:2;
245 unsigned short GpioMode14:2;
246 unsigned short GpioMode15:2;
247} DSP_GPIO_MODE_15_8;
248
249/* Component masks that are defined in dspmgr.h */
250#define MW_ADC_MASK 0x0001
251#define MW_AIC2_MASK 0x0006
252#define MW_MIDI_MASK 0x0008
253#define MW_CDDAC_MASK 0x8001
254#define MW_AIC1_MASK 0xE006
255#define MW_UART_MASK 0xE00A
256#define MW_ACI_MASK 0xE00B
257
258/*
259* Definition of 3780i configuration structure. Unless otherwise stated,
260* these values are provided as input to the 3780i support layer. At present,
261* the only values maintained by the 3780i support layer are the saved UART
262* registers.
263*/
264typedef struct _DSP_3780I_CONFIG_SETTINGS {
265
266 /* Location of base configuration register */
267 unsigned short usBaseConfigIO;
268
269 /* Enables for various DSP components */
270 int bDSPEnabled;
271 int bModemEnabled;
272 int bInterruptClaimed;
273
274 /* IRQ, DMA, and Base I/O addresses for various DSP components */
275 unsigned short usDspIrq;
276 unsigned short usDspDma;
277 unsigned short usDspBaseIO;
278 unsigned short usUartIrq;
279 unsigned short usUartBaseIO;
280
281 /* IRQ modes for various DSP components */
282 int bDspIrqActiveLow;
283 int bUartIrqActiveLow;
284 int bDspIrqPulse;
285 int bUartIrqPulse;
286
287 /* Card abilities */
288 unsigned uIps;
289 unsigned uDStoreSize;
290 unsigned uIStoreSize;
291 unsigned uDmaBandwidth;
292
293 /* Adapter specific 3780i settings */
294 unsigned short usNumTransfers;
295 unsigned short usReRequest;
296 int bEnableMEMCS16;
297 unsigned short usIsaMemCmdWidth;
298 int bGateIOCHRDY;
299 int bEnablePwrMgmt;
300 unsigned short usHBusTimerLoadValue;
301 int bDisableLBusTimeout;
302 unsigned short usN_Divisor;
303 unsigned short usM_Multiplier;
304 int bPllBypass;
305 unsigned short usChipletEnable; /* Used with the chip reset register to enable specific chiplets */
306
307 /* Saved UART registers. These are maintained by the 3780i support layer. */
308 int bUartSaved; /* True after a successful save of the UART registers */
309 unsigned char ucIER; /* Interrupt enable register */
310 unsigned char ucFCR; /* FIFO control register */
311 unsigned char ucLCR; /* Line control register */
312 unsigned char ucMCR; /* Modem control register */
313 unsigned char ucSCR; /* Scratch register */
314 unsigned char ucDLL; /* Divisor latch, low byte */
315 unsigned char ucDLM; /* Divisor latch, high byte */
316} DSP_3780I_CONFIG_SETTINGS;
317
318
319/* 3780i support functions */
320int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
321 unsigned short *pIrqMap,
322 unsigned short *pDmaMap);
323int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings);
324int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings);
325int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings);
326int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
327 unsigned uCount, unsigned long ulDSPAddr);
328int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
329 void __user *pvBuffer, unsigned uCount,
330 unsigned long ulDSPAddr);
331int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
332 unsigned uCount, unsigned long ulDSPAddr);
333int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
334 unsigned uCount, unsigned long ulDSPAddr);
335int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
336 unsigned uCount, unsigned long ulDSPAddr);
337unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
338 unsigned long ulMsaAddr);
339void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
340 unsigned long ulMsaAddr, unsigned short usValue);
341void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
342 unsigned char ucValue);
343unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
344 unsigned uIndex);
345int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
346 unsigned short *pusIPCSource);
347
348/* I/O port access macros */
349#define MKWORD(var) (*((unsigned short *)(&var)))
350#define MKBYTE(var) (*((unsigned char *)(&var)))
351
352#define WriteMsaCfg(addr,value) dsp3780I_WriteMsaCfg(usDspBaseIO,addr,value)
353#define ReadMsaCfg(addr) dsp3780I_ReadMsaCfg(usDspBaseIO,addr)
354#define WriteGenCfg(index,value) dsp3780I_WriteGenCfg(usDspBaseIO,index,value)
355#define ReadGenCfg(index) dsp3780I_ReadGenCfg(usDspBaseIO,index)
356
357#define InWordDsp(index) inw(usDspBaseIO+index)
358#define InByteDsp(index) inb(usDspBaseIO+index)
359#define OutWordDsp(index,value) outw(value,usDspBaseIO+index)
360#define OutByteDsp(index,value) outb(value,usDspBaseIO+index)
361
362#endif
diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile
new file mode 100644
index 000000000000..754c9e2058ed
--- /dev/null
+++ b/drivers/char/mwave/Makefile
@@ -0,0 +1,15 @@
1#
2# Makefile for ACP Modem (Mwave).
3#
4# See the README file in this directory for more info. <paulsch@us.ibm.com>
5#
6
7obj-$(CONFIG_MWAVE) += mwave.o
8
9mwave-objs := mwavedd.o smapi.o tp3780i.o 3780i.o
10
11# To have the mwave driver disable other uarts if necessary
12# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
13
14# To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
15EXTRA_CFLAGS += -DMW_TRACE
diff --git a/drivers/char/mwave/README b/drivers/char/mwave/README
new file mode 100644
index 000000000000..70f8d19fb79f
--- /dev/null
+++ b/drivers/char/mwave/README
@@ -0,0 +1,50 @@
1Module options
2--------------
3
4The mwave module takes the following options. Note that these options
5are not saved by the BIOS and so do not persist after unload and reload.
6
7 mwave_debug=value, where value is bitwise OR of trace flags:
8 0x0001 mwavedd api tracing
9 0x0002 smapi api tracing
10 0x0004 3780i tracing
11 0x0008 tp3780i tracing
12
13 Tracing only occurs if the driver has been compiled with the
14 MW_TRACE macro #defined (i.e. let EXTRA_CFLAGS += -DMW_TRACE
15 in the Makefile).
16
17 mwave_3780i_irq=5/7/10/11/15
18 If the dsp irq has not been setup and stored in bios by the
19 thinkpad configuration utility then this parameter allows the
20 irq used by the dsp to be configured.
21
22 mwave_3780i_io=0x130/0x350/0x0070/0xDB0
23 If the dsp io range has not been setup and stored in bios by the
24 thinkpad configuration utility then this parameter allows the
25 io range used by the dsp to be configured.
26
27 mwave_uart_irq=3/4
28 If the mwave's uart irq has not been setup and stored in bios by the
29 thinkpad configuration utility then this parameter allows the
30 irq used by the mwave uart to be configured.
31
32 mwave_uart_io=0x3f8/0x2f8/0x3E8/0x2E8
33 If the uart io range has not been setup and stored in bios by the
34 thinkpad configuration utility then this parameter allows the
35 io range used by the mwave uart to be configured.
36
37Example to enable the 3780i DSP using ttyS1 resources:
38
39 insmod mwave mwave_3780i_irq=10 mwave_3780i_io=0x0130 mwave_uart_irq=3 mwave_uart_io=0x2f8
40
41Accessing the driver
42--------------------
43
44You must also create a node for the driver. Without devfs:
45 mkdir -p /dev/modems
46 mknod --mode=660 /dev/modems/mwave c 10 219
47With devfs:
48 mkdir -p /dev/modems
49 ln -s ../misc/mwave /dev/modems/mwave
50
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
65MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
66MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
67MODULE_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*/
74int mwave_debug = 0;
75int mwave_3780i_irq = 0;
76int mwave_3780i_io = 0;
77int mwave_uart_irq = 0;
78int mwave_uart_io = 0;
79module_param(mwave_debug, int, 0);
80module_param(mwave_3780i_irq, int, 0);
81module_param(mwave_3780i_io, int, 0);
82module_param(mwave_uart_irq, int, 0);
83module_param(mwave_uart_io, int, 0);
84
85static int mwave_open(struct inode *inode, struct file *file);
86static int mwave_close(struct inode *inode, struct file *file);
87static int mwave_ioctl(struct inode *inode, struct file *filp,
88 unsigned int iocmd, unsigned long ioarg);
89
90MWAVE_DEVICE_DATA mwave_s_mdd;
91
92static 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
105static 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
119static 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
388static 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
399static 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
411static 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
454static 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
464static 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
471struct 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) \
475static 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) \
485static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL)
486
487mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma);
488mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq);
489mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO);
490mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq);
491mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO);
492
493static 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*/
508static 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
544module_exit(mwave_exit);
545
546static 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
664cleanup_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
673module_init(mwave_init);
674
diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h
new file mode 100644
index 000000000000..8eca61e0a19c
--- /dev/null
+++ b/drivers/char/mwave/mwavedd.h
@@ -0,0 +1,150 @@
1/*
2*
3* mwavedd.h -- declarations for 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#ifndef _LINUX_MWAVEDD_H
50#define _LINUX_MWAVEDD_H
51#include "3780i.h"
52#include "tp3780i.h"
53#include "smapi.h"
54#include "mwavepub.h"
55#include <linux/ioctl.h>
56#include <asm/uaccess.h>
57#include <linux/wait.h>
58
59extern int mwave_debug;
60extern int mwave_3780i_irq;
61extern int mwave_3780i_io;
62extern int mwave_uart_irq;
63extern int mwave_uart_io;
64
65#define PRINTK_ERROR printk
66#define KERN_ERR_MWAVE KERN_ERR "mwave: "
67
68#define TRACE_MWAVE 0x0001
69#define TRACE_SMAPI 0x0002
70#define TRACE_3780I 0x0004
71#define TRACE_TP3780I 0x0008
72
73#ifdef MW_TRACE
74#define PRINTK_1(f,s) \
75 if (f & (mwave_debug)) { \
76 printk(s); \
77 }
78
79#define PRINTK_2(f,s,v1) \
80 if (f & (mwave_debug)) { \
81 printk(s,v1); \
82 }
83
84#define PRINTK_3(f,s,v1,v2) \
85 if (f & (mwave_debug)) { \
86 printk(s,v1,v2); \
87 }
88
89#define PRINTK_4(f,s,v1,v2,v3) \
90 if (f & (mwave_debug)) { \
91 printk(s,v1,v2,v3); \
92 }
93
94#define PRINTK_5(f,s,v1,v2,v3,v4) \
95 if (f & (mwave_debug)) { \
96 printk(s,v1,v2,v3,v4); \
97 }
98
99#define PRINTK_6(f,s,v1,v2,v3,v4,v5) \
100 if (f & (mwave_debug)) { \
101 printk(s,v1,v2,v3,v4,v5); \
102 }
103
104#define PRINTK_7(f,s,v1,v2,v3,v4,v5,v6) \
105 if (f & (mwave_debug)) { \
106 printk(s,v1,v2,v3,v4,v5,v6); \
107 }
108
109#define PRINTK_8(f,s,v1,v2,v3,v4,v5,v6,v7) \
110 if (f & (mwave_debug)) { \
111 printk(s,v1,v2,v3,v4,v5,v6,v7); \
112 }
113
114#else
115#define PRINTK_1(f,s)
116#define PRINTK_2(f,s,v1)
117#define PRINTK_3(f,s,v1,v2)
118#define PRINTK_4(f,s,v1,v2,v3)
119#define PRINTK_5(f,s,v1,v2,v3,v4)
120#define PRINTK_6(f,s,v1,v2,v3,v4,v5)
121#define PRINTK_7(f,s,v1,v2,v3,v4,v5,v6)
122#define PRINTK_8(f,s,v1,v2,v3,v4,v5,v6,v7)
123#endif
124
125
126typedef struct _MWAVE_IPC {
127 unsigned short usIntCount; /* 0=none, 1=first, 2=greater than 1st */
128 BOOLEAN bIsEnabled;
129 BOOLEAN bIsHere;
130 /* entry spin lock */
131 wait_queue_head_t ipc_wait_queue;
132} MWAVE_IPC;
133
134typedef struct _MWAVE_DEVICE_DATA {
135 THINKPAD_BD_DATA rBDData; /* board driver's data area */
136 unsigned long ulIPCSource_ISR; /* IPC source bits for recently processed intr, set during ISR processing */
137 unsigned long ulIPCSource_DPC; /* IPC source bits for recently processed intr, set during DPC processing */
138 BOOLEAN bBDInitialized;
139 BOOLEAN bResourcesClaimed;
140 BOOLEAN bDSPEnabled;
141 BOOLEAN bDSPReset;
142 MWAVE_IPC IPCs[16];
143 BOOLEAN bMwaveDevRegistered;
144 short sLine;
145 int nr_registered_attrs;
146 int device_registered;
147
148} MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA;
149
150#endif
diff --git a/drivers/char/mwave/mwavepub.h b/drivers/char/mwave/mwavepub.h
new file mode 100644
index 000000000000..f1f9da7a65c1
--- /dev/null
+++ b/drivers/char/mwave/mwavepub.h
@@ -0,0 +1,89 @@
1/*
2*
3* mwavepub.h -- PUBLIC declarations for the mwave driver
4* and applications using it
5*
6*
7* Written By: Mike Sullivan IBM Corporation
8*
9* Copyright (C) 1999 IBM Corporation
10*
11* This program is free software; you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by
13* the Free Software Foundation; either version 2 of the License, or
14* (at your option) any later version.
15*
16* This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* GNU General Public License for more details.
20*
21* NO WARRANTY
22* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26* solely responsible for determining the appropriateness of using and
27* distributing the Program and assumes all risks associated with its
28* exercise of rights under this Agreement, including but not limited to
29* the risks and costs of program errors, damage to or loss of data,
30* programs or equipment, and unavailability or interruption of operations.
31*
32* DISCLAIMER OF LIABILITY
33* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software
43* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*
45*
46* 10/23/2000 - Alpha Release
47* First release to the public
48*/
49
50#ifndef _LINUX_MWAVEPUB_H
51#define _LINUX_MWAVEPUB_H
52
53#include <linux/miscdevice.h>
54
55
56typedef struct _MW_ABILITIES {
57 unsigned long instr_per_sec;
58 unsigned long data_size;
59 unsigned long inst_size;
60 unsigned long bus_dma_bw;
61 unsigned short uart_enable;
62 short component_count;
63 unsigned long component_list[7];
64 char mwave_os_name[16];
65 char bios_task_name[16];
66} MW_ABILITIES, *pMW_ABILITIES;
67
68
69typedef struct _MW_READWRITE {
70 unsigned short usDspAddress; /* The dsp address */
71 unsigned long ulDataLength; /* The size in bytes of the data or user buffer */
72 void *pBuf; /* Input:variable sized buffer */
73} MW_READWRITE, *pMW_READWRITE;
74
75#define IOCTL_MW_RESET _IO(MWAVE_MINOR,1)
76#define IOCTL_MW_RUN _IO(MWAVE_MINOR,2)
77#define IOCTL_MW_DSP_ABILITIES _IOR(MWAVE_MINOR,3,MW_ABILITIES)
78#define IOCTL_MW_READ_DATA _IOR(MWAVE_MINOR,4,MW_READWRITE)
79#define IOCTL_MW_READCLEAR_DATA _IOR(MWAVE_MINOR,5,MW_READWRITE)
80#define IOCTL_MW_READ_INST _IOR(MWAVE_MINOR,6,MW_READWRITE)
81#define IOCTL_MW_WRITE_DATA _IOW(MWAVE_MINOR,7,MW_READWRITE)
82#define IOCTL_MW_WRITE_INST _IOW(MWAVE_MINOR,8,MW_READWRITE)
83#define IOCTL_MW_REGISTER_IPC _IOW(MWAVE_MINOR,9,int)
84#define IOCTL_MW_UNREGISTER_IPC _IOW(MWAVE_MINOR,10,int)
85#define IOCTL_MW_GET_IPC _IOW(MWAVE_MINOR,11,int)
86#define IOCTL_MW_TRACE _IOR(MWAVE_MINOR,12,MW_READWRITE)
87
88
89#endif
diff --git a/drivers/char/mwave/smapi.c b/drivers/char/mwave/smapi.c
new file mode 100644
index 000000000000..6187fd14b3fe
--- /dev/null
+++ b/drivers/char/mwave/smapi.c
@@ -0,0 +1,570 @@
1/*
2*
3* smapi.c -- SMAPI interface routines
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/kernel.h>
50#include <linux/mc146818rtc.h> /* CMOS defines */
51#include "smapi.h"
52#include "mwavedd.h"
53
54static unsigned short g_usSmapiPort = 0;
55
56
57static int smapi_request(unsigned short inBX, unsigned short inCX,
58 unsigned short inDI, unsigned short inSI,
59 unsigned short *outAX, unsigned short *outBX,
60 unsigned short *outCX, unsigned short *outDX,
61 unsigned short *outDI, unsigned short *outSI)
62{
63 unsigned short myoutAX = 2, *pmyoutAX = &myoutAX;
64 unsigned short myoutBX = 3, *pmyoutBX = &myoutBX;
65 unsigned short myoutCX = 4, *pmyoutCX = &myoutCX;
66 unsigned short myoutDX = 5, *pmyoutDX = &myoutDX;
67 unsigned short myoutDI = 6, *pmyoutDI = &myoutDI;
68 unsigned short myoutSI = 7, *pmyoutSI = &myoutSI;
69 unsigned short usSmapiOK = -EIO, *pusSmapiOK = &usSmapiOK;
70 unsigned int inBXCX = (inBX << 16) | inCX;
71 unsigned int inDISI = (inDI << 16) | inSI;
72 int retval = 0;
73
74 PRINTK_5(TRACE_SMAPI, "inBX %x inCX %x inDI %x inSI %x\n",
75 inBX, inCX, inDI, inSI);
76
77 __asm__ __volatile__("movw $0x5380,%%ax\n\t"
78 "movl %7,%%ebx\n\t"
79 "shrl $16, %%ebx\n\t"
80 "movw %7,%%cx\n\t"
81 "movl %8,%%edi\n\t"
82 "shrl $16,%%edi\n\t"
83 "movw %8,%%si\n\t"
84 "movw %9,%%dx\n\t"
85 "out %%al,%%dx\n\t"
86 "out %%al,$0x4F\n\t"
87 "cmpb $0x53,%%ah\n\t"
88 "je 2f\n\t"
89 "1:\n\t"
90 "orb %%ah,%%ah\n\t"
91 "jnz 2f\n\t"
92 "movw %%ax,%0\n\t"
93 "movw %%bx,%1\n\t"
94 "movw %%cx,%2\n\t"
95 "movw %%dx,%3\n\t"
96 "movw %%di,%4\n\t"
97 "movw %%si,%5\n\t"
98 "movw $1,%6\n\t"
99 "2:\n\t":"=m"(*(unsigned short *) pmyoutAX),
100 "=m"(*(unsigned short *) pmyoutBX),
101 "=m"(*(unsigned short *) pmyoutCX),
102 "=m"(*(unsigned short *) pmyoutDX),
103 "=m"(*(unsigned short *) pmyoutDI),
104 "=m"(*(unsigned short *) pmyoutSI),
105 "=m"(*(unsigned short *) pusSmapiOK)
106 :"m"(inBXCX), "m"(inDISI), "m"(g_usSmapiPort)
107 :"%eax", "%ebx", "%ecx", "%edx", "%edi",
108 "%esi");
109
110 PRINTK_8(TRACE_SMAPI,
111 "myoutAX %x myoutBX %x myoutCX %x myoutDX %x myoutDI %x myoutSI %x usSmapiOK %x\n",
112 myoutAX, myoutBX, myoutCX, myoutDX, myoutDI, myoutSI,
113 usSmapiOK);
114 *outAX = myoutAX;
115 *outBX = myoutBX;
116 *outCX = myoutCX;
117 *outDX = myoutDX;
118 *outDI = myoutDI;
119 *outSI = myoutSI;
120
121 retval = (usSmapiOK == 1) ? 0 : -EIO;
122 PRINTK_2(TRACE_SMAPI, "smapi::smapi_request exit retval %x\n", retval);
123 return retval;
124}
125
126
127int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
128{
129 int bRC = -EIO;
130 unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
131 unsigned short ausDspBases[] = { 0x0030, 0x4E30, 0x8E30, 0xCE30, 0x0130, 0x0350, 0x0070, 0x0DB0 };
132 unsigned short ausUartBases[] = { 0x03F8, 0x02F8, 0x03E8, 0x02E8 };
133 unsigned short numDspBases = 8;
134 unsigned short numUartBases = 4;
135
136 PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg entry\n");
137
138 bRC = smapi_request(0x1802, 0x0000, 0, 0,
139 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
140 if (bRC) {
141 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Error: Could not get DSP Settings. Aborting.\n");
142 return bRC;
143 }
144
145 PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
146
147 pSettings->bDSPPresent = ((usBX & 0x0100) != 0);
148 pSettings->bDSPEnabled = ((usCX & 0x0001) != 0);
149 pSettings->usDspIRQ = usSI & 0x00FF;
150 pSettings->usDspDMA = (usSI & 0xFF00) >> 8;
151 if ((usDI & 0x00FF) < numDspBases) {
152 pSettings->usDspBaseIO = ausDspBases[usDI & 0x00FF];
153 } else {
154 pSettings->usDspBaseIO = 0;
155 }
156 PRINTK_6(TRACE_SMAPI,
157 "smapi::smapi_query_DSP_cfg get DSP Settings bDSPPresent %x bDSPEnabled %x usDspIRQ %x usDspDMA %x usDspBaseIO %x\n",
158 pSettings->bDSPPresent, pSettings->bDSPEnabled,
159 pSettings->usDspIRQ, pSettings->usDspDMA,
160 pSettings->usDspBaseIO);
161
162 /* check for illegal values */
163 if ( pSettings->usDspBaseIO == 0 )
164 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP base I/O address is 0\n");
165 if ( pSettings->usDspIRQ == 0 )
166 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP IRQ line is 0\n");
167
168 bRC = smapi_request(0x1804, 0x0000, 0, 0,
169 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
170 if (bRC) {
171 PRINTK_ERROR("smapi::smapi_query_DSP_cfg: Error: Could not get DSP modem settings. Aborting.\n");
172 return bRC;
173 }
174
175 PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
176
177 pSettings->bModemEnabled = ((usCX & 0x0001) != 0);
178 pSettings->usUartIRQ = usSI & 0x000F;
179 if (((usSI & 0xFF00) >> 8) < numUartBases) {
180 pSettings->usUartBaseIO = ausUartBases[(usSI & 0xFF00) >> 8];
181 } else {
182 pSettings->usUartBaseIO = 0;
183 }
184
185 PRINTK_4(TRACE_SMAPI,
186 "smapi::smapi_query_DSP_cfg get DSP modem settings bModemEnabled %x usUartIRQ %x usUartBaseIO %x\n",
187 pSettings->bModemEnabled,
188 pSettings->usUartIRQ,
189 pSettings->usUartBaseIO);
190
191 /* check for illegal values */
192 if ( pSettings->usUartBaseIO == 0 )
193 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART base I/O address is 0\n");
194 if ( pSettings->usUartIRQ == 0 )
195 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART IRQ line is 0\n");
196
197 PRINTK_2(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg exit bRC %x\n", bRC);
198
199 return bRC;
200}
201
202
203int smapi_set_DSP_cfg(void)
204{
205 int bRC = -EIO;
206 int i;
207 unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
208 unsigned short ausDspBases[] = { 0x0030, 0x4E30, 0x8E30, 0xCE30, 0x0130, 0x0350, 0x0070, 0x0DB0 };
209 unsigned short ausUartBases[] = { 0x03F8, 0x02F8, 0x03E8, 0x02E8 };
210 unsigned short ausDspIrqs[] = { 5, 7, 10, 11, 15 };
211 unsigned short ausUartIrqs[] = { 3, 4 };
212
213 unsigned short numDspBases = 8;
214 unsigned short numUartBases = 4;
215 unsigned short numDspIrqs = 5;
216 unsigned short numUartIrqs = 2;
217 unsigned short dspio_index = 0, uartio_index = 0;
218
219 PRINTK_5(TRACE_SMAPI,
220 "smapi::smapi_set_DSP_cfg entry mwave_3780i_irq %x mwave_3780i_io %x mwave_uart_irq %x mwave_uart_io %x\n",
221 mwave_3780i_irq, mwave_3780i_io, mwave_uart_irq, mwave_uart_io);
222
223 if (mwave_3780i_io) {
224 for (i = 0; i < numDspBases; i++) {
225 if (mwave_3780i_io == ausDspBases[i])
226 break;
227 }
228 if (i == numDspBases) {
229 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_io address %x. Aborting.\n", mwave_3780i_io);
230 return bRC;
231 }
232 dspio_index = i;
233 }
234
235 if (mwave_3780i_irq) {
236 for (i = 0; i < numDspIrqs; i++) {
237 if (mwave_3780i_irq == ausDspIrqs[i])
238 break;
239 }
240 if (i == numDspIrqs) {
241 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_irq %x. Aborting.\n", mwave_3780i_irq);
242 return bRC;
243 }
244 }
245
246 if (mwave_uart_io) {
247 for (i = 0; i < numUartBases; i++) {
248 if (mwave_uart_io == ausUartBases[i])
249 break;
250 }
251 if (i == numUartBases) {
252 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_io address %x. Aborting.\n", mwave_uart_io);
253 return bRC;
254 }
255 uartio_index = i;
256 }
257
258
259 if (mwave_uart_irq) {
260 for (i = 0; i < numUartIrqs; i++) {
261 if (mwave_uart_irq == ausUartIrqs[i])
262 break;
263 }
264 if (i == numUartIrqs) {
265 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_irq %x. Aborting.\n", mwave_uart_irq);
266 return bRC;
267 }
268 }
269
270 if (mwave_uart_irq || mwave_uart_io) {
271
272 /* Check serial port A */
273 bRC = smapi_request(0x1402, 0x0000, 0, 0,
274 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
275 if (bRC) goto exit_smapi_request_error;
276 /* bRC == 0 */
277 if (usBX & 0x0100) { /* serial port A is present */
278 if (usCX & 1) { /* serial port is enabled */
279 if ((usSI & 0xFF) == mwave_uart_irq) {
280#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
281 PRINTK_ERROR(KERN_ERR_MWAVE
282 "smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
283#else
284 PRINTK_3(TRACE_SMAPI,
285 "smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
286#endif
287#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
288 PRINTK_1(TRACE_SMAPI,
289 "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
290 bRC = smapi_request(0x1403, 0x0100, 0, usSI,
291 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
292 if (bRC) goto exit_smapi_request_error;
293 bRC = smapi_request(0x1402, 0x0000, 0, 0,
294 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
295 if (bRC) goto exit_smapi_request_error;
296#else
297 goto exit_conflict;
298#endif
299 } else {
300 if ((usSI >> 8) == uartio_index) {
301#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
302 PRINTK_ERROR(KERN_ERR_MWAVE
303 "smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
304#else
305 PRINTK_3(TRACE_SMAPI,
306 "smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
307#endif
308#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
309 PRINTK_1(TRACE_SMAPI,
310 "smapi::smapi_set_DSP_cfg Disabling conflicting serial port A\n");
311 bRC = smapi_request (0x1403, 0x0100, 0, usSI,
312 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
313 if (bRC) goto exit_smapi_request_error;
314 bRC = smapi_request (0x1402, 0x0000, 0, 0,
315 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
316 if (bRC) goto exit_smapi_request_error;
317#else
318 goto exit_conflict;
319#endif
320 }
321 }
322 }
323 }
324
325 /* Check serial port B */
326 bRC = smapi_request(0x1404, 0x0000, 0, 0,
327 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
328 if (bRC) goto exit_smapi_request_error;
329 /* bRC == 0 */
330 if (usBX & 0x0100) { /* serial port B is present */
331 if (usCX & 1) { /* serial port is enabled */
332 if ((usSI & 0xFF) == mwave_uart_irq) {
333#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
334 PRINTK_ERROR(KERN_ERR_MWAVE
335 "smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
336#else
337 PRINTK_3(TRACE_SMAPI,
338 "smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
339#endif
340#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
341 PRINTK_1(TRACE_SMAPI,
342 "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
343 bRC = smapi_request(0x1405, 0x0100, 0, usSI,
344 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
345 if (bRC) goto exit_smapi_request_error;
346 bRC = smapi_request(0x1404, 0x0000, 0, 0,
347 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
348 if (bRC) goto exit_smapi_request_error;
349#else
350 goto exit_conflict;
351#endif
352 } else {
353 if ((usSI >> 8) == uartio_index) {
354#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
355 PRINTK_ERROR(KERN_ERR_MWAVE
356 "smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
357#else
358 PRINTK_3(TRACE_SMAPI,
359 "smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
360#endif
361#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
362 PRINTK_1 (TRACE_SMAPI,
363 "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
364 bRC = smapi_request (0x1405, 0x0100, 0, usSI,
365 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
366 if (bRC) goto exit_smapi_request_error;
367 bRC = smapi_request (0x1404, 0x0000, 0, 0,
368 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
369 if (bRC) goto exit_smapi_request_error;
370#else
371 goto exit_conflict;
372#endif
373 }
374 }
375 }
376 }
377
378 /* Check IR port */
379 bRC = smapi_request(0x1700, 0x0000, 0, 0,
380 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
381 if (bRC) goto exit_smapi_request_error;
382 bRC = smapi_request(0x1704, 0x0000, 0, 0,
383 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
384 if (bRC) goto exit_smapi_request_error;
385 /* bRC == 0 */
386 if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
387 if ((usCX & 0xff) == mwave_uart_irq) {
388#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
389 PRINTK_ERROR(KERN_ERR_MWAVE
390 "smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
391#else
392 PRINTK_3(TRACE_SMAPI,
393 "smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
394#endif
395#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
396 PRINTK_1(TRACE_SMAPI,
397 "smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
398 bRC = smapi_request(0x1701, 0x0100, 0, 0,
399 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
400 if (bRC) goto exit_smapi_request_error;
401 bRC = smapi_request(0x1700, 0, 0, 0,
402 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
403 if (bRC) goto exit_smapi_request_error;
404 bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
405 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
406 if (bRC) goto exit_smapi_request_error;
407 bRC = smapi_request(0x1704, 0x0000, 0, 0,
408 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
409 if (bRC) goto exit_smapi_request_error;
410#else
411 goto exit_conflict;
412#endif
413 } else {
414 if ((usSI & 0xff) == uartio_index) {
415#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
416 PRINTK_ERROR(KERN_ERR_MWAVE
417 "smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
418#else
419 PRINTK_3(TRACE_SMAPI,
420 "smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
421#endif
422#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
423 PRINTK_1(TRACE_SMAPI,
424 "smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
425 bRC = smapi_request(0x1701, 0x0100, 0, 0,
426 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
427 if (bRC) goto exit_smapi_request_error;
428 bRC = smapi_request(0x1700, 0, 0, 0,
429 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
430 if (bRC) goto exit_smapi_request_error;
431 bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
432 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
433 if (bRC) goto exit_smapi_request_error;
434 bRC = smapi_request(0x1704, 0x0000, 0, 0,
435 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
436 if (bRC) goto exit_smapi_request_error;
437#else
438 goto exit_conflict;
439#endif
440 }
441 }
442 }
443 }
444
445 bRC = smapi_request(0x1802, 0x0000, 0, 0,
446 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
447 if (bRC) goto exit_smapi_request_error;
448
449 if (mwave_3780i_io) {
450 usDI = dspio_index;
451 }
452 if (mwave_3780i_irq) {
453 usSI = (usSI & 0xff00) | mwave_3780i_irq;
454 }
455
456 bRC = smapi_request(0x1803, 0x0101, usDI, usSI,
457 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
458 if (bRC) goto exit_smapi_request_error;
459
460 bRC = smapi_request(0x1804, 0x0000, 0, 0,
461 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
462 if (bRC) goto exit_smapi_request_error;
463
464 if (mwave_uart_io) {
465 usSI = (usSI & 0x00ff) | (uartio_index << 8);
466 }
467 if (mwave_uart_irq) {
468 usSI = (usSI & 0xff00) | mwave_uart_irq;
469 }
470 bRC = smapi_request(0x1805, 0x0101, 0, usSI,
471 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
472 if (bRC) goto exit_smapi_request_error;
473
474 bRC = smapi_request(0x1802, 0x0000, 0, 0,
475 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
476 if (bRC) goto exit_smapi_request_error;
477
478 bRC = smapi_request(0x1804, 0x0000, 0, 0,
479 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
480 if (bRC) goto exit_smapi_request_error;
481
482/* normal exit: */
483 PRINTK_1(TRACE_SMAPI, "smapi::smapi_set_DSP_cfg exit\n");
484 return 0;
485
486exit_conflict:
487 /* Message has already been printed */
488 return -EIO;
489
490exit_smapi_request_error:
491 PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg exit on smapi_request error bRC %x\n", bRC);
492 return bRC;
493}
494
495
496int smapi_set_DSP_power_state(BOOLEAN bOn)
497{
498 int bRC = -EIO;
499 unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
500 unsigned short usPowerFunction;
501
502 PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state entry bOn %x\n", bOn);
503
504 usPowerFunction = (bOn) ? 1 : 0;
505
506 bRC = smapi_request(0x4901, 0x0000, 0, usPowerFunction,
507 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
508
509 PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state exit bRC %x\n", bRC);
510
511 return bRC;
512}
513
514#if 0
515static int SmapiQuerySystemID(void)
516{
517 int bRC = -EIO;
518 unsigned short usAX = 0xffff, usBX = 0xffff, usCX = 0xffff,
519 usDX = 0xffff, usDI = 0xffff, usSI = 0xffff;
520
521 printk("smapi::SmapiQUerySystemID entry\n");
522 bRC = smapi_request(0x0000, 0, 0, 0,
523 &usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
524
525 if (bRC == 0) {
526 printk("AX=%x, BX=%x, CX=%x, DX=%x, DI=%x, SI=%x\n",
527 usAX, usBX, usCX, usDX, usDI, usSI);
528 } else {
529 printk("smapi::SmapiQuerySystemID smapi_request error\n");
530 }
531
532 return bRC;
533}
534#endif /* 0 */
535
536int smapi_init(void)
537{
538 int retval = -EIO;
539 unsigned short usSmapiID = 0;
540 unsigned long flags;
541
542 PRINTK_1(TRACE_SMAPI, "smapi::smapi_init entry\n");
543
544 spin_lock_irqsave(&rtc_lock, flags);
545 usSmapiID = CMOS_READ(0x7C);
546 usSmapiID |= (CMOS_READ(0x7D) << 8);
547 spin_unlock_irqrestore(&rtc_lock, flags);
548 PRINTK_2(TRACE_SMAPI, "smapi::smapi_init usSmapiID %x\n", usSmapiID);
549
550 if (usSmapiID == 0x5349) {
551 spin_lock_irqsave(&rtc_lock, flags);
552 g_usSmapiPort = CMOS_READ(0x7E);
553 g_usSmapiPort |= (CMOS_READ(0x7F) << 8);
554 spin_unlock_irqrestore(&rtc_lock, flags);
555 if (g_usSmapiPort == 0) {
556 PRINTK_ERROR("smapi::smapi_init, ERROR unable to read from SMAPI port\n");
557 } else {
558 PRINTK_2(TRACE_SMAPI,
559 "smapi::smapi_init, exit TRUE g_usSmapiPort %x\n",
560 g_usSmapiPort);
561 retval = 0;
562 //SmapiQuerySystemID();
563 }
564 } else {
565 PRINTK_ERROR("smapi::smapi_init, ERROR invalid usSmapiID\n");
566 retval = -ENXIO;
567 }
568
569 return retval;
570}
diff --git a/drivers/char/mwave/smapi.h b/drivers/char/mwave/smapi.h
new file mode 100644
index 000000000000..64b2ec1420e3
--- /dev/null
+++ b/drivers/char/mwave/smapi.h
@@ -0,0 +1,80 @@
1/*
2*
3* smapi.h -- declarations for SMAPI interface routines
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#ifndef _LINUX_SMAPI_H
50#define _LINUX_SMAPI_H
51
52#define TRUE 1
53#define FALSE 0
54#define BOOLEAN int
55
56typedef struct {
57 int bDSPPresent;
58 int bDSPEnabled;
59 int bModemEnabled;
60 int bMIDIEnabled;
61 int bSblstEnabled;
62 unsigned short usDspIRQ;
63 unsigned short usDspDMA;
64 unsigned short usDspBaseIO;
65 unsigned short usUartIRQ;
66 unsigned short usUartBaseIO;
67 unsigned short usMidiIRQ;
68 unsigned short usMidiBaseIO;
69 unsigned short usSndblstIRQ;
70 unsigned short usSndblstDMA;
71 unsigned short usSndblstBaseIO;
72} SMAPI_DSP_SETTINGS;
73
74int smapi_init(void);
75int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings);
76int smapi_set_DSP_cfg(void);
77int smapi_set_DSP_power_state(BOOLEAN bOn);
78
79
80#endif
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
new file mode 100644
index 000000000000..ab650cd6efc0
--- /dev/null
+++ b/drivers/char/mwave/tp3780i.c
@@ -0,0 +1,592 @@
1/*
2*
3* tp3780i.c -- board driver for 3780i on ThinkPads
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/version.h>
50#include <linux/interrupt.h>
51#include <linux/kernel.h>
52#include <linux/ptrace.h>
53#include <linux/ioport.h>
54#include <asm/io.h>
55#include "smapi.h"
56#include "mwavedd.h"
57#include "tp3780i.h"
58#include "3780i.h"
59#include "mwavepub.h"
60
61extern MWAVE_DEVICE_DATA mwave_s_mdd;
62
63static unsigned short s_ausThinkpadIrqToField[16] =
64 { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004,
65 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 };
66static unsigned short s_ausThinkpadDmaToField[8] =
67 { 0x0001, 0x0002, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0003, 0x0004 };
68static unsigned short s_numIrqs = 16, s_numDmas = 8;
69
70
71static void EnableSRAM(THINKPAD_BD_DATA * pBDData)
72{
73 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
74 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
75 DSP_GPIO_OUTPUT_DATA_15_8 rGpioOutputData;
76 DSP_GPIO_DRIVER_ENABLE_15_8 rGpioDriverEnable;
77 DSP_GPIO_MODE_15_8 rGpioMode;
78
79 PRINTK_1(TRACE_TP3780I, "tp3780i::EnableSRAM, entry\n");
80
81 MKWORD(rGpioMode) = ReadMsaCfg(DSP_GpioModeControl_15_8);
82 rGpioMode.GpioMode10 = 0;
83 WriteMsaCfg(DSP_GpioModeControl_15_8, MKWORD(rGpioMode));
84
85 MKWORD(rGpioDriverEnable) = 0;
86 rGpioDriverEnable.Enable10 = TRUE;
87 rGpioDriverEnable.Mask10 = TRUE;
88 WriteMsaCfg(DSP_GpioDriverEnable_15_8, MKWORD(rGpioDriverEnable));
89
90 MKWORD(rGpioOutputData) = 0;
91 rGpioOutputData.Latch10 = 0;
92 rGpioOutputData.Mask10 = TRUE;
93 WriteMsaCfg(DSP_GpioOutputData_15_8, MKWORD(rGpioOutputData));
94
95 PRINTK_1(TRACE_TP3780I, "tp3780i::EnableSRAM exit\n");
96}
97
98
99static irqreturn_t UartInterrupt(int irq, void *dev_id, struct pt_regs *regs)
100{
101 PRINTK_3(TRACE_TP3780I,
102 "tp3780i::UartInterrupt entry irq %x dev_id %p\n", irq, dev_id);
103 return IRQ_HANDLED;
104}
105
106static irqreturn_t DspInterrupt(int irq, void *dev_id, struct pt_regs *regs)
107{
108 pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
109 DSP_3780I_CONFIG_SETTINGS *pSettings = &pDrvData->rBDData.rDspSettings;
110 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
111 unsigned short usIPCSource = 0, usIsolationMask, usPCNum;
112
113 PRINTK_3(TRACE_TP3780I,
114 "tp3780i::DspInterrupt entry irq %x dev_id %p\n", irq, dev_id);
115
116 if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
117 PRINTK_2(TRACE_TP3780I,
118 "tp3780i::DspInterrupt, return from dsp3780i_GetIPCSource, usIPCSource %x\n",
119 usIPCSource);
120 usIsolationMask = 1;
121 for (usPCNum = 1; usPCNum <= 16; usPCNum++) {
122 if (usIPCSource & usIsolationMask) {
123 usIPCSource &= ~usIsolationMask;
124 PRINTK_3(TRACE_TP3780I,
125 "tp3780i::DspInterrupt usPCNum %x usIPCSource %x\n",
126 usPCNum, usIPCSource);
127 if (pDrvData->IPCs[usPCNum - 1].usIntCount == 0) {
128 pDrvData->IPCs[usPCNum - 1].usIntCount = 1;
129 }
130 PRINTK_2(TRACE_TP3780I,
131 "tp3780i::DspInterrupt usIntCount %x\n",
132 pDrvData->IPCs[usPCNum - 1].usIntCount);
133 if (pDrvData->IPCs[usPCNum - 1].bIsEnabled == TRUE) {
134 PRINTK_2(TRACE_TP3780I,
135 "tp3780i::DspInterrupt, waking up usPCNum %x\n",
136 usPCNum - 1);
137 wake_up_interruptible(&pDrvData->IPCs[usPCNum - 1].ipc_wait_queue);
138 } else {
139 PRINTK_2(TRACE_TP3780I,
140 "tp3780i::DspInterrupt, no one waiting for IPC %x\n",
141 usPCNum - 1);
142 }
143 }
144 if (usIPCSource == 0)
145 break;
146 /* try next IPC */
147 usIsolationMask = usIsolationMask << 1;
148 }
149 } else {
150 PRINTK_1(TRACE_TP3780I,
151 "tp3780i::DspInterrupt, return false from dsp3780i_GetIPCSource\n");
152 }
153 PRINTK_1(TRACE_TP3780I, "tp3780i::DspInterrupt exit\n");
154 return IRQ_HANDLED;
155}
156
157
158int tp3780I_InitializeBoardData(THINKPAD_BD_DATA * pBDData)
159{
160 int retval = 0;
161 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
162
163
164 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData entry pBDData %p\n", pBDData);
165
166 pBDData->bDSPEnabled = FALSE;
167 pSettings->bInterruptClaimed = FALSE;
168
169 retval = smapi_init();
170 if (retval) {
171 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_InitializeBoardData: Error: SMAPI is not available on this machine\n");
172 } else {
173 if (mwave_3780i_irq || mwave_3780i_io || mwave_uart_irq || mwave_uart_io) {
174 retval = smapi_set_DSP_cfg();
175 }
176 }
177
178 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData exit retval %x\n", retval);
179
180 return retval;
181}
182
183int tp3780I_Cleanup(THINKPAD_BD_DATA * pBDData)
184{
185 int retval = 0;
186
187 PRINTK_2(TRACE_TP3780I,
188 "tp3780i::tp3780I_Cleanup entry and exit pBDData %p\n", pBDData);
189
190 return retval;
191}
192
193int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData)
194{
195 SMAPI_DSP_SETTINGS rSmapiInfo;
196 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
197
198 PRINTK_2(TRACE_TP3780I,
199 "tp3780i::tp3780I_CalcResources entry pBDData %p\n", pBDData);
200
201 if (smapi_query_DSP_cfg(&rSmapiInfo)) {
202 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Could not query DSP config. Aborting.\n");
203 return -EIO;
204 }
205
206 /* Sanity check */
207 if (
208 ( rSmapiInfo.usDspIRQ == 0 )
209 || ( rSmapiInfo.usDspBaseIO == 0 )
210 || ( rSmapiInfo.usUartIRQ == 0 )
211 || ( rSmapiInfo.usUartBaseIO == 0 )
212 ) {
213 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Illegal resource setting. Aborting.\n");
214 return -EIO;
215 }
216
217 pSettings->bDSPEnabled = (rSmapiInfo.bDSPEnabled && rSmapiInfo.bDSPPresent);
218 pSettings->bModemEnabled = rSmapiInfo.bModemEnabled;
219 pSettings->usDspIrq = rSmapiInfo.usDspIRQ;
220 pSettings->usDspDma = rSmapiInfo.usDspDMA;
221 pSettings->usDspBaseIO = rSmapiInfo.usDspBaseIO;
222 pSettings->usUartIrq = rSmapiInfo.usUartIRQ;
223 pSettings->usUartBaseIO = rSmapiInfo.usUartBaseIO;
224
225 pSettings->uDStoreSize = TP_ABILITIES_DATA_SIZE;
226 pSettings->uIStoreSize = TP_ABILITIES_INST_SIZE;
227 pSettings->uIps = TP_ABILITIES_INTS_PER_SEC;
228
229 if (pSettings->bDSPEnabled && pSettings->bModemEnabled && pSettings->usDspIrq == pSettings->usUartIrq) {
230 pBDData->bShareDspIrq = pBDData->bShareUartIrq = 1;
231 } else {
232 pBDData->bShareDspIrq = pBDData->bShareUartIrq = 0;
233 }
234
235 PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_CalcResources exit\n");
236
237 return 0;
238}
239
240
241int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
242{
243 int retval = 0;
244 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
245#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
246 struct resource *pres;
247#endif
248
249 PRINTK_2(TRACE_TP3780I,
250 "tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
251
252#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
253 pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
254 if ( pres == NULL ) retval = -EIO;
255#else
256 retval = check_region(pSettings->usDspBaseIO, 16);
257 if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
258#endif
259 if (retval) {
260 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
261 retval = -EIO;
262 }
263
264 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ClaimResources exit retval %x\n", retval);
265
266 return retval;
267}
268
269int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
270{
271 int retval = 0;
272 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
273
274 PRINTK_2(TRACE_TP3780I,
275 "tp3780i::tp3780I_ReleaseResources entry pBDData %p\n", pBDData);
276
277 release_region(pSettings->usDspBaseIO & (~3), 16);
278
279 if (pSettings->bInterruptClaimed) {
280 free_irq(pSettings->usDspIrq, NULL);
281 pSettings->bInterruptClaimed = FALSE;
282 }
283
284 PRINTK_2(TRACE_TP3780I,
285 "tp3780i::tp3780I_ReleaseResources exit retval %x\n", retval);
286
287 return retval;
288}
289
290
291
292int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
293{
294 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
295 BOOLEAN bDSPPoweredUp = FALSE, bDSPEnabled = FALSE, bInterruptAllocated = FALSE;
296
297 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
298
299 if (pBDData->bDSPEnabled) {
300 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: DSP already enabled!\n");
301 goto exit_cleanup;
302 }
303
304 if (!pSettings->bDSPEnabled) {
305 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780::tp3780I_EnableDSP: Error: pSettings->bDSPEnabled not set\n");
306 goto exit_cleanup;
307 }
308
309 if (
310 (pSettings->usDspIrq >= s_numIrqs)
311 || (pSettings->usDspDma >= s_numDmas)
312 || (s_ausThinkpadIrqToField[pSettings->usDspIrq] == 0xFFFF)
313 || (s_ausThinkpadDmaToField[pSettings->usDspDma] == 0xFFFF)
314 ) {
315 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: invalid irq %x\n", pSettings->usDspIrq);
316 goto exit_cleanup;
317 }
318
319 if (
320 ((pSettings->usDspBaseIO & 0xF00F) != 0)
321 || (pSettings->usDspBaseIO & 0x0FF0) == 0
322 ) {
323 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid DSP base I/O address %x\n", pSettings->usDspBaseIO);
324 goto exit_cleanup;
325 }
326
327 if (pSettings->bModemEnabled) {
328 if (
329 pSettings->usUartIrq >= s_numIrqs
330 || s_ausThinkpadIrqToField[pSettings->usUartIrq] == 0xFFFF
331 ) {
332 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid UART IRQ %x\n", pSettings->usUartIrq);
333 goto exit_cleanup;
334 }
335 switch (pSettings->usUartBaseIO) {
336 case 0x03F8:
337 case 0x02F8:
338 case 0x03E8:
339 case 0x02E8:
340 break;
341
342 default:
343 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Invalid UART base I/O address %x\n", pSettings->usUartBaseIO);
344 goto exit_cleanup;
345 }
346 }
347
348 pSettings->bDspIrqActiveLow = pSettings->bDspIrqPulse = TRUE;
349 pSettings->bUartIrqActiveLow = pSettings->bUartIrqPulse = TRUE;
350
351 if (pBDData->bShareDspIrq) {
352 pSettings->bDspIrqActiveLow = FALSE;
353 }
354 if (pBDData->bShareUartIrq) {
355 pSettings->bUartIrqActiveLow = FALSE;
356 }
357
358 pSettings->usNumTransfers = TP_CFG_NumTransfers;
359 pSettings->usReRequest = TP_CFG_RerequestTimer;
360 pSettings->bEnableMEMCS16 = TP_CFG_MEMCS16;
361 pSettings->usIsaMemCmdWidth = TP_CFG_IsaMemCmdWidth;
362 pSettings->bGateIOCHRDY = TP_CFG_GateIOCHRDY;
363 pSettings->bEnablePwrMgmt = TP_CFG_EnablePwrMgmt;
364 pSettings->usHBusTimerLoadValue = TP_CFG_HBusTimerValue;
365 pSettings->bDisableLBusTimeout = TP_CFG_DisableLBusTimeout;
366 pSettings->usN_Divisor = TP_CFG_N_Divisor;
367 pSettings->usM_Multiplier = TP_CFG_M_Multiplier;
368 pSettings->bPllBypass = TP_CFG_PllBypass;
369 pSettings->usChipletEnable = TP_CFG_ChipletEnable;
370
371 if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart", NULL)) {
372 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Could not get UART IRQ %x\n", pSettings->usUartIrq);
373 goto exit_cleanup;
374 } else { /* no conflict just release */
375 free_irq(pSettings->usUartIrq, NULL);
376 }
377
378 if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i", NULL)) {
379 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Could not get 3780i IRQ %x\n", pSettings->usDspIrq);
380 goto exit_cleanup;
381 } else {
382 PRINTK_3(TRACE_TP3780I,
383 "tp3780i::tp3780I_EnableDSP, got interrupt %x bShareDspIrq %x\n",
384 pSettings->usDspIrq, pBDData->bShareDspIrq);
385 bInterruptAllocated = TRUE;
386 pSettings->bInterruptClaimed = TRUE;
387 }
388
389 smapi_set_DSP_power_state(FALSE);
390 if (smapi_set_DSP_power_state(TRUE)) {
391 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: smapi_set_DSP_power_state(TRUE) failed\n");
392 goto exit_cleanup;
393 } else {
394 bDSPPoweredUp = TRUE;
395 }
396
397 if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
398 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
399 goto exit_cleanup;
400 } else {
401 bDSPEnabled = TRUE;
402 }
403
404 EnableSRAM(pBDData);
405
406 pBDData->bDSPEnabled = TRUE;
407
408 PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP exit\n");
409
410 return 0;
411
412exit_cleanup:
413 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
414 if (bDSPEnabled)
415 dsp3780I_DisableDSP(pSettings);
416 if (bDSPPoweredUp)
417 smapi_set_DSP_power_state(FALSE);
418 if (bInterruptAllocated) {
419 free_irq(pSettings->usDspIrq, NULL);
420 pSettings->bInterruptClaimed = FALSE;
421 }
422 return -EIO;
423}
424
425
426int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData)
427{
428 int retval = 0;
429 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
430
431 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP entry pBDData %p\n", pBDData);
432
433 if (pBDData->bDSPEnabled) {
434 dsp3780I_DisableDSP(&pBDData->rDspSettings);
435 if (pSettings->bInterruptClaimed) {
436 free_irq(pSettings->usDspIrq, NULL);
437 pSettings->bInterruptClaimed = FALSE;
438 }
439 smapi_set_DSP_power_state(FALSE);
440 pBDData->bDSPEnabled = FALSE;
441 }
442
443 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP exit retval %x\n", retval);
444
445 return retval;
446}
447
448
449int tp3780I_ResetDSP(THINKPAD_BD_DATA * pBDData)
450{
451 int retval = 0;
452 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
453
454 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ResetDSP entry pBDData %p\n",
455 pBDData);
456
457 if (dsp3780I_Reset(pSettings) == 0) {
458 EnableSRAM(pBDData);
459 } else {
460 retval = -EIO;
461 }
462
463 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ResetDSP exit retval %x\n", retval);
464
465 return retval;
466}
467
468
469int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData)
470{
471 int retval = 0;
472 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
473
474 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP entry pBDData %p\n", pBDData);
475
476 if (dsp3780I_Run(pSettings) == 0) {
477 // @BUG @TBD EnableSRAM(pBDData);
478 } else {
479 retval = -EIO;
480 }
481
482 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP exit retval %x\n", retval);
483
484 return retval;
485}
486
487
488int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities)
489{
490 int retval = 0;
491
492 PRINTK_2(TRACE_TP3780I,
493 "tp3780i::tp3780I_QueryAbilities entry pBDData %p\n", pBDData);
494
495 /* fill out standard constant fields */
496 pAbilities->instr_per_sec = pBDData->rDspSettings.uIps;
497 pAbilities->data_size = pBDData->rDspSettings.uDStoreSize;
498 pAbilities->inst_size = pBDData->rDspSettings.uIStoreSize;
499 pAbilities->bus_dma_bw = pBDData->rDspSettings.uDmaBandwidth;
500
501 /* fill out dynamically determined fields */
502 pAbilities->component_list[0] = 0x00010000 | MW_ADC_MASK;
503 pAbilities->component_list[1] = 0x00010000 | MW_ACI_MASK;
504 pAbilities->component_list[2] = 0x00010000 | MW_AIC1_MASK;
505 pAbilities->component_list[3] = 0x00010000 | MW_AIC2_MASK;
506 pAbilities->component_list[4] = 0x00010000 | MW_CDDAC_MASK;
507 pAbilities->component_list[5] = 0x00010000 | MW_MIDI_MASK;
508 pAbilities->component_list[6] = 0x00010000 | MW_UART_MASK;
509 pAbilities->component_count = 7;
510
511 /* Fill out Mwave OS and BIOS task names */
512
513 memcpy(pAbilities->mwave_os_name, TP_ABILITIES_MWAVEOS_NAME,
514 sizeof(TP_ABILITIES_MWAVEOS_NAME));
515 memcpy(pAbilities->bios_task_name, TP_ABILITIES_BIOSTASK_NAME,
516 sizeof(TP_ABILITIES_BIOSTASK_NAME));
517
518 PRINTK_1(TRACE_TP3780I,
519 "tp3780i::tp3780I_QueryAbilities exit retval=SUCCESSFUL\n");
520
521 return retval;
522}
523
524int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
525 void __user *pvBuffer, unsigned int uCount,
526 unsigned long ulDSPAddr)
527{
528 int retval = 0;
529 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
530 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
531 BOOLEAN bRC = 0;
532
533 PRINTK_6(TRACE_TP3780I,
534 "tp3780i::tp3780I_ReadWriteDspDStore entry pBDData %p, uOpcode %x, pvBuffer %p, uCount %x, ulDSPAddr %lx\n",
535 pBDData, uOpcode, pvBuffer, uCount, ulDSPAddr);
536
537 if (pBDData->bDSPEnabled) {
538 switch (uOpcode) {
539 case IOCTL_MW_READ_DATA:
540 bRC = dsp3780I_ReadDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
541 break;
542
543 case IOCTL_MW_READCLEAR_DATA:
544 bRC = dsp3780I_ReadAndClearDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
545 break;
546
547 case IOCTL_MW_WRITE_DATA:
548 bRC = dsp3780I_WriteDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
549 break;
550 }
551 }
552
553 retval = (bRC) ? -EIO : 0;
554 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ReadWriteDspDStore exit retval %x\n", retval);
555
556 return retval;
557}
558
559
560int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
561 void __user *pvBuffer, unsigned int uCount,
562 unsigned long ulDSPAddr)
563{
564 int retval = 0;
565 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
566 unsigned short usDspBaseIO = pSettings->usDspBaseIO;
567 BOOLEAN bRC = 0;
568
569 PRINTK_6(TRACE_TP3780I,
570 "tp3780i::tp3780I_ReadWriteDspIStore entry pBDData %p, uOpcode %x, pvBuffer %p, uCount %x, ulDSPAddr %lx\n",
571 pBDData, uOpcode, pvBuffer, uCount, ulDSPAddr);
572
573 if (pBDData->bDSPEnabled) {
574 switch (uOpcode) {
575 case IOCTL_MW_READ_INST:
576 bRC = dsp3780I_ReadIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
577 break;
578
579 case IOCTL_MW_WRITE_INST:
580 bRC = dsp3780I_WriteIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
581 break;
582 }
583 }
584
585 retval = (bRC) ? -EIO : 0;
586
587 PRINTK_2(TRACE_TP3780I,
588 "tp3780i::tp3780I_ReadWriteDspIStore exit retval %x\n", retval);
589
590 return retval;
591}
592
diff --git a/drivers/char/mwave/tp3780i.h b/drivers/char/mwave/tp3780i.h
new file mode 100644
index 000000000000..07685b68538f
--- /dev/null
+++ b/drivers/char/mwave/tp3780i.h
@@ -0,0 +1,103 @@
1/*
2*
3* tp3780i.h -- declarations for tp3780i.c
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#ifndef _LINUX_TP3780I_H
50#define _LINUX_TP3780I_H
51
52#include <asm/io.h>
53#include "mwavepub.h"
54
55
56/* DSP abilities constants for 3780i based Thinkpads */
57#define TP_ABILITIES_INTS_PER_SEC 39160800
58#define TP_ABILITIES_DATA_SIZE 32768
59#define TP_ABILITIES_INST_SIZE 32768
60#define TP_ABILITIES_MWAVEOS_NAME "mwaveos0700.dsp"
61#define TP_ABILITIES_BIOSTASK_NAME "mwbio701.dsp"
62
63
64/* DSP configuration values for 3780i based Thinkpads */
65#define TP_CFG_NumTransfers 3 /* 16 transfers */
66#define TP_CFG_RerequestTimer 1 /* 2 usec */
67#define TP_CFG_MEMCS16 0 /* Disabled, 16-bit memory assumed */
68#define TP_CFG_IsaMemCmdWidth 3 /* 295 nsec (16-bit) */
69#define TP_CFG_GateIOCHRDY 0 /* No IOCHRDY gating */
70#define TP_CFG_EnablePwrMgmt 1 /* Enable low poser suspend/resume */
71#define TP_CFG_HBusTimerValue 255 /* HBus timer load value */
72#define TP_CFG_DisableLBusTimeout 0 /* Enable LBus timeout */
73#define TP_CFG_N_Divisor 32 /* Clock = 39.1608 Mhz */
74#define TP_CFG_M_Multiplier 37 /* " */
75#define TP_CFG_PllBypass 0 /* don't bypass */
76#define TP_CFG_ChipletEnable 0xFFFF /* Enable all chiplets */
77
78typedef struct {
79 int bDSPEnabled;
80 int bShareDspIrq;
81 int bShareUartIrq;
82 DSP_3780I_CONFIG_SETTINGS rDspSettings;
83} THINKPAD_BD_DATA;
84
85int tp3780I_InitializeBoardData(THINKPAD_BD_DATA * pBDData);
86int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData);
87int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData);
88int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData);
89int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData);
90int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData);
91int tp3780I_ResetDSP(THINKPAD_BD_DATA * pBDData);
92int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData);
93int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities);
94int tp3780I_Cleanup(THINKPAD_BD_DATA * pBDData);
95int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
96 void __user *pvBuffer, unsigned int uCount,
97 unsigned long ulDSPAddr);
98int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
99 void __user *pvBuffer, unsigned int uCount,
100 unsigned long ulDSPAddr);
101
102
103#endif