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