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