static void spu_memload_stereo8(int leftpos,int rightpos,void *src0,size_t size) { uint8 *src = src0; uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); size = (size+7)/8; while(size--) { unsigned lval,rval,old; lval = *src++; rval = *src++; lval|= (*src++)<<8; rval|= (*src++)<<8; lval|= (*src++)<<16; rval|= (*src++)<<16; lval|= (*src++)<<24; rval|= (*src++)<<24; g2_fifo_wait(); G2_LOCK(old); *left++=lval; *right++=rval; G2_UNLOCK(old); // g2_write_32(*left++,lval); // g2_write_32(*right++,rval); // g2_fifo_wait(); } }
int main( int argc, char *argv[] ) { char buf[65536] __attribute__((aligned(32))); uint32_t aica_addr = AICA_RAM_BASE; int len; int totallen = 0; aica_disable(); /* Load ARM program from stdin and copy to ARM memory */ while( (len = read(0, buf, sizeof(buf))) > 0 ) { if(memcpy_to_aica( aica_addr, buf, len ) != 0 ) { printf( "Failed to load program!\n" ); return 1; } aica_addr += len; totallen += len; } printf( "Program loaded (%d bytes)\n", totallen); /* Main loop waiting for IO commands */ aica_enable(); do { g2_fifo_wait(); irq_disable(); int syscall = long_read(AICA_SYSCALL); irq_enable(); if( syscall != -1 ) { if( syscall == -2 ) { fprintf( stderr, "ARM aborted with general exception\n" ); return -2; } else if( syscall == SYS_EXIT ) { printf( "Exiting at ARM request\n" ); aica_disable(); return long_read(AICA_SYSCALL_ARG1); } else { uint32_t result = do_syscall( syscall, long_read(AICA_SYSCALL_ARG1), long_read(AICA_SYSCALL_ARG2), long_read(AICA_SYSCALL_ARG3) ); g2_fifo_wait(); irq_disable(); long_write( AICA_SYSCALL_RETURN, result ); long_write( AICA_SYSCALL, -1 ); irq_enable(); } } } while( 1 ); }
/* Transfer one packet of data from the AICA->SH4 queue. Expects to find AICA_CMD_MAX_SIZE dwords of space available. Returns -1 if failure, 0 for no packets available, 1 otherwise. Failure might mean a permanent failure since the queue is probably out of sync. */ int snd_aica_to_sh4(void *packetout) { uint32 bot, start, stop, top, size, cnt, *pkt32; sem_wait(sem_qram); /* Set these up for reference */ bot = SPU_RAM_BASE + AICA_MEM_RESP_QUEUE; assert_msg( g2_read_32(bot + offsetof(aica_queue_t, valid)), "Queue is not yet valid" ); top = SPU_RAM_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, size)); start = SPU_RAM_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, tail)); stop = SPU_RAM_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, head)); cnt = 0; pkt32 = (uint32 *)packetout; /* Is there anything? */ if (start == stop) { sem_signal(sem_qram); return 0; } /* Check for packet size overflow */ size = g2_read_32(start + offsetof(aica_cmd_t, size)); if (cnt >= AICA_CMD_MAX_SIZE) { sem_signal(sem_qram); dbglog(DBG_ERROR, "snd_aica_to_sh4(): packet larger than %d dwords\n", AICA_CMD_MAX_SIZE); return -1; } /* Find stop point for this packet */ stop = start + size*4; if (stop > top) stop -= top - (SPU_RAM_BASE + AICA_MEM_RESP_QUEUE); while (start != stop) { /* Fifo wait if necessary */ if (!(cnt % 8)) g2_fifo_wait(); cnt++; /* Read the next dword */ *pkt32++ = g2_read_32(start); /* Move our counters */ start += 4; if (start >= top) start = bot; cnt++; } /* Finally, write a new tail value to signify that we've removed a packet */ g2_write_32(bot + offsetof(aica_queue_t, tail), start - (SPU_RAM_BASE + AICA_MEM_RESP_QUEUE)); sem_signal(sem_qram); return 1; }
static void spu_memload_stereo16(int leftpos,int rightpos,void *src0,size_t size) { uint16 *src = src0; uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); size = (size+7)/8; while(size--) { unsigned lval,rval; lval = *src++; rval = *src++; lval|= (*src++)<<16; rval|= (*src++)<<16; g2_write_32(left++,lval); g2_write_32(right++,rval); g2_fifo_wait(); } }
/* Submit a request to the SH4->AICA queue; size is in uint32's */ int snd_sh4_to_aica(void *packet, uint32 size) { uint32 qa, bot, start, top, *pkt32, cnt; assert_msg( size < 256, "SH4->AICA packets may not be >256 uint32's long" ); sem_wait(sem_qram); /* Set these up for reference */ qa = SPU_RAM_BASE + AICA_MEM_CMD_QUEUE; assert_msg( g2_read_32(qa + offsetof(aica_queue_t, valid)), "Queue is not yet valid" ); bot = SPU_RAM_BASE + g2_read_32(qa + offsetof(aica_queue_t, data)); top = bot + g2_read_32(qa + offsetof(aica_queue_t, size)); start = bot + g2_read_32(qa + offsetof(aica_queue_t, head)); pkt32 = (uint32 *)packet; cnt = 0; while (size > 0) { /* Fifo wait if necessary */ if (!(cnt % 8)) g2_fifo_wait(); cnt++; /* Write the next dword */ g2_write_32(start, *pkt32++); /* Move our counters */ start += 4; if (start >= top) start = bot; size--; } /* Finally, write a new head value to signify that we've added a packet for it to process */ g2_write_32(qa + offsetof(aica_queue_t, head), start - bot); /* We could wait until head == tail here for processing, but there's not really much point; it'll just slow things down. */ sem_signal(sem_qram); return 0; }
static void spu_memload_stereo16(int leftpos, int rightpos, void *src0, size_t size) { register uint16 *src = src0; #if 0 sep_data(src, size, 1); dcache_flush_range((unsigned)sep_buffer, size); dmadest = rightpos; dmacnt = size / 2; spu_dma_transfer(sep_buffer[0], leftpos, size / 2, -1, spu_dma_transfer2, 0); //spu_dma_transfer(sep_buffer[1], rightpos, size / 2, -1, NULL, 0); #else register uint32 *left = (uint32*)(leftpos + SPU_RAM_BASE); register uint32 *right = (uint32*)(rightpos + SPU_RAM_BASE); size = (size+7)/8; unsigned lval, rval, old = 0; while(size--) { lval = *src++; rval = *src++; lval|= (*src++)<<16; rval|= (*src++)<<16; g2_fifo_wait(); G2_LOCK(old); *left++=lval; *right++=rval; G2_UNLOCK(old); /* g2_write_32(*left++,lval); g2_write_32(*right++,rval); g2_fifo_wait();*/ } #endif }