|
|
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:
1.1.1.7 ! root 26: #include <stdio.h>
1.1 root 27: #include <string.h>
1.1.1.4 root 28: #include <math.h>
1.1 root 29:
30: #include "dsp_core.h"
31: #include "dsp_cpu.h"
1.1.1.3 root 32: #include "ioMem.h"
33: #include "dsp.h"
1.1.1.4 root 34: #include "log.h"
1.1.1.3 root 35:
1.1.1.4 root 36: /*--- the DSP core itself ---*/
37: dsp_core_t dsp_core;
1.1 root 38:
1.1.1.2 root 39: /*--- Defines ---*/
1.1 root 40: #ifndef M_PI
41: #define M_PI 3.141592653589793238462643383279502
42: #endif
43:
1.1.1.2 root 44: /*--- Functions prototypes ---*/
1.1.1.4 root 45: static void dsp_core_dsp2host(void);
46: static void dsp_core_host2dsp(void);
1.1 root 47:
1.1.1.3 root 48: static void (*dsp_host_interrupt)(void); /* Function to trigger host interrupt */
49:
1.1 root 50: /* Init DSP emulation */
1.1.1.4 root 51: void dsp_core_init(void (*host_interrupt)(void))
1.1 root 52: {
53: int i;
54:
1.1.1.4 root 55: LOG_TRACE(TRACE_DSP_STATE, "Dsp: core init\n");
1.1 root 56:
1.1.1.3 root 57: dsp_host_interrupt = host_interrupt;
1.1.1.4 root 58: memset(&dsp_core, 0, sizeof(dsp_core_t));
1.1 root 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: }
1.1.1.4 root 69: dsp_core.rom[DSP_SPACE_Y][0x100+i]=dest & 0x00ffffff;
1.1 root 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++) {
1.1.1.4 root 86: dsp_core.rom[DSP_SPACE_X][position++]=value;
1.1 root 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:
1.1.1.4 root 119: dsp_core.rom[DSP_SPACE_X][pos++]=alawbase2;
1.1 root 120: }
121: }
122: }
123: }
124: }
125:
126: /* Shutdown DSP emulation */
1.1.1.4 root 127: void dsp_core_shutdown(void)
1.1 root 128: {
1.1.1.4 root 129: dsp_core.running = 0;
130: LOG_TRACE(TRACE_DSP_STATE, "Dsp: core shutdown\n");
1.1 root 131: }
132:
133: /* Reset */
1.1.1.4 root 134: void dsp_core_reset(void)
1.1 root 135: {
136: int i;
137:
1.1.1.4 root 138: LOG_TRACE(TRACE_DSP_STATE, "Dsp: core reset\n");
139: dsp_core_shutdown();
1.1 root 140:
141: /* Memory */
1.1.1.4 root 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;
1.1 root 147:
1.1.1.4 root 148: dsp_core.bootstrap_pos = 0;
1.1 root 149:
150: /* Registers */
1.1.1.4 root 151: dsp_core.pc = 0x0000;
152: dsp_core.registers[DSP_REG_OMR]=0x02;
1.1 root 153: for (i=0;i<8;i++) {
1.1.1.4 root 154: dsp_core.registers[DSP_REG_M0+i]=0x00ffff;
1.1 root 155: }
156:
1.1.1.2 root 157: /* Interruptions */
1.1.1.4 root 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;
1.1.1.3 root 164: for (i=0;i<5;i++) {
1.1.1.4 root 165: dsp_core.interrupt_ipl[i] = 3;
1.1.1.3 root 166: }
167: for (i=5;i<12;i++) {
1.1.1.4 root 168: dsp_core.interrupt_ipl[i] = -1;
1.1.1.3 root 169: }
1.1.1.2 root 170:
1.1 root 171: /* host port init, dsp side */
1.1.1.4 root 172: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]=(1<<DSP_HOST_HSR_HTDE);
1.1 root 173:
174: /* host port init, cpu side */
1.1.1.5 root 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;
1.1 root 180:
1.1.1.2 root 181: /* SSI registers */
1.1.1.4 root 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;
1.1.1.5 root 188: dsp_core_ssi_configure(DSP_SSI_CRA, 0);
189: dsp_core_ssi_configure(DSP_SSI_CRB, 0);
190:
1.1 root 191: /* Other hardware registers */
1.1.1.4 root 192: dsp_core.periph[DSP_SPACE_X][DSP_IPR]=0;
193: dsp_core.periph[DSP_SPACE_X][DSP_BCR]=0xffff;
1.1 root 194:
195: /* Misc */
1.1.1.4 root 196: dsp_core.loop_rep = 0;
1.1 root 197:
1.1.1.4 root 198: LOG_TRACE(TRACE_DSP_STATE, "Dsp: reset done\n");
199: dsp56k_init_cpu();
1.1.1.2 root 200: }
201:
202: /*
203: SSI INTERFACE processing
204: */
205:
1.1.1.3 root 206: /* Set PortC data register : send a frame order to the DMA in handshake mode */
1.1.1.4 root 207: void dsp_core_setPortCDataRegister(Uint32 value)
1.1.1.2 root 208: {
1.1.1.3 root 209: /* if DSP Record is in handshake mode with DMA Play */
1.1.1.4 root 210: if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x10) == 0x10) {
1.1.1.3 root 211: if ((value & 0x10) == 0x10) {
1.1.1.4 root 212: dsp_core.ssi.waitFrameRX = 0;
1.1.1.3 root 213: DSP_SsiTransmit_SC1();
1.1.1.4 root 214: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp record in handshake mode: SSI send SC1 to crossbar\n");
1.1.1.3 root 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 */
1.1.1.4 root 220: if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x20) == 0x20) {
1.1.1.3 root 221: if ((value & 0x20) == 0x20) {
1.1.1.4 root 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");
1.1.1.3 root 225: }
226: else {
1.1.1.4 root 227: dsp_core.ssi.dspPlay_handshakeMode_frame = 0;
1.1.1.3 root 228: DSP_SsiTransmit_SC2(0);
1.1.1.4 root 229: 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 230: }
231: }
1.1.1.2 root 232: }
233:
234: /* SSI set TX register */
1.1.1.4 root 235: void dsp_core_ssi_writeTX(Uint32 value)
1.1.1.2 root 236: {
237: /* Clear SSI TDE bit */
1.1.1.4 root 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);
1.1.1.3 root 241:
242: /* if DSP Play is in handshake mode with DMA Record, send frame sync */
243: /* to allow transfer of the data */
1.1.1.4 root 244: if (dsp_core.ssi.dspPlay_handshakeMode_frame) {
1.1.1.3 root 245: DSP_SsiTransmit_SC2(1);
1.1.1.4 root 246: 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 247: }
1.1.1.2 root 248: }
249:
250: /* SSI set TDE register (dummy write) */
1.1.1.4 root 251: void dsp_core_ssi_writeTSR(void)
1.1.1.2 root 252: {
253: /* Dummy write : Just clear SSI TDE bit */
1.1.1.4 root 254: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TDE);
1.1.1.2 root 255: }
256:
257: /* SSI get RX register */
1.1.1.4 root 258: Uint32 dsp_core_ssi_readRX(void)
1.1.1.2 root 259: {
1.1.1.3 root 260: /* Clear SSI RDF bit */
1.1.1.4 root 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;
1.1.1.2 root 264: }
265:
1.1 root 266:
1.1.1.3 root 267: /**
268: * SSI receive serial clock.
269: *
270: */
1.1.1.4 root 271: void dsp_core_ssi_Receive_SC0(void)
1.1.1.3 root 272: {
273: Uint32 value, i, temp=0;
1.1.1.2 root 274:
275: /* Receive data from crossbar to SSI */
1.1.1.4 root 276: value = dsp_core.ssi.received_value;
1.1.1.2 root 277:
278: /* adjust value to receive size word */
1.1.1.4 root 279: value <<= (24 - dsp_core.ssi.cra_word_length);
1.1.1.2 root 280: value &= 0xffffff;
281:
282: /* if bit SHFD in CRB is set, swap received data */
1.1.1.4 root 283: if (dsp_core.ssi.crb_shifter) {
1.1.1.2 root 284: temp=0;
1.1.1.4 root 285: for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
1.1.1.2 root 286: temp += value & 1;
287: temp <<= 1;
288: value >>= 1;
289: }
290: value = temp;
291: }
292:
1.1.1.4 root 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) {
1.1.1.3 root 296: /* Send value to DSP receive */
1.1.1.4 root 297: dsp_core.ssi.RX = value;
1.1.1.3 root 298:
299: /* generate interrupt ? */
1.1.1.4 root 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)) {
1.1.1.3 root 302: dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
303: } else {
304: dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
305: }
1.1.1.2 root 306: }
1.1.1.3 root 307: }else{
1.1.1.4 root 308: dsp_core.ssi.RX = 0;
1.1 root 309: }
1.1.1.3 root 310:
311: /* set RDF */
1.1.1.4 root 312: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= 1<<DSP_SSI_SR_RDF;
1.1 root 313: }
314:
1.1.1.3 root 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: */
1.1.1.4 root 320: void dsp_core_ssi_Receive_SC1(Uint32 value)
1.1.1.2 root 321: {
1.1.1.3 root 322: /* SSI runs in network mode ? */
1.1.1.4 root 323: if (dsp_core.ssi.crb_mode) {
1.1.1.3 root 324: if (value) {
325: /* Beginning of a new frame */
1.1.1.4 root 326: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
327: dsp_core.ssi.waitFrameRX = 0;
1.1.1.3 root 328: }else{
1.1.1.4 root 329: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_RFS);
1.1.1.3 root 330: }
331: }else{
332: /* SSI runs in normal mode */
1.1.1.4 root 333: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
1.1.1.3 root 334: }
1.1.1.4 root 335:
336: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI receive frame sync: 0x%01x\n", value);
1.1.1.2 root 337: }
1.1 root 338:
1.1.1.3 root 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: */
1.1.1.4 root 344: void dsp_core_ssi_Receive_SC2(Uint32 value)
1.1 root 345: {
1.1.1.2 root 346: /* SSI runs in network mode ? */
1.1.1.4 root 347: if (dsp_core.ssi.crb_mode) {
1.1.1.3 root 348: if (value) {
349: /* Beginning of a new frame */
1.1.1.4 root 350: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
351: dsp_core.ssi.waitFrameTX = 0;
1.1.1.2 root 352: }else{
1.1.1.4 root 353: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TFS);
1.1.1.2 root 354: }
355: }else{
356: /* SSI runs in normal mode */
1.1.1.4 root 357: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
1.1 root 358: }
1.1.1.4 root 359:
360: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit frame sync: 0x%01x\n", value);
1.1 root 361: }
1.1.1.2 root 362:
1.1.1.3 root 363: /**
364: * SSI transmit serial clock.
365: *
366: */
1.1.1.4 root 367: void dsp_core_ssi_Receive_SCK(void)
1.1.1.3 root 368: {
369: Uint32 value, i, temp=0;
370:
1.1.1.4 root 371: value = dsp_core.ssi.TX;
1.1.1.3 root 372:
373: /* Transfer data from SSI to crossbar*/
374:
375: /* adjust value to transnmit size word */
1.1.1.4 root 376: value >>= (24 - dsp_core.ssi.cra_word_length);
377: value &= dsp_core.ssi.cra_word_mask;
1.1.1.3 root 378:
379: /* if bit SHFD in CRB is set, swap data to transmit */
1.1.1.4 root 380: if (dsp_core.ssi.crb_shifter) {
381: for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
1.1.1.3 root 382: temp += value & 1;
383: temp <<= 1;
384: value >>= 1;
385: }
386: value = temp;
387: }
388:
1.1.1.4 root 389: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit value to crossbar: 0x%06x\n", value);
390:
1.1.1.3 root 391: /* Transmit the data */
1.1.1.4 root 392: if (dsp_core.ssi.crb_te && dsp_core.ssi.waitFrameTX == 0) {
1.1.1.3 root 393: /* Send value to crossbar */
1.1.1.4 root 394: dsp_core.ssi.transmit_value = value;
1.1.1.3 root 395:
396: /* generate interrupt ? */
1.1.1.4 root 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)) {
1.1.1.3 root 399: dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
400: } else {
401: dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
402: }
403: }
404: }else{
1.1.1.4 root 405: dsp_core.ssi.transmit_value = 0;
1.1.1.3 root 406: }
407:
408: /* set TDE */
1.1.1.4 root 409: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TDE);
1.1.1.3 root 410: }
411:
412:
413: /* SSI initialisations and state management */
1.1.1.6 root 414: void dsp_core_ssi_configure(Uint32 address, Uint32 value)
1.1.1.2 root 415: {
1.1.1.3 root 416: Uint32 crb_te, crb_re;
1.1.1.2 root 417:
1.1.1.6 root 418: switch (address) {
1.1.1.2 root 419: case DSP_SSI_CRA:
1.1.1.4 root 420: dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRA] = value;
1.1.1.2 root 421: /* get word size for transfers */
422: switch ((value>>DSP_SSI_CRA_WL0) & 3) {
423: case 0:
1.1.1.4 root 424: dsp_core.ssi.cra_word_length = 8;
425: dsp_core.ssi.cra_word_mask = 0xff;
1.1.1.2 root 426: break;
427: case 1:
1.1.1.4 root 428: dsp_core.ssi.cra_word_length = 12;
429: dsp_core.ssi.cra_word_mask = 0xfff;
1.1.1.2 root 430: break;
431: case 2:
1.1.1.4 root 432: dsp_core.ssi.cra_word_length = 16;
433: dsp_core.ssi.cra_word_mask = 0xffff;
1.1.1.2 root 434: break;
435: case 3:
1.1.1.4 root 436: dsp_core.ssi.cra_word_length = 24;
437: dsp_core.ssi.cra_word_mask = 0xffffff;
1.1.1.2 root 438: break;
439: }
440:
1.1.1.4 root 441: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRA write: 0x%06x\n", value);
442:
1.1.1.2 root 443: /* Get the Frame rate divider ( 2 < value <32) */
1.1.1.4 root 444: dsp_core.ssi.cra_frame_rate_divider = ((value >> DSP_SSI_CRA_DC0) & 0x1f)+1;
1.1.1.2 root 445: break;
446: case DSP_SSI_CRB:
1.1.1.4 root 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;
1.1.1.2 root 450:
1.1.1.4 root 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;
1.1.1.2 root 459:
1.1.1.4 root 460: if (crb_te == 0 && dsp_core.ssi.crb_te) {
461: dsp_core.ssi.waitFrameTX = 1;
1.1.1.3 root 462: }
1.1.1.4 root 463: if (crb_re == 0 && dsp_core.ssi.crb_re) {
464: dsp_core.ssi.waitFrameRX = 1;
1.1.1.2 root 465: }
1.1.1.4 root 466:
467: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRB write: 0x%06x\n", value);
468:
1.1.1.2 root 469: break;
470: }
471: }
472:
1.1.1.3 root 473:
1.1.1.2 root 474: /*
475: HOST INTERFACE processing
476: */
477:
1.1.1.4 root 478: static void dsp_core_hostport_update_trdy(void)
1.1 root 479: {
480: int trdy;
481:
482: /* Clear/set TRDY bit */
1.1.1.4 root 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;
1.1 root 487: }
488:
1.1.1.4 root 489: static void dsp_core_hostport_update_hreq(void)
1.1.1.2 root 490: {
491: int hreq;
492:
1.1.1.4 root 493: hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3;
1.1.1.3 root 494:
495: /* Trigger host interrupt? */
1.1.1.4 root 496: if (hreq && (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_HREQ)) == 0) {
1.1.1.3 root 497: dsp_host_interrupt();
498: }
499:
500: /* Set HREQ bit in hostport */
1.1.1.4 root 501: dsp_core.hostport[CPU_HOST_ISR] &= 0x7f;
502: dsp_core.hostport[CPU_HOST_ISR] |= (hreq?1:0) << CPU_HOST_ISR_HREQ;
1.1.1.2 root 503: }
504:
1.1 root 505: /* Host port transfer ? (dsp->host) */
1.1.1.4 root 506: static void dsp_core_dsp2host(void)
1.1 root 507: {
1.1.1.2 root 508: /* RXDF = 1 ==> host hasn't read the last value yet */
1.1.1.4 root 509: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_RXDF)) {
1.1 root 510: return;
511: }
1.1.1.2 root 512:
513: /* HTDE = 1 ==> nothing to tranfert from DSP port */
1.1.1.4 root 514: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HTDE)) {
1.1 root 515: return;
516: }
517:
1.1.1.4 root 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;
1.1 root 521:
522: /* Set HTDE bit to say that DSP can write */
1.1.1.4 root 523: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HTDE;
1.1.1.2 root 524:
525: /* Is there an interrupt to send ? */
1.1.1.4 root 526: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HTIE)) {
1.1.1.3 root 527: dsp_add_interrupt(DSP_INTER_HOST_TRX_DATA);
1.1.1.2 root 528: }
1.1 root 529:
530: /* Set RXDF bit to say that host can read */
1.1.1.4 root 531: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_RXDF;
532: dsp_core_hostport_update_hreq();
1.1.1.2 root 533:
1.1.1.4 root 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);
1.1 root 535: }
536:
537: /* Host port transfer ? (host->dsp) */
1.1.1.4 root 538: static void dsp_core_host2dsp(void)
1.1 root 539: {
1.1.1.2 root 540: /* TXDE = 1 ==> nothing to tranfert from host port */
1.1.1.4 root 541: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TXDE)) {
1.1 root 542: return;
543: }
1.1.1.2 root 544:
545: /* HRDF = 1 ==> DSP hasn't read the last value yet */
1.1.1.4 root 546: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HRDF)) {
1.1 root 547: return;
548: }
549:
1.1.1.4 root 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;
1.1 root 553:
554: /* Set HRDF bit to say that DSP can read */
1.1.1.4 root 555: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 556:
557: /* Is there an interrupt to send ? */
1.1.1.4 root 558: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 559: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 560: }
1.1 root 561:
562: /* Set TXDE bit to say that host can write */
1.1.1.4 root 563: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_TXDE;
564: dsp_core_hostport_update_hreq();
1.1.1.2 root 565:
1.1.1.4 root 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);
1.1 root 567:
1.1.1.4 root 568: dsp_core_hostport_update_trdy();
1.1 root 569: }
570:
1.1.1.4 root 571: void dsp_core_hostport_dspread(void)
1.1 root 572: {
573: /* Clear HRDF bit to say that DSP has read */
1.1.1.4 root 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();
1.1 root 580: }
581:
1.1.1.4 root 582: void dsp_core_hostport_dspwrite(void)
1.1 root 583: {
584: /* Clear HTDE bit to say that DSP has written */
1.1.1.4 root 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");
1.1.1.3 root 588:
1.1.1.4 root 589: dsp_core_dsp2host();
1.1 root 590: }
591:
592: /* Read/writes on host port */
1.1.1.4 root 593: Uint8 dsp_core_read_host(int addr)
1.1 root 594: {
1.1.1.2 root 595: Uint8 value;
1.1 root 596:
1.1.1.4 root 597: value = dsp_core.hostport[addr];
1.1.1.2 root 598: if (addr == CPU_HOST_TRXL) {
599: /* Clear RXDF bit to say that CPU has read */
1.1.1.4 root 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");
1.1 root 605: }
606: return value;
607: }
608:
1.1.1.4 root 609: void dsp_core_write_host(int addr, Uint8 value)
1.1 root 610: {
611: switch(addr) {
612: case CPU_HOST_ICR:
1.1.1.4 root 613: dsp_core.hostport[CPU_HOST_ICR]=value & 0xfb;
1.1 root 614: /* Set HF1 and HF0 accordingly on the host side */
1.1.1.4 root 615: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &=
1.1 root 616: 0xff-((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
1.1.1.4 root 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();
1.1 root 620: break;
621: case CPU_HOST_CVR:
1.1.1.4 root 622: dsp_core.hostport[CPU_HOST_CVR]=value & 0x9f;
1.1.1.2 root 623: /* if bit 7=1, host command . HSR(bit HCP) is set*/
1.1 root 624: if (value & (1<<7)) {
1.1.1.4 root 625: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 626: /* Is there an interrupt to send ? */
1.1.1.4 root 627: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HCIE)) {
1.1.1.3 root 628: dsp_add_interrupt(DSP_INTER_HOST_COMMAND);
1.1.1.2 root 629: }
1.1 root 630: }
1.1.1.2 root 631: else{
1.1.1.4 root 632: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff - (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 633: }
1.1.1.4 root 634:
635: LOG_TRACE(TRACE_DSP_HOST_COMMAND, "Dsp: (Host->DSP): Host command = %06x\n", value & 0x9f);
636:
1.1 root 637: break;
638: case CPU_HOST_ISR:
1.1.1.2 root 639: case CPU_HOST_TRX0:
1.1 root 640: /* Read only */
641: break;
642: case CPU_HOST_IVR:
1.1.1.4 root 643: dsp_core.hostport[CPU_HOST_IVR]=value;
1.1 root 644: break;
1.1.1.2 root 645: case CPU_HOST_TRXH:
1.1.1.4 root 646: dsp_core.hostport[CPU_HOST_TXH]=value;
1.1.1.2 root 647: break;
648: case CPU_HOST_TRXM:
1.1.1.4 root 649: dsp_core.hostport[CPU_HOST_TXM]=value;
1.1.1.2 root 650: break;
651: case CPU_HOST_TRXL:
1.1.1.4 root 652: dsp_core.hostport[CPU_HOST_TXL]=value;
1.1 root 653:
1.1.1.4 root 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;
1.1.1.2 root 667: }
1.1 root 668: } else {
669:
1.1.1.2 root 670: /* If TRDY is set, the tranfert is direct to DSP (Burst mode) */
1.1.1.4 root 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);
1.1.1.2 root 677:
678: /* Set HRDF bit to say that DSP can read */
1.1.1.4 root 679: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 680:
681: /* Is there an interrupt to send ? */
1.1.1.4 root 682: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 683: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 684: }
1.1.1.4 root 685:
686: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF set\n");
1.1.1.2 root 687: }
688: else{
689: /* Clear TXDE to say that CPU has written */
1.1.1.4 root 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");
1.1.1.2 root 694: }
1.1.1.4 root 695: dsp_core_hostport_update_trdy();
696: dsp_core_host2dsp();
1.1 root 697: }
698: break;
699: }
700: }
701:
702: /*
703: vim:ts=4:sw=4:
704: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.