[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH] Meiner erste Commit ins Git Repo von tyndur. Und ahm nunja. AC97 Treiber unvollständig hinzugefügt. Wichtig sind mir die Kommentare zu der CDI/Sound definition



From: deathly-sequences@xxxxxx <snake707@Cazad-Dum.(none)>

---
 src/modules/cdi/ac97/Makefile.all    |    6 +
 src/modules/cdi/ac97/ac97.c          |  189 ++++++++++++++++++++++++++++++++++
 src/modules/cdi/ac97/includes/ac97.h |   80 ++++++++++++++
 src/modules/cdi/ac97/main.c          |  123 ++++++++++++++++++++++
 src/modules/cdi/include/cdi.h        |    1 +
 src/modules/cdi/include/cdi/sound.h  |  151 +++++++++++++++++++++++++++
 6 files changed, 550 insertions(+), 0 deletions(-)
 create mode 100644 src/modules/cdi/ac97/Makefile.all
 create mode 100644 src/modules/cdi/ac97/ac97.c
 create mode 100644 src/modules/cdi/ac97/includes/ac97.h
 create mode 100644 src/modules/cdi/ac97/main.c
 create mode 100644 src/modules/cdi/include/cdi/sound.h

diff --git a/src/modules/cdi/ac97/Makefile.all b/src/modules/cdi/ac97/Makefile.all
new file mode 100644
index 0000000..d231938
--- /dev/null
+++ b/src/modules/cdi/ac97/Makefile.all
@@ -0,0 +1,6 @@
+shopt -s extglob
+source $LOST_BUILDMK_ROOT/config.sh
+
+echo "LD   $1/modules/ac97"
+$LOST_TOOLS_LD -Ttext=0x40000000 -oac97.mod  *.o --start-group $2 --end-group
+$LOST_TOOLS_STRIP -s ac97.mod -o $1/modules/ac97
diff --git a/src/modules/cdi/ac97/ac97.c b/src/modules/cdi/ac97/ac97.c
new file mode 100644
index 0000000..25ec1cd
--- /dev/null
+++ b/src/modules/cdi/ac97/ac97.c
@@ -0,0 +1,189 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+
+#include "cdi/pci.h"
+#include "cdi/io.h"
+#include "cdi/misc.h"
+
+#include "includes/ac97.h"
+
+/*NOTE: Code kommt zum Teil aus lowlevel.brainsware.org/wiki/AC97 Stand: 
+                                                                    3.8.2009*/
+
+/*FIXME: This Code sucks ass!*/
+
+static void ac97_handle_interrupt(struct cdi_device* device);
+static void play_smpl(struct cdi_device* dev);
+
+/*FIXME: Code Struktur verbessern*/
+
+void ac97_init_device(struct cdi_device* device){
+    struct ac97_device *codec;
+    int i,j;
+    j=0;
+    codec=(struct ac97_device*)device;
+    /*PCI Strukturen initialisieren*/
+    DEBUG_MSG("AC97:- Interrupthandler und Ports initialisieren");
+    cdi_register_irq(codec->pci->irq,ac97_handle_interrupt,device);
+    cdi_pci_alloc_ioports(codec->pci);
+    /*IO-Räume finden: nambar und nabmbar, diese Stehen in der reslist*/
+    cdi_list_t reslist=codec->pci->resources;
+    struct cdi_pci_resource* res;/*zum Reslist traversieren*/
+    codec->nambar=0;
+    codec->nabmbar=0;
+    /*Reslist wird traversiert*/
+    for(i=0; (res=cdi_list_get(reslist,i));i++){
+        if((res->type==CDI_PCI_IOPORTS)&&(codec->nabmbar==0)){
+            /*Nabmbar steht vor Nambar in der Liste!*/
+            codec->nabmbar=res->start;
+            DEBUG_MSG("verm. Nabmbar");
+        }
+        else if((res->type==CDI_PCI_IOPORTS)&&(codec->nambar==0)){
+            /*Nambar eintragen*/
+            DEBUG_MSG("verm. Nambar");
+            codec->nambar=res->start;
+        }
+        else if(res->type==CDI_PCI_IOPORTS){
+            DEBUG_MSG("IOPORT unbekannt");
+        }
+        else{
+            DEBUG_MSG("res->type unbekannt");
+        }
+    }
+    cdi_sleep_ms(1000);
+    /* Karte Resetten */
+    DEBUG_MSG("Karte resetten");
+    cdi_outw(codec->nambar+NAM_RESET,42);/*Reset der Karte durchführen*/
+    cdi_outb(codec->nabmbar+NABM_GLB_CTRL_STAT,0x02);/*wird auch zum Resetten
+benötigt*/
+    cdi_sleep_ms(1000); /*1sec warten*/
+    
+    /* Lautstärke einstellen */
+    DEBUG_MSG("Lautstärke einstellen");
+    /*Lautstärke geht von 0x00 bis 0x1f, wobei 0x00 laut und 0x1f leise ist*/
+    /*Funktioniert anscheinend nicht unter qemu*/
+    uint16_t volume=0x1f;
+    /*Allgemeine Laustärke für Links und Rechts*/
+    cdi_outw(codec->nambar+NAM_MASTER_VOLUME,(volume<<8)|volume);
+    cdi_outw(codec->nambar+NAM_MONO_VOLUME,volume);/*Mono Lautstärke*/
+    cdi_outw(codec->nambar+NAM_PC_BEEP,volume);/*PC BEEP Lautstärke*/
+    /*PCM Lautstärke für links und rechts*/
+    cdi_outw(codec->nambar+NAM_PCM_VOLUME,(volume<<8)|volume);
+    cdi_sleep_ms(1000); /*1sec warten*/
+    
+    /*Sample rate einstellen*/
+    DEBUG_MSG("Sample Rates Einstellen");
+    if(!((cdi_inw(codec->nambar+NAM_EXT_AUDIO_ID)&0x01))){
+        /* Hier liegt die Spl Rate auf fix bei 48kHz*/}
+    else
+    {
+        DEBUG_MSG("Sample Rates Konfigurieren");
+        cdi_outw(codec->nambar+NAM_EXT_AUDIO_STC,cdi_inw(codec->nambar+
+NAM_EXT_AUDIO_ID)|1); /*Variable Sample Rate einstellen*/
+        cdi_sleep_ms(1000);/*Warten!*/
+        /*FIXME: Aus Parametern auslesen!*/
+        /*Front Sample Rate*/
+        cdi_outw(codec->nambar+NAM_FRONT_SPLRATE,44100);
+        /*Links Rechts Sample Rate*/
+        cdi_outw(codec->nambar+NAM_LR_SPLRATE,44100);
+        cdi_sleep_ms(1000);/*Warten!*/
+    }
+    /*Buffer initialisieren.*/
+    DEBUG_MSG("Bufferlist initialisieren - Nur zum Test,\
+gehört hier nicht hin!");
+    /*FIXME: Bitmap bringt glaub ich nichts.*/
+    codec->valid_buffs=0x00;/*Bisher ist keiner der Buffer gültig*/
+    /* Buffer list anlegen*/
+    if(cdi_alloc_phys_mem(32*sizeof(buf),(void **)&codec->buffer_list,
+        &codec->paddr_buf_list)==-1){
+        DEBUG_MSG("MEMALLOC FEHLGESCHLAGEN!");
+        return;
+    }
+    /* Buffer anlegen, eintragen und mit Werten füllen*/
+    /*Letzteres nur zum Test*/
+    DEBUG_MSG("Buffer anlegen und eintragen");
+    for(i=0;i<32;i++)
+    {
+        void* vbuf=0;/*virtuelle Adresse des Buffers*/
+        void* pbuf=0;/*physische Adresse*/
+        if(cdi_alloc_phys_mem(0x10000,&vbuf,&pbuf)==-1){
+            /*0x20000 funzt hier offensichtlich nich*/
+            DEBUG_MSG("MEMALLOC FEHLGESCHLAGEN -- BUFFER INITIALISIEREN");
+            return;
+        }
+        /*Buffer füllen -- Nur zu Testzwecken*/
+        else{
+            codec->buffer_list[i].buffer=pbuf;/*Physikalische Adresse*/
+            /*Maximale Sample Länge.*/
+            codec->buffer_list[i].sample_length=0x7ffe;
+            if(i==31){
+                codec->buffer_list[i].bup=1; /*Buffer underrun Policy setzen.*/
+            }
+            else{
+                codec->buffer_list[i].bup=0; /*Buffer underrun Policy setzen.*/
+            }
+            codec->buffer_list[i].ioc=1; /*Interrupt on completion bit setzen.*/
+            codec->buf_virt[i]=(uint16_t*)vbuf;
+            codec->buf_phys[i]=(uint16_t*)pbuf;
+             uint16_t* xbuf=(uint16_t*)vbuf;
+             for(j=0;j<0x8000;j+=2)
+             {
+                 xbuf[j]=0;
+                 xbuf[j+1]=0;
+             }
+        }
+    }
+    play_smpl((struct cdi_device*) codec);
+    DEBUG_MSG("Abspielen!");
+    cdi_sleep_ms(1000);/*Warten! Dieses hat aber keinen besonderen Grund*/
+    /*Lister der Buffer Deskriptoren an das Gerät übergeben*/
+    cdi_outl(codec->nabmbar+NABM_POBDBAR,(uint32_t)codec->paddr_buf_list);
+    /*Letzten gültigen Buffer eintragen.*/
+    cdi_outb(codec->nabmbar+NABM_POLVI,31);
+    /*Das Gerät die Buffer abspielen lassen.*/
+    /*Hierzu wird das letzte Bit in nabmbar+NABM_POCONTROL gesetzt.*/
+    cdi_outb(codec->nabmbar+NABM_POCONTROL,0x01);
+}
+
+static void play_smpl(struct cdi_device* dev){
+    struct ac97_device *codec;
+    codec=(struct ac97_device*)dev;
+    FILE *pf;
+    pf=fopen("startup.wav","br");
+    char c,d;
+    int i;
+    if(!pf){
+        DEBUG_MSG("Fehler beim öffnen!");
+        return;
+    }
+    /*Header überspringen. Nervt grad nur.*/
+    for(i=0;i<52;i++){
+        c=fgetc(pf);
+    }
+    DEBUG_MSG("Header uebersprungen");
+    /*sooo :) dinge auslesen*/
+    i=0;
+    uint16_t *xbuf=(uint16_t *)codec->buf_virt[0];
+    while((!feof(pf))&&(i<0x10000)){
+        d=c;
+        c=fgetc(pf);
+        i++;
+        if(i%2==0){xbuf[(i-i%2)/2]=(c<<8)+d;};
+        if(c==d){printf("\r FUCK IT!%d %x %x",i,c,d);}
+    }
+    DEBUG_MSG("SOO LONG!");
+    fclose(pf);
+}
+
+void ac97_remove_device(struct cdi_device* device){
+    ;
+}
+
+static void ac97_handle_interrupt(struct cdi_device* device){
+    DEBUG_MSG("Interrupts");
+}
+
+/* EOF */
diff --git a/src/modules/cdi/ac97/includes/ac97.h b/src/modules/cdi/ac97/includes/ac97.h
new file mode 100644
index 0000000..5cd0a43
--- /dev/null
+++ b/src/modules/cdi/ac97/includes/ac97.h
@@ -0,0 +1,80 @@
+
+#ifndef __ac97_h__
+#define __ac97_h__
+
+#include <stdint.h>
+
+#include "cdi.h"
+#include "cdi/net.h"
+#include "cdi/pci.h"
+
+/* Benötigte Konstanten */
+/* Quelle: lowlevel.brainsware.org/wiki/AC97: Stand: 3.8.2009  */
+
+#define NAM_RESET          0x0000
+#define NAM_MASTER_VOLUME  0x0002
+#define NAM_MONO_VOLUME    0x0006
+#define NAM_PC_BEEP        0x000A
+#define NAM_PCM_VOLUME     0x0018
+#define NAM_EXT_AUDIO_ID   0x0028
+#define NAM_EXT_AUDIO_STC  0x002A
+#define NAM_FRONT_SPLRATE  0x002C
+#define NAM_LR_SPLRATE     0x0032
+#define NABM_POBDBAR       0x0010
+#define NABM_POLVI         0x0015
+#define NABM_POCONTROL     0x001B
+#define NABM_GLB_CTRL_STAT 0x0060
+
+/* Makros */
+
+#define DEBUG_MSG(s) printf("[AC97] debug: %s() '%s'\n", __FUNCTION__, s)
+
+struct ac97_buffer_desc_t{
+    void*                   buffer;
+    uint16_t                sample_length;
+    uint16_t                reserved:14;
+    uint16_t                bup:1;
+    uint16_t                ioc:1;
+    
+}__attribute__((packed));
+
+typedef struct ac97_buffer_desc_t buf;
+
+struct ac97_device{
+    struct cdi_device cdi;
+    struct cdi_pci_device* pci;
+    void* phys;
+    buf* buffer_list; /*Liste der Buffer*/
+    void* paddr_buf_list;/*phyisische Adresse der Buffer Descriptor list*/
+    uint32_t valid_buffs; /*mini bitmap welche buffer gerade gültig sind :)*/
+    uint16_t* buf_virt[32];/*Virtuelle Adressen der einzelnen buffer*/
+    uint16_t* buf_phys[32];/*Physische Adressen der einzelnen buffer*/
+    
+    uint32_t nambar; /*Native Audio Mixer Base Address Register*/
+    uint32_t nabmbar; /*Native Audio Bus Master Base Address Register*/
+    
+    uint16_t vol;/*Lautstärke*/
+    uint16_t splrate;/*Samplerate*/
+    
+    //TODO: Volume, Sample Rates etc.
+};
+
+/**
+ * Initialisiert das AC97 Gerät.
+ *
+ * @param device Struktur zur Verwaltung des Gerätes. Elterklasse von ac97_device
+ **/
+
+void ac97_init_device(struct cdi_device* device);
+
+/**
+ * Führt die Aufraumaurbeiten durch. Wie zum Beispiel: Speicherfreigabe.
+ *
+ * @param device Struktur zur Verwaltung des Gerätes. Elterklasse von ac97_device
+ **/
+void ac97_remove_device(struct cdi_device* device);
+
+#endif
+
+/* EOF */
+
diff --git a/src/modules/cdi/ac97/main.c b/src/modules/cdi/ac97/main.c
new file mode 100644
index 0000000..f8aa1b2
--- /dev/null
+++ b/src/modules/cdi/ac97/main.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "cdi/pci.h"
+#include "cdi/io.h"
+#include "cdi/misc.h"
+
+#include "includes/ac97.h"
+
+struct ac97_options{
+    uint32_t mode;
+    uint16_t vol;/*Lautstärke*/
+    uint16_t splr;/*Sample Rate*/
+};
+
+typedef struct ac97_options dro;
+
+struct ac97_driver {
+    struct cdi_driver drv;
+};
+
+static struct ac97_driver ac97;
+
+static const char* driver_name="ac97";
+
+static void ac97_parameters(dro* modi, int argc, char *argv[]);
+static void ac97driver_init(int argc, char *argv[]);
+static void ac97driver_destroy(struct cdi_driver* driver);
+
+#ifdef CDI_STANDALONE
+int main(int argc, char* argv[])
+#else
+int init_ac97(int argc, char* argv[])
+#endif
+{
+    cdi_init();
+    ac97driver_init(argc,argv);
+    cdi_driver_register((struct cdi_driver*) &ac97);
+#ifdef CDI_STANDALONE
+    cdi_run_drivers();
+#endif
+    return 0;
+}
+
+static void ac97driver_init(int argc, char *argv[]){
+    dro options={
+        /*Standardwerte setzen*/
+        .mode=0x00,
+        .vol=0x0f,
+        .splr=44100
+    };
+    
+    ac97_parameters(&options, argc,argv);
+    ac97.drv.name=driver_name;
+    ac97.drv.type=CDI_SOUND;
+    ac97.drv.init_device=ac97_init_device;
+    ac97.drv.remove_device=ac97_remove_device;
+    ac97.drv.destroy=ac97driver_destroy;
+    
+    cdi_list_t pci_devices=cdi_list_create();
+    cdi_pci_get_all_devices(pci_devices);
+    struct cdi_pci_device* get=0;
+    int i;
+    for(i=0;(get=cdi_list_get(pci_devices,i));i++){
+        printf("PCI_DEVICE: %x\n",get->device_id);
+        if((get->vendor_id==0x8086)&&(get->device_id==0x2415)){
+            void* p_phys_device;
+            struct ac97_device* ac97_d;
+            if((cdi_alloc_phys_mem(sizeof(*ac97_d),(void**) &ac97_d,
+&p_phys_device))==-1){
+                DEBUG_MSG("Memalloc fehlgeschlagen!");
+            }
+            memset(ac97_d,0,sizeof(struct ac97_device));
+            ac97_d->phys=p_phys_device;
+            ac97_d->pci=get;
+            ac97_d->vol=options.vol;
+            ac97_d->splrate=options.splr;
+            ac97_init_device((struct cdi_device*)ac97_d);
+        }
+        else{
+            cdi_pci_device_destroy(get);
+        }
+    }
+    cdi_list_destroy(pci_devices);
+}
+
+
+/*TODO: Debugging, einfach überprüfen ob alles funzt*/
+static void ac97_parameters(dro* options, int argc, char *argv[]){
+    int i,j;
+    uint32_t flags=0;
+    for( i=1;i<argc;i++){
+        if(!(strcmp("--volume",argv[i])&&strcmp("-v",argv[i])&&
+            (flags&0x00000001))){
+            options->vol=(uint16_t)strtoul(argv[i+1],NULL,0);
+            flags|=0x00000001;
+            i++; /*Index muss sich noch um eins erhöhen.*/
+            continue;
+        }
+        else if(!(strcmp("--sample-rate",argv[i])&&strcmp("-s",argv[i])&&
+            (flags&0x00000010))){
+            options->splr=(uint16_t)strtoul(argv[i+1],NULL,0);
+            flags|=0x00000010;
+            i++;
+            continue;
+        }
+        else{
+            DEBUG_MSG("Unbekannte oder Wiederhohlte Argumente!");
+            printf("Argumentenliste:\n");
+            for(j=0;j<argc;j++){
+                printf("\t %s", argv[j]);
+            }
+        }
+    }
+}
+
+static void ac97driver_destroy(struct cdi_driver* driver){
+}
+
+/* EOF */
diff --git a/src/modules/cdi/include/cdi.h b/src/modules/cdi/include/cdi.h
index c6215a6..c3a48ee 100644
--- a/src/modules/cdi/include/cdi.h
+++ b/src/modules/cdi/include/cdi.h
@@ -25,6 +25,7 @@ typedef enum {
     CDI_NETWORK         = 1,
     CDI_STORAGE         = 2,
     CDI_SCSI            = 3,
+    CDI_SOUND           = 4,
 } cdi_device_type_t;
 
 struct cdi_driver;
