|
|
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.8 ! root 48: static void (*dsp_host_interrupt)(int); /* Function to set/clear host interrupt */
1.1.1.3 root 49:
1.1 root 50: /* Init DSP emulation */
1.1.1.8 ! root 51: void dsp_core_init(void (*host_interrupt)(int))
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;
1.1.1.8 ! root 104:
1.1 root 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;
1.1.1.8 ! root 111:
1.1 root 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.1.8 ! root 149:
1.1 root 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:
1.1.1.8 ! root 202: /*
1.1.1.2 root 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.8 ! 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.8 ! root 474: /*
1.1.1.2 root 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.8 ! root 493: #if 0
1.1.1.4 root 494: hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3;
1.1.1.3 root 495:
496: /* Trigger host interrupt? */
1.1.1.4 root 497: if (hreq && (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_HREQ)) == 0) {
1.1.1.3 root 498: dsp_host_interrupt();
499: }
500:
501: /* Set HREQ bit in hostport */
1.1.1.4 root 502: dsp_core.hostport[CPU_HOST_ISR] &= 0x7f;
503: dsp_core.hostport[CPU_HOST_ISR] |= (hreq?1:0) << CPU_HOST_ISR_HREQ;
1.1.1.8 ! root 504: #else
! 505: hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3;
! 506:
! 507: if ( hreq != 0 )
! 508: hreq = 1 << CPU_HOST_ISR_HREQ;
! 509:
! 510: /* If hreq doesn't change, we do nothing */
! 511: if ( hreq == ( dsp_core.hostport[CPU_HOST_ISR] & 0x80 ) )
! 512: return;
! 513:
! 514: if ( hreq ) /* 0->1 transition */
! 515: dsp_host_interrupt ( 1 ); /* set host interrupt */
! 516: else /* 1->0 transition */
! 517: dsp_host_interrupt ( 0 ); /* unset host interrupt */
! 518:
! 519: /* Set/clear HREQ bit in hostport */
! 520: dsp_core.hostport[CPU_HOST_ISR] &= 0x7f;
! 521: dsp_core.hostport[CPU_HOST_ISR] |= hreq;
! 522: //fprintf ( stderr , "dsp_core_hostport_update_hreq %x\n" , hreq );
! 523: #endif
! 524: }
1.1.1.2 root 525:
1.1 root 526: /* Host port transfer ? (dsp->host) */
1.1.1.4 root 527: static void dsp_core_dsp2host(void)
1.1 root 528: {
1.1.1.2 root 529: /* RXDF = 1 ==> host hasn't read the last value yet */
1.1.1.4 root 530: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_RXDF)) {
1.1 root 531: return;
532: }
1.1.1.2 root 533:
534: /* HTDE = 1 ==> nothing to tranfert from DSP port */
1.1.1.4 root 535: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HTDE)) {
1.1 root 536: return;
537: }
538:
1.1.1.4 root 539: dsp_core.hostport[CPU_HOST_RXL] = dsp_core.dsp_host_htx;
540: dsp_core.hostport[CPU_HOST_RXM] = dsp_core.dsp_host_htx>>8;
541: dsp_core.hostport[CPU_HOST_RXH] = dsp_core.dsp_host_htx>>16;
1.1 root 542:
543: /* Set HTDE bit to say that DSP can write */
1.1.1.4 root 544: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HTDE;
1.1.1.2 root 545:
546: /* Is there an interrupt to send ? */
1.1.1.4 root 547: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HTIE)) {
1.1.1.3 root 548: dsp_add_interrupt(DSP_INTER_HOST_TRX_DATA);
1.1.1.2 root 549: }
1.1 root 550:
551: /* Set RXDF bit to say that host can read */
1.1.1.4 root 552: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_RXDF;
553: dsp_core_hostport_update_hreq();
1.1.1.2 root 554:
1.1.1.4 root 555: 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 556: }
557:
558: /* Host port transfer ? (host->dsp) */
1.1.1.4 root 559: static void dsp_core_host2dsp(void)
1.1 root 560: {
1.1.1.2 root 561: /* TXDE = 1 ==> nothing to tranfert from host port */
1.1.1.4 root 562: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TXDE)) {
1.1 root 563: return;
564: }
1.1.1.8 ! root 565:
1.1.1.2 root 566: /* HRDF = 1 ==> DSP hasn't read the last value yet */
1.1.1.4 root 567: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HRDF)) {
1.1 root 568: return;
569: }
570:
1.1.1.4 root 571: dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
572: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
573: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
1.1 root 574:
575: /* Set HRDF bit to say that DSP can read */
1.1.1.4 root 576: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 577:
578: /* Is there an interrupt to send ? */
1.1.1.4 root 579: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 580: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 581: }
1.1 root 582:
583: /* Set TXDE bit to say that host can write */
1.1.1.4 root 584: dsp_core.hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_TXDE;
585: dsp_core_hostport_update_hreq();
1.1.1.2 root 586:
1.1.1.4 root 587: 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 588:
1.1.1.4 root 589: dsp_core_hostport_update_trdy();
1.1 root 590: }
591:
1.1.1.4 root 592: void dsp_core_hostport_dspread(void)
1.1 root 593: {
594: /* Clear HRDF bit to say that DSP has read */
1.1.1.4 root 595: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HRDF);
596:
597: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF cleared\n");
598:
599: dsp_core_hostport_update_trdy();
600: dsp_core_host2dsp();
1.1 root 601: }
602:
1.1.1.4 root 603: void dsp_core_hostport_dspwrite(void)
1.1 root 604: {
605: /* Clear HTDE bit to say that DSP has written */
1.1.1.4 root 606: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HTDE);
607:
608: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Dsp HTDE cleared\n");
1.1.1.3 root 609:
1.1.1.4 root 610: dsp_core_dsp2host();
1.1 root 611: }
612:
613: /* Read/writes on host port */
1.1.1.4 root 614: Uint8 dsp_core_read_host(int addr)
1.1 root 615: {
1.1.1.2 root 616: Uint8 value;
1.1 root 617:
1.1.1.4 root 618: value = dsp_core.hostport[addr];
1.1.1.2 root 619: if (addr == CPU_HOST_TRXL) {
620: /* Clear RXDF bit to say that CPU has read */
1.1.1.4 root 621: dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_RXDF);
622: dsp_core_dsp2host();
623: dsp_core_hostport_update_hreq();
1.1.1.8 ! root 624:
1.1.1.4 root 625: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (DSP->Host): Host RXDF=0\n");
1.1 root 626: }
627: return value;
628: }
629:
1.1.1.4 root 630: void dsp_core_write_host(int addr, Uint8 value)
1.1 root 631: {
632: switch(addr) {
633: case CPU_HOST_ICR:
1.1.1.4 root 634: dsp_core.hostport[CPU_HOST_ICR]=value & 0xfb;
1.1 root 635: /* Set HF1 and HF0 accordingly on the host side */
1.1.1.4 root 636: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &=
1.1 root 637: 0xff-((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
1.1.1.4 root 638: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |=
639: dsp_core.hostport[CPU_HOST_ICR] & ((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
640: dsp_core_hostport_update_hreq();
1.1 root 641: break;
642: case CPU_HOST_CVR:
1.1.1.4 root 643: dsp_core.hostport[CPU_HOST_CVR]=value & 0x9f;
1.1.1.2 root 644: /* if bit 7=1, host command . HSR(bit HCP) is set*/
1.1 root 645: if (value & (1<<7)) {
1.1.1.4 root 646: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 647: /* Is there an interrupt to send ? */
1.1.1.4 root 648: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HCIE)) {
1.1.1.3 root 649: dsp_add_interrupt(DSP_INTER_HOST_COMMAND);
1.1.1.2 root 650: }
1.1 root 651: }
1.1.1.2 root 652: else{
1.1.1.4 root 653: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff - (1<<DSP_HOST_HSR_HCP);
1.1.1.2 root 654: }
1.1.1.4 root 655:
656: LOG_TRACE(TRACE_DSP_HOST_COMMAND, "Dsp: (Host->DSP): Host command = %06x\n", value & 0x9f);
657:
1.1 root 658: break;
659: case CPU_HOST_ISR:
1.1.1.2 root 660: case CPU_HOST_TRX0:
1.1 root 661: /* Read only */
662: break;
663: case CPU_HOST_IVR:
1.1.1.4 root 664: dsp_core.hostport[CPU_HOST_IVR]=value;
1.1 root 665: break;
1.1.1.2 root 666: case CPU_HOST_TRXH:
1.1.1.4 root 667: dsp_core.hostport[CPU_HOST_TXH]=value;
1.1.1.2 root 668: break;
669: case CPU_HOST_TRXM:
1.1.1.4 root 670: dsp_core.hostport[CPU_HOST_TXM]=value;
1.1.1.2 root 671: break;
672: case CPU_HOST_TRXL:
1.1.1.4 root 673: dsp_core.hostport[CPU_HOST_TXL]=value;
1.1 root 674:
1.1.1.4 root 675: if (!dsp_core.running) {
676: dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos] =
677: (dsp_core.hostport[CPU_HOST_TXH]<<16) |
678: (dsp_core.hostport[CPU_HOST_TXM]<<8) |
679: dsp_core.hostport[CPU_HOST_TXL];
1.1.1.8 ! root 680:
1.1.1.4 root 681: LOG_TRACE(TRACE_DSP_STATE, "Dsp: bootstrap p:0x%04x = 0x%06x\n",
682: dsp_core.bootstrap_pos,
683: dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos]);
684:
685: if (++dsp_core.bootstrap_pos == 0x200) {
686: LOG_TRACE(TRACE_DSP_STATE, "Dsp: wait bootstrap done\n");
687: dsp_core.running = 1;
1.1.1.2 root 688: }
1.1 root 689: } else {
690:
1.1.1.2 root 691: /* If TRDY is set, the tranfert is direct to DSP (Burst mode) */
1.1.1.4 root 692: if (dsp_core.hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TRDY)){
693: dsp_core.dsp_host_rtx = dsp_core.hostport[CPU_HOST_TXL];
694: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXM]<<8;
695: dsp_core.dsp_host_rtx |= dsp_core.hostport[CPU_HOST_TXH]<<16;
696:
697: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Direct Transfer 0x%06x\n", dsp_core.dsp_host_rtx);
1.1.1.2 root 698:
699: /* Set HRDF bit to say that DSP can read */
1.1.1.4 root 700: dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
1.1.1.2 root 701:
702: /* Is there an interrupt to send ? */
1.1.1.4 root 703: if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] & (1<<DSP_HOST_HCR_HRIE)) {
1.1.1.3 root 704: dsp_add_interrupt(DSP_INTER_HOST_RCV_DATA);
1.1.1.2 root 705: }
1.1.1.4 root 706:
707: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Dsp HRDF set\n");
1.1.1.2 root 708: }
709: else{
710: /* Clear TXDE to say that CPU has written */
1.1.1.4 root 711: dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TXDE);
712: dsp_core_hostport_update_hreq();
713:
714: LOG_TRACE(TRACE_DSP_HOST_INTERFACE, "Dsp: (Host->DSP): Host TXDE cleared\n");
1.1.1.2 root 715: }
1.1.1.4 root 716: dsp_core_hostport_update_trdy();
717: dsp_core_host2dsp();
1.1 root 718: }
719: break;
720: }
721: }
722:
723: /*
724: vim:ts=4:sw=4:
725: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.