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