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