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