diff --git a/src/modules/cdi/include/cdi/sound.h b/src/modules/cdi/include/cdi/sound.h
new file mode 100644
index 0000000..680553a
--- /dev/null
+++ b/src/modules/cdi/include/cdi/sound.h
@@ -0,0 +1,151 @@
+
+/** @file sound.h 
+ *
+ * Diese Datei enthält die Datenstrukturen, von denen die Datenstrukturen der
+ * Treiber abgeleitet werden. Außerdem werden hier die Funktionsprototypen für
+ * die Schnittstelle Soundtreiber, CDI definiert.
+ **/
+
+/**
+ * Treiber für die Soundkarten.
+ *
+ * @defgroup sound
+ **/
+
+#ifndef __sound_h__
+#define __sound_h__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "cdi.h"
+
+/* Angelehnt an net.h */
+
+struct cdi_sound_device{
+    struct cdi_device dev;
+    /* Im folgenden bezeichnet driver immer das Gerät. */
+    /* Ausführlichere Kommentare/Dokumentation findet man in den jeweiligen
+       Implementationen der Treiber. Hier werden nur Funktionszeiger
+       definiert. */
+    
+    /** @brief Damit das Gerät auch beginnt Daten abzuspielen. 
+     *  
+     *  Weißt den Treiber an, Daten abzuspielen, wenn neue vorhanden sind.
+     *
+     * @param driver Treiber, der die Daten abspielen soll.
+     *
+     */
+    void (*cdi_sound_play)(struct cdi_sound_driver *driver);
+    
+    /** @brief Hält die Audioausgabe des Treibers an.
+     *
+     * Wenn der Treiber nicht gerade von einer anderen Anwendung blockiert wird,
+     * wird die Audioausgabe angehalten. Wird ignoriert, wenn der Treiber
+     * 'in use' ist.
+     *
+     * @param driver Treiber, der die Audioausgabe anhalten soll.
+     */
+    void (*cdi_sound_stop)(struct cdi_sound_driver *driver);
+    
+    /** @brief Ein Prozess darf die in_use Option betätigen.
+     *
+     * Die in use Option ist mir eingefallen, als ich mir das Zusammenspiel
+     * Amarok, Firefox mit flashplayer plugin und der rest des Systems angesehen
+     * habe. Die schließen sich gegenseitig aus. Sobald Amarok an ist, kann
+     * der Rest nichts mehr abspielen. Hat auch gute Seiten. Funktionszeiger ...
+     *
+     * @param driver Treiber der in use gestellt werden soll.
+     * @param pid Prozess ID des Prozesses. Dient später nur zur Überprüfung.
+     *
+     * @return 0 bei Erfolg. 1 bei Misserfolg.
+     *
+     */
+    uint32_t (*cdi_sound_in_use_enable)(struct cdi_sound_driver *driver,
+                                    uint32_t pid);
+    
+    /** @brief Der gleiche Prozess darf das in_use Privileg abgeben.
+     *
+     * Anhand von pid wird nur überprüft ob der richtige Prozess die in use
+     * Option abstellt. Funktionszeiger ...
+     * 
+     * @param driver Treiber der die in use Option abschalten soll.
+     * @param pid Prozessnummer.
+     *
+     * @return 0 bei Erfolg. 1 bei Misserfolg.
+     */
+    uint32_t (*cdi_sound_in_use_disable)(struct cdi_sound_driver *driver,
+                                     uint32_t pid);
+    
+    /** @brief Funktionszeiger für eine Schnittstelle, in der man den aktuellen
+     *          Status des Treibers/Gerätes abrufen kann.
+     *
+     * Diese Funktion ist dafür gedacht um herauszufinden ob der Treiber gerade
+     * Daten abspielt oder nicht. Hier ist die Schnittstelle Treiber/CDI
+     * 
+     * @param driver Soundtreiber, dessen Zustand ermittelt werden soll.
+     *
+     * @return Die Returncodes können von Treiber zu Treiber variieren. Hier
+     *         ist eine Liste, von Codes, die auf jeden Fall genauso
+     *         implementiert werden sollen (Zusätzliche können angehangen
+     *         werden): 0 - Treiber/Gerät nicht arbeitsbereit/initialisiert.
+     *         1 - Gerät arbeitsbereit. Spielt keine Daten ab. 2 - Treiber
+     *         erhält Daten. 4 - Gerät spielt Daten ab. Datenempfang möglich.
+     *         8 - Gerät ist gestoppt, aber es sind noch Daten zum spielen
+     *         übrig. Neue Daten können jederzeit hinzugefügt werden.
+     *         16 - Bit ist gesetzt, wenn Qucik Mixing (lineare Superposition
+     *         mit Clippingunterdrückung) erlaubt ist. 32 - Dieses Bit zeigt an
+     *         ob der Treiber gerade von einem Prozess "blockiert" wird.
+     *       
+     */
+    uint32_t (*cdi_sound_driver_state)(struct cdi_sound_driver *driver);
+    
+    /** @brief Funktionszeiger für eine Schnittstelle, die dem Treiber die
+     *          als nächstes abzuspielenden Daten übergibt.
+     *
+     * Dies ist ein Funktionszeiger und für die Schnittstelle Treiber CDI
+     * gedacht.
+     *
+     * @param driver Soundtreiber an den die Daten geschickt werden sollen.
+     * @param data_start Zeiger auf den Beginn der Daten. Es wird angenommen,
+     *                   dass alle Daten hintereinander liegen.
+     * @param data_length Länge des Datenblockes.
+     * @param pid Datenbereiche werden Treiberintern mit einer PID versehen, um
+     *            diese z.B. noch zurückziehen zu können. Prozess beendet.
+     *            Datenbereiche wurden deallokiert.
+     *
+     * @return 0 - bei Erfolg, 1 - bei Fehler, wiederhohlung kann ihn beheben
+     *         2 - Fehler nicht durch wiederhohlte Ausführung behebbar
+     *         kann. Wenn Gerät z.B. von einem Prozess benutzt wird, der Mixing
+     *         nicht zulassen will. Ansonnsten, werden Daten von verschiednen
+     *         Geräten linear superponiert, oder einfach nacheinander
+     *         abgespielt (Flags beachten).
+     */
+    uint32_t (*cdi_sound_input_data)(struct cdi_sound_driver *driver,
+                                     uint32_t* data_start,
+                                     uint32_t data_length,
+                                     uint32_t pid);
+    
+    /** @brief Funktionszeiger für eine Schnittstelle, damit ein Prozess die an
+     *          den Treiber übergebenen Daten zurückziehen kann.
+     *
+     * Diese Funktion ist dafür Gedacht, damit ein Prozess alle Daten, die in
+     * noch nicht fertiggestellten Buffer vorliegen, löschen kann, falls er z.B.
+     * beendet wird. Funktionszeiger für die Schnittstelle Treiber CDI.
+     * 
+     * @param driver Treiber, der die entsprechenden Daten nicht mehr benutzen
+     *               soll.
+     * @param pid Prozess ID, des entsprechenden Prozesses.
+     */
+    void (*cdi_sound_remove_data)(struct cdi_sound_driver *driver,
+                                      uint32_t pid);
+                            
+}
+
+struct cdi_sound_driver{
+    struct cdi_driver *drv;
+}
+
+#endif
+
+/* EOF */
-- 
1.6.0.4