|
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.
|