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  
smapi_request(unsigned short inBX,unsigned short inCX,unsigned short inDI,unsigned short inSI,unsigned short * outAX,unsigned short * outBX,unsigned short * outCX,unsigned short * outDX,unsigned short * outDI,unsigned short * outSI)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  
smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)127  int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
128  {
129  	int bRC;
130  	unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
131  	static const unsigned short ausDspBases[] = {
132  		0x0030, 0x4E30, 0x8E30, 0xCE30,
133  		0x0130, 0x0350, 0x0070, 0x0DB0 };
134  	static const unsigned short ausUartBases[] = {
135  		0x03F8, 0x02F8, 0x03E8, 0x02E8 };
136  
137  	PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg entry\n");
138  
139  	bRC = smapi_request(0x1802, 0x0000, 0, 0,
140  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
141  	if (bRC) {
142  		PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Error: Could not get DSP Settings. Aborting.\n");
143  		return bRC;
144  	}
145  
146  	PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
147  
148  	pSettings->bDSPPresent = ((usBX & 0x0100) != 0);
149  	pSettings->bDSPEnabled = ((usCX & 0x0001) != 0);
150  	pSettings->usDspIRQ = usSI & 0x00FF;
151  	pSettings->usDspDMA = (usSI & 0xFF00) >> 8;
152  	if ((usDI & 0x00FF) < ARRAY_SIZE(ausDspBases)) {
153  		pSettings->usDspBaseIO = ausDspBases[usDI & 0x00FF];
154  	} else {
155  		pSettings->usDspBaseIO = 0;
156  	}
157  	PRINTK_6(TRACE_SMAPI,
158  		"smapi::smapi_query_DSP_cfg get DSP Settings bDSPPresent %x bDSPEnabled %x usDspIRQ %x usDspDMA %x usDspBaseIO %x\n",
159  		pSettings->bDSPPresent, pSettings->bDSPEnabled,
160  		pSettings->usDspIRQ, pSettings->usDspDMA,
161  		pSettings->usDspBaseIO);
162  
163  	/* check for illegal values */
164  	if ( pSettings->usDspBaseIO == 0 )
165  		PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP base I/O address is 0\n");
166  	if ( pSettings->usDspIRQ == 0 )
167  		PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP IRQ line is 0\n");
168  
169  	bRC = smapi_request(0x1804, 0x0000, 0, 0,
170  	   	&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
171  	if (bRC) {
172  		PRINTK_ERROR("smapi::smapi_query_DSP_cfg: Error: Could not get DSP modem settings. Aborting.\n");
173  		return bRC;
174  	}
175  
176  	PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
177  
178  	pSettings->bModemEnabled = ((usCX & 0x0001) != 0);
179  	pSettings->usUartIRQ = usSI & 0x000F;
180  	if (((usSI & 0xFF00) >> 8) < ARRAY_SIZE(ausUartBases)) {
181  		pSettings->usUartBaseIO = ausUartBases[(usSI & 0xFF00) >> 8];
182  	} else {
183  		pSettings->usUartBaseIO = 0;
184  	}
185  
186  	PRINTK_4(TRACE_SMAPI,
187  		"smapi::smapi_query_DSP_cfg get DSP modem settings bModemEnabled %x usUartIRQ %x usUartBaseIO %x\n",
188  		pSettings->bModemEnabled,
189  		pSettings->usUartIRQ,
190  		pSettings->usUartBaseIO);
191  
192  	/* check for illegal values */
193  	if ( pSettings->usUartBaseIO == 0 )
194  		PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART base I/O address is 0\n");
195  	if ( pSettings->usUartIRQ == 0 )
196  		PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART IRQ line is 0\n");
197  
198  	PRINTK_2(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg exit bRC %x\n", bRC);
199  
200  	return bRC;
201  }
202  
203  
smapi_set_DSP_cfg(void)204  int smapi_set_DSP_cfg(void)
205  {
206  	int bRC = -EIO;
207  	int i;
208  	unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
209  	static const unsigned short ausDspBases[] = {
210  		0x0030, 0x4E30, 0x8E30, 0xCE30,
211  		0x0130, 0x0350, 0x0070, 0x0DB0 };
212  	static const unsigned short ausUartBases[] = {
213  		0x03F8, 0x02F8, 0x03E8, 0x02E8 };
214  	static const unsigned short ausDspIrqs[] = {
215  		5, 7, 10, 11, 15 };
216  	static const unsigned short ausUartIrqs[] = {
217  		3, 4 };
218  
219  	unsigned short dspio_index = 0, uartio_index = 0;
220  
221  	PRINTK_5(TRACE_SMAPI,
222  		"smapi::smapi_set_DSP_cfg entry mwave_3780i_irq %x mwave_3780i_io %x mwave_uart_irq %x mwave_uart_io %x\n",
223  		mwave_3780i_irq, mwave_3780i_io, mwave_uart_irq, mwave_uart_io);
224  
225  	if (mwave_3780i_io) {
226  		for (i = 0; i < ARRAY_SIZE(ausDspBases); i++) {
227  			if (mwave_3780i_io == ausDspBases[i])
228  				break;
229  		}
230  		if (i == ARRAY_SIZE(ausDspBases)) {
231  			PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_io address %x. Aborting.\n", mwave_3780i_io);
232  			return bRC;
233  		}
234  		dspio_index = i;
235  	}
236  
237  	if (mwave_3780i_irq) {
238  		for (i = 0; i < ARRAY_SIZE(ausDspIrqs); i++) {
239  			if (mwave_3780i_irq == ausDspIrqs[i])
240  				break;
241  		}
242  		if (i == ARRAY_SIZE(ausDspIrqs)) {
243  			PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_irq %x. Aborting.\n", mwave_3780i_irq);
244  			return bRC;
245  		}
246  	}
247  
248  	if (mwave_uart_io) {
249  		for (i = 0; i < ARRAY_SIZE(ausUartBases); i++) {
250  			if (mwave_uart_io == ausUartBases[i])
251  				break;
252  		}
253  		if (i == ARRAY_SIZE(ausUartBases)) {
254  			PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_io address %x. Aborting.\n", mwave_uart_io);
255  			return bRC;
256  		}
257  		uartio_index = i;
258  	}
259  
260  
261  	if (mwave_uart_irq) {
262  		for (i = 0; i < ARRAY_SIZE(ausUartIrqs); i++) {
263  			if (mwave_uart_irq == ausUartIrqs[i])
264  				break;
265  		}
266  		if (i == ARRAY_SIZE(ausUartIrqs)) {
267  			PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_irq %x. Aborting.\n", mwave_uart_irq);
268  			return bRC;
269  		}
270  	}
271  
272  	if (mwave_uart_irq || mwave_uart_io) {
273  
274  		/* Check serial port A */
275  		bRC = smapi_request(0x1402, 0x0000, 0, 0,
276  			&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
277  		if (bRC) goto exit_smapi_request_error;
278  		/* bRC == 0 */
279  		if (usBX & 0x0100) {	/* serial port A is present */
280  			if (usCX & 1) {	/* serial port is enabled */
281  				if ((usSI & 0xFF) == mwave_uart_irq) {
282  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
283  					PRINTK_ERROR(KERN_ERR_MWAVE
284  						"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
285  #else
286  					PRINTK_3(TRACE_SMAPI,
287  						"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
288  #endif
289  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
290  					PRINTK_1(TRACE_SMAPI,
291  						"smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
292  					bRC = smapi_request(0x1403, 0x0100, 0, usSI,
293  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
294  					if (bRC) goto exit_smapi_request_error;
295  					bRC = smapi_request(0x1402, 0x0000, 0, 0,
296  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
297  					if (bRC) goto exit_smapi_request_error;
298  #else
299  					goto exit_conflict;
300  #endif
301  				} else {
302  					if ((usSI >> 8) == uartio_index) {
303  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
304  						PRINTK_ERROR(KERN_ERR_MWAVE
305  							"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]);
306  #else
307  						PRINTK_3(TRACE_SMAPI,
308  							"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]);
309  #endif
310  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
311  						PRINTK_1(TRACE_SMAPI,
312  							"smapi::smapi_set_DSP_cfg Disabling conflicting serial port A\n");
313  						bRC = smapi_request (0x1403, 0x0100, 0, usSI,
314  							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
315  						if (bRC) goto exit_smapi_request_error;
316  						bRC = smapi_request (0x1402, 0x0000, 0, 0,
317  							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
318  						if (bRC) goto exit_smapi_request_error;
319  #else
320  						goto exit_conflict;
321  #endif
322  					}
323  				}
324  			}
325  		}
326  
327  		/* Check serial port B */
328  		bRC = smapi_request(0x1404, 0x0000, 0, 0,
329  			&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
330  		if (bRC) goto exit_smapi_request_error;
331  		/* bRC == 0 */
332  		if (usBX & 0x0100) {	/* serial port B is present */
333  			if (usCX & 1) {	/* serial port is enabled */
334  				if ((usSI & 0xFF) == mwave_uart_irq) {
335  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
336  					PRINTK_ERROR(KERN_ERR_MWAVE
337  						"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
338  #else
339  					PRINTK_3(TRACE_SMAPI,
340  						"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
341  #endif
342  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
343  					PRINTK_1(TRACE_SMAPI,
344  						"smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
345  					bRC = smapi_request(0x1405, 0x0100, 0, usSI,
346  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
347  					if (bRC) goto exit_smapi_request_error;
348  					bRC = smapi_request(0x1404, 0x0000, 0, 0,
349  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
350  					if (bRC) goto exit_smapi_request_error;
351  #else
352  					goto exit_conflict;
353  #endif
354  				} else {
355  					if ((usSI >> 8) == uartio_index) {
356  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
357  						PRINTK_ERROR(KERN_ERR_MWAVE
358  							"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]);
359  #else
360  						PRINTK_3(TRACE_SMAPI,
361  							"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]);
362  #endif
363  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
364  						PRINTK_1 (TRACE_SMAPI,
365  						    "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
366  						bRC = smapi_request (0x1405, 0x0100, 0, usSI,
367  							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
368  						if (bRC) goto exit_smapi_request_error;
369  						bRC = smapi_request (0x1404, 0x0000, 0, 0,
370  							&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
371  						if (bRC) goto exit_smapi_request_error;
372  #else
373  						goto exit_conflict;
374  #endif
375  					}
376  				}
377  			}
378  		}
379  
380  		/* Check IR port */
381  		bRC = smapi_request(0x1700, 0x0000, 0, 0,
382  			&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
383  		if (bRC) goto exit_smapi_request_error;
384  		bRC = smapi_request(0x1704, 0x0000, 0, 0,
385  			&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
386  		if (bRC) goto exit_smapi_request_error;
387  		/* bRC == 0 */
388  		if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
389  			if ((usCX & 0xff) == mwave_uart_irq) {
390  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
391  				PRINTK_ERROR(KERN_ERR_MWAVE
392  					"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
393  #else
394  				PRINTK_3(TRACE_SMAPI,
395  					"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
396  #endif
397  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
398  				PRINTK_1(TRACE_SMAPI,
399  					"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
400  				bRC = smapi_request(0x1701, 0x0100, 0, 0,
401  					&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
402  				if (bRC) goto exit_smapi_request_error;
403  				bRC = smapi_request(0x1700, 0, 0, 0,
404  					&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
405  				if (bRC) goto exit_smapi_request_error;
406  				bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
407  					&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
408  				if (bRC) goto exit_smapi_request_error;
409  				bRC = smapi_request(0x1704, 0x0000, 0, 0,
410  					&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
411  				if (bRC) goto exit_smapi_request_error;
412  #else
413  				goto exit_conflict;
414  #endif
415  			} else {
416  				if ((usSI & 0xff) == uartio_index) {
417  #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
418  					PRINTK_ERROR(KERN_ERR_MWAVE
419  						"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]);
420  #else
421  					PRINTK_3(TRACE_SMAPI,
422  						"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]);
423  #endif
424  #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
425  					PRINTK_1(TRACE_SMAPI,
426  						"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
427  					bRC = smapi_request(0x1701, 0x0100, 0, 0,
428  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
429  					if (bRC) goto exit_smapi_request_error;
430  					bRC = smapi_request(0x1700, 0, 0, 0,
431  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
432  					if (bRC) goto exit_smapi_request_error;
433  					bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
434  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
435  					if (bRC) goto exit_smapi_request_error;
436  					bRC = smapi_request(0x1704, 0x0000, 0, 0,
437  						&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
438  					if (bRC) goto exit_smapi_request_error;
439  #else
440  					goto exit_conflict;
441  #endif
442  				}
443  			}
444  		}
445  	}
446  
447  	bRC = smapi_request(0x1802, 0x0000, 0, 0,
448  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
449  	if (bRC) goto exit_smapi_request_error;
450  
451  	if (mwave_3780i_io) {
452  		usDI = dspio_index;
453  	}
454  	if (mwave_3780i_irq) {
455  		usSI = (usSI & 0xff00) | mwave_3780i_irq;
456  	}
457  
458  	bRC = smapi_request(0x1803, 0x0101, usDI, usSI,
459  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
460  	if (bRC) goto exit_smapi_request_error;
461  
462  	bRC = smapi_request(0x1804, 0x0000, 0, 0,
463  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
464  	if (bRC) goto exit_smapi_request_error;
465  
466  	if (mwave_uart_io) {
467  		usSI = (usSI & 0x00ff) | (uartio_index << 8);
468  	}
469  	if (mwave_uart_irq) {
470  		usSI = (usSI & 0xff00) | mwave_uart_irq;
471  	}
472  	bRC = smapi_request(0x1805, 0x0101, 0, usSI,
473  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
474  	if (bRC) goto exit_smapi_request_error;
475  
476  	bRC = smapi_request(0x1802, 0x0000, 0, 0,
477  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
478  	if (bRC) goto exit_smapi_request_error;
479  
480  	bRC = smapi_request(0x1804, 0x0000, 0, 0,
481  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
482  	if (bRC) goto exit_smapi_request_error;
483  
484  /* normal exit: */
485  	PRINTK_1(TRACE_SMAPI, "smapi::smapi_set_DSP_cfg exit\n");
486  	return 0;
487  
488  exit_conflict:
489  	/* Message has already been printed */
490  	return -EIO;
491  
492  exit_smapi_request_error:
493  	PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg exit on smapi_request error bRC %x\n", bRC);
494  	return bRC;
495  }
496  
497  
smapi_set_DSP_power_state(bool bOn)498  int smapi_set_DSP_power_state(bool bOn)
499  {
500  	int bRC;
501  	unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
502  	unsigned short usPowerFunction;
503  
504  	PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state entry bOn %x\n", bOn);
505  
506  	usPowerFunction = (bOn) ? 1 : 0;
507  
508  	bRC = smapi_request(0x4901, 0x0000, 0, usPowerFunction,
509  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
510  
511  	PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state exit bRC %x\n", bRC);
512  
513  	return bRC;
514  }
515  
516  #if 0
517  static int SmapiQuerySystemID(void)
518  {
519  	int bRC = -EIO;
520  	unsigned short usAX = 0xffff, usBX = 0xffff, usCX = 0xffff,
521  		usDX = 0xffff, usDI = 0xffff, usSI = 0xffff;
522  
523  	printk("smapi::SmapiQUerySystemID entry\n");
524  	bRC = smapi_request(0x0000, 0, 0, 0,
525  		&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
526  
527  	if (bRC == 0) {
528  		printk("AX=%x, BX=%x, CX=%x, DX=%x, DI=%x, SI=%x\n",
529  			usAX, usBX, usCX, usDX, usDI, usSI);
530  	} else {
531  		printk("smapi::SmapiQuerySystemID smapi_request error\n");
532  	}
533  
534  	return bRC;
535  }
536  #endif  /*  0  */
537  
smapi_init(void)538  int smapi_init(void)
539  {
540  	int retval = -EIO;
541  	unsigned short usSmapiID = 0;
542  	unsigned long flags;
543  
544  	PRINTK_1(TRACE_SMAPI, "smapi::smapi_init entry\n");
545  
546  	spin_lock_irqsave(&rtc_lock, flags);
547  	usSmapiID = CMOS_READ(0x7C);
548  	usSmapiID |= (CMOS_READ(0x7D) << 8);
549  	spin_unlock_irqrestore(&rtc_lock, flags);
550  	PRINTK_2(TRACE_SMAPI, "smapi::smapi_init usSmapiID %x\n", usSmapiID);
551  
552  	if (usSmapiID == 0x5349) {
553  		spin_lock_irqsave(&rtc_lock, flags);
554  		g_usSmapiPort = CMOS_READ(0x7E);
555  		g_usSmapiPort |= (CMOS_READ(0x7F) << 8);
556  		spin_unlock_irqrestore(&rtc_lock, flags);
557  		if (g_usSmapiPort == 0) {
558  			PRINTK_ERROR("smapi::smapi_init, ERROR unable to read from SMAPI port\n");
559  		} else {
560  			PRINTK_2(TRACE_SMAPI,
561  				"smapi::smapi_init, exit true g_usSmapiPort %x\n",
562  				g_usSmapiPort);
563  			retval = 0;
564  			//SmapiQuerySystemID();
565  		}
566  	} else {
567  		PRINTK_ERROR("smapi::smapi_init, ERROR invalid usSmapiID\n");
568  		retval = -ENXIO;
569  	}
570  
571  	return retval;
572  }
573