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