Skip to content

Commit c2ab033

Browse files
committed
WIP
Enable ALSA driver and System V IPC in Linux Kernel. Implement VIRTIO_SND_R_PCM_* prototypes. Set CNFA opaque for sound playing control. Set condition of start, stop, and prepeare playing. Add description of descriptor chaining, yet need refactoring the description as well as code (exists uncertainty of the query struct).
1 parent a0ad61b commit c2ab033

File tree

13 files changed

+903
-3
lines changed

13 files changed

+903
-3
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ jobs:
1010
- name: install-dependencies
1111
run: |
1212
sudo apt-get install build-essential device-tree-compiler expect
13+
sudo apt-get install libasound2-dev libudev-dev
1314
- name: default build
1415
run: make
1516
shell: bash

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "cnfa"]
2+
path = cnfa
3+
url = https://github.com/cntools/cnfa
4+
shallow = true

Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include mk/common.mk
2+
include mk/check-libs.mk
23

34
CC ?= gcc
45
CFLAGS := -O2 -g -Wall -Wextra
@@ -13,6 +14,8 @@ OBJS_EXTRA :=
1314
# command line option
1415
OPTS :=
1516

17+
LDFLAGS :=
18+
1619
# virtio-blk
1720
ENABLE_VIRTIOBLK ?= 1
1821
$(call set-feature, VIRTIOBLK)
@@ -41,6 +44,36 @@ ifeq ($(call has, VIRTIONET), 1)
4144
OBJS_EXTRA += virtio-net.o
4245
endif
4346

47+
# virtio-snd
48+
ENABLE_VIRTIOSND ?= 1
49+
ifneq ($(UNAME_S),Linux)
50+
ENABLE_VIRTIOSND := 0
51+
endif
52+
53+
ifeq (0, $(call check-alsa))
54+
$(warning No libasound installed. Check libasound in advance.)
55+
ENABLE_VIRTIOSND := 0
56+
endif
57+
$(call set-feature, VIRTIOSND)
58+
ifeq ($(call has, VIRTIOSND), 1)
59+
OBJS_EXTRA += virtio-snd.o
60+
LDFLAGS += -lasound -lpthread
61+
CFLAGS += -Icnfa
62+
63+
cnfa/Makefile:
64+
git submodule update --init cnfa
65+
cnfa/os_generic: cnfa/Makefile
66+
$(MAKE) -C $(dir $<) os_generic.h
67+
CNFA_LIB := cnfa/CNFA_sf.h
68+
$(CNFA_LIB): cnfa/Makefile cnfa/os_generic
69+
$(MAKE) -C $(dir $<) CNFA_sf.h
70+
main.o: $(CNFA_LIB)
71+
endif
72+
73+
# .DEFAULT_GOAL should be set to all since the very first target is not all
74+
# after git submodule.
75+
.DEFAULT_GOAL := all
76+
4477
BIN = semu
4578
all: $(BIN) minimal.dtb
4679

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ A minimalist RISC-V system emulator capable of running Linux the kernel and corr
99
- UART: 8250/16550
1010
- PLIC (platform-level interrupt controller): 32 interrupts, no priority
1111
- Standard SBI, with the timer extension
12-
- VirtIO: virtio-blk acquires disk image from the host, and virtio-net is mapped as TAP interface
12+
- Three types of I/O support using VirtIO standard:
13+
- virtio-blk acquires disk image from the host.
14+
- virtio-net is mapped as TAP interface.
15+
- virtio-snd uses ALSA for sound operation.
1316

1417
## Prerequisites
1518

cnfa

Submodule cnfa added at 60bcddd

configs/buildroot.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ BR2_RELRO_NONE=y
3636
# BR2_RELRO_PARTIAL is not set
3737
# BR2_RELRO_FULL is not set
3838
BR2_FORTIFY_SOURCE_1=y
39+
BR2_PACKAGE_ALSA_UTILS=y
40+
BR2_PACKAGE_ALSA_UTILS_APLAY=y
41+
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
3942
# BR2_PACKAGE_URANDOM_SCRIPTS is not set
4043
BR2_TARGET_ROOTFS_CPIO=y
4144
BR2_TARGET_ROOTFS_CPIO_FULL=y

configs/linux.config

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ CONFIG_LOCALVERSION_AUTO=y
3030
CONFIG_BUILD_SALT=""
3131
CONFIG_DEFAULT_INIT=""
3232
CONFIG_DEFAULT_HOSTNAME="(none)"
33-
# CONFIG_SYSVIPC is not set
33+
CONFIG_SYSVIPC=y
34+
CONFIG_SYSVIPC_SYSCTL=y
3435
# CONFIG_POSIX_MQUEUE is not set
3536
# CONFIG_WATCH_QUEUE is not set
3637
# CONFIG_CROSS_MEMORY_ATTACH is not set
@@ -936,7 +937,10 @@ CONFIG_DUMMY_CONSOLE_ROWS=25
936937
# end of Console display driver support
937938
# end of Graphics support
938939

939-
# CONFIG_SOUND is not set
940+
CONFIG_SOUND=y
941+
CONFIG_SND=y
942+
CONFIG_SND_ALOOP=y
943+
CONFIG_SND_VIRTIO=y
940944

941945
#
942946
# HID support

device.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,53 @@ void clint_write(hart_t *vm,
190190
uint8_t width,
191191
uint32_t value);
192192

