Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 May 2016 14:38:08 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r303547 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
Message-ID:  <201605211438.u4LEc8nv082380@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iateaca
Date: Sat May 21 14:38:08 2016
New Revision: 303547
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=303547

Log:
  design the HDA command and control data structure (CORB or RIBB)
  implement the CORB engine initialization
  implement the DMA store and load functions
  
  M    bhyve/pci_hda.c

Modified:
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sat May 21 11:40:41 2016	(r303546)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sat May 21 14:38:08 2016	(r303547)
@@ -2,9 +2,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <assert.h>
 
-#include "hdac_reg.h"
+#include "bhyverun.h"
 #include "pci_emul.h"
+#include "hdac_reg.h"
 
 /*
  * HDA Debug Log
@@ -28,6 +31,8 @@
 #define HDA_OSS_NO		0x04
 #define HDA_ISS_NO		0x04
 #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
 
 /*
  * HDA data structures
@@ -37,8 +42,21 @@
 
 typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t offset, uint32_t old);
 
+struct hda_codec_cmd_ctl {
+	char *name;
+	void *dma_vaddr;
+	uint16_t size;
+	uint16_t wp;
+	uint16_t rp;
+	uint8_t run;
+};
+
 struct hda_softc {
+	struct pci_devinst *pci_dev;
 	uint32_t regs[HDA_LAST_OFFSET];
+
+	struct hda_codec_cmd_ctl corb;
+	struct hda_codec_cmd_ctl rirb;
 };
 
 /*
@@ -58,6 +76,20 @@
 static int
 hda_write(struct hda_softc *sc, uint32_t offset, uint32_t value);
 
+static void
+hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p);
+static int
+hda_corb_start(struct hda_softc *sc);
+static int
+hda_corb_run(struct hda_softc *sc);
+
+static void *
+hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr, size_t len);
+static void
+hda_dma_st_dword(void *dma_vaddr, uint32_t data);
+static uint32_t
+hda_dma_ld_dword(void *dma_vaddr);
+
 static inline uint8_t
 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset);
 
@@ -109,6 +141,13 @@
 	[HDA_LAST_OFFSET] = NULL,
 };
 
+static const uint16_t hda_corb_sizes[] = {
+	[HDAC_CORBSIZE_CORBSIZE_2]	= 2,
+	[HDAC_CORBSIZE_CORBSIZE_16]	= 16,
+	[HDAC_CORBSIZE_CORBSIZE_256]	= 256,
+	[HDAC_CORBSIZE_CORBSIZE_MASK]	= 0,
+};
+
 struct pci_devemu pci_de_hda = {
 	.pe_emu		= "hda",
 	.pe_init	= pci_hda_init,
@@ -209,6 +248,90 @@
 	return 0;
 }
 
+static void
+hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p)
+{
+	char *name = p->name;
+
+	DPRINTF("%s size: %d\n", name, p->size);
+	DPRINTF("%s dma_vaddr: %p\n", name, p->dma_vaddr);
+	DPRINTF("%s wp: %d\n", name, p->wp);
+	DPRINTF("%s rp: %d\n", name, p->rp);
+
+	return;
+}
+
+static int
+hda_corb_start(struct hda_softc *sc)
+{
+	struct hda_codec_cmd_ctl *corb = &sc->corb;
+	uint8_t corbsize = 0;
+	uint64_t corblbase = 0;
+	uint64_t corbubase = 0;
+	uint64_t corbpaddr;
+
+	corb->name = "CORB";
+
+	corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) & HDAC_CORBSIZE_CORBSIZE_MASK;
+	corb->size = hda_corb_sizes[corbsize];
+
+	if (!corb->size) {
+		DPRINTF("Invalid corb size\n");
+		return -1;
+	}
+
+	corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE);
+	corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE);
+
+	corbpaddr = corblbase | (corbubase << 32);
+	DPRINTF("CORB dma_paddr: %p\n", (void *)corbpaddr);
+
+	corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr, HDA_CORB_ENTRY_LEN * corb->size);
+	if (!corb->dma_vaddr) {
+		DPRINTF("Fail to get the guest virtual address\n");
+		return -1;
+	}
+
+	corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
+	corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP);
+
+	corb->run = 1;
+
+	hda_print_cmd_ctl_data(corb);
+
+	return 0;
+}
+
+static int
+hda_corb_run(struct hda_softc *sc)
+{
+	return 0;
+}
+
+static void *
+hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr, size_t len)
+{
+	struct pci_devinst *pi = sc->pci_dev;
+
+	assert(pi);
+
+	return paddr_guest2host(pi->pi_vmctx, (uintptr_t)dma_paddr, len);
+}
+
+static void
+hda_dma_st_dword(void *dma_vaddr, uint32_t data)
+{
+	*(uint32_t*)dma_vaddr = data;
+
+	return;
+}
+
+static uint32_t
+hda_dma_ld_dword(void *dma_vaddr)
+{
+	return *(uint32_t*)dma_vaddr;
+}
+
 static inline uint8_t
 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset)
 {
@@ -230,6 +353,18 @@
 static void
 hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
 {
+	uint32_t value = sc->regs[offset];
+	int err;
+	struct hda_codec_cmd_ctl *corb = NULL;
+
+	if (value & HDAC_CORBCTL_CORBRUN) {
+		err = hda_corb_start(sc);
+		assert(!err);
+	} else {
+		corb = &sc->corb;
+		memset(corb, 0, sizeof(*corb));
+	}
+
 	return;
 }
 
@@ -277,6 +412,7 @@
 	if (!sc)
 		return -1;
 
+	sc->pci_dev = pi;
 	pi->pi_arg = sc;
 
 	return 0;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605211438.u4LEc8nv082380>