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(); } }
/* 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; }
/* 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; }
int rtc_settimeofday(const struct timeval *tv) { uint32 val1, val2; uint32 secs = tv->tv_sec + TWENTY_YEARS; do { g2_write_32((secs & 0xffff0000) >> 16, AICA_RTC_SECS_H); g2_write_32((secs & 0xffff), AICA_RTC_SECS_L); val1 = ((g2_read_32(AICA_RTC_SECS_H) & 0xffff) << 16) | (g2_read_32(AICA_RTC_SECS_L) & 0xffff); val2 = ((g2_read_32(AICA_RTC_SECS_H) & 0xffff) << 16) | (g2_read_32(AICA_RTC_SECS_L) & 0xffff); } while (val1 != val2); return 0; }
/* Stop processing requests in the queue */ void snd_sh4_to_aica_stop() { g2_write_32(SPU_RAM_BASE + AICA_MEM_CMD_QUEUE + offsetof(aica_queue_t, process_ok), 0); }