From: ljsebald <ljs...@us...> - 2023-11-13 17:17:20
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "A pseudo Operating System for the Dreamcast.". The branch, master has been updated via 5e0d59d084fe4ecd7a244956dbab36033e77ea83 (commit) via 2e8aaffe715ff25f312a60de122f3999528589f5 (commit) from a5a79598ba4bf76fc85a66b267eeeedf8cf6d10a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5e0d59d084fe4ecd7a244956dbab36033e77ea83 Author: Andress Barajas <and...@gm...> Date: Mon Nov 13 09:16:51 2023 -0800 ARM AICA Clean up types and spacing (#357) * Update types and spacing commit 2e8aaffe715ff25f312a60de122f3999528589f5 Author: Andress Barajas <and...@gm...> Date: Mon Nov 13 09:13:18 2023 -0800 SPU Clean (#356) * Clean SPU magic numbers and types * Apply SWAT suggestions * Added FIFO_G2 to g2_lock() * Add dbglog for deallocing channels * Use mutex when creating and destroying streams ----------------------------------------------------------------------- Summary of changes: kernel/arch/dreamcast/hardware/spu.c | 73 ++++++++++++++------------------ kernel/arch/dreamcast/include/dc/g2bus.h | 2 +- kernel/arch/dreamcast/include/dc/spu.h | 14 +++--- kernel/arch/dreamcast/sound/snd_iface.c | 39 ++++++++--------- kernel/arch/dreamcast/sound/snd_stream.c | 48 ++++++++++++--------- 5 files changed, 87 insertions(+), 89 deletions(-) diff --git a/kernel/arch/dreamcast/hardware/spu.c b/kernel/arch/dreamcast/hardware/spu.c index 2cc796c..b5c158d 100644 --- a/kernel/arch/dreamcast/hardware/spu.c +++ b/kernel/arch/dreamcast/hardware/spu.c @@ -8,7 +8,6 @@ #include <dc/spu.h> #include <dc/g2bus.h> #include <dc/sq.h> -#include <arch/memory.h> #include <arch/timer.h> /* @@ -36,22 +35,19 @@ kernel; so don't use them if you don't need to =). /* memcpy and memset designed for sound RAM; for addresses, don't bother to include the 0xa0800000 offset that is implied. 'length' must be a multiple of 4, but if it is not it will be rounded up. */ -void spu_memload(uint32 dst, void *src_void, int length) { - uint8 *src = (uint8*)src_void; +void spu_memload(uintptr_t dst, void *src_void, size_t length) { + uint8_t *src = (uint8_t *)src_void; /* Make sure it's an even number of 32-bit words and convert the count to a 32-bit word count */ - if(length % 4) - length = (length / 4) + 1; - else - length = length / 4; + length = (length + 3) >> 2; /* Add in the SPU RAM base */ - dst += 0xa0800000; + dst += SPU_RAM_UNCACHED_BASE; while(length > 8) { g2_fifo_wait(); - g2_write_block_32((uint32*)src, dst, 8); + g2_write_block_32((uint32_t *)src, dst, 8); src += 8 * 4; dst += 8 * 4; @@ -60,32 +56,33 @@ void spu_memload(uint32 dst, void *src_void, int length) { if(length > 0) { g2_fifo_wait(); - g2_write_block_32((uint32*)src, dst, length); + g2_write_block_32((uint32_t *)src, dst, length); } } -void spu_memload_sq(uint32 dst, void *src_void, int length) { - uint8 *src = (uint8 *)src_void; - int aligned_len, old; +void spu_memload_sq(uintptr_t dst, void *src_void, size_t length) { + uint8_t *src = (uint8_t *)src_void; + int aligned_len; + g2_ctx_t ctx; - /* Make sure it's an even number of 32-bit words and convert the - count to a 32-bit word count */ + /* Round up to the nearest multiple of 4 */ if(length & 3) { length = (length + 4) & ~3; } - /* Add in the SPU RAM base (cached area) */ - dst += 0x00800000; - /* Using SQs for all that is divisible by 32 */ aligned_len = length & ~31; length &= 31; - old = irq_disable(); - do { } while(*(vuint32 *)0xa05f688c & (1 << 5)); /* FIFO_SH4 */ - do { } while(*(vuint32 *)0xa05f688c & (1 << 4)); /* FIFO_G2 */ + /* Add in the SPU RAM base (cached area) */ + dst += SPU_RAM_BASE; + + /* Make sure the FIFOs are empty */ + ctx = g2_lock(); + sq_cpy((void *)dst, src, aligned_len); - irq_restore(old); + + g2_unlock(ctx); if(length > 0) { /* Make sure the destination is in a non-cached area */ @@ -93,26 +90,23 @@ void spu_memload_sq(uint32 dst, void *src_void, int length) { dst += aligned_len; src += aligned_len; g2_fifo_wait(); - g2_write_block_32((uint32 *)src, dst, length >> 2); + g2_write_block_32((uint32_t *)src, dst, length >> 2); } } -void spu_memread(void *dst_void, uint32 src, int length) { - uint8 *dst = (uint8*)dst_void; +void spu_memread(void *dst_void, uintptr_t src, size_t length) { + uint8_t *dst = (uint8_t *)dst_void; /* Make sure it's an even number of 32-bit words and convert the count to a 32-bit word count */ - if(length % 4) - length = (length / 4) + 1; - else - length = length / 4; + length = (length + 3) >> 2; /* Add in the SPU RAM base */ - src += 0xa0800000; + src += SPU_RAM_UNCACHED_BASE; while(length > 8) { g2_fifo_wait(); - g2_read_block_32((uint32*)dst, src, 8); + g2_read_block_32((uint32_t *)dst, src, 8); src += 8 * 4; dst += 8 * 4; @@ -121,27 +115,24 @@ void spu_memread(void *dst_void, uint32 src, int length) { if(length > 0) { g2_fifo_wait(); - g2_read_block_32((uint32*)dst, src, length); + g2_read_block_32((uint32_t *)dst, src, length); } } -void spu_memset(uint32 dst, unsigned long what, int length) { - uint32 blank[8]; +void spu_memset(uintptr_t dst, uint32_t what, size_t length) { + uint32_t blank[8]; int i; /* Make sure it's an even number of 32-bit words and convert the count to a 32-bit word count */ - if(length % 4) - length = (length / 4) + 1; - else - length = length / 4; + length = (length + 3) >> 2; /* Initialize the array */ for(i = 0; i < 8; i++) blank[i] = what; /* Add in the SPU RAM base */ - dst += 0xa0800000; + dst += SPU_RAM_UNCACHED_BASE; while(length > 8) { g2_fifo_wait(); @@ -249,7 +240,7 @@ int spu_init(void) { /* Load a default "program" into the SPU that just executes an infinite loop, so that CD audio works. */ g2_fifo_wait(); - g2_write_32(0xa0800000, 0xeafffff8); + g2_write_32(SPU_RAM_UNCACHED_BASE, 0xeafffff8); /* Start the SPU again */ spu_enable(); @@ -273,7 +264,7 @@ int spu_shutdown(void) { int spu_dma_transfer(void *from, uintptr_t dest, size_t length, int block, g2_dma_callback_t callback, void *cbdata) { /* Adjust destination to SPU RAM */ - dest += 0x00800000; + dest += SPU_RAM_BASE; return g2_dma_transfer(from, (void *) dest, length, block, callback, cbdata, 0, 0, G2_DMA_CHAN_SPU, 0); diff --git a/kernel/arch/dreamcast/include/dc/g2bus.h b/kernel/arch/dreamcast/include/dc/g2bus.h index 6962e19..5ce1552 100644 --- a/kernel/arch/dreamcast/include/dc/g2bus.h +++ b/kernel/arch/dreamcast/include/dc/g2bus.h @@ -161,7 +161,7 @@ static inline g2_ctx_t g2_lock(void) { G2_DMA_SUSPEND_BBA = 1; G2_DMA_SUSPEND_CH2 = 1; - while(FIFO_STATUS & FIFO_SH4); + while(FIFO_STATUS & (FIFO_SH4 | FIFO_G2)); return ctx; } diff --git a/kernel/arch/dreamcast/include/dc/spu.h b/kernel/arch/dreamcast/include/dc/spu.h index 8522146..95ca422 100644 --- a/kernel/arch/dreamcast/include/dc/spu.h +++ b/kernel/arch/dreamcast/include/dc/spu.h @@ -22,10 +22,12 @@ __BEGIN_DECLS #include <arch/types.h> +#include <arch/memory.h> #include <dc/g2bus.h> -/** \brief Waits for the sound FIFO to empty. */ -void spu_write_wait(void); +/** \brief Sound ram address from the SH4 side */ +#define SPU_RAM_BASE 0x00800000 +#define SPU_RAM_UNCACHED_BASE (MEM_AREA_P2_BASE | SPU_RAM_BASE) /** \brief Copy a block of data to sound RAM. @@ -37,7 +39,7 @@ void spu_write_wait(void); \param length The number of bytes to copy. Automatically rounded up to be a multiple of 4. */ -void spu_memload(uint32 to, void *from, int length); +void spu_memload(uintptr_t to, void *from, size_t length); /** \brief Copy a block of data to sound RAM. @@ -51,7 +53,7 @@ void spu_memload(uint32 to, void *from, int length); \param length The number of bytes to copy. Automatically rounded up to be a multiple of 4. */ -void spu_memload_sq(uint32 to, void *from, int length); +void spu_memload_sq(uintptr_t to, void *from, size_t length); /** \brief Copy a block of data from sound RAM. @@ -63,7 +65,7 @@ void spu_memload_sq(uint32 to, void *from, int length); \param length The number of bytes to copy. Automatically rounded up to be a multiple of 4. */ -void spu_memread(void *to, uint32 from, int length); +void spu_memread(void *to, uintptr_t from, size_t length); /** \brief Set a block of sound RAM to the specified value. @@ -76,7 +78,7 @@ void spu_memread(void *to, uint32 from, int length); \param length The number of bytes to copy. Automatically rounded up to be a multiple of 4. */ -void spu_memset(uint32 to, uint32 what, int length); +void spu_memset(uintptr_t to, uint32_t what, size_t length); /* DMA copy from SH-4 RAM to SPU RAM; length must be a multiple of 32, and the source and destination addresses must be aligned on 32-byte diff --git a/kernel/arch/dreamcast/sound/snd_iface.c b/kernel/arch/dreamcast/sound/snd_iface.c index 6f22f95..a3f56ed 100644 --- a/kernel/arch/dreamcast/sound/snd_iface.c +++ b/kernel/arch/dreamcast/sound/snd_iface.c @@ -19,15 +19,12 @@ #include "arm/aica_cmd_iface.h" -/* the address of the sound ram from the SH4 side */ -#define SPU_RAM_BASE 0xa0800000 - /* Are we initted? */ static int initted = 0; /* This will come from a seperately linked object file */ -extern uint8 snd_stream_drv[]; -extern uint8 snd_stream_drv_end[]; +extern uint8_t snd_stream_drv[]; +extern uint8_t snd_stream_drv_end[]; /* Thread semaphore */ static semaphore_t sem_qram; @@ -46,7 +43,7 @@ int snd_init(void) { if(amt % 4) amt = (amt + 4) & ~3; - printf("snd_init(): loading %d bytes into SPU RAM\n", amt); + dbglog(DBG_DEBUG, "snd_init(): loading %d bytes into SPU RAM\n", amt); spu_memload(0, snd_stream_drv, amt); /* Enable the AICA and give it a few ms to start up */ @@ -76,17 +73,17 @@ void snd_shutdown(void) { } /* 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; +int snd_sh4_to_aica(void *packet, uint32_t size) { + uint32_t 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; + qa = SPU_RAM_UNCACHED_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)); + bot = SPU_RAM_UNCACHED_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; @@ -125,12 +122,12 @@ int snd_sh4_to_aica(void *packet, uint32 size) { /* Start processing requests in the queue */ void snd_sh4_to_aica_start(void) { - g2_write_32(SPU_RAM_BASE + AICA_MEM_CMD_QUEUE + offsetof(aica_queue_t, process_ok), 1); + g2_write_32(SPU_RAM_UNCACHED_BASE + AICA_MEM_CMD_QUEUE + offsetof(aica_queue_t, process_ok), 1); } /* Stop processing requests in the queue */ void snd_sh4_to_aica_stop(void) { - g2_write_32(SPU_RAM_BASE + AICA_MEM_CMD_QUEUE + offsetof(aica_queue_t, process_ok), 0); + g2_write_32(SPU_RAM_UNCACHED_BASE + AICA_MEM_CMD_QUEUE + offsetof(aica_queue_t, process_ok), 0); } /* Transfer one packet of data from the AICA->SH4 queue. Expects to @@ -143,12 +140,12 @@ int snd_aica_to_sh4(void *packetout) { sem_wait(&sem_qram); /* Set these up for reference */ - bot = SPU_RAM_BASE + AICA_MEM_RESP_QUEUE; + bot = SPU_RAM_UNCACHED_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)); + top = SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, size)); + start = SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, tail)); + stop = SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE + g2_read_32(bot + offsetof(aica_queue_t, head)); cnt = 0; pkt32 = (uint32 *)packetout; @@ -171,7 +168,7 @@ int snd_aica_to_sh4(void *packetout) { stop = start + size * 4; if(stop > top) - stop -= top - (SPU_RAM_BASE + AICA_MEM_RESP_QUEUE); + stop -= top - (SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE); while(start != stop) { /* Fifo wait if necessary */ @@ -193,7 +190,7 @@ int snd_aica_to_sh4(void *packetout) { } /* 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)); + g2_write_32(bot + offsetof(aica_queue_t, tail), start - (SPU_RAM_UNCACHED_BASE + AICA_MEM_RESP_QUEUE)); sem_signal(&sem_qram); @@ -204,9 +201,9 @@ int snd_aica_to_sh4(void *packetout) { running in an interrupt handler (thread perhaps, of whoever is using us). */ void snd_poll_resp(void) { - int rv; - uint32 pkt[AICA_CMD_MAX_SIZE]; - aica_cmd_t * pktcmd; + int rv; + uint32_t pkt[AICA_CMD_MAX_SIZE]; + aica_cmd_t *pktcmd; pktcmd = (aica_cmd_t *)pkt; diff --git a/kernel/arch/dreamcast/sound/snd_stream.c b/kernel/arch/dreamcast/sound/snd_stream.c index 522422d..b379f6f 100644 --- a/kernel/arch/dreamcast/sound/snd_stream.c +++ b/kernel/arch/dreamcast/sound/snd_stream.c @@ -100,9 +100,6 @@ static uint32_t *sep_buffer[2] = {NULL, NULL}; static mutex_t stream_mutex = MUTEX_INITIALIZER; -/* the address of the sound ram from the SH4 side */ -#define SPU_RAM_BASE 0xa0800000 - #define LOCK_TIMEOUT_MS 1000 /* Check an incoming handle */ @@ -222,10 +219,11 @@ static void snd_pcm16_split_unaligned(void *buffer, void *left, void *right, siz } void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t size) { + g2_ctx_t ctx; /* SPU memory in cached area */ - left |= 0x00800000; - right |= 0x00800000; + left |= SPU_RAM_BASE; + right |= SPU_RAM_BASE; uintptr_t masked_left = SQ_MASK_DEST_ADDR(left); uintptr_t masked_right = SQ_MASK_DEST_ADDR(right); @@ -235,8 +233,8 @@ void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t /* Set store queue memory area as desired */ SET_QACR_REGS(left, right); - int old = irq_disable(); - do { } while(FIFO_STATUS & (FIFO_SH4 | FIFO_G2)); + /* Make sure the FIFOs are empty */ + ctx = g2_lock(); /* Separating channels and do fill/write queues as many times necessary. */ snd_pcm16_split_sq_start(data, masked_left, masked_right, size); @@ -245,7 +243,7 @@ void snd_pcm16_split_sq(uint32_t *data, uintptr_t left, uintptr_t right, size_t uint32_t *d = (uint32_t *)MEM_AREA_SQ_BASE; d[0] = d[8] = 0; - irq_restore(old); + g2_unlock(ctx); sq_unlock(); } @@ -295,7 +293,7 @@ static void snd_stream_prefill_part(snd_stream_hnd_t hnd, uint32_t offset) { spu_memload_sq(right, sep_buffer[1], got / 2); } -/* Prefill buffers -- do this before calling start() */ +/* Prefill buffers -- implicitly called by snd_stream_start() */ void snd_stream_prefill(snd_stream_hnd_t hnd) { CHECK_HND(hnd); @@ -314,7 +312,7 @@ void snd_stream_prefill(snd_stream_hnd_t hnd) { /* Initialize stream system */ int snd_stream_init(void) { - /* Create stereo seperation buffers */ + /* Create stereo separation buffers */ if(!sep_buffer[0]) { sep_buffer[0] = memalign(32, SND_STREAM_BUFFER_MAX); sep_buffer[1] = sep_buffer[0] + (SND_STREAM_BUFFER_MAX / 8); @@ -333,9 +331,10 @@ snd_stream_hnd_t snd_stream_alloc(snd_stream_callback_t cb, int bufsize) { int i, old; snd_stream_hnd_t hnd; + mutex_lock(&stream_mutex); + /* Get an unused handle */ hnd = -1; - old = irq_disable(); for(i = 0; i < SND_STREAM_MAX; i++) { if(!streams[i].initted) { @@ -347,10 +346,10 @@ snd_stream_hnd_t snd_stream_alloc(snd_stream_callback_t cb, int bufsize) { if(hnd != -1) streams[hnd].initted = 1; - irq_restore(old); - - if(hnd == -1) + if(hnd == -1) { + mutex_unlock(&stream_mutex); return SND_STREAM_INVALID; + } /* Default this for now */ streams[hnd].buffer_size = bufsize; @@ -373,6 +372,8 @@ snd_stream_hnd_t snd_stream_alloc(snd_stream_callback_t cb, int bufsize) { streams[hnd].ch[1] = snd_sfx_chn_alloc(); dbglog(DBG_INFO, "snd_stream: alloc'd channels %d/%d\n", streams[hnd].ch[0], streams[hnd].ch[1]); + mutex_unlock(&stream_mutex); + return hnd; } @@ -391,10 +392,14 @@ snd_stream_hnd_t snd_stream_reinit(snd_stream_hnd_t hnd, snd_stream_callback_t c void snd_stream_destroy(snd_stream_hnd_t hnd) { filter_t *c, *n; + mutex_lock(&stream_mutex); + CHECK_HND(hnd); - if(!streams[hnd].initted) + if(!streams[hnd].initted) { + mutex_unlock(&stream_mutex); return; + } snd_sfx_chn_free(streams[hnd].ch[0]); snd_sfx_chn_free(streams[hnd].ch[1]); @@ -411,7 +416,10 @@ void snd_stream_destroy(snd_stream_hnd_t hnd) { snd_stream_stop(hnd); snd_mem_free(streams[hnd].spu_ram_sch[0]); + dbglog(DBG_INFO, "snd_stream: dealloc'd channels %d/%d\n", streams[hnd].ch[0], streams[hnd].ch[1]); memset(streams + hnd, 0, sizeof(streams[0])); + + mutex_unlock(&stream_mutex); } /* Shut everything down and free mem */ @@ -503,7 +511,7 @@ static void snd_stream_start_type(snd_stream_hnd_t hnd, uint32_t type, uint32_t /* Start both channels simultaneously */ cmd->cmd_id = (1 << streams[hnd].ch[0]) | - (1 << streams[hnd].ch[1]); + (1 << streams[hnd].ch[1]); } else { /* Start one channel */ @@ -592,12 +600,12 @@ int snd_stream_poll(snd_stream_hnd_t hnd) { } /* Get channels position */ - ch0pos = g2_read_32(SPU_RAM_BASE + + ch0pos = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(stream->ch[0]) + offsetof(aica_channel_t, pos)); if(stream->channels == 2) { - ch1pos = g2_read_32(SPU_RAM_BASE + + ch1pos = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(stream->ch[1]) + ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |