socsvn commit: r305701 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sun Jul 3 19:00:27 UTC 2016
Author: iateaca
Date: Sun Jul 3 19:00:26 2016
New Revision: 305701
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305701
Log:
implement the hda_set_rirbsts function in order to clear the corresponding bits written by the software
implement the hda_get_clock_ns function in order to get the time in ns using the clock_gettime(CLOCK_MONOTONIC)
update the WALL CLOCK register on read using the hda_get_clock_ns function
set the HDAC_SDSTS_FIFORDY bit in the SDSTS register on stream reset
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 Sun Jul 3 18:27:00 2016 (r305700)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c Sun Jul 3 19:00:26 2016 (r305701)
@@ -1,4 +1,6 @@
+#include <time.h>
+
#include "pci_hda.h"
#include "bhyverun.h"
#include "pci_emul.h"
@@ -25,6 +27,11 @@
#define HDA_DMA_ACCESS_LEN (sizeof(uint32_t))
#define HDA_BDL_MAX_LEN 0x0100
+#define HDAC_SDSTS_FIFORDY (1 << 5)
+
+#define HDA_RIRBSTS_IRQ_MASK (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS)
+#define HDA_SDSTS_IRQ_MASK (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS)
+
/*
* HDA data structures
*/
@@ -74,6 +81,7 @@
uint32_t regs[HDA_LAST_OFFSET];
uint8_t lintr;
+ uint64_t wall_clock_start;
struct hda_codec_cmd_ctl corb;
struct hda_codec_cmd_ctl rirb;
@@ -152,6 +160,8 @@
static void
hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
static void
+hda_set_rirbsts(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);
@@ -165,6 +175,7 @@
static int
hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, void *buf, size_t count);
+static uint64_t hda_get_clock_ns(void);
/*
* PCI HDA function declarations
@@ -186,6 +197,7 @@
[HDAC_CORBWP] = hda_set_corbwp,
[HDAC_CORBCTL] = hda_set_corbctl,
[HDAC_RIRBCTL] = hda_set_rirbctl,
+ [HDAC_RIRBSTS] = hda_set_rirbsts,
#define HDAC_ISTREAM(n, iss, oss) \
[_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl, \
@@ -465,6 +477,8 @@
codec->reset(hci);
}
+ sc->wall_clock_start = hda_get_clock_ns();
+
return;
}
@@ -500,6 +514,7 @@
/* Reset the Stream Descriptor */
memset(st, 0, sizeof(*st));
+ hda_set_field_by_offset(sc, off + HDAC_SDSTS, HDAC_SDSTS_FIFORDY, HDAC_SDSTS_FIFORDY);
hda_set_field_by_offset(sc, off + HDAC_SDCTL0, HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
return;
@@ -568,6 +583,8 @@
bdle_desc->addr = bdle_vaddr;
bdle_desc->len = bdle_sz;
bdle_desc->ioc = bdle->ioc;
+
+ DPRINTF("bdle: 0x%x bdle_sz: 0x%x\n", i, bdle_sz);
}
sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0);
@@ -612,6 +629,9 @@
static uint32_t
hda_read(struct hda_softc *sc, uint32_t offset)
{
+ if (offset == HDAC_WALCLK)
+ return (24 * (hda_get_clock_ns() - sc->wall_clock_start) / 1000);
+
return hda_get_reg_by_offset(sc, offset);
}
@@ -846,6 +866,21 @@
}
static void
+hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ hda_set_reg_by_offset(sc, offset, old);
+
+ /* clear the corresponding bits written by the software (guest) */
+ hda_set_field_by_offset(sc, offset, value & HDA_RIRBSTS_IRQ_MASK, 0);
+
+ hda_update_intr(sc);
+
+ 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);
@@ -886,8 +921,10 @@
{
uint32_t value = hda_get_reg_by_offset(sc, offset);
+ hda_set_reg_by_offset(sc, offset, old);
+
/* clear the corresponding bits written by the software (guest) */
- hda_set_field_by_offset(sc, offset, value, 0);
+ hda_set_field_by_offset(sc, offset, value & HDA_SDSTS_IRQ_MASK, 0);
hda_update_intr(sc);
@@ -966,6 +1003,11 @@
assert(stream < HDA_STREAM_TAGS_CNT);
stream_ind = sc->stream_map[stream];
+ if (!dir)
+ assert(stream_ind < HDA_ISS_NO);
+ else
+ assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO);
+
st = &sc->streams[stream_ind];
if (!st->run) {
DPRINTF("Stream 0x%x stopped\n", stream);
@@ -973,7 +1015,6 @@
}
assert(st->stream == stream);
- assert(st->dir == dir);
off = hda_get_offset_stream(stream_ind);
@@ -1021,6 +1062,17 @@
return 0;
}
+static uint64_t hda_get_clock_ns(void)
+{
+ struct timespec ts;
+ int err;
+
+ err = clock_gettime(CLOCK_MONOTONIC, &ts);
+ assert(!err);
+
+ return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+}
+
/*
* PCI HDA function definitions
*/
More information about the svn-soc-all
mailing list