|
|
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.4 ! root 174: dsp_core.hostport[CPU_HOST_CVR]=0x12;
! 175: dsp_core.hostport[CPU_HOST_ISR]=(1<<CPU_HOST_ISR_TRDY)|(1<<CPU_HOST_ISR_TXDE);
! 176: dsp_core.hostport[CPU_HOST_IVR]=0x0f;
1.1 root 177:
1.1.1.2 root 178: /* SSI registers */
1.1.1.4 ! root 179: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR]=1<<DSP_SSI_SR_TDE;
! 180: dsp_core.ssi.waitFrameTX = 1;
! 181: dsp_core.ssi.waitFrameRX = 1;
! 182: dsp_core.ssi.TX = 0;
! 183: dsp_core.ssi.RX = 0;
! 184: dsp_core.ssi.dspPlay_handshakeMode_frame = 0;
1.1.1.2 root 185:
1.1 root 186: /* Other hardware registers */
1.1.1.4 ! root 187: dsp_core.periph[DSP_SPACE_X][DSP_IPR]=0;
! 188: dsp_core.periph[DSP_SPACE_X][DSP_BCR]=0xffff;
1.1 root 189:
190: /* Misc */
1.1.1.4 ! root 191: dsp_core.loop_rep = 0;
1.1 root 192:
1.1.1.4 ! root 193: LOG_TRACE(TRACE_DSP_STATE, "Dsp: reset done\n");
! 194: dsp56k_init_cpu();
1.1.1.2 root 195: }
196:
197: /*
198: SSI INTERFACE processing
199: */
200:
1.1.1.3 root 201: /* Set PortC data register : send a frame order to the DMA in handshake mode */
1.1.1.4 ! root 202: void dsp_core_setPortCDataRegister(Uint32 value)
1.1.1.2 root 203: {
1.1.1.3 root 204: /* if DSP Record is in handshake mode with DMA Play */
1.1.1.4 ! root 205: if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x10) == 0x10) {
1.1.1.3 root 206: if ((value & 0x10) == 0x10) {
1.1.1.4 ! root 207: dsp_core.ssi.waitFrameRX = 0;
1.1.1.3 root 208: DSP_SsiTransmit_SC1();
1.1.1.4 ! root 209: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp record in handshake mode: SSI send SC1 to crossbar\n");
1.1.1.3 root 210: }
211: }
212:
213: /* if DSP Play is in handshake mode with DMA Record, high or low frame sync */
214: /* to allow / disable transfer of the data */
1.1.1.4 ! root 215: if ((dsp_core.periph[DSP_SPACE_X][DSP_PCDDR] & 0x20) == 0x20) {
1.1.1.3 root 216: if ((value & 0x20) == 0x20) {
1.1.1.4 ! root 217: dsp_core.ssi.dspPlay_handshakeMode_frame = 1;
! 218: dsp_core.ssi.waitFrameTX = 0;
! 219: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp play in handshake mode: frame = 1\n");
1.1.1.3 root 220: }
221: else {
1.1.1.4 ! root 222: dsp_core.ssi.dspPlay_handshakeMode_frame = 0;
1.1.1.3 root 223: DSP_SsiTransmit_SC2(0);
1.1.1.4 ! root 224: 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 225: }
226: }
1.1.1.2 root 227: }
228:
229: /* SSI set TX register */
1.1.1.4 ! root 230: void dsp_core_ssi_writeTX(Uint32 value)
1.1.1.2 root 231: {
232: /* Clear SSI TDE bit */
1.1.1.4 ! root 233: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TDE);
! 234: dsp_core.ssi.TX = value;
! 235: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp set TX register: 0x%06x\n", value);
1.1.1.3 root 236:
237: /* if DSP Play is in handshake mode with DMA Record, send frame sync */
238: /* to allow transfer of the data */
1.1.1.4 ! root 239: if (dsp_core.ssi.dspPlay_handshakeMode_frame) {
1.1.1.3 root 240: DSP_SsiTransmit_SC2(1);
1.1.1.4 ! root 241: 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 242: }
1.1.1.2 root 243: }
244:
245: /* SSI set TDE register (dummy write) */
1.1.1.4 ! root 246: void dsp_core_ssi_writeTSR(void)
1.1.1.2 root 247: {
248: /* Dummy write : Just clear SSI TDE bit */
1.1.1.4 ! root 249: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TDE);
1.1.1.2 root 250: }
251:
252: /* SSI get RX register */
1.1.1.4 ! root 253: Uint32 dsp_core_ssi_readRX(void)
1.1.1.2 root 254: {
1.1.1.3 root 255: /* Clear SSI RDF bit */
1.1.1.4 ! root 256: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_RDF);
! 257: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp read RX register: 0x%06x\n", dsp_core.ssi.RX);
! 258: return dsp_core.ssi.RX;
1.1.1.2 root 259: }
260:
1.1 root 261:
1.1.1.3 root 262: /**
263: * SSI receive serial clock.
264: *
265: */
1.1.1.4 ! root 266: void dsp_core_ssi_Receive_SC0(void)
1.1.1.3 root 267: {
268: Uint32 value, i, temp=0;
1.1.1.2 root 269:
270: /* Receive data from crossbar to SSI */
1.1.1.4 ! root 271: value = dsp_core.ssi.received_value;
1.1.1.2 root 272:
273: /* adjust value to receive size word */
1.1.1.4 ! root 274: value <<= (24 - dsp_core.ssi.cra_word_length);
1.1.1.2 root 275: value &= 0xffffff;
276:
277: /* if bit SHFD in CRB is set, swap received data */
1.1.1.4 ! root 278: if (dsp_core.ssi.crb_shifter) {
1.1.1.2 root 279: temp=0;
1.1.1.4 ! root 280: for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
1.1.1.2 root 281: temp += value & 1;
282: temp <<= 1;
283: value >>= 1;
284: }
285: value = temp;
286: }
287:
1.1.1.4 ! root 288: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI received value from crossbar: 0x%06x\n", value);
! 289:
! 290: if (dsp_core.ssi.crb_re && dsp_core.ssi.waitFrameRX == 0) {
1.1.1.3 root 291: /* Send value to DSP receive */
1.1.1.4 ! root 292: dsp_core.ssi.RX = value;
1.1.1.3 root 293:
294: /* generate interrupt ? */
1.1.1.4 ! root 295: if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_RIE)) {
! 296: if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] & (1<<DSP_SSI_SR_RDF)) {
1.1.1.3 root 297: dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
298: } else {
299: dsp_add_interrupt(DSP_INTER_SSI_RCV_DATA);
300: }
1.1.1.2 root 301: }
1.1.1.3 root 302: }else{
1.1.1.4 ! root 303: dsp_core.ssi.RX = 0;
1.1 root 304: }
1.1.1.3 root 305:
306: /* set RDF */
1.1.1.4 ! root 307: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= 1<<DSP_SSI_SR_RDF;
1.1 root 308: }
309:
1.1.1.3 root 310: /**
311: * SSI receive SC1 bit : frame sync for receiver
312: * value = 1 : beginning of a new frame
313: * value = 0 : not beginning of a new frame
314: */
1.1.1.4 ! root 315: void dsp_core_ssi_Receive_SC1(Uint32 value)
1.1.1.2 root 316: {
1.1.1.3 root 317: /* SSI runs in network mode ? */
1.1.1.4 ! root 318: if (dsp_core.ssi.crb_mode) {
1.1.1.3 root 319: if (value) {
320: /* Beginning of a new frame */
1.1.1.4 ! root 321: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
! 322: dsp_core.ssi.waitFrameRX = 0;
1.1.1.3 root 323: }else{
1.1.1.4 ! root 324: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_RFS);
1.1.1.3 root 325: }
326: }else{
327: /* SSI runs in normal mode */
1.1.1.4 ! root 328: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_RFS);
1.1.1.3 root 329: }
1.1.1.4 ! root 330:
! 331: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI receive frame sync: 0x%01x\n", value);
1.1.1.2 root 332: }
1.1 root 333:
1.1.1.3 root 334: /**
335: * SSI receive SC2 bit : frame sync for transmitter
336: * value = 1 : beginning of a new frame
337: * value = 0 : not beginning of a new frame
338: */
1.1.1.4 ! root 339: void dsp_core_ssi_Receive_SC2(Uint32 value)
1.1 root 340: {
1.1.1.2 root 341: /* SSI runs in network mode ? */
1.1.1.4 ! root 342: if (dsp_core.ssi.crb_mode) {
1.1.1.3 root 343: if (value) {
344: /* Beginning of a new frame */
1.1.1.4 ! root 345: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
! 346: dsp_core.ssi.waitFrameTX = 0;
1.1.1.2 root 347: }else{
1.1.1.4 ! root 348: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<<DSP_SSI_SR_TFS);
1.1.1.2 root 349: }
350: }else{
351: /* SSI runs in normal mode */
1.1.1.4 ! root 352: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TFS);
1.1 root 353: }
1.1.1.4 ! root 354:
! 355: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit frame sync: 0x%01x\n", value);
1.1 root 356: }
1.1.1.2 root 357:
1.1.1.3 root 358: /**
359: * SSI transmit serial clock.
360: *
361: */
1.1.1.4 ! root 362: void dsp_core_ssi_Receive_SCK(void)
1.1.1.3 root 363: {
364: Uint32 value, i, temp=0;
365:
1.1.1.4 ! root 366: value = dsp_core.ssi.TX;
1.1.1.3 root 367:
368: /* Transfer data from SSI to crossbar*/
369:
370: /* adjust value to transnmit size word */
1.1.1.4 ! root 371: value >>= (24 - dsp_core.ssi.cra_word_length);
! 372: value &= dsp_core.ssi.cra_word_mask;
1.1.1.3 root 373:
374: /* if bit SHFD in CRB is set, swap data to transmit */
1.1.1.4 ! root 375: if (dsp_core.ssi.crb_shifter) {
! 376: for (i=0; i<dsp_core.ssi.cra_word_length; i++) {
1.1.1.3 root 377: temp += value & 1;
378: temp <<= 1;
379: value >>= 1;
380: }
381: value = temp;
382: }
383:
1.1.1.4 ! root 384: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit value to crossbar: 0x%06x\n", value);
! 385:
1.1.1.3 root 386: /* Transmit the data */
1.1.1.4 ! root 387: if (dsp_core.ssi.crb_te && dsp_core.ssi.waitFrameTX == 0) {
1.1.1.3 root 388: /* Send value to crossbar */
1.1.1.4 ! root 389: dsp_core.ssi.transmit_value = value;
1.1.1.3 root 390:
391: /* generate interrupt ? */
1.1.1.4 ! root 392: if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_TIE)) {
! 393: if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] & (1<<DSP_SSI_SR_TDE)) {
1.1.1.3 root 394: dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
395: } else {
396: dsp_add_interrupt(DSP_INTER_SSI_TRX_DATA);
397: }
398: }
399: }else{
1.1.1.4 ! root 400: dsp_core.ssi.transmit_value = 0;
1.1.1.3 root 401: }
402:
403: /* set TDE */
1.1.1.4 ! root 404: dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] |= (1<<DSP_SSI_SR_TDE);
1.1.1.3 root 405: }
406:
407:
408: /* SSI initialisations and state management */
1.1.1.4 ! root 409: void dsp_core_ssi_configure(Uint32 adress, Uint32 value)
1.1.1.2 root 410: {
1.1.1.3 root 411: Uint32 crb_te, crb_re;
1.1.1.2 root 412:
413: switch (adress) {
414: case DSP_SSI_CRA:
1.1.1.4 ! root 415: dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRA] = value;
1.1.1.2 root 416: /* get word size for transfers */
417: switch ((value>>DSP_SSI_CRA_WL0) & 3) {
418: case 0:
1.1.1.4 ! root 419: dsp_core.ssi.cra_word_length = 8;
! 420: dsp_core.ssi.cra_word_mask = 0xff;
1.1.1.2 root 421: break;
422: case 1:
1.1.1.4 ! root 423: dsp_core.ssi.cra_word_length = 12;
! 424: dsp_core.ssi.cra_word_mask = 0xfff;
1.1.1.2 root 425: break;
426: case 2:
1.1.1.4 ! root 427: dsp_core.ssi.cra_word_length = 16;
! 428: dsp_core.ssi.cra_word_mask = 0xffff;
1.1.1.2 root 429: break;
430: case 3:
1.1.1.4 ! root 431: dsp_core.ssi.cra_word_length = 24;
! 432: dsp_core.ssi.cra_word_mask = 0xffffff;
1.1.1.2 root 433: break;
434: }
435:
1.1.1.4 ! root 436: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRA write: 0x%06x\n", value);
! 437:
1.1.1.2 root 438: /* Get the Frame rate divider ( 2 < value <32) */
1.1.1.4 ! root 439: dsp_core.ssi.cra_frame_rate_divider = ((value >> DSP_SSI_CRA_DC0) & 0x1f)+1;
1.1.1.2 root 440: break;
441: case DSP_SSI_CRB:
1.1.1.4 ! root 442: crb_te = dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_TE);
! 443: crb_re = dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<<DSP_SSI_CRB_RE);
! 444: dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] = value;
1.1.1.2 root 445:
1.1.1.4 ! root 446: dsp_core.ssi.crb_src_clock = (value>>DSP_SSI_CRB_SCKD) & 1;
! 447: dsp_core.ssi.crb_shifter = (value>>DSP_SSI_CRB_SHFD) & 1;
! 448: dsp_core.ssi.crb_synchro = (value>>DSP_SSI_CRB_SYN) & 1;
! 449: dsp_core.ssi.crb_mode = (value>>DSP_SSI_CRB_MOD) & 1;
! 450: dsp_core.ssi.crb_te = (value>>DSP_SSI_CRB_TE) & 1;
! 451: dsp_core.ssi.crb_re = (value>>DSP_SSI_CRB_RE) & 1;
! 452: dsp_core.ssi.crb_tie = (value>>DSP_SSI_CRB_TIE) & 1;
! 453: dsp_core.ssi.crb_rie = (value>>DSP_SSI_CRB_RIE) & 1;
1.1.1.2 root 454:
1.1.1.4 ! root 455: if (crb_te == 0 && dsp_core.ssi.crb_te) {
! 456: dsp_core.ssi.waitFrameTX = 1;
1.1.1.3 root 457: }
1.1.1.4 ! root 458: if (crb_re == 0 && dsp_core.ssi.crb_re) {
! 459: dsp_core.ssi.waitFrameRX = 1;
1.1.1.2 root 460: }
1.1.1.4 ! root 461:
! 462: LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRB write: 0x%06x\n", value);
! 463:
1.1.1.2 root 464: break;
465: }
466: }
467:
1.1.1.3 root 468:
1.1.1.2 root 469: /*
470: HOST INTERFACE processing
471: */
472:
1.1.1.4 ! root 473: static void dsp_core_hostport_update_trdy(void)
1.1 root 474: {
475: int trdy;
476:
477: /* Clear/set TRDY bit */
1.1.1.4 ! root 478: dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TRDY);
! 479: trdy = (dsp_core.hostport[CPU_HOST_ISR]>>CPU_HOST_ISR_TXDE)
! 480: & ~(dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]>>DSP_HOST_HSR_HRDF);
! 481: dsp_core.hostport[CPU_HOST_ISR] |= (trdy & 1)<< CPU_HOST_ISR_TRDY;
1.1 root 482: }
483:
1.1.1.4 ! root 484: static void dsp_core_hostport_update_hreq(void)
1.1.1.2 root 485: {
486: int hreq;
487:
1.1.1.4 ! root 488: hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3;
1.1.1.3 root 489:
490: /* Trigger host interrupt? */
1.1.1.4 ! root 491: if (hreq && (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_HREQ)) == 0) {
1.1.1.3 root 492: dsp_host_interrupt();
493: }
494:
495: /* Set HREQ bit in hostport */
1.1.1.4 ! root 496: dsp_core.hostport[CPU_HOST_ISR] &= 0x7f;
! 497: dsp_core.hostport[CPU_HOST_ISR] |= (hreq?1:0) << CPU_HOST_ISR_HREQ;
1.1.1.2 root 498: }
499:
1.1 root 500: /* Host port transfer ? (dsp->host) */
1.1.1.4 ! root 501: static void dsp_core_dsp2host(void)
1.1 root 502: {
1.1.1.2 root 503: /* RXDF = 1 ==> host hasn't read the last value yet */
1.1.1.4 ! root 504: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_RXDF)) {
1.1 root 505: return;
506: }
1.1.1.2 root 507:
508: /* HTDE = 1 ==> nothing to tranfert from DSP port */
1.1.1.4 ! root 509: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HTDE)) {
1.1 root 510: return;
511: }
512:
1.1.1.4 ! root 513: dsp_core.hostport[CPU_HOST_RXL] = dsp_core.dsp_host_htx;
! 514: dsp_core.hostport[CPU_HOST_RXM] = dsp_core.dsp_host_htx>>8;
! 515: dsp_core.hostport[CPU_HOST_RXH] = dsp_core.dsp_host_htx>>16;
1.1 root 516:
517: /* Set HTDE bit to say that DSP can write */
1.1.1.4 ! root 518: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HTDE;
1.1.1.2 root 519:
520: /* Is there an interrupt to send ? */
1.1.1.4 ! root 521: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HTIE)) {
1.1.1.3 root 522: dsp_add_interrupt(DSP_INTER_HOST_TRX_DATA);
1.1.1.2 root 523: }
1.1 root 524:
525: /* Set RXDF bit to say that host can read */
1.1.1.4 ! root 526: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_RXDF;
! 527: dsp_core_hostport_update_hreq();
1.1.1.2 root 528:
1.1.1.4 ! root 529: 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 530: }
531:
532: /* Host port transfer ? (host->dsp) */
1.1.1.4 ! root 533: static void dsp_core_host2dsp(void)
1.1 root 534: {
1.1.1.2 root 535: /* TXDE = 1 ==> nothing to tranfert from host port */
1.1.1.4 ! root 536: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TXDE)) {
1.1 root 537: return;
538: }
1.1.1.2 root 539:
540: /* HRDF = 1 ==> DSP hasn't read the last value yet */
1.1.1.4 ! root 541: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HRDF)) {
1.1 root 542: return;
543: }
544:
1.1.1.4 ! root 545: dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
! 546: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
! 547: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
1.1 root 548:
549: /* Set HRDF bit to say that DSP can read */
1.1.1.4 ! root 550: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 551:
552: /* Is there an interrupt to send ? */
1.1.1.4 ! root 553: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 554: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 555: }
1.1 root 556:
557: /* Set TXDE bit to say that host can write */
1.1.1.4 ! root 558: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_TXDE;
! 559: dsp_core_hostport_update_hreq();
1.1.1.2 root 560:
1.1.1.4 ! root 561: 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 562:
1.1.1.4 ! root 563: dsp_core_hostport_update_trdy();
1.1 root 564: }
565:
1.1.1.4 ! root 566: void dsp_core_hostport_dspread(void)
1.1 root 567: {
568: /* Clear HRDF bit to say that DSP has read */
1.1.1.4 ! root 569: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HRDF);
! 570:
! 571: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF cleared\n");
! 572:
! 573: dsp_core_hostport_update_trdy();
! 574: dsp_core_host2dsp();
1.1 root 575: }
576:
1.1.1.4 ! root 577: void dsp_core_hostport_dspwrite(void)
1.1 root 578: {
579: /* Clear HTDE bit to say that DSP has written */
1.1.1.4 ! root 580: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HTDE);
! 581:
! 582: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Dsp HTDE cleared\n");
1.1.1.3 root 583:
1.1.1.4 ! root 584: dsp_core_dsp2host();
1.1 root 585: }
586:
587: /* Read/writes on host port */
1.1.1.4 ! root 588: Uint8 dsp_core_read_host(int addr)
1.1 root 589: {
1.1.1.2 root 590: Uint8 value;
1.1 root 591:
1.1.1.4 ! root 592: value = dsp_core.hostport[addr];
1.1.1.2 root 593: if (addr == CPU_HOST_TRXL) {
594: /* Clear RXDF bit to say that CPU has read */
1.1.1.4 ! root 595: dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_RXDF);
! 596: dsp_core_dsp2host();
! 597: dsp_core_hostport_update_hreq();
! 598:
! 599: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Host RXDF=0\n");
1.1 root 600: }
601: return value;
602: }
603:
1.1.1.4 ! root 604: void dsp_core_write_host(int addr, Uint8 value)
1.1 root 605: {
606: switch(addr) {
607: case CPU_HOST_ICR:
1.1.1.4 ! root 608: dsp_core.hostport[CPU_HOST_ICR]=value & 0xfb;
1.1 root 609: /* Set HF1 and HF0 accordingly on the host side */
1.1.1.4 ! root 610: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &=
1.1 root 611: 0xff-((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
1.1.1.4 ! root 612: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |=
! 613: dsp_core.hostport[CPU_HOST_ICR] & ((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
! 614: dsp_core_hostport_update_hreq();
1.1 root 615: break;
616: case CPU_HOST_CVR:
1.1.1.4 ! root 617: dsp_core.hostport[CPU_HOST_CVR]=value & 0x9f;
1.1.1.2 root 618: /* if bit 7=1, host command . HSR(bit HCP) is set*/
1.1 root 619: if (value & (1<<7)) {
1.1.1.4 ! root 620: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 621: /* Is there an interrupt to send ? */
1.1.1.4 ! root 622: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HCIE)) {
1.1.1.3 root 623: dsp_add_interrupt(DSP_INTER_HOST_COMMAND);
1.1.1.2 root 624: }
1.1 root 625: }
1.1.1.2 root 626: else{
1.1.1.4 ! root 627: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff - (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 628: }
1.1.1.4 ! root 629:
! 630: LOG_TRACE(TRACE_DSP_HOST_COMMAND, "Dsp: (Host->DSP): Host command = %06x\n", value & 0x9f);
! 631:
1.1 root 632: break;
633: case CPU_HOST_ISR:
1.1.1.2 root 634: case CPU_HOST_TRX0:
1.1 root 635: /* Read only */
636: break;
637: case CPU_HOST_IVR:
1.1.1.4 ! root 638: dsp_core.hostport[CPU_HOST_IVR]=value;
1.1 root 639: break;
1.1.1.2 root 640: case CPU_HOST_TRXH:
1.1.1.4 ! root 641: dsp_core.hostport[CPU_HOST_TXH]=value;
1.1.1.2 root 642: break;
643: case CPU_HOST_TRXM:
1.1.1.4 ! root 644: dsp_core.hostport[CPU_HOST_TXM]=value;
1.1.1.2 root 645: break;
646: case CPU_HOST_TRXL:
1.1.1.4 ! root 647: dsp_core.hostport[CPU_HOST_TXL]=value;
1.1 root 648:
1.1.1.4 ! root 649: if (!dsp_core.running) {
! 650: dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos] =
! 651: (dsp_core.hostport[CPU_HOST_TXH]<<16) |
! 652: (dsp_core.hostport[CPU_HOST_TXM]<<8) |
! 653: dsp_core.hostport[CPU_HOST_TXL];
! 654:
! 655: LOG_TRACE(TRACE_DSP_STATE, "Dsp: bootstrap p:0x%04x = 0x%06x\n",
! 656: dsp_core.bootstrap_pos,
! 657: dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos]);
! 658:
! 659: if (++dsp_core.bootstrap_pos == 0x200) {
! 660: LOG_TRACE(TRACE_DSP_STATE, "Dsp: wait bootstrap done\n");
! 661: dsp_core.running = 1;
1.1.1.2 root 662: }
1.1 root 663: } else {
664:
1.1.1.2 root 665: /* If TRDY is set, the tranfert is direct to DSP (Burst mode) */
1.1.1.4 ! root 666: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TRDY)){
! 667: dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
! 668: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
! 669: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
! 670:
! 671: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Direct Transfer 0x%06x\n", dsp_core.dsp_host_rtx);
1.1.1.2 root 672:
673: /* Set HRDF bit to say that DSP can read */
1.1.1.4 ! root 674: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 675:
676: /* Is there an interrupt to send ? */
1.1.1.4 ! root 677: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 678: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 679: }
1.1.1.4 ! root 680:
! 681: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF set\n");
1.1.1.2 root 682: }
683: else{
684: /* Clear TXDE to say that CPU has written */
1.1.1.4 ! root 685: dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TXDE);
! 686: dsp_core_hostport_update_hreq();
! 687:
! 688: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Host TXDE cleared\n");
1.1.1.2 root 689: }
1.1.1.4 ! root 690: dsp_core_hostport_update_trdy();
! 691: dsp_core_host2dsp();
1.1 root 692: }
693: break;
694: }
695: }
696:
697: /*
698: vim:ts=4:sw=4:
699: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.