socsvn commit: r303547 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sat May 21 14:38:09 UTC 2016
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;
More information about the svn-soc-all
mailing list