1 /*
2 	DSP M56001 emulation
3 	Host/Emulator <-> DSP glue
4 
5 	(C) 2003-2008 ARAnyM developer team
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 2 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	You should have received a copy of the GNU General Public License
18 	along with this program; if not, write to the Free Software
19 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <math.h>
29 
30 #include "dsp_core.h"
31 #include "dsp_cpu.h"
32 #include "ioMem.h"
33 #include "dsp.h"
34 #include "log.h"
35 
36 /*--- the DSP core itself ---*/
37 dsp_core_t dsp_core;
38 
39 /*--- Defines ---*/
40 #ifndef M_PI
41 #define M_PI	3.141592653589793238462643383279502
42 #endif
43 
44 /*--- Functions prototypes ---*/
45 static void dsp_core_dsp2host(void);
46 static void dsp_core_host2dsp(void);
47 
48 static void (*dsp_host_interrupt)(void);   /* Function to trigger host interrupt */
49 
50 /* Init DSP emulation */
dsp_core_init(void (* host_interrupt)(void))51 void dsp_core_init(void (*host_interrupt)(void))
52 {
53 	int i;
54 
55 	LOG_TRACE(TRACE_DSP_STATE, "Dsp: core init\n");
56 
57 	dsp_host_interrupt = host_interrupt;
58 	memset(&dsp_core, 0, sizeof(dsp_core_t));
59 
60 	/* Initialize Y:rom[0x0100-0x01ff] with a sin table */
61 	for (i=0;i<256;i++) {
62 		float src = (((float) i)*M_PI)/128.0;
63 		Sint32 dest = (Sint32) (sin(src) * 8388608.0); /* 1<<23 */
64 		if (dest>8388607) {
65 			dest = 8388607;
66 		} else if (dest<-8388608) {
67 			dest = -8388608;
68 		}
69 		dsp_core.rom[DSP_SPACE_Y][0x100+i]=dest & 0x00ffffff;
70 	}
71 
72 	/* Initialize X:rom[0x0100-0x017f] with a mu-law table */
73 	{
74 		const Uint16 mulaw_base[8]={
75 			0x7d7c, 0x3e7c, 0x1efc, 0x0f3c, 0x075c, 0x036c, 0x0174, 0x0078
76 		};
77 
78 		Uint32 position = 0x0100;
79 		Uint32 offset = 0x040000;
80 
81 		for(i=0;i<8;i++) {
82 			int j;
83 			Uint32 value = mulaw_base[i]<<8;
84 
85 			for (j=0;j<16;j++) {
86 				dsp_core.rom[DSP_SPACE_X][position++]=value;
87 				value -= offset;
88 			}
89 
90 			offset >>= 1;
91 		}
92 	}
93 
94 	/* Initialize X:rom[0x0180-0x01ff] with a a-law table */
95 	{
96 		const Sint32 multiply_base[8]={
97 			0x1580, 0x0ac0, 0x5600, 0x2b00,
98 			0x1580, 0x0058, 0x0560, 0x02b0
99 		};
100 		const Sint32 multiply_col[4]={0x10, 0x01, 0x04, 0x02};
101 		const Sint32 multiply_line[4]={0x40, 0x04, 0x10, 0x08};
102 		const Sint32 base_values[4]={0, -1, 2, 1};
103 		Uint32 pos=0x0180;
104 
105 		for (i=0;i<8;i++) {
106 			Sint32 alawbase, j;
107 
108 			alawbase = multiply_base[i]<<8;
109 			for (j=0;j<4;j++) {
110 				Sint32 alawbase1, k;
111 
112 				alawbase1 = alawbase + ((base_values[j]*multiply_line[i & 3])<<12);
113 
114 				for (k=0;k<4;k++) {
115 					Sint32 alawbase2;
116 
117 					alawbase2 = alawbase1 + ((base_values[k]*multiply_col[i & 3])<<12);
118 
119 					dsp_core.rom[DSP_SPACE_X][pos++]=alawbase2;
120 				}
121 			}
122 		}
123 	}
124 }
125 
126 /* Shutdown DSP emulation */
dsp_core_shutdown(void)127 void dsp_core_shutdown(void)
128 {
129 	dsp_core.running = 0;
130 	LOG_TRACE(TRACE_DSP_STATE, "Dsp: core shutdown\n");
131 }
132 
133 /* Reset */
dsp_core_reset(void)134 void dsp_core_reset(void)
135 {
136 	int i;
137 
138 	LOG_TRACE(TRACE_DSP_STATE, "Dsp: core reset\n");
139 	dsp_core_shutdown();
140 
141 	/* Memory */
142 	memset((void*)dsp_core.periph, 0, sizeof(dsp_core.periph));
143 	memset(dsp_core.stack, 0, sizeof(dsp_core.stack));
144 	memset(dsp_core.registers, 0, sizeof(dsp_core.registers));
145 	dsp_core.dsp_host_rtx = 0;
146 	dsp_core.dsp_host_htx = 0;
147 
148 	dsp_core.bootstrap_pos = 0;
149 
150 	/* Registers */
151 	dsp_core.pc = 0x0000;
152 	dsp_core.registers[DSP_REG_OMR]=0x02;
153 	for (i=0;i<8;i++) {
154 		dsp_core.registers[DSP_REG_M0+i]=0x00ffff;
155 	}
156 
157 	/* Interruptions */
158 	memset((void*)dsp_core.interrupt_isPending, 0, sizeof(dsp_core.interrupt_isPending));
159 	dsp_core.interrupt_state = DSP_INTERRUPT_NONE;
160 	dsp_core.interrupt_instr_fetch = -1;
161 	dsp_core.interrupt_save_pc = -1;
162 	dsp_core.interrupt_counter = 0;
163 	dsp_core.interrupt_pipeline_count = 0;
164 	for (i=0;i<5;i++) {
165 		dsp_core.interrupt_ipl[i] = 3;
166 	}
167 	for (i=5;i<12;i++) {
168 		dsp_core.interrupt_ipl[i] = -1;
169 	}
170 
171 	/* host port init, dsp side */
172 	dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]=(1<<DSP_HOST_HSR_HTDE);
173 
174 	/* host port init, cpu side */
175 	dsp_core.hostport[CPU_HOST_ICR] = 0x0;
176 	dsp_core.hostport[CPU_HOST_CVR] = 0x12;
177 	dsp_core.hostport[CPU_HOST_ISR] = (1<<CPU_HOST_ISR_TRDY)|(1<<CPU_HOST_ISR_TXDE);
178 	dsp_core.hostport[CPU_HOST_IVR] = 0x0f;
179 	dsp_core.hostport[CPU_HOST_RX0] = 0x0;
180 
181 	/* SSI registers */
182 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR]=1<<DSP_SSI_SR_TDE;
183 	dsp_core.ssi.waitFrameTX = 1;
184 	dsp_core.ssi.waitFrameRX = 1;
185 	dsp_core.ssi.TX = 0;
186 	dsp_core.ssi.RX = 0;
187 	dsp_core.ssi.dspPlay_handshakeMode_frame = 0;
188 	dsp_core_ssi_configure(DSP_SSI_CRA, 0);
189 	dsp_core_ssi_configure(DSP_SSI_CRB, 0);
190 
191 	/* Other hardware registers */
192 	dsp_core.periph[DSP_SPACE_X][DSP_IPR]=0;
193 	dsp_core.periph[DSP_SPACE_X][DSP_BCR]=0xffff;
194 
195 	/* Misc */
196 	dsp_core.loop_rep = 0;
197 
198 	LOG_TRACE(TRACE_DSP_STATE, "Dsp: reset done\n");
199 	dsp56k_init_cpu();
200 }
201 
202 /*
203 	SSI INTERFACE processing
204 */
205 
206 /* Set PortC data register : send a frame order to the DMA in handshake mode */
dsp_core_setPortCDataRegister(Uint32 value)207 void dsp_core_setPortCDataRegister(Uint32 value)
208 {
209 	/* if DSP Record is in handshake mode with DMA Play */
210 	if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x10) == 0x10) {
211 		if ((value & 0x10) == 0x10) {
212 			dsp_core.ssi.waitFrameRX = 0;
213 			DSP_SsiTransmit_SC1();
214 			LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp record in handshake mode: SSI send SC1 to crossbar\n");
215 		}
216 	}
217 
218 	/* if DSP Play is in handshake mode with DMA Record, high or low frame sync */
219 	/* to allow / disable transfer of the data */
220 	if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x20) == 0x20) {
221 		if ((value & 0x20) == 0x20) {
222 			dsp_core.ssi.dspPlay_handshakeMode_frame = 1;
223 			dsp_core.ssi.waitFrameTX = 0;
224 			LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp play in handshake mode: frame = 1\n");
225 		}
226 		else {
227 			dsp_core.ssi.dspPlay_handshakeMode_frame = 0;
228 			DSP_SsiTransmit_SC2(0);
229 			LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp play in handshake mode: SSI send SC2 to crossbar, frame sync = 0\n");
230 		}
231 	}
232 }
233 
234 /* SSI set TX register */
dsp_core_ssi_writeTX(Uint32 value)235 void dsp_core_ssi_writeTX(Uint32 value)
236 {
237 	/* Clear SSI TDE bit */
238 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TDE);
239 	dsp_core.ssi.TX = value;
240 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp set TX register: 0x%06x\n", value);
241 
242 	/* if DSP Play is in handshake mode with DMA Record, send frame sync */
243 	/* to allow transfer of the data */
244 	if (dsp_core.ssi.dspPlay_handshakeMode_frame) {
245 		DSP_SsiTransmit_SC2(1);
246 		LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp play in handshake mode: SSI send SC2 to crossbar, frame sync = 1\n");
247 	}
248 }
249 
250 /* SSI set TDE register (dummy write) */
dsp_core_ssi_writeTSR(void)251 void dsp_core_ssi_writeTSR(void)
252 {
253 	/* Dummy write : Just clear SSI TDE bit */
254 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TDE);
255 }
256 
257 /* SSI get RX register */
dsp_core_ssi_readRX(void)258 Uint32 dsp_core_ssi_readRX(void)
259 {
260 	/* Clear SSI RDF bit */
261 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_RDF);
262 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp read RX register: 0x%06x\n", dsp_core.ssi.RX);
263 	return dsp_core.ssi.RX;
264 }
265 
266 
267 /**
268  * SSI receive serial clock.
269  *
270  */
dsp_core_ssi_Receive_SC0(void)271 void dsp_core_ssi_Receive_SC0(void)
272 {
273 	Uint32 value, i, temp=0;
274 
275 	/* Receive data from crossbar to SSI */
276 	value = dsp_core.ssi.received_value;
277 
278 	/* adjust value to receive size word */
279 	value <<= (24 - dsp_core.ssi.cra_word_length);
280 	value &= 0xffffff;
281 
282 	/* if bit SHFD in CRB is set, swap received data */
283 	if (dsp_core.ssi.crb_shifter) {
284 		temp=0;
285 		for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
286 			temp += value & 1;
287 			temp <<= 1;
288 			value >>= 1;
289 		}
290 		value = temp;
291 	}
292 
293 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI received value from crossbar: 0x%06x\n", value);
294 
295 	if (dsp_core.ssi.crb_re && dsp_core.ssi.waitFrameRX == 0) {
296 		/* Send value to DSP receive */
297 		dsp_core.ssi.RX = value;
298 
299 		/* generate interrupt ? */
300 		if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_RIE)) {
301 			if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] & (1<<DSP_SSI_SR_RDF)) {
302 				dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
303 			} else {
304 				dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
305 			}
306 		}
307 	}else{
308 		dsp_core.ssi.RX = 0;
309 	}
310 
311 	/* set RDF */
312 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= 1<<DSP_SSI_SR_RDF;
313 }
314 
315 /**
316  * SSI receive SC1 bit : frame sync for receiver
317  *     value = 1 : beginning of a new frame
318  *     value = 0 : not beginning of a new frame
319  */
dsp_core_ssi_Receive_SC1(Uint32 value)320 void dsp_core_ssi_Receive_SC1(Uint32 value)
321 {
322 	/* SSI runs in network mode ? */
323 	if (dsp_core.ssi.crb_mode) {
324 		if (value) {
325 			/* Beginning of a new frame */
326 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
327 			dsp_core.ssi.waitFrameRX = 0;
328 		}else{
329 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_RFS);
330 		}
331 	}else{
332 		/* SSI runs in normal mode */
333 		dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
334 	}
335 
336 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI receive frame sync: 0x%01x\n", value);
337 }
338 
339 /**
340  * SSI receive SC2 bit : frame sync for transmitter
341  *     value = 1 : beginning of a new frame
342  *     value = 0 : not beginning of a new frame
343  */
dsp_core_ssi_Receive_SC2(Uint32 value)344 void dsp_core_ssi_Receive_SC2(Uint32 value)
345 {
346 	/* SSI runs in network mode ? */
347 	if (dsp_core.ssi.crb_mode) {
348 		if (value) {
349 			/* Beginning of a new frame */
350 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
351 			dsp_core.ssi.waitFrameTX = 0;
352 		}else{
353 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TFS);
354 		}
355 	}else{
356 		/* SSI runs in normal mode */
357 		dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
358 	}
359 
360 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit frame sync: 0x%01x\n", value);
361 }
362 
363 /**
364  * SSI transmit serial clock.
365  *
366  */
dsp_core_ssi_Receive_SCK(void)367 void dsp_core_ssi_Receive_SCK(void)
368 {
369 	Uint32 value, i, temp=0;
370 
371 	value = dsp_core.ssi.TX;
372 
373 	/* Transfer data from SSI to crossbar*/
374 
375 	/* adjust value to transnmit size word */
376 	value >>= (24 - dsp_core.ssi.cra_word_length);
377 	value &= dsp_core.ssi.cra_word_mask;
378 
379 	/* if bit SHFD in CRB is set, swap data to transmit */
380 	if (dsp_core.ssi.crb_shifter) {
381 		for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
382 			temp += value & 1;
383 			temp <<= 1;
384 			value >>= 1;
385 		}
386 		value = temp;
387 	}
388 
389 	LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit value to crossbar: 0x%06x\n", value);
390 
391 	/* Transmit the data */
392 	if (dsp_core.ssi.crb_te && dsp_core.ssi.waitFrameTX == 0) {
393 		/* Send value to crossbar */
394 		dsp_core.ssi.transmit_value = value;
395 
396 		/* generate interrupt ? */
397 		if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_TIE)) {
398 			if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] & (1<<DSP_SSI_SR_TDE)) {
399 				dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
400 			} else {
401 				dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
402 			}
403 		}
404 	}else{
405 		dsp_core.ssi.transmit_value = 0;
406 	}
407 
408 	/* set TDE */
409 	dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TDE);
410 }
411 
412 
413 /* SSI initialisations and state management */
dsp_core_ssi_configure(Uint32 address,Uint32 value)414 void dsp_core_ssi_configure(Uint32 address, Uint32 value)
415 {
416 	Uint32 crb_te, crb_re;
417 
418 	switch (address) {
419 		case DSP_SSI_CRA:
420 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRA] = value;
421 			/* get word size for transfers */
422 			switch ((value>>DSP_SSI_CRA_WL0) & 3) {
423 				case 0:
424 					dsp_core.ssi.cra_word_length = 8;
425 					dsp_core.ssi.cra_word_mask = 0xff;
426 					break;
427 				case 1:
428 					dsp_core.ssi.cra_word_length = 12;
429 					dsp_core.ssi.cra_word_mask = 0xfff;
430 					break;
431 				case 2:
432 					dsp_core.ssi.cra_word_length = 16;
433 					dsp_core.ssi.cra_word_mask = 0xffff;
434 					break;
435 				case 3:
436 					dsp_core.ssi.cra_word_length = 24;
437 					dsp_core.ssi.cra_word_mask = 0xffffff;
438 					break;
439 			}
440 
441 			LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRA write: 0x%06x\n", value);
442 
443 			/* Get the Frame rate divider ( 2 < value <32) */
444 			dsp_core.ssi.cra_frame_rate_divider = ((value >> DSP_SSI_CRA_DC0) & 0x1f)+1;
445 			break;
446 		case DSP_SSI_CRB:
447 			crb_te = dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_TE);
448 			crb_re = dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_RE);
449 			dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] = value;
450 
451 			dsp_core.ssi.crb_src_clock = (value>>DSP_SSI_CRB_SCKD) & 1;
452 			dsp_core.ssi.crb_shifter   = (value>>DSP_SSI_CRB_SHFD) & 1;
453 			dsp_core.ssi.crb_synchro   = (value>>DSP_SSI_CRB_SYN) & 1;
454 			dsp_core.ssi.crb_mode      = (value>>DSP_SSI_CRB_MOD) & 1;
455 			dsp_core.ssi.crb_te        = (value>>DSP_SSI_CRB_TE) & 1;
456 			dsp_core.ssi.crb_re        = (value>>DSP_SSI_CRB_RE) & 1;
457 			dsp_core.ssi.crb_tie       = (value>>DSP_SSI_CRB_TIE) & 1;
458 			dsp_core.ssi.crb_rie       = (value>>DSP_SSI_CRB_RIE) & 1;
459 
460 			if (crb_te == 0 && dsp_core.ssi.crb_te) {
461 				dsp_core.ssi.waitFrameTX = 1;
462 			}
463 			if (crb_re == 0 && dsp_core.ssi.crb_re) {
464 				dsp_core.ssi.waitFrameRX = 1;
465 			}
466 
467 			LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRB write: 0x%06x\n", value);
468 
469 			break;
470 	}
471 }
472 
473 
474 /*
475 	HOST INTERFACE processing
476 */
477 
dsp_core_hostport_update_trdy(void)478 static void dsp_core_hostport_update_trdy(void)
479 {
480 	int trdy;
481 
482 	/* Clear/set TRDY bit */
483 	dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TRDY);
484 	trdy = (dsp_core.hostport[CPU_HOST_ISR]>>CPU_HOST_ISR_TXDE)
485 		& ~(dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]>>DSP_HOST_HSR_HRDF);
486 	dsp_core.hostport[CPU_HOST_ISR] |= (trdy & 1)<< CPU_HOST_ISR_TRDY;
487 }
488 
dsp_core_hostport_update_hreq(void)489 static void dsp_core_hostport_update_hreq(void)
490 {
491 	int hreq;
492 
493 	hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3;
494 
495 	/* Trigger host interrupt? */
496 	if (hreq && (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_HREQ)) == 0) {
497 		dsp_host_interrupt();
498 	}
499 
500 	/* Set HREQ bit in hostport */
501 	dsp_core.hostport[CPU_HOST_ISR] &= 0x7f;
502 	dsp_core.hostport[CPU_HOST_ISR] |= (hreq?1:0) << CPU_HOST_ISR_HREQ;
503 }
504 
505 /* Host port transfer ? (dsp->host) */
dsp_core_dsp2host(void)506 static void dsp_core_dsp2host(void)
507 {
508 	/* RXDF = 1 ==> host hasn't read the last value yet */
509 	if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_RXDF)) {
510 		return;
511 	}
512 
513 	/* HTDE = 1 ==> nothing to tranfert from DSP port */
514 	if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HTDE)) {
515 		return;
516 	}
517 
518 	dsp_core.hostport[CPU_HOST_RXL] = dsp_core.dsp_host_htx;
519 	dsp_core.hostport[CPU_HOST_RXM] = dsp_core.dsp_host_htx>>8;
520 	dsp_core.hostport[CPU_HOST_RXH] = dsp_core.dsp_host_htx>>16;
521 
522 	/* Set HTDE bit to say that DSP can write */
523 	dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HTDE;
524 
525 	/* Is there an interrupt to send ? */
526 	if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HTIE)) {
527 		dsp_add_interrupt(DSP_INTER_HOST_TRX_DATA);
528 	}
529 
530 	/* Set RXDF bit to say that host can read */
531 	dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_RXDF;
532 	dsp_core_hostport_update_hreq();
533 
534 	LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Transfer 0x%06x, Dsp HTDE=1, Host RXDF=1\n", dsp_core.dsp_host_htx);
535 }
536 
537 /* Host port transfer ? (host->dsp) */
dsp_core_host2dsp(void)538 static void dsp_core_host2dsp(void)
539 {
540 	/* TXDE = 1 ==> nothing to tranfert from host port */
541 	if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TXDE)) {
542 		return;
543 	}
544 
545 	/* HRDF = 1 ==> DSP hasn't read the last value yet */
546 	if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HRDF)) {
547 		return;
548 	}
549 
550 	dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
551 	dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
552 	dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
553 
554 	/* Set HRDF bit to say that DSP can read */
555 	dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
556 
557 	/* Is there an interrupt to send ? */
558 	if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
559 		dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
560 	}
561 
562 	/* Set TXDE bit to say that host can write */
563 	dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_TXDE;
564 	dsp_core_hostport_update_hreq();
565 
566 	LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Transfer 0x%06x, Dsp HRDF=1, Host TXDE=1\n", dsp_core.dsp_host_rtx);
567 
568 	dsp_core_hostport_update_trdy();
569 }
570 
dsp_core_hostport_dspread(void)571 void dsp_core_hostport_dspread(void)
572 {
573 	/* Clear HRDF bit to say that DSP has read */
574 	dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HRDF);
575 
576 	LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF cleared\n");
577 
578 	dsp_core_hostport_update_trdy();
579 	dsp_core_host2dsp();
580 }
581 
dsp_core_hostport_dspwrite(void)582 void dsp_core_hostport_dspwrite(void)
583 {
584 	/* Clear HTDE bit to say that DSP has written */
585 	dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HTDE);
586 
587 	LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Dsp HTDE cleared\n");
588 
589 	dsp_core_dsp2host();
590 }
591 
592 /* Read/writes on host port */
dsp_core_read_host(int addr)593 Uint8 dsp_core_read_host(int addr)
594 {
595 	Uint8 value;
596 
597 	value = dsp_core.hostport[addr];
598 	if (addr == CPU_HOST_TRXL) {
599 		/* Clear RXDF bit to say that CPU has read */
600 		dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_RXDF);
601 		dsp_core_dsp2host();
602 		dsp_core_hostport_update_hreq();
603 
604 		LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Host RXDF=0\n");
605 	}
606 	return value;
607 }
608 
dsp_core_write_host(int addr,Uint8 value)609 void dsp_core_write_host(int addr, Uint8 value)
610 {
611 	switch(addr) {
612 		case CPU_HOST_ICR:
613 			dsp_core.hostport[CPU_HOST_ICR]=value & 0xfb;
614 			/* Set HF1 and HF0 accordingly on the host side */
615 			dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &=
616 					0xff-((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
617 			dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |=
618 					dsp_core.hostport[CPU_HOST_ICR] & ((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
619 			dsp_core_hostport_update_hreq();
620 			break;
621 		case CPU_HOST_CVR:
622 			dsp_core.hostport[CPU_HOST_CVR]=value & 0x9f;
623 			/* if bit 7=1, host command . HSR(bit HCP) is set*/
624 			if (value & (1<<7)) {
625 				dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= (1<<DSP_HOST_HSR_HCP);
626 				/* Is there an interrupt to send ? */
627 				if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HCIE)) {
628 					dsp_add_interrupt(DSP_INTER_HOST_COMMAND);
629 				}
630 			}
631 			else{
632 				dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff - (1<<DSP_HOST_HSR_HCP);
633 			}
634 
635 			LOG_TRACE(TRACE_DSP_HOST_COMMAND, "Dsp: (Host->DSP): Host command = %06x\n", value & 0x9f);
636 
637 			break;
638 		case CPU_HOST_ISR:
639 		case CPU_HOST_TRX0:
640 			/* Read only */
641 			break;
642 		case CPU_HOST_IVR:
643 			dsp_core.hostport[CPU_HOST_IVR]=value;
644 			break;
645 		case CPU_HOST_TRXH:
646 			dsp_core.hostport[CPU_HOST_TXH]=value;
647 			break;
648 		case CPU_HOST_TRXM:
649 			dsp_core.hostport[CPU_HOST_TXM]=value;
650 			break;
651 		case CPU_HOST_TRXL:
652 			dsp_core.hostport[CPU_HOST_TXL]=value;
653 
654 			if (!dsp_core.running) {
655 				dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos] =
656 					(dsp_core.hostport[CPU_HOST_TXH]<<16) |
657 					(dsp_core.hostport[CPU_HOST_TXM]<<8) |
658 					 dsp_core.hostport[CPU_HOST_TXL];
659 
660 				LOG_TRACE(TRACE_DSP_STATE, "Dsp: bootstrap p:0x%04x = 0x%06x\n",
661 								dsp_core.bootstrap_pos,
662 								dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos]);
663 
664 				if (++dsp_core.bootstrap_pos == 0x200) {
665 					LOG_TRACE(TRACE_DSP_STATE, "Dsp: wait bootstrap done\n");
666 					dsp_core.running = 1;
667 				}
668 			} else {
669 
670 				/* If TRDY is set, the tranfert is direct to DSP (Burst mode) */
671 				if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TRDY)){
672 					dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
673 					dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
674 					dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
675 
676 					LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Direct Transfer 0x%06x\n", dsp_core.dsp_host_rtx);
677 
678 					/* Set HRDF bit to say that DSP can read */
679 					dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
680 
681 					/* Is there an interrupt to send ? */
682 					if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
683 						dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
684 					}
685 
686 					LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF set\n");
687 				}
688 				else{
689 					/* Clear TXDE to say that CPU has written */
690 					dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TXDE);
691 					dsp_core_hostport_update_hreq();
692 
693 					LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Host TXDE cleared\n");
694 				}
695 				dsp_core_hostport_update_trdy();
696 				dsp_core_host2dsp();
697 			}
698 			break;
699 	}
700 }
701 
702 /*
703 vim:ts=4:sw=4:
704 */
705