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