mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 03:55:04 +00:00
dde_bsd: add audio drivers ported from OpenBSD
These audio drivers enable support for Intel HD Audio (Azalia) and Ensoniq AudioPCI (ES1370) compatible soundcards. They are ported from OpenBSD 5.7. Fixes #1498.
This commit is contained in:
parent
df04b17594
commit
49dd9242f7
24
repos/dde_bsd/Makefile
Normal file
24
repos/dde_bsd/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# \brief Download, and unpack BSD kernel sources
|
||||
# \author Josef Soentgen
|
||||
# \date 2014-11-09
|
||||
#
|
||||
|
||||
VERBOSE ?= @
|
||||
ECHO := @echo
|
||||
|
||||
#
|
||||
# Print help information by default
|
||||
#
|
||||
help::
|
||||
|
||||
prepare:
|
||||
$(VERBOSE)../../tool/ports/prepare_port dde_bsd
|
||||
|
||||
help::
|
||||
$(ECHO)
|
||||
$(ECHO) "Prepare the dde_bsd repository"
|
||||
$(ECHO)
|
||||
$(ECHO) "--- available commands ---"
|
||||
$(ECHO) "prepare - checkout upstream source codes"
|
||||
$(ECHO)
|
29
repos/dde_bsd/README
Normal file
29
repos/dde_bsd/README
Normal file
@ -0,0 +1,29 @@
|
||||
This repository contains device drivers ported from OpenBSD.
|
||||
|
||||
Audio
|
||||
#####
|
||||
|
||||
The audio driver is ported from OpenBSD 5.7 and includes support for
|
||||
Intel HD Audio as well as for Ensoniq AudioPCI (ES1370) compatible
|
||||
soundcards. The HDA driver works on real hardware and Virtualbox
|
||||
whereas the ES1370 driver is only used in Qemu.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
You have to prepare the contrib sources for this repository by
|
||||
executing _tool/ports/prepare_port dde_bsd_. Also you need to make
|
||||
sure to add the 'dde_bsd' repository to the REPOSITORIES variable
|
||||
in your 'etc/build.conf'.
|
||||
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
The driver can be tested by executing the run script 'run/audio_out.run'.
|
||||
This example plays a sample file in a loop. The file format is header less
|
||||
two channel float 32 at 44100 Hz. You may use the 'sox' utility to create
|
||||
these audio files:
|
||||
|
||||
! sox -c 2 -r 44100 foo.wav foo.f32
|
18
repos/dde_bsd/audio.list
Normal file
18
repos/dde_bsd/audio.list
Normal file
@ -0,0 +1,18 @@
|
||||
./sys/dev/audio.c
|
||||
./sys/dev/audio_if.h
|
||||
./sys/dev/pci/azalia.c
|
||||
./sys/dev/pci/azalia.h
|
||||
./sys/dev/pci/azalia_codec.c
|
||||
./sys/dev/pci/eap.c
|
||||
./sys/dev/pci/eapreg.h
|
||||
./sys/dev/pci/pcidevs.h
|
||||
./sys/dev/pci/pcidevs_data.h
|
||||
./sys/dev/auconv.c
|
||||
./sys/dev/auconv.h
|
||||
./sys/dev/mulaw.c
|
||||
./sys/dev/mulaw.h
|
||||
./sys/dev/ic/ac97.c
|
||||
./sys/dev/ic/ac97.h
|
||||
./sys/sys/audioio.h
|
||||
./sys/sys/device.h
|
||||
./sys/sys/queue.h
|
40
repos/dde_bsd/include/audio/audio.h
Normal file
40
repos/dde_bsd/include/audio/audio.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Audio library interface
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-12-27
|
||||
*
|
||||
* This header declares the private Audio namespace. It contains
|
||||
* functions called by the driver frontend that are implemented
|
||||
* by the driver library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO__AUDIO_H_
|
||||
#define _AUDIO__AUDIO_H_
|
||||
|
||||
#include <os/server.h>
|
||||
|
||||
/*****************************
|
||||
** private Audio namespace **
|
||||
*****************************/
|
||||
|
||||
namespace Audio {
|
||||
|
||||
enum Channel_number { LEFT, RIGHT, MAX_CHANNELS, INVALID = MAX_CHANNELS };
|
||||
|
||||
void init_driver(Server::Entrypoint &ep);
|
||||
|
||||
bool driver_active();
|
||||
|
||||
void dma_notifier(Genode::Signal_context_capability cap);
|
||||
|
||||
int play(short *data, Genode::size_t size);
|
||||
}
|
||||
|
||||
#endif /* _AUDIO__AUDIO_H_ */
|
77
repos/dde_bsd/lib/mk/audio.inc
Normal file
77
repos/dde_bsd/lib/mk/audio.inc
Normal file
@ -0,0 +1,77 @@
|
||||
LIB_DIR = $(REP_DIR)/src/lib/audio
|
||||
LIB_INC_DIR = $(LIB_DIR)/include
|
||||
|
||||
AUDIO_CONTRIB_DIR := $(call select_from_ports,dde_bsd)/src/lib/audio
|
||||
|
||||
INC_DIR += $(LIB_DIR)
|
||||
INC_DIR += $(LIB_INC_DIR)
|
||||
INC_DIR += $(AUDIO_CONTRIB_DIR)
|
||||
|
||||
SRC_CC += bus.cc dummies.cc driver.cc irq.cc mem.cc misc.cc scheduler.cc timer.cc
|
||||
SRC_C += bsd_emul.c
|
||||
SRC_S += setjmp.S
|
||||
|
||||
CC_OPT += -Wno-unused-but-set-variable
|
||||
|
||||
# disable builtins
|
||||
CC_OPT += -fno-builtin-printf -fno-builtin-snprintf -fno-builtin-vsnprintf \
|
||||
-fno-builtin-malloc -fno-builtin-free -fno-builtin-log -fno-builtin-log2
|
||||
|
||||
CC_OPT += -D_KERNEL
|
||||
|
||||
# enable when debugging
|
||||
# CC_OPT += -DAUDIO_DEBUG
|
||||
# CC_OPT += -DAZALIA_DEBUG
|
||||
# CC_OPT += -DDIAGNOSTIC
|
||||
|
||||
# audio interface
|
||||
SRC_C += dev/audio.c dev/auconv.c
|
||||
|
||||
# AC97 codec
|
||||
SRC_C += dev/ic/ac97.c
|
||||
|
||||
# HDA driver
|
||||
SRC_C += dev/pci/azalia.c dev/pci/azalia_codec.c
|
||||
|
||||
# ES1370
|
||||
SRC_C += dev/pci/eap.c
|
||||
|
||||
SRC_C += dev/mulaw.c
|
||||
|
||||
#
|
||||
# Determine the header files included by the contrib code. For each
|
||||
# of these header files we create a symlink to 'bsd_emul.h'.
|
||||
#
|
||||
GEN_INCLUDES := $(shell grep -rh "^\#include .*" $(AUDIO_CONTRIB_DIR) |\
|
||||
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | sort | uniq)
|
||||
|
||||
#
|
||||
# Filter out original BSD headers that exist in the contrib directory
|
||||
#
|
||||
NO_GEN_INCLUDES := $(shell cd $(AUDIO_CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | sed "s/.*include\///")
|
||||
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
|
||||
|
||||
#
|
||||
# Put BSD headers in 'GEN_INC' dir
|
||||
#
|
||||
GEN_INC := $(shell pwd)/include
|
||||
|
||||
$(shell mkdir -p $(GEN_INC))
|
||||
|
||||
GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES))
|
||||
INC_DIR += $(GEN_INC)
|
||||
|
||||
#
|
||||
# Make sure to create the header symlinks prior building
|
||||
#
|
||||
$(SRC_C:.c=.o) $(SRC_CC:.cc=.o): $(GEN_INCLUDES)
|
||||
|
||||
$(GEN_INCLUDES):
|
||||
$(VERBOSE)mkdir -p $(dir $@)
|
||||
$(VERBOSE)ln -s $(LIB_INC_DIR)/bsd_emul.h $@
|
||||
|
||||
vpath %.c $(AUDIO_CONTRIB_DIR)
|
||||
vpath %.c $(LIB_DIR)
|
||||
vpath %.cc $(LIB_DIR)
|
||||
|
||||
# vi: set ft=make :
|
5
repos/dde_bsd/lib/mk/x86_32/audio.mk
Normal file
5
repos/dde_bsd/lib/mk/x86_32/audio.mk
Normal file
@ -0,0 +1,5 @@
|
||||
INC_DIR += $(LIB_INC_DIR)/x86_32 $(LIB_INC_DIR)/x86
|
||||
|
||||
include $(REP_DIR)/lib/mk/audio.inc
|
||||
|
||||
vpath %.S $(LIB_DIR)/x86_32
|
5
repos/dde_bsd/lib/mk/x86_64/audio.mk
Normal file
5
repos/dde_bsd/lib/mk/x86_64/audio.mk
Normal file
@ -0,0 +1,5 @@
|
||||
INC_DIR += $(LIB_INC_DIR)/x86_64 $(LIB_INC_DIR)/x86
|
||||
|
||||
include $(REP_DIR)/lib/mk/audio.inc
|
||||
|
||||
vpath %.S $(LIB_DIR)/x86_64
|
14
repos/dde_bsd/patches/oppress_warning.patch
Normal file
14
repos/dde_bsd/patches/oppress_warning.patch
Normal file
@ -0,0 +1,14 @@
|
||||
dev/audio.c:XXX:Y: warning: ‘type’ may be used uninitialized in this function [-Wmaybe-uninitialized]
|
||||
diff --git a/dev/audio.c b/dev/audio.c
|
||||
index a9fa22b..da8a783 100644
|
||||
--- a/dev/audio.c
|
||||
+++ b/dev/audio.c
|
||||
@@ -639,7 +639,7 @@ int
|
||||
audioprint(void *aux, const char *pnp)
|
||||
{
|
||||
struct audio_attach_args *arg = aux;
|
||||
- const char *type;
|
||||
+ const char *type = "never printed";
|
||||
|
||||
if (pnp != NULL) {
|
||||
switch (arg->type) {
|
1
repos/dde_bsd/ports/dde_bsd.hash
Normal file
1
repos/dde_bsd/ports/dde_bsd.hash
Normal file
@ -0,0 +1 @@
|
||||
74279f98408dcf0fcd90849659e73fd1cbb82e78
|
25
repos/dde_bsd/ports/dde_bsd.port
Normal file
25
repos/dde_bsd/ports/dde_bsd.port
Normal file
@ -0,0 +1,25 @@
|
||||
LICENSE := BSD
|
||||
VERSION := 1
|
||||
DOWNLOADS := audio.archive
|
||||
|
||||
#
|
||||
# Audio drivers from OpenBSD 5.7
|
||||
#
|
||||
SRC_DIR_AUDIO := src/lib/audio
|
||||
VERSION_AUDIO := 5.7
|
||||
URL(audio) := http://openbsd.cs.fau.de/pub/OpenBSD/$(VERSION_AUDIO)/sys.tar.gz
|
||||
SHA(audio) := 1a60125a7fce6524b0d62643db47acca0b11506a
|
||||
DIR(audio) := $(SRC_DIR_AUDIO)
|
||||
TAR_OPT(audio) := --strip-components=2 --files-from $(REP_DIR)/audio.list
|
||||
HASH_INPUT += $(REP_DIR)/audio.list
|
||||
|
||||
#
|
||||
# Patches
|
||||
#
|
||||
PATCHES := $(addprefix patches/,$(notdir $(wildcard $(REP_DIR)/patches/*.patch)))
|
||||
|
||||
AUDIO_OPT := -p1 -d$(SRC_DIR_AUDIO)
|
||||
PATCH_OPT(patches/oppress_warning.patch) := $(AUDIO_OPT)
|
||||
PATCH_OPT(patches/eap_c.patch) := $(AUDIO_OPT)
|
||||
|
||||
# vi: set ft=make :
|
166
repos/dde_bsd/run/audio_out.run
Normal file
166
repos/dde_bsd/run/audio_out.run
Normal file
@ -0,0 +1,166 @@
|
||||
assert_spec x86
|
||||
|
||||
#
|
||||
# Check used commands
|
||||
#
|
||||
|
||||
set wget [check_installed wget]
|
||||
|
||||
#
|
||||
# Configure
|
||||
#
|
||||
|
||||
set use_mixer 0
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
drivers/audio_out
|
||||
drivers/pci
|
||||
test/audio_out
|
||||
}
|
||||
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if [have_spec pci] build_components drivers/pci/device_pd
|
||||
lappend_if $use_mixer build_components server/mixer
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Config
|
||||
#
|
||||
|
||||
append config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL" />
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if [have_spec acpi] config {
|
||||
<start name="acpi_drv">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<provides>
|
||||
<service name="PCI"/>
|
||||
<service name="IRQ" />
|
||||
</provides>
|
||||
<route>
|
||||
<any-service> <parent/> <any-child /> </any-service>
|
||||
</route>
|
||||
<config>
|
||||
<policy label="acpi_drv">
|
||||
<pci class="ALL"/>
|
||||
</policy>
|
||||
<policy label="audio_out_drv">
|
||||
<pci class="AUDIO"/>
|
||||
</policy>
|
||||
</config>
|
||||
</start>}
|
||||
|
||||
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||
<start name="pci_drv">
|
||||
<resource name="RAM" quantum="4M" constrain_phys="yes"/>
|
||||
<provides> <service name="PCI"/> </provides>
|
||||
<config>
|
||||
<policy label="audio_out_drv">
|
||||
<pci class="AUDIO"/>
|
||||
</policy>
|
||||
</config>
|
||||
</start>}
|
||||
|
||||
append_if $use_mixer config {
|
||||
<start name="mixer">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Audio_out"/></provides>
|
||||
<route>
|
||||
<service name="Audio_out"> <child name="audio_out_drv"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
|
||||
append config {
|
||||
<start name="audio_out_drv">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<provides>
|
||||
<service name="Audio_out"/>
|
||||
</provides>
|
||||
</start>
|
||||
<start name="test-audio_out">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<filename>sample.raw</filename>
|
||||
</config>
|
||||
<route>}
|
||||
append_if $use_mixer config {
|
||||
<service name="Audio_out"><child name="mixer"/></service>}
|
||||
append config {
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
|
||||
#
|
||||
# Get sample file
|
||||
#
|
||||
|
||||
if {[info exists env(GENODE_SAMPLE_RAW)]} {
|
||||
catch { exec $wget $::env(GENODE_SAMPLE_RAW) -O bin/sample.raw }
|
||||
}
|
||||
|
||||
if {![file exists bin/sample.raw]} {
|
||||
puts ""
|
||||
puts "The sample file is missing. Please take a look at"
|
||||
puts "repos/dde_bsd/README, create 'sample.raw' and put"
|
||||
puts "the file into './bin'. afterwards"
|
||||
puts ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
set boot_modules {
|
||||
core init timer audio_out_drv test-audio_out sample.raw }
|
||||
|
||||
lappend_if $use_mixer boot_modules mixer
|
||||
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
lappend_if [have_spec nova] boot_modules pci_device_pd
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -m 128 -nographic -soundhw es1370 "
|
||||
|
||||
#
|
||||
# For obvious reasons the timeout depends on the total
|
||||
# length of the used sample file.
|
||||
#
|
||||
run_genode_until {.*played.*1 time\(s\)} 60
|
297
repos/dde_bsd/src/drivers/audio_out/main.cc
Normal file
297
repos/dde_bsd/src/drivers/audio_out/main.cc
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* \brief Startup audio driver library
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-09
|
||||
*/
|
||||
|
||||
#include <audio_out_session/rpc_object.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/server.h>
|
||||
#include <root/component.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
#include <audio/audio.h>
|
||||
|
||||
static bool const verbose = false;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
using namespace Audio;
|
||||
|
||||
namespace Audio_out {
|
||||
class Session_component;
|
||||
class Out;
|
||||
class Root;
|
||||
struct Root_policy;
|
||||
static Session_component *channel_acquired[MAX_CHANNELS];
|
||||
}
|
||||
|
||||
|
||||
class Audio_out::Session_component : public Audio_out::Session_rpc_object
|
||||
{
|
||||
private:
|
||||
|
||||
Channel_number _channel;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Channel_number channel, Signal_context_capability cap)
|
||||
:
|
||||
Session_rpc_object(cap), _channel(channel)
|
||||
{
|
||||
Audio_out::channel_acquired[_channel] = this;
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
Audio_out::channel_acquired[_channel] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class Audio_out::Out
|
||||
{
|
||||
private:
|
||||
|
||||
Server::Entrypoint &_ep;
|
||||
Genode::Signal_rpc_member<Audio_out::Out> _data_avail_dispatcher;
|
||||
Genode::Signal_rpc_member<Audio_out::Out> _dma_notify_dispatcher;
|
||||
|
||||
bool _active() {
|
||||
return channel_acquired[LEFT] && channel_acquired[RIGHT] &&
|
||||
channel_acquired[LEFT]->active() && channel_acquired[RIGHT]->active();
|
||||
}
|
||||
|
||||
Stream *left() { return channel_acquired[LEFT]->stream(); }
|
||||
Stream *right() { return channel_acquired[RIGHT]->stream(); }
|
||||
|
||||
void _advance_position(Packet *l, Packet *r)
|
||||
{
|
||||
bool full_left = left()->full();
|
||||
bool full_right = right()->full();
|
||||
|
||||
left()->pos(left()->packet_position(l));
|
||||
right()->pos(right()->packet_position(r));
|
||||
|
||||
left()->increment_position();
|
||||
right()->increment_position();
|
||||
|
||||
Session_component *channel_left = channel_acquired[LEFT];
|
||||
Session_component *channel_right = channel_acquired[RIGHT];
|
||||
|
||||
if (full_left)
|
||||
channel_left->alloc_submit();
|
||||
|
||||
if (full_right)
|
||||
channel_right->alloc_submit();
|
||||
|
||||
channel_left->progress_submit();
|
||||
channel_right->progress_submit();
|
||||
}
|
||||
|
||||
void _play_silence()
|
||||
{
|
||||
static short silence[2 * Audio_out::PERIOD] = { 0 };
|
||||
|
||||
if (int err = Audio::play(silence, sizeof(silence)))
|
||||
PWRN("Error %d during silence playback", err);
|
||||
}
|
||||
|
||||
void _play_packet()
|
||||
{
|
||||
Packet *p_left = left()->get(left()->pos());
|
||||
Packet *p_right = right()->get(right()->pos());
|
||||
|
||||
if ((p_left->valid() && p_right->valid())) {
|
||||
/* convert float to S16LE */
|
||||
static short data[2 * Audio_out::PERIOD];
|
||||
|
||||
for (int i = 0; i < 2 * Audio_out::PERIOD; i += 2) {
|
||||
data[i] = p_left->content()[i / 2] * 32767;
|
||||
data[i + 1] = p_right->content()[i / 2] * 32767;
|
||||
}
|
||||
|
||||
/* send to driver */
|
||||
if (int err = Audio::play(data, sizeof(data)))
|
||||
PWRN("Error %d during playback", err);
|
||||
} else
|
||||
_play_silence();
|
||||
|
||||
p_left->invalidate();
|
||||
p_right->invalidate();
|
||||
|
||||
p_left->mark_as_played();
|
||||
p_right->mark_as_played();
|
||||
|
||||
_advance_position(p_left, p_right);
|
||||
}
|
||||
|
||||
/*
|
||||
* Data available in session buffer
|
||||
*
|
||||
* We do not care about this signal because we already have
|
||||
* started to play and we will keep doing it, even if it is
|
||||
* silence.
|
||||
*/
|
||||
void _handle_data_avail(unsigned) { }
|
||||
|
||||
/*
|
||||
* DMA block played
|
||||
*
|
||||
* After each block played from the DMA buffer, the hw will
|
||||
* generated an interrupt. The IRQ handling code will notify
|
||||
* us as soon as this happens and we will play the next
|
||||
* packet.
|
||||
*/
|
||||
void _handle_dma_notify(unsigned)
|
||||
{
|
||||
if (!_active())
|
||||
return;
|
||||
|
||||
_play_packet();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Out(Server::Entrypoint &ep)
|
||||
:
|
||||
_ep(ep),
|
||||
_data_avail_dispatcher(ep, *this, &Audio_out::Out::_handle_data_avail),
|
||||
_dma_notify_dispatcher(ep, *this, &Audio_out::Out::_handle_dma_notify)
|
||||
{
|
||||
/* play a silence packet to get the driver running */
|
||||
_play_silence();
|
||||
}
|
||||
|
||||
Signal_context_capability data_avail() { return _data_avail_dispatcher; }
|
||||
|
||||
Signal_context_capability dma_notifier() { return _dma_notify_dispatcher; }
|
||||
|
||||
const char *debug() { return "Audio out"; }
|
||||
};
|
||||
|
||||
|
||||
static bool channel_number_from_string(const char *name,
|
||||
Channel_number *out_number)
|
||||
{
|
||||
static struct Names {
|
||||
const char *name;
|
||||
Channel_number number;
|
||||
} names[] = {
|
||||
{ "left", LEFT }, { "front left", LEFT },
|
||||
{ "right", RIGHT }, { "front right", RIGHT },
|
||||
{ 0, INVALID }
|
||||
};
|
||||
|
||||
for (Names *n = names; n->name; ++n)
|
||||
if (!Genode::strcmp(name, n->name)) {
|
||||
*out_number = n->number;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Session creation policy for our service
|
||||
*/
|
||||
struct Audio_out::Root_policy
|
||||
{
|
||||
void aquire(const char *args)
|
||||
{
|
||||
size_t ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
||||
size_t session_size =
|
||||
align_addr(sizeof(Audio_out::Session_component), 12);
|
||||
|
||||
if ((ram_quota < session_size) ||
|
||||
(sizeof(Stream) > ram_quota - session_size)) {
|
||||
PERR("insufficient 'ram_quota', got %zd, need %zd",
|
||||
ram_quota, sizeof(Stream) + session_size);
|
||||
throw ::Root::Quota_exceeded();
|
||||
}
|
||||
|
||||
char channel_name[16];
|
||||
Channel_number channel_number;
|
||||
Arg_string::find_arg(args, "channel").string(channel_name,
|
||||
sizeof(channel_name),
|
||||
"left");
|
||||
if (!channel_number_from_string(channel_name, &channel_number))
|
||||
throw ::Root::Invalid_args();
|
||||
if (Audio_out::channel_acquired[channel_number])
|
||||
throw ::Root::Unavailable();
|
||||
}
|
||||
|
||||
void release() { }
|
||||
};
|
||||
|
||||
|
||||
namespace Audio_out {
|
||||
typedef Root_component<Session_component, Root_policy> Root_component;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Root component, handling new session requests.
|
||||
*/
|
||||
class Audio_out::Root : public Audio_out::Root_component
|
||||
{
|
||||
private:
|
||||
|
||||
Server::Entrypoint &_ep;
|
||||
|
||||
Signal_context_capability _cap;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
char channel_name[16];
|
||||
Channel_number channel_number = INVALID;
|
||||
Arg_string::find_arg(args, "channel").string(channel_name,
|
||||
sizeof(channel_name),
|
||||
"left");
|
||||
channel_number_from_string(channel_name, &channel_number);
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(channel_number, _cap);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Server::Entrypoint &ep, Allocator &md_alloc,
|
||||
Signal_context_capability cap)
|
||||
:
|
||||
Root_component(&ep.rpc_ep(), &md_alloc),
|
||||
_ep(ep), _cap(cap)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Server::Entrypoint &ep;
|
||||
|
||||
Main(Server::Entrypoint &ep) : ep(ep)
|
||||
{
|
||||
Audio::init_driver(ep);
|
||||
|
||||
if (Audio::driver_active()) {
|
||||
static Audio_out::Out out(ep);
|
||||
Audio::dma_notifier(out.dma_notifier());
|
||||
static Audio_out::Root audio_root(ep, *env()->heap(), out.data_avail());
|
||||
|
||||
PINF("--- BSD Audio_out driver started ---");
|
||||
env()->parent()->announce(ep.manage(audio_root));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Server {
|
||||
char const *name() { return "audio_drv_ep"; }
|
||||
size_t stack_size() { return 4*1024*sizeof(long); }
|
||||
void construct(Entrypoint &ep) { static Main server(ep); }
|
||||
}
|
5
repos/dde_bsd/src/drivers/audio_out/target.mk
Normal file
5
repos/dde_bsd/src/drivers/audio_out/target.mk
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = audio_out_drv
|
||||
REQUIRES = x86
|
||||
SRC_CC = main.cc
|
||||
LIBS = audio base config server
|
||||
INC_DIR += $(REP_DIR)/include
|
51
repos/dde_bsd/src/lib/audio/bsd.h
Normal file
51
repos/dde_bsd/src/lib/audio/bsd.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _BSD_H_
|
||||
#define _BSD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/cache.h>
|
||||
#include <irq_session/capability.h>
|
||||
#include <os/server.h>
|
||||
|
||||
/* local includes */
|
||||
#include <scheduler.h>
|
||||
|
||||
namespace Bsd {
|
||||
|
||||
int probe_drivers();
|
||||
|
||||
void irq_init(Server::Entrypoint &ep);
|
||||
|
||||
void timer_init(Server::Entrypoint &ep);
|
||||
void update_time();
|
||||
|
||||
|
||||
/**************************
|
||||
** Bus_driver interface **
|
||||
**************************/
|
||||
|
||||
struct Bus_driver
|
||||
{
|
||||
virtual Genode::Irq_session_capability irq_session() = 0;
|
||||
|
||||
virtual Genode::addr_t alloc(Genode::size_t size, int align) = 0;
|
||||
virtual void free(Genode::addr_t virt, Genode::size_t size) = 0;
|
||||
virtual Genode::addr_t virt_to_phys(Genode::addr_t virt) = 0;
|
||||
virtual Genode::addr_t phys_to_virt(Genode::addr_t phys) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _BSD_H_ */
|
141
repos/dde_bsd/src/lib/audio/bsd_emul.c
Normal file
141
repos/dde_bsd/src/lib/audio/bsd_emul.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <bsd_emul.h>
|
||||
|
||||
#include <sys/device.h>
|
||||
#include <dev/audio_if.h>
|
||||
|
||||
|
||||
/******************
|
||||
** sys/kernel.h **
|
||||
******************/
|
||||
|
||||
int hz = HZ;
|
||||
|
||||
|
||||
/* ioconf.c */
|
||||
extern struct cfdriver audio_cd;
|
||||
extern struct cfattach audio_ca;
|
||||
extern struct cfdriver azalia_cd;
|
||||
extern struct cfattach azalia_ca;
|
||||
extern struct cfdriver eap_cd;
|
||||
extern struct cfattach eap_ca;
|
||||
|
||||
|
||||
/* original value */
|
||||
enum { PCI_BUS_PARENT = 56 };
|
||||
short pv[] = { -1, PCI_BUS_PARENT };
|
||||
|
||||
|
||||
struct cfdata cfdata[] = {
|
||||
{&audio_ca, &audio_cd, 0, 0, 0, 0, pv+0, 0, 0},
|
||||
{&azalia_ca, &azalia_cd, 0, 0, 0, 0, pv+1, 0, 0},
|
||||
{&eap_ca, &eap_cd, 0, 0, 0, 0, pv+1, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
int enodev(void) { return ENODEV; }
|
||||
|
||||
|
||||
/* global character device switch table */
|
||||
struct cdevsw cdevsw[] = {
|
||||
/* cdev_audio_init */
|
||||
{
|
||||
audioopen,
|
||||
audioclose,
|
||||
audioread,
|
||||
audiowrite,
|
||||
audioioctl,
|
||||
(int (*)(struct tty*, int)) enodev,
|
||||
0,
|
||||
audiopoll,
|
||||
audiommap,
|
||||
0,
|
||||
0,
|
||||
audiokqfilter,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* needed by dev/audio.c:522 */
|
||||
int nchrdev = sizeof(cdevsw) / sizeof(struct cdevsw);
|
||||
|
||||
|
||||
struct device pci_bus = { DV_DULL, { 0, 0 }, 0, 0, { 'p', 'c', 'i', '0'}, 0, 0, 0 };
|
||||
|
||||
/**
|
||||
* This function is our little helper that matches and attaches
|
||||
* the driver to the device.
|
||||
*/
|
||||
int probe_cfdata(struct pci_attach_args *pa)
|
||||
{
|
||||
size_t ncd = sizeof(cfdata) / sizeof(struct cfdata);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < ncd; i++) {
|
||||
struct cfdata *cf = &cfdata[i];
|
||||
struct cfdriver *cd = cf->cf_driver;
|
||||
|
||||
if (*cf->cf_parents != PCI_BUS_PARENT)
|
||||
continue;
|
||||
|
||||
struct cfattach *ca = cf->cf_attach;
|
||||
if (!ca->ca_match)
|
||||
continue;
|
||||
|
||||
int rv = ca->ca_match(&pci_bus, 0, pa);
|
||||
|
||||
if (rv) {
|
||||
struct device *dev = (struct device *) malloc(ca->ca_devsize,
|
||||
M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
|
||||
snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", cd->cd_name,
|
||||
dev->dv_unit);
|
||||
printf("%s at %s\n", dev->dv_xname, pci_bus.dv_xname);
|
||||
ca->ca_attach(&pci_bus, dev, pa);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct device *config_found_sm(struct device *parent, void *aux, cfprint_t print,
|
||||
cfmatch_t submatch)
|
||||
{
|
||||
struct cfdata *cf = &cfdata[0];
|
||||
struct cfattach *ca = cf->cf_attach;
|
||||
struct cfdriver *cd = cf->cf_driver;
|
||||
|
||||
int rv = ca->ca_match(parent, NULL, aux);
|
||||
if (rv) {
|
||||
struct device *dev = (struct device *) malloc(ca->ca_devsize, M_DEVBUF,
|
||||
M_NOWAIT|M_ZERO);
|
||||
|
||||
snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", cd->cd_name,
|
||||
dev->dv_unit);
|
||||
printf("%s at %s\n", dev->dv_xname, parent->dv_xname);
|
||||
|
||||
ca->ca_attach(parent, dev, aux);
|
||||
|
||||
audio_cd.cd_ndevs = 1;
|
||||
audio_cd.cd_devs = malloc(sizeof(void*), 0, 0);
|
||||
audio_cd.cd_devs[0] = dev;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
564
repos/dde_bsd/src/lib/audio/bus.cc
Normal file
564
repos/dde_bsd/src/lib/audio/bus.cc
Normal file
@ -0,0 +1,564 @@
|
||||
/*
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/object_pool.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <io_port_session/connection.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <pci_session/connection.h>
|
||||
#include <pci_device/client.h>
|
||||
|
||||
/* local includes */
|
||||
#include "bsd.h"
|
||||
#include <extern_c_begin.h>
|
||||
# include <bsd_emul.h>
|
||||
# include <dev/pci/pcidevs.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
extern "C" int probe_cfdata(struct pci_attach_args *);
|
||||
|
||||
namespace {
|
||||
|
||||
class Pci_driver : public Bsd::Bus_driver
|
||||
{
|
||||
public:
|
||||
|
||||
enum Pci_config { IRQ = 0x3c, CMD = 0x4,
|
||||
CMD_IO = 0x1, CMD_MEMORY = 0x2, CMD_MASTER = 0x4 };
|
||||
|
||||
private:
|
||||
|
||||
struct pci_attach_args _pa { 0, 0, 0, 0, 0 };
|
||||
|
||||
Pci::Connection _pci;
|
||||
Pci::Device_capability _cap;
|
||||
|
||||
Genode::Io_port_connection *_io_port { nullptr };
|
||||
|
||||
/**
|
||||
* The Dma_region_manager provides memory used for DMA
|
||||
* and manages its mappings.
|
||||
*/
|
||||
struct Dma_region_manager : public Genode::Allocator_avl
|
||||
{
|
||||
enum { BACKING_STORE_SIZE = 1024 * 1024 };
|
||||
|
||||
Genode::addr_t base;
|
||||
Genode::addr_t mapped_base;
|
||||
|
||||
bool _dma_initialized { false };
|
||||
|
||||
Pci_driver &_drv;
|
||||
|
||||
Dma_region_manager(Genode::Allocator &alloc, Pci_driver &drv)
|
||||
: Genode::Allocator_avl(&alloc), _drv(drv) { }
|
||||
|
||||
Genode::addr_t alloc(Genode::size_t size, int align)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
if (!_dma_initialized) {
|
||||
try {
|
||||
Ram_dataspace_capability cap = _drv._alloc_dma_memory(BACKING_STORE_SIZE);
|
||||
mapped_base = (addr_t)env()->rm_session()->attach(cap);
|
||||
base = Dataspace_client(cap).phys_addr();
|
||||
|
||||
Allocator_avl::add_range(mapped_base, BACKING_STORE_SIZE);
|
||||
} catch (...) {
|
||||
PERR("alloc DMA memory failed");
|
||||
return 0;
|
||||
}
|
||||
_dma_initialized = true;
|
||||
}
|
||||
|
||||
void *ptr = nullptr;
|
||||
bool err = Allocator_avl::alloc_aligned(size, &ptr, align).is_error();
|
||||
|
||||
return err ? 0 : (addr_t)ptr;
|
||||
}
|
||||
|
||||
void free(Genode::addr_t virt, Genode::size_t size) {
|
||||
Genode::Allocator_avl::free((void*)virt, size); }
|
||||
|
||||
Genode::addr_t virt_to_phys(Genode::addr_t virt) {
|
||||
return virt - mapped_base + base; }
|
||||
|
||||
Genode::addr_t phys_to_virt(Genode::addr_t phys) {
|
||||
return phys - base + mapped_base; }
|
||||
|
||||
} _dma_region_manager;
|
||||
|
||||
/**
|
||||
* Scan pci bus for sound devices
|
||||
*/
|
||||
Pci::Device_capability _scan_pci(Pci::Device_capability const &prev)
|
||||
{
|
||||
Pci::Device_capability cap;
|
||||
/* shift values for Pci interface used by Genode */
|
||||
cap = _pci.next_device(prev, PCI_CLASS_MULTIMEDIA << 16,
|
||||
PCI_CLASS_MASK << 16);
|
||||
if (prev.valid())
|
||||
_pci.release_device(prev);
|
||||
return cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate DMA memory from the PCI driver
|
||||
*/
|
||||
Genode::Ram_dataspace_capability _alloc_dma_memory(Genode::size_t size)
|
||||
{
|
||||
try {
|
||||
/* trigger that the device gets assigned to this driver (needed by IOMMUs) */
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
try {
|
||||
_pci.config_extended(_cap);
|
||||
break;
|
||||
} catch (Pci::Device::Quota_exceeded) {
|
||||
Genode::env()->parent()->upgrade(_pci.cap(), "ram_quota=4096");
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
Genode::snprintf(buf, sizeof(buf), "ram_quota=%zu", size);
|
||||
Genode::env()->parent()->upgrade(_pci.cap(), buf);
|
||||
|
||||
return _pci.alloc_dma_buffer(size);
|
||||
} catch (...) { return Genode::Ram_dataspace_capability(); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Pci_driver() : _dma_region_manager(*Genode::env()->heap(), *this) { }
|
||||
|
||||
Pci::Device_capability cap() { return _cap; }
|
||||
|
||||
Pci::Connection &pci() { return _pci; }
|
||||
|
||||
int probe()
|
||||
{
|
||||
/*
|
||||
* We hide ourself in the bus_dma_tag_t as well as
|
||||
* in the pci_chipset_tag_t field because they are
|
||||
* used in all pci or bus related functions and are
|
||||
* our access window, hence.
|
||||
*/
|
||||
_pa.pa_dmat = (bus_dma_tag_t)this;
|
||||
_pa.pa_pc = (pci_chipset_tag_t)this;
|
||||
|
||||
int found = 0;
|
||||
while ((_cap = _scan_pci(_cap)).valid()) {
|
||||
Pci::Device_client device(_cap);
|
||||
|
||||
uint8_t bus, dev, func;
|
||||
device.bus_address(&bus, &dev, &func);
|
||||
|
||||
/* XXX until we get the platform_drv, we blacklist HDMI/DP HDA devices */
|
||||
if (device.device_id() == PCI_PRODUCT_INTEL_CORE4G_HDA_2) {
|
||||
PWRN("ignore %u:%u:%u device, Intel Core 4G HDA not supported",
|
||||
bus, dev, func);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we do the shifting to match OpenBSD's assumptions */
|
||||
_pa.pa_tag = 0x80000000UL | (bus << 16) | (dev << 11) | (func << 8);
|
||||
_pa.pa_class = device.class_code() << 8;
|
||||
_pa.pa_id = device.vendor_id() | device.device_id() << 16;
|
||||
|
||||
if (probe_cfdata(&_pa)) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**************************
|
||||
** Bus_driver interface **
|
||||
**************************/
|
||||
|
||||
Genode::Irq_session_capability irq_session() override {
|
||||
return Pci::Device_client(_cap).irq(0); }
|
||||
|
||||
Genode::addr_t alloc(Genode::size_t size, int align) override {
|
||||
return _dma_region_manager.alloc(size, align); }
|
||||
|
||||
void free(Genode::addr_t virt, Genode::size_t size) override {
|
||||
_dma_region_manager.free(virt, size); }
|
||||
|
||||
Genode::addr_t virt_to_phys(Genode::addr_t virt) override {
|
||||
return _dma_region_manager.virt_to_phys(virt); }
|
||||
|
||||
Genode::addr_t phys_to_virt(Genode::addr_t phys) override {
|
||||
return _dma_region_manager.phys_to_virt(phys); }
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
** Bus space helper **
|
||||
**********************/
|
||||
|
||||
struct Bus_space
|
||||
{
|
||||
virtual unsigned read_1(unsigned long address) = 0;
|
||||
virtual unsigned read_2(unsigned long address) = 0;
|
||||
virtual unsigned read_4(unsigned long address) = 0;
|
||||
|
||||
virtual void write_1(unsigned long address, unsigned char value) = 0;
|
||||
virtual void write_2(unsigned long address, unsigned short value) = 0;
|
||||
virtual void write_4(unsigned long address, unsigned int value) = 0;
|
||||
};
|
||||
|
||||
|
||||
/*********************
|
||||
** I/O port helper **
|
||||
*********************/
|
||||
|
||||
struct Io_port : public Bus_space
|
||||
{
|
||||
Genode::Io_port_session_client _io;
|
||||
Genode::addr_t _base;
|
||||
|
||||
Io_port(Genode::addr_t base, Genode::Io_port_session_capability cap)
|
||||
: _io(cap), _base(base) { }
|
||||
|
||||
unsigned read_1(unsigned long address) {
|
||||
return _io.inb(_base + address); }
|
||||
|
||||
unsigned read_2(unsigned long address) {
|
||||
return _io.inw(_base + address); }
|
||||
|
||||
unsigned read_4(unsigned long address) {
|
||||
return _io.inl(_base + address); }
|
||||
|
||||
void write_1(unsigned long address, unsigned char value) {
|
||||
_io.outb(_base + address, value); }
|
||||
|
||||
void write_2(unsigned long address, unsigned short value) {
|
||||
_io.outw(_base + address, value); }
|
||||
|
||||
void write_4(unsigned long address, unsigned int value) {
|
||||
_io.outl(_base + address, value); }
|
||||
};
|
||||
|
||||
|
||||
/***********************
|
||||
** I/O memory helper **
|
||||
***********************/
|
||||
|
||||
struct Io_memory : public Bus_space
|
||||
{
|
||||
Genode::Io_mem_session_client _mem;
|
||||
Genode::Io_mem_dataspace_capability _mem_ds;
|
||||
Genode::addr_t _vaddr;
|
||||
|
||||
Io_memory(Genode::addr_t base, Genode::Io_mem_session_capability cap)
|
||||
:
|
||||
_mem(cap),
|
||||
_mem_ds(_mem.dataspace())
|
||||
{
|
||||
if (!_mem_ds.valid())
|
||||
throw Genode::Exception();
|
||||
|
||||
_vaddr = Genode::env()->rm_session()->attach(_mem_ds);
|
||||
_vaddr |= base & 0xfff;
|
||||
}
|
||||
|
||||
unsigned read_1(unsigned long address) {
|
||||
return *(volatile unsigned char*)(_vaddr + address); }
|
||||
|
||||
unsigned read_2(unsigned long address) {
|
||||
return *(volatile unsigned short*)(_vaddr + address); }
|
||||
|
||||
unsigned read_4(unsigned long address) {
|
||||
return *(volatile unsigned int*)(_vaddr + address); }
|
||||
|
||||
void write_1(unsigned long address, unsigned char value) {
|
||||
*(volatile unsigned char*)(_vaddr + address) = value; }
|
||||
|
||||
void write_2(unsigned long address, unsigned short value) {
|
||||
*(volatile unsigned short*)(_vaddr + address) = value; }
|
||||
|
||||
void write_4(unsigned long address, unsigned int value) {
|
||||
*(volatile unsigned int*)(_vaddr + address) = value; }
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
|
||||
int Bsd::probe_drivers()
|
||||
{
|
||||
PINF("--- probe drivers ---");
|
||||
static Pci_driver drv;
|
||||
return drv.probe();
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** dev/pci/pcivar.h **
|
||||
**********************/
|
||||
|
||||
extern "C" int pci_matchbyid(struct pci_attach_args *pa, const struct pci_matchid *ids, int num)
|
||||
{
|
||||
pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id);
|
||||
pci_product_id_t pid = PCI_PRODUCT(pa->pa_id);
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (vid == ids[i].pm_vid && pid == ids[i].pm_pid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_mapreg_map(struct pci_attach_args *pa,
|
||||
int reg, pcireg_t type,
|
||||
int flags, bus_space_tag_t *tagp,
|
||||
bus_space_handle_t *handlep, bus_addr_t *basep,
|
||||
bus_size_t *sizep, bus_size_t maxsize)
|
||||
{
|
||||
/* calculate BAR from given register */
|
||||
int r = (reg - 0x10) / 4;
|
||||
|
||||
Pci_driver *drv = (Pci_driver*)pa->pa_pc;
|
||||
|
||||
Pci::Device_capability cap = drv->cap();
|
||||
Pci::Device_client device(cap);
|
||||
Pci::Device::Resource res = device.resource(r);
|
||||
|
||||
switch (res.type()) {
|
||||
case Pci::Device::Resource::IO:
|
||||
{
|
||||
Io_port *iop = new (Genode::env()->heap())
|
||||
Io_port(res.base(), device.io_port(r));
|
||||
*tagp = (Genode::addr_t) iop;
|
||||
break;
|
||||
}
|
||||
case Pci::Device::Resource::MEMORY:
|
||||
{
|
||||
Io_memory *iom = new (Genode::env()->heap())
|
||||
Io_memory(res.base(), device.io_mem(r));
|
||||
*tagp = (Genode::addr_t) iom;
|
||||
break;
|
||||
}
|
||||
case Pci::Device::Resource::INVALID:
|
||||
{
|
||||
PERR("PCI resource type invalid");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*handlep = res.base();
|
||||
|
||||
if (basep != 0)
|
||||
*basep = res.base();
|
||||
if (sizep != 0)
|
||||
*sizep = maxsize > 0 && res.size() > maxsize ? maxsize : res.size();
|
||||
|
||||
/* enable bus master and I/O or memory bits */
|
||||
uint16_t cmd = device.config_read(Pci_driver::CMD, Pci::Device::ACCESS_16BIT);
|
||||
if (res.type() == Pci::Device::Resource::IO) {
|
||||
cmd &= ~Pci_driver:: CMD_MEMORY;
|
||||
cmd |= Pci_driver::CMD_IO;
|
||||
} else {
|
||||
cmd &= ~Pci_driver::CMD_IO;
|
||||
cmd |= Pci_driver::CMD_MEMORY;
|
||||
}
|
||||
|
||||
cmd |= Pci_driver::CMD_MASTER;
|
||||
device.config_write(Pci_driver::CMD, cmd, Pci::Device::ACCESS_16BIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
** machine/pci_machdep.h **
|
||||
***************************/
|
||||
|
||||
extern "C" pcireg_t pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)pc;
|
||||
Pci::Device_client device(drv->cap());
|
||||
return device.config_read(reg, Pci::Device::ACCESS_32BIT);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg,
|
||||
pcireg_t val)
|
||||
{
|
||||
Pci_driver *drv = (Pci_driver *)pc;
|
||||
Pci::Device_client device(drv->cap());
|
||||
return device.config_write(reg, val, Pci::Device::ACCESS_32BIT);
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** machine/bus.h **
|
||||
*******************/
|
||||
|
||||
extern "C" u_int8_t bus_space_read_1(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
return bus->read_1(offset);
|
||||
}
|
||||
|
||||
|
||||
extern "C" u_int16_t bus_space_read_2(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
return bus->read_2(offset);
|
||||
}
|
||||
|
||||
|
||||
extern "C" u_int32_t bus_space_read_4(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
return bus->read_4(offset);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_space_write_1(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset, u_int8_t value)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
bus->write_1(offset, value);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_space_write_2(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset, u_int16_t value)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
bus->write_2(offset, value);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_space_write_4(bus_space_tag_t space,
|
||||
bus_space_handle_t handle,
|
||||
bus_size_t offset, u_int32_t value)
|
||||
{
|
||||
Bus_space *bus = (Bus_space*)space;
|
||||
bus->write_4(offset, value);
|
||||
}
|
||||
|
||||
|
||||
extern "C" int bus_dmamap_create(bus_dma_tag_t tag, bus_size_t size, int nsegments,
|
||||
bus_size_t maxsegsz, bus_size_t boundart,
|
||||
int flags, bus_dmamap_t *dmamp)
|
||||
{
|
||||
struct bus_dmamap *map;
|
||||
map = (struct bus_dmamap*) malloc(sizeof(struct bus_dmamap), M_DEVBUF, M_ZERO);
|
||||
|
||||
map->size = size;
|
||||
map->maxsegsz = maxsegsz;
|
||||
map->nsegments = nsegments;
|
||||
|
||||
*dmamp = map;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_dmamap_destroy(bus_dma_tag_t tag, bus_dmamap_t map) {
|
||||
free(map, 0, 0); }
|
||||
|
||||
|
||||
extern "C" int bus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t dmam, void *buf,
|
||||
bus_size_t buflen, struct proc *p, int flags)
|
||||
{
|
||||
Bsd::Bus_driver *drv = (Bsd::Bus_driver *)tag;
|
||||
|
||||
Genode::addr_t virt = (Genode::addr_t)buf;
|
||||
dmam->dm_segs[0].ds_addr = drv->virt_to_phys(virt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t)
|
||||
{
|
||||
PDBG("not implemented, called from %p", __builtin_return_address(0));
|
||||
}
|
||||
|
||||
|
||||
extern "C" int bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment,
|
||||
bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
|
||||
int *rsegs, int flags)
|
||||
{
|
||||
Bsd::Bus_driver *drv = (Bsd::Bus_driver *)tag;
|
||||
|
||||
Genode::addr_t virt = drv->alloc(size, Genode::log2(alignment));
|
||||
if (virt == 0)
|
||||
return -1;
|
||||
|
||||
segs->ds_addr = drv->virt_to_phys(virt);
|
||||
segs->ds_size = size;
|
||||
*rsegs = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs)
|
||||
{
|
||||
Bsd::Bus_driver *drv = (Bsd::Bus_driver *)tag;
|
||||
|
||||
for (int i = 0; i < nsegs; i++) {
|
||||
Genode::addr_t phys = (Genode::addr_t)segs[i].ds_addr;
|
||||
Genode::addr_t virt = drv->phys_to_virt(phys);
|
||||
|
||||
drv->free(virt, segs[i].ds_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" int bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
|
||||
size_t size, caddr_t *kvap, int flags)
|
||||
{
|
||||
if (nsegs > 1) {
|
||||
PERR("%s: cannot map more than 1 segment", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Bsd::Bus_driver *drv = (Bsd::Bus_driver *)tag;
|
||||
|
||||
Genode::addr_t phys = (Genode::addr_t)segs[0].ds_addr;
|
||||
Genode::addr_t virt = drv->phys_to_virt(phys);
|
||||
|
||||
*kvap = (caddr_t)virt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void bus_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t) { }
|
||||
|
||||
|
||||
extern "C" paddr_t bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *,
|
||||
int, off_t, int, int)
|
||||
{
|
||||
PDBG("not implemented, called from %p", __builtin_return_address(0));
|
||||
return 0;
|
||||
}
|
168
repos/dde_bsd/src/lib/audio/driver.cc
Normal file
168
repos/dde_bsd/src/lib/audio/driver.cc
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/signal.h> /* FIXME needed by audio_out_session.h */
|
||||
#include <audio_out_session/audio_out_session.h>
|
||||
#include <os/server.h>
|
||||
|
||||
/* local includes */
|
||||
#include <audio/audio.h>
|
||||
#include <bsd.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <bsd_emul.h>
|
||||
# include <sys/device.h>
|
||||
# include <sys/audioio.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
static bool const verbose = false;
|
||||
|
||||
extern struct cfdriver audio_cd;
|
||||
|
||||
static dev_t const adev = 0x80; /* audio0 128 */
|
||||
static dev_t const mdev = 0x10; /* mixer0 16 */
|
||||
|
||||
static bool adev_usuable = false;
|
||||
|
||||
|
||||
static bool drv_loaded() { return audio_cd.cd_ndevs > 0 ? true : false; }
|
||||
|
||||
|
||||
static void dump_prinfo(struct audio_prinfo *prinfo)
|
||||
{
|
||||
struct audio_info ai;
|
||||
|
||||
int err = audioioctl(adev, AUDIO_GETINFO, (char*)&ai, 0, 0);
|
||||
if (err) {
|
||||
PERR("could not gather play information");
|
||||
return;
|
||||
}
|
||||
|
||||
PLOG("--- play information ---");
|
||||
PLOG("sample_rate: %u", prinfo->sample_rate);
|
||||
PLOG("channels: %u", prinfo->channels);
|
||||
PLOG("precision: %u", prinfo->precision);
|
||||
PLOG("bps: %u", prinfo->bps);
|
||||
PLOG("encoding: %u", prinfo->encoding);
|
||||
PLOG("gain: %u", prinfo->gain);
|
||||
PLOG("port: %u", prinfo->port);
|
||||
PLOG("seek: %u", prinfo->seek);
|
||||
PLOG("avail_ports: %u", prinfo->avail_ports);
|
||||
PLOG("buffer_size: %u", prinfo->buffer_size);
|
||||
PLOG("block_size: %u", prinfo->block_size);
|
||||
/* current state of the device */
|
||||
PLOG("samples: %u", prinfo->samples);
|
||||
PLOG("eof: %u", prinfo->eof);
|
||||
PLOG("pause: %u", prinfo->pause);
|
||||
PLOG("error: %u", prinfo->error);
|
||||
PLOG("waiting: %u", prinfo->waiting);
|
||||
PLOG("balance: %u", prinfo->balance);
|
||||
PLOG("open: %u", prinfo->open);
|
||||
PLOG("active: %u", prinfo->active);
|
||||
}
|
||||
|
||||
|
||||
static bool open_audio_device(dev_t dev)
|
||||
{
|
||||
if (!drv_loaded())
|
||||
return false;
|
||||
|
||||
int err = audioopen(dev, FWRITE, 0 /* ifmt */, 0 /* proc */);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool configure_audio_device(dev_t dev)
|
||||
{
|
||||
struct audio_info ai;
|
||||
|
||||
int err = audioioctl(adev, AUDIO_GETINFO, (char*)&ai, 0, 0);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
using namespace Audio;
|
||||
|
||||
/* configure the device according to our Audio_session settings */
|
||||
ai.play.sample_rate = Audio_out::SAMPLE_RATE;
|
||||
ai.play.channels = MAX_CHANNELS;
|
||||
ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
|
||||
ai.play.block_size = MAX_CHANNELS * sizeof(short) * Audio_out::PERIOD;
|
||||
|
||||
err = audioioctl(adev, AUDIO_SETINFO, (char*)&ai, 0, 0);
|
||||
if (err)
|
||||
return false;
|
||||
|
||||
if (verbose)
|
||||
dump_prinfo(&ai.play);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void run_bsd(void *)
|
||||
{
|
||||
if (!Bsd::probe_drivers()) {
|
||||
PERR("no supported sound card found");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
if (!open_audio_device(adev)) {
|
||||
PERR("could not initialize sound card");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
adev_usuable = configure_audio_device(adev);
|
||||
|
||||
while (true) {
|
||||
Bsd::scheduler().current()->block_and_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
static Bsd::Task *_task;
|
||||
|
||||
|
||||
/*****************************
|
||||
** private Audio namespace **
|
||||
*****************************/
|
||||
|
||||
void Audio::init_driver(Server::Entrypoint &ep)
|
||||
{
|
||||
Bsd::irq_init(ep);
|
||||
Bsd::timer_init(ep);
|
||||
|
||||
static Bsd::Task task_bsd(run_bsd, nullptr, "bsd",
|
||||
Bsd::Task::PRIORITY_0, Bsd::scheduler(),
|
||||
2048 * sizeof(long));
|
||||
|
||||
_task = &task_bsd;
|
||||
|
||||
Bsd::scheduler().schedule();
|
||||
}
|
||||
|
||||
|
||||
bool Audio::driver_active()
|
||||
{
|
||||
return drv_loaded() && adev_usuable;
|
||||
}
|
||||
|
||||
|
||||
int Audio::play(short *data, Genode::size_t size)
|
||||
{
|
||||
struct uio uio = { 0, size, data, size };
|
||||
return audiowrite(adev, &uio, IO_NDELAY);
|
||||
}
|
67
repos/dde_bsd/src/lib/audio/dummies.cc
Normal file
67
repos/dde_bsd/src/lib/audio/dummies.cc
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* \brief Dummy functions
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/printf.h>
|
||||
|
||||
extern "C" {
|
||||
typedef long DUMMY;
|
||||
|
||||
enum {
|
||||
SHOW_DUMMY = 0,
|
||||
SHOW_SKIP = 0,
|
||||
SHOW_RET = 0,
|
||||
};
|
||||
|
||||
#define DUMMY(retval, name) \
|
||||
DUMMY name(void) { \
|
||||
if (SHOW_DUMMY) \
|
||||
PDBG( #name " called (from %p) not implemented", __builtin_return_address(0)); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define DUMMY_SKIP(retval, name) \
|
||||
DUMMY name(void) { \
|
||||
if (SHOW_SKIP) \
|
||||
PLOG( #name " called (from %p) skipped", __builtin_return_address(0)); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define DUMMY_RET(retval, name) \
|
||||
DUMMY name(void) { \
|
||||
if (SHOW_RET) \
|
||||
PWRN( #name " called (from %p) return %d", __builtin_return_address(0), retval); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
DUMMY_RET(1, pci_intr_map_msi) /* do not support MSI API */
|
||||
DUMMY_RET(0, pci_intr_string)
|
||||
|
||||
DUMMY(0, bus_space_unmap)
|
||||
DUMMY(0, config_activate_children)
|
||||
DUMMY(0, config_deactivate)
|
||||
DUMMY(0, config_detach)
|
||||
DUMMY(0, config_detach_children)
|
||||
DUMMY(0, cpu_info_primary)
|
||||
DUMMY(0, pci_findvendor)
|
||||
DUMMY(0, pci_intr_disestablish)
|
||||
DUMMY(0, pci_set_powerstate)
|
||||
DUMMY(0, psignal)
|
||||
DUMMY(0, selrecord)
|
||||
DUMMY(0, selwakeup)
|
||||
DUMMY(0, timeout_add_msec)
|
||||
DUMMY(0, timeout_del)
|
||||
DUMMY(0, timeout_set)
|
||||
DUMMY(0, tsleep)
|
||||
DUMMY(0, vdevgone)
|
||||
|
||||
} /* extern "C" */
|
670
repos/dde_bsd/src/lib/audio/include/bsd_emul.h
Normal file
670
repos/dde_bsd/src/lib/audio/include/bsd_emul.h
Normal file
@ -0,0 +1,670 @@
|
||||
/*
|
||||
* \brief Emulation of the OpenBSD kernel API
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-09
|
||||
*
|
||||
* The content of this file, in particular data structures, is partially
|
||||
* derived from OpenBSD-internal headers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _BSD_EMUL_H_
|
||||
#define _BSD_EMUL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*****************
|
||||
** sys/types.h **
|
||||
*****************/
|
||||
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef unsigned int u_int32_t;
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef signed long ssize_t;
|
||||
|
||||
typedef char * caddr_t;
|
||||
typedef unsigned long paddr_t;
|
||||
|
||||
typedef signed int dev_t;
|
||||
typedef signed long long off_t;
|
||||
|
||||
#define minor(x) ((int32_t)((x) & 0xff) | (((x) & 0xffff0000) >> 8))
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/errno.h **
|
||||
*****************/
|
||||
|
||||
enum {
|
||||
EIO = 5,
|
||||
ENXIO = 6,
|
||||
ENOMEM = 12,
|
||||
EACCES = 13,
|
||||
EBUSY = 16,
|
||||
ENODEV = 19,
|
||||
EINVAL = 22,
|
||||
ENOTTY = 25,
|
||||
EAGAIN = 35,
|
||||
EWOULDBLOCK = EAGAIN,
|
||||
ETIMEDOUT = 60,
|
||||
};
|
||||
|
||||
|
||||
/******************
|
||||
** sys/signal.h **
|
||||
******************/
|
||||
|
||||
enum {
|
||||
SIGIO = 23,
|
||||
};
|
||||
|
||||
|
||||
/******************
|
||||
** sys/malloc.h **
|
||||
******************/
|
||||
|
||||
enum {
|
||||
/* malloc flags */
|
||||
M_WAITOK = 0x01,
|
||||
M_NOWAIT = 0x02,
|
||||
M_ZERO = 0x08,
|
||||
/* types of memory */
|
||||
M_DEVBUF = 2,
|
||||
};
|
||||
|
||||
void *malloc(size_t, int, int);
|
||||
void *mallocarray(size_t, size_t, int, int);
|
||||
void free(void *, int, size_t);
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/param.h **
|
||||
*****************/
|
||||
|
||||
enum {
|
||||
PZERO = 22,
|
||||
PWAIT = 32,
|
||||
|
||||
PCATCH = 0x100,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL (void*)0
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||
|
||||
|
||||
/******************
|
||||
** sys/kernel.h **
|
||||
******************/
|
||||
|
||||
enum { HZ = 100 };
|
||||
|
||||
|
||||
extern int hz;
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/cdefs.h **
|
||||
*****************/
|
||||
|
||||
#define __packed __attribute((__packed__))
|
||||
|
||||
|
||||
/****************
|
||||
** sys/proc.h **
|
||||
****************/
|
||||
|
||||
struct proc { };
|
||||
|
||||
|
||||
/****************
|
||||
** sys/task.h **
|
||||
****************/
|
||||
|
||||
struct task { };
|
||||
|
||||
/***************
|
||||
** sys/uio.h **
|
||||
***************/
|
||||
|
||||
struct uio
|
||||
{
|
||||
off_t uio_offset;
|
||||
size_t uio_resid;
|
||||
|
||||
/* emul specific fields */
|
||||
void *buf;
|
||||
size_t buflen;
|
||||
};
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/event.h **
|
||||
*****************/
|
||||
|
||||
enum {
|
||||
EVFILT_READ = -1,
|
||||
EVFILT_WRITE = -2,
|
||||
};
|
||||
|
||||
struct kevent
|
||||
{
|
||||
short filter;
|
||||
};
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
struct knote;
|
||||
SLIST_HEAD(klist, knote);
|
||||
|
||||
struct filterops
|
||||
{
|
||||
int f_isfd;
|
||||
int (*f_attach)(struct knote*);
|
||||
void (*f_detach)(struct knote*);
|
||||
int (*f_event)(struct knote*, long);
|
||||
};
|
||||
|
||||
struct knote
|
||||
{
|
||||
SLIST_ENTRY(knote) kn_selnext;
|
||||
struct kevent kn_kevent;
|
||||
#define kn_filter kn_kevent.filter
|
||||
|
||||
const struct filterops *kn_fop;
|
||||
void *kn_hook;
|
||||
};
|
||||
|
||||
|
||||
/*******************
|
||||
** sys/selinfo.h **
|
||||
*******************/
|
||||
|
||||
struct selinfo
|
||||
{
|
||||
struct klist si_note;
|
||||
};
|
||||
|
||||
void selrecord(struct proc *selector, struct selinfo *);
|
||||
void selwakeup(struct selinfo *);
|
||||
|
||||
|
||||
/*******************
|
||||
** machine/cpu.h **
|
||||
*******************/
|
||||
|
||||
struct cpu_info { };
|
||||
extern struct cpu_info cpu_info_primary;
|
||||
|
||||
#define curcpu() (&cpu_info_primary)
|
||||
|
||||
|
||||
/*********************
|
||||
** machine/mutex.h **
|
||||
*********************/
|
||||
|
||||
#define MUTEX_INITIALIZER(ipl) { 0, (ipl), 0, NULL }
|
||||
#define MUTEX_ASSERT_UNLOCK(mtx) do { \
|
||||
if ((mtx)->mtx_owner != curcpu()) \
|
||||
panic("mutex %p not held in %s\n", (mtx), __func__); \
|
||||
} while (0)
|
||||
#define MUTEX_ASSERT_LOCKED(mtx) do { \
|
||||
if ((mtx)->mtx_owner != curcpu()) \
|
||||
panic("mutex %p not held in %s\n", (mtx), __func__); \
|
||||
} while (0)
|
||||
#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
|
||||
if ((mtx)->mtx_owner == curcpu()) \
|
||||
panic("mutex %p held in %s\n", (mtx), __func__); \
|
||||
} while (0)
|
||||
|
||||
struct mutex
|
||||
{
|
||||
volatile int mtx_lock;
|
||||
int mtx_wantipl; /* interrupt priority level */
|
||||
int mtx_oldipl;
|
||||
void *mtx_owner;
|
||||
};
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/mutex.h **
|
||||
*****************/
|
||||
|
||||
void mtx_enter(struct mutex *);
|
||||
void mtx_leave(struct mutex *);
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/systm.h **
|
||||
*****************/
|
||||
|
||||
extern int nchrdev;
|
||||
|
||||
int enodev(void);
|
||||
|
||||
int printf(const char *, ...);
|
||||
int snprintf(char *buf, size_t, const char *, ...);
|
||||
void panic(const char *, ...);
|
||||
|
||||
void bcopy(const void *, void *, size_t);
|
||||
void bzero(void *, size_t);
|
||||
void *memcpy(void *, const void *, size_t);
|
||||
void *memset(void *, int, size_t);
|
||||
|
||||
void wakeup(const volatile void*);
|
||||
int tsleep(const volatile void *, int, const char *, int);
|
||||
int msleep(const volatile void *, struct mutex *, int, const char*, int);
|
||||
|
||||
int uiomovei(void *, int, struct uio *);
|
||||
|
||||
|
||||
/*******************
|
||||
** lib/libkern.h **
|
||||
*******************/
|
||||
|
||||
static inline u_int max(u_int a, u_int b) { return (a > b ? a : b); }
|
||||
static inline u_int min(u_int a, u_int b) { return (a < b ? a : b); }
|
||||
|
||||
size_t strlcpy(char *, const char *, size_t);
|
||||
int strcmp(const char *, const char *);
|
||||
|
||||
|
||||
/*********************
|
||||
** machine/param.h **
|
||||
*********************/
|
||||
|
||||
#define DELAY(x) delay(x)
|
||||
void delay(int);
|
||||
|
||||
|
||||
/*******************************
|
||||
** machine/intrdefs.h **
|
||||
*******************************/
|
||||
|
||||
enum {
|
||||
IPL_AUDIO = 8,
|
||||
IPL_MPSAFE = 0x100,
|
||||
};
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/fcntl.h **
|
||||
*****************/
|
||||
|
||||
enum {
|
||||
FREAD = 0x0001,
|
||||
FWRITE = 0x0002,
|
||||
};
|
||||
|
||||
|
||||
/****************
|
||||
** sys/poll.h **
|
||||
****************/
|
||||
|
||||
enum {
|
||||
POLLIN = 0x0001,
|
||||
POLLOUT = 0x0004,
|
||||
POLLERR = 0x0008,
|
||||
POLLRDNORM = 0x0040,
|
||||
POLLWRNORM = POLLOUT,
|
||||
};
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/vnode.h **
|
||||
*****************/
|
||||
|
||||
enum vtype {
|
||||
VCHR,
|
||||
};
|
||||
|
||||
enum {
|
||||
IO_NDELAY = 0x10,
|
||||
};
|
||||
|
||||
void vdevgone(int, int, int, enum vtype);
|
||||
|
||||
|
||||
/******************
|
||||
** sys/ioccom.h **
|
||||
******************/
|
||||
|
||||
#define IOCPARM_MASK 0x1fff
|
||||
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
|
||||
#define IOCGROUP(x) (((x) >> 8) & 0xff)
|
||||
|
||||
#define IOC_VOID (unsigned long)0x20000000
|
||||
#define IOC_OUT (unsigned long)0x40000000
|
||||
#define IOC_IN (unsigned long)0x80000000
|
||||
#define IOC_INOUT (IOC_IN|IOC_OUT)
|
||||
|
||||
#define _IOC(inout,group,num,len) \
|
||||
(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
|
||||
#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0)
|
||||
#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
|
||||
#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
|
||||
#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/filio.h **
|
||||
*****************/
|
||||
|
||||
#define FIONBIO _IOW('f', 126, int)
|
||||
#define FIOASYNC _IOW('f', 125, int)
|
||||
|
||||
|
||||
/***************
|
||||
** sys/tty.h **
|
||||
***************/
|
||||
|
||||
struct tty { };
|
||||
|
||||
|
||||
/****************
|
||||
** sys/conf.h **
|
||||
****************/
|
||||
|
||||
struct cdevsw
|
||||
{
|
||||
int (*d_open)(dev_t dev, int oflags, int devtype, struct proc *p);
|
||||
int (*d_close)(dev_t dev, int fflag, int devtype, struct proc *);
|
||||
int (*d_read)(dev_t dev, struct uio *uio, int ioflag);
|
||||
int (*d_write)(dev_t dev, struct uio *uio, int ioflag);
|
||||
int (*d_ioctl)(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p);
|
||||
int (*d_stop)(struct tty *tp, int rw);
|
||||
struct tty *(*d_tty)(dev_t dev);
|
||||
int (*d_poll)(dev_t dev, int events, struct proc *p);
|
||||
paddr_t (*d_mmap)(dev_t, off_t, int);
|
||||
u_int d_type;
|
||||
u_int d_flags;
|
||||
int (*d_kqfilter)(dev_t dev, struct knote *kn);
|
||||
};
|
||||
|
||||
extern struct cdevsw cdevsw[];
|
||||
|
||||
/**
|
||||
* Normally these functions are defined by macro magic but we declare
|
||||
* them verbatim.
|
||||
*/
|
||||
int audioopen(dev_t, int, int, struct proc *);
|
||||
int audioclose(dev_t, int, int, struct proc *);
|
||||
int audioread(dev_t, struct uio *, int);
|
||||
int audiowrite(dev_t, struct uio *, int);
|
||||
int audioioctl(dev_t, u_long, caddr_t, int, struct proc *);
|
||||
int audiostop(struct tty *, int);
|
||||
struct tty *audiotty(dev_t);
|
||||
int audiopoll(dev_t, int, struct proc *);
|
||||
paddr_t audiommap(dev_t, off_t, int);
|
||||
int audiokqfilter(dev_t, struct knote *);
|
||||
|
||||
#define NMIDI 0
|
||||
|
||||
/******************
|
||||
** sys/select.h **
|
||||
******************/
|
||||
|
||||
enum {
|
||||
NBBY = 8, /* num of bits in byte */
|
||||
};
|
||||
|
||||
|
||||
/*********************
|
||||
** sys/singalvar.h **
|
||||
*********************/
|
||||
|
||||
void psignal(struct proc *p, int sig);
|
||||
|
||||
|
||||
/******************
|
||||
** sys/rndvar.h **
|
||||
******************/
|
||||
|
||||
#define add_audio_randomness(d)
|
||||
|
||||
|
||||
/*******************
|
||||
** machine/bus.h **
|
||||
*******************/
|
||||
|
||||
typedef u_long bus_addr_t;
|
||||
typedef u_long bus_size_t;
|
||||
typedef u_long bus_space_handle_t;
|
||||
|
||||
struct bus_dma_segment
|
||||
{
|
||||
bus_addr_t ds_addr;
|
||||
|
||||
/* emul specific fields */
|
||||
bus_size_t ds_size;
|
||||
};
|
||||
typedef struct bus_dma_segment bus_dma_segment_t;
|
||||
|
||||
typedef struct bus_dmamap* bus_dmamap_t;
|
||||
struct bus_dmamap
|
||||
{
|
||||
bus_dma_segment_t dm_segs[1];
|
||||
|
||||
/* emul specific fields */
|
||||
bus_size_t size;
|
||||
bus_size_t maxsegsz;
|
||||
int nsegments;
|
||||
};
|
||||
|
||||
typedef struct bus_dma_tag *bus_dma_tag_t;
|
||||
struct bus_dma_tag
|
||||
{
|
||||
void *_cookie; /* cookie used in the guts */
|
||||
|
||||
/*
|
||||
* DMA mapping methods.
|
||||
*/
|
||||
int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
|
||||
bus_size_t, bus_size_t, int, bus_dmamap_t *);
|
||||
void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
|
||||
int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
|
||||
bus_size_t, struct proc *, int);
|
||||
void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
|
||||
|
||||
/*
|
||||
* DMA memory utility functions.
|
||||
*/
|
||||
int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
|
||||
bus_size_t, bus_dma_segment_t *, int, int *, int);
|
||||
void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
|
||||
int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
|
||||
int, size_t, caddr_t *, int);
|
||||
void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
|
||||
paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
|
||||
int, off_t, int, int);
|
||||
|
||||
};
|
||||
|
||||
int bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, bus_size_t, int, bus_dmamap_t *);
|
||||
void bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
|
||||
int bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, struct proc *, int);
|
||||
void bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
|
||||
|
||||
int bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, bus_dma_segment_t *, int, int *, int);
|
||||
void bus_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
|
||||
int bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t, caddr_t *, int);
|
||||
void bus_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t);
|
||||
paddr_t bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int);
|
||||
|
||||
typedef u_long bus_space_tag_t;
|
||||
|
||||
void bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
|
||||
|
||||
u_int8_t bus_space_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
|
||||
u_int16_t bus_space_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
|
||||
u_int32_t bus_space_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
|
||||
void bus_space_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int8_t);
|
||||
void bus_space_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int16_t);
|
||||
void bus_space_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, u_int32_t);
|
||||
|
||||
enum {
|
||||
BUS_DMA_WAITOK = 0x0000,
|
||||
BUS_DMA_NOWAIT = 0x0001,
|
||||
BUS_DMA_COHERENT = 0x0004,
|
||||
};
|
||||
|
||||
|
||||
/**********************
|
||||
** dev/pci/pcireg.h **
|
||||
**********************/
|
||||
|
||||
typedef u_int16_t pci_vendor_id_t;
|
||||
typedef u_int16_t pci_product_id_t;
|
||||
|
||||
#define PCI_VENDOR_SHIFT 0
|
||||
#define PCI_VENDOR_MASK 0xffff
|
||||
#define PCI_VENDOR(id) \
|
||||
(((id) >> PCI_VENDOR_SHIFT) & PCI_VENDOR_MASK)
|
||||
|
||||
#define PCI_PRODUCT_SHIFT 16
|
||||
#define PCI_PRODUCT_MASK 0xffff
|
||||
#define PCI_PRODUCT(id) \
|
||||
(((id) >> PCI_PRODUCT_SHIFT) & PCI_PRODUCT_MASK)
|
||||
|
||||
#define PCI_CLASS_SHIFT 24
|
||||
#define PCI_CLASS_MASK 0xff
|
||||
#define PCI_CLASS(cr) \
|
||||
(((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK)
|
||||
|
||||
#define PCI_SUBCLASS_SHIFT 16
|
||||
#define PCI_SUBCLASS_MASK 0xff
|
||||
#define PCI_SUBCLASS(cr) \
|
||||
(((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK)
|
||||
|
||||
#define PCI_REVISION_SHIFT 0
|
||||
#define PCI_REVISION_MASK 0xff
|
||||
#define PCI_REVISION(cr) \
|
||||
(((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK)
|
||||
|
||||
enum {
|
||||
PCI_COMMAND_IO_ENABLE = 0x00000001,
|
||||
PCI_COMMAND_STATUS_REG = 0x04,
|
||||
PCI_COMMAND_BACKTOBACK_ENABLE = 0x00000200,
|
||||
|
||||
PCI_CLASS_MULTIMEDIA = 0x04,
|
||||
|
||||
PCI_SUBCLASS_MULTIMEDIA_HDAUDIO = 0x03,
|
||||
|
||||
PCI_MAPREG_TYPE_MASK = 0x00000001,
|
||||
PCI_MAPREG_MEM_TYPE_MASK = 0x00000006,
|
||||
|
||||
PCI_MAPREG_TYPE_IO = 0x00000001,
|
||||
PCI_MAPREG_TYPE_MEM = 0x00000000,
|
||||
|
||||
PCI_SUBSYS_ID_REG = 0x2c,
|
||||
|
||||
PCI_PMCSR_STATE_D0 = 0x0000,
|
||||
};
|
||||
|
||||
#define PCI_MAPREG_IO_ADDR(mr) \
|
||||
((mr) & PCI_MAPREG_IO_ADDR_MASK)
|
||||
#define PCI_MAPREG_IO_SIZE(mr) \
|
||||
(PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))
|
||||
#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffe
|
||||
|
||||
|
||||
/**********************
|
||||
** dev/pci/pcivar.h **
|
||||
**********************/
|
||||
|
||||
/* actually from pci_machdep.h */
|
||||
typedef void *pci_chipset_tag_t;
|
||||
typedef uint32_t pcitag_t;
|
||||
|
||||
|
||||
typedef uint32_t pcireg_t;
|
||||
struct pci_attach_args
|
||||
{
|
||||
bus_dma_tag_t pa_dmat;
|
||||
pci_chipset_tag_t pa_pc;
|
||||
pcitag_t pa_tag;
|
||||
pcireg_t pa_id;
|
||||
pcireg_t pa_class;
|
||||
};
|
||||
|
||||
struct pci_matchid {
|
||||
pci_vendor_id_t pm_vid;
|
||||
pci_product_id_t pm_pid;
|
||||
};
|
||||
|
||||
|
||||
int pci_matchbyid(struct pci_attach_args *, const struct pci_matchid *, int);
|
||||
int pci_set_powerstate(pci_chipset_tag_t, pcitag_t, int);
|
||||
int pci_mapreg_map(struct pci_attach_args *, int, pcireg_t, int,
|
||||
bus_space_tag_t *, bus_space_handle_t *, bus_addr_t *,
|
||||
bus_size_t *, bus_size_t);
|
||||
const char *pci_findvendor(pcireg_t);
|
||||
|
||||
/***************************
|
||||
** machine/pci_machdep.h **
|
||||
***************************/
|
||||
|
||||
struct pci_intr_handle { unsigned irq; };
|
||||
typedef struct pci_intr_handle pci_intr_handle_t;
|
||||
|
||||
int pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *);
|
||||
int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
|
||||
const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t);
|
||||
void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
|
||||
int, int (*)(void *), void *, const char *);
|
||||
void pci_intr_disestablish(pci_chipset_tag_t, void *);
|
||||
|
||||
pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
|
||||
void pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
|
||||
|
||||
|
||||
/*******************
|
||||
** sys/timeout.h **
|
||||
*******************/
|
||||
|
||||
struct timeout { };
|
||||
|
||||
void timeout_set(struct timeout *, void (*)(void *), void *);
|
||||
int timeout_add_msec(struct timeout *, int);
|
||||
int timeout_del(struct timeout *);
|
||||
|
||||
|
||||
/******************
|
||||
** sys/endian.h **
|
||||
******************/
|
||||
|
||||
#define htole32(x) ((uint32_t)(x))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _BSD_EMUL_H_ */
|
26
repos/dde_bsd/src/lib/audio/include/extern_c_begin.h
Normal file
26
repos/dde_bsd/src/lib/audio/include/extern_c_begin.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* \brief Include before including Linux headers in C++
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-08-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#define extern_c_begin
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* some warnings should only be switched of for Linux headers */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-arith"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/* deal with C++ keywords used for identifiers etc. */
|
||||
#define private private_
|
||||
#define class class_
|
||||
#define new new_
|
20
repos/dde_bsd/src/lib/audio/include/extern_c_end.h
Normal file
20
repos/dde_bsd/src/lib/audio/include/extern_c_end.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* \brief Include after including Linux headers in C++
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-08-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#undef new
|
||||
#undef class
|
||||
#undef private
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
} /* extern "C" */
|
99
repos/dde_bsd/src/lib/audio/include/list.h
Normal file
99
repos/dde_bsd/src/lib/audio/include/list.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* \brief Slightly improved list
|
||||
* \author Christian Helmuth
|
||||
* \date 2014-09-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
#include <util/list.h>
|
||||
|
||||
|
||||
namespace Bsd {
|
||||
template <typename> class List;
|
||||
template <typename> class List_element;
|
||||
}
|
||||
|
||||
template <typename LT>
|
||||
class Bsd::List : private Genode::List<LT>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::List<LT> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::Element;
|
||||
|
||||
void append(LT const *le)
|
||||
{
|
||||
LT *at = nullptr;
|
||||
|
||||
for (LT *l = first(); l; l = l->next())
|
||||
at = l;
|
||||
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
void prepend(LT const *le)
|
||||
{
|
||||
Base::insert(le);
|
||||
}
|
||||
|
||||
void insert_before(LT const *le, LT const *at)
|
||||
{
|
||||
if (at == first()) {
|
||||
prepend(le);
|
||||
return;
|
||||
}
|
||||
|
||||
for (LT *l = first(); l; l = l->next())
|
||||
if (l->next() == at)
|
||||
at = l;
|
||||
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
** Genode::List interface **
|
||||
****************************/
|
||||
|
||||
LT *first() { return Base::first(); }
|
||||
LT const *first() const { return Base::first(); }
|
||||
|
||||
void insert(LT const *le, LT const *at = 0)
|
||||
{
|
||||
Base::insert(le, at);
|
||||
}
|
||||
|
||||
void remove(LT const *le)
|
||||
{
|
||||
Base::remove(le);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class Bsd::List_element : public Bsd::List<List_element<T> >::Element
|
||||
{
|
||||
private:
|
||||
|
||||
T *_object;
|
||||
|
||||
public:
|
||||
|
||||
List_element(T *object) : _object(object) { }
|
||||
|
||||
T *object() const { return _object; }
|
||||
};
|
||||
|
||||
#endif /* _LIST_H_ */
|
179
repos/dde_bsd/src/lib/audio/include/scheduler.h
Normal file
179
repos/dde_bsd/src/lib/audio/include/scheduler.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* \brief User-level scheduling
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Christian Helmuth
|
||||
* \date 2012-04-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SCHEDULER_H_
|
||||
#define _SCHEDULER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <platform/platform.h>
|
||||
|
||||
|
||||
namespace Bsd {
|
||||
class Scheduler;
|
||||
class Task;
|
||||
|
||||
Scheduler &scheduler();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allows pseudo-parallel execution of functions
|
||||
*/
|
||||
class Bsd::Task : public Bsd::List<Bsd::Task>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
enum Priority { PRIORITY_0, PRIORITY_1, PRIORITY_2, PRIORITY_3 };
|
||||
|
||||
/**
|
||||
* Runtime state
|
||||
*
|
||||
* INIT
|
||||
* |
|
||||
* [run]
|
||||
* v
|
||||
* BLOCKED <--[block/unblock]--> RUNNING
|
||||
*/
|
||||
enum State { STATE_INIT, STATE_RUNNING, STATE_BLOCKED };
|
||||
|
||||
private:
|
||||
|
||||
State _state = STATE_INIT;
|
||||
|
||||
/* sub-classes may overwrite the runnable condition */
|
||||
virtual bool _runnable() const;
|
||||
|
||||
void *_stack = nullptr; /* stack pointer */
|
||||
jmp_buf _env; /* execution state */
|
||||
jmp_buf _saved_env; /* saved state of thread calling run() */
|
||||
|
||||
Priority _priority;
|
||||
Scheduler &_scheduler; /* scheduler this task is attached to */
|
||||
|
||||
void (*_func)(void *); /* function to call*/
|
||||
void *_arg; /* argument for function */
|
||||
char const *_name; /* name of task */
|
||||
int const _stack_size; /* size of the stack of task */
|
||||
|
||||
public:
|
||||
|
||||
Task(void (*func)(void*), void *arg, char const *name,
|
||||
Priority priority, Scheduler &scheduler, int stack_size);
|
||||
virtual ~Task();
|
||||
|
||||
State state() const { return _state; }
|
||||
Priority priority() const { return _priority; }
|
||||
|
||||
|
||||
/*******************************
|
||||
** Runtime state transitions **
|
||||
*******************************/
|
||||
|
||||
void block()
|
||||
{
|
||||
if (_state == STATE_RUNNING) {
|
||||
_state = STATE_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
void unblock()
|
||||
{
|
||||
if (_state == STATE_BLOCKED) {
|
||||
_state = STATE_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run task until next preemption point
|
||||
*
|
||||
* \return true if run, false if not runnable
|
||||
*/
|
||||
bool run();
|
||||
|
||||
/**
|
||||
* Request scheduling (of other tasks)
|
||||
*
|
||||
* Note, this task may not be blocked when calling schedule() depending
|
||||
* on the use case.
|
||||
*/
|
||||
void schedule();
|
||||
|
||||
/**
|
||||
* Shortcut to enter blocking state and request scheduling
|
||||
*/
|
||||
void block_and_schedule()
|
||||
{
|
||||
block();
|
||||
schedule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the task (mainly for debugging purposes)
|
||||
*/
|
||||
char const *name() { return _name; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scheduler
|
||||
*/
|
||||
class Bsd::Scheduler
|
||||
{
|
||||
private:
|
||||
|
||||
Bsd::List<Bsd::Task> _present_list;
|
||||
Genode::Lock _present_list_mutex;
|
||||
|
||||
Task *_current = nullptr; /* currently scheduled task */
|
||||
|
||||
bool _run_task(Task *);
|
||||
|
||||
public:
|
||||
|
||||
Scheduler();
|
||||
~Scheduler();
|
||||
|
||||
/**
|
||||
* Return currently scheduled task
|
||||
*/
|
||||
Task *current();
|
||||
|
||||
/**
|
||||
* Add new task to the present list
|
||||
*/
|
||||
void add(Task *);
|
||||
|
||||
/**
|
||||
* Schedule all present tasks
|
||||
*
|
||||
* Returns if no task is runnable.
|
||||
*/
|
||||
void schedule();
|
||||
|
||||
/**
|
||||
* Log current state of tasks in present list (debug)
|
||||
*
|
||||
* Log lines are prefixed with 'prefix'
|
||||
*/
|
||||
void log_state(char const *prefix);
|
||||
};
|
||||
|
||||
#endif /* _SCHEDULER_H_ */
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* \brief Platform specific code
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-06-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _X86_32__PLATFORM_H_
|
||||
#define _X86_32__PLATFORM_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _JBLEN 11
|
||||
typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1];
|
||||
|
||||
void _longjmp(jmp_buf, int);
|
||||
int _setjmp(jmp_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
void platform_execute(void *sp, void *func, void *arg)
|
||||
{
|
||||
asm volatile ("movl %2, 0(%0);"
|
||||
"movl %1, -0x4(%0);"
|
||||
"movl %0, %%esp;"
|
||||
"call *-4(%%esp);"
|
||||
: : "r" (sp), "r" (func), "r" (arg));
|
||||
}
|
||||
|
||||
#endif /* _X86_32__PLATFORM_H_ */
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* \brief Platform specific code
|
||||
* \author Sebastian Sumpf
|
||||
* \author Alexander Boettcher
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-06-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _X86_64__PLATFORM_H_
|
||||
#define _X86_64__PLATFORM_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _JBLEN 12
|
||||
typedef struct _jmp_buf { long _jb[_JBLEN]; } jmp_buf[1];
|
||||
|
||||
void _longjmp(jmp_buf, int);
|
||||
int _setjmp(jmp_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline
|
||||
void platform_execute(void *sp, void *func, void *arg)
|
||||
{
|
||||
asm volatile ("movq %2, %%rdi;"
|
||||
"movq %1, 0(%0);"
|
||||
"movq %0, %%rsp;"
|
||||
"call *0(%%rsp);"
|
||||
: "+r" (sp), "+r" (func), "+r" (arg) : : "memory");
|
||||
}
|
||||
|
||||
#endif /* _X86_64__PLATFORM_H_ */
|
172
repos/dde_bsd/src/lib/audio/irq.cc
Normal file
172
repos/dde_bsd/src/lib/audio/irq.cc
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* \brief Signal context for IRQ's
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/tslab.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <audio/audio.h>
|
||||
#include <bsd.h>
|
||||
#include <extern_c_begin.h>
|
||||
# include <bsd_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
namespace Bsd {
|
||||
class Irq;
|
||||
}
|
||||
|
||||
static void run_irq(void *args);
|
||||
|
||||
static Genode::Signal_context_capability _dma_notifier_cap;
|
||||
|
||||
void Audio::dma_notifier(Genode::Signal_context_capability cap) {
|
||||
_dma_notifier_cap = cap; }
|
||||
|
||||
class Bsd::Irq
|
||||
{
|
||||
public:
|
||||
|
||||
typedef int (*intrh_t)(void*);
|
||||
|
||||
/**
|
||||
* Context encapsulates the handling of an IRQ
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
private:
|
||||
|
||||
enum { STACK_SIZE = 1024 * sizeof(long) };
|
||||
|
||||
Bsd::Task _task;
|
||||
Genode::Irq_session_client _irq;
|
||||
Genode::Signal_rpc_member<Context> _dispatcher;
|
||||
|
||||
intrh_t _intrh;
|
||||
void *_intarg;
|
||||
|
||||
/**
|
||||
* Signal handler
|
||||
*/
|
||||
void _handle(unsigned)
|
||||
{
|
||||
_task.unblock();
|
||||
Bsd::scheduler().schedule();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Context(Server::Entrypoint &ep,
|
||||
Genode::Irq_session_capability cap,
|
||||
intrh_t intrh, void *intarg)
|
||||
:
|
||||
_task(run_irq, this, "irq", Bsd::Task::PRIORITY_3,
|
||||
Bsd::scheduler(), STACK_SIZE),
|
||||
_irq(cap),
|
||||
_dispatcher(ep, *this, &Context::_handle),
|
||||
_intrh(intrh), _intarg(intarg)
|
||||
{
|
||||
_irq.sigh(_dispatcher);
|
||||
_irq.ack_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle IRQ
|
||||
*/
|
||||
void handle_irq()
|
||||
{
|
||||
_intrh(_intarg);
|
||||
_irq.ack_irq();
|
||||
|
||||
/*
|
||||
* Notify the frontend when a block from the DMA
|
||||
* was played.
|
||||
*/
|
||||
if (_dma_notifier_cap.valid())
|
||||
Genode::Signal_transmitter(_dma_notifier_cap).submit();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
Server::Entrypoint &_ep;
|
||||
Context *_ctx;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Irq(Genode::Allocator &alloc, Server::Entrypoint &ep)
|
||||
: _alloc(alloc), _ep(ep), _ctx(nullptr) { }
|
||||
|
||||
/**
|
||||
* Request an IRQ
|
||||
*/
|
||||
void establish_intr(Genode::Irq_session_capability cap, intrh_t intrh, void *intarg)
|
||||
{
|
||||
if (_ctx) {
|
||||
PERR("interrupt already established");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
_ctx = new (&_alloc) Context(_ep, cap, intrh, intarg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Bsd::Irq *_bsd_irq;
|
||||
|
||||
|
||||
void Bsd::irq_init(Server::Entrypoint &ep)
|
||||
{
|
||||
static Bsd::Irq irq_context(*Genode::env()->heap(), ep);
|
||||
_bsd_irq = &irq_context;
|
||||
}
|
||||
|
||||
|
||||
static void run_irq(void *args)
|
||||
{
|
||||
Bsd::Irq::Context *ctx = static_cast<Bsd::Irq::Context*>(args);
|
||||
|
||||
while (true) {
|
||||
Bsd::scheduler().current()->block_and_schedule();
|
||||
ctx->handle_irq();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** dev/pci/pcivar.h **
|
||||
**********************/
|
||||
|
||||
extern "C" int pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ih) {
|
||||
return 0; }
|
||||
|
||||
|
||||
extern "C" void *pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
|
||||
int ipl, int (*intrh)(void *), void *intarg,
|
||||
const char *intrstr)
|
||||
{
|
||||
Bsd::Bus_driver *drv = (Bsd::Bus_driver*)pc;
|
||||
|
||||
_bsd_irq->establish_intr(drv->irq_session(), intrh, intarg);
|
||||
return _bsd_irq;
|
||||
}
|
386
repos/dde_bsd/src/lib/audio/mem.cc
Normal file
386
repos/dde_bsd/src/lib/audio/mem.cc
Normal file
@ -0,0 +1,386 @@
|
||||
/**
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/printf.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* local includes */
|
||||
#include "bsd.h"
|
||||
#include <extern_c_begin.h>
|
||||
# include <bsd_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
static bool const verbose = false;
|
||||
|
||||
|
||||
namespace Bsd {
|
||||
typedef Genode::addr_t addr_t;
|
||||
|
||||
class Slab_backend_alloc;
|
||||
class Slab_alloc;
|
||||
class Malloc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Back-end allocator for Genode's slab allocator
|
||||
*/
|
||||
class Bsd::Slab_backend_alloc : public Genode::Allocator,
|
||||
public Genode::Rm_connection
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
VM_SIZE = 8 * 1024 * 1024, /* size of VM region to reserve */
|
||||
BLOCK_SIZE = 1024 * 1024, /* 1 MiB */
|
||||
ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */
|
||||
};
|
||||
|
||||
addr_t _base; /* virt. base address */
|
||||
Genode::Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
|
||||
addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
|
||||
int _index; /* current index in ds_cap */
|
||||
Genode::Allocator_avl _range; /* manage allocations */
|
||||
Genode::Ram_session &_ram; /* ram session to allocate ds from */
|
||||
|
||||
bool _alloc_block()
|
||||
{
|
||||
if (_index == ELEMENTS) {
|
||||
PERR("Slab-backend exhausted!");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
_ds_cap[_index] = _ram.alloc(BLOCK_SIZE);
|
||||
Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
|
||||
} catch (...) { return false; }
|
||||
|
||||
/* return base + offset in VM area */
|
||||
addr_t block_base = _base + (_index * BLOCK_SIZE);
|
||||
++_index;
|
||||
|
||||
_range.add_range(block_base, BLOCK_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Slab_backend_alloc(Genode::Ram_session &ram)
|
||||
:
|
||||
Rm_connection(0, VM_SIZE),
|
||||
_index(0), _range(Genode::env()->heap()), _ram(ram)
|
||||
{
|
||||
/* reserver attach us, anywere */
|
||||
_base = Genode::env()->rm_session()->attach(dataspace());
|
||||
}
|
||||
|
||||
addr_t start() const { return _base; }
|
||||
addr_t end() const { return _base + VM_SIZE - 1; }
|
||||
|
||||
|
||||
/*************************
|
||||
** Allocator interface **
|
||||
*************************/
|
||||
|
||||
bool alloc(Genode::size_t size, void **out_addr)
|
||||
{
|
||||
bool done = _range.alloc(size, out_addr);
|
||||
|
||||
if (done)
|
||||
return done;
|
||||
|
||||
done = _alloc_block();
|
||||
if (!done) {
|
||||
PERR("Backend allocator exhausted\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return _range.alloc(size, out_addr);
|
||||
}
|
||||
|
||||
void free(void *addr, Genode::size_t size) { }
|
||||
Genode::size_t overhead(Genode::size_t size) const { return 0; }
|
||||
bool need_size_for_free() const override { return false; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Slab allocator using our back-end allocator
|
||||
*/
|
||||
class Bsd::Slab_alloc : public Genode::Slab
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Each slab block in the slab contains about 8 objects (slab entries)
|
||||
* as proposed in the paper by Bonwick and block sizes are multiples of
|
||||
* page size.
|
||||
*/
|
||||
static size_t _calculate_block_size(size_t object_size)
|
||||
{
|
||||
size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
|
||||
+ sizeof(Genode::Slab_block);
|
||||
return Genode::align_addr(block_size, 12);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Slab_alloc(size_t object_size, Slab_backend_alloc &allocator)
|
||||
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
|
||||
|
||||
/**
|
||||
* Convenience slabe-entry allocation
|
||||
*/
|
||||
addr_t alloc()
|
||||
{
|
||||
addr_t result;
|
||||
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Memory interface
|
||||
*/
|
||||
class Bsd::Malloc
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
SLAB_START_LOG2 = 5, /* 32 B */
|
||||
SLAB_STOP_LOG2 = 17, /* 64 KiB */
|
||||
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
|
||||
};
|
||||
|
||||
typedef Genode::addr_t addr_t;
|
||||
typedef Bsd::Slab_alloc Slab_alloc;
|
||||
typedef Bsd::Slab_backend_alloc Slab_backend_alloc;
|
||||
|
||||
Slab_backend_alloc &_back_allocator;
|
||||
Slab_alloc *_allocator[NUM_SLABS];
|
||||
addr_t _start;
|
||||
addr_t _end;
|
||||
|
||||
/**
|
||||
* Set 'value' at 'addr'
|
||||
*/
|
||||
void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; }
|
||||
|
||||
/**
|
||||
* Retrieve slab index belonging to given address
|
||||
*/
|
||||
unsigned _slab_index(Genode::addr_t **addr)
|
||||
{
|
||||
using namespace Genode;
|
||||
/* get index */
|
||||
addr_t index = *(*addr - 1);
|
||||
|
||||
/*
|
||||
* If index large, we use aligned memory, retrieve beginning of slab entry
|
||||
* and read index from there
|
||||
*/
|
||||
if (index > 32) {
|
||||
*addr = (addr_t *)*(*addr - 1);
|
||||
index = *(*addr - 1);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the originally requested size of the allocation
|
||||
*/
|
||||
Genode::size_t _get_orig_size(Genode::addr_t **addr)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
addr_t index = *(*addr - 1);
|
||||
if (index > 32) {
|
||||
*addr = (addr_t *) * (*addr - 1);
|
||||
}
|
||||
|
||||
return *(*addr - 2);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Malloc(Slab_backend_alloc &alloc)
|
||||
:
|
||||
_back_allocator(alloc), _start(alloc.start()),
|
||||
_end(alloc.end())
|
||||
{
|
||||
/* init slab allocators */
|
||||
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
|
||||
_allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap())
|
||||
Slab_alloc(1U << i, _back_allocator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alloc in slabs
|
||||
*/
|
||||
void *alloc(Genode::size_t size, int align = 0)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* save requested size */
|
||||
Genode::size_t orig_size = size;
|
||||
size += sizeof(addr_t);
|
||||
|
||||
/* += slab index + aligment size */
|
||||
size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0);
|
||||
|
||||
int msb = Genode::log2(size);
|
||||
|
||||
if (size > (1U << msb))
|
||||
msb++;
|
||||
|
||||
if (size < (1U << SLAB_START_LOG2))
|
||||
msb = SLAB_STOP_LOG2;
|
||||
|
||||
if (msb > SLAB_STOP_LOG2) {
|
||||
PERR("Slab too large %u reqested %zu", 1U << msb, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc();
|
||||
if (!addr) {
|
||||
PERR("Failed to get slab for %u", 1U << msb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_set_at(addr, orig_size);
|
||||
addr += sizeof(addr_t);
|
||||
|
||||
_set_at(addr, msb - SLAB_START_LOG2);
|
||||
addr += sizeof(addr_t);
|
||||
|
||||
if (align > 2) {
|
||||
/* save */
|
||||
addr_t ptr = addr;
|
||||
addr_t align_val = (1U << align);
|
||||
addr_t align_mask = align_val - 1;
|
||||
/* align */
|
||||
addr = (addr + align_val) & ~align_mask;
|
||||
/* write start address before aligned address */
|
||||
_set_at(addr - sizeof(addr_t), ptr);
|
||||
}
|
||||
|
||||
return (addr_t *)addr;
|
||||
}
|
||||
|
||||
void free(void const *a)
|
||||
{
|
||||
using namespace Genode;
|
||||
addr_t *addr = (addr_t *)a;
|
||||
|
||||
unsigned nr = _slab_index(&addr);
|
||||
/* we need to decrease addr by 2, orig_size and index come first */
|
||||
_allocator[nr]->free((void *)(addr - 2));
|
||||
}
|
||||
|
||||
Genode::size_t size(void const *a)
|
||||
{
|
||||
using namespace Genode;
|
||||
addr_t *addr = (addr_t *)a;
|
||||
|
||||
return _get_orig_size(&addr);
|
||||
}
|
||||
|
||||
bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); }
|
||||
};
|
||||
|
||||
|
||||
static Bsd::Malloc& malloc_backend()
|
||||
{
|
||||
static Bsd::Slab_backend_alloc sb(*Genode::env()->ram_session());
|
||||
static Bsd::Malloc m(sb);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** Memory allocation *
|
||||
**********************/
|
||||
|
||||
extern "C" void *malloc(size_t size, int type, int flags)
|
||||
{
|
||||
void *addr = malloc_backend().alloc(size);
|
||||
|
||||
if (flags & M_ZERO)
|
||||
Genode::memset(addr, 0, size);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void *mallocarray(size_t nmemb, size_t size, int type, int flags)
|
||||
{
|
||||
if (size != 0 && nmemb > (~0UL / size))
|
||||
return 0;
|
||||
|
||||
return malloc(nmemb * size, type, flags);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void free(void *addr, int type, size_t size)
|
||||
{
|
||||
if (!addr) return;
|
||||
|
||||
if (!malloc_backend().inside((Genode::addr_t)addr)) {
|
||||
PERR("cannot free unknown memory at %p, called from %p",
|
||||
addr, __builtin_return_address(0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
size_t ssize = malloc_backend().size(addr);
|
||||
|
||||
if (ssize != size)
|
||||
PWRN("size: %zu for %p does not match stored size: %zu",
|
||||
size, addr, ssize);
|
||||
}
|
||||
|
||||
malloc_backend().free(addr);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/systm.h **
|
||||
*****************/
|
||||
|
||||
extern "C" void bcopy(const void *src, void *dst, size_t len)
|
||||
{
|
||||
/* XXX may overlap */
|
||||
Genode::memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
|
||||
extern "C" int uiomovei(void *buf, int n, struct uio *uio)
|
||||
{
|
||||
void *dst = buf;
|
||||
void *src = ((char*)uio->buf) + uio->uio_offset;
|
||||
size_t len = uio->uio_resid < (size_t)n ? uio->uio_resid : (size_t)n;
|
||||
|
||||
Genode::memcpy(dst, src, len);
|
||||
|
||||
uio->uio_resid -= len;
|
||||
uio->uio_offset += len;
|
||||
|
||||
return 0;
|
||||
}
|
127
repos/dde_bsd/src/lib/audio/misc.cc
Normal file
127
repos/dde_bsd/src/lib/audio/misc.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* \brief Audio driver BSD API emulation
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-11-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-15 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* local includes */
|
||||
#include <extern_c_begin.h>
|
||||
#include <bsd_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
/* compiler includes */
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/*******************
|
||||
** machine/mutex **
|
||||
*******************/
|
||||
|
||||
void mtx_enter(struct mutex *mtx) {
|
||||
mtx->mtx_owner = curcpu(); }
|
||||
|
||||
|
||||
void mtx_leave(struct mutex *mtx) {
|
||||
mtx->mtx_owner = nullptr; }
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/systm.h **
|
||||
*****************/
|
||||
|
||||
extern "C" void panic(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
Genode::vprintf(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
extern "C" int printf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
Genode::vprintf(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return 0; /* XXX proper return value */
|
||||
}
|
||||
|
||||
|
||||
extern "C" int snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
||||
va_start(list, format);
|
||||
Genode::String_console sc(str, size);
|
||||
sc.vprintf(format, list);
|
||||
va_end(list);
|
||||
|
||||
return sc.len();
|
||||
}
|
||||
|
||||
|
||||
extern "C" int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
return Genode::strcmp(s1, s2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
extern "C" size_t strlcpy(char *dst, const char *src, size_t siz)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0) {
|
||||
do {
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return(s - src - 1); /* count does not include NUL */
|
||||
}
|
256
repos/dde_bsd/src/lib/audio/scheduler.cc
Normal file
256
repos/dde_bsd/src/lib/audio/scheduler.cc
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* \brief User-level scheduling
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \author Christian Helmuth
|
||||
* \date 2012-04-25
|
||||
*
|
||||
* We use a pseudo-thread implementation based on setjmp/longjmp.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* local includes */
|
||||
#include <bsd.h>
|
||||
#include <scheduler.h>
|
||||
|
||||
|
||||
static bool const debugging = false;
|
||||
static bool const verbose = false;
|
||||
#define PDBGV(...) do { if (verbose) PDBG(__VA_ARGS__); } while (0)
|
||||
|
||||
|
||||
/**********
|
||||
** Task **
|
||||
**********/
|
||||
|
||||
bool Bsd::Task::_runnable() const
|
||||
{
|
||||
switch (_state) {
|
||||
case STATE_INIT: return true;
|
||||
case STATE_RUNNING: return true;
|
||||
case STATE_BLOCKED: return false;
|
||||
}
|
||||
|
||||
PERR("state %d not handled by switch", _state);
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
bool Bsd::Task::run()
|
||||
{
|
||||
if (!_runnable())
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Save the execution environment. The scheduled task returns to this point
|
||||
* after execution, i.e., at the next preemption point.
|
||||
*/
|
||||
if (_setjmp(_saved_env))
|
||||
return true;
|
||||
|
||||
if (_state == STATE_INIT) {
|
||||
/* setup execution environment and call task's function */
|
||||
_state = STATE_RUNNING;
|
||||
Genode::Thread_base *th = Genode::Thread_base::myself();
|
||||
|
||||
_stack = th->alloc_secondary_stack(_name, _stack_size);
|
||||
|
||||
/* switch stack and call '_func(_arg)' */
|
||||
platform_execute(_stack, (void *)_func, _arg);
|
||||
} else {
|
||||
/* restore execution environment */
|
||||
_longjmp(_env, 1);
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
PERR("Unexpected return of Task");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
|
||||
void Bsd::Task::schedule()
|
||||
{
|
||||
/*
|
||||
* Save the execution environment. The task will resume from here on next
|
||||
* schedule.
|
||||
*/
|
||||
if (_setjmp(_env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* return to thread calling run() */
|
||||
_longjmp(_saved_env, 1);
|
||||
}
|
||||
|
||||
|
||||
Bsd::Task::Task(void (*func)(void*), void *arg, char const *name,
|
||||
Priority priority, Scheduler &scheduler, int stack_size)
|
||||
:
|
||||
_priority(priority), _scheduler(scheduler),
|
||||
_func(func), _arg(arg), _name(name), _stack_size(stack_size)
|
||||
{
|
||||
scheduler.add(this);
|
||||
|
||||
PDBGV("name: '%s' func: %p arg: %p prio: %u t: %p", name, func, arg, priority, this);
|
||||
}
|
||||
|
||||
|
||||
Bsd::Task::~Task()
|
||||
{
|
||||
if (_stack)
|
||||
Genode::Thread_base::myself()->free_secondary_stack(_stack);
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Scheduler **
|
||||
***************/
|
||||
|
||||
Bsd::Scheduler & Bsd::scheduler()
|
||||
{
|
||||
static Bsd::Scheduler inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
Bsd::Task *Bsd::Scheduler::current()
|
||||
{
|
||||
if (!_current) {
|
||||
PERR("BUG: _current is zero!");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
return _current;
|
||||
}
|
||||
|
||||
|
||||
void Bsd::Scheduler::add(Task *task)
|
||||
{
|
||||
Bsd::Task *p = _present_list.first();
|
||||
for ( ; p; p = p->next()) {
|
||||
if (p->priority() <= task->priority()) {
|
||||
_present_list.insert_before(task, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p)
|
||||
_present_list.append(task);
|
||||
}
|
||||
|
||||
|
||||
void Bsd::Scheduler::schedule()
|
||||
{
|
||||
bool at_least_one = false;
|
||||
|
||||
/*
|
||||
* Iterate over all tasks and run first runnable.
|
||||
*
|
||||
* (1) If one runnable tasks was run start over from beginning of
|
||||
* list.
|
||||
*
|
||||
* (2) If no task is runnable quit scheduling (break endless
|
||||
* loop).
|
||||
*/
|
||||
while (true) {
|
||||
/* update current time before running task */
|
||||
Bsd::update_time();
|
||||
|
||||
bool was_run = false;
|
||||
for (Task *t = _present_list.first(); t; t = t->next()) {
|
||||
/* update current before running task */
|
||||
_current = t;
|
||||
|
||||
if ((was_run = t->run())) {
|
||||
at_least_one = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!was_run)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!at_least_one) {
|
||||
PWRN("schedule() called without runnable tasks");
|
||||
log_state("SCHEDULE");
|
||||
}
|
||||
|
||||
/* clear current as no task is running */
|
||||
_current = nullptr;
|
||||
}
|
||||
|
||||
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
namespace {
|
||||
struct Logger : Genode::Thread<0x4000>
|
||||
{
|
||||
Timer::Connection _timer;
|
||||
Bsd::Scheduler &_scheduler;
|
||||
unsigned const _interval;
|
||||
|
||||
Logger(Bsd::Scheduler &scheduler, unsigned interval_seconds)
|
||||
:
|
||||
Genode::Thread<0x4000>("logger"),
|
||||
_scheduler(scheduler), _interval(interval_seconds)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
PWRN("Scheduler::Logger is up");
|
||||
_timer.msleep(1000 * _interval);
|
||||
while (true) {
|
||||
_scheduler.log_state("LOGGER");
|
||||
_timer.msleep(2000);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define ANSI_ESC_RESET "\033[00m"
|
||||
#define ANSI_ESC_BLACK "\033[30m"
|
||||
#define ANSI_ESC_RED "\033[31m"
|
||||
#define ANSI_ESC_YELLOW "\033[33m"
|
||||
|
||||
static char const *state_color(Bsd::Task::State state)
|
||||
{
|
||||
switch (state) {
|
||||
case Bsd::Task::STATE_INIT: return ANSI_ESC_RESET;
|
||||
case Bsd::Task::STATE_RUNNING: return ANSI_ESC_RED;
|
||||
case Bsd::Task::STATE_BLOCKED: return ANSI_ESC_YELLOW;
|
||||
}
|
||||
|
||||
return ANSI_ESC_BLACK;
|
||||
}
|
||||
|
||||
|
||||
void Bsd::Scheduler::log_state(char const *prefix)
|
||||
{
|
||||
unsigned i;
|
||||
Bsd::Task *t;
|
||||
for (i = 0, t = _present_list.first(); t; t = t->next(), ++i) {
|
||||
Genode::printf("%s [%u] prio: %u state: %s%u" ANSI_ESC_RESET " %s\n",
|
||||
prefix, i, t->priority(), state_color(t->state()),
|
||||
t->state(), t->name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Bsd::Scheduler::Scheduler()
|
||||
{
|
||||
if (debugging)
|
||||
new (Genode::env()->heap()) Logger(*this, 10);
|
||||
}
|
||||
|
||||
|
||||
Bsd::Scheduler::~Scheduler() { }
|
139
repos/dde_bsd/src/lib/audio/timer.cc
Normal file
139
repos/dde_bsd/src/lib/audio/timer.cc
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* \brief Signal context for timer events
|
||||
* \author Josef Soentgen
|
||||
* \date 2014-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/tslab.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <list.h>
|
||||
#include <bsd.h>
|
||||
|
||||
#include <extern_c_begin.h>
|
||||
# include <bsd_emul.h>
|
||||
#include <extern_c_end.h>
|
||||
|
||||
|
||||
static unsigned long millisecs;
|
||||
|
||||
|
||||
namespace Bsd {
|
||||
class Timer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bsd::Timer
|
||||
*/
|
||||
class Bsd::Timer
|
||||
{
|
||||
private:
|
||||
|
||||
::Timer::Connection _timer_conn;
|
||||
Genode::Signal_rpc_member<Bsd::Timer> _dispatcher;
|
||||
|
||||
/**
|
||||
* Handle trigger_once signal
|
||||
*/
|
||||
void _handle(unsigned)
|
||||
{
|
||||
Bsd::scheduler().schedule();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timer(Server::Entrypoint &ep)
|
||||
:
|
||||
_dispatcher(ep, *this, &Bsd::Timer::_handle)
|
||||
{
|
||||
_timer_conn.sigh(_dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update time counter
|
||||
*/
|
||||
void update_millisecs()
|
||||
{
|
||||
millisecs = _timer_conn.elapsed_ms();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static Bsd::Timer *_bsd_timer;
|
||||
|
||||
|
||||
void Bsd::timer_init(Server::Entrypoint &ep)
|
||||
{
|
||||
/* XXX safer way preventing possible nullptr access? */
|
||||
static Bsd::Timer bsd_timer(ep);
|
||||
_bsd_timer = &bsd_timer;
|
||||
|
||||
/* initialize value explicitly */
|
||||
millisecs = 0UL;
|
||||
}
|
||||
|
||||
|
||||
void Bsd::update_time() {
|
||||
_bsd_timer->update_millisecs(); }
|
||||
|
||||
|
||||
static Timer::Connection _timer;
|
||||
|
||||
|
||||
static Bsd::Task *_sleep_task;
|
||||
|
||||
|
||||
/*****************
|
||||
** sys/systm.h **
|
||||
*****************/
|
||||
|
||||
extern "C" int msleep(const volatile void *ident, struct mutex *mtx,
|
||||
int priority, const char *wmesg, int timo)
|
||||
{
|
||||
// PDBG("ident: %p mtx: %p priority: %d wmesg: '%s' timo: %d",
|
||||
// ident, mtx, priority, wmesg, timo);
|
||||
|
||||
if (_sleep_task) {
|
||||
PERR("_sleep_task is not null, current task: '%s'", Bsd::scheduler().current()->name());
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
_sleep_task = Bsd::scheduler().current();
|
||||
// PERR("msleep: '%s' %p", _sleep_task->name(), ident);
|
||||
_sleep_task->block_and_schedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void wakeup(const volatile void *ident)
|
||||
{
|
||||
// PERR("wakeup: '%s' %p", _sleep_task->name(), ident);
|
||||
_sleep_task->unblock();
|
||||
_sleep_task = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
** machine/param.h **
|
||||
*********************/
|
||||
|
||||
extern "C" void delay(int delay)
|
||||
{
|
||||
_timer.msleep(delay);
|
||||
}
|
79
repos/dde_bsd/src/lib/audio/x86_32/setjmp.S
Normal file
79
repos/dde_bsd/src/lib/audio/x86_32/setjmp.S
Normal file
@ -0,0 +1,79 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
.asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90"
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
//#include <machine/asm.h>
|
||||
|
||||
/*
|
||||
* C library -- _setjmp, _longjmp
|
||||
*
|
||||
* _longjmp(a,v)
|
||||
* will generate a "return(v)" from the last call to
|
||||
* _setjmp(a)
|
||||
* by restoring registers from the environment 'a'.
|
||||
* The previous signal state is NOT restored.
|
||||
*/
|
||||
|
||||
.text; .p2align 2,0x90
|
||||
.globl _setjmp; .type _setjmp,@function; _setjmp:
|
||||
movl 4(%esp),%eax
|
||||
movl 0(%esp),%edx
|
||||
movl %edx, 0(%eax) /* rta */
|
||||
movl %ebx, 4(%eax)
|
||||
movl %esp, 8(%eax)
|
||||
movl %ebp,12(%eax)
|
||||
movl %esi,16(%eax)
|
||||
movl %edi,20(%eax)
|
||||
fnstcw 24(%eax)
|
||||
xorl %eax,%eax
|
||||
ret
|
||||
.size _setjmp, . - _setjmp
|
||||
|
||||
.text; .p2align 2,0x90
|
||||
.globl _longjmp; .type _longjmp,@function; _longjmp:
|
||||
movl 4(%esp),%edx
|
||||
movl 8(%esp),%eax
|
||||
movl 0(%edx),%ecx
|
||||
movl 4(%edx),%ebx
|
||||
movl 8(%edx),%esp
|
||||
movl 12(%edx),%ebp
|
||||
movl 16(%edx),%esi
|
||||
movl 20(%edx),%edi
|
||||
fldcw 24(%edx)
|
||||
testl %eax,%eax
|
||||
jnz 1f
|
||||
incl %eax
|
||||
1: movl %ecx,0(%esp)
|
||||
ret
|
||||
.size _longjmp, . - _longjmp
|
93
repos/dde_bsd/src/lib/audio/x86_64/setjmp.S
Normal file
93
repos/dde_bsd/src/lib/audio/x86_64/setjmp.S
Normal file
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
.asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90"
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
//#include <machine/asm.h>
|
||||
|
||||
/*
|
||||
* C library -- _setjmp, _longjmp
|
||||
*
|
||||
* _longjmp(a,v)
|
||||
* will generate a "return(v)" from the last call to
|
||||
* _setjmp(a)
|
||||
* by restoring registers from the environment 'a'.
|
||||
* The previous signal state is NOT restored.
|
||||
*/
|
||||
|
||||
.text; .p2align 4,0x90
|
||||
.globl _setjmp; .type _setjmp,@function; _setjmp:
|
||||
movq %rdi,%rax
|
||||
movq 0(%rsp),%rdx /* retval */
|
||||
movq %rdx, 0(%rax) /* 0; retval */
|
||||
movq %rbx, 8(%rax) /* 1; rbx */
|
||||
movq %rsp,16(%rax) /* 2; rsp */
|
||||
movq %rbp,24(%rax) /* 3; rbp */
|
||||
movq %r12,32(%rax) /* 4; r12 */
|
||||
movq %r13,40(%rax) /* 5; r13 */
|
||||
movq %r14,48(%rax) /* 6; r14 */
|
||||
movq %r15,56(%rax) /* 7; r15 */
|
||||
fnstcw 64(%rax) /* 8; fpu cw */
|
||||
stmxcsr 68(%rax) /* and mxcsr */
|
||||
xorq %rax,%rax
|
||||
ret
|
||||
.size _setjmp, . - _setjmp
|
||||
|
||||
.text; .p2align 4,0x90
|
||||
.globl _longjmp; .type _longjmp,@function; _longjmp:
|
||||
movq %rdi,%rdx
|
||||
/* Restore the mxcsr, but leave exception flags intact. */
|
||||
stmxcsr -4(%rsp)
|
||||
movl 68(%rdx),%eax
|
||||
andl $0xffffffc0,%eax
|
||||
movl -4(%rsp),%edi
|
||||
andl $0x3f,%edi
|
||||
xorl %eax,%edi
|
||||
movl %edi,-4(%rsp)
|
||||
ldmxcsr -4(%rsp)
|
||||
movq %rsi,%rax /* retval */
|
||||
movq 0(%rdx),%rcx
|
||||
movq 8(%rdx),%rbx
|
||||
movq 16(%rdx),%rsp
|
||||
movq 24(%rdx),%rbp
|
||||
movq 32(%rdx),%r12
|
||||
movq 40(%rdx),%r13
|
||||
movq 48(%rdx),%r14
|
||||
movq 56(%rdx),%r15
|
||||
fldcw 64(%rdx)
|
||||
testq %rax,%rax
|
||||
jnz 1f
|
||||
incq %rax
|
||||
1: movq %rcx,0(%rsp)
|
||||
ret
|
||||
.size _longjmp, . - _longjmp
|
@ -4,6 +4,11 @@
|
||||
#
|
||||
#REPOSITORIES += $(GENODE_DIR)/repos/dde_oss
|
||||
|
||||
#
|
||||
# Drivers ported from the OpenBSD
|
||||
#
|
||||
#REPOSITORIES += $(GENODE_DIR)/repos/dde_bsd
|
||||
|
||||
#
|
||||
# Drivers ported from iPXE
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user