socsvn commit: r303606 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sun May 22 19:37:59 UTC 2016
Author: iateaca
Date: Sun May 22 19:37:57 2016
New Revision: 303606
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=303606
Log:
add hda_codec module
design the interface of communication between the hda controller and codec using data set
design the concept of hda_codec_class and hda_codec_inst
when CORBWP is set load from the system memory the VERB command using DMA
M bhyve/Makefile
A bhyve/hda_codec.c
M bhyve/pci_hda.c
A bhyve/pci_hda.h
Added:
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h
Modified:
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile
soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile Sun May 22 18:20:45 2016 (r303605)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/Makefile Sun May 22 19:37:57 2016 (r303606)
@@ -20,6 +20,7 @@
consport.c \
dbgport.c \
fwctl.c \
+ hda_codec.c \
inout.c \
ioapic.c \
mem.c \
Added: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/hda_codec.c Sun May 22 19:37:57 2016 (r303606)
@@ -0,0 +1,18 @@
+
+#include "pci_hda.h"
+
+static int
+hda_codec_init(struct hda_codec_inst *hci, const char *opts)
+{
+ DPRINTF("cad: 0x%x opts: %s\n", hci->cad, opts);
+
+ return 0;
+}
+
+struct hda_codec_class hda_codec = {
+ .name = "hda_codec",
+ .init = hda_codec_init,
+};
+
+HDA_EMUL_SET(hda_codec);
+
Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sun May 22 18:20:45 2016 (r303605)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sun May 22 19:37:57 2016 (r303606)
@@ -1,28 +1,10 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <assert.h>
-
+#include "pci_hda.h"
#include "bhyverun.h"
#include "pci_emul.h"
#include "hdac_reg.h"
/*
- * HDA Debug Log
- */
-#define DEBUG_HDA 1
-#if DEBUG_HDA == 1
-static FILE *dbg;
-#define DPRINTF(fmt, arg...) \
-do {fprintf(dbg, "%s-%d: " fmt, __func__, __LINE__, ##arg); \
-fflush(dbg); } while (0)
-#else
-#define DPRINTF(fmt, arg...)
-#endif
-
-/*
* HDA defines
*/
#define INTEL_VENDORID 0x8086
@@ -30,6 +12,7 @@
#define HDA_OSS_NO 0x04
#define HDA_ISS_NO 0x04
+#define HDA_CODEC_MAX 0x10
#define HDA_LAST_OFFSET (0x80 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
#define HDA_CORB_ENTRY_LEN 0x04
#define HDA_RIRB_ENTRY_LEN 0x08
@@ -57,6 +40,9 @@
struct hda_codec_cmd_ctl corb;
struct hda_codec_cmd_ctl rirb;
+
+ struct hda_codec_inst *codecs[HDA_CODEC_MAX];
+ uint8_t codecs_no;
};
/*
@@ -70,6 +56,11 @@
hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t mask, uint32_t value);
static struct hda_softc *hda_init(const char *opts);
+static int
+hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec);
+static struct hda_codec_class *
+hda_find_codec_class(const char *name);
+
static void hda_reset_regs(struct hda_softc *sc);
static uint32_t
hda_read(struct hda_softc *sc, uint32_t offset);
@@ -98,6 +89,8 @@
static void
hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
static void
+hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void
hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
static void
hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
@@ -121,6 +114,7 @@
static const hda_set_reg_handler hda_set_reg_table[] = {
[HDAC_GCTL] = hda_set_gctl,
+ [HDAC_CORBWP] = hda_set_corbwp,
[HDAC_CORBCTL] = hda_set_corbctl,
[HDAC_RIRBCTL] = hda_set_rirbctl,
@@ -166,6 +160,12 @@
PCI_EMUL_SET(pci_de_hda);
+SET_DECLARE(hda_codec_class_set, struct hda_codec_class);
+
+#if DEBUG_HDA == 1
+FILE *dbg;
+#endif
+
/*
* HDA module function definitions
*/
@@ -204,6 +204,8 @@
static struct hda_softc *hda_init(const char *opts)
{
struct hda_softc *sc = NULL;
+ struct hda_codec_class *codec = NULL;
+ int err;
#if DEBUG_HDA == 1
dbg = fopen("/tmp/bhyve_hda.log", "w+");
@@ -217,9 +219,58 @@
hda_reset_regs(sc);
+ /*
+ * TODO search all the codecs declared in opts
+ * For now we play with one single codec
+ */
+ codec = hda_find_codec_class("hda_codec");
+ if (codec) {
+ err = hda_codec_constructor(sc, codec);
+ assert(!err);
+ }
+
return sc;
}
+static int
+hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec)
+{
+ struct hda_codec_inst *hci = NULL;
+ int err;
+
+ if (sc->codecs_no >= HDA_CODEC_MAX)
+ return -1;
+
+ hci = calloc(1, sizeof(struct hda_codec_inst));
+ if (!hci)
+ return -1;
+
+ hci->hda = sc;
+ hci->cad = sc->codecs_no;
+
+ sc->codecs[sc->codecs_no++] = hci;
+
+ err = codec->init(hci, NULL);
+ assert(!err);
+
+ return 0;
+}
+
+static struct hda_codec_class *
+hda_find_codec_class(const char *name)
+{
+ struct hda_codec_class **pdpp = NULL, *pdp = NULL;
+
+ SET_FOREACH(pdpp, hda_codec_class_set) {
+ pdp = *pdpp;
+ if (!strcmp(pdp->name, name)) {
+ return (pdp);
+ }
+ }
+
+ return NULL;
+}
+
static void hda_reset_regs(struct hda_softc *sc)
{
DPRINTF("Reset the HDA controller registers ...\n");
@@ -395,12 +446,40 @@
if (!(value & HDAC_GCTL_CRST)) {
hda_reset_regs(sc);
+ hda_set_reg_by_offset(sc, HDAC_STATESTS, 0x0001);
}
return;
}
static void
+hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ struct hda_codec_cmd_ctl *corb = &sc->corb;
+ uint32_t value = sc->regs[offset];
+ uint32_t verb = 0;
+
+ corb->wp = value;
+
+ /*
+ * TODO do it in loop
+ */
+ if (corb->wp != corb->rp && corb->run) {
+ corb->rp++;
+ verb = hda_dma_ld_dword(corb->dma_vaddr + HDA_CORB_ENTRY_LEN * corb->rp);
+
+ /*
+ * TODO get cad from verb and send command to codec[cad]
+ */
+ DPRINTF("VERB: 0x%x\n", verb);
+ }
+
+ hda_set_reg_by_offset(sc, HDAC_CORBRP, corb->rp);
+
+ return;
+}
+
+static void
hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
{
uint32_t value = sc->regs[offset];
Added: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.h Sun May 22 19:37:57 2016 (r303606)
@@ -0,0 +1,43 @@
+
+#ifndef _HDA_EMUL_H_
+#define _HDA_EMUL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+
+/*
+ * HDA Debug Log
+ */
+#define DEBUG_HDA 1
+#if DEBUG_HDA == 1
+extern FILE *dbg;
+#define DPRINTF(fmt, arg...) \
+do {fprintf(dbg, "%s-%d: " fmt, __func__, __LINE__, ##arg); \
+fflush(dbg); } while (0)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+struct hda_softc;
+
+struct hda_codec_inst {
+ struct hda_softc *hda;
+ uint8_t cad;
+ void *priv;
+};
+
+struct hda_codec_class {
+ char *name;
+ int (*init)(struct hda_codec_inst *hci, const char *opts);
+};
+
+#define HDA_EMUL_SET(x) DATA_SET(hda_codec_class_set, x);
+
+#endif /* _HDA_EMUL_H_ */
More information about the svn-soc-all
mailing list