From: quzar <qu...@us...> - 2025-01-20 01:47:11
|
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 06b0843665d5a7afa45bf7d679dccf675ec0e453 (commit) via a3231f457f3fb8442c8a7b9e78f42c10ff1f7f80 (commit) via a20c61927841e8ba0d8732c85c3409b393553b76 (commit) via 37d557dea2aa395fe980370d7915d94e1b115ff2 (commit) via 255e17c48f6439508c1b0b493f5622dc1986d6df (commit) via a5657640b2ccf425e1d6e4e4718fb03a56669c2d (commit) via 5b246dbd1ab8c5e0976197a81e91397349907b10 (commit) via c4e7a0b05d8512006950346d98cb211321b17632 (commit) via fb4ff1cefa8d86241e938db3ace0f91abe8ca572 (commit) via 8a277744e2a4c45ff7b94a4a9af894571641e3bf (commit) via 13cdb081a8a4817b194b663ef567426ccf69c285 (commit) via 1a2db8d2044573ca244eedfce78df1c8e489625c (commit) via ac37700bf34123e96086b63382d3d3d860309cbe (commit) via 04ab390efc2495ee202b92dc395ef18b992edfaa (commit) via 4dcc37545696d28251e21970bcece71263d60270 (commit) via cf41ae4243d971c263f08c4b9abd9f84c7efaedc (commit) via 61d140e37afd3284d12d6b04521782cf4ffe5475 (commit) via d721f513c09088aa47bebe696ba1955509bc604e (commit) via 063cfe2ebbf6bd9730ee1341344381dfb5f7fad0 (commit) via eb848555577d6ea21d9ce10c8194b5a56241ec84 (commit) via e5f606fdeb3d7c28a87cee110cca1ffc6f3e4afa (commit) via d9c4aae26c31a19ed4f6102fe8f301130c71ffd3 (commit) via 1f4dfb739bafb86c00d2c9f30c3af37abf112c18 (commit) via 7b1fdffbcd54ce298ab0786266f1e58e59d82e39 (commit) via 54ac13e471616e9e8ccb9dc773e29a1822e5cca9 (commit) via ddf9995ecf05e3b00c90351a67ce89080961baed (commit) via a963d200a5f2eee564f9335347e613374c284ba0 (commit) via 65a36141de8dd0aa42daa171dd09ce6fe3ce46e3 (commit) via acab06e130a1ebdbd7a8341338a4ba701341cc02 (commit) via ef6046fafad8907feb9a1c60ec012379f830fea1 (commit) from 949af4bbfdcf42bec68d87d265fa59d831f1b21b (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 06b0843665d5a7afa45bf7d679dccf675ec0e453 Merge: a3231f45 37d557de Author: Donald Haase <qu...@ya...> Date: Sun Jan 19 20:44:51 2025 -0500 Merge pull request #901 from KallistiOS/unbreak_dcload Correct logic for looking up a dir in dcload_close. commit a3231f457f3fb8442c8a7b9e78f42c10ff1f7f80 Merge: a20c6192 255e17c4 Author: Donald Haase <qu...@ya...> Date: Sun Jan 19 20:44:32 2025 -0500 Merge pull request #894 from KallistiOS/byteswap_builtins Byteswap builtins commit a20c61927841e8ba0d8732c85c3409b393553b76 Author: jnmartin84 <jnm...@gm...> Date: Sun Jan 19 20:43:52 2025 -0500 Allow `loopstart`, `loopend` setting for `snd_sfx_play_ex` (#900) These match settings already present for the aica sfx playing command. commit 37d557dea2aa395fe980370d7915d94e1b115ff2 Author: QuzarDC <qu...@co...> Date: Sun Jan 19 17:12:32 2025 -0500 Correct logic for looking up a dir in dcload_close. commit 255e17c48f6439508c1b0b493f5622dc1986d6df Author: QuzarDC <qu...@co...> Date: Sun Jan 19 14:46:14 2025 -0500 Cleanup arch byteswapping. Repalce the inline asm with gcc builtins which should allow for better optimization. Additionally make them static inline functions to leverage type checking and ease binding. commit a5657640b2ccf425e1d6e4e4718fb03a56669c2d Merge: 5b246dbd 8a277744 Author: Donald Haase <qu...@ya...> Date: Sat Jan 18 03:26:40 2025 -0500 Merge pull request #898 from pcercuei/vmufb-xbm vmufb: Add vmufb_paint_xbm() commit 5b246dbd1ab8c5e0976197a81e91397349907b10 Merge: c4e7a0b0 13cdb081 Author: Donald Haase <qu...@ya...> Date: Sat Jan 18 03:26:09 2025 -0500 Merge pull request #871 from pcercuei/dmac DMA Controller API commit c4e7a0b05d8512006950346d98cb211321b17632 Merge: fb4ff1ce 54ac13e4 Author: Donald Haase <qu...@ya...> Date: Sat Jan 18 03:25:44 2025 -0500 Merge pull request #838 from DC-SWAT/snd_stream_fill Improved sound streams data processing. commit fb4ff1cefa8d86241e938db3ace0f91abe8ca572 Merge: 949af4bb 61d140e3 Author: Donald Haase <qu...@ya...> Date: Sat Jan 18 03:25:05 2025 -0500 Merge pull request #885 from nextgeniuspro/snd_sfx_loop Add looping support to snd_sfxmgr commit 8a277744e2a4c45ff7b94a4a9af894571641e3bf Author: Paul Cercueil <pa...@cr...> Date: Fri Jan 17 12:31:17 2025 +0100 vmufb: Add vmufb_paint_xbm() This function can be used to display a X11 XBM image onto the VMU framebuffer. Signed-off-by: Paul Cercueil <pa...@cr...> commit 13cdb081a8a4817b194b663ef567426ccf69c285 Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 18:12:37 2025 +0100 examples: Add DMA speedtest example This speedtest example will benchmark the speed of the DMAC and the speed of the PVR DMA, doing transfers between RAM buffers, between VRAM buffers, and between RAM and VRAM buffers. Signed-off-by: Paul Cercueil <pa...@cr...> commit 1a2db8d2044573ca244eedfce78df1c8e489625c Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 18:15:04 2025 +0100 pvr: Flush source buffer in pvr_dma_transfer() The pvr_dma_transfer(), as well as the pvr_txr_load_dma(), pvr_dma_load_ta() and pvr_dma_yuv_conv() functions, expected the source data to be completely flushed to RAM, without it being explicitly written anywhere. Therefore, the expectation was that manual handling of the cache was not required. Update the pvr_dma_transfer() function (called by the other ones) to handle the cache flush itself. Signed-off-by: Paul Cercueil <pa...@cr...> commit ac37700bf34123e96086b63382d3d3d860309cbe Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 15:50:46 2025 +0100 timer: Set IRQ source priority with irq_set_priority() Use the dedicated API to set the IRQ source's priority. Signed-off-by: Paul Cercueil <pa...@cr...> commit 04ab390efc2495ee202b92dc395ef18b992edfaa Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 15:49:57 2025 +0100 watchdog: Set IRQ source priority with irq_set_priority() Use the dedicated API to set the IRQ source's priority. Signed-off-by: Paul Cercueil <pa...@cr...> commit 4dcc37545696d28251e21970bcece71263d60270 Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 15:49:20 2025 +0100 scif: Set IRQ source priority with irq_set_priority() Use the dedicated API to set the IRQ source's priority. Signed-off-by: Paul Cercueil <pa...@cr...> commit cf41ae4243d971c263f08c4b9abd9f84c7efaedc Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 15 15:46:58 2025 +0100 irq: Add irq_{get,set}_priority() functions The irq_set_priority() function can be used to change the priority of a given IRQ source, and to mask IRQs from a given IRQ source. The irq_get_priority() returns the priority value of a given IRQ source. Signed-off-by: Paul Cercueil <pa...@cr...> commit 61d140e37afd3284d12d6b04521782cf4ffe5475 Author: Yev <ev...@gm...> Date: Fri Jan 10 20:56:21 2025 +0100 Add looping support to snd_sfxmgr commit d721f513c09088aa47bebe696ba1955509bc604e Merge: 063cfe2e 4120477f Author: Yev <ev...@gm...> Date: Fri Jan 10 15:13:02 2025 +0100 Merge branch 'master' into snd_sfx_loop commit 063cfe2ebbf6bd9730ee1341344381dfb5f7fad0 Author: Yev <ev...@gm...> Date: Fri Jan 10 11:19:51 2025 +0100 Add looping support to snd_sfxmgr commit eb848555577d6ea21d9ce10c8194b5a56241ec84 Author: Paul Cercueil <pa...@cr...> Date: Wed Jan 8 12:46:17 2025 +0100 irq: Use regfield macros and mask DMA IRQs on shutdown Make the code more self-describing by using the regfield macros. Mask DMA IRQs on shutdown to avoid potential nasty bugs. Signed-off-by: Paul Cercueil <pa...@cr...> commit e5f606fdeb3d7c28a87cee110cca1ffc6f3e4afa Author: Paul Cercueil <pa...@cr...> Date: Sun Dec 15 17:01:31 2024 +0100 pvr: Use DMA Controller API Use the new DMA Controller API instead of poking into the DMAC registers directly. Signed-off-by: Paul Cercueil <pa...@cr...> commit d9c4aae26c31a19ed4f6102fe8f301130c71ffd3 Author: Paul Cercueil <pa...@cr...> Date: Sun Dec 15 16:10:40 2024 +0100 Add DMA Controller API Introduce an API to use the DMA Controller of the SH4. This new API can be used to program DMA transfers between memory and devices, or from memory to memory. Signed-off-by: Paul Cercueil <pa...@cr...> commit 1f4dfb739bafb86c00d2c9f30c3af37abf112c18 Author: Paul Cercueil <pa...@cr...> Date: Tue Jan 7 20:45:33 2025 +0100 irq: Unmask DMA IRQs By default, the DMA IRQs have a priority of 0, which means that they are masked. Increase that to a priority of 3, which unmasks them. Signed-off-by: Paul Cercueil <pa...@cr...> commit 7b1fdffbcd54ce298ab0786266f1e58e59d82e39 Author: Yev <ev...@gm...> Date: Tue Jan 7 17:53:56 2025 +0100 Add looping support to snd_sfxmgr commit 54ac13e471616e9e8ccb9dc773e29a1822e5cca9 Author: DC-SWAT <sw...@21...> Date: Sun Jan 5 23:49:32 2025 +0700 Add check memory allocation for sound streams. commit ddf9995ecf05e3b00c90351a67ce89080961baed Author: DC-SWAT <sw...@21...> Date: Tue Dec 10 17:47:59 2024 +0700 Fix aligment for SPU DMA in sound streams. commit a963d200a5f2eee564f9335347e613374c284ba0 Author: DC-SWAT <sw...@21...> Date: Tue Dec 10 10:46:13 2024 +0700 Handle SPU DMA errors better. commit 65a36141de8dd0aa42daa171dd09ce6fe3ce46e3 Author: DC-SWAT <sw...@21...> Date: Tue Nov 12 15:29:41 2024 +0700 Updated SND_STREAM_BUFFER_MAX commit acab06e130a1ebdbd7a8341338a4ba701341cc02 Author: DC-SWAT <sw...@21...> Date: Wed Nov 6 16:24:09 2024 +0700 Minor fixes from review suggestions. commit ef6046fafad8907feb9a1c60ec012379f830fea1 Author: DC-SWAT <sw...@21...> Date: Mon Oct 28 13:07:41 2024 +0700 Improved sound streams data processing. - Refactoring for data preparation. - Use DMA for all possible transfers. Freeup SQs. - Minor fixes and optimizations. ----------------------------------------------------------------------- Summary of changes: examples/dreamcast/basic/dma/speedtest/Makefile | 20 ++ examples/dreamcast/basic/dma/speedtest/speedtest.c | 133 +++++++ kernel/arch/dreamcast/exports-naomi.txt | 1 + kernel/arch/dreamcast/exports-pristine.txt | 1 + kernel/arch/dreamcast/fs/fs_dcload.c | 2 +- kernel/arch/dreamcast/hardware/Makefile | 2 +- kernel/arch/dreamcast/hardware/dmac.c | 162 +++++++++ kernel/arch/dreamcast/hardware/pvr/pvr_dma.c | 29 +- kernel/arch/dreamcast/hardware/pvr/pvr_irq.c | 6 - kernel/arch/dreamcast/hardware/scif.c | 4 +- kernel/arch/dreamcast/include/arch/byteorder.h | 34 +- kernel/arch/dreamcast/include/arch/dmac.h | 246 +++++++++++++ kernel/arch/dreamcast/include/arch/irq.h | 52 +++ kernel/arch/dreamcast/include/dc/sound/sfxmgr.h | 35 ++ kernel/arch/dreamcast/include/dc/sound/stream.h | 14 +- kernel/arch/dreamcast/include/dc/vmu_fb.h | 22 ++ kernel/arch/dreamcast/kernel/irq.c | 28 ++ kernel/arch/dreamcast/kernel/ser_console.c | 5 +- kernel/arch/dreamcast/kernel/timer.c | 9 +- kernel/arch/dreamcast/kernel/wdt.c | 11 +- kernel/arch/dreamcast/sound/snd_sfxmgr.c | 100 ++++-- kernel/arch/dreamcast/sound/snd_stream.c | 392 ++++++++++----------- kernel/arch/dreamcast/util/vmu_fb.c | 31 +- 23 files changed, 1036 insertions(+), 303 deletions(-) create mode 100644 examples/dreamcast/basic/dma/speedtest/Makefile create mode 100644 examples/dreamcast/basic/dma/speedtest/speedtest.c create mode 100644 kernel/arch/dreamcast/hardware/dmac.c create mode 100644 kernel/arch/dreamcast/include/arch/dmac.h diff --git a/examples/dreamcast/basic/dma/speedtest/Makefile b/examples/dreamcast/basic/dma/speedtest/Makefile new file mode 100644 index 00000000..2b1c31d9 --- /dev/null +++ b/examples/dreamcast/basic/dma/speedtest/Makefile @@ -0,0 +1,20 @@ +# +# DMA speedtest program +# Copyright (C) 2025 Paul Cercueil +# + +TARGET = speedtest.elf +OBJS = speedtest.o + +all: rm-elf $(TARGET) + +include $(KOS_BASE)/Makefile.rules + +clean: rm-elf + -rm -f $(OBJS) + +rm-elf: + -rm -f $(TARGET) + +$(TARGET): $(OBJS) + kos-cc -o $@ $^ diff --git a/examples/dreamcast/basic/dma/speedtest/speedtest.c b/examples/dreamcast/basic/dma/speedtest/speedtest.c new file mode 100644 index 00000000..9572b82a --- /dev/null +++ b/examples/dreamcast/basic/dma/speedtest/speedtest.c @@ -0,0 +1,133 @@ +/* KallistiOS ##version## + + speedtest.c + Copyright (C) 2025 Paul Cercueil +*/ + +#include <stdio.h> +#include <stdint.h> + +#include <arch/dmac.h> +#include <arch/timer.h> +#include <arch/irq.h> +#include <dc/pvr.h> +#include <kos/genwait.h> + +#define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0) + +#define BUF_SIZE (1024 * 1024) + +static alignas(32) char buf1[BUF_SIZE]; +static alignas(32) char buf2[BUF_SIZE]; + +static void dma_done(void *d) +{ + *(uint64_t *)d = timer_us_gettime64(); + genwait_wake_all(d); +} + +static dma_config_t dma_cfg = { + .channel = 1, + .request = DMA_REQUEST_AUTO_MEM_TO_MEM, + .unit_size = DMA_UNITSIZE_32BYTE, + .src_mode = DMA_ADDRMODE_INCREMENT, + .dst_mode = DMA_ADDRMODE_INCREMENT, + .transmit_mode = DMA_TRANSMITMODE_BURST, + .callback = dma_done, +}; + +static uint64_t +do_dma_transfer(unsigned int test, pvr_ptr_t vram1, pvr_ptr_t vram2) +{ + uint64_t before, after = 0; + + irq_disable_scoped(); + + before = timer_us_gettime64(); + + switch (test) { + case 0: + /* RAM to RAM */ + dma_transfer(&dma_cfg, + dma_map_dst(buf1, BUF_SIZE), + dma_map_src(buf2, BUF_SIZE), + BUF_SIZE, &after); + break; + case 1: + /* RAM to VRAM */ + dma_transfer(&dma_cfg, + hw_to_dma_addr((uintptr_t)vram1), + dma_map_src(buf2, BUF_SIZE), + BUF_SIZE, &after); + break; + case 2: + /* VRAM to RAM */ + dma_transfer(&dma_cfg, + dma_map_dst(buf1, BUF_SIZE), + hw_to_dma_addr((uintptr_t)vram1), + BUF_SIZE, &after); + break; + case 3: + /* VRAM to VRAM */ + dma_transfer(&dma_cfg, + hw_to_dma_addr((uintptr_t)vram1), + hw_to_dma_addr((uintptr_t)vram2), + BUF_SIZE, &after); + break; + case 4: + /* RAM to VRAM using SQs */ + pvr_txr_load(buf1, vram1, BUF_SIZE); + + return timer_us_gettime64() - before; + case 5: + /* RAM to 64-bit VRAM using PVR DMA */ + pvr_txr_load_dma(buf1, vram1, BUF_SIZE, + 0, dma_done, &after); + break; + case 6: + /* RAM to 32-bit VRAM using PVR DMA */ + pvr_dma_transfer(buf1, (uintptr_t)vram1, BUF_SIZE, + PVR_DMA_VRAM32, 0, + dma_done, &after); + break; + } + + while ((volatile uint64_t)after == 0) + genwait_wait(&after, "IRQ wait", 0, NULL); + + return after - before; +} + +static const char * const test_lbl[] = { + "DMAC, RAM to RAM: ", + "DMAC, RAM to VRAM: ", + "DMAC, VRAM to RAM: ", + "DMAC, VRAM to VRAM: ", + "PVR SQs: ", + "PVR DMA, 64-bit: ", + "PVR DMA, 32-bit: ", +}; + +int main(int argc, char **argv) +{ + pvr_ptr_t vram, vram2; + uint64_t time_us; + unsigned int i; + + pvr_init_defaults(); + + vram = pvr_mem_malloc(BUF_SIZE); + vram2 = pvr_mem_malloc(BUF_SIZE); + + for (i = 0; i < ARRAY_SIZE(test_lbl); i++) { + time_us = do_dma_transfer(i, vram, vram2); + printf("%s%f MiB/s\n", + test_lbl[i], (float)BUF_SIZE / (float)time_us); + + } + + pvr_mem_free(vram); + pvr_mem_free(vram2); + + return 0; +} diff --git a/kernel/arch/dreamcast/exports-naomi.txt b/kernel/arch/dreamcast/exports-naomi.txt index 20fac7bb..8624b585 100644 --- a/kernel/arch/dreamcast/exports-naomi.txt +++ b/kernel/arch/dreamcast/exports-naomi.txt @@ -118,6 +118,7 @@ snd_sfx_load_fd snd_sfx_play snd_sfx_stop_all snd_sfx_play_chn +snd_sfx_play_ex snd_sfx_stop snd_sfx_chn_alloc snd_sfx_chn_free diff --git a/kernel/arch/dreamcast/exports-pristine.txt b/kernel/arch/dreamcast/exports-pristine.txt index 829d112d..ac7531ab 100644 --- a/kernel/arch/dreamcast/exports-pristine.txt +++ b/kernel/arch/dreamcast/exports-pristine.txt @@ -174,6 +174,7 @@ snd_sfx_load_fd snd_sfx_play snd_sfx_stop_all snd_sfx_play_chn +snd_sfx_play_ex snd_sfx_stop snd_sfx_chn_alloc snd_sfx_chn_free diff --git a/kernel/arch/dreamcast/fs/fs_dcload.c b/kernel/arch/dreamcast/fs/fs_dcload.c index b27c935e..302db0b1 100644 --- a/kernel/arch/dreamcast/fs/fs_dcload.c +++ b/kernel/arch/dreamcast/fs/fs_dcload.c @@ -175,7 +175,7 @@ static int dcload_close(void * h) { i = hnd_is_dir(hnd); /* We found it in the list, so it's a dir */ - if(!i) { + if(i) { dclsc(DCLOAD_CLOSEDIR, hnd); LIST_REMOVE(i, fhlist); free(i->path); diff --git a/kernel/arch/dreamcast/hardware/Makefile b/kernel/arch/dreamcast/hardware/Makefile index f83f51db..bf010e51 100644 --- a/kernel/arch/dreamcast/hardware/Makefile +++ b/kernel/arch/dreamcast/hardware/Makefile @@ -28,7 +28,7 @@ OBJS += asic.o g2bus.o OBJS += video.o vblank.o # CPU-related -OBJS += sq.o sq_fast_cpy.o scif.o ubc.o +OBJS += sq.o sq_fast_cpy.o scif.o ubc.o dmac.o # SPI device support OBJS += scif-spi.o sd.o diff --git a/kernel/arch/dreamcast/hardware/dmac.c b/kernel/arch/dreamcast/hardware/dmac.c new file mode 100644 index 00000000..67bd9c54 --- /dev/null +++ b/kernel/arch/dreamcast/hardware/dmac.c @@ -0,0 +1,162 @@ +#include <arch/cache.h> +#include <arch/dmac.h> +#include <arch/irq.h> +#include <arch/memory.h> +#include <kos/dbglog.h> +#include <kos/genwait.h> +#include <kos/regfield.h> + +#include <errno.h> + +#define DMAC_BASE 0xffa00000 + +typedef enum dma_register { + DMA_REG_SAR = 0x00, /* Source Address Register */ + DMA_REG_DAR = 0x04, /* Destination Address Register */ + DMA_REG_TCR = 0x08, /* Transfer Count Register */ + DMA_REG_CHCR = 0x0C, /* Channel Control Register */ + DMA_REG_DMAOR = 0x40, /* DMA Operation Register */ +} dma_register_t; + +#define REG_CHCR_DST_ADDRMODE GENMASK(15, 14) +#define REG_CHCR_SRC_ADDRMODE GENMASK(13, 12) +#define REG_CHCR_REQUEST GENMASK(11, 8) +#define REG_CHCR_TRANSMIT_MODE BIT(7) +#define REG_CHCR_BUSWIDTH GENMASK(6, 4) +#define REG_CHCR_INTERRUPT_EN BIT(2) +#define REG_CHCR_TRANSFER_END BIT(1) +#define REG_CHCR_DMAC_EN BIT(0) + +static const dma_config_t *channels_cfg[4]; + +static const irq_t channel_to_irq[] = { + [0] = EXC_DMAC_DMTE0, + [1] = EXC_DMAC_DMTE1, + [2] = EXC_DMAC_DMTE2, + [3] = EXC_DMAC_DMTE3, +}; + +static inline unsigned char irq_to_channel(irq_t irq) { + return (irq - EXC_DMAC_DMTE0) >> 5; +} + +static uint32_t dmac_read(dma_channel_t channel, dma_register_t reg) { + return *(volatile uint32_t *)(DMAC_BASE + channel * 0x10 + reg); +} + +static void dmac_write(dma_channel_t channel, dma_register_t reg, uint32_t val) { + *(volatile uint32_t *)(DMAC_BASE + channel * 0x10 + reg) = val; +} + +dma_addr_t hw_to_dma_addr(uintptr_t hw_addr) { + return (dma_addr_t)(hw_addr & MEM_AREA_CACHE_MASK); +} + +static dma_addr_t dma_map_src_dst(uintptr_t addr, size_t len, bool is_dst) { + switch(addr & ~MEM_AREA_CACHE_MASK) { + case MEM_AREA_P0_BASE: + case MEM_AREA_P1_BASE: + case MEM_AREA_P3_BASE: + if(is_dst) + dcache_inval_range(addr, len); + else + dcache_flush_range(addr, len); + break; + + default: + /* Nothing to do */ + break; + } + + return hw_to_dma_addr(addr); +} + +dma_addr_t dma_map_src(const void *ptr, size_t len) { + return dma_map_src_dst((uintptr_t)ptr, len, false); +} + +dma_addr_t dma_map_dst(void *ptr, size_t len) { + return dma_map_src_dst((uintptr_t)ptr, len, true); +} + +static const unsigned char dma_unit_size[] = { + [DMA_UNITSIZE_64BIT] = 8, + [DMA_UNITSIZE_8BIT] = 1, + [DMA_UNITSIZE_16BIT] = 2, + [DMA_UNITSIZE_32BIT] = 4, + [DMA_UNITSIZE_32BYTE] = 32, +}; + +static void dma_irq_handler(irq_t code, irq_context_t *context, void *d) { + unsigned char channel = irq_to_channel(code); + + (void)context; + + /* ACK the IRQ by clearing CHCR */ + dmac_write(channel, DMA_REG_CHCR, 0); + + genwait_wake_all((void *)&channels_cfg[channel]->callback); + channels_cfg[channel]->callback(d); +} + +static bool dma_is_running(dma_channel_t channel) { + uint32_t chcr = dmac_read(channel, DMA_REG_CHCR); + + return (chcr & (REG_CHCR_TRANSFER_END | REG_CHCR_DMAC_EN)) == REG_CHCR_DMAC_EN; +} + +void dma_wait_complete(dma_channel_t channel) { + irq_disable_scoped(); + + while(dma_is_running(channel)) { + if(!irq_inside_int()) { + if(channels_cfg[channel]->callback) + genwait_wait(channels_cfg[channel]->callback, "DMA complete wait", 0, NULL); + else + thd_pass(); + } + } +} + +int dma_transfer(const dma_config_t *cfg, dma_addr_t dst, dma_addr_t src, + size_t len, void *cb_data) { + unsigned int transfer_size = dma_unit_size[cfg->unit_size]; + uint32_t chcr; + + if((len | dst | src) & (transfer_size - 1)) { + dbglog(DBG_ERROR, "dmac: src/dst/len not aligned to the bus width\n"); + errno = EFAULT; + return -1; + } + + irq_disable_scoped(); + + dma_wait_complete(cfg->channel); + channels_cfg[cfg->channel] = cfg; + + dmac_write(cfg->channel, DMA_REG_CHCR, 0); + dmac_write(cfg->channel, DMA_REG_SAR, src); + dmac_write(cfg->channel, DMA_REG_DAR, dst); + dmac_write(cfg->channel, DMA_REG_TCR, len >> __builtin_ctz(transfer_size)); + + irq_set_handler(channel_to_irq[cfg->channel], dma_irq_handler, cb_data); + + chcr = FIELD_PREP(REG_CHCR_DST_ADDRMODE, cfg->dst_mode) + | FIELD_PREP(REG_CHCR_SRC_ADDRMODE, cfg->src_mode) + | FIELD_PREP(REG_CHCR_REQUEST, cfg->request) + | FIELD_PREP(REG_CHCR_TRANSMIT_MODE, cfg->transmit_mode) + | FIELD_PREP(REG_CHCR_BUSWIDTH, cfg->unit_size) + | FIELD_PREP(REG_CHCR_INTERRUPT_EN, !!cfg->callback) + | FIELD_PREP(REG_CHCR_DMAC_EN, 1); + + dmac_write(cfg->channel, DMA_REG_CHCR, chcr); + + return 0; +} + +size_t dma_transfer_get_remaining(dma_channel_t channel) { + unsigned char unit_size = channels_cfg[channel]->unit_size; + uint32_t tcr = dmac_read(channel, DMA_REG_TCR); + + return tcr * dma_unit_size[unit_size]; +} diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c b/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c index 40ed9cd9..98196e6b 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_dma.c @@ -11,9 +11,9 @@ #include <stdio.h> #include <errno.h> +#include <arch/dmac.h> #include <dc/pvr.h> #include <dc/asic.h> -#include <dc/dmac.h> #include <dc/sq.h> #include <kos/thread.h> #include <kos/sem.h> @@ -42,7 +42,7 @@ static void pvr_dma_irq_hnd(uint32_t code, void *data) { (void)code; (void)data; - if(DMAC_DMATCR2 != 0) + if(dma_transfer_get_remaining(DMA_CHANNEL_2) != 0) dbglog(DBG_INFO, "pvr_dma: The dma did not complete successfully\n"); /* Call the callback, if any. */ @@ -95,10 +95,18 @@ static uintptr_t pvr_dest_addr(uintptr_t dest, pvr_dma_type_t type) { return dest_addr; } +static const dma_config_t pvr_dma_config = { + .channel = DMA_CHANNEL_2, + .request = DMA_REQUEST_EXTERNAL_MEM_TO_DEV, + .unit_size = DMA_UNITSIZE_32BYTE, + .src_mode = DMA_ADDRMODE_INCREMENT, + .transmit_mode = DMA_TRANSMITMODE_BURST, +}; + int pvr_dma_transfer(const void *src, uintptr_t dest, size_t count, pvr_dma_type_t type, bool block, pvr_dma_callback_t callback, void *cbdata) { - uintptr_t src_addr = ((uintptr_t)src); + dma_addr_t src_addr = dma_map_src(src, count); /* Check for 32-byte alignment */ if(src_addr & 0x1F) { @@ -118,21 +126,8 @@ int pvr_dma_transfer(const void *src, uintptr_t dest, size_t count, return -1; } - if(DMAC_CHCR2 & 0x1) /* DE bit set so we must clear it */ - DMAC_CHCR2 &= ~0x1; - - if(DMAC_CHCR2 & 0x2) /* TE bit set so we must clear it */ - DMAC_CHCR2 &= ~0x2; - - DMAC_SAR2 = src_addr; - DMAC_DMATCR2 = count / 32; - DMAC_CHCR2 = 0x12c1; - - if((DMAC_DMAOR & DMAOR_STATUS_MASK) != DMAOR_NORMAL_OPERATION) { - dbglog(DBG_ERROR, "pvr_dma: Failed DMAOR check\n"); - errno = EIO; + if(dma_transfer(&pvr_dma_config, 0, src_addr, count, NULL)) return -1; - } pvr_dma[PVR_STATE] = pvr_dest_addr(dest, type); pvr_dma[PVR_LEN] = count; diff --git a/kernel/arch/dreamcast/hardware/pvr/pvr_irq.c b/kernel/arch/dreamcast/hardware/pvr/pvr_irq.c index 5feb2f1c..d54057d5 100644 --- a/kernel/arch/dreamcast/hardware/pvr/pvr_irq.c +++ b/kernel/arch/dreamcast/hardware/pvr/pvr_irq.c @@ -49,12 +49,6 @@ static void dma_next_list(void *thread) { continue; } - // Flush the last 32 bytes out of dcache, just in case. - // dcache_flush_range((ptr_t)(b->base[i] + b->ptr[i] - 32), 32); - dcache_flush_range((ptr_t)(b->base[i]), b->ptr[i] + 32); - //amt = b->ptr[i] > 16384 ? 16384 : b->ptr[i]; - //dcache_flush_range((ptr_t)(b->base[i] + b->ptr[i] - amt), amt); - // Start the DMA transfer, chaining to ourselves. //DBG(("dma_begin(buf %d, list %d, base %p, len %d)\n", // pvr_state.ram_target ^ 1, i, diff --git a/kernel/arch/dreamcast/hardware/scif.c b/kernel/arch/dreamcast/hardware/scif.c index 1e87f826..4ceab8ca 100644 --- a/kernel/arch/dreamcast/hardware/scif.c +++ b/kernel/arch/dreamcast/hardware/scif.c @@ -165,7 +165,7 @@ int scif_set_irq_usage(int on) { irq_set_handler(EXC_SCIF_ERI, scif_err_irq, NULL); irq_set_handler(EXC_SCIF_BRI, scif_err_irq, NULL); irq_set_handler(EXC_SCIF_RXI, scif_data_irq, NULL); - *((vuint16*)0xffd0000c) |= 0x000e << 4; + irq_set_priority(IRQ_SRC_SCIF, 14); /* Enable transmit/receive, recv/recv error ints */ SCSCR2 |= 0x48; @@ -175,7 +175,7 @@ int scif_set_irq_usage(int on) { SCSCR2 &= ~0x48; ...<truncated>... hooks/post-receive -- A pseudo Operating System for the Dreamcast. |