193+
/* VirtIO-Sound */
194+
195+
#if SEMU_HAS(VIRTIOSND)
196+
#define IRQ_VSND 4
197+
#define IRQ_VSND_BIT (1 << IRQ_VSND)
198+
199+
typedef struct {
200+
uint32_t QueueNum;
201+
uint32_t QueueDesc;
202+
uint32_t QueueAvail;
203+
uint32_t QueueUsed;
204+
uint16_t last_avail;
205+
bool ready;
206+
} virtio_snd_queue_t;
207+
208+
typedef struct {
209+
/* feature negotiation */
210+
uint32_t DeviceFeaturesSel;
211+
uint32_t DriverFeatures;
212+
uint32_t DriverFeaturesSel;
213+
/* queue config */
214+
uint32_t QueueSel;
215+
virtio_snd_queue_t queues[4];
216+
/* status */
217+
uint32_t Status;
218+
uint32_t InterruptStatus;
219+
/* supplied by environment */
220+
uint32_t *ram;
221+
/* implementation-specific */
222+
void *priv;
223+
} virtio_snd_state_t;
224+
225+
void virtio_snd_read(hart_t *core,
226+
virtio_snd_state_t *vsnd,
227+
uint32_t addr,
228+
uint8_t width,
229+
uint32_t *value);
230+
231+
void virtio_snd_write(hart_t *core,
232+
virtio_snd_state_t *vsnd,
233+
uint32_t addr,
234+
uint8_t width,
235+
uint32_t value);
236+
237+
bool virtio_snd_init(virtio_snd_state_t *vsnd);
238+
#endif /* SEMU_HAS(VIRTIOSND) */
239+
193240
/* memory mapping */
194241

195242
typedef struct {
@@ -205,4 +252,8 @@ typedef struct {
205252
virtio_blk_state_t vblk;
206253
#endif
207254
clint_state_t clint;
255+
#if SEMU_HAS(VIRTIOSND)
256+
virtio_snd_state_t vsnd;
257+
#endif
258+
uint64_t timer;
208259
} emu_state_t;

feature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,10 @@
1212
#define SEMU_FEATURE_VIRTIONET 1
1313
#endif
1414

15+
/* virtio-snd */
16+
#ifndef SEMU_FEATURE_VIRTIOSND
17+
#define SEMU_FEATURE_VIRTIOSND 1
18+
#endif
19+
1520
/* Feature test macro */
1621
#define SEMU_HAS(x) SEMU_FEATURE_##x

main.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ static void emu_update_timer_interrupt(hart_t *hart)
8181
clint_update_interrupts(hart, &data->clint);
8282
}
8383

84+
#if SEMU_HAS(VIRTIOSND)
85+
static void emu_update_vsnd_interrupts(vm_t *vm)
86+
{
87+
emu_state_t *data = PRIV(vm->hart[0]);
88+
if (data->vsnd.InterruptStatus)
89+
data->plic.active |= IRQ_VSND_BIT;
90+
else
91+
data->plic.active &= ~IRQ_VSND_BIT;
92+
plic_update_interrupts(vm, &data->plic);
93+
}
94+
#endif
95+
8496
static void mem_load(hart_t *hart,
8597
uint32_t addr,
8698
uint8_t width,
@@ -121,6 +133,13 @@ static void mem_load(hart_t *hart,
121133
clint_read(hart, &data->clint, addr & 0xFFFFF, width, value);
122134
clint_update_interrupts(hart, &data->clint);
123135
return;
136+
137+
#if SEMU_HAS(VIRTIOSND)
138+
case 0x44: /* virtio-snd */
139+
virtio_snd_read(hart, &data->vsnd, addr & 0xFFFFF, width, value);
140+
emu_update_vsnd_interrupts(hart->vm);
141+
return;
142+
#endif
124143
}
125144
}
126145
vm_set_exception(hart, RV_EXC_LOAD_FAULT, hart->exc_val);
@@ -166,6 +185,12 @@ static void mem_store(hart_t *hart,
166185
clint_write(hart, &data->clint, addr & 0xFFFFF, width, value);
167186
clint_update_interrupts(hart, &data->clint);
168187
return;
188+
#if SEMU_HAS(VIRTIOSND)
189+
case 0x44: /* virtio-snd */
190+
virtio_snd_write(hart, &data->vsnd, addr & 0xFFFFF, width, value);
191+
emu_update_vsnd_interrupts(hart->vm);
192+
return;
193+
#endif
169194
}
170195
}
171196
vm_set_exception(hart, RV_EXC_STORE_FAULT, hart->exc_val);
@@ -581,6 +606,11 @@ static int semu_start(int argc, char **argv)
581606
emu.vblk.ram = emu.ram;
582607
emu.disk = virtio_blk_init(&(emu.vblk), disk_file);
583608
#endif
609+
#if SEMU_HAS(VIRTIOSND)
610+
if (!virtio_snd_init(&(emu.vsnd)))
611+
fprintf(stderr, "No virtio-snd functioned\n");
612+
emu.vsnd.ram = emu.ram;
613+
#endif
584614

585615
/* Emulate */
586616
uint32_t peripheral_update_ctr = 0;
@@ -603,6 +633,11 @@ static int semu_start(int argc, char **argv)
603633
if (emu.vblk.InterruptStatus)
604634
emu_update_vblk_interrupts(&vm);
605635
#endif
636+
637+
#if SEMU_HAS(VIRTIOSND)
638+
if (emu.vsnd.InterruptStatus)
639+
emu_update_vsnd_interrupts(&vm);
640+
#endif
606641
}
607642

608643
emu_update_timer_interrupt(vm.hart[i]);

0 commit comments

Comments
 (0)