Skip to content

Commit 164a0ad

Browse files
committed
WIP
Enable ALSA driver and System V IPC in Linux Kernel. Implement VIRTIO_SND_R_PCM_* actions. Add description of descriptor chaining, yet need refactoring the description as well as code (exists uncertainty of the query struct). Succeed to initialize virtio-snd. Freeze at pcm_stop as the device does not receive any data for playing sound.
1 parent a0ad61b commit 164a0ad

File tree

13 files changed

+985
-3
lines changed

13 files changed

+985
-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: 5 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,9 @@ 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_VIRTIO=y
940943

941944
#
942945
# 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)