socsvn commit: r305909 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sat Jul 9 18:46:32 UTC 2016
Author: iateaca
Date: Sat Jul 9 18:46:31 2016
New Revision: 305909
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305909
Log:
implement the DMA Position in Buffer mechanism in order to allow the guest to read the position in buffer of each stream
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 Jul 9 17:48:45 2016 (r305908)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sat Jul 9 18:46:31 2016 (r305909)
@@ -20,6 +20,7 @@
#define HDA_CORB_ENTRY_LEN 0x04
#define HDA_RIRB_ENTRY_LEN 0x08
#define HDA_BDL_ENTRY_LEN 0x10
+#define HDA_DMA_PIB_ENTRY_LEN 0x08
#define HDA_STREAM_TAGS_CNT 0x10
#define HDA_STREAM_REGS_BASE 0x80
#define HDA_STREAM_REGS_LEN 0x20
@@ -91,6 +92,9 @@
struct hda_codec_inst *codecs[HDA_CODEC_MAX];
uint8_t codecs_no;
+ /* Base Address of the DMA Position Buffer */
+ void *dma_pib_vaddr;
+
struct hda_stream_desc streams[HDA_IOSS_NO];
uint8_t stream_map[HDA_STREAM_TAGS_CNT];
};
@@ -168,6 +172,8 @@
static void
hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old);
static void
+hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void
hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
static void
hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old);
@@ -205,6 +211,7 @@
[HDAC_CORBCTL] = hda_set_corbctl,
[HDAC_RIRBCTL] = hda_set_rirbctl,
[HDAC_RIRBSTS] = hda_set_rirbsts,
+ [HDAC_DPIBLBASE] = hda_set_dpiblbase,
#define HDAC_ISTREAM(n, iss, oss) \
[_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl, \
@@ -631,6 +638,8 @@
st->bp = 0;
st->be = 0;
hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, 0);
+ if (sc->dma_pib_vaddr)
+ *(uint32_t *)(sc->dma_pib_vaddr + stream_ind * HDA_DMA_PIB_ENTRY_LEN) = 0;
st->run = 1;
@@ -931,6 +940,36 @@
}
static void
+hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+ uint64_t dpiblbase = 0;
+ uint64_t dpibubase = 0;
+ uint64_t dpibpaddr = 0;
+
+ if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old & HDAC_DPLBASE_DPLBASE_DMAPBE)) {
+ if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) {
+ dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK;
+ dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE);
+
+ dpibpaddr = dpiblbase | (dpibubase << 32);
+ DPRINTF("DMA Position In Buffer dma_paddr: %p\n", (void *)dpibpaddr);
+
+ sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr, HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO);
+ if (!sc->dma_pib_vaddr) {
+ DPRINTF("Fail to get the guest virtual address\n");
+ assert(0);
+ }
+ } else {
+ DPRINTF("DMA Position In Buffer Reset\n");
+ sc->dma_pib_vaddr = NULL;
+ }
+ }
+
+ return;
+}
+
+static void
hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
{
uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
@@ -1111,6 +1150,8 @@
}
hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, lpib);
+ if (sc->dma_pib_vaddr)
+ *(uint32_t *)(sc->dma_pib_vaddr + stream_ind * HDA_DMA_PIB_ENTRY_LEN) = lpib;
if (irq) {
hda_set_field_by_offset(sc, off + HDAC_SDSTS, HDAC_SDSTS_BCIS, HDAC_SDSTS_BCIS);
More information about the svn-soc-all
mailing list